imogie commited on
Commit
b0b6579
Β·
verified Β·
1 Parent(s): d18bf4f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +313 -28
app.py CHANGED
@@ -5,10 +5,110 @@ import numpy as np
5
  import re
6
  from datetime import datetime
7
  import os
 
 
 
 
 
 
 
8
 
9
  # Initialize the chatbot class
10
  class PediatricPulmonologyChatbot:
11
  def __init__(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # Knowledge base from your original code
13
  self.knowledge_base = {
14
  "asthma": {
@@ -220,14 +320,183 @@ class PediatricPulmonologyChatbot:
220
  }
221
  }
222
 
 
223
  # Try to load the spaCy model - fallback to rule-based if not available
224
  self.nlp = None
225
  try:
226
- # In production, you might want to download and include your trained model
227
- # For now, we'll use rule-based classification
228
  pass
229
  except:
230
- print("Using rule-based classification as fallback")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
  def rule_based_classifier(self, text):
233
  """Rule-based classification as fallback"""
@@ -281,52 +550,68 @@ class PediatricPulmonologyChatbot:
281
  return None
282
 
283
  def generate_response(self, user_input, history):
284
- """Generate response based on user input"""
285
  if not user_input or not user_input.strip():
286
  return "Please describe your child's symptoms so I can help you better."
287
 
288
- # Classify the condition
289
- condition = self.rule_based_classifier(user_input)
 
 
 
290
 
291
- if not condition:
292
- return """I couldn't identify a specific condition from your description. Please provide more details about:
293
 
294
- β€’ **Specific symptoms** (cough, fever, breathing difficulty, etc.)
295
- β€’ **Duration** of symptoms
296
- β€’ **Child's age**
 
297
  β€’ **Any triggers** you've noticed
298
 
299
- **Remember:** This is for informational purposes only. Always consult with a pediatrician for proper medical evaluation."""
 
 
 
 
300
 
301
  # Get information from knowledge base
302
  info = self.knowledge_base.get(condition)
303
  if not info:
304
- return f"I identified this might be related to **{condition.replace('_', ' ').title()}**, but I need more information to provide specific guidance. Please consult a pediatric pulmonologist."
305
 
306
- # Build comprehensive response
307
- response = f"## **Possible Condition: {condition.replace('_', ' ').title()}**\n\n"
308
 
309
- response += f"**Definition:**\n{info['definition']}\n\n"
 
 
 
 
310
 
311
  if info['symptoms']:
312
- response += "**Common Symptoms:**\n"
313
- for symptom in info['symptoms'][:4]: # Show top 4 symptoms
314
  response += f"β€’ {symptom}\n"
315
  response += "\n"
316
 
317
  if info['red_flags']:
318
- response += "** RED FLAGS - Seek URGENT Medical Care if you notice:**\n"
319
  for flag in info['red_flags']:
320
- response += f"β€’ {flag}\n"
321
  response += "\n"
322
 
323
  if info['advice']:
324
- response += f"** General Advice:**\n{info['advice']}\n\n"
 
 
 
 
325
 
326
  response += """---
327
- ** IMPORTANT DISCLAIMER:**
328
  - This is for educational purposes only
329
- - Always consult a pediatrician for proper diagnosis
330
  - If symptoms worsen or red flags appear, seek immediate medical attention
331
  - Call emergency services if your child has severe breathing difficulty"""
332
 
@@ -385,7 +670,7 @@ with gr.Blocks(
385
  # Warning Box
386
  gr.HTML("""
387
  <div class="warning-box">
388
- <h3> Medical Disclaimer</h3>
389
  <p><strong>This tool is for educational purposes only and is not a substitute for professional medical advice.</strong>
390
  Always consult with a qualified pediatrician or healthcare provider for proper diagnosis and treatment.
391
  In case of emergency or severe symptoms, call emergency services immediately.</p>
@@ -407,14 +692,14 @@ with gr.Blocks(
407
  scale=4,
408
  lines=2
409
  )
410
- send_btn = gr.Button("Send", scale=1, variant="primary")
411
 
412
  with gr.Row():
413
- clear_btn = gr.Button("Clear Chat", variant="secondary")
414
 
415
  # Quick Examples
416
  gr.Markdown("""
417
- ### Example Questions You Can Ask:
418
 
419
  - "My 2-year-old has been wheezing and coughing, especially at night"
420
  - "Baby has runny nose, fast breathing, and won't eat well"
@@ -424,7 +709,7 @@ with gr.Blocks(
424
  """)
425
 
426
  # Conditions Covered
427
- with gr.Accordion(" Conditions This Assistant Can Help With", open=False):
428
  gr.Markdown("""
429
  **Common Conditions:**
430
  - Asthma
 
5
  import re
6
  from datetime import datetime
7
  import os
8
+ from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
9
+ import torch
10
+ from sklearn.feature_extraction.text import TfidfVectorizer
11
+ from sklearn.metrics.pairwise import cosine_similarity
12
+ import pickle
13
+ import warnings
14
+ warnings.filterwarnings('ignore')
15
 
16
  # Initialize the chatbot class
17
  class PediatricPulmonologyChatbot:
18
  def __init__(self):
19
+ # Initialize ML models
20
+ self.setup_ml_models()
21
+
22
+ # Training data for intent classification
23
+ self.training_data = {
24
+ "asthma": [
25
+ "my child is wheezing", "he has a tight chest and can't breathe", "child sounds breathless",
26
+ "she's coughing and short of breath", "wheezing at night", "tight chest", "inhaler needed",
27
+ "difficulty breathing", "whistling sound when breathing", "chest tightness during exercise",
28
+ "chronic wheezing", "allergic asthma", "exercise induced asthma", "nocturnal coughing"
29
+ ],
30
+ "bronchiolitis": [
31
+ "baby has stuffy nose and cough", "infant wheezing with fever", "rapid breathing in baby",
32
+ "congested and breathing fast", "nasal flaring", "chest congestion in baby", "rsv symptoms",
33
+ "baby struggling to feed", "fast shallow breathing", "infant with cold symptoms",
34
+ "runny nose and wheezing baby", "difficulty feeding baby", "baby sounds congested"
35
+ ],
36
+ "pneumonia": [
37
+ "child has chest pain and fever", "coughing up mucus", "high fever and fatigue",
38
+ "breathing fast with chills", "chest crackling sounds", "very tired with fever",
39
+ "productive cough", "bacterial infection lungs", "viral pneumonia", "chest x-ray abnormal",
40
+ "difficulty breathing with fever", "shaking chills", "pleuritic chest pain"
41
+ ],
42
+ "chronic cough": [
43
+ "persistent cough for weeks", "dry cough won't stop", "cough worsens at night",
44
+ "ongoing cough after cold", "chronic dry cough", "cough for more than month",
45
+ "post-infectious cough", "habitual cough", "psychogenic cough", "cough variant asthma",
46
+ "lingering cough", "cough without other symptoms", "nighttime coughing fits"
47
+ ],
48
+ "paradoxical vocal fold movement": [
49
+ "stridor when inhaling", "tight throat can't breathe in", "voice disappears suddenly",
50
+ "throat closes during breathing", "panic with breathing", "exercise induced stridor",
51
+ "vocal cord dysfunction", "throat tightness stress", "difficulty inhaling only",
52
+ "feels like choking", "throat spasm", "can't get air in", "inspiratory stridor"
53
+ ],
54
+ "subglottic stenosis": [
55
+ "high pitched breathing sound", "noisy breathing", "stridor at rest",
56
+ "airway narrowing", "difficulty breathing lying down", "hoarse voice chronic",
57
+ "breathing obstruction", "harsh breathing sounds", "airway surgery needed",
58
+ "congenital stridor", "biphasic stridor", "progressive breathing difficulty"
59
+ ],
60
+ "acute respiratory distress syndrome": [
61
+ "severe breathing difficulty", "needs ventilator", "lung inflammation severe",
62
+ "icu admission breathing", "oxygen not helping", "rapid onset breathing failure",
63
+ "bilateral lung infiltrates", "severe hypoxia", "mechanical ventilation needed",
64
+ "acute lung injury", "sepsis related breathing", "shock lung"
65
+ ],
66
+ "hereditary hemorrhagic telangiectasia": [
67
+ "frequent nosebleeds", "family history bleeding", "abnormal blood vessels",
68
+ "chronic bleeding", "telangiectasia", "arteriovenous malformation",
69
+ "genetic bleeding disorder", "recurrent epistaxis", "vascular malformation",
70
+ "hereditary bleeding", "osler weber rendu", "pulmonary avm"
71
+ ],
72
+ "tracheoesophageal fistula": [
73
+ "coughs when feeding", "milk comes through nose", "choking during feeding",
74
+ "aspiration with feeds", "connection windpipe foodpipe", "surgical repair needed",
75
+ "esophageal atresia", "feeding difficulties newborn", "recurrent pneumonia feeding",
76
+ "congenital anomaly", "h-type fistula", "feeding intolerance"
77
+ ],
78
+ "laryngeal web": [
79
+ "weak hoarse cry", "congenital voice problems", "stridor since birth",
80
+ "membrane vocal cords", "difficulty intubating", "web larynx", "glottic web",
81
+ "voice abnormality birth", "inspiratory stridor newborn", "cry abnormal",
82
+ "congenital laryngeal anomaly", "airway obstruction birth"
83
+ ],
84
+ "primary ciliary dyskinesia": [
85
+ "chronic wet cough", "sinus infections recurrent", "ear infections frequent",
86
+ "immotile cilia", "kartagener syndrome", "bronchiectasis", "daily sputum",
87
+ "chronic rhinosinusitis", "hearing loss chronic", "situs inversus",
88
+ "chronic respiratory infections", "ciliary dysfunction", "genetic lung disease"
89
+ ],
90
+ "pulmonary arterial hypertension": [
91
+ "fatigue with exertion", "shortness breath exercise", "fainting spells",
92
+ "high lung pressure", "right heart failure", "blue lips exercise",
93
+ "syncope exertion", "chest pain exertion", "elevated pulmonary pressure",
94
+ "right heart strain", "eisenmenger syndrome", "pah diagnosis"
95
+ ],
96
+ "esophageal atresia": [
97
+ "frothy saliva newborn", "cannot swallow", "choking feeding attempts",
98
+ "milk regurgitation", "unable pass feeding tube", "congenital esophagus",
99
+ "feeding tube won't pass", "excessive drooling baby", "aspiration feeding",
100
+ "surgical correction needed", "type c ea", "blind pouch esophagus"
101
+ ],
102
+ "asbestosis": [
103
+ "asbestos exposure history", "lung scarring", "occupational lung disease",
104
+ "interstitial fibrosis", "progressive breathlessness", "chest imaging abnormal",
105
+ "environmental exposure", "lung function decline", "pulmonary fibrosis",
106
+ "occupational hazard", "mesothelioma risk", "pleural plaques"
107
+ ]
108
+ }
109
+
110
+ # Setup TF-IDF vectorizer for similarity matching
111
+ self.setup_similarity_model()
112
  # Knowledge base from your original code
113
  self.knowledge_base = {
114
  "asthma": {
 
320
  }
321
  }
322
 
323
+
324
  # Try to load the spaCy model - fallback to rule-based if not available
325
  self.nlp = None
326
  try:
327
+ # You can add your trained spaCy model here later
 
328
  pass
329
  except:
330
+ print("Using ML-enhanced classification")
331
+
332
+ def setup_ml_models(self):
333
+ """Initialize machine learning models"""
334
+ try:
335
+ # Use a medical/clinical BERT model for better understanding
336
+ print("Loading ML models...")
337
+ self.tokenizer = AutoTokenizer.from_pretrained("emilyalsentzer/Bio_ClinicalBERT")
338
+ self.model = AutoModelForSequenceClassification.from_pretrained("emilyalsentzer/Bio_ClinicalBERT", num_labels=14)
339
+ print("Bio-Clinical BERT loaded successfully")
340
+ except Exception as e:
341
+ print(f"Could not load Bio-Clinical BERT: {e}")
342
+ try:
343
+ # Fallback to general medical model
344
+ self.classifier = pipeline(
345
+ "text-classification",
346
+ model="microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract-fulltext",
347
+ return_all_scores=True
348
+ )
349
+ print("PubMed BERT loaded successfully")
350
+ except Exception as e2:
351
+ print(f"Could not load PubMed BERT: {e2}")
352
+ # Final fallback to general model
353
+ try:
354
+ self.classifier = pipeline(
355
+ "text-classification",
356
+ model="distilbert-base-uncased",
357
+ return_all_scores=True
358
+ )
359
+ print("DistilBERT loaded as fallback")
360
+ except:
361
+ print("Using rule-based classification only")
362
+ self.classifier = None
363
+
364
+ def setup_similarity_model(self):
365
+ """Setup TF-IDF similarity model for intent matching"""
366
+ # Prepare all training texts and labels
367
+ all_texts = []
368
+ self.labels = []
369
+
370
+ for condition, examples in self.training_data.items():
371
+ for example in examples:
372
+ all_texts.append(example.lower())
373
+ self.labels.append(condition)
374
+
375
+ # Create TF-IDF vectors
376
+ self.vectorizer = TfidfVectorizer(
377
+ max_features=1000,
378
+ stop_words='english',
379
+ ngram_range=(1, 2) # Include bigrams
380
+ )
381
+ self.tfidf_matrix = self.vectorizer.fit_transform(all_texts)
382
+ print(f"TF-IDF model trained on {len(all_texts)} examples")
383
+
384
+ def predict_condition_ml(self, text):
385
+ """Use ML models to predict condition"""
386
+ text_lower = text.lower()
387
+
388
+ # Method 1: TF-IDF Similarity
389
+ try:
390
+ query_vector = self.vectorizer.transform([text_lower])
391
+ similarities = cosine_similarity(query_vector, self.tfidf_matrix).flatten()
392
+
393
+ # Get top 3 most similar examples
394
+ top_indices = similarities.argsort()[-3:][::-1]
395
+ top_similarities = similarities[top_indices]
396
+
397
+ if top_similarities[0] > 0.1: # Minimum similarity threshold
398
+ predicted_condition = self.labels[top_indices[0]]
399
+ confidence = float(top_similarities[0])
400
+
401
+ # Calculate condition-level confidence by averaging similar examples
402
+ condition_scores = {}
403
+ for idx in top_indices:
404
+ if similarities[idx] > 0.05:
405
+ condition = self.labels[idx]
406
+ if condition not in condition_scores:
407
+ condition_scores[condition] = []
408
+ condition_scores[condition].append(similarities[idx])
409
+
410
+ # Average scores for each condition
411
+ for condition in condition_scores:
412
+ condition_scores[condition] = np.mean(condition_scores[condition])
413
+
414
+ best_condition = max(condition_scores, key=condition_scores.get)
415
+ best_confidence = condition_scores[best_condition]
416
+
417
+ return best_condition, float(best_confidence)
418
+ except Exception as e:
419
+ print(f"TF-IDF prediction error: {e}")
420
+
421
+ # Method 2: Rule-based fallback with enhanced patterns
422
+ return self.rule_based_classifier_enhanced(text_lower)
423
+
424
+ def rule_based_classifier_enhanced(self, text):
425
+ """Enhanced rule-based classification with better pattern matching"""
426
+ text_lower = text.lower()
427
+
428
+ # Create scoring system for multiple keywords
429
+ condition_scores = {}
430
+
431
+ # Enhanced keyword patterns
432
+ patterns = {
433
+ "asthma": [
434
+ (["wheez", "wheezing"], 0.8),
435
+ (["tight chest", "chest tight"], 0.7),
436
+ (["shortness", "breath"], 0.6),
437
+ (["inhaler"], 0.9),
438
+ (["asthma"], 1.0),
439
+ (["breathless"], 0.6),
440
+ (["night", "cough"], 0.5),
441
+ (["exercise", "breathing"], 0.4)
442
+ ],
443
+ "bronchiolitis": [
444
+ (["baby", "infant"], 0.6),
445
+ (["runny nose", "stuffy"], 0.5),
446
+ (["fast breathing", "rapid"], 0.7),
447
+ (["bronchiolitis"], 1.0),
448
+ (["rsv"], 0.8),
449
+ (["nasal flaring"], 0.8),
450
+ (["feeding", "difficulty"], 0.6)
451
+ ],
452
+ "pneumonia": [
453
+ (["fever", "high"], 0.6),
454
+ (["chest pain"], 0.7),
455
+ (["mucus", "phlegm"], 0.6),
456
+ (["pneumonia"], 1.0),
457
+ (["chills"], 0.5),
458
+ (["fatigue", "tired"], 0.4),
459
+ (["crackling"], 0.8)
460
+ ],
461
+ "chronic cough": [
462
+ (["persistent", "chronic"], 0.7),
463
+ (["weeks", "month"], 0.6),
464
+ (["dry cough"], 0.6),
465
+ (["night", "cough"], 0.5),
466
+ (["4 weeks", "four weeks"], 0.8),
467
+ (["ongoing"], 0.5)
468
+ ],
469
+ "paradoxical vocal fold movement": [
470
+ (["stridor"], 0.9),
471
+ (["throat", "tight"], 0.7),
472
+ (["voice", "loss"], 0.6),
473
+ (["inhaling", "difficult"], 0.7),
474
+ (["vocal cord"], 0.8),
475
+ (["choking", "feeling"], 0.6)
476
+ ]
477
+ # Add more patterns for other conditions...
478
+ }
479
+
480
+ # Score each condition
481
+ for condition, pattern_list in patterns.items():
482
+ score = 0
483
+ for keywords, weight in pattern_list:
484
+ if isinstance(keywords, list):
485
+ if all(keyword in text_lower for keyword in keywords):
486
+ score += weight
487
+ else:
488
+ if keywords in text_lower:
489
+ score += weight
490
+
491
+ if score > 0:
492
+ condition_scores[condition] = score
493
+
494
+ if condition_scores:
495
+ best_condition = max(condition_scores, key=condition_scores.get)
496
+ confidence = min(condition_scores[best_condition] / 2.0, 0.95) # Normalize
497
+ return best_condition, confidence
498
+
499
+ return None, 0.0
500
 
501
  def rule_based_classifier(self, text):
502
  """Rule-based classification as fallback"""
 
550
  return None
551
 
552
  def generate_response(self, user_input, history):
553
+ """Generate response based on user input using ML models"""
554
  if not user_input or not user_input.strip():
555
  return "Please describe your child's symptoms so I can help you better."
556
 
557
+ # Use ML model for classification
558
+ condition, confidence = self.predict_condition_ml(user_input)
559
+
560
+ # Set confidence threshold
561
+ confidence_threshold = 0.15
562
 
563
+ if not condition or confidence < confidence_threshold:
564
+ return f"""I need more specific information to help you better. Please describe:
565
 
566
+ β€’ **Specific symptoms** (e.g., "wheezing", "fever", "difficulty breathing")
567
+ β€’ **How long** has your child had these symptoms?
568
+ β€’ **Your child's age** (infant, toddler, school-age)
569
+ β€’ **When symptoms occur** (night, during activity, after eating)
570
  β€’ **Any triggers** you've noticed
571
 
572
+ **Example:** "My 3-year-old has been wheezing at night and coughs when running"
573
+
574
+ **Remember:** This is for educational purposes only. Always consult a pediatrician for proper medical evaluation.
575
+
576
+ **Current analysis:** Based on your input "{user_input}", I detected some patterns but need more details for accurate information (confidence: {confidence:.2f})."""
577
 
578
  # Get information from knowledge base
579
  info = self.knowledge_base.get(condition)
580
  if not info:
581
+ return f"I identified this might be related to **{condition.replace('_', ' ').title()}** (confidence: {confidence:.2f}), but I need more information to provide specific guidance. Please consult a pediatric pulmonologist."
582
 
583
+ # Build comprehensive response with confidence indicator
584
+ confidence_indicator = "🟒 High" if confidence > 0.6 else "🟑 Moderate" if confidence > 0.3 else "🟠 Low"
585
 
586
+ response = f"## 🩺 **Analysis Result**\n\n"
587
+ response += f"**Possible Condition:** {condition.replace('_', ' ').title()}\n"
588
+ response += f"**Confidence Level:** {confidence_indicator} ({confidence:.2f})\n\n"
589
+
590
+ response += f"**πŸ“‹ Definition:**\n{info['definition']}\n\n"
591
 
592
  if info['symptoms']:
593
+ response += "**πŸ” Common Symptoms:**\n"
594
+ for symptom in info['symptoms'][:4]:
595
  response += f"β€’ {symptom}\n"
596
  response += "\n"
597
 
598
  if info['red_flags']:
599
+ response += "**🚨 RED FLAGS - Seek URGENT Medical Care if you notice:**\n"
600
  for flag in info['red_flags']:
601
+ response += f"β€’ ⚠️ {flag}\n"
602
  response += "\n"
603
 
604
  if info['advice']:
605
+ response += f"**πŸ’‘ General Advice:**\n{info['advice']}\n\n"
606
+
607
+ # Add confidence-based disclaimer
608
+ if confidence < 0.4:
609
+ response += "**⚠️ Low Confidence Notice:**\nThis prediction has lower confidence. Please provide more specific symptoms or consult a healthcare provider for accurate assessment.\n\n"
610
 
611
  response += """---
612
+ **⚠️ IMPORTANT DISCLAIMER:**
613
  - This is for educational purposes only
614
+ - Always consult a pediatrician for proper diagnosis
615
  - If symptoms worsen or red flags appear, seek immediate medical attention
616
  - Call emergency services if your child has severe breathing difficulty"""
617
 
 
670
  # Warning Box
671
  gr.HTML("""
672
  <div class="warning-box">
673
+ <h3>⚠️ Medical Disclaimer</h3>
674
  <p><strong>This tool is for educational purposes only and is not a substitute for professional medical advice.</strong>
675
  Always consult with a qualified pediatrician or healthcare provider for proper diagnosis and treatment.
676
  In case of emergency or severe symptoms, call emergency services immediately.</p>
 
692
  scale=4,
693
  lines=2
694
  )
695
+ send_btn = gr.Button("Send πŸ“€", scale=1, variant="primary")
696
 
697
  with gr.Row():
698
+ clear_btn = gr.Button("Clear Chat πŸ—‘οΈ", variant="secondary")
699
 
700
  # Quick Examples
701
  gr.Markdown("""
702
+ ### πŸ’‘ Example Questions You Can Ask:
703
 
704
  - "My 2-year-old has been wheezing and coughing, especially at night"
705
  - "Baby has runny nose, fast breathing, and won't eat well"
 
709
  """)
710
 
711
  # Conditions Covered
712
+ with gr.Accordion("πŸ” Conditions This Assistant Can Help With", open=False):
713
  gr.Markdown("""
714
  **Common Conditions:**
715
  - Asthma