Spaces:
Sleeping
Sleeping
import gradio as gr | |
import re | |
# Load language detection model only (smaller model) | |
from transformers import pipeline | |
language_detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection") | |
# Omdurman National Bank-specific guidelines in Arabic | |
ONB_GUIDELINES_AR = { | |
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك الوطني.", | |
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.", | |
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.", | |
"transfer": "لتحويل الأموال، استخدم تطبيق الهاتف أو الخدمة المصرفية عبر الإنترنت.", | |
"new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.", | |
"interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.", | |
"branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان. زيارة موقعنا للتفاصيل.", | |
"working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.", | |
"contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]." | |
} | |
# Omdurman National Bank-specific guidelines in English | |
ONB_GUIDELINES_EN = { | |
"balance": "You can check your balance online or via the ONB mobile app.", | |
"lost_card": "In case of a lost card, call 249-123-456-789 immediately.", | |
"loan": "Loan requirements include minimum income (5000 SDG) and good credit history.", | |
"transfer": "To transfer funds, use the mobile app or online banking service.", | |
"new_account": "To open a new account, visit your nearest branch with your passport or national ID.", | |
"interest_rates": "Interest rates on deposits range from 5% to 10% annually.", | |
"branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan. Visit our website for details.", | |
"working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.", | |
"contact": "Contact us at 249-123-456-789 or via email at [email protected]." | |
} | |
# Menu options in both languages | |
MENU_AR = """ | |
قائمة الخدمات المصرفية: | |
1. رصيد - استعلام عن رصيد حسابك | |
2. بطاقة - الإبلاغ عن بطاقة مفقودة | |
3. قرض - معلومات عن القروض | |
4. تحويل - تحويل الأموال | |
5. حساب - فتح حساب جديد | |
6. فائدة - أسعار الفائدة | |
7. فرع - مواقع الفروع | |
8. ساعات - ساعات العمل | |
9. اتصال - معلومات الاتصال | |
""" | |
MENU_EN = """ | |
Banking Services Menu: | |
1. balance - Check your account balance | |
2. card - Report a lost card | |
3. loan - Information about loans | |
4. transfer - Transfer funds | |
5. account - Open a new account | |
6. interest - Interest rates | |
7. branch - Branch locations | |
8. hours - Working hours | |
9. contact - Contact information | |
""" | |
# Map intents to keywords (enhanced) | |
INTENT_KEYWORDS = { | |
"balance": ["balance", "check balance", "account balance", "how much", "رصيد", "حساب", "كم المبلغ", "1"], | |
"lost_card": ["lost", "card", "stolen", "missing", "فقدت", "بطاقة", "مسروقة", "ضائعة", "2"], | |
"loan": ["loan", "borrow", "borrowing", "credit", "قرض", "استدانة", "إئتمان", "3"], | |
"transfer": ["transfer", "send money", "payment", "تحويل", "ارسال", "دفع", "4"], | |
"new_account": ["account", "open", "create", "new", "حساب", "فتح", "جديد", "إنشاء", "5"], | |
"interest_rates": ["interest", "rate", "rates", "return", "فائدة", "نسبة", "عائد", "6"], | |
"branches": ["branch", "location", "where", "office", "فرع", "موقع", "أين", "مكتب", "7"], | |
"working_hours": ["hours", "time", "open", "close", "ساعات", "وقت", "مفتوح", "مغلق", "8"], | |
"contact": ["contact", "phone", "email", "call", "اتصال", "هاتف", "بريد", "اتصل", "9"] | |
} | |
def detect_language(text): | |
# Use Hugging Face language detection model | |
result = language_detector(text) | |
language = result[0]['label'] | |
return language | |
def classify_intent(message: str): | |
# Check for menu request | |
menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"] | |
message_lower = message.lower() | |
for keyword in menu_keywords: | |
if keyword in message_lower: | |
return "menu" | |
# Use keyword matching for intent classification | |
for intent_key, keywords in INTENT_KEYWORDS.items(): | |
for keyword in keywords: | |
if keyword.lower() in message_lower: | |
return intent_key | |
return "unknown" | |
def respond(message: str): | |
if not message.strip(): | |
return { | |
"ar": "الرجاء كتابة سؤالك.", | |
"en": "Please type your question." | |
} | |
# Detect language | |
language = detect_language(message) | |
# If the language is neither Arabic nor English, default to English | |
if language != "ar" and language != "en": | |
language = "en" | |
# Classify the user's intent using keyword matching | |
intent = classify_intent(message) | |
# Prepare responses in both languages | |
responses = { | |
"ar": "", | |
"en": "" | |
} | |
# Special handling for menu request | |
if intent == "menu": | |
responses["ar"] = MENU_AR | |
responses["en"] = MENU_EN | |
return responses | |
# If intent is recognized, return the corresponding response | |
if intent != "unknown": | |
responses["ar"] = ONB_GUIDELINES_AR.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.") | |
responses["en"] = ONB_GUIDELINES_EN.get(intent, "Sorry, the selected option was not recognized.") | |
else: | |
# Default response if no intent is matched - show menu | |
responses["ar"] = "عذرًا، لم أفهم سؤالك. إليك قائمة بالخدمات المتاحة:" + MENU_AR | |
responses["en"] = "Sorry, I didn't understand your question. Here's a menu of available services:" + MENU_EN | |
return responses | |
# Custom CSS for better UI | |
custom_css = """ | |
.gradio-container { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
} | |
.chat-message { | |
padding: 1rem; | |
border-radius: 10px; | |
margin-bottom: 1rem; | |
max-width: 80%; | |
} | |
.user-message { | |
background-color: #e6f7ff; | |
margin-left: auto; | |
text-align: right; | |
} | |
.bot-message { | |
background-color: #f0f0f0; | |
margin-right: auto; | |
text-align: left; | |
} | |
.bot-message-ar { | |
background-color: #f0f0f0; | |
margin-left: auto; | |
text-align: right; | |
} | |
.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; | |
} | |
.lang-selector { | |
text-align: right; | |
margin-bottom: 1rem; | |
} | |
.menu-button { | |
margin-top: 0.5rem; | |
} | |
""" | |
# Chat interface with enhanced UI | |
with gr.Blocks(css=custom_css) as demo: | |
# Store conversation history | |
state = gr.State(value=[]) | |
# Store selected language | |
selected_lang = gr.State(value="ar") | |
with gr.Row(elem_classes="header-section"): | |
with gr.Column(): | |
gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني") | |
gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي الافتراضي") | |
with gr.Row(): | |
with gr.Column(elem_classes="lang-selector"): | |
language_btn = gr.Radio( | |
["العربية", "English"], | |
value="العربية", | |
label="Language | اللغة" | |
) | |
with gr.Row(): | |
chat_box = gr.Chatbot(elem_id="chatbox", height=400) | |
with gr.Row(): | |
with gr.Column(scale=8): | |
text_input = gr.Textbox( | |
placeholder="Type your question here | اكتب سؤالك هنا", | |
label="", | |
elem_id="chat-input" | |
) | |
with gr.Column(scale=1): | |
submit_btn = gr.Button("Send | إرسال", variant="primary") | |
with gr.Row(): | |
with gr.Column(elem_classes="menu-button"): | |
menu_btn = gr.Button("Show Menu | إظهار القائمة") | |
with gr.Row(elem_classes="footer-section"): | |
gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©") | |
# Update language state when language is changed | |
def update_language(lang): | |
if lang == "العربية": | |
return "ar" | |
else: | |
return "en" | |
language_btn.change( | |
fn=update_language, | |
inputs=language_btn, | |
outputs=selected_lang | |
) | |
# Handle message submission | |
def on_submit(message, chat_history, lang): | |
if not message.strip(): | |
return "", chat_history | |
# Add user message to chat history | |
chat_history.append([message, None]) | |
# Get response | |
responses = respond(message) | |
# Select response based on language | |
response = responses[lang] | |
# Update bot response in chat history | |
chat_history[-1][1] = response | |
return "", chat_history | |
# Handle menu button click | |
def show_menu(chat_history, lang): | |
menu_responses = { | |
"ar": MENU_AR, | |
"en": MENU_EN | |
} | |
# Add system message showing the menu | |
menu_text = menu_responses[lang] | |
chat_history.append([None, menu_text]) | |
return chat_history | |
# Link inputs and button to response function | |
submit_btn.click( | |
fn=on_submit, | |
inputs=[text_input, chat_box, selected_lang], | |
outputs=[text_input, chat_box] | |
) | |
# Link menu button to show menu function | |
menu_btn.click( | |
fn=show_menu, | |
inputs=[chat_box, selected_lang], | |
outputs=[chat_box] | |
) | |
# Also trigger on Enter key | |
text_input.submit( | |
fn=on_submit, | |
inputs=[text_input, chat_box, selected_lang], | |
outputs=[text_input, chat_box] | |
) | |
if __name__ == "__main__": | |
demo.launch( | |
server_name="0.0.0.0", | |
server_port=7860, | |
share=True # Enable public link | |
) |