Blaiseboy commited on
Commit
02a841e
·
verified ·
1 Parent(s): d85cddc

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -638
app.py DELETED
@@ -1,638 +0,0 @@
1
- import gradio as gr
2
- import os
3
- import torch
4
- import re
5
- import json
6
- from transformers import AutoTokenizer, AutoModelForCausalLM
7
- import logging
8
-
9
- # Configure logging
10
- logging.basicConfig(level=logging.INFO)
11
- logger = logging.getLogger(__name__)
12
-
13
- class StandaloneMedicalChatbot:
14
- def __init__(self, use_gpu=False):
15
- """Standalone medical chatbot with built-in ML improvements"""
16
- self.use_gpu = use_gpu and torch.cuda.is_available()
17
- self.device = "cuda" if self.use_gpu else "cpu"
18
-
19
- # Initialize model components
20
- self.model = None
21
- self.tokenizer = None
22
- self.knowledge_chunks = []
23
-
24
- # Setup medical intelligence
25
- self.setup_medical_keywords()
26
- self.load_biomedical_model()
27
-
28
- def setup_medical_keywords(self):
29
- """Setup comprehensive medical keyword dictionaries"""
30
- self.medical_keywords = {
31
- 'symptoms': [
32
- 'fever', 'temperature', 'hot', 'cough', 'cold', 'headache', 'pain', 'ache',
33
- 'sore', 'swelling', 'rash', 'vomiting', 'nausea', 'diarrhea', 'fatigue',
34
- 'tired', 'breathing', 'breath', 'wheeze', 'sneeze', 'runny nose', 'congestion',
35
- 'itchy', 'burning', 'stinging', 'cramping', 'bloating', 'dizzy', 'weakness'
36
- ],
37
- 'conditions': [
38
- 'asthma', 'pneumonia', 'bronchitis', 'allergy', 'allergic', 'infection',
39
- 'flu', 'influenza', 'covid', 'coronavirus', 'strep', 'throat', 'ear infection',
40
- 'gastroenteritis', 'dehydration', 'constipation', 'reflux', 'eczema',
41
- 'dermatitis', 'chickenpox', 'measles', 'mumps', 'rubella', 'rsv'
42
- ],
43
- 'treatments': [
44
- 'medicine', 'medication', 'drug', 'antibiotic', 'paracetamol', 'acetaminophen',
45
- 'ibuprofen', 'aspirin', 'treatment', 'therapy', 'dose', 'dosage', 'prescription',
46
- 'vaccine', 'vaccination', 'immunization', 'shot', 'injection', 'remedy',
47
- 'cure', 'heal', 'recover', 'rest', 'fluids', 'hydration'
48
- ],
49
- 'anatomy': [
50
- 'head', 'chest', 'stomach', 'belly', 'throat', 'ear', 'eye', 'nose', 'mouth',
51
- 'skin', 'lung', 'lungs', 'heart', 'brain', 'kidney', 'liver', 'blood',
52
- 'bones', 'muscle', 'joint', 'neck', 'back', 'arm', 'leg', 'hand', 'foot'
53
- ],
54
- 'age_groups': [
55
- 'baby', 'babies', 'infant', 'toddler', 'child', 'children', 'pediatric',
56
- 'newborn', 'kid', 'kids', 'teenager', 'adolescent', 'preschooler',
57
- 'months', 'years', 'old', 'age', 'young', 'little'
58
- ],
59
- 'medical_context': [
60
- 'doctor', 'physician', 'pediatrician', 'hospital', 'clinic', 'nurse',
61
- 'diagnosis', 'symptom', 'symptoms', 'health', 'medical', 'care', 'urgent',
62
- 'emergency', 'when to call', 'normal', 'abnormal', 'healthy', 'sick',
63
- 'illness', 'disease', 'condition', 'problem', 'concern', 'help'
64
- ],
65
- 'emergency': [
66
- 'emergency', 'urgent', 'critical', 'severe', 'serious', 'dangerous',
67
- 'life threatening', 'call doctor', 'hospital', '911', 'ambulance',
68
- 'immediate', 'right away', 'cannot breathe', 'unconscious', 'seizure'
69
- ]
70
- }
71
-
72
- # Non-medical keywords
73
- self.non_medical_keywords = [
74
- 'weather', 'cooking', 'recipe', 'food', 'restaurant', 'movie', 'film',
75
- 'music', 'song', 'sports', 'football', 'basketball', 'game', 'play',
76
- 'travel', 'vacation', 'holiday', 'work', 'job', 'school', 'homework',
77
- 'money', 'shopping', 'buy', 'sell', 'car', 'vehicle', 'computer',
78
- 'phone', 'technology', 'politics', 'news', 'celebrity', 'entertainment'
79
- ]
80
-
81
- # Create flat list of medical keywords
82
- self.all_medical_keywords = []
83
- for category_keywords in self.medical_keywords.values():
84
- self.all_medical_keywords.extend(category_keywords)
85
-
86
- def load_biomedical_model(self):
87
- """Load a lightweight biomedical model"""
88
- try:
89
- logger.info("Loading biomedical language model...")
90
-
91
- # Use a lightweight medical model or fallback to general model
92
- model_name = "microsoft/DialoGPT-medium" # Lightweight conversational model
93
-
94
- self.tokenizer = AutoTokenizer.from_pretrained(model_name)
95
- self.model = AutoModelForCausalLM.from_pretrained(
96
- model_name,
97
- torch_dtype=torch.float16 if self.use_gpu else torch.float32,
98
- device_map="auto" if self.use_gpu else None
99
- )
100
-
101
- # Add padding token if not present
102
- if self.tokenizer.pad_token is None:
103
- self.tokenizer.pad_token = self.tokenizer.eos_token
104
-
105
- logger.info(f"Model loaded successfully on {self.device}")
106
-
107
- except Exception as e:
108
- logger.error(f"Error loading model: {e}")
109
- logger.info("Model loading failed, will use template-based responses")
110
- self.model = None
111
- self.tokenizer = None
112
-
113
- def load_medical_data(self, file_path):
114
- """Load and chunk medical data"""
115
- try:
116
- if not os.path.exists(file_path):
117
- logger.error(f"Medical data file not found: {file_path}")
118
- return False
119
-
120
- with open(file_path, 'r', encoding='utf-8') as f:
121
- content = f.read()
122
-
123
- # Simple chunking by paragraphs or sentences
124
- chunks = []
125
-
126
- # Split by double newlines (paragraphs)
127
- paragraphs = content.split('\n\n')
128
-
129
- for i, paragraph in enumerate(paragraphs):
130
- if len(paragraph.strip()) > 50: # Minimum chunk size
131
- chunks.append({
132
- 'id': i,
133
- 'text': paragraph.strip(),
134
- 'source': file_path
135
- })
136
-
137
- # If no paragraphs, split by sentences
138
- if len(chunks) < 10:
139
- sentences = re.split(r'[.!?]+', content)
140
- chunks = []
141
- for i, sentence in enumerate(sentences):
142
- if len(sentence.strip()) > 30:
143
- chunks.append({
144
- 'id': i,
145
- 'text': sentence.strip(),
146
- 'source': file_path
147
- })
148
-
149
- self.knowledge_chunks = chunks
150
- logger.info(f"Loaded {len(self.knowledge_chunks)} knowledge chunks")
151
- return True
152
-
153
- except Exception as e:
154
- logger.error(f"Error loading medical data: {e}")
155
- return False
156
-
157
- def calculate_medical_relevance(self, query):
158
- """Calculate medical relevance score"""
159
- if not query:
160
- return 0.0
161
-
162
- query_lower = query.lower()
163
- words = re.findall(r'\b\w+\b', query_lower)
164
-
165
- if not words:
166
- return 0.0
167
-
168
- # Count medical keyword matches
169
- medical_matches = 0
170
- for word in words:
171
- for keyword in self.all_medical_keywords:
172
- if word == keyword or keyword in word or word in keyword:
173
- medical_matches += 1
174
- break
175
-
176
- # Count non-medical keywords
177
- non_medical_matches = sum(1 for word in words if word in self.non_medical_keywords)
178
-
179
- # Calculate score
180
- medical_score = medical_matches / len(words)
181
- non_medical_penalty = non_medical_matches / len(words)
182
-
183
- relevance_score = medical_score - (non_medical_penalty * 0.7)
184
- return max(0.0, min(1.0, relevance_score))
185
-
186
- def classify_medical_intent(self, query):
187
- """Classify medical intent with improved fever detection"""
188
- query_lower = query.lower()
189
- intent_scores = {}
190
-
191
- # Special handling for fever-related queries
192
- fever_keywords = ['fever', 'temperature', 'hot', 'warm', 'degrees', 'thermometer']
193
- if any(keyword in query_lower for keyword in fever_keywords):
194
- # This is definitely a fever/symptom query
195
- return "fever_management", 0.9
196
-
197
- for category, keywords in self.medical_keywords.items():
198
- score = 0
199
- for keyword in keywords:
200
- if keyword in query_lower:
201
- # Give higher weight to exact matches
202
- if f" {keyword} " in f" {query_lower} ":
203
- score += 2
204
- else:
205
- score += 1
206
- intent_scores[category] = score
207
-
208
- if max(intent_scores.values()) > 0:
209
- best_intent = max(intent_scores, key=intent_scores.get)
210
- max_score = intent_scores[best_intent]
211
- confidence = min(1.0, max_score / 3) # Normalize confidence
212
- return best_intent, confidence
213
-
214
- return "general", 0.1
215
-
216
- def search_relevant_chunks(self, query, top_k=5):
217
- """Enhanced search for relevant knowledge chunks"""
218
- if not self.knowledge_chunks:
219
- return []
220
-
221
- query_lower = query.lower()
222
- query_words = set(re.findall(r'\b\w+\b', query_lower))
223
-
224
- # Get intent for boosting
225
- intent, _ = self.classify_medical_intent(query)
226
- intent_keywords = set(self.medical_keywords.get(intent, []))
227
-
228
- # Special fever keywords for boosting fever-related content
229
- fever_keywords = {'fever', 'temperature', 'hot', 'warm', 'degrees', 'thermometer'}
230
- is_fever_query = bool(fever_keywords.intersection(query_words))
231
-
232
- scored_chunks = []
233
- for chunk in self.knowledge_chunks:
234
- chunk_text = chunk['text'].lower()
235
- chunk_words = set(re.findall(r'\b\w+\b', chunk_text))
236
-
237
- # Calculate different similarity scores
238
-
239
- # 1. Exact word matches
240
- exact_matches = len(query_words.intersection(chunk_words))
241
- exact_score = exact_matches / len(query_words) if query_words else 0
242
-
243
- # 2. Partial matches
244
- partial_matches = 0
245
- for q_word in query_words:
246
- for c_word in chunk_words:
247
- if q_word in c_word or c_word in q_word:
248
- partial_matches += 0.5
249
- break
250
- partial_score = partial_matches / len(query_words) if query_words else 0
251
-
252
- # 3. Intent keyword matches
253
- intent_matches = len(intent_keywords.intersection(chunk_words))
254
- intent_score = intent_matches * 0.2
255
-
256
- # 4. Special fever boost
257
- fever_boost = 0
258
- if is_fever_query:
259
- fever_matches = len(fever_keywords.intersection(chunk_words))
260
- fever_boost = fever_matches * 0.5
261
-
262
- # 5. Medical keyword density
263
- medical_words_in_chunk = sum(1 for word in chunk_words if word in self.all_medical_keywords)
264
- medical_density = medical_words_in_chunk / len(chunk_words) if chunk_words else 0
265
-
266
- # Combine scores
267
- final_score = (
268
- exact_score * 0.4 +
269
- partial_score * 0.3 +
270
- intent_score +
271
- fever_boost +
272
- medical_density * 0.1
273
- )
274
-
275
- # Length bonus for substantial chunks
276
- if len(chunk['text']) > 100:
277
- final_score *= 1.1
278
-
279
- scored_chunks.append((final_score, chunk))
280
-
281
- # Sort and return top chunks
282
- scored_chunks.sort(key=lambda x: x[0], reverse=True)
283
- return [chunk for score, chunk in scored_chunks[:top_k] if score > 0.1]
284
-
285
- def generate_response_with_model(self, query, context):
286
- """Generate response using the language model"""
287
- if not self.model or not self.tokenizer:
288
- return None
289
-
290
- try:
291
- # Prepare prompt with better structure
292
- prompt = f"Medical Question: {query}\n\nRelevant Medical Information:\n{context[:800]}\n\nProvide a helpful medical response:"
293
-
294
- # Tokenize
295
- inputs = self.tokenizer.encode(prompt, return_tensors="pt", max_length=512, truncation=True)
296
- if self.use_gpu:
297
- inputs = inputs.to(self.device)
298
-
299
- # Generate
300
- with torch.no_grad():
301
- outputs = self.model.generate(
302
- inputs,
303
- max_length=inputs.shape[1] + 150,
304
- num_return_sequences=1,
305
- temperature=0.7,
306
- do_sample=True,
307
- pad_token_id=self.tokenizer.eos_token_id
308
- )
309
-
310
- # Decode response
311
- response = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
312
-
313
- # Extract just the answer part
314
- if "Provide a helpful medical response:" in response:
315
- answer = response.split("Provide a helpful medical response:")[-1].strip()
316
- elif "Medical response:" in response.lower():
317
- answer = response.split("Medical response:")[-1].strip()
318
- else:
319
- # Take the part after the original prompt
320
- answer = response[len(prompt):].strip()
321
-
322
- return answer if len(answer) > 10 else None
323
-
324
- except Exception as e:
325
- logger.error(f"Error generating response with model: {e}")
326
- return None
327
-
328
- def generate_template_response(self, query, context, intent):
329
- """Generate template-based response with improved fever handling"""
330
-
331
- # Check if this is a fever query
332
- query_lower = query.lower()
333
- if any(keyword in query_lower for keyword in ['fever', 'temperature', 'hot', 'warm']):
334
- # Generate fever-specific response
335
- if context:
336
- fever_response = self.create_fever_specific_response(context)
337
- if fever_response:
338
- return fever_response
339
-
340
- # Template responses based on intent
341
- templates = {
342
- 'fever_management': [
343
- f"For fever management in children:\n\n{context[:400]}...\n\n⚠️ Always monitor your child closely and consult a doctor if fever is high or persistent."
344
- ],
345
- 'symptoms': [
346
- f"Regarding symptoms in children:\n\n{context[:400]}...\n\nIf symptoms persist or worsen, please consult a healthcare professional."
347
- ],
348
- 'treatments': [
349
- f"Treatment information from medical sources:\n\n{context[:400]}...\n\n⚠️ Always consult a doctor before starting any treatment."
350
- ],
351
- 'emergency': [
352
- f"⚠️ For emergency situations:\n\n{context[:300]}...\n\n🚨 IMPORTANT: If this is a medical emergency, call emergency services immediately!"
353
- ],
354
- 'conditions': [
355
- f"Medical information about this condition:\n\n{context[:400]}...\n\nConsult your pediatrician for proper diagnosis and treatment."
356
- ]
357
- }
358
-
359
- # Select appropriate template
360
- if intent in templates:
361
- template_list = templates[intent]
362
- template = template_list[0] # Use first template for now
363
- else:
364
- template = f"Based on medical information:\n\n{context[:400]}...\n\nPlease consult with a healthcare professional for personalized advice."
365
-
366
- return template
367
-
368
- def create_fever_specific_response(self, context):
369
- """Create fever-specific response from context"""
370
- if not context:
371
- return None
372
-
373
- # Look for fever-related sentences in the context
374
- sentences = re.split(r'[.!?]+', context)
375
- fever_sentences = []
376
-
377
- fever_keywords = ['fever', 'temperature', 'hot', 'warm', 'degrees', 'thermometer', 'acetaminophen', 'ibuprofen', 'fluids']
378
-
379
- for sentence in sentences:
380
- sentence = sentence.strip()
381
- if len(sentence) > 20:
382
- sentence_lower = sentence.lower()
383
- if any(keyword in sentence_lower for keyword in fever_keywords):
384
- fever_sentences.append(sentence)
385
-
386
- if fever_sentences:
387
- # Take the most relevant fever sentences
388
- response = "For managing fever in children:\n\n" + '. '.join(fever_sentences[:3]) + '.'
389
- response += "\n\n⚠️ Monitor your child's temperature regularly and seek medical attention if fever is high (>104°F/40°C) or if your child appears very ill."
390
- return response
391
-
392
- return None
393
-
394
- def chat(self, user_input):
395
- """Main chat method with enhanced fever handling"""
396
- try:
397
- # Check medical relevance
398
- relevance_score = self.calculate_medical_relevance(user_input)
399
-
400
- if relevance_score < 0.2:
401
- return ("I'm designed to help with pediatric medical questions. Your query doesn't seem to be medical-related. "
402
- "Please ask about children's health, symptoms, treatments, or medical conditions.\n\n"
403
- "Examples:\n"
404
- "• 'What should I do if my child has a fever?'\n"
405
- "• 'How to treat a child's cough?'\n"
406
- "• 'When should I call the doctor for my baby?'")
407
-
408
- # Classify intent with special fever handling
409
- intent, intent_confidence = self.classify_medical_intent(user_input)
410
-
411
- # Search for relevant information
412
- relevant_chunks = self.search_relevant_chunks(user_input, top_k=4)
413
-
414
- if not relevant_chunks:
415
- # Provide helpful response even without chunks
416
- if 'fever' in user_input.lower():
417
- return ("For fever in children, general guidelines include:\n\n"
418
- "• Monitor temperature regularly\n"
419
- "• Ensure adequate fluid intake\n"
420
- "• Consider age-appropriate fever reducers (consult your pediatrician)\n"
421
- "• Watch for signs of dehydration or severe illness\n"
422
- "• Seek medical attention if fever is very high or persistent\n\n"
423
- "⚠️ Always consult with your pediatrician for specific advice about your child's fever.")
424
- else:
425
- return (f"I understand you're asking about {intent}-related medical information, "
426
- f"but I couldn't find specific details in my knowledge base. "
427
- f"Please consult with a pediatrician for personalized medical advice about your child's condition.")
428
-
429
- # Prepare context
430
- context = "\n\n".join([chunk['text'] for chunk in relevant_chunks])
431
-
432
- # Try to generate response with model
433
- response = self.generate_response_with_model(user_input, context)
434
-
435
- # Fallback to template response
436
- if not response or len(response) < 20:
437
- response = self.generate_template_response(user_input, context, intent)
438
-
439
- # Add helpful footer
440
- footer = "\n\n💡 This information is for educational purposes only. Always consult with a qualified pediatrician for medical advice, diagnosis, and treatment."
441
-
442
- if intent == "emergency" or any(word in user_input.lower() for word in ['urgent', 'emergency', 'serious']):
443
- footer = "\n\n🚨 IMPORTANT: For medical emergencies, contact emergency services immediately (911 in the US, 999 in the UK, etc.)"
444
-
445
- return response + footer
446
-
447
- except Exception as e:
448
- logger.error(f"Error in chat: {e}")
449
- return f"I encountered an error processing your question: {str(e)}. Please try rephrasing your medical question."
450
-
451
- def initialize_standalone_chatbot():
452
- """Initialize the standalone chatbot"""
453
- try:
454
- print("🚀 Initializing Standalone Medical Chatbot...")
455
-
456
- use_gpu = torch.cuda.is_available()
457
- chatbot = StandaloneMedicalChatbot(use_gpu=use_gpu)
458
-
459
- # Load medical data
460
- medical_file = "Pediatric_cleaned.txt"
461
- if os.path.exists(medical_file):
462
- success = chatbot.load_medical_data(medical_file)
463
- if success:
464
- status = f"✅ Standalone Medical Chatbot loaded! Medical file '{medical_file}' processed with {len(chatbot.knowledge_chunks)} knowledge chunks."
465
- return chatbot, status, True
466
- else:
467
- status = f"⚠️ Chatbot initialized but failed to load medical data from '{medical_file}'."
468
- return chatbot, status, False
469
- else:
470
- status = f"⚠️ Medical file '{medical_file}' not found. Chatbot will work with basic medical knowledge only."
471
- return chatbot, status, False
472
-
473
- except Exception as e:
474
- error_msg = f"❌ Failed to initialize chatbot: {str(e)}"
475
- print(error_msg)
476
- return None, error_msg, False
477
-
478
- # Initialize chatbot
479
- print("🏥 Starting Standalone Pediatric Medical Assistant...")
480
- chatbot, startup_status, medical_file_loaded = initialize_standalone_chatbot()
481
-
482
- def generate_response(user_input, history):
483
- """Generate response"""
484
- if not chatbot:
485
- return history + [("System Error", "❌ Chatbot failed to initialize. Please refresh the page and try again.")], ""
486
-
487
- if not user_input.strip():
488
- return history, ""
489
-
490
- try:
491
- bot_response = chatbot.chat(user_input)
492
- history = history + [(user_input, bot_response)]
493
- return history, ""
494
-
495
- except Exception as e:
496
- error_response = f"⚠️ Sorry, I encountered an error: {str(e)}. Please try rephrasing your question."
497
- history = history + [(user_input, error_response)]
498
- return history, ""
499
-
500
- # Custom CSS
501
- custom_css = """
502
- .gradio-container {
503
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
504
- }
505
-
506
- .chatbot {
507
- height: 500px !important;
508
- }
509
-
510
- .standalone-badge {
511
- background: linear-gradient(90deg, #2196f3, #1976d2);
512
- color: white;
513
- padding: 6px 15px;
514
- border-radius: 25px;
515
- font-size: 0.9em;
516
- font-weight: bold;
517
- display: inline-block;
518
- margin-bottom: 15px;
519
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
520
- }
521
- """
522
-
523
- # Create Gradio interface
524
- with gr.Blocks(css=custom_css, title="Standalone Medical Assistant") as demo:
525
- gr.Markdown(
526
- """
527
- # 🩺 Standalone Pediatric Medical Assistant
528
-
529
- <div class="standalone-badge">🚀 FULLY STANDALONE - NO EXTERNAL DEPENDENCIES</div>
530
-
531
- This is a complete standalone medical chatbot that includes:
532
- - **🧠 Built-in Medical Intelligence** - No external ML libraries needed
533
- - **🎯 Smart Relevance Detection** - Filters medical vs non-medical queries
534
- - **🔍 Advanced Search** - Multi-factor similarity scoring
535
- - **💬 Conversational AI** - Powered by transformer models
536
- - **📚 Medical Knowledge Base** - Pediatric-focused information
537
-
538
- **⚠️ Medical Disclaimer:** This tool provides educational information only.
539
- Always consult qualified healthcare professionals for medical diagnosis, treatment, and personalized advice.
540
- """
541
- )
542
-
543
- # Status display
544
- gr.Markdown(f"**System Status:** {startup_status}")
545
-
546
- # Main chat interface
547
- with gr.Row():
548
- with gr.Column(scale=4):
549
- chatbot_ui = gr.Chatbot(
550
- label="💬 Standalone Medical AI Chat",
551
- height=500,
552
- show_label=True,
553
- avatar_images=("👤", "🤖")
554
- )
555
-
556
- with gr.Row():
557
- user_input = gr.Textbox(
558
- placeholder="Ask any pediatric medical question... (e.g., 'What should I do if my child has a fever?')",
559
- lines=2,
560
- max_lines=5,
561
- show_label=False,
562
- scale=4
563
- )
564
- submit_btn = gr.Button("Send 📤", variant="primary", scale=1)
565
-
566
- with gr.Column(scale=1):
567
- gr.Markdown(
568
- """
569
- ### ✨ Key Features:
570
-
571
- **��� Intelligent Filtering**
572
- - Detects medical relevance
573
- - Redirects non-medical queries
574
- - Provides helpful suggestions
575
-
576
- **🧠 Medical Understanding**
577
- - Symptom recognition
578
- - Treatment information
579
- - Emergency detection
580
- - Age-appropriate advice
581
-
582
- **🔍 Smart Search**
583
- - Multi-factor scoring
584
- - Intent-based boosting
585
- - Context-aware matching
586
-
587
- ### 💡 Try These Questions:
588
-
589
- - "My 2-year-old has a fever of 101°F, what should I do?"
590
- - "How do I know if my baby's cough is serious?"
591
- - "What are normal sleep patterns for toddlers?"
592
- - "When should I call the doctor for vomiting?"
593
- - "How to treat diaper rash naturally?"
594
- - "Signs of allergic reactions in children"
595
-
596
- ### 🔧 Technical Info:
597
- - **Base:** Transformer language model
598
- - **Search:** Multi-factor similarity
599
- - **Knowledge:** Pediatric medical database
600
- - **Relevance:** Keyword-based ML
601
- """
602
- )
603
-
604
- # Event handlers
605
- user_input.submit(
606
- fn=generate_response,
607
- inputs=[user_input, chatbot_ui],
608
- outputs=[chatbot_ui, user_input],
609
- show_progress=True
610
- )
611
-
612
- submit_btn.click(
613
- fn=generate_response,
614
- inputs=[user_input, chatbot_ui],
615
- outputs=[chatbot_ui, user_input],
616
- show_progress=True
617
- )
618
-
619
- # Footer
620
- gr.Markdown(
621
- """
622
- ---
623
- **🏥 Standalone Medical AI** | Self-Contained System | For Educational Purposes Only
624
-
625
- **No External Dependencies:** This system runs entirely standalone without requiring
626
- external ML libraries like NLTK, scikit-learn, or sentence-transformers.
627
-
628
- **Always Remember:** Consult healthcare professionals for medical emergencies and personalized advice.
629
- """
630
- )
631
-
632
- if __name__ == "__main__":
633
- demo.launch(
634
- server_name="0.0.0.0",
635
- server_port=7860,
636
- show_error=True,
637
- share=False
638
- )