hmrizal commited on
Commit
71a08c8
·
verified ·
1 Parent(s): 57bee5c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +252 -0
app.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import uuid
4
+ import threading
5
+ import pandas as pd
6
+ import torch
7
+ from langchain.document_loaders.csv_loader import CSVLoader
8
+ from langchain.embeddings import HuggingFaceEmbeddings
9
+ from langchain.vectorstores import FAISS
10
+ from langchain.llms import CTransformers
11
+ from langchain.chains import ConversationalRetrievalChain
12
+
13
+ # Global model cache
14
+ MODEL_CACHE = {
15
+ "model": None,
16
+ "init_lock": threading.Lock()
17
+ }
18
+
19
+ # Create directories for user data
20
+ os.makedirs("user_data", exist_ok=True)
21
+
22
+ def initialize_model_once():
23
+ """Initialize the model once and cache it"""
24
+ with MODEL_CACHE["init_lock"]:
25
+ if MODEL_CACHE["model"] is None:
26
+ # Path ke model local dalam repository
27
+ model_path = "llama-2-7b-chat.gguf"
28
+ MODEL_CACHE["model"] = CTransformers(
29
+ model=model_path,
30
+ model_type="llama",
31
+ max_new_tokens=512,
32
+ temperature=0.2,
33
+ top_p=0.9,
34
+ top_k=50,
35
+ repetition_penalty=1.2
36
+ )
37
+
38
+ return MODEL_CACHE["model"]
39
+
40
+ class ChatBot:
41
+ def __init__(self, session_id):
42
+ self.session_id = session_id
43
+ self.chat_history = []
44
+ self.chain = None
45
+ self.user_dir = f"user_data/{session_id}"
46
+ os.makedirs(self.user_dir, exist_ok=True)
47
+
48
+ def process_file(self, file):
49
+ if file is None:
50
+ return "Mohon upload file CSV terlebih dahulu."
51
+
52
+ try:
53
+ # Handle file from Gradio
54
+ file_path = file.name if hasattr(file, 'name') else str(file)
55
+
56
+ # Copy to user directory
57
+ user_file_path = f"{self.user_dir}/uploaded.csv"
58
+
59
+ # For debugging
60
+ print(f"Processing file: {file_path}")
61
+ print(f"Saving to: {user_file_path}")
62
+
63
+ # Verify the CSV can be loaded
64
+ try:
65
+ df = pd.read_csv(file_path)
66
+ print(f"CSV verified: {df.shape[0]} rows, {len(df.columns)} columns")
67
+
68
+ # Save a copy in user directory
69
+ df.to_csv(user_file_path, index=False)
70
+ except Exception as e:
71
+ return f"Error membaca CSV: {str(e)}"
72
+
73
+ # Load document
74
+ try:
75
+ loader = CSVLoader(file_path=file_path, encoding="utf-8", csv_args={
76
+ 'delimiter': ','})
77
+ data = loader.load()
78
+ print(f"Documents loaded: {len(data)}")
79
+ except Exception as e:
80
+ return f"Error loading documents: {str(e)}"
81
+
82
+ # Create vector database
83
+ try:
84
+ db_path = f"{self.user_dir}/db_faiss"
85
+ embeddings = HuggingFaceEmbeddings(
86
+ model_name='sentence-transformers/all-MiniLM-L6-v2',
87
+ model_kwargs={'device': 'cuda' if torch.cuda.is_available() else 'cpu'}
88
+ )
89
+
90
+ db = FAISS.from_documents(data, embeddings)
91
+ db.save_local(db_path)
92
+ print(f"Vector database created at {db_path}")
93
+ except Exception as e:
94
+ return f"Error creating vector database: {str(e)}"
95
+
96
+ # Create LLM and chain
97
+ try:
98
+ llm = initialize_model_once()
99
+ self.chain = ConversationalRetrievalChain.from_llm(
100
+ llm=llm,
101
+ retriever=db.as_retriever(search_kwargs={"k": 4})
102
+ )
103
+ print("Chain created successfully")
104
+ except Exception as e:
105
+ return f"Error creating chain: {str(e)}"
106
+
107
+ # Add basic file info to chat history for context
108
+ file_info = f"CSV berhasil dimuat dengan {df.shape[0]} baris dan {len(df.columns)} kolom. Kolom: {', '.join(df.columns.tolist())}"
109
+ self.chat_history.append(("System", file_info))
110
+
111
+ return "File CSV berhasil diproses! Anda dapat mulai chat dengan model Llama2."
112
+ except Exception as e:
113
+ import traceback
114
+ print(traceback.format_exc())
115
+ return f"Error pemrosesan file: {str(e)}"
116
+
117
+ def chat(self, message, history):
118
+ if self.chain is None:
119
+ return "Mohon upload file CSV terlebih dahulu."
120
+
121
+ try:
122
+ # Process the question with the chain
123
+ result = self.chain({"question": message, "chat_history": self.chat_history})
124
+
125
+ # Update internal chat history
126
+ answer = result["answer"]
127
+ self.chat_history.append((message, answer))
128
+
129
+ # Return just the answer for Gradio
130
+ return answer
131
+ except Exception as e:
132
+ import traceback
133
+ print(traceback.format_exc())
134
+ return f"Error: {str(e)}"
135
+
136
+ def cleanup(self):
137
+ """Release resources when session ends"""
138
+ self.chain = None
139
+
140
+ def create_gradio_interface():
141
+ with gr.Blocks(title="Chat with CSV using Llama2 🦙") as interface:
142
+ # Create unique session ID for each user
143
+ session_id = gr.State(lambda: str(uuid.uuid4()))
144
+ # Create user-specific chatbot instance
145
+ chatbot_state = gr.State(lambda: None)
146
+
147
+ gr.HTML("<h1 style='text-align: center;'>Chat with CSV using Llama2 🦙</h1>")
148
+ gr.HTML("<h3 style='text-align: center;'>Asisten analisis CSV yang powerfull</h3>")
149
+
150
+ with gr.Row():
151
+ with gr.Column(scale=1):
152
+ file_input = gr.File(
153
+ label="Upload CSV Anda",
154
+ file_types=[".csv"]
155
+ )
156
+ process_button = gr.Button("Proses CSV")
157
+
158
+ with gr.Accordion("Informasi Model", open=False):
159
+ gr.Markdown("""
160
+ **Model**: Llama-2-7b-chat
161
+
162
+ **Fitur**:
163
+ - Dioptimalkan untuk analisis data dan percakapan
164
+ - Efisien dengan kuantisasi GGUF
165
+ - Manajemen sesi per pengguna
166
+ """)
167
+
168
+ with gr.Column(scale=2):
169
+ chatbot_interface = gr.Chatbot(
170
+ label="Riwayat Chat",
171
+ height=400
172
+ )
173
+ message_input = gr.Textbox(
174
+ label="Ketik pesan Anda",
175
+ placeholder="Tanyakan tentang data CSV Anda...",
176
+ lines=2
177
+ )
178
+ submit_button = gr.Button("Kirim")
179
+ clear_button = gr.Button("Bersihkan Chat")
180
+
181
+ # Process file handler
182
+ def handle_process_file(file, sess_id):
183
+ # Create chatbot if doesn't exist
184
+ chatbot = ChatBot(sess_id)
185
+ result = chatbot.process_file(file)
186
+ return chatbot, [(None, result)]
187
+
188
+ process_button.click(
189
+ fn=handle_process_file,
190
+ inputs=[file_input, session_id],
191
+ outputs=[chatbot_state, chatbot_interface]
192
+ )
193
+
194
+ # Chat handler - show user message immediately and then start thinking
195
+ def user_message_submitted(message, history, chatbot, sess_id):
196
+ # Add user message to history immediately
197
+ history = history + [(message, None)]
198
+ return history, "", chatbot, sess_id
199
+
200
+ def bot_response(history, chatbot, sess_id):
201
+ # Create chatbot if doesn't exist
202
+ if chatbot is None:
203
+ chatbot = ChatBot(sess_id)
204
+ history[-1] = (history[-1][0], "Mohon upload file CSV terlebih dahulu.")
205
+ return chatbot, history
206
+
207
+ user_message = history[-1][0]
208
+ response = chatbot.chat(user_message, history[:-1])
209
+
210
+ # Update the last history item with the response
211
+ history[-1] = (user_message, response)
212
+ return chatbot, history
213
+
214
+ submit_button.click(
215
+ fn=user_message_submitted,
216
+ inputs=[message_input, chatbot_interface, chatbot_state, session_id],
217
+ outputs=[chatbot_interface, message_input, chatbot_state, session_id]
218
+ ).then(
219
+ fn=bot_response,
220
+ inputs=[chatbot_interface, chatbot_state, session_id],
221
+ outputs=[chatbot_state, chatbot_interface]
222
+ )
223
+
224
+ # Also hook up message input for pressing Enter
225
+ message_input.submit(
226
+ fn=user_message_submitted,
227
+ inputs=[message_input, chatbot_interface, chatbot_state, session_id],
228
+ outputs=[chatbot_interface, message_input, chatbot_state, session_id]
229
+ ).then(
230
+ fn=bot_response,
231
+ inputs=[chatbot_interface, chatbot_state, session_id],
232
+ outputs=[chatbot_state, chatbot_interface]
233
+ )
234
+
235
+ # Clear chat handler
236
+ def handle_clear_chat(chatbot):
237
+ if chatbot is not None:
238
+ chatbot.chat_history = []
239
+ return chatbot, []
240
+
241
+ clear_button.click(
242
+ fn=handle_clear_chat,
243
+ inputs=[chatbot_state],
244
+ outputs=[chatbot_state, chatbot_interface]
245
+ )
246
+
247
+ return interface
248
+
249
+ # Launch the interface
250
+ if __name__ == "__main__":
251
+ demo = create_gradio_interface()
252
+ demo.launch(share=True)