avtak commited on
Commit
8e66eb7
ยท
verified ยท
1 Parent(s): 8244583

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -53
app.py CHANGED
@@ -4,24 +4,24 @@ from huggingface_hub import login
4
  from openai import OpenAI
5
  import os
6
 
7
- # --- 1. SETUP ---
8
  hf_token = os.getenv("HF_TOKEN")
9
  if hf_token:
10
  login(token=hf_token)
11
 
12
- # --- 2. LOAD TOOL ---
13
  print("Loading Mental-Longformer...")
14
  model_name = "avtak/erisk-longformer-depression-v1"
15
  classifier = pipeline("text-classification", model=model_name, truncation=True, max_length=4096, top_k=None)
16
 
17
- # --- 3. LOGIC & TOOLS ---
18
 
19
  def get_crisis_resources(location: str = "Global") -> str:
20
  """Returns mental health resources based on location."""
21
  resources = {
22
  "US": "๐Ÿ‡บ๐Ÿ‡ธ **US:** Crisis Text Line: 741741 | Suicide Lifeline: 988",
23
  "Malaysia": "๐Ÿ‡ฒ๐Ÿ‡พ **Malaysia:** Befrienders KL: 03-76272929 | Talian Kasih: 15999",
24
- "Global": "๐ŸŒ **Global:** [befrienders.org](https://www.befrienders.org)"
25
  }
26
  for key in resources:
27
  if location and key.lower() in location.lower():
@@ -30,12 +30,12 @@ def get_crisis_resources(location: str = "Global") -> str:
30
 
31
  def detect_depression_risk(text: str) -> dict:
32
  """Analyzes text using Mental-Longformer (eRisk 2025)."""
33
- # Thesis Logic: Aggregation
34
  processed_text = text.replace("\n", "\n\n")
35
  results = classifier(processed_text)[0]
36
  prob = next((r['score'] for r in results if r['label'] == 'LABEL_1'), 0)
37
 
38
- # Thesis Thresholds & Biomarkers
39
  if prob < 0.40:
40
  level = "Low Risk"
41
  biomarker = "Healthy External Focus"
@@ -49,7 +49,7 @@ def detect_depression_risk(text: str) -> dict:
49
  else:
50
  level = "High Risk"
51
  biomarker = "Nocturnal & High-Effort"
52
- desc = "Matches 'Depressed' cohort. Indicators: Nocturnal posting spikes (00-05 UTC), high-effort/low-frequency posting, semantic isolation."
53
  color = "#ef4444" # Red
54
 
55
  return {
@@ -63,13 +63,11 @@ def detect_depression_risk(text: str) -> dict:
63
 
64
  # --- 4. AGENT CHAT LOGIC ---
65
 
66
- def generate_chat_response(history, risk_context, provider):
67
  """
68
- Generates a chat response using the selected Sponsor API.
69
- Context-aware: It knows the risk analysis from the previous step.
70
  """
71
  if not risk_context:
72
- # Fallback if chat starts without analysis
73
  risk_context = {"risk_level": "Unknown", "probability": 0.0, "description": "No analysis run yet."}
74
 
75
  # CONFIGURE CLIENT
@@ -78,12 +76,12 @@ def generate_chat_response(history, risk_context, provider):
78
 
79
  if provider == "SambaNova":
80
  client = OpenAI(base_url="https://api.sambanova.ai/v1", api_key=os.getenv("SAMBANOVA_API_KEY"))
81
- model_id = "Meta-Llama-3.3-70B-Instruct"
82
  else: # Nebius
83
  client = OpenAI(base_url="https://api.tokenfactory.nebius.com/v1/", api_key=os.getenv("NEBIUS_API_KEY"))
84
- model_id = "moonshotai/Kimi-K2-Thinking"
85
 
86
- # SYSTEM PROMPT (Injects Thesis Context)
87
  system_prompt = f"""
88
  You are 'Dr. Longformer', a specialized Clinical AI Assistant based on Hassan's 2025 Thesis.
89
 
@@ -94,17 +92,15 @@ def generate_chat_response(history, risk_context, provider):
94
  YOUR GOAL:
95
  Provide supportive, scientifically-grounded chat.
96
  - If High Risk: Focus on sleep hygiene ('Nocturnal' findings) and breaking isolation.
97
- - If Moderate Risk: Discuss burnout and setting boundaries ('Supportive Responder' fatigue).
98
  - If Low Risk: Encourage their hobbies.
99
 
100
  DO NOT diagnose. Use phrases like "Our analysis suggests..." or "Thesis patterns indicate..."
101
- Be concise and conversational.
102
  """
103
 
104
- # Format history for OpenAI API
105
  messages = [{"role": "system", "content": system_prompt}]
106
- for msg in history:
107
- messages.append({"role": msg["role"], "content": msg["content"]})
108
 
109
  try:
110
  response = client.chat.completions.create(
@@ -120,30 +116,26 @@ def generate_chat_response(history, risk_context, provider):
120
  # --- 5. UI ORCHESTRATION ---
121
 
122
  def run_analysis(text, location, provider):
123
- if not text.strip(): return None, None, None
124
 
125
  # 1. Run Tool
126
  data = detect_depression_risk(text)
127
  resources = get_crisis_resources(location)
128
 
129
- # 2. Create Visual Dashboard (HTML)
130
  html_dashboard = f"""
131
  <div style="padding: 20px; border-radius: 12px; background-color: {data['color']}15; border: 1px solid {data['color']};">
132
  <div style="display: flex; justify-content: space-between; align-items: center;">
133
  <h2 style="color: {data['color']}; margin: 0;">{data['risk_level']}</h2>
134
  <h3 style="margin: 0;">{data['probability']*100:.1f}% Match</h3>
135
  </div>
136
-
137
- <!-- Progress Bar -->
138
  <div style="background-color: #e5e7eb; border-radius: 9999px; height: 10px; margin-top: 10px; width: 100%;">
139
  <div style="background-color: {data['color']}; height: 10px; border-radius: 9999px; width: {data['probability']*100}%;"></div>
140
  </div>
141
-
142
  <div style="margin-top: 20px;">
143
  <p><strong>๐Ÿง  Thesis Reflection:</strong> {data['biomarker']}</p>
144
  <p style="opacity: 0.8; font-size: 0.9em;">{data['description']}</p>
145
  </div>
146
-
147
  <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #ccc;">
148
  <p><strong>๐Ÿ†˜ Local Resources ({location}):</strong></p>
149
  <pre style="font-family: inherit; white-space: pre-wrap; margin: 0;">{resources}</pre>
@@ -151,30 +143,47 @@ def run_analysis(text, location, provider):
151
  </div>
152
  """
153
 
154
- # 3. Generate Initial Agent Greeting
155
- greeting_prompt = [{"role": "user", "content": "I just ran the analysis. Please explain my results and start a conversation."}]
156
- initial_response = generate_chat_response(greeting_prompt, data, provider)
 
157
 
158
- # Return: Visual HTML, Chat History (with greeting), State Data
159
- return html_dashboard, [{"role": "assistant", "content": initial_response}], data
 
 
160
 
161
- def user_chat(user_message, history, risk_data, provider):
162
- if not user_message: return history, ""
163
 
164
- # Add user message
165
- history.append({"role": "user", "content": user_message})
166
 
167
- # Generate response
168
- ai_msg = generate_chat_response(history, risk_data, provider)
169
 
170
- # Add AI message
171
- history.append({"role": "assistant", "content": ai_msg})
172
 
173
- return history, ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- # --- 6. EXAMPLES ---
176
  example_high = """I don't know why I even bother getting out of bed anymore. I slept for 12 hours yesterday and I'm still exhausted. It feels like my limbs weigh a thousand pounds.
 
177
  I've been avoiding my friends for weeks. They keep texting me, but I can't bring myself to reply. The thought of socializing is terrifying.
 
178
  Everything feels like a shade of grey. I can't concentrate on my work. I feel like I'm drowning while everyone else is breathing fine. I was up until 4 AM again last night just staring at the ceiling."""
179
 
180
  # --- 7. UI LAYOUT ---
@@ -182,8 +191,8 @@ with gr.Blocks(title="Depression Risk Agent") as demo:
182
  gr.Markdown("# ๐Ÿง  Early Depression Detection Agent (MCP)")
183
  gr.Markdown("Agentic system using **Mental-Longformer** (Tool) + **SambaNova/Nebius** (Chat).")
184
 
185
- # State to hold the analysis data across chat turns
186
  risk_state = gr.State(None)
 
187
 
188
  with gr.Row():
189
  # LEFT: INPUT
@@ -195,6 +204,15 @@ with gr.Blocks(title="Depression Risk Agent") as demo:
195
  value=example_high
196
  )
197
 
 
 
 
 
 
 
 
 
 
198
  with gr.Row():
199
  loc_drop = gr.Dropdown(["Global", "US", "Malaysia"], value="Malaysia", label="Region")
200
  prov_drop = gr.Dropdown(["SambaNova", "Nebius"], value="SambaNova", label="Agent Brain")
@@ -206,34 +224,39 @@ with gr.Blocks(title="Depression Risk Agent") as demo:
206
 
207
  # RIGHT: DASHBOARD & CHAT
208
  with gr.Column(scale=1):
209
- # The "Reflection" Dashboard
210
  dashboard = gr.HTML(label="Clinical Dashboard")
211
-
212
- # The Chat Interface
213
- chatbot = gr.Chatbot(type="messages", label="Agent Chat", height=400)
214
  msg_input = gr.Textbox(label="Chat with Agent", placeholder="Ask about your results or get advice...")
215
  send_btn = gr.Button("Send Message")
216
 
217
  # LOGIC WIRING
218
 
219
- # 1. Analyze Button -> Updates Dashboard & Starts Chat
220
  analyze_btn.click(
221
  run_analysis,
222
  inputs=[input_text, loc_drop, prov_drop],
223
- outputs=[dashboard, chatbot, risk_state]
224
  )
225
 
226
- # 2. Send Message -> Updates Chat using State
 
 
 
 
 
227
  send_btn.click(
228
  user_chat,
229
- inputs=[msg_input, chatbot, risk_state, prov_drop],
230
- outputs=[chatbot, msg_input]
231
  )
232
  msg_input.submit(
233
  user_chat,
234
- inputs=[msg_input, chatbot, risk_state, prov_drop],
235
- outputs=[chatbot, msg_input]
236
  )
237
 
238
  if __name__ == "__main__":
239
- demo.launch(mcp_server=True, theme=gr.themes.Soft())
 
 
 
 
4
  from openai import OpenAI
5
  import os
6
 
7
+ # --- 1. AUTHENTICATION & SETUP ---
8
  hf_token = os.getenv("HF_TOKEN")
9
  if hf_token:
10
  login(token=hf_token)
11
 
12
+ # --- 2. LOAD THE SPECIALIZED TOOL ---
13
  print("Loading Mental-Longformer...")
14
  model_name = "avtak/erisk-longformer-depression-v1"
15
  classifier = pipeline("text-classification", model=model_name, truncation=True, max_length=4096, top_k=None)
16
 
17
+ # --- 3. MCP TOOLS ---
18
 
19
  def get_crisis_resources(location: str = "Global") -> str:
20
  """Returns mental health resources based on location."""
21
  resources = {
22
  "US": "๐Ÿ‡บ๐Ÿ‡ธ **US:** Crisis Text Line: 741741 | Suicide Lifeline: 988",
23
  "Malaysia": "๐Ÿ‡ฒ๐Ÿ‡พ **Malaysia:** Befrienders KL: 03-76272929 | Talian Kasih: 15999",
24
+ "Global": "๐ŸŒ **International:** [befrienders.org](https://www.befrienders.org)"
25
  }
26
  for key in resources:
27
  if location and key.lower() in location.lower():
 
30
 
31
  def detect_depression_risk(text: str) -> dict:
32
  """Analyzes text using Mental-Longformer (eRisk 2025)."""
33
+ # Thesis Logic: User-Level Aggregation simulation
34
  processed_text = text.replace("\n", "\n\n")
35
  results = classifier(processed_text)[0]
36
  prob = next((r['score'] for r in results if r['label'] == 'LABEL_1'), 0)
37
 
38
+ # Thesis Thresholds (Figure 4.15)
39
  if prob < 0.40:
40
  level = "Low Risk"
41
  biomarker = "Healthy External Focus"
 
49
  else:
50
  level = "High Risk"
51
  biomarker = "Nocturnal & High-Effort"
52
+ desc = "Matches 'Depressed' cohort. Indicators: Nocturnal posting spikes (00-05 UTC), high-effort/low-frequency posting."
53
  color = "#ef4444" # Red
54
 
55
  return {
 
63
 
64
  # --- 4. AGENT CHAT LOGIC ---
65
 
66
+ def generate_chat_response(history_state, risk_context, provider):
67
  """
68
+ Generates response using Sponsor API.
 
69
  """
70
  if not risk_context:
 
71
  risk_context = {"risk_level": "Unknown", "probability": 0.0, "description": "No analysis run yet."}
72
 
73
  # CONFIGURE CLIENT
 
76
 
77
  if provider == "SambaNova":
78
  client = OpenAI(base_url="https://api.sambanova.ai/v1", api_key=os.getenv("SAMBANOVA_API_KEY"))
79
+ model_id = "Meta-Llama-3.3-70B-Instruct" # Latest Model
80
  else: # Nebius
81
  client = OpenAI(base_url="https://api.tokenfactory.nebius.com/v1/", api_key=os.getenv("NEBIUS_API_KEY"))
82
+ model_id = "moonshotai/Kimi-K2-Thinking" # Requested Model
83
 
84
+ # SYSTEM PROMPT (Thesis-Informed)
85
  system_prompt = f"""
86
  You are 'Dr. Longformer', a specialized Clinical AI Assistant based on Hassan's 2025 Thesis.
87
 
 
92
  YOUR GOAL:
93
  Provide supportive, scientifically-grounded chat.
94
  - If High Risk: Focus on sleep hygiene ('Nocturnal' findings) and breaking isolation.
95
+ - If Moderate Risk: Discuss burnout and setting boundaries.
96
  - If Low Risk: Encourage their hobbies.
97
 
98
  DO NOT diagnose. Use phrases like "Our analysis suggests..." or "Thesis patterns indicate..."
99
+ Be concise (max 2 sentences per reply) and conversational.
100
  """
101
 
 
102
  messages = [{"role": "system", "content": system_prompt}]
103
+ messages.extend(history_state)
 
104
 
105
  try:
106
  response = client.chat.completions.create(
 
116
  # --- 5. UI ORCHESTRATION ---
117
 
118
  def run_analysis(text, location, provider):
119
+ if not text.strip(): return None, None, None, None
120
 
121
  # 1. Run Tool
122
  data = detect_depression_risk(text)
123
  resources = get_crisis_resources(location)
124
 
125
+ # 2. Create Visual Dashboard
126
  html_dashboard = f"""
127
  <div style="padding: 20px; border-radius: 12px; background-color: {data['color']}15; border: 1px solid {data['color']};">
128
  <div style="display: flex; justify-content: space-between; align-items: center;">
129
  <h2 style="color: {data['color']}; margin: 0;">{data['risk_level']}</h2>
130
  <h3 style="margin: 0;">{data['probability']*100:.1f}% Match</h3>
131
  </div>
 
 
132
  <div style="background-color: #e5e7eb; border-radius: 9999px; height: 10px; margin-top: 10px; width: 100%;">
133
  <div style="background-color: {data['color']}; height: 10px; border-radius: 9999px; width: {data['probability']*100}%;"></div>
134
  </div>
 
135
  <div style="margin-top: 20px;">
136
  <p><strong>๐Ÿง  Thesis Reflection:</strong> {data['biomarker']}</p>
137
  <p style="opacity: 0.8; font-size: 0.9em;">{data['description']}</p>
138
  </div>
 
139
  <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #ccc;">
140
  <p><strong>๐Ÿ†˜ Local Resources ({location}):</strong></p>
141
  <pre style="font-family: inherit; white-space: pre-wrap; margin: 0;">{resources}</pre>
 
143
  </div>
144
  """
145
 
146
+ # 3. Agent Greeting
147
+ history_state = []
148
+ initial_prompt = "I just ran the analysis. Please explain my results and start a conversation."
149
+ ai_response = generate_chat_response([{"role": "user", "content": initial_prompt}], data, provider)
150
 
151
+ history_state.append({"role": "assistant", "content": ai_response})
152
+ ui_history = [(None, ai_response)]
153
+
154
+ return html_dashboard, ui_history, history_state, data
155
 
156
+ def user_chat(user_message, ui_history, history_state, risk_data, provider):
157
+ if not user_message: return ui_history, history_state, ""
158
 
159
+ history_state.append({"role": "user", "content": user_message})
160
+ ui_history.append((user_message, None))
161
 
162
+ ai_msg = generate_chat_response(history_state, risk_data, provider)
 
163
 
164
+ history_state.append({"role": "assistant", "content": ai_msg})
165
+ ui_history[-1] = (user_message, ai_msg)
166
 
167
+ return ui_history, history_state, ""
168
+
169
+ # --- 6. EXAMPLES (RESTORED) ---
170
+
171
+ example_low = """The new update for the Linux kernel (6.8) finally addressed the driver issues I was seeing with Realtek cards. I read the changelog on kernel.org and noticed they patched the module specific to the rtl8821ce chipset.
172
+
173
+ On a different note, the defensive stats for the basketball team have improved significantly. Allowing 15% fewer points per possession is a game changer.
174
+
175
+ I also spent some time woodworking. I'm building a walnut coffee table and the grain is tricky to plane. I might switch to a polyurethane finish for durability."""
176
+
177
+ example_mod = """Things have been pretty busy at work. We're in the middle of a big project and deadlines are tight. Staying a bit later than usual but that's just how it goes sometimes. Team is handling it well overall.
178
+
179
+ Sleep could be better. Been staying up too late scrolling my phone. Need to work on that. Usually feel okay once I get moving in the morning though.
180
+
181
+ Went hiking with some friends last weekend which was nice. Good to get outside and move around. We're talking about doing another trip next month. Weather should be better by then."""
182
 
 
183
  example_high = """I don't know why I even bother getting out of bed anymore. I slept for 12 hours yesterday and I'm still exhausted. It feels like my limbs weigh a thousand pounds.
184
+
185
  I've been avoiding my friends for weeks. They keep texting me, but I can't bring myself to reply. The thought of socializing is terrifying.
186
+
187
  Everything feels like a shade of grey. I can't concentrate on my work. I feel like I'm drowning while everyone else is breathing fine. I was up until 4 AM again last night just staring at the ceiling."""
188
 
189
  # --- 7. UI LAYOUT ---
 
191
  gr.Markdown("# ๐Ÿง  Early Depression Detection Agent (MCP)")
192
  gr.Markdown("Agentic system using **Mental-Longformer** (Tool) + **SambaNova/Nebius** (Chat).")
193
 
 
194
  risk_state = gr.State(None)
195
+ chat_state = gr.State([])
196
 
197
  with gr.Row():
198
  # LEFT: INPUT
 
204
  value=example_high
205
  )
206
 
207
+ # EXAMPLES ROW (Restored)
208
+ gr.Markdown("### ๐Ÿ” Try Thesis Patterns")
209
+ with gr.Row():
210
+ btn_low = gr.Button("๐ŸŸข Low Risk", size="sm", variant="secondary")
211
+ btn_mod = gr.Button("๐ŸŸก Moderate", size="sm", variant="secondary")
212
+ btn_high = gr.Button("๐Ÿ”ด High Risk", size="sm", variant="secondary")
213
+
214
+ # SETTINGS ROW
215
+ gr.Markdown("### โš™๏ธ Settings")
216
  with gr.Row():
217
  loc_drop = gr.Dropdown(["Global", "US", "Malaysia"], value="Malaysia", label="Region")
218
  prov_drop = gr.Dropdown(["SambaNova", "Nebius"], value="SambaNova", label="Agent Brain")
 
224
 
225
  # RIGHT: DASHBOARD & CHAT
226
  with gr.Column(scale=1):
 
227
  dashboard = gr.HTML(label="Clinical Dashboard")
228
+ chatbot = gr.Chatbot(label="Agent Chat", height=400)
 
 
229
  msg_input = gr.Textbox(label="Chat with Agent", placeholder="Ask about your results or get advice...")
230
  send_btn = gr.Button("Send Message")
231
 
232
  # LOGIC WIRING
233
 
234
+ # 1. Analyze Button
235
  analyze_btn.click(
236
  run_analysis,
237
  inputs=[input_text, loc_drop, prov_drop],
238
+ outputs=[dashboard, chatbot, chat_state, risk_state]
239
  )
240
 
241
+ # 2. Example Buttons
242
+ btn_low.click(lambda: example_low, None, input_text)
243
+ btn_mod.click(lambda: example_mod, None, input_text)
244
+ btn_high.click(lambda: example_high, None, input_text)
245
+
246
+ # 3. Chat Interactions
247
  send_btn.click(
248
  user_chat,
249
+ inputs=[msg_input, chatbot, chat_state, risk_state, prov_drop],
250
+ outputs=[chatbot, chat_state, msg_input]
251
  )
252
  msg_input.submit(
253
  user_chat,
254
+ inputs=[msg_input, chatbot, chat_state, risk_state, prov_drop],
255
+ outputs=[chatbot, chat_state, msg_input]
256
  )
257
 
258
  if __name__ == "__main__":
259
+ demo.launch(
260
+ mcp_server=True,
261
+ theme=gr.themes.Soft()
262
+ )