waleedmohd's picture
Update app.py
edd7ea8 verified
raw
history blame
32.9 kB
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
)