File size: 10,980 Bytes
c045b61
 
 
 
 
 
d1f8c20
c045b61
 
 
 
 
 
d1f8c20
edd7ea8
 
 
 
 
 
 
 
 
 
 
c045b61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1f8c20
 
 
c045b61
 
d1f8c20
 
 
c045b61
 
d1f8c20
c045b61
d1f8c20
 
 
 
 
 
 
 
 
c045b61
 
 
d1f8c20
 
 
 
 
 
 
 
 
c045b61
 
d1f8c20
c045b61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1f8c20
c045b61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1f8c20
c045b61
 
 
 
 
 
 
d1f8c20
edd7ea8
 
 
 
 
 
c045b61
d1f8c20
c045b61
 
d1f8c20
c045b61
 
 
 
 
d1f8c20
c045b61
 
 
 
 
 
d1f8c20
c045b61
 
 
d1f8c20
 
c045b61
 
 
d1f8c20
c045b61
 
 
d1f8c20
 
c045b61
 
 
d1f8c20
c045b61
 
 
 
 
d1f8c20
 
c045b61
 
 
 
 
 
 
d1f8c20
 
c045b61
 
 
 
d1f8c20
c045b61
d1f8c20
 
edd7ea8
d1f8c20
c045b61
 
d1f8c20
 
c045b61
 
d1f8c20
 
 
c045b61
d1f8c20
c045b61
 
30e88fa
 
c045b61
 
 
 
30e88fa
 
c045b61
 
 
 
30e88fa
 
c045b61
 
 
 
30e88fa
 
c045b61
 
d1f8c20
c045b61
30e88fa
c045b61
edd7ea8
c045b61
 
 
d1f8c20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
import gradio as gr
import re
import json
import time
from datetime import datetime

# Simple language detection function
def simple_detect_language(text):
    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
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
    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?"],
        "thanks": ["Thank you for contacting Omdurman National Bank!"],
        "follow_up": ["Is there anything else I can help you with?"]
    }

# Omdurman National Bank-specific guidelines
ONB_GUIDELINES_AR = {
    "balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك أم درمان الوطني.",
    "lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
    "loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
    "transfer": "لتحويل الأموال، استخدم تطبيق الهاتف أو الخدمة المصرفية عبر الإنترنت.",
    "new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.",
    "interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.",
    "branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان.",
    "working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.",
    "contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
}

ONB_GUIDELINES_EN = {
    "balance": "You can check your balance online or via the ONB mobile app.",
    "lost_card": "In case of a lost card, call 249-123-456-789 immediately.",
    "loan": "Loan requirements include minimum income (5000 SDG) and good credit history.",
    "transfer": "To transfer funds, use the mobile app or online banking service.",
    "new_account": "To open a new account, visit your nearest branch with your passport or national ID.",
    "interest_rates": "Interest rates on deposits range from 5% to 10% annually.",
    "branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan.",
    "working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.",
    "contact": "Contact us at 249-123-456-789 or via email at [email protected]."
}

# Quick action buttons
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_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"}
]

# Function to get a random phrase
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):
    menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"]
    message_lower = message.lower()
    
    for keyword in menu_keywords:
        if keyword in message_lower:
            return "menu"
    
    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}")

# Function to generate responses
def respond(message: str):
    if not message.strip():
        return {
            "ar": "الرجاء كتابة سؤالك.",
            "en": "Please type your question."
        }
    
    # Detect language
    if ARABIC_NLP_AVAILABLE:
        language = detect_language_with_nlp(message)
        if language != "ar" and language != "en":
            language = "en"
    else:
        language = simple_detect_language(message)
    
    # Classify intent
    intent = classify_intent(message)
    
    # Prepare responses
    responses = {
        "ar": "",
        "en": ""
    }
    
    # Handle menu request
    if intent == "menu":
        responses["ar"] = MENU_AR
        responses["en"] = MENU_EN
        log_interaction(message, responses[language], "menu", language)
        return responses
    
    # Handle banking FAQ
    if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
        faq_answer = handle_banking_faq(message, language)
        if faq_answer:
            responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{faq_answer}<br><br>{get_random_phrase('follow_up', 'ar')}"
            responses["en"] = f"{get_random_phrase('greeting', 'en')}<br><br>{faq_answer}<br><br>{get_random_phrase('follow_up', 'en')}"
            log_interaction(message, responses[language], "faq", language)
            return responses
    
    # Handle banking term definition
    if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
        term_definition = get_banking_term_definition(message, language)
        if term_definition:
            responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{term_definition}<br><br>{get_random_phrase('follow_up', 'ar')}"
            responses["en"] = f"{get_random_phrase('greeting', 'en')}<br><br>{term_definition}<br><br>{get_random_phrase('follow_up', 'en')}"
            log_interaction(message, responses[language], "term", language)
            return responses
    
    # Handle recognized intents
    if intent != "unknown":
        if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
            responses["ar"] = get_enhanced_response(intent, "ar")
            responses["en"] = get_enhanced_response(intent, "en")
        else:
            responses["ar"] = f"{get_random_phrase('greeting', 'ar')}<br><br>{ONB_GUIDELINES_AR.get(intent, 'عذرًا، لم يتم التعرف على الخيار المحدد.')}<br><br>{get_random_phrase('follow_up', 'ar')}"
            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')}"
    else:
        responses["ar"] = "عذرًا، لم أفهم سؤالك. إليك قائمة بالخدمات المتاحة:" + MENU_AR
        responses["en"] = "Sorry, I didn't understand your question. Here's a menu of available services:" + MENU_EN
    
    log_interaction(message, responses[language], intent, language)
    return responses

# Gradio Interface
with gr.Blocks() as demo:
    selected_lang = gr.State(value="ar")
    user_name = gr.State(value=None)
    
    with gr.Row():
        gr.Markdown("# Omdurman National Bank Virtual Assistant")
    
    with gr.Row():
        language_btn = gr.Radio(["العربية", "English"], value="العربية", label="Language")
    
    chatbot = gr.Chatbot(height=400)
    
    with gr.Row():
        text_input = gr.Textbox(placeholder="Type your question here", label="")
        submit_btn = gr.Button("Send", variant="primary")
    
    with gr.Row():
        menu_btn = gr.Button("Show Menu")
        live_agent_btn = gr.Button("Connect to Live Agent")
        survey_btn = gr.Button("Feedback")
    
    # Link inputs and buttons to response functions
    submit_btn.click(
        fn=on_submit,
        inputs=[text_input, chatbot, selected_lang, user_name],
        outputs=[text_input, chatbot, user_name]
    )
    
    menu_btn.click(
        fn=show_menu,
        inputs=[chatbot, selected_lang],
        outputs=[chatbot]
    )
    
    live_agent_btn.click(
        fn=connect_to_live_agent,
        inputs=[chatbot, selected_lang],
        outputs=[chatbot]
    )
    
    survey_btn.click(
        fn=show_satisfaction_survey,
        inputs=[chatbot, selected_lang],
        outputs=[chatbot]
    )
    
    # Initialize chat
    demo.load(
        fn=init_chat,
        inputs=[],
        outputs=[chatbot]
    )

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860, share=True)