Update app.py
Browse files
app.py
CHANGED
@@ -1,14 +1,18 @@
|
|
1 |
import gradio as gr
|
2 |
from transformers import pipeline
|
|
|
3 |
|
4 |
# Load Arabic NLP model for intent classification
|
5 |
-
|
|
|
|
|
|
|
6 |
|
7 |
# Load language detection model
|
8 |
language_detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
|
9 |
|
10 |
-
# Omdurman National Bank-specific guidelines
|
11 |
-
|
12 |
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك الوطني.",
|
13 |
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
|
14 |
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
|
@@ -20,17 +24,30 @@ ONB_GUIDELINES = {
|
|
20 |
"contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
# Map intents to responses
|
24 |
-
|
25 |
-
"balance": "balance",
|
26 |
-
"lost_card": "
|
27 |
-
"loan": "loan",
|
28 |
-
"transfer": "transfer",
|
29 |
-
"new_account": "
|
30 |
-
"interest_rates": "
|
31 |
-
"branches": "
|
32 |
-
"working_hours": "
|
33 |
-
"contact": "contact"
|
34 |
}
|
35 |
|
36 |
def detect_language(text):
|
@@ -39,57 +56,200 @@ def detect_language(text):
|
|
39 |
language = result[0]['label']
|
40 |
return language
|
41 |
|
42 |
-
def classify_intent(message: str):
|
43 |
-
# Use
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
def respond(message: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
# Detect language
|
50 |
language = detect_language(message)
|
51 |
|
52 |
-
# If the language is
|
53 |
-
if language != "ar":
|
54 |
-
|
|
|
|
|
|
|
55 |
|
56 |
-
#
|
57 |
-
|
|
|
|
|
|
|
58 |
|
59 |
# If intent is recognized, return the corresponding response
|
60 |
if intent != "unknown":
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
67 |
|
68 |
-
|
69 |
-
return "عذرًا، لم أفهم سؤالك. الرجاء إعادة الصياغة أو اختيار أحد الخيارات التالية: " + ", ".join(INTENT_TO_RESPONSE.keys())
|
70 |
|
71 |
-
#
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
-
with gr.
|
76 |
-
gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
-
#
|
79 |
-
|
80 |
|
81 |
-
#
|
82 |
-
|
83 |
|
84 |
-
#
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
if __name__ == "__main__":
|
95 |
demo.launch(
|
|
|
1 |
import gradio as gr
|
2 |
from transformers import pipeline
|
3 |
+
import re
|
4 |
|
5 |
# Load Arabic NLP model for intent classification
|
6 |
+
intent_classifier_ar = pipeline("text-classification", model="aubmindlab/bert-base-arabertv02")
|
7 |
+
|
8 |
+
# Load English NLP model for intent classification
|
9 |
+
intent_classifier_en = pipeline("text-classification", model="facebook/bart-large-mnli")
|
10 |
|
11 |
# Load language detection model
|
12 |
language_detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
|
13 |
|
14 |
+
# Omdurman National Bank-specific guidelines in Arabic
|
15 |
+
ONB_GUIDELINES_AR = {
|
16 |
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك الوطني.",
|
17 |
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
|
18 |
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
|
|
|
24 |
"contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
|
25 |
}
|
26 |
|
27 |
+
# Omdurman National Bank-specific guidelines in English
|
28 |
+
ONB_GUIDELINES_EN = {
|
29 |
+
"balance": "You can check your balance online or via the ONB mobile app.",
|
30 |
+
"lost_card": "In case of a lost card, call 249-123-456-789 immediately.",
|
31 |
+
"loan": "Loan requirements include minimum income (5000 SDG) and good credit history.",
|
32 |
+
"transfer": "To transfer funds, use the mobile app or online banking service.",
|
33 |
+
"new_account": "To open a new account, visit your nearest branch with your passport or national ID.",
|
34 |
+
"interest_rates": "Interest rates on deposits range from 5% to 10% annually.",
|
35 |
+
"branches": "Our branches are located in Omdurman, Khartoum, and Port Sudan. Visit our website for details.",
|
36 |
+
"working_hours": "Working hours are from 8 AM to 3 PM, Sunday to Thursday.",
|
37 |
+
"contact": "Contact us at 249-123-456-789 or via email at [email protected]."
|
38 |
+
}
|
39 |
+
|
40 |
# Map intents to responses
|
41 |
+
INTENT_KEYWORDS = {
|
42 |
+
"balance": ["balance", "رصيد", "حساب"],
|
43 |
+
"lost_card": ["lost", "card", "stolen", "فقدت", "بطاقة", "مسروقة"],
|
44 |
+
"loan": ["loan", "borrow", "قرض", "استدانة"],
|
45 |
+
"transfer": ["transfer", "send money", "تحويل", "ارسال"],
|
46 |
+
"new_account": ["account", "open", "حساب", "فتح"],
|
47 |
+
"interest_rates": ["interest", "rate", "فائدة", "نسبة"],
|
48 |
+
"branches": ["branch", "location", "فرع", "موقع"],
|
49 |
+
"working_hours": ["hours", "time", "ساعات", "وقت"],
|
50 |
+
"contact": ["contact", "phone", "email", "اتصال", "هاتف", "بريد"]
|
51 |
}
|
52 |
|
53 |
def detect_language(text):
|
|
|
56 |
language = result[0]['label']
|
57 |
return language
|
58 |
|
59 |
+
def classify_intent(message: str, language: str):
|
60 |
+
# Use appropriate classifier based on language
|
61 |
+
if language == "ar":
|
62 |
+
# For Arabic
|
63 |
+
result = intent_classifier_ar(message)
|
64 |
+
intent = result[0]['label']
|
65 |
+
else:
|
66 |
+
# For English
|
67 |
+
result = intent_classifier_en(message, candidate_labels=list(INTENT_KEYWORDS.keys()))
|
68 |
+
intent = result["labels"][0]
|
69 |
+
|
70 |
+
# Fallback to keyword matching
|
71 |
+
if intent not in INTENT_KEYWORDS:
|
72 |
+
for intent_key, keywords in INTENT_KEYWORDS.items():
|
73 |
+
for keyword in keywords:
|
74 |
+
if re.search(r'\b' + re.escape(keyword.lower()) + r'\b', message.lower()):
|
75 |
+
return intent_key
|
76 |
+
return "unknown"
|
77 |
+
|
78 |
+
return intent
|
79 |
|
80 |
def respond(message: str):
|
81 |
+
if not message.strip():
|
82 |
+
return {
|
83 |
+
"ar": "الرجاء كتابة سؤالك.",
|
84 |
+
"en": "Please type your question."
|
85 |
+
}
|
86 |
+
|
87 |
# Detect language
|
88 |
language = detect_language(message)
|
89 |
|
90 |
+
# If the language is neither Arabic nor English, default to English
|
91 |
+
if language != "ar" and language != "en":
|
92 |
+
language = "en"
|
93 |
+
|
94 |
+
# Classify the user's intent
|
95 |
+
intent = classify_intent(message, language)
|
96 |
|
97 |
+
# Prepare responses in both languages
|
98 |
+
responses = {
|
99 |
+
"ar": "",
|
100 |
+
"en": ""
|
101 |
+
}
|
102 |
|
103 |
# If intent is recognized, return the corresponding response
|
104 |
if intent != "unknown":
|
105 |
+
responses["ar"] = ONB_GUIDELINES_AR.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.")
|
106 |
+
responses["en"] = ONB_GUIDELINES_EN.get(intent, "Sorry, the selected option was not recognized.")
|
107 |
+
else:
|
108 |
+
# Default response if no intent is matched
|
109 |
+
ar_options = ", ".join(list(ONB_GUIDELINES_AR.keys()))
|
110 |
+
en_options = ", ".join(list(ONB_GUIDELINES_EN.keys()))
|
111 |
+
|
112 |
+
responses["ar"] = f"عذرًا، لم أفهم سؤالك. الرجاء إعادة الصياغة أو اختيار أحد الخيارات التالية: {ar_options}"
|
113 |
+
responses["en"] = f"Sorry, I didn't understand your question. Please rephrase or choose one of the following options: {en_options}"
|
114 |
|
115 |
+
return responses
|
|
|
116 |
|
117 |
+
# Custom CSS for better UI
|
118 |
+
custom_css = """
|
119 |
+
.gradio-container {
|
120 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
121 |
+
}
|
122 |
+
|
123 |
+
.chat-message {
|
124 |
+
padding: 1rem;
|
125 |
+
border-radius: 10px;
|
126 |
+
margin-bottom: 1rem;
|
127 |
+
max-width: 80%;
|
128 |
+
}
|
129 |
+
|
130 |
+
.user-message {
|
131 |
+
background-color: #e6f7ff;
|
132 |
+
margin-left: auto;
|
133 |
+
text-align: right;
|
134 |
+
}
|
135 |
+
|
136 |
+
.bot-message {
|
137 |
+
background-color: #f0f0f0;
|
138 |
+
margin-right: auto;
|
139 |
+
text-align: left;
|
140 |
+
}
|
141 |
+
|
142 |
+
.bot-message-ar {
|
143 |
+
background-color: #f0f0f0;
|
144 |
+
margin-left: auto;
|
145 |
+
text-align: right;
|
146 |
+
}
|
147 |
+
|
148 |
+
.header-section {
|
149 |
+
background-color: #1a5276;
|
150 |
+
color: white;
|
151 |
+
padding: 1rem;
|
152 |
+
border-radius: 10px;
|
153 |
+
margin-bottom: 1rem;
|
154 |
+
text-align: center;
|
155 |
+
}
|
156 |
+
|
157 |
+
.footer-section {
|
158 |
+
font-size: 0.8rem;
|
159 |
+
text-align: center;
|
160 |
+
margin-top: 2rem;
|
161 |
+
color: #666;
|
162 |
+
}
|
163 |
+
|
164 |
+
.lang-selector {
|
165 |
+
text-align: right;
|
166 |
+
margin-bottom: 1rem;
|
167 |
+
}
|
168 |
+
"""
|
169 |
+
|
170 |
+
# Chat interface with enhanced UI
|
171 |
+
with gr.Blocks(css=custom_css) as demo:
|
172 |
+
# Store conversation history
|
173 |
+
state = gr.State(value=[])
|
174 |
+
# Store selected language
|
175 |
+
selected_lang = gr.State(value="ar")
|
176 |
+
|
177 |
+
with gr.Row(elem_classes="header-section"):
|
178 |
+
with gr.Column(scale=1):
|
179 |
+
gr.Image("https://via.placeholder.com/150", elem_id="bank-logo", label="")
|
180 |
+
with gr.Column(scale=2):
|
181 |
+
gr.Markdown("# Omdurman National Bank | بنك أم درمان الوطني")
|
182 |
+
gr.Markdown("### Virtual Banking Assistant | المساعد المصرفي الافتراضي")
|
183 |
+
|
184 |
+
with gr.Row():
|
185 |
+
with gr.Column(elem_classes="lang-selector"):
|
186 |
+
language_btn = gr.Radio(
|
187 |
+
["العربية", "English"],
|
188 |
+
value="العربية",
|
189 |
+
label="Language | اللغة"
|
190 |
+
)
|
191 |
|
192 |
+
with gr.Row():
|
193 |
+
chat_box = gr.Chatbot(elem_id="chatbox", height=400)
|
194 |
+
|
195 |
+
with gr.Row():
|
196 |
+
with gr.Column(scale=8):
|
197 |
+
text_input = gr.Textbox(
|
198 |
+
placeholder="Type your question here | اكتب سؤالك هنا",
|
199 |
+
label="",
|
200 |
+
elem_id="chat-input"
|
201 |
+
)
|
202 |
+
with gr.Column(scale=1):
|
203 |
+
submit_btn = gr.Button("Send | إرسال", variant="primary")
|
204 |
+
|
205 |
+
with gr.Row(elem_classes="footer-section"):
|
206 |
+
gr.Markdown("© 2025 Omdurman National Bank. All Rights Reserved. | جميع الحقوق محفوظة لبنك أم درمان الوطني ٢٠٢٥ ©")
|
207 |
+
|
208 |
+
# Update language state when language is changed
|
209 |
+
def update_language(lang):
|
210 |
+
if lang == "العربية":
|
211 |
+
return "ar"
|
212 |
+
else:
|
213 |
+
return "en"
|
214 |
+
|
215 |
+
language_btn.change(
|
216 |
+
fn=update_language,
|
217 |
+
inputs=language_btn,
|
218 |
+
outputs=selected_lang
|
219 |
+
)
|
220 |
+
|
221 |
+
# Handle message submission
|
222 |
+
def on_submit(message, chat_history, lang):
|
223 |
+
if not message.strip():
|
224 |
+
return "", chat_history
|
225 |
+
|
226 |
+
# Add user message to chat history
|
227 |
+
chat_history.append([message, None])
|
228 |
|
229 |
+
# Get response
|
230 |
+
responses = respond(message)
|
231 |
|
232 |
+
# Select response based on language
|
233 |
+
response = responses[lang]
|
234 |
|
235 |
+
# Update bot response in chat history
|
236 |
+
chat_history[-1][1] = response
|
237 |
|
238 |
+
return "", chat_history
|
239 |
+
|
240 |
+
# Link inputs and button to response function
|
241 |
+
submit_btn.click(
|
242 |
+
fn=on_submit,
|
243 |
+
inputs=[text_input, chat_box, selected_lang],
|
244 |
+
outputs=[text_input, chat_box]
|
245 |
+
)
|
246 |
+
|
247 |
+
# Also trigger on Enter key
|
248 |
+
text_input.submit(
|
249 |
+
fn=on_submit,
|
250 |
+
inputs=[text_input, chat_box, selected_lang],
|
251 |
+
outputs=[text_input, chat_box]
|
252 |
+
)
|
253 |
|
254 |
if __name__ == "__main__":
|
255 |
demo.launch(
|