amberroohee commited on
Commit
cc8dec6
·
verified ·
1 Parent(s): 576383e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +526 -0
app.py ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from gtts import gTTS
3
+ from io import BytesIO
4
+ import json
5
+ import datetime
6
+ import re
7
+ from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
8
+ import torch
9
+ import numpy as np
10
+
11
+ # Page config
12
+ st.set_page_config(
13
+ page_title="شفیق - AI Mental Health Assistant",
14
+ page_icon="🧠",
15
+ layout="wide"
16
+ )
17
+
18
+ # ============== LOAD MENTAL HEALTH BERT MODEL ==============
19
+
20
+ @st.cache_resource
21
+ def load_mental_health_model():
22
+ """Load the mental health diagnosis model"""
23
+ try:
24
+ # Primary model: Mental Health BERT
25
+ model_name = "mental/mental-roberta-base"
26
+
27
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
28
+ model = AutoModelForSequenceClassification.from_pretrained(model_name)
29
+
30
+ # Create pipeline
31
+ classifier = pipeline(
32
+ "text-classification",
33
+ model=model,
34
+ tokenizer=tokenizer,
35
+ return_all_scores=True,
36
+ device=-1 # Use CPU (change to 0 if you have GPU)
37
+ )
38
+
39
+ return classifier, model.config.id2label
40
+ except Exception as e:
41
+ st.error(f"Model loading error: {e}")
42
+ return None, None
43
+
44
+ @st.cache_resource
45
+ def load_emotion_model():
46
+ """Load emotion detection model"""
47
+ try:
48
+ emotion_classifier = pipeline(
49
+ "text-classification",
50
+ model="j-hartmann/emotion-english-distilroberta-base",
51
+ return_all_scores=True,
52
+ device=-1
53
+ )
54
+ return emotion_classifier
55
+ except:
56
+ return None
57
+
58
+ @st.cache_resource
59
+ def load_suicide_risk_model():
60
+ """Load suicide risk detection model"""
61
+ try:
62
+ # Using a general classifier for risk assessment
63
+ risk_classifier = pipeline(
64
+ "text-classification",
65
+ model="distilbert-base-uncased-finetuned-sst-2-english",
66
+ device=-1
67
+ )
68
+ return risk_classifier
69
+ except:
70
+ return None
71
+
72
+ # Load models
73
+ with st.spinner("🔄 AI models loading... please wait"):
74
+ mental_health_classifier, id2label = load_mental_health_model()
75
+ emotion_classifier = load_emotion_model()
76
+ risk_classifier = load_suicide_risk_model()
77
+
78
+ # ============== CSS STYLING ==============
79
+
80
+ st.markdown("""
81
+ <style>
82
+ @import url('https://fonts.googleapis.com/css2?family=Noto+Nastaliq+Urdu&display=swap');
83
+
84
+ .urdu-text {
85
+ font-family: 'Noto Nastaliq Urdu', 'Jameel Noori Nastaleeq', serif;
86
+ direction: rtl;
87
+ text-align: right;
88
+ line-height: 2.5;
89
+ font-size: 20px;
90
+ }
91
+
92
+ .diagnosis-box {
93
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
94
+ color: white;
95
+ padding: 20px;
96
+ border-radius: 15px;
97
+ margin: 10px 0;
98
+ }
99
+
100
+ .risk-high { border-left: 5px solid #ff4757; background: #ffebee; }
101
+ .risk-medium { border-left: 5px solid #ffa502; background: #fff3e0; }
102
+ .risk-low { border-left: 5px solid #2ed573; background: #e8f5e9; }
103
+
104
+ .metric-card {
105
+ background: white;
106
+ padding: 15px;
107
+ border-radius: 10px;
108
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
109
+ text-align: center;
110
+ }
111
+
112
+ .severity-critical { color: #ff4757; font-weight: bold; }
113
+ .severity-high { color: #ff6348; font-weight: bold; }
114
+ .severity-moderate { color: #ffa502; font-weight: bold; }
115
+ .severity-low { color: #2ed573; font-weight: bold; }
116
+ </style>
117
+ """, unsafe_allow_html=True)
118
+
119
+ # ============== MENTAL HEALTH ANALYSIS FUNCTIONS ==============
120
+
121
+ def analyze_mental_health(text):
122
+ """
123
+ Use BERT model to analyze mental health conditions
124
+ Returns: dict with conditions, scores, and severity
125
+ """
126
+ results = {
127
+ 'primary_condition': 'unknown',
128
+ 'confidence': 0.0,
129
+ 'all_conditions': {},
130
+ 'severity': 'low',
131
+ 'risk_factors': [],
132
+ 'recommendations': []
133
+ }
134
+
135
+ if mental_health_classifier is None:
136
+ return fallback_analysis(text)
137
+
138
+ try:
139
+ # Get predictions from BERT model
140
+ predictions = mental_health_classifier(text[:512]) # Limit text length
141
+
142
+ if predictions and len(predictions) > 0:
143
+ scores = predictions[0]
144
+
145
+ # Sort by score
146
+ sorted_scores = sorted(scores, key=lambda x: x['score'], reverse=True)
147
+
148
+ # Get primary condition
149
+ primary = sorted_scores[0]
150
+ results['primary_condition'] = primary['label']
151
+ results['confidence'] = round(primary['score'] * 100, 2)
152
+
153
+ # Store all conditions
154
+ for item in sorted_scores:
155
+ results['all_conditions'][item['label']] = round(item['score'] * 100, 2)
156
+
157
+ # Determine severity based on confidence and condition type
158
+ high_risk_conditions = ['suicidal', 'self-harm', 'severe-depression', 'psychosis']
159
+ medium_risk_conditions = ['depression', 'anxiety', 'ptsd', 'bipolar']
160
+
161
+ if results['primary_condition'].lower() in high_risk_conditions or results['confidence'] > 85:
162
+ results['severity'] = 'critical'
163
+ elif results['primary_condition'].lower() in medium_risk_conditions or results['confidence'] > 70:
164
+ results['severity'] = 'moderate-high'
165
+ elif results['confidence'] > 50:
166
+ results['severity'] = 'moderate'
167
+ else:
168
+ results['severity'] = 'low'
169
+
170
+ # Extract risk factors from text
171
+ results['risk_factors'] = extract_risk_factors(text)
172
+
173
+ # Generate recommendations
174
+ results['recommendations'] = generate_recommendations(
175
+ results['primary_condition'],
176
+ results['severity']
177
+ )
178
+
179
+ except Exception as e:
180
+ st.error(f"Analysis error: {e}")
181
+ return fallback_analysis(text)
182
+
183
+ return results
184
+
185
+ def fallback_analysis(text):
186
+ """Fallback when BERT model fails"""
187
+ text_lower = text.lower()
188
+
189
+ # Keyword-based fallback
190
+ conditions = {
191
+ 'depression': ['اداس', 'مایوس', 'udas', 'mayoos', 'hopeless', 'khamoshi', 'تنہا'],
192
+ 'anxiety': ['پریشان', 'ghabrahat', 'tension', 'fikar', 'bechaini', 'گھبراہٹ'],
193
+ 'ptsd': ['خوف', 'khoof', 'nightmare', 'flashback', 'حادثہ', 'trauma'],
194
+ 'suicidal': ['خودکشی', 'mar jaun', 'موت', 'zehar', 'مرنا', 'khatam'],
195
+ 'stress': ['tension', 'دباؤ', 'stress', 'bojh', 'بوجھ', 'pressure']
196
+ }
197
+
198
+ detected = {}
199
+ for condition, keywords in conditions.items():
200
+ score = sum(1 for kw in keywords if kw in text_lower)
201
+ if score > 0:
202
+ detected[condition] = min(score * 20, 100)
203
+
204
+ if not detected:
205
+ return {
206
+ 'primary_condition': 'unknown',
207
+ 'confidence': 0,
208
+ 'all_conditions': {},
209
+ 'severity': 'low',
210
+ 'risk_factors': [],
211
+ 'recommendations': ['general_support']
212
+ }
213
+
214
+ primary = max(detected, key=detected.get)
215
+ return {
216
+ 'primary_condition': primary,
217
+ 'confidence': detected[primary],
218
+ 'all_conditions': detected,
219
+ 'severity': 'moderate' if detected[primary] > 50 else 'low',
220
+ 'risk_factors': extract_risk_factors(text),
221
+ 'recommendations': generate_recommendations(primary, 'moderate')
222
+ }
223
+
224
+ def extract_risk_factors(text):
225
+ """Extract specific risk factors from text"""
226
+ text_lower = text.lower()
227
+ factors = []
228
+
229
+ risk_indicators = {
230
+ 'sleep_issues': ['نیند', 'neend', 'neend nahi', 'جاگنا', 'so nahi pa raha'],
231
+ 'social_isolation': ['اکیلا', 'tanha', 'koi nahi', 'دور', 'alone'],
232
+ 'substance_abuse': ['شراب', 'drugs', 'nasha', 'سیگریٹ', 'smoking'],
233
+ 'self_harm_history': ['زخم', 'cutting', 'khud ko chot', 'خون'],
234
+ 'family_history': ['ghar mein', 'والدین', 'maa baap', 'خاندان'],
235
+ 'work_stress': ['نوکری', 'job', 'kaam', 'boss', 'office', 'پیسے']
236
+ }
237
+
238
+ for factor, keywords in risk_indicators.items():
239
+ if any(kw in text_lower for kw in keywords):
240
+ factors.append(factor)
241
+
242
+ return factors
243
+
244
+ def generate_recommendations(condition, severity):
245
+ """Generate therapeutic recommendations"""
246
+ recommendations = {
247
+ 'critical': [
248
+ "🚨 فوری پیشہ ورانہ مدد ضروری ہے",
249
+ "کسی قریبی ہسپتال یا کلینک جائیں",
250
+ "کسی قریبی رشتہ دار کو مطلع کریں",
251
+ "ہیلپ لائن 1122 پر کال کریں"
252
+ ],
253
+ 'moderate-high': [
254
+ "پیشہ ورانہ مدد مشورہ دینا چاہیے",
255
+ "نفسیاتی ماہر سے ملاقات کریں",
256
+ "مستقل مانیٹرنگ ضروری ہے",
257
+ "دواؤں پر غور کریں"
258
+ ],
259
+ 'moderate': [
260
+ "کاؤنسلنگ سے فائدہ ہوگا",
261
+ "مشقیں اور تھراپی جاری رکھیں",
262
+ "دوستوں سے بات کریں",
263
+ "ورزش اور冥思 کریں"
264
+ ],
265
+ 'low': [
266
+ "خود مدد کی تکنیکیں استعمال کریں",
267
+ "مثبت سرگرمیاں جاری رکھیں",
268
+ "ضرورت ہو تو کاؤنسلنگ کریں"
269
+ ]
270
+ }
271
+
272
+ specific_recs = {
273
+ 'depression': ["روزانہ شیڈول بنائیں", "کھیل کود میں حصہ لیں", "نیند درست کریں"],
274
+ 'anxiety': ["گہری سانسیں لیں", "زمینی حقیقتوں پر توجہ دیں", "پیشہ ورانہ مدد لیں"],
275
+ 'ptsd': ["ٹریما سے نمٹنے کی تربیت", "محفوظ ماحول بنائیں", "پیشہ ورانہ تھراپی"],
276
+ 'suicidal': ["فوری ��سپتال جائیں", "کسی کو بتائیں", "ہتھیار دور رکھیں"]
277
+ }
278
+
279
+ base_recs = recommendations.get(severity, recommendations['low'])
280
+ specific = specific_recs.get(condition, [])
281
+
282
+ return base_recs + specific
283
+
284
+ def analyze_emotion_enhanced(text):
285
+ """Enhanced emotion analysis using BERT"""
286
+ if emotion_classifier:
287
+ try:
288
+ results = emotion_classifier(text[:512])
289
+ if results:
290
+ emotions = {item['label']: item['score'] for item in results[0]}
291
+ dominant = max(emotions, key=emotions.get)
292
+ return dominant, emotions
293
+ except:
294
+ pass
295
+
296
+ # Fallback to keyword
297
+ return detect_emotion_fallback(text)
298
+
299
+ def detect_emotion_fallback(text):
300
+ """Fallback emotion detection"""
301
+ text_lower = text.lower()
302
+
303
+ emotion_keywords = {
304
+ 'sadness': ['اداس', 'rona', 'udas', 'غم', 'dukh', 'tanha'],
305
+ 'fear': ['ڈر', 'khoof', 'ghabrahat', 'fear', 'خوف'],
306
+ 'anger': ['غصہ', 'gussa', 'naraz', 'angry'],
307
+ 'joy': ['خوش', 'khush', 'happy', 'khushi'],
308
+ 'surprise': ['حیران', 'heran', ' shocked', 'واہ'],
309
+ 'disgust': ['نفرت', 'nafrat', 'گھن', 'ghin']
310
+ }
311
+
312
+ scores = {}
313
+ for emotion, keywords in emotion_keywords.items():
314
+ scores[emotion] = sum(1 for kw in keywords if kw in text_lower)
315
+
316
+ if max(scores.values()) == 0:
317
+ return 'neutral', {'neutral': 1.0}
318
+
319
+ dominant = max(scores, key=scores.get)
320
+ total = sum(scores.values())
321
+ normalized = {k: v/total for k, v in scores.items()}
322
+
323
+ return dominant, normalized
324
+
325
+ def get_therapeutic_response_enhanced(mental_health_data, emotion, text):
326
+ """Generate response based on BERT diagnosis"""
327
+ condition = mental_health_data['primary_condition']
328
+ severity = mental_health_data['severity']
329
+ confidence = mental_health_data['confidence']
330
+
331
+ # Crisis response for critical cases
332
+ if severity == 'critical':
333
+ return """
334
+ 🚨 **اہم انتباہ / Critical Alert**
335
+
336
+ میں نوٹ کر رہا ہوں کہ آپ بہت پریشان ہیں۔ آپ کی زندگی قیمتی ہے۔
337
+
338
+ **فوری اقدامات:**
339
+ - 📞 ہیلپ لائن: 1122
340
+ - 🏥 قریبی ہسپتال جائیں
341
+ - 👨‍👩‍👧 کسی کو بتائیں
342
+
343
+ آپ اکیلے نہیں ہیں۔ مدد دستیاب ہے۔
344
+ """
345
+
346
+ # Condition-specific responses
347
+ responses = {
348
+ 'depression': [
349
+ f"میں سمجھتا ہوں آپ {condition} کا سامنا کر رہے ہیں ({confidence}% یقین)۔",
350
+ "یہ ایک طبی حالت ہے جو علاج سے ٹھیک ہو سکتی ہے۔",
351
+ "پیشہ ورانہ مدد سے آپ بہتر محسوس کریں گے۔"
352
+ ],
353
+ 'anxiety': [
354
+ f"آپ کے {condition} کی نشانیاں نظر آ رہی ہیں ({confidence}% یقین)۔",
355
+ "گہری سانسیں اور زمینی تکنیکیں مددگار ثابت ہو سکتی ہیں۔",
356
+ "یہ قابل علاج ہے، امید رکھیں۔"
357
+ ],
358
+ 'ptsd': [
359
+ f"ممکنہ طور پر {condition} کے اثرات ({confidence}% یقین)۔",
360
+ "ٹریما بہت گہرا ہوتا ہے، پیشہ ورانہ مدد ضروری ہے۔",
361
+ "آپ محفوظ ہیں، یہ احساس گزر جائے گا۔"
362
+ ],
363
+ 'stress': [
364
+ "زندگی کے دباؤ آپ پر بھاری ہو رہے ہیں۔",
365
+ "چھوٹے وقفے لیں، خود کو ترجیح دیں۔",
366
+ "تناؤ کا نظم سیکھنا ضروری ہے۔"
367
+ ]
368
+ }
369
+
370
+ base_response = responses.get(condition, responses.get('stress', ["میں آپ کی مدد کرنا چاہتا ہوں۔"]))
371
+
372
+ # Add recommendations
373
+ recs = mental_health_data.get('recommendations', [])
374
+ if recs:
375
+ base_response.append("\n**سفارشات:**")
376
+ for i, rec in enumerate(recs[:3], 1):
377
+ base_response.append(f"{i}. {rec}")
378
+
379
+ return "\n\n".join(base_response)
380
+
381
+ def text_to_speech(text):
382
+ """Convert text to Urdu speech"""
383
+ try:
384
+ # Clean text for TTS
385
+ clean_text = re.sub(r'[^\w\s\u0600-\u06FF]', ' ', text)
386
+ clean_text = clean_text[:500] # Limit length
387
+
388
+ tts = gTTS(text=clean_text, lang='ur', slow=False)
389
+ mp3 = BytesIO()
390
+ tts.write_to_fp(mp3)
391
+ mp3.seek(0)
392
+ return mp3
393
+ except:
394
+ return None
395
+
396
+ # ============== MAIN APP ==============
397
+
398
+ def main():
399
+ # Header
400
+ st.markdown('<h1 style="text-align: center; color: #667eea;">🧠 شفیق Pro</h1>',
401
+ unsafe_allow_html=True)
402
+ st.markdown('<h4 style="text-align: center; color: #666;">AI-Powered Mental Health Assistant</h4>',
403
+ unsafe_allow_html=True)
404
+
405
+ # Initialize session
406
+ if 'chat_history' not in st.session_state:
407
+ st.session_state.chat_history = []
408
+ st.session_state.diagnosis_history = []
409
+
410
+ # Sidebar - Diagnosis Dashboard
411
+ with st.sidebar:
412
+ st.header("📊 طبی تجزیہ / Medical Analysis")
413
+
414
+ if st.session_state.diagnosis_history:
415
+ latest = st.session_state.diagnosis_history[-1]
416
+
417
+ # Severity indicator
418
+ severity = latest['severity']
419
+ severity_class = f"severity-{severity.replace('-', '')}"
420
+
421
+ st.markdown(f"""
422
+ <div class="metric-card {severity_class}">
423
+ <h3>سنگینی / Severity</h3>
424
+ <h2>{severity.upper()}</h2>
425
+ </div>
426
+ """, unsafe_allow_html=True)
427
+
428
+ # Primary condition
429
+ st.write(f"**Primary Condition:** {latest['primary_condition']}")
430
+ st.write(f"**Confidence:** {latest['confidence']}%")
431
+
432
+ # Risk factors
433
+ if latest['risk_factors']:
434
+ st.write("**Risk Factors:**")
435
+ for factor in latest['risk_factors']:
436
+ st.write(f"- {factor}")
437
+
438
+ # History chart
439
+ if len(st.session_state.diagnosis_history) > 1:
440
+ st.write("**Trend:**")
441
+ conditions = [d['primary_condition'] for d in st.session_state.diagnosis_history]
442
+ st.bar_chart(pd.Series(conditions).value_counts())
443
+
444
+ st.markdown("---")
445
+ st.info("""
446
+ ⚠️ **Disclaimer:** This AI provides preliminary screening only.
447
+ Not a substitute for professional psychiatric evaluation.
448
+ """)
449
+
450
+ if st.button("🗑️ New Session"):
451
+ st.session_state.chat_history = []
452
+ st.session_state.diagnosis_history = []
453
+ st.rerun()
454
+
455
+ # Main chat area
456
+ st.markdown("---")
457
+
458
+ # Display chat
459
+ for msg in st.session_state.chat_history:
460
+ if msg['role'] == 'user':
461
+ st.markdown(f"""
462
+ <div style="background: #f3e5f5; padding: 15px; border-radius: 15px;
463
+ text-align: right; margin: 10px 0;">
464
+ <strong>👤 You:</strong><br>
465
+ <span class="urdu-text">{msg['content']}</span>
466
+ </div>
467
+ """, unsafe_allow_html=True)
468
+ else:
469
+ st.markdown(f"""
470
+ <div class="diagnosis-box urdu-text">
471
+ <strong>🤖 شفیق:</strong><br>
472
+ {msg['content']}
473
+ <br><small>Diagnosis: {msg.get('diagnosis', 'N/A')} |
474
+ Confidence: {msg.get('confidence', 0)}%</small>
475
+ </div>
476
+ """, unsafe_allow_html=True)
477
+ if msg.get('audio'):
478
+ st.audio(msg['audio'], format='audio/mp3')
479
+
480
+ # Input
481
+ st.markdown("---")
482
+
483
+ col1, col2 = st.columns([4, 1])
484
+ with col1:
485
+ user_input = st.text_input("Message / پیغام...",
486
+ key="input",
487
+ placeholder="اپنے جذبات بیان کریں...")
488
+ with col2:
489
+ send = st.button("📤 Send", use_container_width=True)
490
+
491
+ if send and user_input:
492
+ with st.spinner("Analyzing with AI..."):
493
+ # Run BERT analysis
494
+ mental_health_data = analyze_mental_health(user_input)
495
+
496
+ # Get emotion
497
+ emotion, emotion_scores = analyze_emotion_enhanced(user_input)
498
+
499
+ # Generate response
500
+ response = get_therapeutic_response_enhanced(
501
+ mental_health_data, emotion, user_input
502
+ )
503
+
504
+ # Text to speech
505
+ audio = text_to_speech(response)
506
+
507
+ # Save to history
508
+ st.session_state.chat_history.append({
509
+ 'role': 'user',
510
+ 'content': user_input
511
+ })
512
+ st.session_state.chat_history.append({
513
+ 'role': 'bot',
514
+ 'content': response,
515
+ 'diagnosis': mental_health_data['primary_condition'],
516
+ 'confidence': mental_health_data['confidence'],
517
+ 'audio': audio
518
+ })
519
+
520
+ st.session_state.diagnosis_history.append(mental_health_data)
521
+
522
+ st.rerun()
523
+
524
+ if __name__ == "__main__":
525
+ import pandas as pd
526
+ main()