Spaces:
Running
Running
| import gradio as gr | |
| import requests | |
| import json | |
| import logging | |
| import os | |
| from dotenv import load_dotenv | |
| from typing import Dict, List, Tuple | |
| # Load environment variables | |
| load_dotenv() | |
| # Configure logging | |
| logging.basicConfig( | |
| filename='gradio_frontend.log', | |
| level=logging.INFO, | |
| format='%(asctime)s - %(levelname)s - %(message)s' | |
| ) | |
| # API Configuration | |
| API_BASE_URL=os.getenv("API_BASE_URL") | |
| async def process_query(message: str, language: str, mode: str, chat_history: List[Dict]) -> Tuple[str, str]: | |
| """Make API request to get chatbot response""" | |
| try: | |
| payload = { | |
| "message": message, | |
| "language": language, | |
| "mode": mode | |
| } | |
| response = requests.post( | |
| f"{API_BASE_URL}/api/query", | |
| json=payload | |
| ) | |
| response.raise_for_status() | |
| result = response.json() | |
| return result["answer"], result.get("id") | |
| except requests.RequestException as e: | |
| logging.error(f"API request failed: {str(e)}") | |
| return f"Sorry, there was an error processing your request: {str(e)}", None | |
| async def submit_feedback(feedback_type: str, full_chat_history: List[Dict], language_choice: str, mode: str) -> str: | |
| """Submit feedback via API""" | |
| try: | |
| if mode == "Private": | |
| return "Feedback is disabled in private mode." | |
| if not full_chat_history or len(full_chat_history) < 2: | |
| return "No recent interaction to provide feedback for." | |
| # Get the last assistant message with an ID | |
| assistant_messages = [msg for msg in full_chat_history | |
| if msg.get("role") == "assistant" and "id" in msg] | |
| if not assistant_messages: | |
| logging.error("No assistant messages with ID found in chat history") | |
| return "No response found to provide feedback for." | |
| last_message = assistant_messages[-1] | |
| question_id = last_message.get("id") | |
| if not question_id: | |
| logging.error(f"No ID found in last message: {last_message}") | |
| return "Question ID not found. Please try asking another question." | |
| logging.info(f"Submitting feedback for question ID: {question_id}") | |
| # Submit feedback | |
| payload = { | |
| "question_id": question_id, | |
| "feedback_type": feedback_type, | |
| "language": language_choice, | |
| "mode": mode | |
| } | |
| response = requests.post( | |
| f"{API_BASE_URL}/api/feedback", | |
| json=payload | |
| ) | |
| response.raise_for_status() | |
| return "Thanks for your feedback! Your response has been recorded." | |
| except requests.RequestException as e: | |
| logging.error(f"Failed to submit feedback: {str(e)}") | |
| return f"Sorry, there was an error submitting your feedback: {str(e)}" | |
| except Exception as e: | |
| logging.error(f"Unexpected error in submit_feedback: {str(e)}") | |
| return "An unexpected error occurred. Please try again." | |
| # Create Gradio interface | |
| with gr.Blocks(title="RRA FAQ Chatbot") as demo: | |
| full_chat_history = gr.State([]) # Add this line | |
| gr.Markdown( | |
| """ | |
| # RRA FAQ Chatbot | |
| Ask tax-related questions in English or Kinyarwanda | |
| """ | |
| ) | |
| # Add mode selector | |
| with gr.Row(): | |
| interaction_mode = gr.Radio( | |
| choices=["Normal", "Private"], | |
| value="Normal", | |
| label="Interaction Mode", | |
| info="Normal: Stores interactions to improve service | Private: No data storage" | |
| ) | |
| with gr.Row(): | |
| gr.Markdown( | |
| """ | |
| > π **Data Storage Notice:** | |
| > - Normal Mode: Questions and interactions are stored to improve our service | |
| > - Private Mode: No data is stored, feedback feature is disabled | |
| """ | |
| ) | |
| # Add language selector | |
| language = gr.Radio( | |
| choices=["English", "Kinyarwanda"], | |
| value="English", | |
| label="Select Language / Hitamo Ururimi" | |
| ) | |
| chatbot = gr.Chatbot( | |
| value=[], | |
| show_label=False, | |
| height=400 | |
| ) | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="Ask your question", | |
| placeholder="Type your tax-related question here...", | |
| show_label=False | |
| ) | |
| submit = gr.Button("Send") | |
| # Add feedback section | |
| feedback_container = gr.Row(visible=True) | |
| with feedback_container: | |
| with gr.Column(scale=2): | |
| feedback_label = gr.Markdown("Was this response helpful?") | |
| with gr.Column(scale=1): | |
| feedback_positive = gr.Button("π Helpful") | |
| with gr.Column(scale=1): | |
| feedback_negative = gr.Button("π Not Helpful") | |
| # Add feedback status message | |
| feedback_status = gr.Markdown("") | |
| async def respond(message, lang, mode, chat_history, full_chat_history): | |
| """Process a user message and update chat history""" | |
| try: | |
| if chat_history is None: | |
| chat_history = [] | |
| if full_chat_history is None: | |
| full_chat_history = [] | |
| # Get response from API | |
| bot_message, question_id = await process_query(message, lang, mode, chat_history) | |
| if not bot_message: | |
| return "", chat_history, full_chat_history | |
| # Build new messages | |
| user_message = { | |
| "content": message, | |
| "role": "user" | |
| } | |
| assistant_message = { | |
| "content": bot_message, | |
| "role": "assistant", | |
| "id": question_id # Store ID in the message | |
| } | |
| # Append to full chat history | |
| new_full_history = full_chat_history + [user_message, assistant_message] | |
| # Prepare messages for chatbot display | |
| new_chat_history = chat_history + [[message, bot_message]] | |
| return "", new_chat_history, new_full_history | |
| except Exception as e: | |
| logging.error(f"Error in respond function: {e}") | |
| return "", chat_history, full_chat_history | |
| def update_mode(mode: str): | |
| """Update UI when mode changes""" | |
| is_private = (mode == "Private") | |
| return { | |
| feedback_container: gr.update(visible=not is_private), | |
| feedback_status: gr.update(value="" if not is_private else "Feedback is disabled in private mode") | |
| } | |
| # Connect feedback buttons | |
| async def submit_positive_feedback(full_chat_history, language_choice, mode): | |
| return await submit_feedback("positive", full_chat_history, language_choice, mode) | |
| async def submit_negative_feedback(full_chat_history, language_choice, mode): | |
| return await submit_feedback("negative", full_chat_history, language_choice, mode) | |
| feedback_positive.click( | |
| fn=submit_positive_feedback, | |
| inputs=[full_chat_history, language, interaction_mode], | |
| outputs=feedback_status | |
| ) | |
| feedback_negative.click( | |
| fn=submit_negative_feedback, | |
| inputs=[full_chat_history, language, interaction_mode], | |
| outputs=feedback_status | |
| ) | |
| # Update UI when mode changes | |
| interaction_mode.change( | |
| fn=update_mode, | |
| inputs=[interaction_mode], | |
| outputs=[feedback_container, feedback_status] | |
| ) | |
| # Example questions | |
| with gr.Row() as english_examples_row: | |
| gr.Examples( | |
| examples=[ | |
| "What is VAT in Rwanda?", | |
| "How do I register for taxes?", | |
| "What are the tax payment deadlines?", | |
| "How can I get a TIN number?", | |
| "How do I get purchase code?" | |
| ], | |
| inputs=msg, | |
| label="English Examples" | |
| ) | |
| with gr.Row(visible=False) as kinyarwanda_examples_row: | |
| gr.Examples( | |
| examples=[ | |
| "Ese VAT ni iki mu Rwanda?", | |
| "Nabona TIN number nte?", | |
| "Ni ryari tugomba kwishyura imisoro?", | |
| "Ese nandikwa nte ku musoro?", | |
| "Ni gute nabone kode yo kugura?" | |
| ], | |
| inputs=msg, | |
| label="Kinyarwanda Examples" | |
| ) | |
| def toggle_language_interface(language_choice): | |
| if language_choice == "English": | |
| placeholder_text = "Type your tax-related question here..." | |
| return { | |
| msg: gr.update(placeholder=placeholder_text), | |
| english_examples_row: gr.update(visible=True), | |
| kinyarwanda_examples_row: gr.update(visible=False) | |
| } | |
| else: | |
| placeholder_text = "Andika ibibazo bijyanye n'umusoro hano" | |
| return { | |
| msg: gr.update(placeholder=placeholder_text), | |
| english_examples_row: gr.update(visible=False), | |
| kinyarwanda_examples_row: gr.update(visible=True) | |
| } | |
| # Connect user inputs | |
| msg.submit( | |
| respond, | |
| [msg, language, interaction_mode, chatbot, full_chat_history], | |
| [msg, chatbot, full_chat_history] | |
| ) | |
| submit.click( | |
| respond, | |
| [msg, language, interaction_mode, chatbot, full_chat_history], | |
| [msg, chatbot, full_chat_history] | |
| ) | |
| # Update interface on language change | |
| language.change( | |
| fn=toggle_language_interface, | |
| inputs=language, | |
| outputs=[msg, english_examples_row, kinyarwanda_examples_row] | |
| ) | |
| gr.Markdown( | |
| """ | |
| ### About | |
| - Created by: [Cedric](mailto:[email protected]) | |
| - Data source: [RRA Website FAQ](https://www.rra.gov.rw/en/domestic-tax-services/faqs) | |
| **Disclaimer:** This chatbot provides general tax information. For official guidance, | |
| consult RRA or call 3004. | |
| """ | |
| ) | |
| if __name__ == "__main__": | |
| try: | |
| demo.launch(share=False) | |
| logging.info("Gradio app launched successfully.") | |
| except Exception as launch_error: | |
| logging.critical(f"Failed to launch Gradio app: {launch_error}") | |
| raise | |