Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -1,363 +1,99 @@
|
|
1 |
import gradio as gr
|
2 |
-
import
|
3 |
-
import json
|
4 |
-
import time
|
5 |
-
from datetime import datetime
|
6 |
|
7 |
-
#
|
8 |
-
|
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 |
-
#
|
15 |
-
|
16 |
-
from transformers import pipeline
|
17 |
-
arabic_nlp = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
|
18 |
-
ARABIC_NLP_AVAILABLE = True
|
19 |
-
|
20 |
-
def detect_language_with_nlp(text):
|
21 |
-
result = arabic_nlp(text)
|
22 |
-
return result[0]['label']
|
23 |
-
except ImportError:
|
24 |
-
ARABIC_NLP_AVAILABLE = False
|
25 |
-
|
26 |
-
# Import customer service enhancements
|
27 |
-
try:
|
28 |
-
from customer_service_enhancements import (
|
29 |
-
ENHANCED_CUSTOMER_SERVICE_PHRASES_AR,
|
30 |
-
ENHANCED_CUSTOMER_SERVICE_PHRASES_EN,
|
31 |
-
BANKING_FAQS_AR,
|
32 |
-
BANKING_FAQS_EN,
|
33 |
-
BANKING_GLOSSARY_AR,
|
34 |
-
BANKING_GLOSSARY_EN,
|
35 |
-
get_enhanced_response,
|
36 |
-
handle_banking_faq,
|
37 |
-
offer_satisfaction_survey,
|
38 |
-
get_banking_term_definition
|
39 |
-
)
|
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 |
-
|
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 |
-
|
68 |
-
|
69 |
-
"
|
70 |
-
"
|
71 |
-
"
|
72 |
-
"
|
73 |
-
"
|
74 |
-
"
|
75 |
-
"
|
76 |
-
"
|
|
|
77 |
}
|
78 |
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
{"text": "تحويل الأموال", "intent": "transfer"},
|
85 |
-
{"text": "فتح حساب جديد", "intent": "new_account"},
|
86 |
-
{"text": "أسعار الفائدة", "intent": "interest_rates"},
|
87 |
-
{"text": "مواقع الفروع", "intent": "branches"},
|
88 |
-
{"text": "ساعات العمل", "intent": "working_hours"},
|
89 |
-
{"text": "اتصل بنا", "intent": "contact"}
|
90 |
-
]
|
91 |
-
|
92 |
-
QUICK_ACTIONS_EN = [
|
93 |
-
{"text": "Check Balance", "intent": "balance"},
|
94 |
-
{"text": "Report Lost Card", "intent": "lost_card"},
|
95 |
-
{"text": "Loan Information", "intent": "loan"},
|
96 |
-
{"text": "Transfer Funds", "intent": "transfer"},
|
97 |
-
{"text": "Open New Account", "intent": "new_account"},
|
98 |
-
{"text": "Interest Rates", "intent": "interest_rates"},
|
99 |
-
{"text": "Branch Locations", "intent": "branches"},
|
100 |
-
{"text": "Working Hours", "intent": "working_hours"},
|
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":
|
108 |
-
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_AR[category])
|
109 |
-
else:
|
110 |
-
return random.choice(ENHANCED_CUSTOMER_SERVICE_PHRASES_EN[category])
|
111 |
|
112 |
def classify_intent(message: str):
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
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:
|
123 |
-
return intent_key
|
124 |
-
|
125 |
-
return "unknown"
|
126 |
|
127 |
-
# Function to log customer interactions
|
128 |
-
def log_interaction(user_message, bot_response, intent, language):
|
129 |
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
130 |
-
log_entry = {
|
131 |
-
"timestamp": timestamp,
|
132 |
-
"user_message": user_message,
|
133 |
-
"bot_response": bot_response,
|
134 |
-
"intent": intent,
|
135 |
-
"language": language
|
136 |
-
}
|
137 |
-
|
138 |
-
try:
|
139 |
-
with open("interaction_logs.jsonl", "a") as f:
|
140 |
-
f.write(json.dumps(log_entry) + "\n")
|
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 {
|
148 |
-
"ar": "الرجاء كتابة سؤالك.",
|
149 |
-
"en": "Please type your question."
|
150 |
-
}
|
151 |
-
|
152 |
# Detect language
|
153 |
-
|
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 |
-
#
|
170 |
-
if
|
171 |
-
|
172 |
-
responses["en"] = MENU_EN
|
173 |
-
log_interaction(message, responses[language], "menu", language)
|
174 |
-
return responses
|
175 |
|
176 |
-
#
|
177 |
-
|
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 |
-
#
|
195 |
if intent != "unknown":
|
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 |
-
# Add user message to chat history
|
230 |
-
chat_history = chat_history + [[message, None]]
|
231 |
-
|
232 |
-
# Get response
|
233 |
-
responses = respond(message)
|
234 |
-
|
235 |
-
# Select response based on language
|
236 |
-
response = responses[lang]
|
237 |
-
|
238 |
-
# Personalize response if name is available
|
239 |
-
if name and CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
240 |
-
if lang == "ar":
|
241 |
-
response = response.replace("مرحبًا", f"مرحبًا {name}")
|
242 |
-
else:
|
243 |
-
response = response.replace("Welcome", f"Welcome {name}")
|
244 |
-
response = response.replace("Hello", f"Hello {name}")
|
245 |
-
|
246 |
-
# Update bot response in chat history
|
247 |
-
chat_history[-1][1] = response
|
248 |
-
|
249 |
-
return "", chat_history, name
|
250 |
-
|
251 |
-
# Function to show menu
|
252 |
-
def show_menu(chat_history, lang):
|
253 |
-
menu_responses = {
|
254 |
-
"ar": MENU_AR,
|
255 |
-
"en": MENU_EN
|
256 |
-
}
|
257 |
-
|
258 |
-
# Get menu text
|
259 |
-
menu_text = menu_responses[lang]
|
260 |
-
|
261 |
-
# Add system message showing the menu
|
262 |
-
chat_history = chat_history + [[None, menu_text.replace("\n", "<br>")]]
|
263 |
-
|
264 |
-
return chat_history
|
265 |
-
|
266 |
-
# Function to connect to live agent
|
267 |
-
def connect_to_live_agent(chat_history, lang):
|
268 |
-
message = "Connecting to a live customer service agent. Please wait a moment..." if lang == "en" else "جاري الاتصال بوكيل خدمة العملاء. يرجى الانتظار لحظة..."
|
269 |
-
chat_history = chat_history + [[None, message]]
|
270 |
-
return chat_history
|
271 |
-
|
272 |
-
# Function to show satisfaction survey
|
273 |
-
def show_satisfaction_survey(chat_history, lang):
|
274 |
-
if CUSTOMER_SERVICE_ENHANCEMENTS_AVAILABLE:
|
275 |
-
survey_html = offer_satisfaction_survey(lang)
|
276 |
-
chat_history = chat_history + [[None, survey_html]]
|
277 |
-
else:
|
278 |
-
# Simple survey message if enhancements not available
|
279 |
-
title = "استطلاع رضا العملاء" if lang == "ar" else "Customer Satisfaction Survey"
|
280 |
-
message = f"<div class='satisfaction-survey'><h3>{title}</h3><p>{'نشكرك على استخدام المساعد المصرفي الافتراضي!' if lang == 'ar' else 'Thank you for using our virtual banking assistant!'}</p></div>"
|
281 |
-
chat_history = chat_history + [[None, message]]
|
282 |
-
|
283 |
-
return chat_history
|
284 |
-
|
285 |
-
# Function to reset chat
|
286 |
-
def reset_chat():
|
287 |
-
return [], None # Clear chat history and reset user name
|
288 |
-
|
289 |
-
# Function to initialize chat with welcome message
|
290 |
-
def init_chat():
|
291 |
-
welcome_ar = "مرحبًا بك في المساعد المصرفي الافتراضي لبنك أم درمان الوطني! يمكنك طرح أي سؤال حول خدماتنا المصرفية أو استخدام أزرار الإجراءات السريعة أدناه."
|
292 |
-
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."
|
293 |
-
|
294 |
-
# Initialize chat with welcome messages
|
295 |
-
chat_history = []
|
296 |
-
chat_history.append([None, welcome_ar])
|
297 |
-
chat_history.append([None, welcome_en])
|
298 |
-
|
299 |
-
return chat_history
|
300 |
-
|
301 |
-
# Gradio Interface
|
302 |
-
with gr.Blocks() as demo:
|
303 |
-
selected_lang = gr.State(value="ar")
|
304 |
-
user_name = gr.State(value=None)
|
305 |
-
|
306 |
-
with gr.Row():
|
307 |
-
gr.Markdown("# Omdurman National Bank Virtual Assistant")
|
308 |
-
|
309 |
-
with gr.Row():
|
310 |
-
language_btn = gr.Radio(["العربية", "English"], value="العربية", label="Language")
|
311 |
-
|
312 |
-
chatbot = gr.Chatbot(height=400, type="messages") # Updated to use the new format
|
313 |
-
|
314 |
-
with gr.Row():
|
315 |
-
text_input = gr.Textbox(placeholder="Type your question here", label="")
|
316 |
-
submit_btn = gr.Button("Send", variant="primary")
|
317 |
-
|
318 |
-
with gr.Row():
|
319 |
-
menu_btn = gr.Button("Show Menu")
|
320 |
-
live_agent_btn = gr.Button("Connect to Live Agent")
|
321 |
-
survey_btn = gr.Button("Feedback")
|
322 |
-
reset_btn = gr.Button("Reset Chat")
|
323 |
-
|
324 |
-
# Link inputs and buttons to response functions
|
325 |
-
submit_btn.click(
|
326 |
-
fn=on_submit,
|
327 |
-
inputs=[text_input, chatbot, selected_lang, user_name],
|
328 |
-
outputs=[text_input, chatbot, user_name]
|
329 |
-
)
|
330 |
-
|
331 |
-
menu_btn.click(
|
332 |
-
fn=show_menu,
|
333 |
-
inputs=[chatbot, selected_lang],
|
334 |
-
outputs=[chatbot]
|
335 |
-
)
|
336 |
-
|
337 |
-
live_agent_btn.click(
|
338 |
-
fn=connect_to_live_agent,
|
339 |
-
inputs=[chatbot, selected_lang],
|
340 |
-
outputs=[chatbot]
|
341 |
-
)
|
342 |
-
|
343 |
-
survey_btn.click(
|
344 |
-
fn=show_satisfaction_survey,
|
345 |
-
inputs=[chatbot, selected_lang],
|
346 |
-
outputs=[chatbot]
|
347 |
-
)
|
348 |
-
|
349 |
-
reset_btn.click(
|
350 |
-
fn=reset_chat,
|
351 |
-
inputs=[],
|
352 |
-
outputs=[chatbot, user_name]
|
353 |
-
)
|
354 |
-
|
355 |
-
# Initialize chat
|
356 |
-
demo.load(
|
357 |
-
fn=init_chat,
|
358 |
-
inputs=[],
|
359 |
-
outputs=[chatbot]
|
360 |
-
)
|
361 |
|
362 |
if __name__ == "__main__":
|
363 |
-
demo.launch(
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
from transformers import pipeline
|
|
|
|
|
|
|
3 |
|
4 |
+
# Load Arabic NLP model for intent classification
|
5 |
+
intent_classifier = pipeline("text-classification", model="aubmindlab/bert-base-arabertv02")
|
|
|
|
|
|
|
|
|
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 |
+
ONB_GUIDELINES = {
|
12 |
"balance": "يمكنك التحقق من رصيدك عبر الإنترنت أو عبر تطبيق الهاتف الخاص ببنك أم درمان الوطني.",
|
13 |
"lost_card": "في حالة فقدان البطاقة، اتصل بالرقم 249-123-456-789 فورًا.",
|
14 |
"loan": "شروط القرض تشمل الحد الأدنى للدخل (5000 جنيه سوداني) وتاريخ ائتماني جيد.",
|
15 |
"transfer": "لتحويل الأموال، استخدم تطبيق الهاتف أو الخدمة المصرفية عبر الإنترنت.",
|
16 |
"new_account": "لفتح حساب جديد، قم بزيارة أقرب فرع مع جواز سفرك أو هويتك الوطنية.",
|
17 |
"interest_rates": "أسعار الفائدة على الودائع تتراوح بين 5% إلى 10% سنويًا.",
|
18 |
+
"branches": "فروعنا موجودة في أم درمان، الخرطوم، وبورتسودان. زيارة موقعنا للتفاصيل.",
|
19 |
"working_hours": "ساعات العمل من 8 صباحًا إلى 3 مساءً من الأحد إلى الخميس.",
|
20 |
"contact": "الاتصال بنا على الرقم 249-123-456-789 أو عبر البريد الإلكتروني [email protected]."
|
21 |
}
|
22 |
|
23 |
+
# Map intents to responses
|
24 |
+
INTENT_TO_RESPONSE = {
|
25 |
+
"balance": "balance",
|
26 |
+
"lost_card": "lost_card",
|
27 |
+
"loan": "loan",
|
28 |
+
"transfer": "transfer",
|
29 |
+
"new_account": "new_account",
|
30 |
+
"interest_rates": "interest_rates",
|
31 |
+
"branches": "branches",
|
32 |
+
"working_hours": "working_hours",
|
33 |
+
"contact": "contact"
|
34 |
}
|
35 |
|
36 |
+
def detect_language(text):
|
37 |
+
# Use Hugging Face language detection model
|
38 |
+
result = language_detector(text)
|
39 |
+
language = result[0]['label']
|
40 |
+
return language
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
def classify_intent(message: str):
|
43 |
+
# Use NLP model to classify the user's intent
|
44 |
+
result = intent_classifier(message)
|
45 |
+
intent = result[0]['label']
|
46 |
+
return INTENT_TO_RESPONSE.get(intent, "unknown")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
def respond(message: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
# Detect language
|
50 |
+
language = detect_language(message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
+
# If the language is not Arabic, return a default response
|
53 |
+
if language != "ar":
|
54 |
+
return "عذرًا، هذا المساعد يدعم اللغة العربية فقط. الرجاء إعادة الصياغة بالعربية."
|
|
|
|
|
|
|
55 |
|
56 |
+
# Classify the user's intent using NLP
|
57 |
+
intent = classify_intent(message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
+
# If intent is recognized, return the corresponding response
|
60 |
if intent != "unknown":
|
61 |
+
return ONB_GUIDELINES.get(intent, "عذرًا، لم يتم التعرف على الخيار المحدد.")
|
62 |
+
|
63 |
+
# Fallback to keyword matching if NLP doesn't recognize the intent
|
64 |
+
for keyword, key in INTENT_TO_RESPONSE.items():
|
65 |
+
if keyword in message:
|
66 |
+
return ONB_GUIDELINES.get(key, "عذرًا، لم يتم التعرف على الخيار المحدد.")
|
67 |
+
|
68 |
+
# Default response if no intent or keyword is matched
|
69 |
+
return "عذرًا، لم أفهم سؤالك. الرجاء إعادة الصياغة أو اختيار أحد الخيارات التالية: " + ", ".join(INTENT_TO_RESPONSE.keys())
|
70 |
+
|
71 |
+
# Chat interface
|
72 |
+
with gr.Blocks(css=".gradio-container {direction: rtl;}") as demo:
|
73 |
+
gr.Markdown("# <center>بنك أم درمان الوطني - المساعد المصرفي</center>")
|
74 |
+
|
75 |
+
with gr.Tab("المحادثة"):
|
76 |
+
gr.Markdown("## اكتب سؤالك هنا:")
|
77 |
+
|
78 |
+
# Text input
|
79 |
+
text_input = gr.Textbox(label="السؤال")
|
80 |
+
|
81 |
+
# Submit button
|
82 |
+
submit_btn = gr.Button("إرسال")
|
83 |
+
|
84 |
+
# Output textbox for responses
|
85 |
+
output = gr.Textbox(label="الرد", interactive=False)
|
86 |
+
|
87 |
+
# Link inputs and button to response function
|
88 |
+
submit_btn.click(
|
89 |
+
fn=respond,
|
90 |
+
inputs=text_input,
|
91 |
+
outputs=output
|
92 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
if __name__ == "__main__":
|
95 |
+
demo.launch(
|
96 |
+
server_name="0.0.0.0",
|
97 |
+
server_port=7860,
|
98 |
+
share=True # Enable public link
|
99 |
+
)
|