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" | |
| # 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"] | |
| } | |
| # Customer service phrases for more human-like responses | |
| CUSTOMER_SERVICE_PHRASES_AR = { | |
| "greeting": [ | |
| "مرحبًا! كيف يمكنني مساعدتك اليوم؟", | |
| "أهلاً بك في بنك أم درمان الوطني! كيف يمكنني خدمتك؟", | |
| "مرحبًا بك! أنا هنا للمساعدة في أي استفسارات مصرفية." | |
| ], | |
| "thanks": [ | |
| "شكرًا لتواصلك معنا!", | |
| "نشكرك على استخدام خدماتنا المصرفية.", | |
| "سعداء بخدمتك دائمًا!" | |
| ], | |
| "follow_up": [ | |
| "هل هناك شيء آخر يمكنني مساعدتك به؟", | |
| "هل لديك أي أسئلة أخرى؟", | |
| "هل تحتاج إلى مساعدة في أمر آخر؟" | |
| ] | |
| } | |
| CUSTOMER_SERVICE_PHRASES_EN = { | |
| "greeting": [ | |
| "Hello! How can I assist you today?", | |
| "Welcome to Omdurman National Bank! How may I help you?", | |
| "Hi there! I'm here to help with any banking inquiries." | |
| ], | |
| "thanks": [ | |
| "Thank you for contacting us!", | |
| "We appreciate you using our banking services.", | |
| "Always happy to serve you!" | |
| ], | |
| "follow_up": [ | |
| "Is there anything else I can help you with?", | |
| "Do you have any other questions?", | |
| "Do you need assistance with anything else?" | |
| ] | |
| } | |
| # 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(CUSTOMER_SERVICE_PHRASES_AR[category]) | |
| else: | |
| return random.choice(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("/home/ubuntu/banking_chatbot/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 simple function | |
| 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 | |
| # If intent is recognized, return the corresponding response | |
| if intent != "unknown": | |
| # 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; | |
| } | |
| .typing-indicator { | |
| display: inline-block; | |
| width: 50px; | |
| text-align: left; | |
| } | |
| .typing-indicator span { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| background-color: #1a5276; | |
| border-radius: 50%; | |
| margin-right: 5px; | |
| animation: typing 1s infinite; | |
| } | |
| .typing-indicator span:nth-child(2) { | |
| animation-delay: 0.2s; | |
| } | |
| .typing-indicator span:nth-child(3) { | |
| animation-delay: 0.4s; | |
| } | |
| @keyframes typing { | |
| 0%, 100% { | |
| transform: translateY(0); | |
| } | |
| 50% { | |
| transform: translateY(-5px); | |
| } | |
| } | |
| .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; | |
| } | |
| """ | |
| # Custom JavaScript for enhanced functionality | |
| custom_js = """ | |
| function simulateTyping(message, elementId, delay = 30) { | |
| const element = document.getElementById(elementId); | |
| if (!element) return; | |
| element.innerHTML = ""; | |
| let i = 0; | |
| function type() { | |
| if (i < message.length) { | |
| element.innerHTML += message.charAt(i); | |
| i++; | |
| setTimeout(type, delay); | |
| } | |
| } | |
| type(); | |
| } | |
| // Function to show typing indicator | |
| function showTypingIndicator() { | |
| const chatbox = document.getElementById('chatbox'); | |
| if (!chatbox) return; | |
| const typingIndicator = document.createElement('div'); | |
| typingIndicator.className = 'typing-indicator'; | |
| typingIndicator.id = 'typing-indicator'; | |
| typingIndicator.innerHTML = '<span></span><span></span><span></span>'; | |
| chatbox.appendChild(typingIndicator); | |
| chatbox.scrollTop = chatbox.scrollHeight; | |
| } | |
| // Function to hide typing indicator | |
| function hideTypingIndicator() { | |
| const typingIndicator = document.getElementById('typing-indicator'); | |
| if (typingIndicator) { | |
| typingIndicator.remove(); | |
| } | |
| } | |
| // Function to connect with a live agent | |
| function connectLiveAgent() { | |
| alert('Connecting to a live customer service agent. Please wait a moment...'); | |
| // In a real implementation, this would initiate a connection to a live agent system | |
| } | |
| """ | |
| # Chat interface with enhanced UI | |
| with gr.Blocks(css=custom_css, js=custom_js) as demo: | |
| # Store conversation history | |
| state = gr.State(value=[]) | |
| # Store selected language | |
| selected_lang = gr.State(value="ar") | |
| with gr.Row(elem_classes="header-section"): | |
| with gr.Column(): | |
| gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني") | |
| gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي ا<response clipped><NOTE>To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with `grep -n` in order to find the line numbers of what you are looking for.</NOTE> |