Muhammadidrees commited on
Commit
d2f95f3
·
verified ·
1 Parent(s): dea85f3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +524 -0
app.py ADDED
@@ -0,0 +1,524 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from groq import Groq
3
+ from datetime import datetime
4
+ from reportlab.lib.pagesizes import A4
5
+ from reportlab.lib.units import inch
6
+ from reportlab.lib import colors
7
+ from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
8
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
9
+ from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY, TA_RIGHT
10
+ import tempfile
11
+
12
+ # ==============================
13
+ # Initialize Groq client
14
+ # ==============================
15
+ client = Groq(api_key="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")
16
+
17
+ # ==============================
18
+ # Language Configuration
19
+ # ==============================
20
+ LANGUAGES = {
21
+ "english": {
22
+ "code": "en",
23
+ "name": "English",
24
+ "system_prompt": """
25
+ You are Dr. HealBot, a calm, knowledgeable, and empathetic virtual doctor.
26
+
27
+ GOAL:
28
+ Hold a natural, focused conversation with the patient to understand their health issue and offer helpful preliminary medical guidance.
29
+
30
+ CONVERSATION LOGIC:
31
+ - Ask only relevant and concise medical questions necessary for diagnosing the illness.
32
+ - Each question should help clarify symptoms or narrow possible causes.
33
+ - Stop asking once enough information is collected for a basic assessment.
34
+ - Then, provide a structured, friendly, and visually clear medical response using headings, emojis, and bullet points.
35
+
36
+ FINAL RESPONSE FORMAT:
37
+ 🩺 **Based on what you've told me...**
38
+ Brief summary of what the patient described.
39
+
40
+ 💡 **Possible Causes (Preliminary)**
41
+ - List 1–2 possible conditions using phrases like "It could be" or "This sounds like".
42
+
43
+ 💊 **Suggested Over-the-Counter Medicines**
44
+ - Generic medicine names only.
45
+ - Mention to check packaging or consult a pharmacist for dosage confirmation.
46
+
47
+ 🥗 **Lifestyle & Home Care Tips**
48
+ - 2–3 practical suggestions.
49
+
50
+ ⚠️ **When to See a Real Doctor**
51
+ - 2–3 warning signs or conditions when urgent medical care is needed.
52
+
53
+ 📅 **Follow-Up Advice**
54
+ - Brief recommendation for self-care or follow-up timing.
55
+
56
+ TONE & STYLE:
57
+ - Speak like a real, caring doctor — short, clear, and empathetic.
58
+ - Use plain language, no jargon.
59
+ - Only one question per turn unless clarification is essential.
60
+ - Keep tone warm, calm, and professional.
61
+
62
+ IMPORTANT:
63
+ - Always emphasize that this is preliminary guidance.
64
+ - Never make definitive diagnoses.
65
+ - For severe symptoms, immediately advise seeking emergency care.
66
+ """,
67
+ "initial_message": "👋 Hello! I'm **Dr. HealBot**. How can I help you today? Please describe your main concern or symptom.",
68
+ "consultation_complete": "✅ **Consultation complete!** You can now export this as a PDF or start a new consultation.",
69
+ "placeholder": "💬 Describe your symptoms (e.g., 'I have a fever and headache for 3 days')...",
70
+ "send_btn": "Send 📤",
71
+ "new_consultation": "🔄 New Consultation",
72
+ "export_pdf": "💾 Export PDF",
73
+ "title": "Dr. HealBot - AI Medical Consultant",
74
+ "subtitle": "Your AI Medical Consultation Assistant",
75
+ "pdf_label": "📄 Download Consultation Report",
76
+ "language_label": "Language / اللغة",
77
+ "pdf_title": "Dr. HealBot",
78
+ "pdf_subtitle": "AI Medical Consultation Summary",
79
+ "pdf_disclaimer_title": "IMPORTANT MEDICAL DISCLAIMER",
80
+ "pdf_disclaimer_text": "This consultation provides preliminary AI-generated medical guidance and is NOT a substitute for professional medical care. Always consult a licensed healthcare provider for accurate diagnosis and treatment. In case of emergency, call emergency services immediately.",
81
+ "pdf_transcript": "Consultation Transcript",
82
+ "pdf_patient": "Patient:",
83
+ "pdf_doctor": "Dr. HealBot:",
84
+ "pdf_footer1": "This document is confidential and for personal reference only.",
85
+ "pdf_footer2": "© 2025 Dr. HealBot - AI Medical Consultation Tool"
86
+ },
87
+ "arabic": {
88
+ "code": "ar",
89
+ "name": "العربية",
90
+ "system_prompt": """
91
+ أنت دكتور هيل بوت، طبيب افتراضي هادئ وذو معرفة واسعة ومتعاطف.
92
+
93
+ الهدف:
94
+ إجراء محادثة طبيعية ومركزة مع المريض لفهم مشكلته الصحية وتقديم إرشادات طبية أولية مفيدة.
95
+
96
+ منطق المحادثة:
97
+ - اطرح فقط الأسئلة الطبية ذات الصلة والموجزة اللازمة لتشخيص المرض.
98
+ - يجب أن يساعد كل سؤال في توضيح الأعراض أو تضييق الأسباب المحتملة.
99
+ - توقف عن طرح الأسئلة بمجرد جمع معلومات كافية للتقييم الأساسي.
100
+ - بعد ذلك، قدم استجابة طبية منظمة وودية وواضحة بصريًا باستخدام العناوين والرموز التعبيرية والنقاط.
101
+
102
+ صيغة الاستجابة النهائية:
103
+ 🩺 **بناءً على ما أخبرتني به...**
104
+ ملخص موجز لما ��صفه المريض.
105
+
106
+ 💡 **الأسباب المحتملة (أولية)**
107
+ - اذكر 1-2 من الحالات المحتملة باستخدام عبارات مثل "قد يكون" أو "يبدو أن هذا".
108
+
109
+ 💊 **الأدوية المقترحة بدون وصفة طبية**
110
+ - أسماء الأدوية العامة فقط.
111
+ - اذكر ضرورة التحقق من العبوة أو استشارة الصيدلي لتأكيد الجرعة.
112
+
113
+ 🥗 **نصائح نمط الحياة والرعاية المنزلية**
114
+ - 2-3 اقتراحات عملية.
115
+
116
+ ⚠️ **متى يجب زيارة طبيب حقيقي**
117
+ - 2-3 علامات تحذيرية أو حالات تتطلب رعاية طبية عاجلة.
118
+
119
+ 📅 **نصائح المتابعة**
120
+ - توصية موجزة للرعاية الذاتية أو توقيت المتابعة.
121
+
122
+ الأسلوب والنبرة:
123
+ - تحدث كطبيب حقيقي ومهتم - قصير وواضح ومتعاطف.
124
+ - استخدم لغة بسيطة، بدون مصطلحات معقدة.
125
+ - سؤال واحد فقط في كل دورة ما لم يكن التوضيح ضروريًا.
126
+ - حافظ على نبرة دافئة وهادئة ومهنية.
127
+
128
+ مهم:
129
+ - أكد دائمًا أن هذا إرشاد أولي.
130
+ - لا تقدم تشخيصات نهائية أبدًا.
131
+ - للأعراض الشديدة، انصح فورًا بطلب الرعاية الطارئة.
132
+
133
+ يجب أن تكون جميع إجاباتك باللغة العربية.
134
+ """,
135
+ "initial_message": "👋 مرحباً! أنا **دكتور هيل بوت**. كيف يمكنني مساعدتك اليوم؟ من فضلك صف مشكلتك الرئيسية أو العَرَض.",
136
+ "consultation_complete": "✅ **اكتملت الاستشارة!** يمكنك الآن تصدير هذا كملف PDF أو بدء استشارة جديدة.",
137
+ "placeholder": "💬 صف أعراضك (مثال: 'لدي حمى وصداع منذ 3 أيام')...",
138
+ "send_btn": "إرسال 📤",
139
+ "new_consultation": "🔄 استشارة جديدة",
140
+ "export_pdf": "💾 تصدير PDF",
141
+ "title": "دكتور هيل بوت - استشارة طبية بالذكاء الاصطناعي",
142
+ "subtitle": "مساعدك الطبي بالذكاء الاصطناعي",
143
+ "pdf_label": "📄 تحميل تقرير الاستشارة",
144
+ "language_label": "اللغة / Language",
145
+ "pdf_title": "دكتور هيل بوت",
146
+ "pdf_subtitle": "ملخص الاستشارة الطبية بالذكاء الاصطناعي",
147
+ "pdf_disclaimer_title": "إخلاء المسؤولية الطبية المهم",
148
+ "pdf_disclaimer_text": "توفر هذه الاستشارة إرشادات طبية أولية مُنتَجة بالذكاء الاصطناعي وليست بديلاً عن الرعاية الطبية المهنية. استشر دائمًا مقدم رعاية صحية مرخصًا للحصول على تشخيص ودواء دقيق. في حالة الطوارئ، اتصل بخدمات الطوارئ فورًا.",
149
+ "pdf_transcript": "نص الاستشارة",
150
+ "pdf_patient": "المريض:",
151
+ "pdf_doctor": "دكتور هيل بوت:",
152
+ "pdf_footer1": "هذا المستند سري وللاستخدام الشخصي فقط.",
153
+ "pdf_footer2": "© 2025 دكتور هيل بوت - أداة الاستشارة الطبية بالذكاء الاصطناعي"
154
+ }
155
+ }
156
+
157
+ # ==============================
158
+ # Chat Logic (Now with per-user state)
159
+ # ==============================
160
+ def chat_with_doctor(message, history, language):
161
+ """Process user message and generate AI response"""
162
+ if not message.strip():
163
+ return history, ""
164
+
165
+ lang_config = LANGUAGES[language]
166
+
167
+ # Build message history
168
+ messages = [{"role": "system", "content": lang_config["system_prompt"]}]
169
+ for chat in history:
170
+ if isinstance(chat, (list, tuple)) and len(chat) == 2:
171
+ if chat[0] and chat[0] != "(System)" and not chat[0].startswith("✅"):
172
+ messages.append({"role": "user", "content": chat[0]})
173
+ if chat[1] and chat[1] != "(System)" and not chat[1].startswith("✅"):
174
+ messages.append({"role": "assistant", "content": chat[1]})
175
+
176
+ messages.append({"role": "user", "content": message})
177
+
178
+ try:
179
+ # Count patient turns
180
+ patient_turns = sum(1 for chat in history
181
+ if isinstance(chat, (list, tuple))
182
+ and chat[0]
183
+ and chat[0] != "(System)"
184
+ and not chat[0].startswith("✅"))
185
+
186
+ # After 4-5 exchanges, encourage conclusion
187
+ if patient_turns >= 4:
188
+ messages.append({
189
+ "role": "system",
190
+ "content": "You have gathered sufficient information. Provide your complete structured medical assessment now."
191
+ })
192
+
193
+ # API call
194
+ chat_completion = client.chat.completions.create(
195
+ messages=messages,
196
+ model="llama-3.3-70b-versatile",
197
+ temperature=0.7,
198
+ max_tokens=800,
199
+ top_p=0.9,
200
+ )
201
+
202
+ response = chat_completion.choices[0].message.content.strip()
203
+ history.append([message, response])
204
+
205
+ # Detect completion
206
+ if "🩺" in response and ("Based on what you've told me" in response or "بناءً على ما أخبرتني به" in response):
207
+ history.append([None, lang_config["consultation_complete"]])
208
+
209
+ return history, "" # Return empty string to clear input
210
+
211
+ except Exception as e:
212
+ error_message = f"⚠️ **Error:** {str(e)}"
213
+ history.append([message, error_message])
214
+ return history, ""
215
+
216
+
217
+ def reset_conversation(language):
218
+ """Reset conversation"""
219
+ lang_config = LANGUAGES[language]
220
+ return [[None, lang_config["initial_message"]]]
221
+
222
+
223
+ def change_language(language):
224
+ """Change interface language"""
225
+ lang_config = LANGUAGES[language]
226
+
227
+ return (
228
+ [[None, lang_config["initial_message"]]], # chatbot
229
+ gr.update(placeholder=lang_config["placeholder"]), # msg
230
+ gr.update(value=lang_config["send_btn"]), # submit_btn
231
+ gr.update(value=lang_config["new_consultation"]), # clear_btn
232
+ gr.update(value=lang_config["export_pdf"]), # export_btn
233
+ gr.update(label=lang_config["pdf_label"]), # pdf_output
234
+ )
235
+
236
+
237
+ # ==============================
238
+ # PDF Export
239
+ # ==============================
240
+ def export_conversation_to_pdf(history, language):
241
+ """Generate PDF with Arabic support"""
242
+ if not history or len(history) <= 1:
243
+ return None
244
+
245
+ lang_config = LANGUAGES[language]
246
+ is_rtl = (language == "arabic")
247
+
248
+ temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf", mode='wb')
249
+ pdf_path = temp_pdf.name
250
+ temp_pdf.close()
251
+
252
+ doc = SimpleDocTemplate(
253
+ pdf_path,
254
+ pagesize=A4,
255
+ rightMargin=0.75*inch,
256
+ leftMargin=0.75*inch,
257
+ topMargin=0.75*inch,
258
+ bottomMargin=0.75*inch,
259
+ )
260
+
261
+ elements = []
262
+ styles = getSampleStyleSheet()
263
+
264
+ title_align = TA_CENTER
265
+ text_align = TA_RIGHT if is_rtl else TA_JUSTIFY
266
+
267
+ title_style = ParagraphStyle(
268
+ 'CustomTitle',
269
+ parent=styles['Heading1'],
270
+ fontSize=24,
271
+ textColor=colors.HexColor('#1e40af'),
272
+ spaceAfter=6,
273
+ alignment=title_align,
274
+ fontName='Helvetica-Bold'
275
+ )
276
+
277
+ subtitle_style = ParagraphStyle(
278
+ 'CustomSubtitle',
279
+ parent=styles['Normal'],
280
+ fontSize=11,
281
+ textColor=colors.HexColor('#4b5563'),
282
+ alignment=title_align,
283
+ spaceAfter=20
284
+ )
285
+
286
+ heading_style = ParagraphStyle(
287
+ 'CustomHeading',
288
+ parent=styles['Heading2'],
289
+ fontSize=13,
290
+ textColor=colors.HexColor('#1e40af'),
291
+ spaceAfter=10,
292
+ spaceBefore=12,
293
+ fontName='Helvetica-Bold',
294
+ alignment=text_align
295
+ )
296
+
297
+ content_style = ParagraphStyle(
298
+ 'Content',
299
+ parent=styles['Normal'],
300
+ fontSize=9,
301
+ leftIndent=35 if not is_rtl else 0,
302
+ rightIndent=0 if not is_rtl else 35,
303
+ spaceAfter=10,
304
+ alignment=text_align,
305
+ )
306
+
307
+ # Header
308
+ elements.append(Paragraph(lang_config["pdf_title"], title_style))
309
+ elements.append(Paragraph(lang_config["pdf_subtitle"], subtitle_style))
310
+
311
+ # Metadata
312
+ metadata = [
313
+ ['Generated:', datetime.now().strftime('%B %d, %Y at %I:%M %p')],
314
+ ['Document Type:', 'AI Medical Consultation Record'],
315
+ ]
316
+
317
+ metadata_table = Table(metadata, colWidths=[2.5*inch, 3.5*inch])
318
+ metadata_table.setStyle(TableStyle([
319
+ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f0f4f8')),
320
+ ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
321
+ ('FONTSIZE', (0, 0), (-1, -1), 9),
322
+ ('PADDING', (0, 0), (-1, -1), 8),
323
+ ('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor('#e0e0e0')),
324
+ ]))
325
+ elements.append(metadata_table)
326
+ elements.append(Spacer(1, 0.2*inch))
327
+
328
+ # Disclaimer
329
+ disclaimer_style = ParagraphStyle(
330
+ 'Disclaimer',
331
+ parent=styles['Normal'],
332
+ fontSize=9,
333
+ textColor=colors.HexColor('#dc2626'),
334
+ alignment=title_align,
335
+ fontName='Helvetica-Bold',
336
+ spaceAfter=8
337
+ )
338
+ elements.append(Paragraph(f"⚠️ {lang_config['pdf_disclaimer_title']}", disclaimer_style))
339
+
340
+ disclaimer_text_style = ParagraphStyle(
341
+ 'DisclaimerText',
342
+ parent=styles['Normal'],
343
+ fontSize=8,
344
+ textColor=colors.HexColor('#991b1b'),
345
+ alignment=text_align,
346
+ spaceAfter=15
347
+ )
348
+ elements.append(Paragraph(lang_config['pdf_disclaimer_text'], disclaimer_text_style))
349
+
350
+ # Transcript
351
+ elements.append(Paragraph(f"📋 {lang_config['pdf_transcript']}", heading_style))
352
+
353
+ for user_msg, bot_msg in history:
354
+ if user_msg and user_msg is not None and not user_msg.startswith("✅"):
355
+ elements.append(Paragraph(f"👤 <b>{lang_config['pdf_patient']}</b>", content_style))
356
+ elements.append(Paragraph(user_msg, content_style))
357
+
358
+ if bot_msg and bot_msg is not None and not bot_msg.startswith("✅"):
359
+ elements.append(Paragraph(f"👨‍⚕️ <b>{lang_config['pdf_doctor']}</b>", content_style))
360
+ elements.append(Paragraph(bot_msg, content_style))
361
+
362
+ # Footer
363
+ elements.append(Spacer(1, 0.3*inch))
364
+ footer_style = ParagraphStyle(
365
+ 'Footer',
366
+ parent=styles['Normal'],
367
+ fontSize=8,
368
+ textColor=colors.HexColor('#6b7280'),
369
+ alignment=title_align,
370
+ )
371
+ elements.append(Paragraph(lang_config['pdf_footer1'], footer_style))
372
+ elements.append(Paragraph(lang_config['pdf_footer2'], footer_style))
373
+
374
+ doc.build(elements)
375
+ return pdf_path
376
+
377
+
378
+ def handle_export_pdf(history, language):
379
+ pdf_path = export_conversation_to_pdf(history, language)
380
+ return gr.update(value=pdf_path, visible=True) if pdf_path else gr.update(visible=False)
381
+
382
+
383
+ # ==============================
384
+ # CSS
385
+ # ==============================
386
+ custom_css = """
387
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
388
+ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@400;500;600;700&display=swap');
389
+
390
+ .gradio-container {
391
+ font-family: 'Inter', 'Noto Sans Arabic', sans-serif;
392
+ max-width: 950px !important;
393
+ margin: 0 auto !important;
394
+ padding: 20px !important;
395
+ background-color: #f9fafb;
396
+ }
397
+
398
+ #chatbot {
399
+ height: 60vh !important;
400
+ border-radius: 16px;
401
+ border: 1.5px solid #e5e7eb;
402
+ box-shadow: 0 4px 12px rgba(0,0,0,0.05);
403
+ background: white;
404
+ }
405
+
406
+ .rtl { direction: rtl; text-align: right; }
407
+ footer { display: none !important; }
408
+
409
+ @media (max-width: 768px) {
410
+ #chatbot { height: 70vh !important; }
411
+ }
412
+ """
413
+
414
+ # ==============================
415
+ # Gradio Interface with Session State
416
+ # ==============================
417
+ with gr.Blocks(css=custom_css, title="Dr. HealBot") as demo:
418
+ # CRITICAL: Use gr.State() for per-user session data
419
+ chat_history = gr.State([[None, LANGUAGES["english"]["initial_message"]]])
420
+
421
+ with gr.Row():
422
+ language_selector = gr.Radio(
423
+ choices=["english", "arabic"],
424
+ value="english",
425
+ label=LANGUAGES["english"]["language_label"],
426
+ interactive=True
427
+ )
428
+
429
+ title_md = gr.Markdown(
430
+ f"<h1 style='text-align:center; color:#1e40af;'>🏥 {LANGUAGES['english']['title']}</h1>"
431
+ f"<p style='text-align:center; color:#6b7280;'>{LANGUAGES['english']['subtitle']}</p>",
432
+ elem_id="title_section"
433
+ )
434
+
435
+ chatbot = gr.Chatbot(
436
+ elem_id="chatbot",
437
+ show_label=False,
438
+ type="tuples",
439
+ bubble_full_width=False,
440
+ render_markdown=True,
441
+ height=500,
442
+ show_copy_button=True,
443
+ rtl=False
444
+ )
445
+
446
+ with gr.Row():
447
+ msg = gr.Textbox(
448
+ placeholder=LANGUAGES["english"]["placeholder"],
449
+ show_label=False,
450
+ scale=8,
451
+ lines=2,
452
+ )
453
+ submit_btn = gr.Button(LANGUAGES["english"]["send_btn"], scale=1, variant="primary")
454
+
455
+ with gr.Row():
456
+ clear_btn = gr.Button(LANGUAGES["english"]["new_consultation"], variant="secondary")
457
+ export_btn = gr.Button(LANGUAGES["english"]["export_pdf"], variant="secondary")
458
+
459
+ pdf_output = gr.File(label=LANGUAGES["english"]["pdf_label"], visible=False)
460
+
461
+ # Event handlers - ALL use chat_history State
462
+ language_selector.change(
463
+ change_language,
464
+ inputs=[language_selector],
465
+ outputs=[chat_history, msg, submit_btn, clear_btn, export_btn, pdf_output]
466
+ ).then(
467
+ lambda h: h,
468
+ inputs=[chat_history],
469
+ outputs=[chatbot]
470
+ )
471
+
472
+ msg.submit(
473
+ chat_with_doctor,
474
+ inputs=[msg, chat_history, language_selector],
475
+ outputs=[chat_history, msg]
476
+ ).then(
477
+ lambda h: h,
478
+ inputs=[chat_history],
479
+ outputs=[chatbot]
480
+ )
481
+
482
+ submit_btn.click(
483
+ chat_with_doctor,
484
+ inputs=[msg, chat_history, language_selector],
485
+ outputs=[chat_history, msg]
486
+ ).then(
487
+ lambda h: h,
488
+ inputs=[chat_history],
489
+ outputs=[chatbot]
490
+ )
491
+
492
+ clear_btn.click(
493
+ reset_conversation,
494
+ inputs=[language_selector],
495
+ outputs=[chat_history]
496
+ ).then(
497
+ lambda h: h,
498
+ inputs=[chat_history],
499
+ outputs=[chatbot]
500
+ )
501
+
502
+ export_btn.click(
503
+ handle_export_pdf,
504
+ inputs=[chat_history, language_selector],
505
+ outputs=[pdf_output]
506
+ )
507
+
508
+ # Initialize chatbot display from state
509
+ demo.load(
510
+ lambda h: h,
511
+ inputs=[chat_history],
512
+ outputs=[chatbot]
513
+ )
514
+
515
+ # ==============================
516
+ # Launch
517
+ # ==============================
518
+ if __name__ == "__main__":
519
+ demo.launch(
520
+ share=True,
521
+ show_error=True,
522
+ server_name="0.0.0.0",
523
+ server_port=7860,
524
+ )