waleedmohd's picture
Update app.py
ffd82d1 verified
import gradio as gr
import re
from transformers import pipeline
import json
# Load language detection model
language_detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
# Enhanced Omdurman National Bank guidelines with more detailed information
ONB_GUIDELINES = {
"ar": {
"balance": {
"response": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك الوطني.",
"actions": [
{"label": "تطبيق الهاتف", "url": "https://onb.sd/mobile-app"},
{"label": "الخدمات المصرفية عبر الإنترنت", "url": "https://onb.sd/online-banking"}
]
},
"lost_card": {
"response": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا. سنقوم بإيقاف البطاقة وإصدار بطاقة جديدة.",
"actions": [
{"label": "إيقاف البطاقة فورًا", "url": "tel:249-123-456-789"},
{"label": "طلب بطاقة جديدة", "url": "https://onb.sd/replace-card"}
]
},
"loan": {
"response": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد. نقدم أنواع مختلفة من القروض لتناسب احتياجاتك.",
"actions": [
{"label": "حاسبة القروض", "url": "https://onb.sd/loan-calculator"},
{"label": "تقديم طلب قرض", "url": "https://onb.sd/loan-application"}
]
},
# ... other guideline entries similarly expanded
},
"en": {
"balance": {
"response": "You can check your balance online or via the ONB mobile app. We offer multiple convenient ways to monitor your account.",
"actions": [
{"label": "Mobile App", "url": "https://onb.sd/mobile-app"},
{"label": "Online Banking", "url": "https://onb.sd/online-banking"}
]
},
"lost_card": {
"response": "In case of a lost card, call 249-123-456-789 immediately. We'll block the card and issue a new one to protect your funds.",
"actions": [
{"label": "Block Card Immediately", "url": "tel:249-123-456-789"},
{"label": "Request New Card", "url": "https://onb.sd/replace-card"}
]
},
"loan": {
"response": "Loan requirements include minimum income (5000 SDG) and good credit history. We offer various loan types to suit your needs.",
"actions": [
{"label": "Loan Calculator", "url": "https://onb.sd/loan-calculator"},
{"label": "Apply for Loan", "url": "https://onb.sd/loan-application"}
]
},
# ... other guideline entries similarly expanded
}
}
# Expanded menu with more descriptive options
MENU = {
"ar": """
📱 قائمة الخدمات المصرفية المتقدمة:
1️⃣ رصيد - تتبع حسابك بسهولة 💰
2️⃣ بطاقة - الإبلاغ عن بطاقة مفقودة أو إيقافها 💳
3️⃣ قرض - استكشف خيارات التمويل 💸
4️⃣ تحويل - حوالات محلية ودولية 🌐
5️⃣ حساب - فتح حساب جديد بخطوات مبسطة 📋
6️⃣ فائدة - معرفة أحدث أسعار الفائدة 📈
7️⃣ فرع - مواقع وعناوين الفروع 🏦
8️⃣ ساعات - مواعيد العمل 🕒
9️⃣ اتصال - قنوات التواصل المتاحة 📞
""",
"en": """
📱 Advanced Banking Services Menu:
1️⃣ Balance - Easily track your account 💰
2️⃣ Card - Report or block lost card 💳
3️⃣ Loan - Explore financing options 💸
4️⃣ Transfer - Local and international transfers 🌐
5️⃣ Account - Open a new account in simple steps 📋
6️⃣ Interest - Latest interest rates 📈
7️⃣ Branch - Locations and addresses 🏦
8️⃣ Hours - Working hours 🕒
9️⃣ Contact - Available communication channels 📞
"""
}
# Enhanced intent keywords with more variations
INTENT_KEYWORDS = {
"balance": [
"balance", "check balance", "account balance", "how much",
"رصيد", "حساب", "كم المبلغ", "1", "مبلغ"
],
"lost_card": [
"lost", "card", "stolen", "missing", "block",
"فقدت", "بطاقة", "مسروقة", "ضائعة", "إيقاف", "2"
],
# ... other intents similarly expanded
}
def detect_language(text):
"""Detect the language of the input text."""
try:
result = language_detector(text)
language = result[0]['label']
return language if language in ['ar', 'en'] else 'en'
except Exception:
return 'en'
def classify_intent(message: str):
"""Classify user intent based on keywords."""
message_lower = message.lower()
# Check for menu request
menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"]
if any(keyword in message_lower for keyword in menu_keywords):
return "menu"
# Use keyword matching for intent classification
for intent_key, keywords in INTENT_KEYWORDS.items():
if any(keyword.lower() in message_lower for keyword in keywords):
return intent_key
return "unknown"
def generate_response(intent: str, language: str):
"""Generate a comprehensive response with actions."""
if intent == "menu":
return {
"response": MENU[language],
"actions": []
}
# Get the guideline for the specific intent and language
guideline = ONB_GUIDELINES.get(language, {}).get(intent, {
"response": "I'm sorry, I couldn't find specific information about this topic.",
"actions": []
})
return guideline
def generate_chat_response(message: str):
"""Generate a comprehensive chat response."""
if not message.strip():
return {
"response": {
"ar": "الرجاء كتابة سؤالك.",
"en": "Please type your question."
},
"actions": []
}
# Detect language
language = detect_language(message)
# Classify intent
intent = classify_intent(message)
# Generate response
response_data = generate_response(intent, language)
return {
"response": response_data['response'],
"actions": response_data.get('actions', []),
"language": language
}
# Custom CSS for enhanced UI
custom_css = """
.gradio-container {
font-family: 'Cairo', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
direction: rtl;
}
.chat-message {
padding: 1rem;
border-radius: 10px;
margin-bottom: 1rem;
max-width: 80%;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.user-message {
background-color: #e6f7ff;
margin-left: auto;
text-align: right;
direction: rtl;
}
.bot-message {
background-color: #f0f0f0;
margin-right: auto;
text-align: right;
direction: rtl;
}
.action-buttons {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 0.5rem;
}
.action-button {
background-color: #1a5276;
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 5px;
text-decoration: none;
display: inline-block;
transition: background-color 0.3s ease;
}
.action-button:hover {
background-color: #2980b9;
}
.header-section {
background-color: #1a5276;
color: white;
padding: 1rem;
border-radius: 10px;
margin-bottom: 1rem;
text-align: center;
}
.footer-section {
font-size: 0.8rem;
text-align: center;
margin-top: 2rem;
color: #666;
}
"""
# Enhanced Gradio Interface
def create_gradio_interface():
with gr.Blocks(css=custom_css) as demo:
# Language selection
language_state = gr.State(value="ar")
language_btn = gr.Radio(
["العربية", "English"],
value="العربية",
label="Language | اللغة"
).container=False)
# Chat interface
chatbot = gr.Chatbot(height=500)
msg = gr.Textbox(label="", placeholder="اكتب سؤالك هنا | Type your question here")
submit_btn = gr.Button("إرسال | Send")
# Action buttons container
action_container = gr.HTML()
# Update language state
def update_language(lang):
return "ar" if lang == "العربية" else "en"
language_btn.change(
fn=update_language,
inputs=language_btn,
outputs=language_state
)
# Chat submission handler
def submit_message(message, chat_history, language):
# Generate response
response_data = generate_chat_response(message)
# Ensure we're using the correct language
if response_data['language'] != language:
language = response_data['language']
# Update chat history
chat_history.append((message, response_data['response']))
# Prepare action buttons HTML
action_html = ""
if response_data.get('actions'):
action_html = "<div class='action-buttons'>"
for action in response_data['actions']:
action_html += f"""
<a href="{action['url']}"
class="action-button"
target="_blank">
{action['label']}
</a>
"""
action_html += "</div>"
return "", chat_history, action_html
# Wire up the interface
submit_btn.click(
fn=submit_message,
inputs=[msg, chatbot, language_state],
outputs=[msg, chatbot, action_container]
)
msg.submit(
fn=submit_message,
inputs=[msg, chatbot, language_state],
outputs=[msg, chatbot, action_container]
)
# Add menu button
menu_btn = gr.Button("إظهار القائمة | Show Menu")
def show_menu(chat_history, language):
menu_text = MENU[language]
chat_history.append((None, menu_text))
return chat_history
menu_btn.click(
fn=show_menu,
inputs=[chatbot, language_state],
outputs=[chatbot]
)
# Header and footer
with gr.Row(elem_classes="header-section"):
gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني")
gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي الافتراضي")
with gr.Row(elem_classes="footer-section"):
gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©")
return demo
# Launch the application
if __name__ == "__main__":
demo = create_gradio_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True
)