Spaces:
Runtime error
Runtime error
import gradio as gr | |
import re | |
import json | |
import time | |
from datetime import datetime | |
# Simple language detection function instead of using transformers | |
def simple_detect_language(text): | |
# Check for Arabic characters | |
arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+') | |
if arabic_pattern.search(text): | |
return "ar" | |
return "en" | |
# Try to import transformers for Arabic NLP if available | |
try: | |
from transformers import pipeline | |
arabic_nlp = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection") | |
ARABIC_NLP_AVAILABLE = True | |
def detect_language_with_nlp(text): | |
result = arabic_nlp(text) | |
return result[0]['label'] | |
except ImportError: | |
ARABIC_NLP_AVAILABLE = False | |
# Import customer service enhancements | |
try: | |
from customer_service_enhancements import ( | |
ENHANCED_CUSTOMER_SERVICE_PHRASES_AR, | |
ENHANCED_CUSTOMER_SERVICE_PHRASES_EN, | |
BANKING_FAQS_AR, | |
BANKING_FAQS_EN, | |
BANKING_GLOSSARY_AR, | |
BANKING_GLOSSARY_EN, | |
get_enhanced_response, | |
handle_banking_faq, | |
offer_satisfaction_survey, | |
get_banking_term_definition | |
) | |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = True | |
except ImportError: | |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = False | |
# Fallback customer service phrases | |
ENHANCED_CUSTOMER_SERVICE_PHRASES_AR = { | |
"greeting": [ | |
"مرحبًا بك في بنك أم درمان الوطني! كيف يمكنني مساعدتك اليوم؟", | |
"أهلاً بك في خدمة العملاء الافتراضية لبنك أم درمان الوطني. كيف يمكنني خدمتك؟" | |
], | |
"thanks": [ | |
"شكرًا لتواصلك مع بنك أم درمان الوطني!", | |
"نشكرك على ثقتك في خدماتنا المصرفية." | |
], | |
"follow_up": [ | |
"هل هناك خدمة مصرفية أخرى يمكنني مساعدتك بها اليوم؟", | |
"هل لديك أي استفسارات أخرى حول منتجاتنا أو خدماتنا المصرفية؟" | |
] | |
} | |
ENHANCED_CUSTOMER_SERVICE_PHRASES_EN = { | |
"greeting": [ | |
"Welcome to Omdurman National Bank! How may I assist you today?", | |
"Hello and welcome to ONB virtual customer service. How can I help you?" | |
], | |
"thanks": [ | |
"Thank you for contacting Omdurman National Bank!", | |
"We appreciate your trust in our banking services." | |
], | |
"follow_up": [ | |
"Is there any other banking service I can assist you with today?", | |
"Do you have any other questions about our products or banking services?" | |
] | |
} | |
# Omdurman National Bank-specific guidelines in Arabic | |
ONB_GUIDELINES_AR = { | |
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك أم درمان الوطني. <a href='#' onclick='window.open(\"https://onb.sd/balance\", \"_blank\")'>افحص رصيدك الآن</a>", | |
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم <a href='tel:249123456789'>249-123-456-789</a> فورًا أو <a href='#' onclick='window.open(\"https://onb.sd/block-card\", \"_blank\")'>أوقف البطاقة عبر الإنترنت</a>.", | |
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد. <a href='#' onclick='window.open(\"https://onb.sd/loans\", \"_blank\")'>تقدم بطلب قرض الآن</a>", | |
"transfer": "لتحويل الأموال، استخدم <a href='#' onclick='window.open(\"https://onb.sd/mobile-app\", \"_blank\")'>تطبيق الهاتف</a> أو <a href='#' onclick='window.open(\"https://onb.sd/online-banking\", \"_blank\")'>الخدمة المصرفية عبر الإنترنت</a>.", | |
"new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية. <a href='#' onclick='window.open(\"https://onb.sd/new-account\", \"_blank\")'>احجز موعدًا الآن</a>", | |
"interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا. <a href='#' onclick='window.open(\"https://onb.sd/rates\", \"_blank\")'>اطلع على جميع الأسعار</a>", | |
"branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان. <a href='#' onclick='window.open(\"https://onb.sd/branches\", \"_blank\")'>اعثر على أقرب فرع</a>", | |
"working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس. <a href='#' onclick='window.open(\"https://onb.sd/hours\", \"_blank\")'>تحقق من ساعات العمل الخاصة</a>", | |
"contact": "الاتصال بنا على الرقم <a href='tel:249123456789'>249-123-456-789</a> أو عبر البريد الإلكتروني <a href='mailto:[email protected]'>[email protected]</a>. <a href='#' onclick='window.open(\"https://onb.sd/contact\", \"_blank\")'>نموذج الاتصال</a>" | |
} | |
# Omdurman National Bank-specific guidelines in English | |
ONB_GUIDELINES_EN = { | |
"balance": "You can check your balance online or via the ONB mobile app. <a href='#' onclick='window.open(\"https://onb.sd/balance\", \"_blank\")'>Check your balance now</a>", | |
"lost_card": "In case of a lost card, call <a href='tel:249123456789'>249-123-456-789</a> immediately or <a href='#' onclick='window.open(\"https://onb.sd/block-card\", \"_blank\")'>block your card online</a>.", | |
"loan": "Loan requirements include minimum income (5000 SDG) and good credit history. <a href='#' onclick='window.open(\"https://onb.sd/loans\", \"_blank\")'>Apply for a loan now</a>", | |
"transfer": "To transfer funds, use the <a href='#' onclick='window.open(\"https://onb.sd/mobile-app\", \"_blank\")'>mobile app</a> or <a href='#' onclick='window.open(\"https://onb.sd/online-banking\", \"_blank\")'>online banking service</a>.", | |
"new_account": "To open a new account, visit your nearest branch with your passport or national ID. <a href='#' onclick='window.open(\"https://onb.sd/new-account\", \"_blank\")'>Book an appointment now</a>", | |
"interest_rates": "Interest rates on deposits range from 5% to 10% annually. <a href='#' onclick='window.open(\"https://onb.sd/rates\", \"_blank\")'>View all rates</a>", | |
"branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan. <a href='#' onclick='window.open(\"https://onb.sd/branches\", \"_blank\")'>Find your nearest branch</a>", | |
"working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday. <a href='#' onclick='window.open(\"https://onb.sd/hours\", \"_blank\")'>Check special hours</a>", | |
"contact": "Contact us at <a href='tel:249123456789'>249-123-456-789</a> or via email at <a href='mailto:[email protected]'>[email protected]</a>. <a href='#' onclick='window.open(\"https://onb.sd/contact\", \"_blank\")'>Contact form</a>" | |
} | |
# Quick action buttons in Arabic | |
QUICK_ACTIONS_AR = [ | |
{"text": "تحقق من الرصيد", "intent": "balance"}, | |
{"text": "الإبلاغ عن بطاقة مفقودة", "intent": "lost_card"}, | |
{"text": "معلومات القرض", "intent": "loan"}, | |
{"text": "تحويل الأموال", "intent": "transfer"}, | |
{"text": "فتح حساب جديد", "intent": "new_account"}, | |
{"text": "أسعار الفائدة", "intent": "interest_rates"}, | |
{"text": "مواقع الفروع", "intent": "branches"}, | |
{"text": "ساعات العمل", "intent": "working_hours"}, | |
{"text": "اتصل بنا", "intent": "contact"} | |
] | |
# Quick action buttons in English | |
QUICK_ACTIONS_EN = [ | |
{"text": "Check Balance", "intent": "balance"}, | |
{"text": "Report Lost Card", "intent": "lost_card"}, | |
{"text": "Loan Information", "intent": "loan"}, | |
{"text": "Transfer Funds", "intent": "transfer"}, | |
{"text": "Open New Account", "intent": "new_account"}, | |
{"text": "Interest Rates", "intent": "interest_rates"}, | |
{"text": "Branch Locations", "intent": "branches"}, | |
{"text": "Working Hours", "intent": "working_hours"}, | |
{"text": "Contact Us", "intent": "contact"} | |
] | |
# 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"] | |
} | |
# Function to get a random phrase from the customer service phrases | |
def get_random_phrase(category, language): | |
import random | |
if language == "ar": | |
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_AR[category]) | |
else: | |
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_EN[category]) | |
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" | |
# Function to log customer interactions | |
def log_interaction(user_message, bot_response, intent, language): | |
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
log_entry = { | |
"timestamp": timestamp, | |
"user_message": user_message, | |
"bot_response": bot_response, | |
"intent": intent, | |
"language": language | |
} | |
try: | |
with open("interaction_logs.jsonl", "a") as f: | |
f.write(json.dumps(log_entry) + "\n") | |
except Exception as e: | |
print(f"Error logging interaction: {e}") | |
def respond(message: str): | |
if not message.strip(): | |
return { | |
"ar": "الرجاء كتابة سؤالك.", | |
"en": "Please type your question." | |
} | |
# Detect language using NLP if available, otherwise use simple detection | |
if ARABIC_NLP_AVAILABLE: | |
language = detect_language_with_nlp(message) | |
# If the language is neither Arabic nor English, default to English | |
if language != "ar" and language != "en": | |
language = "en" | |
else: | |
language = simple_detect_language(message) | |
# 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 | |
log_interaction(message, responses[language], "menu", language) | |
return responses | |
# Check if it's a banking FAQ | |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
faq_answer = handle_banking_faq(message, language) | |
if faq_answer: | |
# Add a greeting phrase at the beginning | |
greeting_ar = get_random_phrase("greeting", "ar") | |
greeting_en = get_random_phrase("greeting", "en") | |
# Add a follow-up phrase at the end | |
follow_up_ar = get_random_phrase("follow_up", "ar") | |
follow_up_en = get_random_phrase("follow_up", "en") | |
# Combine all parts | |
responses["ar"] = f"{greeting_ar}<br><br>{faq_answer}<br><br>{follow_up_ar}" | |
responses["en"] = f"{greeting_en}<br><br>{faq_answer}<br><br>{follow_up_en}" | |
log_interaction(message, responses[language], "faq", language) | |
return responses | |
# Check if it's a banking term definition request | |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
term_definition = get_banking_term_definition(message, language) | |
if term_definition: | |
# Add a greeting phrase at the beginning | |
greeting_ar = get_random_phrase("greeting", "ar") | |
greeting_en = get_random_phrase("greeting", "en") | |
# Add a follow-up phrase at the end | |
follow_up_ar = get_random_phrase("follow_up", "ar") | |
follow_up_en = get_random_phrase("follow_up", "en") | |
# Combine all parts | |
responses["ar"] = f"{greeting_ar}<br><br>{term_definition}<br><br>{follow_up_ar}" | |
responses["en"] = f"{greeting_en}<br><br>{term_definition}<br><br>{follow_up_en}" | |
log_interaction(message, responses[language], "term", language) | |
return responses | |
# If intent is recognized, return the corresponding response | |
if intent != "unknown": | |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
# Use enhanced response if available | |
responses["ar"] = get_enhanced_response(intent, "ar") | |
responses["en"] = get_enhanced_response(intent, "en") | |
else: | |
# Add a greeting phrase at the beginning | |
greeting_ar = get_random_phrase("greeting", "ar") | |
greeting_en = get_random_phrase("greeting", "en") | |
# Add the main response | |
main_response_ar = ONB_GUIDELINES_AR.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.") | |
main_response_en = ONB_GUIDELINES_EN.get(intent, "Sorry, the selected option was not recognized.") | |
# Add a follow-up phrase at the end | |
follow_up_ar = get_random_phrase("follow_up", "ar") | |
follow_up_en = get_random_phrase("follow_up", "en") | |
# Combine all parts | |
responses["ar"] = f"{greeting_ar}<br><br>{main_response_ar}<br><br>{follow_up_ar}" | |
responses["en"] = f"{greeting_en}<br><br>{main_response_en}<br><br>{follow_up_en}" | |
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 | |
# Log the interaction | |
log_interaction(message, responses[language], intent, language) | |
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; | |
} | |
.quick-actions { | |
display: flex; | |
flex-wrap: wrap; | |
gap: 0.5rem; | |
margin: 1rem 0; | |
} | |
.quick-action-button { | |
background-color: #1a5276; | |
color: white; | |
border: none; | |
border-radius: 20px; | |
padding: 0.5rem 1rem; | |
cursor: pointer; | |
font-size: 0.9rem; | |
transition: background-color 0.3s; | |
} | |
.quick-action-button:hover { | |
background-color: #2980b9; | |
} | |
.chat-container { | |
border: 1px solid #ddd; | |
border-radius: 10px; | |
padding: 1rem; | |
background-color: #f9f9f9; | |
} | |
.live-agent-button { | |
background-color: #27ae60; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
padding: 0.5rem 1rem; | |
cursor: pointer; | |
font-size: 0.9rem; | |
margin-top: 1rem; | |
transition: background-color 0.3s; | |
} | |
.live-agent-button:hover { | |
background-color: #2ecc71; | |
} | |
/* Add custom styling for links */ | |
a { | |
color: #2980b9; | |
text-decoration: none; | |
font-weight: bold; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
/* Add styling for action buttons */ | |
.action-button { | |
display: inline-block; | |
background-color: #3498db; | |
color: white; | |
padding: 0.5rem 1rem; | |
border-radius: 5px; | |
margin: 0.5rem 0; | |
text-decoration: none; | |
} | |
.action-button:hover { | |
background-color: #2980b9; | |
text-decoration: none; | |
} | |
/* Styling for satisfaction survey */ | |
.satisfaction-survey { | |
background-color: #f8f9fa; | |
border: 1px solid #ddd; | |
border-radius: 10px; | |
padding: 1rem; | |
margin-top: 1rem; | |
} | |
.survey-question { | |
margin-bottom: 1rem; | |
} | |
.rating-options { | |
display: flex; | |
justify-content: space-between; | |
margin-bottom: 0.5rem; | |
} | |
.survey-submit { | |
background-color: #1a5276; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
padding: 0.5rem 1rem; | |
cursor: pointer; | |
font-size: 0.9rem; | |
margin-top: 1rem; | |
} | |
.survey-submit:hover { | |
background-color: #2980b9; | |
} | |
""" | |
# Chat interface with simplified UI for Hugging Face | |
with gr.Blocks(css=custom_css) as demo: | |
# Store selected language | |
selected_lang = gr.State(value="ar") | |
# Store user name for personalization | |
user_name = gr.State(value=None) | |
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(elem_classes="chat-container"): | |
chatbot = gr.Chatbot(height=400) | |
# Quick action buttons container | |
with gr.Row(elem_classes="quick-actions", visible=True) as quick_actions_container: | |
balance_btn = gr.Button("تحقق من الرصيد", elem_classes="quick-action-button") | |
lost_card_btn = gr.Button("الإبلاغ عن بطاقة مفقودة", elem_classes="quick-action-button") | |
loan_btn = gr.Button("معلومات القرض", elem_classes="quick-action-button") | |
with gr.Row(elem_classes="quick-actions", visible=True): | |
transfer_btn = gr.Button("تحويل الأموال", elem_classes="quick-action-button") | |
new_account_btn = gr.Button("فتح حساب جديد", elem_classes="quick-action-button") | |
interest_btn = gr.Button("أسعار الفائدة", elem_classes="quick-action-button") | |
with gr.Row(elem_classes="quick-actions", visible=True): | |
branches_btn = gr.Button("مواقع الفروع", elem_classes="quick-action-button") | |
hours_btn = gr.Button("ساعات العمل", elem_classes="quick-action-button") | |
contact_btn = gr.Button("اتصل بنا", elem_classes="quick-action-button") | |
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(scale=1): | |
menu_btn = gr.Button("Show Menu | إظهار القائمة", elem_classes="menu-button") | |
with gr.Column(scale=1): | |
live_agent_btn = gr.Button("Connect to Live Agent | الاتصال بوكيل حي", elem_classes="live-agent-button") | |
with gr.Column(scale=1): | |
survey_btn = gr.Button("Feedback | تقييم الخدمة", elem_classes="menu-button") | |
with gr.Row(elem_classes="footer-section"): | |
gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©") | |
# Update language state and quick action buttons when language is changed | |
def update_language(lang): | |
language_code = "ar" if lang == "العربية" else "en" | |
# Get the appropriate quick actions based on language | |
quick_actions = QUICK_ACTIONS_AR if language_code == "ar" else QUICK_ACTIONS_EN | |
# Update button text based on language | |
return [ | |
language_code, | |
quick_actions[0]["text"], # balance | |
quick_actions[1]["text"], # lost_card | |
quick_actions[2]["text"], # loan | |
quick_actions[3]["text"], # transfer | |
quick_actions[4]["text"], # new_account | |
quick_actions[5]["text"], # interest | |
quick_actions[6]["text"], # branches | |
quick_actions[7]["text"], # working_hours | |
quick_actions[8]["text"] # contact | |
] | |
# Connect language button to update function | |
language_btn.change( | |
fn=update_language, | |
inputs=language_btn, | |
outputs=[ | |
selected_lang, | |
balance_btn, | |
lost_card_btn, | |
loan_btn, | |
transfer_btn, | |
new_account_btn, | |
interest_btn, | |
branches_btn, | |
hours_btn, | |
contact_btn | |
] | |
) | |
# Handle message submission | |
def on_submit(message, chat_history, lang, name): | |
if not message.strip(): | |
return "", chat_history, name | |
# Check if this is a name introduction | |
name_patterns = [ | |
r"my name is (\w+)", | |
r"i am (\w+)", | |
r"i'm (\w+)", | |
r"اسمي (\w+)", | |
r"أنا (\w+)" | |
] | |
for pattern in name_patterns: | |
match = re.search(pattern, message.lower()) | |
if match: | |
name = match.group(1) | |
break | |
# Add user message to chat history | |
chat_history = chat_history + [[message, None]] | |
# Get response | |
responses = respond(message) | |
# Select response based on language | |
response = responses[lang] | |
# Personalize response if name is available | |
if name and CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
if lang == "ar": | |
response = response.replace("مرحبًا", f"مرحبًا {name}") | |
else: | |
response = response.replace("Welcome", f"Welcome {name}") | |
response = response.replace("Hello", f"Hello {name}") | |
# Update bot response in chat history | |
chat_history[-1][1] = response | |
return "", chat_history, name | |
# Handle menu button click | |
def show_menu(chat_history, lang): | |
menu_responses = { | |
"ar": MENU_AR, | |
"en": MENU_EN | |
} | |
# Get menu text | |
menu_text = menu_responses[lang] | |
# Add system message showing the menu | |
chat_history = chat_history + [[None, menu_text.replace("\n", "<br>")]] | |
return chat_history | |
# Handle quick action button clicks | |
def handle_quick_action(intent, chat_history, lang, name): | |
# Get the appropriate quick actions based on language | |
quick_actions = QUICK_ACTIONS_AR if lang == "ar" else QUICK_ACTIONS_EN | |
# Find the button text for this intent | |
button_text = "" | |
for action in quick_actions: | |
if action["intent"] == intent: | |
button_text = action["text"] | |
break | |
# Add button text as user message | |
chat_history = chat_history + [[button_text, None]] | |
# Get the response for this intent | |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
# Use enhanced response if available | |
response_ar = get_enhanced_response(intent, "ar", name) | |
response_en = get_enhanced_response(intent, "en", name) | |
else: | |
# Add a greeting phrase at the beginning | |
greeting_ar = get_random_phrase("greeting", "ar") | |
greeting_en = get_random_phrase("greeting", "en") | |
# Add the main response | |
main_response_ar = ONB_GUIDELINES_AR.get(intent, "") | |
main_response_en = ONB_GUIDELINES_EN.get(intent, "") | |
# Add a follow-up phrase at the end | |
follow_up_ar = get_random_phrase("follow_up", "ar") | |
follow_up_en = get_random_phrase("follow_up", "en") | |
# Combine all parts | |
response_ar = f"{greeting_ar}<br><br>{main_response_ar}<br><br>{follow_up_ar}" | |
response_en = f"{greeting_en}<br><br>{main_response_en}<br><br>{follow_up_en}" | |
responses = { | |
"ar": response_ar, | |
"en": response_en | |
} | |
# Select response based on language | |
response = responses[lang] | |
# Personalize response if name is available | |
if name: | |
if lang == "ar": | |
response = response.replace("مرحبًا", f"مرحبًا {name}") | |
else: | |
response = response.replace("Welcome", f"Welcome {name}") | |
response = response.replace("Hello", f"Hello {name}") | |
# Update bot response in chat history | |
chat_history[-1][1] = response | |
# Log the interaction | |
log_interaction(button_text, response, intent, lang) | |
return chat_history | |
# Handle live agent button click | |
def connect_to_live_agent(chat_history, lang): | |
message = "Connecting to a live customer service agent. Please wait a moment..." if lang == "en" else "جاري الاتصال بوكيل خدمة العملاء. يرجى الانتظار لحظة..." | |
chat_history = chat_history + [[None, message]] | |
return chat_history | |
# Handle satisfaction survey button click | |
def show_satisfaction_survey(chat_history, lang): | |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE: | |
survey_html = offer_satisfaction_survey(lang) | |
chat_history = chat_history + [[None, survey_html]] | |
else: | |
# Simple survey message if enhancements not available | |
title = "استطلاع رضا العملاء" if lang == "ar" else "Customer Satisfaction Survey" | |
message = f"<div class='satisfaction-survey'><h3>{title}</h3><p>{'نشكرك على استخدام المساعد المصرفي الافتراضي!' if lang == 'ar' else 'Thank you for using our virtual banking assistant!'}</p></div>" | |
chat_history = chat_history + [[None, message]] | |
return chat_history | |
# Link inputs and button to response function | |
submit_btn.click( | |
fn=on_submit, | |
inputs=[text_input, chatbot, selected_lang, user_name], | |
outputs=[text_input, chatbot, user_name] | |
) | |
# Link menu button to show menu function | |
menu_btn.click( | |
fn=show_menu, | |
inputs=[chatbot, selected_lang], | |
outputs=[chatbot] | |
) | |
# Link live agent button to connect function | |
live_agent_btn.click( | |
fn=connect_to_live_agent, | |
inputs=[chatbot, selected_lang], | |
outputs=[chatbot] | |
) | |
# Link survey button to show survey function | |
survey_btn.click( | |
fn=show_satisfaction_survey, | |
inputs=[chatbot, selected_lang], | |
outputs=[chatbot] | |
) | |
# Link quick action buttons to handler function | |
balance_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("balance", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
lost_card_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("lost_card", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
loan_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("loan", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
transfer_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("transfer", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
new_account_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("new_account", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
interest_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("interest_rates", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
branches_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("branches", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
hours_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("working_hours", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
contact_btn.click( | |
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("contact", chat, lang, name), | |
inputs=[chatbot, selected_lang, user_name], | |
outputs=[chatbot] | |
) | |
# Also trigger on Enter key | |
text_input.submit( | |
fn=on_submit, | |
inputs=[text_input, chatbot, selected_lang, user_name], | |
outputs=[text_input, chatbot, user_name] | |
) | |
# Initialize the chat with a welcome message | |
def init_chat(): | |
# Welcome message in both languages | |
welcome_ar = "مرحبًا بك في المساعد المصرفي الافتراضي لبنك أم درمان الوطني! يمكنك طرح أي سؤال حول خدماتنا المصرفية أو استخدام أزرار الإجراءات السريعة أدناه." | |
welcome_en = "Welcome to Omdurman National Bank Virtual Banking Assistant! You can ask any question about our banking services or use the quick action buttons below." | |
# Initialize chat with welcome messages | |
chat_history = [] | |
chat_history.append([None, welcome_ar]) | |
chat_history.append([None, welcome_en]) | |
return chat_history | |
# Initialize the chat when the app starts | |
demo.load( | |
fn=init_chat, | |
inputs=[], | |
outputs=[chatbot] | |
) | |
if __name__ == "__main__": | |
demo.launch( | |
server_name="0.0.0.0", | |
server_port=7860, | |
share=True # Enable public link | |
) | |