maternal-chat / app.py
michsethowusu's picture
Update app.py
c3d3c70 verified
"""
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()