Spaces:
Runtime error
Runtime error
| """ | |
| Hugging Face Spaces App - Twi Health Information Chatbot | |
| ChatGPT-style conversational interface | |
| Focused on Twi language input and output | |
| Place this file as app.py in your HF Space | |
| """ | |
| import gradio as gr | |
| from sentence_transformers import SentenceTransformer | |
| import faiss | |
| import json | |
| import numpy as np | |
| # Load model and index at startup | |
| print("Loading model and index...") | |
| MODEL_NAME = 'intfloat/multilingual-e5-large' | |
| model = SentenceTransformer(MODEL_NAME) | |
| # Load FAISS index | |
| index = faiss.read_index('faiss_index.bin') | |
| # Load metadata | |
| with open('metadata.json', 'r', encoding='utf-8') as f: | |
| metadata = json.load(f) | |
| print(f"Loaded {len(metadata):,} question-answer pairs") | |
| def search_answers(query, top_k=1): | |
| """ | |
| Search for answers based on query | |
| Args: | |
| query: User's question in Twi or English | |
| top_k: Number of top results to retrieve (default: 1) | |
| Returns: | |
| List of top matching answers | |
| """ | |
| # Encode query with E5 prefix for query encoding | |
| query_text = "query: " + query.strip() | |
| query_embedding = model.encode( | |
| [query_text], | |
| normalize_embeddings=True | |
| ) | |
| # Search in FAISS | |
| distances, indices = index.search(query_embedding.astype('float32'), top_k) | |
| # Prepare results | |
| results = [] | |
| for idx, (similarity, index_pos) in enumerate(zip(distances[0], indices[0]), 1): | |
| if index_pos < len(metadata): | |
| item = metadata[index_pos] | |
| results.append({ | |
| 'rank': idx, | |
| 'question': item['question'], | |
| 'answer': item['answer'], | |
| 'similarity': float(similarity) | |
| }) | |
| return results | |
| # Welcome message in Twi | |
| WELCOME_MESSAGE = """Akwaaba! 👋 | |
| Meyɛ Twi Akwahosan Boafoɔ. Metumi aboa wo wɔ nsɛmmisa ahorow a ɛfa akwahosan ho. | |
| Bisa me nsɛmmisa biara wɔ Twi anaa English mu, na mɛma wo mmuae wɔ Twi mu. | |
| --- | |
| _Welcome! I'm your Twi Health Assistant. I can help you with various health-related questions. Ask me anything in Twi or English, and I'll provide answers in Twi._""" | |
| # Create custom CSS for ChatGPT-like appearance | |
| custom_css = """ | |
| #chatbot { | |
| height: 600px; | |
| overflow-y: auto; | |
| } | |
| .message { | |
| padding: 12px 16px !important; | |
| border-radius: 18px !important; | |
| margin: 8px 0 !important; | |
| } | |
| #input-box textarea { | |
| border-radius: 24px !important; | |
| } | |
| .contain { | |
| max-width: 900px !important; | |
| margin: auto !important; | |
| } | |
| footer { | |
| display: none !important; | |
| } | |
| .chat-header { | |
| text-align: center; | |
| padding: 20px; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border-radius: 12px; | |
| margin-bottom: 20px; | |
| } | |
| """ | |
| # Create Gradio interface with ChatGPT style | |
| with gr.Blocks( | |
| css=custom_css, | |
| theme=gr.themes.Soft( | |
| primary_hue="purple", | |
| secondary_hue="blue", | |
| font=gr.themes.GoogleFont("Inter") | |
| ), | |
| title="Twi Akwahosan Boafoɔ | Twi Health Assistant" | |
| ) as demo: | |
| # Header | |
| gr.HTML(""" | |
| <div class="chat-header"> | |
| <h1 style="margin:0; font-size: 2em;">🏥 Twi Akwahosan Boafoɔ</h1> | |
| <p style="margin:10px 0 0 0; opacity: 0.9;">Twi Health Information Assistant</p> | |
| </div> | |
| """) | |
| # Chatbot interface - simplified without avatar_images to avoid bug | |
| chatbot = gr.Chatbot( | |
| value=[[None, WELCOME_MESSAGE]], | |
| elem_id="chatbot", | |
| label="", | |
| show_label=False, | |
| bubble_full_width=False, | |
| height=600 | |
| ) | |
| # Input section | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| placeholder="Kyerɛw wo nsɛmmisa wɔ ha... | Type your question here...", | |
| show_label=False, | |
| scale=9, | |
| container=False, | |
| elem_id="input-box" | |
| ) | |
| submit_btn = gr.Button("📤", scale=1, variant="primary", size="lg") | |
| # Clear button | |
| with gr.Row(): | |
| clear_btn = gr.Button("🗑️ Firi Aseɛ Bio | Start New Chat", size="sm") | |
| # Example questions section | |
| with gr.Accordion("📝 Nhwɛsoɔ Nsɛmmisa | Example Questions", open=False): | |
| gr.Examples( | |
| examples=[ | |
| ["Dɛn na menyɛ fa alcohol ho wɔ nufunom bere mu?"], | |
| ["Ɛyɛ dɛn sɛ meyi nyinsɛn adi ntɛm?"], | |
| ["Mɛnya ambulance service frɛ nɔma no?"], | |
| ["What should I do if I have malaria?"], | |
| ["Dɛn na memfa ahwɛ me tirim yadeɛ?"], | |
| ["How do I take care of a newborn baby?"], | |
| ["Nsuo dodow bɛn na ɛsɛ sɛ menom da biara?"], | |
| ], | |
| inputs=msg, | |
| label="" | |
| ) | |
| # Information section | |
| with gr.Accordion("ℹ️ Nkyerɛkyerɛmu | About This Assistant", open=False): | |
| gr.Markdown(""" | |
| ### Sɛdeɛ Ɛyɛ Adwuma | How It Works | |
| 1. **Kyerɛw wo nsɛmmisa** wɔ Twi anaa English mu | |
| 2. **Sistɛm no bɛhwehwɛ** nsɛmmisa a ɛne wo de no hyia wɔ database no mu | |
| 3. **Wonya mmuae** wɔ Twi mu ntɛm ara | |
| ### 📊 Technical Details | |
| - **Model**: Multilingual E5-Large (Semantic Search) | |
| - **Database**: Health Q&A pairs in Twi | |
| - **Retrieval**: FAISS vector similarity search | |
| - **Languages**: Primarily Twi, with English support | |
| ### 🔒 Ahobammɔ | Privacy | |
| Wo nsɛmmisa ahorow no yɛ ahobammɔ na wɔmfa nkora so. | |
| _Your questions are private and not stored permanently._ | |
| ### ⚠️ Kɔkɔbɔ | Important Notice | |
| Sɛ ɛyɛ emergency anaa yadeɛ a emu yɛ den a, kɔ ayaresabea anaa frɛ dokta. | |
| _For emergencies or serious health conditions, please visit a hospital or call a doctor._ | |
| """) | |
| # Event handlers | |
| def user_message(user_msg, history): | |
| """Handle user message submission""" | |
| return "", history + [[user_msg, None]] | |
| def bot_message(history): | |
| """Generate bot response""" | |
| if history[-1][1] is not None: | |
| return history | |
| user_msg = history[-1][0] | |
| # Get bot response | |
| results = search_answers(user_msg, top_k=1) | |
| if results and results[0]['similarity'] > 0.3: | |
| bot_response = results[0]['answer'] | |
| else: | |
| bot_response = "Menya mmuae biara a ɛne wo nsɛmmisa no hyia. Yɛsrɛ wo sɛ bɔ mmɔden bio wɔ nsɛmmisa foforɔ so anaa kyerɛw wo nsɛmmisa no bio.\n\n_Menya mmuae a ɛne wo nsɛmmisa no hyia. Sɛ wobɛtumi akyerɛw wo nsɛmmisa no bio anaa bisa nsɛmmisa foforɔ a, ɛbɛboa._" | |
| history[-1][1] = bot_response | |
| return history | |
| def clear_chat(): | |
| """Reset chat to welcome message""" | |
| return [[None, WELCOME_MESSAGE]] | |
| # Wire up events | |
| msg.submit(user_message, [msg, chatbot], [msg, chatbot], queue=False).then( | |
| bot_message, chatbot, chatbot | |
| ) | |
| submit_btn.click(user_message, [msg, chatbot], [msg, chatbot], queue=False).then( | |
| bot_message, chatbot, chatbot | |
| ) | |
| clear_btn.click(clear_chat, None, chatbot, queue=False) | |
| # Footer | |
| gr.Markdown(""" | |
| --- | |
| <div style="text-align: center; color: #666; font-size: 0.9em;"> | |
| <p>Powered by Multilingual E5 & FAISS | Yɛde Twi kasa reba anim 🇬🇭</p> | |
| </div> | |
| """) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.queue() | |
| demo.launch() |