Zahid0123 commited on
Commit
fb14d9c
Β·
verified Β·
1 Parent(s): cd1d99b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -73
app.py CHANGED
@@ -48,7 +48,7 @@ logging.basicConfig(level=logging.INFO)
48
  logger = logging.getLogger(__name__)
49
 
50
  # ===================================================================
51
- # UTILITY CLASSES
52
  # ===================================================================
53
 
54
  class WebSearchTool:
@@ -111,7 +111,7 @@ class ConfigManager:
111
 
112
 
113
  # ===================================================================
114
- # DOCUMENT PROCESSING
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
248
  # ===================================================================
249
 
250
  class DocumentRetriever:
@@ -285,7 +285,7 @@ class DocumentRetriever:
285
 
286
 
287
  # ===================================================================
288
- # AGENTIC TOOLS
289
  # ===================================================================
290
 
291
  class AgenticTools:
@@ -455,7 +455,7 @@ class AgenticEvaluator:
455
 
456
 
457
  # ===================================================================
458
- # MAIN AGENT CLASS
459
  # ===================================================================
460
 
461
  class AgenticRAGAgent:
@@ -492,11 +492,8 @@ 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,43 +502,24 @@ class AgenticRAGAgent:
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,13 +538,11 @@ class AgenticRAGAgent:
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,10 +571,8 @@ Answer:"""
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,7 +622,7 @@ Answer:"""
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,7 +654,7 @@ Answer:"""
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,7 +673,6 @@ Answer:"""
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,12 +721,12 @@ Answer:"""
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,57 +780,56 @@ def create_interface():
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()
 
 
48
  logger = logging.getLogger(__name__)
49
 
50
  # ===================================================================
51
+ # UTILITY CLASSES (unchanged)
52
  # ===================================================================
53
 
54
  class WebSearchTool:
 
111
 
112
 
113
  # ===================================================================
114
+ # DOCUMENT PROCESSING (unchanged)
115
  # ===================================================================
116
 
117
  class DocumentProcessor:
 
244
 
245
 
246
  # ===================================================================
247
+ # RETRIEVER (unchanged)
248
  # ===================================================================
249
 
250
  class DocumentRetriever:
 
285
 
286
 
287
  # ===================================================================
288
+ # AGENTIC TOOLS (unchanged)
289
  # ===================================================================
290
 
291
  class AgenticTools:
 
455
 
456
 
457
  # ===================================================================
458
+ # MAIN AGENT CLASS (unchanged except small fix for audio clear)
459
  # ===================================================================
460
 
461
  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
  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
  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
  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
  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
  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
  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
 
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
  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()