Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -4,15 +4,14 @@ import json
|
|
4 |
import time
|
5 |
from datetime import datetime
|
6 |
|
7 |
-
# Simple language detection function
|
8 |
def simple_detect_language(text):
|
9 |
-
# Check for Arabic characters
|
10 |
arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+')
|
11 |
if arabic_pattern.search(text):
|
12 |
return "ar"
|
13 |
return "en"
|
14 |
|
15 |
-
# Try to import transformers for Arabic NLP
|
16 |
try:
|
17 |
from transformers import pipeline
|
18 |
arabic_nlp = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
|
@@ -41,63 +40,43 @@ try:
|
|
41 |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = True
|
42 |
except ImportError:
|
43 |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = False
|
44 |
-
# Fallback customer service phrases
|
45 |
ENHANCED_CUSTOMER_SERVICE_PHRASES_AR = {
|
46 |
-
"greeting": [
|
47 |
-
|
48 |
-
|
49 |
-
],
|
50 |
-
"thanks": [
|
51 |
-
"شكرًا لتواصلك مع بنك أم درمان الوطني!",
|
52 |
-
"نشكرك على ثقتك في خدماتنا المصرفية."
|
53 |
-
],
|
54 |
-
"follow_up": [
|
55 |
-
"هل هناك خدمة مصرفية أخرى يمكنني مساعدتك بها اليوم؟",
|
56 |
-
"هل لديك أي استفسارات أخرى حول منتجاتنا أو خدماتنا المصرفية؟"
|
57 |
-
]
|
58 |
}
|
59 |
ENHANCED_CUSTOMER_SERVICE_PHRASES_EN = {
|
60 |
-
"greeting": [
|
61 |
-
|
62 |
-
|
63 |
-
],
|
64 |
-
"thanks": [
|
65 |
-
"Thank you for contacting Omdurman National Bank!",
|
66 |
-
"We appreciate your trust in our banking services."
|
67 |
-
],
|
68 |
-
"follow_up": [
|
69 |
-
"Is there any other banking service I can assist you with today?",
|
70 |
-
"Do you have any other questions about our products or banking services?"
|
71 |
-
]
|
72 |
}
|
73 |
|
74 |
-
# Omdurman National Bank-specific guidelines
|
75 |
ONB_GUIDELINES_AR = {
|
76 |
-
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك أم درمان الوطني.
|
77 |
-
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم
|
78 |
-
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.
|
79 |
-
"transfer": "لتحويل الأموال، استخدم
|
80 |
-
"new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.
|
81 |
-
"interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.
|
82 |
-
"branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان.
|
83 |
-
"working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.
|
84 |
-
"contact": "الاتصال بنا على الرقم
|
85 |
}
|
86 |
|
87 |
-
# Omdurman National Bank-specific guidelines in English
|
88 |
ONB_GUIDELINES_EN = {
|
89 |
-
"balance": "You can check your balance online or via the ONB mobile app.
|
90 |
-
"lost_card": "In case of a lost card, call
|
91 |
-
"loan": "Loan requirements include minimum income (5000 SDG) and good credit history.
|
92 |
-
"transfer": "To transfer funds, use the
|
93 |
-
"new_account": "To open a new account, visit your nearest branch with your passport or national ID.
|
94 |
-
"interest_rates": "Interest rates on deposits range from 5% to 10% annually.
|
95 |
-
"branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan.
|
96 |
-
"working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.
|
97 |
-
"contact": "Contact us at
|
98 |
}
|
99 |
|
100 |
-
# Quick action buttons
|
101 |
QUICK_ACTIONS_AR = [
|
102 |
{"text": "تحقق من الرصيد", "intent": "balance"},
|
103 |
{"text": "الإبلاغ عن بطاقة مفقودة", "intent": "lost_card"},
|
@@ -110,7 +89,6 @@ QUICK_ACTIONS_AR = [
|
|
110 |
{"text": "اتصل بنا", "intent": "contact"}
|
111 |
]
|
112 |
|
113 |
-
# Quick action buttons in English
|
114 |
QUICK_ACTIONS_EN = [
|
115 |
{"text": "Check Balance", "intent": "balance"},
|
116 |
{"text": "Report Lost Card", "intent": "lost_card"},
|
@@ -123,47 +101,7 @@ QUICK_ACTIONS_EN = [
|
|
123 |
{"text": "Contact Us", "intent": "contact"}
|
124 |
]
|
125 |
|
126 |
-
#
|
127 |
-
MENU_AR = """
|
128 |
-
قائمة الخدمات المصرفية:
|
129 |
-
1. رصيد - استعلام عن رصيد حسابك
|
130 |
-
2. بطاقة - الإبلاغ عن بطاقة مفقودة
|
131 |
-
3. قرض - معلومات عن القروض
|
132 |
-
4. تحويل - تحويل الأموال
|
133 |
-
5. حساب - فتح حساب جديد
|
134 |
-
6. فائدة - أسعار الفائدة
|
135 |
-
7. فرع - م��اقع الفروع
|
136 |
-
8. ساعات - ساعات العمل
|
137 |
-
9. اتصال - معلومات الاتصال
|
138 |
-
"""
|
139 |
-
|
140 |
-
MENU_EN = """
|
141 |
-
Banking Services Menu:
|
142 |
-
1. balance - Check your account balance
|
143 |
-
2. card - Report a lost card
|
144 |
-
3. loan - Information about loans
|
145 |
-
4. transfer - Transfer funds
|
146 |
-
5. account - Open a new account
|
147 |
-
6. interest - Interest rates
|
148 |
-
7. branch - Branch locations
|
149 |
-
8. hours - Working hours
|
150 |
-
9. contact - Contact information
|
151 |
-
"""
|
152 |
-
|
153 |
-
# Map intents to keywords (enhanced)
|
154 |
-
INTENT_KEYWORDS = {
|
155 |
-
"balance": ["balance", "check balance", "account balance", "how much", "رصيد", "حساب", "كم المبلغ", "1"],
|
156 |
-
"lost_card": ["lost", "card", "stolen", "missing", "فقدت", "بطاقة", "مسروقة", "ضائعة", "2"],
|
157 |
-
"loan": ["loan", "borrow", "borrowing", "credit", "قرض", "استدانة", "إئتمان", "3"],
|
158 |
-
"transfer": ["transfer", "send money", "payment", "تحويل", "ارسال", "دفع", "4"],
|
159 |
-
"new_account": ["account", "open", "create", "new", "حساب", "فتح", "جديد", "إنشاء", "5"],
|
160 |
-
"interest_rates": ["interest", "rate", "rates", "return", "فائدة", "نسبة", "عائد", "6"],
|
161 |
-
"branches": ["branch", "location", "where", "office", "فرع", "موقع", "أين", "مكتب", "7"],
|
162 |
-
"working_hours": ["hours", "time", "open", "close", "ساعات", "وقت", "مفتوح", "مغلق", "8"],
|
163 |
-
"contact": ["contact", "phone", "email", "call", "اتصال", "هاتف", "بريد", "اتصل", "9"]
|
164 |
-
}
|
165 |
-
|
166 |
-
# Function to get a random phrase from the customer service phrases
|
167 |
def get_random_phrase(category, language):
|
168 |
import random
|
169 |
if language == "ar":
|
@@ -172,7 +110,6 @@ def get_random_phrase(category, language):
|
|
172 |
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_EN[category])
|
173 |
|
174 |
def classify_intent(message: str):
|
175 |
-
# Check for menu request
|
176 |
menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"]
|
177 |
message_lower = message.lower()
|
178 |
|
@@ -180,7 +117,6 @@ def classify_intent(message: str):
|
|
180 |
if keyword in message_lower:
|
181 |
return "menu"
|
182 |
|
183 |
-
# Use keyword matching for intent classification
|
184 |
for intent_key, keywords in INTENT_KEYWORDS.items():
|
185 |
for keyword in keywords:
|
186 |
if keyword.lower() in message_lower:
|
@@ -205,6 +141,7 @@ def log_interaction(user_message, bot_response, intent, language):
|
|
205 |
except Exception as e:
|
206 |
print(f"Error logging interaction: {e}")
|
207 |
|
|
|
208 |
def respond(message: str):
|
209 |
if not message.strip():
|
210 |
return {
|
@@ -212,604 +149,111 @@ def respond(message: str):
|
|
212 |
"en": "Please type your question."
|
213 |
}
|
214 |
|
215 |
-
# Detect language
|
216 |
if ARABIC_NLP_AVAILABLE:
|
217 |
language = detect_language_with_nlp(message)
|
218 |
-
# If the language is neither Arabic nor English, default to English
|
219 |
if language != "ar" and language != "en":
|
220 |
language = "en"
|
221 |
else:
|
222 |
language = simple_detect_language(message)
|
223 |
|
224 |
-
# Classify
|
225 |
intent = classify_intent(message)
|
226 |
|
227 |
-
# Prepare responses
|
228 |
responses = {
|
229 |
"ar": "",
|
230 |
"en": ""
|
231 |
}
|
232 |
|
233 |
-
#
|
234 |
if intent == "menu":
|
235 |
responses["ar"] = MENU_AR
|
236 |
responses["en"] = MENU_EN
|
237 |
log_interaction(message, responses[language], "menu", language)
|
238 |
return responses
|
239 |
|
240 |
-
#
|
241 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
242 |
faq_answer = handle_banking_faq(message, language)
|
243 |
if faq_answer:
|
244 |
-
|
245 |
-
|
246 |
-
greeting_en = get_random_phrase("greeting", "en")
|
247 |
-
|
248 |
-
# Add a follow-up phrase at the end
|
249 |
-
follow_up_ar = get_random_phrase("follow_up", "ar")
|
250 |
-
follow_up_en = get_random_phrase("follow_up", "en")
|
251 |
-
|
252 |
-
# Combine all parts
|
253 |
-
responses["ar"] = f"{greeting_ar}<br><br>{faq_answer}<br><br>{follow_up_ar}"
|
254 |
-
responses["en"] = f"{greeting_en}<br><br>{faq_answer}<br><br>{follow_up_en}"
|
255 |
-
|
256 |
log_interaction(message, responses[language], "faq", language)
|
257 |
return responses
|
258 |
|
259 |
-
#
|
260 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
261 |
term_definition = get_banking_term_definition(message, language)
|
262 |
if term_definition:
|
263 |
-
|
264 |
-
|
265 |
-
greeting_en = get_random_phrase("greeting", "en")
|
266 |
-
|
267 |
-
# Add a follow-up phrase at the end
|
268 |
-
follow_up_ar = get_random_phrase("follow_up", "ar")
|
269 |
-
follow_up_en = get_random_phrase("follow_up", "en")
|
270 |
-
|
271 |
-
# Combine all parts
|
272 |
-
responses["ar"] = f"{greeting_ar}<br><br>{term_definition}<br><br>{follow_up_ar}"
|
273 |
-
responses["en"] = f"{greeting_en}<br><br>{term_definition}<br><br>{follow_up_en}"
|
274 |
-
|
275 |
log_interaction(message, responses[language], "term", language)
|
276 |
return responses
|
277 |
|
278 |
-
#
|
279 |
if intent != "unknown":
|
280 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
281 |
-
# Use enhanced response if available
|
282 |
responses["ar"] = get_enhanced_response(intent, "ar")
|
283 |
responses["en"] = get_enhanced_response(intent, "en")
|
284 |
else:
|
285 |
-
|
286 |
-
|
287 |
-
greeting_en = get_random_phrase("greeting", "en")
|
288 |
-
|
289 |
-
# Add the main response
|
290 |
-
main_response_ar = ONB_GUIDELINES_AR.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.")
|
291 |
-
main_response_en = ONB_GUIDELINES_EN.get(intent, "Sorry, the selected option was not recognized.")
|
292 |
-
|
293 |
-
# Add a follow-up phrase at the end
|
294 |
-
follow_up_ar = get_random_phrase("follow_up", "ar")
|
295 |
-
follow_up_en = get_random_phrase("follow_up", "en")
|
296 |
-
|
297 |
-
# Combine all parts
|
298 |
-
responses["ar"] = f"{greeting_ar}<br><br>{main_response_ar}<br><br>{follow_up_ar}"
|
299 |
-
responses["en"] = f"{greeting_en}<br><br>{main_response_en}<br><br>{follow_up_en}"
|
300 |
else:
|
301 |
-
# Default response if no intent is matched - show menu
|
302 |
responses["ar"] = "عذرًا، لم أفهم سؤالك. إليك قائمة بالخدمات المتاحة:" + MENU_AR
|
303 |
responses["en"] = "Sorry, I didn't understand your question. Here's a menu of available services:" + MENU_EN
|
304 |
|
305 |
-
# Log the interaction
|
306 |
log_interaction(message, responses[language], intent, language)
|
307 |
-
|
308 |
return responses
|
309 |
|
310 |
-
#
|
311 |
-
|
312 |
-
.gradio-container {
|
313 |
-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
314 |
-
}
|
315 |
-
|
316 |
-
.chat-message {
|
317 |
-
padding: 1rem;
|
318 |
-
border-radius: 10px;
|
319 |
-
margin-bottom: 1rem;
|
320 |
-
max-width: 80%;
|
321 |
-
}
|
322 |
-
|
323 |
-
.user-message {
|
324 |
-
background-color: #e6f7ff;
|
325 |
-
margin-left: auto;
|
326 |
-
text-align: right;
|
327 |
-
}
|
328 |
-
|
329 |
-
.bot-message {
|
330 |
-
background-color: #f0f0f0;
|
331 |
-
margin-right: auto;
|
332 |
-
text-align: left;
|
333 |
-
}
|
334 |
-
|
335 |
-
.bot-message-ar {
|
336 |
-
background-color: #f0f0f0;
|
337 |
-
margin-left: auto;
|
338 |
-
text-align: right;
|
339 |
-
}
|
340 |
-
|
341 |
-
.header-section {
|
342 |
-
background-color: #1a5276;
|
343 |
-
color: white;
|
344 |
-
padding: 1rem;
|
345 |
-
border-radius: 10px;
|
346 |
-
margin-bottom: 1rem;
|
347 |
-
text-align: center;
|
348 |
-
}
|
349 |
-
|
350 |
-
.footer-section {
|
351 |
-
font-size: 0.8rem;
|
352 |
-
text-align: center;
|
353 |
-
margin-top: 2rem;
|
354 |
-
color: #666;
|
355 |
-
}
|
356 |
-
|
357 |
-
.lang-selector {
|
358 |
-
text-align: right;
|
359 |
-
margin-bottom: 1rem;
|
360 |
-
}
|
361 |
-
|
362 |
-
.menu-button {
|
363 |
-
margin-top: 0.5rem;
|
364 |
-
}
|
365 |
-
|
366 |
-
.quick-actions {
|
367 |
-
display: flex;
|
368 |
-
flex-wrap: wrap;
|
369 |
-
gap: 0.5rem;
|
370 |
-
margin: 1rem 0;
|
371 |
-
}
|
372 |
-
|
373 |
-
.quick-action-button {
|
374 |
-
background-color: #1a5276;
|
375 |
-
color: white;
|
376 |
-
border: none;
|
377 |
-
border-radius: 20px;
|
378 |
-
padding: 0.5rem 1rem;
|
379 |
-
cursor: pointer;
|
380 |
-
font-size: 0.9rem;
|
381 |
-
transition: background-color 0.3s;
|
382 |
-
}
|
383 |
-
|
384 |
-
.quick-action-button:hover {
|
385 |
-
background-color: #2980b9;
|
386 |
-
}
|
387 |
-
|
388 |
-
.chat-container {
|
389 |
-
border: 1px solid #ddd;
|
390 |
-
border-radius: 10px;
|
391 |
-
padding: 1rem;
|
392 |
-
background-color: #f9f9f9;
|
393 |
-
}
|
394 |
-
|
395 |
-
.live-agent-button {
|
396 |
-
background-color: #27ae60;
|
397 |
-
color: white;
|
398 |
-
border: none;
|
399 |
-
border-radius: 5px;
|
400 |
-
padding: 0.5rem 1rem;
|
401 |
-
cursor: pointer;
|
402 |
-
font-size: 0.9rem;
|
403 |
-
margin-top: 1rem;
|
404 |
-
transition: background-color 0.3s;
|
405 |
-
}
|
406 |
-
|
407 |
-
.live-agent-button:hover {
|
408 |
-
background-color: #2ecc71;
|
409 |
-
}
|
410 |
-
|
411 |
-
/* Add custom styling for links */
|
412 |
-
a {
|
413 |
-
color: #2980b9;
|
414 |
-
text-decoration: none;
|
415 |
-
font-weight: bold;
|
416 |
-
}
|
417 |
-
|
418 |
-
a:hover {
|
419 |
-
text-decoration: underline;
|
420 |
-
}
|
421 |
-
|
422 |
-
/* Add styling for action buttons */
|
423 |
-
.action-button {
|
424 |
-
display: inline-block;
|
425 |
-
background-color: #3498db;
|
426 |
-
color: white;
|
427 |
-
padding: 0.5rem 1rem;
|
428 |
-
border-radius: 5px;
|
429 |
-
margin: 0.5rem 0;
|
430 |
-
text-decoration: none;
|
431 |
-
}
|
432 |
-
|
433 |
-
.action-button:hover {
|
434 |
-
background-color: #2980b9;
|
435 |
-
text-decoration: none;
|
436 |
-
}
|
437 |
-
|
438 |
-
/* Styling for satisfaction survey */
|
439 |
-
.satisfaction-survey {
|
440 |
-
background-color: #f8f9fa;
|
441 |
-
border: 1px solid #ddd;
|
442 |
-
border-radius: 10px;
|
443 |
-
padding: 1rem;
|
444 |
-
margin-top: 1rem;
|
445 |
-
}
|
446 |
-
|
447 |
-
.survey-question {
|
448 |
-
margin-bottom: 1rem;
|
449 |
-
}
|
450 |
-
|
451 |
-
.rating-options {
|
452 |
-
display: flex;
|
453 |
-
justify-content: space-between;
|
454 |
-
margin-bottom: 0.5rem;
|
455 |
-
}
|
456 |
-
|
457 |
-
.survey-submit {
|
458 |
-
background-color: #1a5276;
|
459 |
-
color: white;
|
460 |
-
border: none;
|
461 |
-
border-radius: 5px;
|
462 |
-
padding: 0.5rem 1rem;
|
463 |
-
cursor: pointer;
|
464 |
-
font-size: 0.9rem;
|
465 |
-
margin-top: 1rem;
|
466 |
-
}
|
467 |
-
|
468 |
-
.survey-submit:hover {
|
469 |
-
background-color: #2980b9;
|
470 |
-
}
|
471 |
-
"""
|
472 |
-
|
473 |
-
# Chat interface with simplified UI for Hugging Face
|
474 |
-
with gr.Blocks(css=custom_css) as demo:
|
475 |
-
# Store selected language
|
476 |
selected_lang = gr.State(value="ar")
|
477 |
-
# Store user name for personalization
|
478 |
user_name = gr.State(value=None)
|
479 |
|
480 |
-
with gr.Row(elem_classes="header-section"):
|
481 |
-
with gr.Column():
|
482 |
-
gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني")
|
483 |
-
gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي الافتراضي")
|
484 |
-
|
485 |
with gr.Row():
|
486 |
-
|
487 |
-
language_btn = gr.Radio(
|
488 |
-
["العربية", "English"],
|
489 |
-
value="العربية",
|
490 |
-
label="Language | اللغة"
|
491 |
-
)
|
492 |
-
|
493 |
-
with gr.Row(elem_classes="chat-container"):
|
494 |
-
chatbot = gr.Chatbot(height=400)
|
495 |
|
496 |
-
|
497 |
-
|
498 |
-
balance_btn = gr.Button("تحقق من الرصيد", elem_classes="quick-action-button")
|
499 |
-
lost_card_btn = gr.Button("الإبلاغ عن بطاقة مفقودة", elem_classes="quick-action-button")
|
500 |
-
loan_btn = gr.Button("معلومات القرض", elem_classes="quick-action-button")
|
501 |
-
|
502 |
-
with gr.Row(elem_classes="quick-actions", visible=True):
|
503 |
-
transfer_btn = gr.Button("تحويل الأموال", elem_classes="quick-action-button")
|
504 |
-
new_account_btn = gr.Button("فتح حساب جديد", elem_classes="quick-action-button")
|
505 |
-
interest_btn = gr.Button("أسعار الفائدة", elem_classes="quick-action-button")
|
506 |
|
507 |
-
|
508 |
-
branches_btn = gr.Button("مواقع الفروع", elem_classes="quick-action-button")
|
509 |
-
hours_btn = gr.Button("ساعات العمل", elem_classes="quick-action-button")
|
510 |
-
contact_btn = gr.Button("اتصل بنا", elem_classes="quick-action-button")
|
511 |
|
512 |
with gr.Row():
|
513 |
-
|
514 |
-
|
515 |
-
placeholder="Type your question here | اكتب سؤالك هنا",
|
516 |
-
label="",
|
517 |
-
elem_id="chat-input"
|
518 |
-
)
|
519 |
-
with gr.Column(scale=1):
|
520 |
-
submit_btn = gr.Button("Send | إرسال", variant="primary")
|
521 |
|
522 |
with gr.Row():
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
live_agent_btn = gr.Button("Connect to Live Agent | الاتصال بوكيل حي", elem_classes="live-agent-button")
|
527 |
-
with gr.Column(scale=1):
|
528 |
-
survey_btn = gr.Button("Feedback | تقييم الخدمة", elem_classes="menu-button")
|
529 |
-
|
530 |
-
with gr.Row(elem_classes="footer-section"):
|
531 |
-
gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©")
|
532 |
-
|
533 |
-
# Update language state and quick action buttons when language is changed
|
534 |
-
def update_language(lang):
|
535 |
-
language_code = "ar" if lang == "العربية" else "en"
|
536 |
-
|
537 |
-
# Get the appropriate quick actions based on language
|
538 |
-
quick_actions = QUICK_ACTIONS_AR if language_code == "ar" else QUICK_ACTIONS_EN
|
539 |
-
|
540 |
-
# Update button text based on language
|
541 |
-
return [
|
542 |
-
language_code,
|
543 |
-
quick_actions[0]["text"], # balance
|
544 |
-
quick_actions[1]["text"], # lost_card
|
545 |
-
quick_actions[2]["text"], # loan
|
546 |
-
quick_actions[3]["text"], # transfer
|
547 |
-
quick_actions[4]["text"], # new_account
|
548 |
-
quick_actions[5]["text"], # interest
|
549 |
-
quick_actions[6]["text"], # branches
|
550 |
-
quick_actions[7]["text"], # working_hours
|
551 |
-
quick_actions[8]["text"] # contact
|
552 |
-
]
|
553 |
-
|
554 |
-
# Connect language button to update function
|
555 |
-
language_btn.change(
|
556 |
-
fn=update_language,
|
557 |
-
inputs=language_btn,
|
558 |
-
outputs=[
|
559 |
-
selected_lang,
|
560 |
-
balance_btn,
|
561 |
-
lost_card_btn,
|
562 |
-
loan_btn,
|
563 |
-
transfer_btn,
|
564 |
-
new_account_btn,
|
565 |
-
interest_btn,
|
566 |
-
branches_btn,
|
567 |
-
hours_btn,
|
568 |
-
contact_btn
|
569 |
-
]
|
570 |
-
)
|
571 |
-
|
572 |
-
# Handle message submission
|
573 |
-
def on_submit(message, chat_history, lang, name):
|
574 |
-
if not message.strip():
|
575 |
-
return "", chat_history, name
|
576 |
-
|
577 |
-
# Check if this is a name introduction
|
578 |
-
name_patterns = [
|
579 |
-
r"my name is (\w+)",
|
580 |
-
r"i am (\w+)",
|
581 |
-
r"i'm (\w+)",
|
582 |
-
r"اسمي (\w+)",
|
583 |
-
r"أنا (\w+)"
|
584 |
-
]
|
585 |
-
|
586 |
-
for pattern in name_patterns:
|
587 |
-
match = re.search(pattern, message.lower())
|
588 |
-
if match:
|
589 |
-
name = match.group(1)
|
590 |
-
break
|
591 |
-
|
592 |
-
# Add user message to chat history
|
593 |
-
chat_history = chat_history + [[message, None]]
|
594 |
-
|
595 |
-
# Get response
|
596 |
-
responses = respond(message)
|
597 |
-
|
598 |
-
# Select response based on language
|
599 |
-
response = responses[lang]
|
600 |
-
|
601 |
-
# Personalize response if name is available
|
602 |
-
if name and CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
603 |
-
if lang == "ar":
|
604 |
-
response = response.replace("مرحبًا", f"مرحبًا {name}")
|
605 |
-
else:
|
606 |
-
response = response.replace("Welcome", f"Welcome {name}")
|
607 |
-
response = response.replace("Hello", f"Hello {name}")
|
608 |
-
|
609 |
-
# Update bot response in chat history
|
610 |
-
chat_history[-1][1] = response
|
611 |
-
|
612 |
-
return "", chat_history, name
|
613 |
-
|
614 |
-
# Handle menu button click
|
615 |
-
def show_menu(chat_history, lang):
|
616 |
-
menu_responses = {
|
617 |
-
"ar": MENU_AR,
|
618 |
-
"en": MENU_EN
|
619 |
-
}
|
620 |
-
|
621 |
-
# Get menu text
|
622 |
-
menu_text = menu_responses[lang]
|
623 |
-
|
624 |
-
# Add system message showing the menu
|
625 |
-
chat_history = chat_history + [[None, menu_text.replace("\n", "<br>")]]
|
626 |
-
|
627 |
-
return chat_history
|
628 |
|
629 |
-
#
|
630 |
-
def handle_quick_action(intent, chat_history, lang, name):
|
631 |
-
# Get the appropriate quick actions based on language
|
632 |
-
quick_actions = QUICK_ACTIONS_AR if lang == "ar" else QUICK_ACTIONS_EN
|
633 |
-
|
634 |
-
# Find the button text for this intent
|
635 |
-
button_text = ""
|
636 |
-
for action in quick_actions:
|
637 |
-
if action["intent"] == intent:
|
638 |
-
button_text = action["text"]
|
639 |
-
break
|
640 |
-
|
641 |
-
# Add button text as user message
|
642 |
-
chat_history = chat_history + [[button_text, None]]
|
643 |
-
|
644 |
-
# Get the response for this intent
|
645 |
-
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
646 |
-
# Use enhanced response if available
|
647 |
-
response_ar = get_enhanced_response(intent, "ar", name)
|
648 |
-
response_en = get_enhanced_response(intent, "en", name)
|
649 |
-
else:
|
650 |
-
# Add a greeting phrase at the beginning
|
651 |
-
greeting_ar = get_random_phrase("greeting", "ar")
|
652 |
-
greeting_en = get_random_phrase("greeting", "en")
|
653 |
-
|
654 |
-
# Add the main response
|
655 |
-
main_response_ar = ONB_GUIDELINES_AR.get(intent, "")
|
656 |
-
main_response_en = ONB_GUIDELINES_EN.get(intent, "")
|
657 |
-
|
658 |
-
# Add a follow-up phrase at the end
|
659 |
-
follow_up_ar = get_random_phrase("follow_up", "ar")
|
660 |
-
follow_up_en = get_random_phrase("follow_up", "en")
|
661 |
-
|
662 |
-
# Combine all parts
|
663 |
-
response_ar = f"{greeting_ar}<br><br>{main_response_ar}<br><br>{follow_up_ar}"
|
664 |
-
response_en = f"{greeting_en}<br><br>{main_response_en}<br><br>{follow_up_en}"
|
665 |
-
|
666 |
-
responses = {
|
667 |
-
"ar": response_ar,
|
668 |
-
"en": response_en
|
669 |
-
}
|
670 |
-
|
671 |
-
# Select response based on language
|
672 |
-
response = responses[lang]
|
673 |
-
|
674 |
-
# Personalize response if name is available
|
675 |
-
if name:
|
676 |
-
if lang == "ar":
|
677 |
-
response = response.replace("مرحبًا", f"مرحبًا {name}")
|
678 |
-
else:
|
679 |
-
response = response.replace("Welcome", f"Welcome {name}")
|
680 |
-
response = response.replace("Hello", f"Hello {name}")
|
681 |
-
|
682 |
-
# Update bot response in chat history
|
683 |
-
chat_history[-1][1] = response
|
684 |
-
|
685 |
-
# Log the interaction
|
686 |
-
log_interaction(button_text, response, intent, lang)
|
687 |
-
|
688 |
-
return chat_history
|
689 |
-
|
690 |
-
# Handle live agent button click
|
691 |
-
def connect_to_live_agent(chat_history, lang):
|
692 |
-
message = "Connecting to a live customer service agent. Please wait a moment..." if lang == "en" else "جاري الاتصال بوكيل خدمة العملاء. يرجى الانتظار لحظة..."
|
693 |
-
chat_history = chat_history + [[None, message]]
|
694 |
-
return chat_history
|
695 |
-
|
696 |
-
# Handle satisfaction survey button click
|
697 |
-
def show_satisfaction_survey(chat_history, lang):
|
698 |
-
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
699 |
-
survey_html = offer_satisfaction_survey(lang)
|
700 |
-
chat_history = chat_history + [[None, survey_html]]
|
701 |
-
else:
|
702 |
-
# Simple survey message if enhancements not available
|
703 |
-
title = "استطلاع رضا العملاء" if lang == "ar" else "Customer Satisfaction Survey"
|
704 |
-
message = f"<div class='satisfaction-survey'><h3>{title}</h3><p>{'نشكرك على استخدام المساعد المصرفي الافتراضي!' if lang == 'ar' else 'Thank you for using our virtual banking assistant!'}</p></div>"
|
705 |
-
chat_history = chat_history + [[None, message]]
|
706 |
-
|
707 |
-
return chat_history
|
708 |
-
|
709 |
-
# Link inputs and button to response function
|
710 |
submit_btn.click(
|
711 |
fn=on_submit,
|
712 |
inputs=[text_input, chatbot, selected_lang, user_name],
|
713 |
outputs=[text_input, chatbot, user_name]
|
714 |
)
|
715 |
|
716 |
-
# Link menu button to show menu function
|
717 |
menu_btn.click(
|
718 |
fn=show_menu,
|
719 |
inputs=[chatbot, selected_lang],
|
720 |
outputs=[chatbot]
|
721 |
)
|
722 |
|
723 |
-
# Link live agent button to connect function
|
724 |
live_agent_btn.click(
|
725 |
fn=connect_to_live_agent,
|
726 |
inputs=[chatbot, selected_lang],
|
727 |
outputs=[chatbot]
|
728 |
)
|
729 |
|
730 |
-
# Link survey button to show survey function
|
731 |
survey_btn.click(
|
732 |
fn=show_satisfaction_survey,
|
733 |
inputs=[chatbot, selected_lang],
|
734 |
outputs=[chatbot]
|
735 |
)
|
736 |
|
737 |
-
#
|
738 |
-
balance_btn.click(
|
739 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("balance", chat, lang, name),
|
740 |
-
inputs=[chatbot, selected_lang, user_name],
|
741 |
-
outputs=[chatbot]
|
742 |
-
)
|
743 |
-
|
744 |
-
lost_card_btn.click(
|
745 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("lost_card", chat, lang, name),
|
746 |
-
inputs=[chatbot, selected_lang, user_name],
|
747 |
-
outputs=[chatbot]
|
748 |
-
)
|
749 |
-
|
750 |
-
loan_btn.click(
|
751 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("loan", chat, lang, name),
|
752 |
-
inputs=[chatbot, selected_lang, user_name],
|
753 |
-
outputs=[chatbot]
|
754 |
-
)
|
755 |
-
|
756 |
-
transfer_btn.click(
|
757 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("transfer", chat, lang, name),
|
758 |
-
inputs=[chatbot, selected_lang, user_name],
|
759 |
-
outputs=[chatbot]
|
760 |
-
)
|
761 |
-
|
762 |
-
new_account_btn.click(
|
763 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("new_account", chat, lang, name),
|
764 |
-
inputs=[chatbot, selected_lang, user_name],
|
765 |
-
outputs=[chatbot]
|
766 |
-
)
|
767 |
-
|
768 |
-
interest_btn.click(
|
769 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("interest_rates", chat, lang, name),
|
770 |
-
inputs=[chatbot, selected_lang, user_name],
|
771 |
-
outputs=[chatbot]
|
772 |
-
)
|
773 |
-
|
774 |
-
branches_btn.click(
|
775 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("branches", chat, lang, name),
|
776 |
-
inputs=[chatbot, selected_lang, user_name],
|
777 |
-
outputs=[chatbot]
|
778 |
-
)
|
779 |
-
|
780 |
-
hours_btn.click(
|
781 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("working_hours", chat, lang, name),
|
782 |
-
inputs=[chatbot, selected_lang, user_name],
|
783 |
-
outputs=[chatbot]
|
784 |
-
)
|
785 |
-
|
786 |
-
contact_btn.click(
|
787 |
-
fn=lambda chat=chatbot, lang=selected_lang, name=user_name: handle_quick_action("contact", chat, lang, name),
|
788 |
-
inputs=[chatbot, selected_lang, user_name],
|
789 |
-
outputs=[chatbot]
|
790 |
-
)
|
791 |
-
|
792 |
-
# Also trigger on Enter key
|
793 |
-
text_input.submit(
|
794 |
-
fn=on_submit,
|
795 |
-
inputs=[text_input, chatbot, selected_lang, user_name],
|
796 |
-
outputs=[text_input, chatbot, user_name]
|
797 |
-
)
|
798 |
-
|
799 |
-
# Initialize the chat with a welcome message
|
800 |
-
def init_chat():
|
801 |
-
# Welcome message in both languages
|
802 |
-
welcome_ar = "مرحبًا بك في المساعد المصرفي الافتراضي لبنك أم درمان الوطني! يمكنك طرح أي سؤال حول خدماتنا المصرفية أو استخدام أزرار الإجراءات السريعة أدناه."
|
803 |
-
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."
|
804 |
-
|
805 |
-
# Initialize chat with welcome messages
|
806 |
-
chat_history = []
|
807 |
-
chat_history.append([None, welcome_ar])
|
808 |
-
chat_history.append([None, welcome_en])
|
809 |
-
|
810 |
-
return chat_history
|
811 |
-
|
812 |
-
# Initialize the chat when the app starts
|
813 |
demo.load(
|
814 |
fn=init_chat,
|
815 |
inputs=[],
|
@@ -817,8 +261,4 @@ with gr.Blocks(css=custom_css) as demo:
|
|
817 |
)
|
818 |
|
819 |
if __name__ == "__main__":
|
820 |
-
demo.launch(
|
821 |
-
server_name="0.0.0.0",
|
822 |
-
server_port=7860,
|
823 |
-
share=True # Enable public link
|
824 |
-
)
|
|
|
4 |
import time
|
5 |
from datetime import datetime
|
6 |
|
7 |
+
# Simple language detection function
|
8 |
def simple_detect_language(text):
|
|
|
9 |
arabic_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+')
|
10 |
if arabic_pattern.search(text):
|
11 |
return "ar"
|
12 |
return "en"
|
13 |
|
14 |
+
# Try to import transformers for Arabic NLP
|
15 |
try:
|
16 |
from transformers import pipeline
|
17 |
arabic_nlp = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
|
|
|
40 |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = True
|
41 |
except ImportError:
|
42 |
CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE = False
|
|
|
43 |
ENHANCED_CUSTOMER_SERVICE_PHRASES_AR = {
|
44 |
+
"greeting": ["مرحبًا بك في بنك أم درمان الوطني! كيف يمكنني مساعدتك اليوم؟"],
|
45 |
+
"thanks": ["شكرًا لتواصلك مع بنك أم درمان الوطني!"],
|
46 |
+
"follow_up": ["هل هناك خدمة أخرى يمكنني مساعدتك بها؟"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
}
|
48 |
ENHANCED_CUSTOMER_SERVICE_PHRASES_EN = {
|
49 |
+
"greeting": ["Welcome to Omdurman National Bank! How may I assist you today?"],
|
50 |
+
"thanks": ["Thank you for contacting Omdurman National Bank!"],
|
51 |
+
"follow_up": ["Is there anything else I can help you with?"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
|
54 |
+
# Omdurman National Bank-specific guidelines
|
55 |
ONB_GUIDELINES_AR = {
|
56 |
+
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك أم درمان الوطني.",
|
57 |
+
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
|
58 |
+
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
|
59 |
+
"transfer": "لتحويل الأموال، استخدم تطبيق الهاتف أو الخدمة المصرفية عبر الإنترنت.",
|
60 |
+
"new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.",
|
61 |
+
"interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.",
|
62 |
+
"branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان.",
|
63 |
+
"working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.",
|
64 |
+
"contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
|
65 |
}
|
66 |
|
|
|
67 |
ONB_GUIDELINES_EN = {
|
68 |
+
"balance": "You can check your balance online or via the ONB mobile app.",
|
69 |
+
"lost_card": "In case of a lost card, call 249-123-456-789 immediately.",
|
70 |
+
"loan": "Loan requirements include minimum income (5000 SDG) and good credit history.",
|
71 |
+
"transfer": "To transfer funds, use the mobile app or online banking service.",
|
72 |
+
"new_account": "To open a new account, visit your nearest branch with your passport or national ID.",
|
73 |
+
"interest_rates": "Interest rates on deposits range from 5% to 10% annually.",
|
74 |
+
"branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan.",
|
75 |
+
"working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.",
|
76 |
+
"contact": "Contact us at 249-123-456-789 or via email at [email protected]."
|
77 |
}
|
78 |
|
79 |
+
# Quick action buttons
|
80 |
QUICK_ACTIONS_AR = [
|
81 |
{"text": "تحقق من الرصيد", "intent": "balance"},
|
82 |
{"text": "الإبلاغ عن بطاقة مفقودة", "intent": "lost_card"},
|
|
|
89 |
{"text": "اتصل بنا", "intent": "contact"}
|
90 |
]
|
91 |
|
|
|
92 |
QUICK_ACTIONS_EN = [
|
93 |
{"text": "Check Balance", "intent": "balance"},
|
94 |
{"text": "Report Lost Card", "intent": "lost_card"},
|
|
|
101 |
{"text": "Contact Us", "intent": "contact"}
|
102 |
]
|
103 |
|
104 |
+
# Function to get a random phrase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
def get_random_phrase(category, language):
|
106 |
import random
|
107 |
if language == "ar":
|
|
|
110 |
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_EN[category])
|
111 |
|
112 |
def classify_intent(message: str):
|
|
|
113 |
menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"]
|
114 |
message_lower = message.lower()
|
115 |
|
|
|
117 |
if keyword in message_lower:
|
118 |
return "menu"
|
119 |
|
|
|
120 |
for intent_key, keywords in INTENT_KEYWORDS.items():
|
121 |
for keyword in keywords:
|
122 |
if keyword.lower() in message_lower:
|
|
|
141 |
except Exception as e:
|
142 |
print(f"Error logging interaction: {e}")
|
143 |
|
144 |
+
# Function to generate responses
|
145 |
def respond(message: str):
|
146 |
if not message.strip():
|
147 |
return {
|
|
|
149 |
"en": "Please type your question."
|
150 |
}
|
151 |
|
152 |
+
# Detect language
|
153 |
if ARABIC_NLP_AVAILABLE:
|
154 |
language = detect_language_with_nlp(message)
|
|
|
155 |
if language != "ar" and language != "en":
|
156 |
language = "en"
|
157 |
else:
|
158 |
language = simple_detect_language(message)
|
159 |
|
160 |
+
# Classify intent
|
161 |
intent = classify_intent(message)
|
162 |
|
163 |
+
# Prepare responses
|
164 |
responses = {
|
165 |
"ar": "",
|
166 |
"en": ""
|
167 |
}
|
168 |
|
169 |
+
# Handle menu request
|
170 |
if intent == "menu":
|
171 |
responses["ar"] = MENU_AR
|
172 |
responses["en"] = MENU_EN
|
173 |
log_interaction(message, responses[language], "menu", language)
|
174 |
return responses
|
175 |
|
176 |
+
# Handle banking FAQ
|
177 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
178 |
faq_answer = handle_banking_faq(message, language)
|
179 |
if faq_answer:
|
180 |
+
responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{faq_answer}<br><br>{get_random_phrase('follow_up', 'ar')}"
|
181 |
+
responses["en"] = f"{get_random_phrase('greeting', 'en')}<br><br>{faq_answer}<br><br>{get_random_phrase('follow_up', 'en')}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
log_interaction(message, responses[language], "faq", language)
|
183 |
return responses
|
184 |
|
185 |
+
# Handle banking term definition
|
186 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
187 |
term_definition = get_banking_term_definition(message, language)
|
188 |
if term_definition:
|
189 |
+
responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{term_definition}<br><br>{get_random_phrase('follow_up', 'ar')}"
|
190 |
+
responses["en"] = f"{get_random_phrase('greeting', 'en')}<br><br>{term_definition}<br><br>{get_random_phrase('follow_up', 'en')}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
log_interaction(message, responses[language], "term", language)
|
192 |
return responses
|
193 |
|
194 |
+
# Handle recognized intents
|
195 |
if intent != "unknown":
|
196 |
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
|
|
197 |
responses["ar"] = get_enhanced_response(intent, "ar")
|
198 |
responses["en"] = get_enhanced_response(intent, "en")
|
199 |
else:
|
200 |
+
responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{ONB_GUIDELINES_AR.get(intent, 'عذرًا، لم يتم التعرف على الخيار المحدد.')}<br><br>{get_random_phrase('follow_up', 'ar')}"
|
201 |
+
responses["en"] = f"{get_random_phrase('greeting', 'en')}<br><br>{ONB_GUIDELINES_EN.get(intent, 'Sorry, the selected option was not recognized.')}<br><br>{get_random_phrase('follow_up', 'en')}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
else:
|
|
|
203 |
responses["ar"] = "عذرًا، لم أفهم سؤالك. إليك قائمة بالخدمات المتاحة:" + MENU_AR
|
204 |
responses["en"] = "Sorry, I didn't understand your question. Here's a menu of available services:" + MENU_EN
|
205 |
|
|
|
206 |
log_interaction(message, responses[language], intent, language)
|
|
|
207 |
return responses
|
208 |
|
209 |
+
# Gradio Interface
|
210 |
+
with gr.Blocks() as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
selected_lang = gr.State(value="ar")
|
|
|
212 |
user_name = gr.State(value=None)
|
213 |
|
|
|
|
|
|
|
|
|
|
|
214 |
with gr.Row():
|
215 |
+
gr.Markdown("# Omdurman National Bank Virtual Assistant")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
|
217 |
+
with gr.Row():
|
218 |
+
language_btn = gr.Radio(["العربية", "English"], value="العربية", label="Language")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
+
chatbot = gr.Chatbot(height=400)
|
|
|
|
|
|
|
221 |
|
222 |
with gr.Row():
|
223 |
+
text_input = gr.Textbox(placeholder="Type your question here", label="")
|
224 |
+
submit_btn = gr.Button("Send", variant="primary")
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
|
226 |
with gr.Row():
|
227 |
+
menu_btn = gr.Button("Show Menu")
|
228 |
+
live_agent_btn = gr.Button("Connect to Live Agent")
|
229 |
+
survey_btn = gr.Button("Feedback")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
|
231 |
+
# Link inputs and buttons to response functions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
submit_btn.click(
|
233 |
fn=on_submit,
|
234 |
inputs=[text_input, chatbot, selected_lang, user_name],
|
235 |
outputs=[text_input, chatbot, user_name]
|
236 |
)
|
237 |
|
|
|
238 |
menu_btn.click(
|
239 |
fn=show_menu,
|
240 |
inputs=[chatbot, selected_lang],
|
241 |
outputs=[chatbot]
|
242 |
)
|
243 |
|
|
|
244 |
live_agent_btn.click(
|
245 |
fn=connect_to_live_agent,
|
246 |
inputs=[chatbot, selected_lang],
|
247 |
outputs=[chatbot]
|
248 |
)
|
249 |
|
|
|
250 |
survey_btn.click(
|
251 |
fn=show_satisfaction_survey,
|
252 |
inputs=[chatbot, selected_lang],
|
253 |
outputs=[chatbot]
|
254 |
)
|
255 |
|
256 |
+
# Initialize chat
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
demo.load(
|
258 |
fn=init_chat,
|
259 |
inputs=[],
|
|
|
261 |
)
|
262 |
|
263 |
if __name__ == "__main__":
|
264 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|
|
|
|
|
|
|
|