Zahid0123 commited on
Commit
992ab7f
Β·
verified Β·
1 Parent(s): 559403a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -28
app.py CHANGED
@@ -18,6 +18,7 @@ try:
18
  GROQ_OK = True
19
  except ImportError:
20
  GROQ_OK = False
 
21
 
22
  logging.basicConfig(level=logging.INFO)
23
  logger = logging.getLogger(__name__)
@@ -31,20 +32,34 @@ groq_client = None
31
  if GROQ_OK:
32
  try:
33
  print("DEBUG β†’ Initializing Groq client...")
34
- groq_client = Groq(api_key=GROQ_API_KEY) # <- only api_key
35
- print("DEBUG β†’ Groq client initialized successfully!")
 
 
 
 
 
 
 
 
 
 
 
36
  except Exception as e:
37
  groq_client = None
38
- print("❌ Groq initialization error:", e)
 
 
39
 
40
  class AgenticRAGAgent:
41
  def __init__(self):
42
  self.chunks = []
43
  self.index = None
44
  self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
 
45
 
46
- # Remove emojis completely
47
  def remove_emojis(self, text: str) -> str:
 
48
  emoji_pattern = re.compile("["
49
  u"\U0001F600-\U0001F64F"
50
  u"\U0001F300-\U0001F5FF"
@@ -56,19 +71,21 @@ class AgenticRAGAgent:
56
  return emoji_pattern.sub(r'', text)
57
 
58
  def clean_for_voice(self, text: str) -> str:
 
59
  text = self.remove_emojis(text)
60
  text = re.sub(r'[\*_`#\[\]]', '', text)
61
  text = re.sub(r'\s+', ' ', text).strip()
62
  return text
63
 
64
  def generate_voice(self, text: str):
 
65
  if not text or not text.strip():
66
  return None
67
  clean = self.clean_for_voice(text)
68
  if len(clean) < 5:
69
  return None
70
  try:
71
- tts = gTTS(text=clean, lang='en')
72
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
73
  tts.save(tmp.name)
74
  return tmp.name
@@ -77,6 +94,7 @@ class AgenticRAGAgent:
77
  return None
78
 
79
  def upload_pdfs(self, files):
 
80
  if not files:
81
  return "No files selected."
82
 
@@ -86,14 +104,17 @@ class AgenticRAGAgent:
86
  count = 0
87
 
88
  for file in files:
89
- if not str(file.name).lower().endswith('.pdf'):
 
90
  continue
91
- dest = folder / Path(file.name).name
 
92
  try:
93
- content = file.read() if hasattr(file, 'read') else open(file.name, 'rb').read()
94
  with open(dest, "wb") as f:
95
  f.write(content)
96
  except Exception as e:
 
97
  continue
98
 
99
  text = ""
@@ -104,7 +125,8 @@ class AgenticRAGAgent:
104
  t = page.extract_text()
105
  if t:
106
  text += t + " "
107
- except:
 
108
  continue
109
 
110
  if text.strip():
@@ -115,33 +137,43 @@ class AgenticRAGAgent:
115
  if not all_chunks:
116
  return "No readable text found in the PDFs."
117
 
118
- vecs = self.embedder.encode([c["content"] for c in all_chunks], show_progress_bar=False)
 
 
119
  vecs = vecs / np.linalg.norm(vecs, axis=1, keepdims=True)
120
  dim = vecs.shape[1]
 
121
  self.index = faiss.IndexFlatIP(dim)
122
  self.index.add(vecs.astype('float32'))
123
  self.chunks = all_chunks
124
 
125
- return f"Loaded {count} PDF(s) β†’ {len(all_chunks)} chunks ready!"
 
 
126
 
127
  def ask(self, question: str, history: List):
 
128
  global groq_client
 
129
  if not question.strip():
130
  return history, None
131
 
132
  if not history:
133
  history = []
134
 
 
135
  if question.strip().lower() in ["hi", "hello", "hey", "hola", "howdy"]:
136
  reply = "Hi there! I am AI Research Agent with agentic capabilities. Upload PDF documents and ask complex questions!"
137
  history.append([question, reply])
138
  return history, self.generate_voice(reply)
139
 
 
140
  if not self.index:
141
  reply = "Please upload a PDF document first!"
142
  history.append([question, reply])
143
  return history, self.generate_voice(reply)
144
 
 
145
  q_vec = self.embedder.encode([question])
146
  q_vec = q_vec / np.linalg.norm(q_vec)
147
  D, I = self.index.search(q_vec.astype('float32'), k=6)
@@ -150,9 +182,11 @@ class AgenticRAGAgent:
150
  prompt = f"Context from documents:\n{context}\n\nQuestion: {question}\nAnswer clearly and accurately:"
151
 
152
  if groq_client is None:
153
- reply = "GROQ_API_KEY is missing or invalid."
 
154
  else:
155
  try:
 
156
  resp = groq_client.chat.completions.create(
157
  model="llama-3.3-70b-versatile",
158
  messages=[{"role": "user", "content": prompt}],
@@ -160,56 +194,108 @@ class AgenticRAGAgent:
160
  max_tokens=700
161
  )
162
  reply = resp.choices[0].message.content.strip()
 
163
  except Exception as e:
164
  reply = f"Groq API error: {str(e)}"
 
165
 
166
  history.append([question, reply])
167
  return history, self.generate_voice(reply)
168
 
 
169
  # =========================================
170
  # GRADIO UI
171
  # =========================================
172
  def create_interface():
173
  agent = AgenticRAGAgent()
174
 
175
- with gr.Blocks(title="πŸ€– AI Research Agent", theme=gr.themes.Soft()) as interface:
176
  gr.HTML("""
177
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px;">
178
- <h1 style="color: white; margin: 0;">πŸ€– AI Research Agent - Agentic RAG</h1>
179
- <p style="color: white; margin: 10px 0;">Advanced Multi-Tool Research Assistant with Voice Support πŸ”Š</p>
180
  </div>
181
  """)
182
 
183
  with gr.Row():
184
  with gr.Column(scale=2):
185
- chatbot = gr.Chatbot(label="πŸ’¬ Chat", height=500)
 
 
 
 
186
 
187
  with gr.Row():
188
- msg = gr.Textbox(label="", placeholder="Ask a complex research question...", scale=4)
189
- submit_btn = gr.Button("πŸš€ Send", variant="primary", scale=1)
 
 
 
 
 
190
 
191
  with gr.Row():
192
- clear_btn = gr.Button("πŸ—‘οΈ Clear Chat", variant="secondary")
193
 
194
- audio_output = gr.Audio(label="πŸ”Š Voice Response", autoplay=True, interactive=False)
 
 
 
 
195
 
196
  with gr.Column(scale=1):
197
  with gr.Group():
198
- gr.HTML("<h3 style='text-align: center;'>πŸ“„ Upload Documents</h3>")
199
- file_upload = gr.Files(label="", file_types=[".pdf"], file_count="multiple")
200
- upload_status = gr.Textbox(label="πŸ“Š Status", interactive=False, max_lines=10)
 
 
 
 
 
 
 
 
201
 
202
  def respond(message, history):
 
203
  new_hist, audio_file = agent.ask(message, history)
204
  return "", new_hist, audio_file
205
 
206
- submit_btn.click(respond, inputs=[msg, chatbot], outputs=[msg, chatbot, audio_output])
207
- msg.submit(respond, inputs=[msg, chatbot], outputs=[msg, chatbot, audio_output])
208
- clear_btn.click(lambda: ([], None), outputs=[chatbot, audio_output])
209
- file_upload.change(agent.upload_pdfs, inputs=[file_upload], outputs=[upload_status])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  return interface
212
 
 
213
  if __name__ == "__main__":
 
214
  app = create_interface()
215
- app.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
18
  GROQ_OK = True
19
  except ImportError:
20
  GROQ_OK = False
21
+ print("❌ Groq library not installed!")
22
 
23
  logging.basicConfig(level=logging.INFO)
24
  logger = logging.getLogger(__name__)
 
32
  if GROQ_OK:
33
  try:
34
  print("DEBUG β†’ Initializing Groq client...")
35
+ # Initialize with just api_key - most compatible approach
36
+ groq_client = Groq(api_key=GROQ_API_KEY)
37
+ print("βœ… DEBUG β†’ Groq client initialized successfully!")
38
+ except TypeError as te:
39
+ # Fallback for version compatibility issues
40
+ print(f"⚠️ TypeError during init: {te}")
41
+ try:
42
+ print("πŸ”„ Attempting fallback initialization...")
43
+ groq_client = Groq(api_key=GROQ_API_KEY)
44
+ print("βœ… Fallback initialization successful!")
45
+ except Exception as e:
46
+ groq_client = None
47
+ print(f"❌ Groq initialization failed: {e}")
48
  except Exception as e:
49
  groq_client = None
50
+ print(f"❌ Groq initialization error: {e}")
51
+ else:
52
+ print("❌ Groq library import failed!")
53
 
54
  class AgenticRAGAgent:
55
  def __init__(self):
56
  self.chunks = []
57
  self.index = None
58
  self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
59
+ print("βœ… AgenticRAGAgent initialized with SentenceTransformer")
60
 
 
61
  def remove_emojis(self, text: str) -> str:
62
+ """Remove emojis from text for clean voice output"""
63
  emoji_pattern = re.compile("["
64
  u"\U0001F600-\U0001F64F"
65
  u"\U0001F300-\U0001F5FF"
 
71
  return emoji_pattern.sub(r'', text)
72
 
73
  def clean_for_voice(self, text: str) -> str:
74
+ """Clean text for voice synthesis"""
75
  text = self.remove_emojis(text)
76
  text = re.sub(r'[\*_`#\[\]]', '', text)
77
  text = re.sub(r'\s+', ' ', text).strip()
78
  return text
79
 
80
  def generate_voice(self, text: str):
81
+ """Generate voice output from text"""
82
  if not text or not text.strip():
83
  return None
84
  clean = self.clean_for_voice(text)
85
  if len(clean) < 5:
86
  return None
87
  try:
88
+ tts = gTTS(text=clean, lang='en', slow=False)
89
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
90
  tts.save(tmp.name)
91
  return tmp.name
 
94
  return None
95
 
96
  def upload_pdfs(self, files):
97
+ """Upload and process PDF files"""
98
  if not files:
99
  return "No files selected."
100
 
 
104
  count = 0
105
 
106
  for file in files:
107
+ filename = str(file.name) if hasattr(file, 'name') else str(file)
108
+ if not filename.lower().endswith('.pdf'):
109
  continue
110
+
111
+ dest = folder / Path(filename).name
112
  try:
113
+ content = file.read() if hasattr(file, 'read') else open(filename, 'rb').read()
114
  with open(dest, "wb") as f:
115
  f.write(content)
116
  except Exception as e:
117
+ logger.warning(f"Failed to save file {filename}: {e}")
118
  continue
119
 
120
  text = ""
 
125
  t = page.extract_text()
126
  if t:
127
  text += t + " "
128
+ except Exception as e:
129
+ logger.warning(f"Failed to extract text from {filename}: {e}")
130
  continue
131
 
132
  if text.strip():
 
137
  if not all_chunks:
138
  return "No readable text found in the PDFs."
139
 
140
+ # Create embeddings and FAISS index
141
+ print(f"Creating embeddings for {len(all_chunks)} chunks...")
142
+ vecs = self.embedder.encode([c["content"] for c in all_chunks], show_progress_bar=True)
143
  vecs = vecs / np.linalg.norm(vecs, axis=1, keepdims=True)
144
  dim = vecs.shape[1]
145
+
146
  self.index = faiss.IndexFlatIP(dim)
147
  self.index.add(vecs.astype('float32'))
148
  self.chunks = all_chunks
149
 
150
+ status_msg = f"βœ… Loaded {count} PDF(s) β†’ {len(all_chunks)} chunks ready!"
151
+ print(status_msg)
152
+ return status_msg
153
 
154
  def ask(self, question: str, history: List):
155
+ """Process user question and generate response"""
156
  global groq_client
157
+
158
  if not question.strip():
159
  return history, None
160
 
161
  if not history:
162
  history = []
163
 
164
+ # Handle greeting
165
  if question.strip().lower() in ["hi", "hello", "hey", "hola", "howdy"]:
166
  reply = "Hi there! I am AI Research Agent with agentic capabilities. Upload PDF documents and ask complex questions!"
167
  history.append([question, reply])
168
  return history, self.generate_voice(reply)
169
 
170
+ # Check if PDFs are loaded
171
  if not self.index:
172
  reply = "Please upload a PDF document first!"
173
  history.append([question, reply])
174
  return history, self.generate_voice(reply)
175
 
176
+ # Retrieve relevant chunks
177
  q_vec = self.embedder.encode([question])
178
  q_vec = q_vec / np.linalg.norm(q_vec)
179
  D, I = self.index.search(q_vec.astype('float32'), k=6)
 
182
  prompt = f"Context from documents:\n{context}\n\nQuestion: {question}\nAnswer clearly and accurately:"
183
 
184
  if groq_client is None:
185
+ reply = "ERROR: Groq client is not initialized. Check your API key and connection."
186
+ print("❌ Groq client is None - cannot process request")
187
  else:
188
  try:
189
+ print(f"πŸ“€ Sending request to Groq API for question: {question[:50]}...")
190
  resp = groq_client.chat.completions.create(
191
  model="llama-3.3-70b-versatile",
192
  messages=[{"role": "user", "content": prompt}],
 
194
  max_tokens=700
195
  )
196
  reply = resp.choices[0].message.content.strip()
197
+ print(f"βœ… Received response from Groq API")
198
  except Exception as e:
199
  reply = f"Groq API error: {str(e)}"
200
+ print(f"❌ Groq API error: {e}")
201
 
202
  history.append([question, reply])
203
  return history, self.generate_voice(reply)
204
 
205
+
206
  # =========================================
207
  # GRADIO UI
208
  # =========================================
209
  def create_interface():
210
  agent = AgenticRAGAgent()
211
 
212
+ with gr.Blocks(title="AI Research Agent", theme=gr.themes.Soft()) as interface:
213
  gr.HTML("""
214
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px;">
215
+ <h1 style="color: white; margin: 0;">AI Research Agent - Agentic RAG</h1>
216
+ <p style="color: white; margin: 10px 0;">Advanced Multi-Tool Research Assistant with Voice Support</p>
217
  </div>
218
  """)
219
 
220
  with gr.Row():
221
  with gr.Column(scale=2):
222
+ chatbot = gr.Chatbot(
223
+ label="Chat",
224
+ height=500,
225
+ type="tuples"
226
+ )
227
 
228
  with gr.Row():
229
+ msg = gr.Textbox(
230
+ label="",
231
+ placeholder="Ask a complex research question...",
232
+ scale=4,
233
+ lines=1
234
+ )
235
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
236
 
237
  with gr.Row():
238
+ clear_btn = gr.Button("Clear Chat", variant="secondary")
239
 
240
+ audio_output = gr.Audio(
241
+ label="Voice Response",
242
+ autoplay=True,
243
+ interactive=False
244
+ )
245
 
246
  with gr.Column(scale=1):
247
  with gr.Group():
248
+ gr.HTML("<h3 style='text-align: center;'>Upload Documents</h3>")
249
+ file_upload = gr.Files(
250
+ label="",
251
+ file_types=[".pdf"],
252
+ file_count="multiple"
253
+ )
254
+ upload_status = gr.Textbox(
255
+ label="Status",
256
+ interactive=False,
257
+ max_lines=10
258
+ )
259
 
260
  def respond(message, history):
261
+ """Handle user message"""
262
  new_hist, audio_file = agent.ask(message, history)
263
  return "", new_hist, audio_file
264
 
265
+ def clear_chat():
266
+ """Clear chat history"""
267
+ return [], None
268
+
269
+ # Connect events
270
+ submit_btn.click(
271
+ respond,
272
+ inputs=[msg, chatbot],
273
+ outputs=[msg, chatbot, audio_output]
274
+ )
275
+ msg.submit(
276
+ respond,
277
+ inputs=[msg, chatbot],
278
+ outputs=[msg, chatbot, audio_output]
279
+ )
280
+ clear_btn.click(
281
+ clear_chat,
282
+ outputs=[chatbot, audio_output]
283
+ )
284
+ file_upload.change(
285
+ agent.upload_pdfs,
286
+ inputs=[file_upload],
287
+ outputs=[upload_status]
288
+ )
289
 
290
  return interface
291
 
292
+
293
  if __name__ == "__main__":
294
+ print("πŸš€ Starting AI Research Agent...")
295
  app = create_interface()
296
+ app.launch(
297
+ server_name="0.0.0.0",
298
+ server_port=7860,
299
+ show_error=True,
300
+ share=False
301
+ )