ayush200399391001 commited on
Commit
131f0c3
·
verified ·
1 Parent(s): 9caae68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -252
app.py CHANGED
@@ -2,13 +2,6 @@ import streamlit as st
2
  import os
3
  from groq import Groq
4
  from datetime import datetime
5
- from transformers import pipeline
6
- import pandas as pd
7
- import re
8
- import torch
9
-
10
- # Force CPU usage
11
- device = torch.device("cpu")
12
 
13
  # Set page config FIRST
14
  st.set_page_config(page_title="AI Medical Consultancy", layout="wide")
@@ -16,80 +9,56 @@ st.set_page_config(page_title="AI Medical Consultancy", layout="wide")
16
  # Custom CSS for styling
17
  st.markdown("""
18
  <style>
19
- /* Color Variables */
20
- :root {
21
- --primary: #3498db; /* Blue */
22
- --secondary: #2c3e50; /* Dark accent */
23
- --accent: #f1c40f; /* Yellow */
24
- --success: #2ecc71; /* Positive actions */
25
- --light: #ffffff; /* White backgrounds */
26
- --dark: #000000; /* Black text/elements */
27
- }
28
-
29
  /* Main container styling */
30
  .stApp {
31
- background: linear-gradient(135deg, #3498db 0%, #e0e0e0 100%);
32
  font-family: 'Arial', sans-serif;
33
  }
34
 
35
  /* Headers styling */
36
  h1, h2, h3 {
37
- color: var(--dark) !important;
38
- border-bottom: 3px solid var(--primary);
39
  padding-bottom: 0.3em;
40
  }
41
 
42
  /* Form containers */
43
  .stForm {
44
- background: #000000;
45
- border: 1px solid rgba(44, 62, 80, 0.2);
46
  border-radius: 15px;
47
  padding: 2rem;
48
- box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
49
  margin: 1rem 0;
50
  }
51
 
52
  /* Input fields */
53
- .stTextInput input, .stNumberInput input,
54
- .stSelectbox select, .stTextArea textarea {
55
- border: 2px solid #00FFFF !important;
56
- border-radius: 10px !important;
57
- padding: 1rem !important;
58
- background: #00FFFF !important;
59
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
60
- color: var(--dark) !important;
61
  }
62
 
63
  .stTextInput input:focus, .stNumberInput input:focus,
64
  .stSelectbox select:focus, .stTextArea textarea:focus {
65
- border-color: var(--primary) !important;
66
- box-shadow: 0 0 12px rgba(52, 152, 219, 0.2) !important;
67
- background: white !important;
68
- color: var(--dark) !important;
69
  }
70
 
71
  /* Buttons styling */
72
  .stButton>button {
73
- background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%) !important;
74
- color: var(--dark) !important;
75
  border: none !important;
76
- border-radius: 10px !important;
77
- padding: 1rem 2rem !important;
78
  font-size: 1rem !important;
79
- transition: all 0.3s ease;
80
- position: relative;
81
- overflow: hidden;
82
  }
83
 
84
  .stButton>button:hover {
85
  transform: translateY(-2px);
86
- box-shadow: 0 8px 15px rgba(52, 152, 219, 0.3);
87
- opacity: 0.95;
88
- }
89
-
90
- .stButton>button:active {
91
- transform: translateY(0);
92
- opacity: 1;
93
  }
94
 
95
  /* Progress indicator */
@@ -100,60 +69,39 @@ st.markdown("""
100
  padding: 1rem;
101
  background: rgba(255, 255, 255, 0.9);
102
  border-radius: 10px;
103
- color: var(--dark) !important;
104
  }
105
 
106
  .step {
107
  flex: 1;
108
  text-align: center;
109
- padding: 1rem;
110
- font-weight: 600;
111
- color: #95a5a6;
112
- position: relative;
113
  }
114
 
115
  .step.active {
116
- color: var(--primary);
117
- }
118
-
119
- .step.active:after {
120
- content: '';
121
- position: absolute;
122
- bottom: -1px;
123
- left: 50%;
124
- transform: translateX(-50%);
125
- width: 40%;
126
- height: 3px;
127
- background: var(--primary);
128
  }
129
 
130
  /* Chat bubbles */
131
  .dr-message {
132
- background: linear-gradient(135deg, var(--primary) 0%, #2980b9 100%);
133
  color: white;
134
- border-radius: 20px 20px 20px 4px;
135
- padding: 1.2rem 1.5rem;
136
  margin: 1rem 0;
137
  max-width: 80%;
138
  width: fit-content;
139
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
140
- }
141
-
142
- .user-message {
143
- background: linear-gradient(135deg, #f1c40f 0%, #e1b800 100%);
144
- margin-left: auto;
145
- border-radius: 20px 20px 4px 20px;
146
- color: var(--dark) !important;
147
  }
148
 
149
  /* Emergency alert */
150
  .emergency-alert {
151
- background: linear-gradient(135deg, var(--accent) 0%, #c0392b 100%);
152
  color: white;
153
  padding: 2rem;
154
  border-radius: 15px;
155
  animation: pulse 1.5s infinite;
156
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
157
  }
158
 
159
  @keyframes pulse {
@@ -164,43 +112,11 @@ st.markdown("""
164
 
165
  /* Download button */
166
  .download-btn {
167
- background: linear-gradient(135deg, var(--success) 0%, #27ae60 100%) !important;
168
- }
169
-
170
- /* Enhanced Data Visualization Contrast */
171
- .stDataFrame {
172
- border: 1px solid rgba(0, 0, 0, 0.1);
173
- border-radius: 12px;
174
- overflow: hidden;
175
- background: #f0f0f0;
176
- color: var(--dark) !important;
177
- }
178
-
179
- /* Tabbed Interface Styling */
180
- .stTabs [role="tablist"] {
181
- gap: 10px;
182
- padding: 8px;
183
- background: rgba(240, 240, 240, 0.9);
184
- border-radius: 12px;
185
- color: var(--dark) !important;
186
- }
187
-
188
- .stTabs [role="tab"] {
189
- background: #ffffff !important;
190
- border-radius: 8px !important;
191
- transition: all 0.3s ease;
192
- color: var(--dark) !important;
193
- }
194
-
195
- .stTabs [role="tab"][aria-selected="true"] {
196
- background: var(--primary) !important;
197
- color: white !important;
198
- transform: scale(1.05);
199
  }
200
  </style>
201
  """, unsafe_allow_html=True)
202
 
203
-
204
  # Initialize session state variables
205
  if 'current_step' not in st.session_state:
206
  st.session_state.current_step = 0
@@ -209,96 +125,6 @@ if 'symptom_details' not in st.session_state:
209
  if 'patient_info' not in st.session_state:
210
  st.session_state.patient_info = {}
211
 
212
- # Initialize models and dataset with caching
213
- @st.cache_resource
214
- def load_ner_model():
215
- return pipeline("token-classification",
216
- model="d4data/biomedical-ner-all",
217
- aggregation_strategy='first',
218
- device=-1)
219
-
220
- @st.cache_resource
221
- def load_dataset():
222
- try:
223
- data = pd.read_csv('DATASET.csv', encoding='latin1')
224
- data['Symptom_lower'] = data['Symptom'].str.strip().str.lower()
225
- return data
226
- except FileNotFoundError:
227
- st.error("DATASET.csv not found. Please ensure the file is in the correct directory.")
228
- return None
229
-
230
- pipe = load_ner_model()
231
- data = load_dataset()
232
- if data is None:
233
- st.stop()
234
-
235
- SEVERITY_KEYWORDS = {
236
- 'normal': ['mild', 'occasional', 'controlled', 'temporary', 'fleeting'],
237
- 'moderate': ['moderate', 'persistent', 'frequent', 'prolonged', 'bloating'],
238
- 'severe': ['severe', 'extreme', 'crushing', 'radiating', 'blood', 'inability',
239
- 'sweating', 'vomiting', 'fever', 'swelling', 'radiates', 'persistent >3 days']
240
- }
241
-
242
- def merge_entities(entities, text):
243
- """Merge entities using dataset symptom names for multi-word matching"""
244
- merged = []
245
- detected = set()
246
- text_lower = text.lower()
247
-
248
- symptoms_sorted = data['Symptom'].str.lower().sort_values(
249
- key=lambda x: x.str.len(), ascending=False).tolist()
250
-
251
- for symptom in symptoms_sorted:
252
- if symptom in text_lower and symptom not in detected:
253
- start = text_lower.find(symptom)
254
- end = start + len(symptom)
255
- merged.append({
256
- 'word': text[start:end],
257
- 'start': start,
258
- 'end': end,
259
- 'entity_group': 'Sign_symptom'
260
- })
261
- detected.add(symptom)
262
- return merged
263
-
264
- def determine_condition(text, entity):
265
- context_window = re.findall(r'\w+', text[max(0, entity['start']-20):entity['end']+20])
266
- context = ' '.join(context_window).lower()
267
-
268
- for level, keywords in SEVERITY_KEYWORDS.items():
269
- if any(k in context for k in keywords):
270
- return level.capitalize()
271
- return 'Normal'
272
-
273
- def get_risk_score(symptom, condition):
274
- symptom_clean = symptom.strip().lower()
275
- matches = data[
276
- data['Symptom_lower'].str.contains(rf'\b{symptom_clean}\b', regex=True, flags=re.IGNORECASE)
277
- ]
278
- if not matches.empty:
279
- matches = matches[matches['Condition'] == condition]
280
- return matches['Risk Score'].values[0] if not matches.empty else 0
281
- return 0
282
-
283
- def calculate_risk_score(text):
284
- entities = pipe(text)
285
- merged_entities = merge_entities(entities, text)
286
-
287
- score = 0
288
- breakdown = []
289
- for ent in merged_entities:
290
- if ent['entity_group'] == "Sign_symptom":
291
- symptom = ent['word'].strip().lower()
292
- condition = determine_condition(text, ent)
293
- risk = get_risk_score(symptom, condition)
294
- score += risk
295
- breakdown.append({
296
- 'symptom': symptom.capitalize(),
297
- 'condition': condition,
298
- 'risk': risk
299
- })
300
- return score, breakdown
301
-
302
  def initialize_groq_client():
303
  try:
304
  # Try to get the API key from Streamlit secrets
@@ -306,7 +132,7 @@ def initialize_groq_client():
306
  try:
307
  api_key = st.secrets.get("GROQ_API_KEY", os.getenv("GROQ_API_KEY"))
308
  except FileNotFoundError:
309
- st.warning("No secrets.toml file found. Please create one in the .streamlit folder.")
310
 
311
  # If not found, prompt the user to enter it
312
  if not api_key:
@@ -343,9 +169,7 @@ def symptom_interrogation_step():
343
  focusing on {focus} to differentiate serious causes. Your task is to have a polite and simple conversation with a patient.
344
  Start by asking ONE specific follow-up question about their initial symptom: {main_symptom}.
345
  Ask only one question at a time to avoid overwhelming the patient.
346
- Keep your language clear, professional, and easy to understand.
347
-
348
- Dont display possibe symptoms or why you are asking questions."""
349
 
350
  messages = [
351
  {"role": "system", "content": "Ask focused clinical questions. One at a time."},
@@ -382,7 +206,7 @@ def handle_symptom_interrogation():
382
 
383
  if 'current_question' in st.session_state:
384
  with st.form("symptom_qna"):
385
- st.markdown(f'<div class="dr-message">👨‍⚕ {st.session_state.current_question}</div>', unsafe_allow_html=True)
386
  answer = st.text_input("Your answer:", key=f"answer_{len(st.session_state.symptom_details)}")
387
 
388
  if st.form_submit_button("Next"):
@@ -458,41 +282,40 @@ def generate_risk_assessment():
458
  )
459
 
460
  patient_profile = f"""
461
- *Patient Profile*
462
  Name: {st.session_state.patient_info['name']}
463
  Age: {st.session_state.patient_info['age']}
464
  Gender: {st.session_state.patient_info['gender']}
465
 
466
- *Primary Complaint*
467
  {st.session_state.patient_info['main_symptom']}
468
 
469
- *Symptom Interrogation*
470
  {symptom_log}
471
 
472
- *Medical History*
473
  {st.session_state.patient_info.get('medical_history', 'None reported')}
474
 
475
- *Current Medications*
476
  {st.session_state.patient_info.get('medications', 'None')}
477
 
478
- *Allergies*
479
  {st.session_state.patient_info.get('allergies', 'None reported')}
480
 
481
- *Recent Context*
482
  Last Meal: {st.session_state.patient_info.get('last_meal', 'Unknown')}
483
  Recent Travel: {st.session_state.patient_info.get('recent_travel', 'None')}
484
  """
485
 
486
  analysis_prompt = f"""STRICTLY follow these instructions:
487
  1. Analyze this case: {patient_profile}
488
- 2. *Include ONLY symptoms the patient is actively experiencing*. Exclude all negated symptoms (e.g., "no fever," "denies breathlessness").
489
- 3. Output *EXCLUSIVELY* in this format with NO additional text or explanations:
490
- [Age]-year-old [gender] with [specific, present symptoms].
491
 
492
  Example Output:
493
  "45-year-old man with severe chest pain radiating to the jaw"
494
 
495
- Your Output:"""
496
 
497
  response = st.session_state.client.chat.completions.create(
498
  messages=[
@@ -507,42 +330,11 @@ Your Output:"""
507
  risk_prompt = response.choices[0].message.content.strip('"')
508
 
509
  st.subheader("Clinical Summary")
510
- st.markdown(f"\n{risk_prompt}\n")
511
 
512
- # Add risk scoring
513
- risk_score, breakdown = calculate_risk_score(risk_prompt)
514
-
515
- # Display risk score with color coding
516
- score_color = "#2ecc71" if risk_score < 40 else "#f1c40f" if risk_score < 70 else "#e74c3c"
517
- st.markdown(f"""
518
- <div style="background: {score_color};
519
- color: white;
520
- padding: 1.5rem;
521
- border-radius: 10px;
522
- text-align: center;
523
- margin: 2rem 0;">
524
- <h2 style="color: white; margin: 0;">Risk Assessment Score</h2>
525
- <h1 style="font-size: 3.5rem; margin: 0.5rem 0;">{risk_score}/100</h1>
526
- <p>{'Low Risk' if risk_score < 40 else 'Moderate Risk' if risk_score < 70 else 'High Risk'}</p>
527
- </div>
528
- """, unsafe_allow_html=True)
529
-
530
- # Display breakdown
531
- with st.expander("View Detailed Risk Breakdown", expanded=True):
532
- for item in breakdown:
533
- st.markdown(f"""
534
- <div style="background: rgba(236, 240, 241, 0.5);
535
- padding: 1rem;
536
- border-radius: 8px;
537
- margin: 0.5rem 0;">
538
- <strong>{item['symptom']}</strong> ({item['condition']})
539
- <div style="float: right;">+{item['risk']} pts</div>
540
- </div>
541
- """, unsafe_allow_html=True)
542
-
543
  # Create download button
544
  timestamp = datetime.now().strftime('%Y%m%d%H%M')
545
- filename = f"{st.session_state.patient_info['name'].replace(' ', '')}_assessment{timestamp}.txt"
546
  st.download_button(
547
  label="Download Assessment",
548
  data=risk_prompt,
@@ -592,5 +384,5 @@ def main():
592
  if current_step in steps:
593
  steps[current_step]()
594
 
595
- if __name__ == "_main_":
596
  main()
 
2
  import os
3
  from groq import Groq
4
  from datetime import datetime
 
 
 
 
 
 
 
5
 
6
  # Set page config FIRST
7
  st.set_page_config(page_title="AI Medical Consultancy", layout="wide")
 
9
  # Custom CSS for styling
10
  st.markdown("""
11
  <style>
 
 
 
 
 
 
 
 
 
 
12
  /* Main container styling */
13
  .stApp {
14
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
15
  font-family: 'Arial', sans-serif;
16
  }
17
 
18
  /* Headers styling */
19
  h1, h2, h3 {
20
+ color: #2c3e50 !important;
21
+ border-bottom: 2px solid #3498db;
22
  padding-bottom: 0.3em;
23
  }
24
 
25
  /* Form containers */
26
  .stForm {
27
+ background: rgba(255, 255, 255, 0.9);
 
28
  border-radius: 15px;
29
  padding: 2rem;
30
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
31
  margin: 1rem 0;
32
  }
33
 
34
  /* Input fields */
35
+ .stTextInput input, .stNumberInput input, .stSelectbox select, .stTextArea textarea {
36
+ border: 2px solid #3498db !important;
37
+ border-radius: 8px !important;
38
+ padding: 0.8rem !important;
39
+ transition: all 0.3s ease;
 
 
 
40
  }
41
 
42
  .stTextInput input:focus, .stNumberInput input:focus,
43
  .stSelectbox select:focus, .stTextArea textarea:focus {
44
+ border-color: #2980b9 !important;
45
+ box-shadow: 0 0 8px rgba(52, 152, 219, 0.3) !important;
 
 
46
  }
47
 
48
  /* Buttons styling */
49
  .stButton>button {
50
+ background: linear-gradient(135deg, #3498db 0%, #2980b9 100%) !important;
51
+ color: white !important;
52
  border: none !important;
53
+ border-radius: 8px !important;
54
+ padding: 0.8rem 1.5rem !important;
55
  font-size: 1rem !important;
56
+ transition: transform 0.2s ease;
 
 
57
  }
58
 
59
  .stButton>button:hover {
60
  transform: translateY(-2px);
61
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
62
  }
63
 
64
  /* Progress indicator */
 
69
  padding: 1rem;
70
  background: rgba(255, 255, 255, 0.9);
71
  border-radius: 10px;
 
72
  }
73
 
74
  .step {
75
  flex: 1;
76
  text-align: center;
77
+ padding: 0.5rem;
78
+ font-weight: bold;
79
+ color: #7f8c8d;
 
80
  }
81
 
82
  .step.active {
83
+ color: #3498db;
84
+ border-bottom: 3px solid #3498db;
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  /* Chat bubbles */
88
  .dr-message {
89
+ background: #3498db;
90
  color: white;
91
+ border-radius: 15px;
92
+ padding: 1rem;
93
  margin: 1rem 0;
94
  max-width: 80%;
95
  width: fit-content;
 
 
 
 
 
 
 
 
96
  }
97
 
98
  /* Emergency alert */
99
  .emergency-alert {
100
+ background: #e74c3c;
101
  color: white;
102
  padding: 2rem;
103
  border-radius: 15px;
104
  animation: pulse 1.5s infinite;
 
105
  }
106
 
107
  @keyframes pulse {
 
112
 
113
  /* Download button */
114
  .download-btn {
115
+ background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
  </style>
118
  """, unsafe_allow_html=True)
119
 
 
120
  # Initialize session state variables
121
  if 'current_step' not in st.session_state:
122
  st.session_state.current_step = 0
 
125
  if 'patient_info' not in st.session_state:
126
  st.session_state.patient_info = {}
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  def initialize_groq_client():
129
  try:
130
  # Try to get the API key from Streamlit secrets
 
132
  try:
133
  api_key = st.secrets.get("GROQ_API_KEY", os.getenv("GROQ_API_KEY"))
134
  except FileNotFoundError:
135
+ st.warning("No `secrets.toml` file found. Please create one in the `.streamlit` folder.")
136
 
137
  # If not found, prompt the user to enter it
138
  if not api_key:
 
169
  focusing on {focus} to differentiate serious causes. Your task is to have a polite and simple conversation with a patient.
170
  Start by asking ONE specific follow-up question about their initial symptom: {main_symptom}.
171
  Ask only one question at a time to avoid overwhelming the patient.
172
+ Keep your language clear, professional, and easy to understand."""
 
 
173
 
174
  messages = [
175
  {"role": "system", "content": "Ask focused clinical questions. One at a time."},
 
206
 
207
  if 'current_question' in st.session_state:
208
  with st.form("symptom_qna"):
209
+ st.markdown(f'<div class="dr-message">👨‍⚕️ {st.session_state.current_question}</div>', unsafe_allow_html=True)
210
  answer = st.text_input("Your answer:", key=f"answer_{len(st.session_state.symptom_details)}")
211
 
212
  if st.form_submit_button("Next"):
 
282
  )
283
 
284
  patient_profile = f"""
285
+ **Patient Profile**
286
  Name: {st.session_state.patient_info['name']}
287
  Age: {st.session_state.patient_info['age']}
288
  Gender: {st.session_state.patient_info['gender']}
289
 
290
+ **Primary Complaint**
291
  {st.session_state.patient_info['main_symptom']}
292
 
293
+ **Symptom Interrogation**
294
  {symptom_log}
295
 
296
+ **Medical History**
297
  {st.session_state.patient_info.get('medical_history', 'None reported')}
298
 
299
+ **Current Medications**
300
  {st.session_state.patient_info.get('medications', 'None')}
301
 
302
+ **Allergies**
303
  {st.session_state.patient_info.get('allergies', 'None reported')}
304
 
305
+ **Recent Context**
306
  Last Meal: {st.session_state.patient_info.get('last_meal', 'Unknown')}
307
  Recent Travel: {st.session_state.patient_info.get('recent_travel', 'None')}
308
  """
309
 
310
  analysis_prompt = f"""STRICTLY follow these instructions:
311
  1. Analyze this case: {patient_profile}
312
+ 2. Output ONLY this exact format WITHOUT ANY additional text:
313
+ [Age]-year-old [gender] with [symptom details]
 
314
 
315
  Example Output:
316
  "45-year-old man with severe chest pain radiating to the jaw"
317
 
318
+ Your Output MUST BE:"""
319
 
320
  response = st.session_state.client.chat.completions.create(
321
  messages=[
 
330
  risk_prompt = response.choices[0].message.content.strip('"')
331
 
332
  st.subheader("Clinical Summary")
333
+ st.markdown(f"```\n{risk_prompt}\n```")
334
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  # Create download button
336
  timestamp = datetime.now().strftime('%Y%m%d%H%M')
337
+ filename = f"{st.session_state.patient_info['name'].replace(' ', '_')}_assessment_{timestamp}.txt"
338
  st.download_button(
339
  label="Download Assessment",
340
  data=risk_prompt,
 
384
  if current_step in steps:
385
  steps[current_step]()
386
 
387
+ if __name__ == "__main__":
388
  main()