Zahid0123 commited on
Commit
4b0b53b
Β·
verified Β·
1 Parent(s): 0452f80

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -45
app.py CHANGED
@@ -48,7 +48,7 @@ logging.basicConfig(level=logging.INFO)
48
  logger = logging.getLogger(__name__)
49
 
50
  # ===================================================================
51
- # UTILITY CLASSES (unchanged)
52
  # ===================================================================
53
 
54
  class WebSearchTool:
@@ -111,7 +111,7 @@ class ConfigManager:
111
 
112
 
113
  # ===================================================================
114
- # DOCUMENT PROCESSING (unchanged)
115
  # ===================================================================
116
 
117
  class DocumentProcessor:
@@ -244,7 +244,7 @@ def build_embeddings_from_directory(data_directory: str, output_directory: str,
244
 
245
 
246
  # ===================================================================
247
- # RETRIEVER (unchanged)
248
  # ===================================================================
249
 
250
  class DocumentRetriever:
@@ -285,7 +285,7 @@ class DocumentRetriever:
285
 
286
 
287
  # ===================================================================
288
- # AGENTIC TOOLS (unchanged)
289
  # ===================================================================
290
 
291
  class AgenticTools:
@@ -455,7 +455,7 @@ class AgenticEvaluator:
455
 
456
 
457
  # ===================================================================
458
- # MAIN AGENT CLASS (unchanged except small fix for audio clear)
459
  # ===================================================================
460
 
461
  class AgenticRAGAgent:
@@ -492,8 +492,11 @@ class AgenticRAGAgent:
492
  print(f"❌ Error: {e}")
493
 
494
  def clean_text_for_speech(self, text):
 
495
  if not text:
496
  return ""
 
 
497
  text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text)
498
  text = re.sub(r'\*([^*]+)\*', r'\1', text)
499
  text = re.sub(r'^#{1,6}\s+', '', text, flags=re.MULTILINE)
@@ -502,24 +505,43 @@ class AgenticRAGAgent:
502
  text = re.sub(r'`([^`]+)`', r'\1', text)
503
  text = re.sub(r'^[\s]*[-*+β€’]\s+', '', text, flags=re.MULTILINE)
504
  text = re.sub(r'^[\s]*\d+\.\s+', '', text, flags=re.MULTILINE)
505
- emoji_pattern = re.compile("[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF\U0001F1E0-\U0001F1FF\U00002702-\U000027B0\U000024C2-\U0001F251\U0001F900-\U0001F9FF\U00002600-\U000026FF\U00002700-\U000027BF]+")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  text = emoji_pattern.sub('', text)
507
  text = re.sub(r'\s+', ' ', text)
508
  text = re.sub(r'\n+', '. ', text)
509
  text = text.strip()
510
  text = re.sub(r'\.+', '.', text)
 
511
  return text
512
 
513
  def generate_audio_response(self, text):
 
514
  if not text or not GTTS_AVAILABLE:
515
  return None
 
516
  clean_text = self.clean_text_for_speech(text)
517
  if not clean_text:
518
  return None
 
519
  try:
520
  temp_dir = tempfile.gettempdir()
521
  timestamp = int(time.time())
522
  audio_file = os.path.join(temp_dir, f"response_{timestamp}.mp3")
 
523
  tts = gTTS(text=clean_text, lang='en', slow=False)
524
  tts.save(audio_file)
525
  return audio_file
@@ -538,11 +560,13 @@ class AgenticRAGAgent:
538
  def get_simple_answer(self, query, retrieved_docs):
539
  if not self.groq_client:
540
  return "Error: Groq API not configured"
 
541
  context = "\n\n".join([doc.get('content', str(doc)) for doc in retrieved_docs[:5]])
542
  prompt = f"""Based on this context, provide a clear answer.
543
  Context: {context}
544
  Question: {query}
545
  Answer:"""
 
546
  try:
547
  response = self.groq_client.chat.completions.create(
548
  model="llama-3.1-8b-instant",
@@ -571,8 +595,10 @@ Answer:"""
571
  progress(0.5, desc="Generating response...")
572
  response = self.get_greeting_response(query)
573
  chat_history.append({"role": "assistant", "content": response})
 
574
  progress(0.8, desc="πŸ”Š Generating voice...")
575
  audio_file = self.generate_audio_response(response)
 
576
  return chat_history, "", audio_file
577
 
578
  progress(0.1, desc="🧠 Planning...")
@@ -622,7 +648,7 @@ Answer:"""
622
  if self.synthesizer:
623
  final_answer = self.synthesizer.synthesize_results(query, results, self.temperature, self.max_tokens)
624
  else:
625
- successful = [r['result'] for r in results.values() if r.get("success")]
626
  final_answer = f"Based on available info: {' '.join(map(str, successful))}"
627
 
628
  progress(0.9, desc="πŸ“Š Evaluating...")
@@ -654,7 +680,7 @@ Answer:"""
654
  return chat_history, "", audio_file
655
 
656
  except Exception as e:
657
- mockery = f"❌ Error: {str(e)}"
658
  chat_history.append({"role": "assistant", "content": error})
659
  return chat_history, "", None
660
 
@@ -673,6 +699,7 @@ Answer:"""
673
  dest = os.path.join("sample_data", original)
674
  with open(dest, "wb") as dst:
675
  dst.write(file.read())
 
676
  uploaded.append(original)
677
 
678
  if not uploaded:
@@ -721,12 +748,12 @@ Answer:"""
721
 
722
 
723
  # ===================================================================
724
- # CREATE AGENT GLOBALLY + FIXED GRADIO INTERFACE
725
  # ===================================================================
726
 
727
- agent = AgenticRAGAgent() # ← Important: global instance
728
-
729
  def create_interface():
 
 
730
  with gr.Blocks(title="πŸ€– AI Research Agent", theme=gr.themes.Soft()) as interface:
731
  gr.HTML("""
732
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px;">
@@ -780,56 +807,57 @@ def create_interface():
780
  gr.HTML(f"""
781
  <div style="padding: 10px;">
782
  <p><strong>Text-to-Speech (gTTS):</strong> {'βœ… Available' if GTTS_AVAILABLE else '❌ Not Available'}</p>
783
- <p>< Urol><strong>Speech-to-Text:</strong> {'βœ… Available' if STT_AVAILABLE else '❌ Not Available (HF Spaces limitation)'}</p>
784
  <p><em>Voice output: Auto-plays with responses</em></p>
785
  </div>
786
  """)
787
 
788
- # ===================== FIXED EVENT HANDLERS =====================
789
- def respond(message, history):
790
- return agent.process_agentic_query(message, history)
791
-
792
- submit_btn.click(
793
- fn=respond,
794
- inputs=[msg, chatbot],
795
- outputs=[chatbot, msg, audio_output],
796
- concurrency_limit=1
797
- )
798
- msg.submit(
799
- fn=respond,
800
- inputs=[msg, chatbot],
801
- outputs=[chatbot, msg, audio_output],
802
- concurrency_limit=1
803
- )
804
 
805
- clear_btn.click(
806
- lambda: ([], None),
807
- outputs=[chatbot, audio_output]
808
- )
809
 
810
- file_upload.change(
811
- fn=agent.upload_documents,
812
- inputs=[file_upload],
813
- outputs=[upload_status]
814
- )
815
 
816
  apply_btn.click(
817
- fn=agent.update_settings,
818
- inputs=[temperature_slider, max_tokens_slider, chunk_size_slider,
819
- chunk_overlap_slider, retrieval_k_slider, enable_web,
820
- enable_calc, enable_fact, enable_analysis],
 
 
821
  outputs=[settings_status]
822
  )
823
 
824
  return interface
825
 
826
-
827
  # ===================================================================
828
- # MAIN - WITH QUEUE (CRITICAL FOR HF SPACES)
829
  # ===================================================================
830
 
831
  if __name__ == "__main__":
832
  print("πŸš€ Launching AI Research Agent on Hugging Face Spaces...")
 
 
 
 
 
 
 
 
833
  app = create_interface()
834
- app.queue() # ← THIS FIXES 99% of button issues on HF Spaces
835
- app.launch()
 
48
  logger = logging.getLogger(__name__)
49
 
50
  # ===================================================================
51
+ # UTILITY CLASSES
52
  # ===================================================================
53
 
54
  class WebSearchTool:
 
111
 
112
 
113
  # ===================================================================
114
+ # DOCUMENT PROCESSING
115
  # ===================================================================
116
 
117
  class DocumentProcessor:
 
244
 
245
 
246
  # ===================================================================
247
+ # RETRIEVER
248
  # ===================================================================
249
 
250
  class DocumentRetriever:
 
285
 
286
 
287
  # ===================================================================
288
+ # AGENTIC TOOLS
289
  # ===================================================================
290
 
291
  class AgenticTools:
 
455
 
456
 
457
  # ===================================================================
458
+ # MAIN AGENT CLASS
459
  # ===================================================================
460
 
461
  class AgenticRAGAgent:
 
492
  print(f"❌ Error: {e}")
493
 
494
  def clean_text_for_speech(self, text):
495
+ """Clean text for TTS"""
496
  if not text:
497
  return ""
498
+
499
+ # Remove markdown formatting
500
  text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text)
501
  text = re.sub(r'\*([^*]+)\*', r'\1', text)
502
  text = re.sub(r'^#{1,6}\s+', '', text, flags=re.MULTILINE)
 
505
  text = re.sub(r'`([^`]+)`', r'\1', text)
506
  text = re.sub(r'^[\s]*[-*+β€’]\s+', '', text, flags=re.MULTILINE)
507
  text = re.sub(r'^[\s]*\d+\.\s+', '', text, flags=re.MULTILINE)
508
+
509
+ # Remove emojis
510
+ emoji_pattern = re.compile(
511
+ "["
512
+ "\U0001F600-\U0001F64F"
513
+ "\U0001F300-\U0001F5FF"
514
+ "\U0001F680-\U0001F6FF"
515
+ "\U0001F1E0-\U0001F1FF"
516
+ "\U00002702-\U000027B0"
517
+ "\U000024C2-\U0001F251"
518
+ "\U0001F900-\U0001F9FF"
519
+ "\U00002600-\U000026FF"
520
+ "\U00002700-\U000027BF"
521
+ "]+"
522
+ )
523
  text = emoji_pattern.sub('', text)
524
  text = re.sub(r'\s+', ' ', text)
525
  text = re.sub(r'\n+', '. ', text)
526
  text = text.strip()
527
  text = re.sub(r'\.+', '.', text)
528
+
529
  return text
530
 
531
  def generate_audio_response(self, text):
532
+ """Generate audio using gTTS"""
533
  if not text or not GTTS_AVAILABLE:
534
  return None
535
+
536
  clean_text = self.clean_text_for_speech(text)
537
  if not clean_text:
538
  return None
539
+
540
  try:
541
  temp_dir = tempfile.gettempdir()
542
  timestamp = int(time.time())
543
  audio_file = os.path.join(temp_dir, f"response_{timestamp}.mp3")
544
+
545
  tts = gTTS(text=clean_text, lang='en', slow=False)
546
  tts.save(audio_file)
547
  return audio_file
 
560
  def get_simple_answer(self, query, retrieved_docs):
561
  if not self.groq_client:
562
  return "Error: Groq API not configured"
563
+
564
  context = "\n\n".join([doc.get('content', str(doc)) for doc in retrieved_docs[:5]])
565
  prompt = f"""Based on this context, provide a clear answer.
566
  Context: {context}
567
  Question: {query}
568
  Answer:"""
569
+
570
  try:
571
  response = self.groq_client.chat.completions.create(
572
  model="llama-3.1-8b-instant",
 
595
  progress(0.5, desc="Generating response...")
596
  response = self.get_greeting_response(query)
597
  chat_history.append({"role": "assistant", "content": response})
598
+
599
  progress(0.8, desc="πŸ”Š Generating voice...")
600
  audio_file = self.generate_audio_response(response)
601
+
602
  return chat_history, "", audio_file
603
 
604
  progress(0.1, desc="🧠 Planning...")
 
648
  if self.synthesizer:
649
  final_answer = self.synthesizer.synthesize_results(query, results, self.temperature, self.max_tokens)
650
  else:
651
+ successful = [r['result'] for r in results.values() if r.get('success')]
652
  final_answer = f"Based on available info: {' '.join(map(str, successful))}"
653
 
654
  progress(0.9, desc="πŸ“Š Evaluating...")
 
680
  return chat_history, "", audio_file
681
 
682
  except Exception as e:
683
+ error = f"❌ Error: {str(e)}"
684
  chat_history.append({"role": "assistant", "content": error})
685
  return chat_history, "", None
686
 
 
699
  dest = os.path.join("sample_data", original)
700
  with open(dest, "wb") as dst:
701
  dst.write(file.read())
702
+
703
  uploaded.append(original)
704
 
705
  if not uploaded:
 
748
 
749
 
750
  # ===================================================================
751
+ # GRADIO INTERFACE (COMPATIBLE WITH GRADIO 4.27)
752
  # ===================================================================
753
 
 
 
754
  def create_interface():
755
+ agent = AgenticRAGAgent()
756
+
757
  with gr.Blocks(title="πŸ€– AI Research Agent", theme=gr.themes.Soft()) as interface:
758
  gr.HTML("""
759
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px;">
 
807
  gr.HTML(f"""
808
  <div style="padding: 10px;">
809
  <p><strong>Text-to-Speech (gTTS):</strong> {'βœ… Available' if GTTS_AVAILABLE else '❌ Not Available'}</p>
810
+ <p><strong>Speech-to-Text:</strong> {'βœ… Available' if STT_AVAILABLE else '❌ Not Available (HF Spaces limitation)'}</p>
811
  <p><em>Voice output: Auto-plays with responses</em></p>
812
  </div>
813
  """)
814
 
815
+ # -----------------------------
816
+ # Event Handlers (Sync wrapper for async)
817
+ # -----------------------------
818
+ def process_msg(message, history):
819
+ import asyncio
820
+ try:
821
+ loop = asyncio.get_event_loop()
822
+ if loop.is_running():
823
+ future = asyncio.run_coroutine_threadsafe(agent.process_agentic_query(message, history), loop)
824
+ return future.result()
825
+ else:
826
+ return loop.run_until_complete(agent.process_agentic_query(message, history))
827
+ except RuntimeError:
828
+ return asyncio.run(agent.process_agentic_query(message, history))
 
 
829
 
830
+ submit_btn.click(process_msg, inputs=[msg, chatbot], outputs=[chatbot, msg, audio_output])
831
+ msg.submit(process_msg, inputs=[msg, chatbot], outputs=[chatbot, msg, audio_output])
832
+ clear_btn.click(lambda: [], outputs=[chatbot])
 
833
 
834
+ file_upload.change(agent.upload_documents, inputs=[file_upload], outputs=[upload_status])
 
 
 
 
835
 
836
  apply_btn.click(
837
+ agent.update_settings,
838
+ inputs=[
839
+ temperature_slider, max_tokens_slider, chunk_size_slider,
840
+ chunk_overlap_slider, retrieval_k_slider, enable_web,
841
+ enable_calc, enable_fact, enable_analysis
842
+ ],
843
  outputs=[settings_status]
844
  )
845
 
846
  return interface
847
 
 
848
  # ===================================================================
849
+ # MAIN
850
  # ===================================================================
851
 
852
  if __name__ == "__main__":
853
  print("πŸš€ Launching AI Research Agent on Hugging Face Spaces...")
854
+ print("✨ Features:")
855
+ print(" β€’ Multi-Tool Integration")
856
+ print(" β€’ Intelligent Query Planning")
857
+ print(" β€’ Multi-Step Reasoning")
858
+ print(" β€’ Result Synthesis")
859
+ print(" β€’ Quality Evaluation")
860
+ print(" β€’ πŸ”Š Voice Output (Text-to-Speech)")
861
+
862
  app = create_interface()
863
+ app.launch()