Rabbit-Innotech commited on
Commit
2d0370f
·
verified ·
1 Parent(s): 172bb91

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -125
app.py CHANGED
@@ -207,25 +207,29 @@ class TranslationService:
207
 
208
  def translate_text(self, text: str, src_lang: str, tgt_lang: str) -> str:
209
  """Translate text using Hugging Face API."""
210
- response = requests.post(
211
- self.url,
212
- headers=self.headers,
213
- json={
214
- "inputs": text,
215
- "parameters": {
216
- "src_lang": src_lang,
217
- "tgt_lang": tgt_lang
 
 
218
  }
219
- }
220
- )
221
-
222
- if response.status_code == 200:
223
- result = response.json()
224
- if isinstance(result, list) and len(result) > 0:
225
- return result[0]['translation_text']
226
- return result['translation_text']
227
- else:
228
- print(f"Translation error: {response.status_code}, {response.text}")
 
 
229
  return text # Return original text if translation fails
230
 
231
 
@@ -298,24 +302,28 @@ class UserSession:
298
  f"5. Keep the message concise and impactful."
299
  )
300
 
301
- # Use the LLM to generate the message
302
- welcome = "".join(self.llm.stream(prompt))
303
-
304
- # Get translation service and translate welcome message
305
- api_token = os.environ.get('Token')
306
- translator = TranslationService(api_token)
307
- welcome_text = translator.translate_text(welcome, src_lang, tgt_lang)
308
-
309
- # Format the message with HTML styling
310
- self.welcome_message = (
311
- f"<div style='font-size: 20px;'>"
312
- f"{welcome_text}"
313
- f"</div>"
314
- )
 
 
 
 
315
 
316
  def get_welcome_message(self) -> str:
317
  """Get the welcome message."""
318
- return self.welcome_message
319
 
320
  def add_to_history(self, role: str, message: str) -> None:
321
  """Add a message to the conversation history."""
@@ -338,20 +346,35 @@ class GBVSupportChatbot:
338
  """Main chatbot application class."""
339
 
340
  def __init__(self):
341
- self.api_key = os.environ.get('V2')
342
- self.api_token = os.environ.get('Token')
 
 
 
 
 
 
 
 
 
 
343
  self.llm_instance = OpenRouterLLM(key=self.api_key)
344
  self.user_session = UserSession(self.llm_instance)
345
  self.translator = TranslationService(self.api_token)
346
 
347
  # Initialize embedding model
348
- self.embed_model = HuggingFaceEmbeddings(model_name="mixedbread-ai/mxbai-embed-large-v1")
349
-
350
- # Initialize vector store
351
- self.vectorstore = Chroma(
352
- collection_name="Dataset",
353
- embedding_function=self.embed_model,
354
- )
 
 
 
 
 
355
 
356
  # Template for GBV support chatbot
357
  self.template = """
@@ -400,51 +423,82 @@ class GBVSupportChatbot:
400
 
401
  def load_data(self) -> None:
402
  """Load and process all data sources."""
403
- # Process all data sources
404
- data_processor = DataProcessor()
405
- context_data = data_processor.process_tabular_data()
406
-
407
- # Process PDFs
408
- pdf_documents = data_processor.process_pdf_files()
409
- text_chunks = data_processor.split_documents(pdf_documents)
410
-
411
- # Combine all data
412
- all_data = []
413
- all_data.extend(context_data)
414
- all_data.extend([item for item in text_chunks if item not in all_data])
415
-
416
- # Add data to vector store
417
- self.vectorstore.add_texts(all_data)
 
 
 
 
 
 
 
 
 
 
418
 
419
  def create_rag_chain(self):
420
  """Create RAG chain with user context and conversation history."""
421
- retriever = self.vectorstore.as_retriever()
422
- rag_prompt = PromptTemplate.from_template(self.template)
423
-
424
- def stream_func(input_dict):
425
- # Get context using the retriever's invoke method
426
- context = retriever.invoke(input_dict["question"])
427
- context_str = "\n".join([doc.page_content for doc in context])
428
-
429
- # Get user info from the session
430
- user_info = self.user_session.get_user() or {}
431
- first_name = user_info.get("Nickname", "User")
432
 
433
- # Get conversation history
434
- conversation_history = self.user_session.get_formatted_history()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
 
436
- # Format prompt with user context and conversation history
437
- prompt = rag_prompt.format(
438
- context=context_str,
439
- question=input_dict["question"],
440
- first_name=first_name,
441
- conversation_history=conversation_history
442
- )
443
 
444
- # Stream response
445
- return self.llm_instance.stream(prompt)
446
-
447
- return stream_func
 
448
 
449
  def collect_user_info(self, nickname: str):
450
  """Collect and process user information."""
@@ -463,34 +517,63 @@ class GBVSupportChatbot:
463
  # Generate welcome message
464
  welcome_message = self.user_session.get_welcome_message()
465
 
466
- # For the standard Chatbot component, the history format is different
467
- chat_history = [(None, welcome_message)]
468
 
469
  # Return welcome message and update UI
470
  return welcome_message, gr.update(visible=True), gr.update(visible=False), chat_history
471
 
472
  def rag_memory_stream(self, message: str, history):
473
  """Process user message, translate, and generate response."""
474
- # Translate user message to English (from Kinyarwanda by default)
475
- english_message = self.translator.translate_text(message, "kin_Latn", "eng_Latn")
476
-
477
- # Add translated message to history
478
- self.user_session.add_to_history("user", english_message)
479
-
480
- # Generate response using RAG chain
481
- full_response = ""
482
- rag_chain = self.create_rag_chain()
483
-
484
- for new_text in rag_chain({"question": english_message}):
485
- full_response += new_text
486
-
487
- # Translate response back to user language (Kinyarwanda by default)
488
- translated_response = self.translator.translate_text(full_response, "eng_Latn", "kin_Latn")
489
-
490
- # Add response to history
491
- self.user_session.add_to_history("assistant", full_response)
492
-
493
- yield translated_response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
 
495
  def create_chatbot_interface(self):
496
  """Create and configure the chatbot UI."""
@@ -514,12 +597,13 @@ class GBVSupportChatbot:
514
 
515
  # Chatbot section (initially hidden)
516
  with gr.Column(visible=False, elem_id="chatbot_container") as chatbot_container:
517
- # Replace ChatInterface with standard Chatbot
518
  chatbot = gr.Chatbot(
519
  label="Chat with GBVR",
520
  height=500,
521
  show_label=True,
522
- elem_id="chat_interface"
 
523
  )
524
 
525
  with gr.Row():
@@ -532,27 +616,22 @@ class GBVSupportChatbot:
532
  )
533
  send_btn = gr.Button("Send", variant="primary", scale=1)
534
 
535
- # Set up the chat behavior
536
- def chat_response(message, history):
537
- # Clear input
538
- yield history, ""
539
- # Process message and generate response
540
- for response in self.rag_memory_stream(message, history):
541
- history.append((message, response))
542
- yield history, ""
543
-
544
  # Configure event handlers
545
- msg.submit(
546
- chat_response,
547
  inputs=[msg, chatbot],
548
  outputs=[chatbot, msg]
549
  )
550
- send_btn.click(
551
- chat_response,
552
  inputs=[msg, chatbot],
553
  outputs=[chatbot, msg]
554
  )
555
 
 
 
 
 
556
  # Footer with version info
557
  gr.Markdown("Ijwi ry'Ubufasha Chatbot v1.0.0 © 2025")
558
 
@@ -573,7 +652,7 @@ class GBVSupportChatbot:
573
  body, .gradio-container {
574
  margin: 0;
575
  padding: 0;
576
- width: 100vw;
577
  height: 100vh;
578
  display: flex;
579
  flex-direction: column;
@@ -631,17 +710,29 @@ class GBVSupportChatbot:
631
 
632
  return demo
633
 
 
 
 
 
 
 
 
 
634
  # Main execution function
635
  def main():
636
  # Initialize the chatbot
637
  chatbot = GBVSupportChatbot()
638
 
639
- # Load data
640
- chatbot.load_data()
641
-
642
- # Create and launch the interface
643
- demo = chatbot.create_chatbot_interface()
644
- demo.launch(share=True)
 
 
 
 
645
 
646
  if __name__ == "__main__":
647
  main()
 
207
 
208
  def translate_text(self, text: str, src_lang: str, tgt_lang: str) -> str:
209
  """Translate text using Hugging Face API."""
210
+ try:
211
+ response = requests.post(
212
+ self.url,
213
+ headers=self.headers,
214
+ json={
215
+ "inputs": text,
216
+ "parameters": {
217
+ "src_lang": src_lang,
218
+ "tgt_lang": tgt_lang
219
+ }
220
  }
221
+ )
222
+
223
+ if response.status_code == 200:
224
+ result = response.json()
225
+ if isinstance(result, list) and len(result) > 0:
226
+ return result[0]['translation_text']
227
+ return result['translation_text']
228
+ else:
229
+ print(f"Translation error: {response.status_code}, {response.text}")
230
+ return text # Return original text if translation fails
231
+ except Exception as e:
232
+ print(f"Translation error: {e}")
233
  return text # Return original text if translation fails
234
 
235
 
 
302
  f"5. Keep the message concise and impactful."
303
  )
304
 
305
+ try:
306
+ # Use the LLM to generate the message
307
+ welcome = "".join(list(self.llm.stream(prompt)))
308
+
309
+ # Get translation service and translate welcome message
310
+ api_token = os.environ.get('Token')
311
+ if not api_token:
312
+ self.welcome_message = f"Welcome {nickname}! This is a safe space where you can find support and resources."
313
+ return
314
+
315
+ translator = TranslationService(api_token)
316
+ welcome_text = translator.translate_text(welcome, src_lang, tgt_lang)
317
+
318
+ # Format the message with HTML styling
319
+ self.welcome_message = welcome_text
320
+ except Exception as e:
321
+ print(f"Error generating welcome message: {e}")
322
+ self.welcome_message = f"Welcome {nickname}! This is a safe space where you can find support and resources."
323
 
324
  def get_welcome_message(self) -> str:
325
  """Get the welcome message."""
326
+ return self.welcome_message or "Welcome! This is a safe space where you can find support."
327
 
328
  def add_to_history(self, role: str, message: str) -> None:
329
  """Add a message to the conversation history."""
 
346
  """Main chatbot application class."""
347
 
348
  def __init__(self):
349
+ self.api_key = os.environ.get('V2', '')
350
+ self.api_token = os.environ.get('Token', '')
351
+
352
+ # Add fallback for missing environment variables
353
+ if not self.api_key:
354
+ print("Warning: V2 API key not found in environment variables.")
355
+ self.api_key = "demo_key" # Use a placeholder value
356
+
357
+ if not self.api_token:
358
+ print("Warning: Token not found in environment variables.")
359
+ self.api_token = "demo_token" # Use a placeholder value
360
+
361
  self.llm_instance = OpenRouterLLM(key=self.api_key)
362
  self.user_session = UserSession(self.llm_instance)
363
  self.translator = TranslationService(self.api_token)
364
 
365
  # Initialize embedding model
366
+ try:
367
+ self.embed_model = HuggingFaceEmbeddings(model_name="mixedbread-ai/mxbai-embed-large-v1")
368
+
369
+ # Initialize vector store
370
+ self.vectorstore = Chroma(
371
+ collection_name="Dataset",
372
+ embedding_function=self.embed_model,
373
+ )
374
+ except Exception as e:
375
+ print(f"Error initializing embeddings: {e}")
376
+ # Create a simple placeholder for vectorstore if initialization fails
377
+ self.vectorstore = None
378
 
379
  # Template for GBV support chatbot
380
  self.template = """
 
423
 
424
  def load_data(self) -> None:
425
  """Load and process all data sources."""
426
+ if not self.vectorstore:
427
+ print("Warning: Vector store not initialized. Skipping data loading.")
428
+ return
429
+
430
+ try:
431
+ # Process all data sources
432
+ data_processor = DataProcessor()
433
+ context_data = data_processor.process_tabular_data()
434
+
435
+ # Process PDFs
436
+ pdf_documents = data_processor.process_pdf_files()
437
+ text_chunks = data_processor.split_documents(pdf_documents)
438
+
439
+ # Combine all data
440
+ all_data = []
441
+ all_data.extend(context_data)
442
+ all_data.extend([item for item in text_chunks if item not in all_data])
443
+
444
+ if all_data:
445
+ # Add data to vector store
446
+ self.vectorstore.add_texts(all_data)
447
+ else:
448
+ print("Warning: No data found to load into vector store.")
449
+ except Exception as e:
450
+ print(f"Error loading data: {e}")
451
 
452
  def create_rag_chain(self):
453
  """Create RAG chain with user context and conversation history."""
454
+ try:
455
+ if self.vectorstore:
456
+ retriever = self.vectorstore.as_retriever()
457
+ else:
458
+ # Create a simple fallback if vectorstore is not available
459
+ retriever = FallbackRetriever()
460
+
461
+ rag_prompt = PromptTemplate.from_template(self.template)
 
 
 
462
 
463
+ def stream_func(input_dict):
464
+ try:
465
+ # Get context using the retriever's invoke method
466
+ if self.vectorstore:
467
+ context = retriever.invoke(input_dict["question"])
468
+ context_str = "\n".join([doc.page_content for doc in context])
469
+ else:
470
+ context_str = "No specific information available on this topic."
471
+
472
+ # Get user info from the session
473
+ user_info = self.user_session.get_user() or {}
474
+ first_name = user_info.get("Nickname", "User")
475
+
476
+ # Get conversation history
477
+ conversation_history = self.user_session.get_formatted_history()
478
+
479
+ # Format prompt with user context and conversation history
480
+ prompt = rag_prompt.format(
481
+ context=context_str,
482
+ question=input_dict["question"],
483
+ first_name=first_name,
484
+ conversation_history=conversation_history
485
+ )
486
+
487
+ # Stream response
488
+ return self.llm_instance.stream(prompt)
489
+ except Exception as e:
490
+ print(f"Error in RAG chain: {e}")
491
+ yield f"I apologize, but I'm having trouble processing your request. Please try again or rephrase your question."
492
 
493
+ return stream_func
494
+ except Exception as e:
495
+ print(f"Error creating RAG chain: {e}")
 
 
 
 
496
 
497
+ # Return a simple fallback function
498
+ def fallback_func(input_dict):
499
+ yield "I apologize, but I'm having technical difficulties. Please try again later."
500
+
501
+ return fallback_func
502
 
503
  def collect_user_info(self, nickname: str):
504
  """Collect and process user information."""
 
517
  # Generate welcome message
518
  welcome_message = self.user_session.get_welcome_message()
519
 
520
+ # Create welcome message in the new messages format for Gradio chatbot
521
+ chat_history = [{"role": "assistant", "content": welcome_message}]
522
 
523
  # Return welcome message and update UI
524
  return welcome_message, gr.update(visible=True), gr.update(visible=False), chat_history
525
 
526
  def rag_memory_stream(self, message: str, history):
527
  """Process user message, translate, and generate response."""
528
+ try:
529
+ # First, yield the current history to show user message
530
+ history_copy = history.copy()
531
+ history_copy.append({"role": "user", "content": message})
532
+ yield history_copy, ""
533
+
534
+ # Translate user message to English (from Kinyarwanda by default)
535
+ try:
536
+ english_message = self.translator.translate_text(message, "kin_Latn", "eng_Latn")
537
+ except Exception as e:
538
+ print(f"Translation error: {e}")
539
+ english_message = message # Fallback to original message if translation fails
540
+
541
+ # Add translated message to history
542
+ self.user_session.add_to_history("user", english_message)
543
+
544
+ # Generate response using RAG chain
545
+ full_response = ""
546
+ rag_chain = self.create_rag_chain()
547
+
548
+ # Generate chunks of response and update as they come
549
+ for new_text in rag_chain({"question": english_message}):
550
+ full_response += new_text
551
+
552
+ # Translate response back to user language (Kinyarwanda by default)
553
+ try:
554
+ translated_response = self.translator.translate_text(full_response, "eng_Latn", "kin_Latn")
555
+ except Exception as e:
556
+ print(f"Translation error: {e}")
557
+ translated_response = full_response # Fallback to original message if translation fails
558
+
559
+ # Update history with current response
560
+ current_history = history_copy.copy()
561
+ current_history.append({"role": "assistant", "content": translated_response})
562
+ yield current_history, ""
563
+
564
+ # Add final response to session history
565
+ self.user_session.add_to_history("assistant", full_response)
566
+
567
+ except Exception as e:
568
+ print(f"Error in chat processing: {e}")
569
+ # Provide a fallback response if something goes wrong
570
+ error_history = history.copy()
571
+ error_history.append({"role": "user", "content": message})
572
+ error_history.append({
573
+ "role": "assistant",
574
+ "content": "I apologize, but I'm having trouble processing your request. Please try again."
575
+ })
576
+ yield error_history, ""
577
 
578
  def create_chatbot_interface(self):
579
  """Create and configure the chatbot UI."""
 
597
 
598
  # Chatbot section (initially hidden)
599
  with gr.Column(visible=False, elem_id="chatbot_container") as chatbot_container:
600
+ # Use the new messages format for the chatbot
601
  chatbot = gr.Chatbot(
602
  label="Chat with GBVR",
603
  height=500,
604
  show_label=True,
605
+ elem_id="chat_interface",
606
+ type="messages" # Use messages format instead of tuples
607
  )
608
 
609
  with gr.Row():
 
616
  )
617
  send_btn = gr.Button("Send", variant="primary", scale=1)
618
 
 
 
 
 
 
 
 
 
 
619
  # Configure event handlers
620
+ msg_event = msg.submit(
621
+ self.rag_memory_stream,
622
  inputs=[msg, chatbot],
623
  outputs=[chatbot, msg]
624
  )
625
+ send_event = send_btn.click(
626
+ self.rag_memory_stream,
627
  inputs=[msg, chatbot],
628
  outputs=[chatbot, msg]
629
  )
630
 
631
+ # Clear textbox after sending
632
+ msg_event.then(lambda: "", None, msg)
633
+ send_event.then(lambda: "", None, msg)
634
+
635
  # Footer with version info
636
  gr.Markdown("Ijwi ry'Ubufasha Chatbot v1.0.0 © 2025")
637
 
 
652
  body, .gradio-container {
653
  margin: 0;
654
  padding: 0;
655
+ width: 100%;
656
  height: 100vh;
657
  display: flex;
658
  flex-direction: column;
 
710
 
711
  return demo
712
 
713
+
714
+ # Fallback retriever class for when vectorstore is not available
715
+ class FallbackRetriever:
716
+ def invoke(self, query):
717
+ # Return a list of document-like objects with empty content
718
+ return [Document(page_content="No specific information available on this topic.", metadata={})]
719
+
720
+
721
  # Main execution function
722
  def main():
723
  # Initialize the chatbot
724
  chatbot = GBVSupportChatbot()
725
 
726
+ try:
727
+ # Load data
728
+ chatbot.load_data()
729
+
730
+ # Create and launch the interface
731
+ demo = chatbot.create_chatbot_interface()
732
+ demo.launch(share=True)
733
+ except Exception as e:
734
+ print(f"Error in main execution: {e}")
735
+
736
 
737
  if __name__ == "__main__":
738
  main()