waleedmohd commited on
Commit
6d68b47
·
verified ·
1 Parent(s): 1bc7c7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +289 -71
app.py CHANGED
@@ -1,87 +1,305 @@
1
  import gradio as gr
2
- import spacy
3
- import json
4
- from datetime import datetime
5
-
6
- # Load spaCy language models
7
- try:
8
- nlp_ar = spacy.blank("ar") # Arabic
9
- nlp_en = spacy.blank("en") # English
10
- except Exception as e:
11
- print(f"Error loading spaCy models: {e}")
12
- nlp_ar = None
13
- nlp_en = None
14
-
15
- # Function to detect language using spaCy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def detect_language(text):
17
- if not text.strip():
18
- return "unknown"
19
-
20
- # Check if the text contains Arabic characters using spaCy
21
- if nlp_ar and any(token.is_alpha for token in nlp_ar(text)):
22
- return "ar"
 
 
 
23
 
24
- # Check for English
25
- if nlp_en and any(token.is_alpha for token in nlp_en(text)):
26
- return "en"
27
 
 
 
 
 
 
 
28
  return "unknown"
29
 
30
- # Placeholder customer service functions
31
- def get_enhanced_response(intent, lang):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  responses = {
33
- "balance": {"ar": "رصيدك هو 1000 جنيه سوداني.", "en": "Your balance is 1000 SDG."},
34
- "lost_card": {"ar": "يرجى الاتصال بالبنك فورًا للإبلاغ عن بطاقة مفقودة.", "en": "Please contact the bank immediately to report a lost card."}
35
- }
36
- return responses.get(intent, {}).get(lang, "I'm not sure how to answer that.")
37
-
38
- # Log interactions
39
- def log_interaction(user_message, bot_response, intent, language):
40
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
41
- log_entry = {"timestamp": timestamp, "user_message": user_message, "bot_response": bot_response, "intent": intent, "language": language}
42
- with open("/mnt/data/chat_logs.jsonl", "a", encoding="utf-8") as f:
43
- f.write(json.dumps(log_entry, ensure_ascii=False) + "\n")
44
-
45
- # Intent classification function
46
- def classify_intent(message):
47
- keywords = {
48
- "balance": ["balance", "رصيد"],
49
- "lost_card": ["lost", "card", "بطاقة", "ضائعة"]
50
  }
51
- for intent, words in keywords.items():
52
- if any(word in message.lower() for word in words):
53
- return intent
54
- return "unknown"
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- # Response function
57
- def respond(message):
58
- language = detect_language(message)
59
- intent = classify_intent(message)
60
- response = get_enhanced_response(intent, language)
61
- log_interaction(message, response, intent, language)
62
- return response
63
 
64
- # Chatbot interface with Gradio
65
- def chatbot_interface(user_input, chat_history):
66
- if not user_input.strip():
67
- return "", chat_history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- response = respond(user_input)
70
- chat_history.append(("User", user_input))
71
- chat_history.append(("Bot", response))
 
 
 
 
 
72
 
73
- return "", chat_history
 
 
 
 
 
74
 
75
- # Gradio UI
76
- with gr.Blocks() as demo:
77
- gr.Markdown("# Banking Chatbot - Now with spaCy")
78
- chat_history = gr.State([])
79
- chatbot = gr.Chatbot()
80
- user_input = gr.Textbox(placeholder="Type your message...")
81
- send_btn = gr.Button("Send")
82
 
83
- send_btn.click(fn=chatbot_interface, inputs=[user_input, chat_history], outputs=[user_input, chatbot])
84
- user_input.submit(fn=chatbot_interface, inputs=[user_input, chat_history], outputs=[user_input, chatbot])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  if __name__ == "__main__":
87
- demo.launch()
 
 
 
 
 
1
  import gradio as gr
2
+ import re
3
+
4
+ # Load language detection model only (smaller model)
5
+ from transformers import pipeline
6
+ language_detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
7
+
8
+ # Omdurman National Bank-specific guidelines in Arabic
9
+ ONB_GUIDELINES_AR = {
10
+ "balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك الوطني.",
11
+ "lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
12
+ "loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
13
+ "transfer": "لتحويل الأموال، استخدم تطبيق الهاتف أو الخدمة المصرفية عبر الإنترنت.",
14
+ "new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.",
15
+ "interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.",
16
+ "branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان. زيارة موقعنا للتفاصيل.",
17
+ "working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.",
18
+ "contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
19
+ }
20
+
21
+ # Omdurman National Bank-specific guidelines in English
22
+ ONB_GUIDELINES_EN = {
23
+ "balance": "You can check your balance online or via the ONB mobile app.",
24
+ "lost_card": "In case of a lost card, call 249-123-456-789 immediately.",
25
+ "loan": "Loan requirements include minimum income (5000 SDG) and good credit history.",
26
+ "transfer": "To transfer funds, use the mobile app or online banking service.",
27
+ "new_account": "To open a new account, visit your nearest branch with your passport or national ID.",
28
+ "interest_rates": "Interest rates on deposits range from 5% to 10% annually.",
29
+ "branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan. Visit our website for details.",
30
+ "working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.",
31
+ "contact": "Contact us at 249-123-456-789 or via email at [email protected]."
32
+ }
33
+
34
+ # Menu options in both languages
35
+ MENU_AR = """
36
+ قائمة الخدمات المصرفية:
37
+ 1. رصيد - استعلام عن رصيد حسابك
38
+ 2. بطاقة - الإبلاغ عن بطاقة مفقودة
39
+ 3. قرض - معلومات عن القروض
40
+ 4. تحويل - تحويل الأموال
41
+ 5. حساب - فتح حساب جديد
42
+ 6. فائدة - أسعار الفائدة
43
+ 7. فرع - مواقع الفروع
44
+ 8. ساعات - ساعات العمل
45
+ 9. اتصال - معلومات الاتصال
46
+ """
47
+
48
+ MENU_EN = """
49
+ Banking Services Menu:
50
+ 1. balance - Check your account balance
51
+ 2. card - Report a lost card
52
+ 3. loan - Information about loans
53
+ 4. transfer - Transfer funds
54
+ 5. account - Open a new account
55
+ 6. interest - Interest rates
56
+ 7. branch - Branch locations
57
+ 8. hours - Working hours
58
+ 9. contact - Contact information
59
+ """
60
+
61
+ # Map intents to keywords (enhanced)
62
+ INTENT_KEYWORDS = {
63
+ "balance": ["balance", "check balance", "account balance", "how much", "رصيد", "حساب", "كم المبلغ", "1"],
64
+ "lost_card": ["lost", "card", "stolen", "missing", "فقدت", "بطاقة", "مسروقة", "ضائعة", "2"],
65
+ "loan": ["loan", "borrow", "borrowing", "credit", "قرض", "استدانة", "إئتمان", "3"],
66
+ "transfer": ["transfer", "send money", "payment", "تحويل", "ارسال", "دفع", "4"],
67
+ "new_account": ["account", "open", "create", "new", "حساب", "فتح", "جديد", "إنشاء", "5"],
68
+ "interest_rates": ["interest", "rate", "rates", "return", "فائدة", "نسبة", "عائد", "6"],
69
+ "branches": ["branch", "location", "where", "office", "فرع", "موقع", "أين", "مكتب", "7"],
70
+ "working_hours": ["hours", "time", "open", "close", "ساعات", "وقت", "مفتوح", "مغلق", "8"],
71
+ "contact": ["contact", "phone", "email", "call", "اتصال", "هاتف", "بريد", "اتصل", "9"]
72
+ }
73
+
74
  def detect_language(text):
75
+ # Use Hugging Face language detection model
76
+ result = language_detector(text)
77
+ language = result[0]['label']
78
+ return language
79
+
80
+ def classify_intent(message: str):
81
+ # Check for menu request
82
+ menu_keywords = ["menu", "options", "help", "قائمة", "خيارات", "مساعدة"]
83
+ message_lower = message.lower()
84
 
85
+ for keyword in menu_keywords:
86
+ if keyword in message_lower:
87
+ return "menu"
88
 
89
+ # Use keyword matching for intent classification
90
+ for intent_key, keywords in INTENT_KEYWORDS.items():
91
+ for keyword in keywords:
92
+ if keyword.lower() in message_lower:
93
+ return intent_key
94
+
95
  return "unknown"
96
 
97
+ def respond(message: str):
98
+ if not message.strip():
99
+ return {
100
+ "ar": "الرجاء كتابة سؤالك.",
101
+ "en": "Please type your question."
102
+ }
103
+
104
+ # Detect language
105
+ language = detect_language(message)
106
+
107
+ # If the language is neither Arabic nor English, default to English
108
+ if language != "ar" and language != "en":
109
+ language = "en"
110
+
111
+ # Classify the user's intent using keyword matching
112
+ intent = classify_intent(message)
113
+
114
+ # Prepare responses in both languages
115
  responses = {
116
+ "ar": "",
117
+ "en": ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
+
120
+ # Special handling for menu request
121
+ if intent == "menu":
122
+ responses["ar"] = MENU_AR
123
+ responses["en"] = MENU_EN
124
+ return responses
125
+
126
+ # If intent is recognized, return the corresponding response
127
+ if intent != "unknown":
128
+ responses["ar"] = ONB_GUIDELINES_AR.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.")
129
+ responses["en"] = ONB_GUIDELINES_EN.get(intent, "Sorry, the selected option was not recognized.")
130
+ else:
131
+ # Default response if no intent is matched - show menu
132
+ responses["ar"] = "عذرًا، لم أفهم سؤالك. إليك قائمة بالخدمات المتاحة:" + MENU_AR
133
+ responses["en"] = "Sorry, I didn't understand your question. Here's a menu of available services:" + MENU_EN
134
+
135
+ return responses
136
 
137
+ # Custom CSS for better UI
138
+ custom_css = """
139
+ .gradio-container {
140
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
141
+ }
 
 
142
 
143
+ .chat-message {
144
+ padding: 1rem;
145
+ border-radius: 10px;
146
+ margin-bottom: 1rem;
147
+ max-width: 80%;
148
+ }
149
+
150
+ .user-message {
151
+ background-color: #e6f7ff;
152
+ margin-left: auto;
153
+ text-align: right;
154
+ }
155
+
156
+ .bot-message {
157
+ background-color: #f0f0f0;
158
+ margin-right: auto;
159
+ text-align: left;
160
+ }
161
+
162
+ .bot-message-ar {
163
+ background-color: #f0f0f0;
164
+ margin-left: auto;
165
+ text-align: right;
166
+ }
167
 
168
+ .header-section {
169
+ background-color: #1a5276;
170
+ color: white;
171
+ padding: 1rem;
172
+ border-radius: 10px;
173
+ margin-bottom: 1rem;
174
+ text-align: center;
175
+ }
176
 
177
+ .footer-section {
178
+ font-size: 0.8rem;
179
+ text-align: center;
180
+ margin-top: 2rem;
181
+ color: #666;
182
+ }
183
 
184
+ .lang-selector {
185
+ text-align: right;
186
+ margin-bottom: 1rem;
187
+ }
 
 
 
188
 
189
+ .menu-button {
190
+ margin-top: 0.5rem;
191
+ }
192
+ """
193
+
194
+ # Chat interface with enhanced UI
195
+ with gr.Blocks(css=custom_css) as demo:
196
+ # Store conversation history
197
+ state = gr.State(value=[])
198
+ # Store selected language
199
+ selected_lang = gr.State(value="ar")
200
+
201
+ with gr.Row(elem_classes="header-section"):
202
+ with gr.Column():
203
+ gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني")
204
+ gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي الافتراضي")
205
+
206
+ with gr.Row():
207
+ with gr.Column(elem_classes="lang-selector"):
208
+ language_btn = gr.Radio(
209
+ ["العربية", "English"],
210
+ value="العربية",
211
+ label="Language | اللغة"
212
+ )
213
+
214
+ with gr.Row():
215
+ chat_box = gr.Chatbot(elem_id="chatbox", height=400)
216
+
217
+ with gr.Row():
218
+ with gr.Column(scale=8):
219
+ text_input = gr.Textbox(
220
+ placeholder="Type your question here | اكتب سؤالك هنا",
221
+ label="",
222
+ elem_id="chat-input"
223
+ )
224
+ with gr.Column(scale=1):
225
+ submit_btn = gr.Button("Send | إرسال", variant="primary")
226
+
227
+ with gr.Row():
228
+ with gr.Column(elem_classes="menu-button"):
229
+ menu_btn = gr.Button("Show Menu | إظهار القائمة")
230
+
231
+ with gr.Row(elem_classes="footer-section"):
232
+ gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©")
233
+
234
+ # Update language state when language is changed
235
+ def update_language(lang):
236
+ if lang == "العربية":
237
+ return "ar"
238
+ else:
239
+ return "en"
240
+
241
+ language_btn.change(
242
+ fn=update_language,
243
+ inputs=language_btn,
244
+ outputs=selected_lang
245
+ )
246
+
247
+ # Handle message submission
248
+ def on_submit(message, chat_history, lang):
249
+ if not message.strip():
250
+ return "", chat_history
251
+
252
+ # Add user message to chat history
253
+ chat_history.append([message, None])
254
+
255
+ # Get response
256
+ responses = respond(message)
257
+
258
+ # Select response based on language
259
+ response = responses[lang]
260
+
261
+ # Update bot response in chat history
262
+ chat_history[-1][1] = response
263
+
264
+ return "", chat_history
265
+
266
+ # Handle menu button click
267
+ def show_menu(chat_history, lang):
268
+ menu_responses = {
269
+ "ar": MENU_AR,
270
+ "en": MENU_EN
271
+ }
272
+
273
+ # Add system message showing the menu
274
+ menu_text = menu_responses[lang]
275
+ chat_history.append([None, menu_text])
276
+
277
+ return chat_history
278
+
279
+ # Link inputs and button to response function
280
+ submit_btn.click(
281
+ fn=on_submit,
282
+ inputs=[text_input, chat_box, selected_lang],
283
+ outputs=[text_input, chat_box]
284
+ )
285
+
286
+ # Link menu button to show menu function
287
+ menu_btn.click(
288
+ fn=show_menu,
289
+ inputs=[chat_box, selected_lang],
290
+ outputs=[chat_box]
291
+ )
292
+
293
+ # Also trigger on Enter key
294
+ text_input.submit(
295
+ fn=on_submit,
296
+ inputs=[text_input, chat_box, selected_lang],
297
+ outputs=[text_input, chat_box]
298
+ )
299
 
300
  if __name__ == "__main__":
301
+ demo.launch(
302
+ server_name="0.0.0.0",
303
+ server_port=7860,
304
+ share=True # Enable public link
305
+ )