-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
372 lines (338 loc) · 15.3 KB
/
app.py
File metadata and controls
372 lines (338 loc) · 15.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
import streamlit as st
from modules import file_reader, visualizer
import os
from datetime import datetime
from modules import predict_score
st.set_page_config(
page_title="PsyNLP - Mental Health Text Analysis",
page_icon="🧠",
layout="wide",
initial_sidebar_state="expanded"
)
st.markdown("""
<style>
.main-header {
font-size: 3rem;
color: #667eea;
text-align: center;
margin-bottom: 1rem;
}
.sub-header {
text-align: center;
color: #6c757d;
margin-bottom: 2rem;
}
.metric-card {
background-color: #f8f9fa;
padding: 1.5rem;
border-radius: 0.5rem;
border-left: 4px solid #667eea;
margin: 0.5rem 0;
}
.warning-box {
background-color: #fff3cd;
border-left: 4px solid #ffc107;
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
}
.success-box {
background-color: #d4edda;
border-left: 4px solid #28a745;
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
}
.danger-box {
background-color: #f8d7da;
border-left: 4px solid #dc3545;
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
st.markdown('<h1 class="main-header">🧠 PsyNLP</h1>', unsafe_allow_html=True)
st.markdown('<p class="sub-header">Mental Health Text Analysis Tool - Powered by NLP & LLM</p>', unsafe_allow_html=True)
if 'analysis_complete' not in st.session_state:
st.session_state.analysis_complete = False
if 'analysis_result' not in st.session_state:
st.session_state.analysis_result = None
if 'report_path' not in st.session_state:
st.session_state.report_path = None
if 'html_path' not in st.session_state:
st.session_state.html_path = None
if 'pdf_available' not in st.session_state:
st.session_state.pdf_available = False
if 'pdf_error' not in st.session_state:
st.session_state.pdf_error = None
with st.sidebar:
st.header("ℹ️ About PsyNLP")
st.markdown("""
**PsyNLP** is a local mental health text analysis tool that combines:
- 🤖 BERT emotion detection
- 🧠 DeBERTa mental health classification
- 📊 LLM-based severity scoring
- 📈 Comprehensive HTML reports
**Privacy First**: All analysis happens locally on your device.
""")
st.divider()
st.header("📋 Supported Formats")
st.markdown("""
- 📄 `.txt` - Plain text
- 📝 `.md` - Markdown
- 📃 `.docx` - Word documents
""")
st.divider()
st.header("1. Select User Mode")
user_mode = st.radio(
"Choose your mode:",
("General User", "Professionals/Researchers"),
index=0,
help="**General User**: Get personalized recommendations and wellness tips.\n\n**Professionals/Researchers**: Access clinical insights, DSM-5 considerations, and risk assessments.",
horizontal=True
)
mode_key = "user" if user_mode == "General User" else "professional"
if user_mode == "General User":
st.info("👤 **General User Mode**: You'll receive supportive recommendations, coping strategies, and wellness guidance.")
else:
st.info("🏥 **Professional Mode**: You'll receive clinical assessments, DSM-5 considerations, treatment recommendations, and risk evaluations.")
st.divider()
st.header("2. Upload Your File")
uploaded_file = st.file_uploader(
"Choose a file to analyze",
type=["md", "docx", "txt"],
help="Upload your text file (.txt), markdown file (.md), or Word document (.docx)"
)
if uploaded_file:
try:
content = file_reader.read_file(uploaded_file)
col1, col2, col3 = st.columns(3)
with col1:
st.metric("📄 File Name", uploaded_file.name)
with col2:
st.metric("📊 File Size", f"{len(content)} chars")
with col3:
st.metric("📝 Word Count", f"{len(content.split())} words")
st.success(f"✅ File '{uploaded_file.name}' uploaded successfully!")
st.divider()
st.header("3. Run Analysis")
if st.button("🔍 Analyze Text", type="primary", use_container_width=True):
with st.spinner("🔄 Analyzing text... This may take a few minutes depending on file length."):
try:
progress_bar = st.progress(0)
status_text = st.empty()
status_text.text("📝 Processing text and splitting into sentences...")
progress_bar.progress(20)
status_text.text("🤖 Running BERT emotion and mental health classification...")
progress_bar.progress(40)
status_text.text("🧠 Running LLM severity analysis on each sentence...")
progress_bar.progress(60)
result = predict_score.calculate_text_severity(content)
st.session_state.analysis_result = result
progress_bar.progress(80)
status_text.text("📊 Generating PDF report...")
report_dir = "reports"
os.makedirs(report_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
pdf_filename = f"report_{mode_key}_{timestamp}.pdf"
pdf_path = os.path.join(report_dir, pdf_filename)
html_filename = f"report_{mode_key}_{timestamp}.html"
html_path = os.path.join(report_dir, html_filename)
try:
visualizer.generate_pdf_report(
result,
output_path=pdf_path,
language="en",
mode=mode_key
)
st.session_state.report_path = pdf_path
st.session_state.html_path = html_path
st.session_state.pdf_available = True
except Exception as pdf_error:
status_text.text("⚠️ PDF generation failed, creating HTML report...")
visualizer.generate_html_report(
result,
output_path=html_path,
language="en",
mode=mode_key
)
st.session_state.report_path = html_path
st.session_state.html_path = html_path
st.session_state.pdf_available = False
st.session_state.pdf_error = str(pdf_error)
progress_bar.progress(100)
status_text.text("Analysis complete!")
st.session_state.analysis_complete = True
import time
time.sleep(1)
progress_bar.empty()
status_text.empty()
st.success("🎉 Analysis completed successfully!")
st.balloons()
except Exception as e:
st.error(f"Error during analysis: {str(e)}")
st.exception(e)
st.session_state.analysis_complete = False
if st.session_state.analysis_complete and st.session_state.analysis_result:
st.divider()
st.header("4. Analysis Results")
result = st.session_state.analysis_result
stats = result['severity_stats']
nlp_analysis = result['nlp_analysis']
overall_severity = stats['overall_severity_score']
if overall_severity >= 7:
st.markdown(f"""
<div class="danger-box">
<h3>⚠️ HIGH RISK DETECTED</h3>
<p>Overall Severity Score: <strong>{overall_severity}/10</strong></p>
<p>This text shows significant mental health concerns. Professional help is strongly recommended.</p>
</div>
""", unsafe_allow_html=True)
elif overall_severity >= 4:
st.markdown(f"""
<div class="warning-box">
<h3>⚠️ MODERATE RISK</h3>
<p>Overall Severity Score: <strong>{overall_severity}/10</strong></p>
<p>This text shows some mental health concerns. Consider seeking support.</p>
</div>
""", unsafe_allow_html=True)
else:
st.markdown(f"""
<div class="success-box">
<h3>✅ LOW RISK</h3>
<p>Overall Severity Score: <strong>{overall_severity}/10</strong></p>
<p>This text shows minimal mental health concerns.</p>
</div>
""", unsafe_allow_html=True)
st.subheader("📊 Key Metrics")
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric(
"Overall Severity",
f"{stats['overall_severity_score']}/10",
help="Comprehensive severity score"
)
with col2:
st.metric(
"Maximum Risk",
f"{stats['max_severity']}/10",
help="Highest severity found in any sentence"
)
with col3:
st.metric(
"Average Severity",
f"{stats['avg_severity']}/10",
help="Average severity across all sentences"
)
with col4:
st.metric(
"High-Risk Sentences",
stats['high_risk_sentences'],
help="Number of sentences with severity ≥ 6"
)
st.subheader("🤖 NLP Analysis")
col1, col2 = st.columns(2)
with col1:
st.markdown(f"""
<div class="metric-card">
<h4>Emotion Detection</h4>
<p><strong>Label:</strong> {nlp_analysis['emotion_pred']}</p>
<p><strong>Confidence:</strong> {nlp_analysis['emotion_score']:.2%}</p>
</div>
""", unsafe_allow_html=True)
with col2:
st.markdown(f"""
<div class="metric-card">
<h4>Mental Health Classification</h4>
<p><strong>Label:</strong> {nlp_analysis['psy_pred']}</p>
<p><strong>Confidence:</strong> {nlp_analysis['psy_score']:.2%}</p>
</div>
""", unsafe_allow_html=True)
st.divider()
st.subheader("📥 Download Full Report")
if st.session_state.report_path and os.path.exists(st.session_state.report_path):
if st.session_state.pdf_available:
col1, col2, col3 = st.columns([2, 2, 1])
with col1:
with open(st.session_state.report_path, 'rb') as pdf_file:
pdf_bytes = pdf_file.read()
st.download_button(
label="📑 Download PDF Report",
data=pdf_bytes,
file_name=os.path.basename(st.session_state.report_path),
mime="application/pdf",
type="primary",
use_container_width=True
)
with col2:
if st.session_state.html_path and os.path.exists(st.session_state.html_path):
with open(st.session_state.html_path, 'r', encoding='utf-8') as html_file:
html_content = html_file.read()
st.download_button(
label="📄 Download HTML (Alternative)",
data=html_content,
file_name=os.path.basename(st.session_state.html_path),
mime="text/html",
use_container_width=True
)
with col3:
if st.button("🔄 Reset", use_container_width=True):
st.session_state.analysis_complete = False
st.session_state.analysis_result = None
st.session_state.report_path = None
st.session_state.html_path = None
st.session_state.pdf_available = False
st.rerun()
st.info("💡 **Tip**: PDF report is ready for download and printing. HTML version also available for web viewing.")
else:
col1, col2 = st.columns([3, 1])
with col1:
with open(st.session_state.report_path, 'r', encoding='utf-8') as html_file:
html_content = html_file.read()
st.download_button(
label="📄 Download HTML Report",
data=html_content,
file_name=os.path.basename(st.session_state.report_path),
mime="text/html",
type="primary",
use_container_width=True
)
with col2:
if st.button("🔄 Reset", use_container_width=True):
st.session_state.analysis_complete = False
st.session_state.analysis_result = None
st.session_state.report_path = None
st.session_state.html_path = None
st.session_state.pdf_available = False
st.rerun()
st.warning("⚠️ PDF generation not available. HTML report provided instead.")
if st.session_state.pdf_error:
with st.expander("🔧 How to enable PDF generation"):
st.code(st.session_state.pdf_error)
st.markdown("""
**Install WeasyPrint for PDF support:**
macOS:
```bash
brew install cairo pango gdk-pixbuf libffi
pip install weasyprint
```
Ubuntu/Debian:
```bash
sudo apt-get install libcairo2 libpango-1.0-0
pip install weasyprint
```
""")
except Exception as e:
st.error(f"❌ Error reading file: {str(e)}")
st.exception(e)
else:
st.info("👆 Please upload a file to begin analysis.")
st.divider()
st.markdown("""
<div style='text-align: center; color: #6c757d; font-size: 0.85rem; margin-top: 2rem;'>
<p>🧠 <strong>PsyNLP</strong> - Mental Health Text Analysis Tool</p>
<p>For educational and research purposes only | Not a substitute for professional care</p>
<p><strong>Crisis Resources:</strong> 988 Suicide & Crisis Lifeline | Text 'HELLO' to 741741</p>
</div>
""", unsafe_allow_html=True)