Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,58 +4,45 @@ from huggingface_hub import login
|
|
| 4 |
from openai import OpenAI
|
| 5 |
import os
|
| 6 |
|
| 7 |
-
# --- 1.
|
| 8 |
-
# Authenticate Hugging Face (for your private Mental-Longformer)
|
| 9 |
hf_token = os.getenv("HF_TOKEN")
|
| 10 |
if hf_token:
|
| 11 |
login(token=hf_token)
|
| 12 |
|
| 13 |
-
# --- 2.
|
| 14 |
print("Loading Mental-Longformer...")
|
| 15 |
model_name = "avtak/erisk-longformer-depression-v1"
|
| 16 |
classifier = pipeline("text-classification", model=model_name, truncation=True, max_length=4096, top_k=None)
|
| 17 |
|
| 18 |
-
# --- 3.
|
| 19 |
|
| 20 |
def get_crisis_resources(location: str = "Global") -> str:
|
| 21 |
-
"""
|
| 22 |
-
MCP Tool: Returns mental health resources based on location.
|
| 23 |
-
"""
|
| 24 |
resources = {
|
| 25 |
-
"US": "πΊπΈ **US
|
| 26 |
-
"Malaysia": "π²πΎ **Malaysia
|
| 27 |
-
"Global": "π **International
|
| 28 |
}
|
|
|
|
| 29 |
for key in resources:
|
| 30 |
-
if key.lower() in location.lower():
|
| 31 |
return resources[key]
|
| 32 |
return resources["Global"]
|
| 33 |
|
| 34 |
def detect_depression_risk(text: str) -> dict:
|
| 35 |
-
"""
|
| 36 |
-
|
| 37 |
-
Returns probability, risk level, and word count.
|
| 38 |
-
"""
|
| 39 |
-
# Thesis Logic: User-Level Aggregation simulation
|
| 40 |
processed_text = text.replace("\n", "\n\n")
|
| 41 |
results = classifier(processed_text)[0]
|
| 42 |
prob = next((r['score'] for r in results if r['label'] == 'LABEL_1'), 0)
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
elif 0.40 <= prob < 0.60:
|
| 48 |
-
level = "Moderate Risk (Interactive Echo Chamber Pattern)"
|
| 49 |
-
else:
|
| 50 |
-
level = "High Risk (Depressed Cohort Pattern)"
|
| 51 |
|
| 52 |
-
return {
|
| 53 |
-
"probability": prob,
|
| 54 |
-
"risk_level": level,
|
| 55 |
-
"word_count": len(processed_text.split())
|
| 56 |
-
}
|
| 57 |
|
| 58 |
-
# --- 4. AGENT REASONING (
|
| 59 |
def agent_reasoning(text, risk_data, provider="SambaNova"):
|
| 60 |
"""
|
| 61 |
Uses Sponsor APIs to interpret the clinical data.
|
|
@@ -63,21 +50,21 @@ def agent_reasoning(text, risk_data, provider="SambaNova"):
|
|
| 63 |
client = None
|
| 64 |
model = None
|
| 65 |
|
| 66 |
-
# SYSTEM PROMPT
|
| 67 |
system_prompt = f"""
|
| 68 |
-
You are an empathetic Clinical AI
|
| 69 |
|
| 70 |
CLINICAL DATA (Mental-Longformer):
|
| 71 |
- Risk Level: {risk_data['risk_level']}
|
| 72 |
- Probability: {risk_data['probability']:.1%}
|
| 73 |
- Input Length: {risk_data['word_count']} words
|
| 74 |
|
| 75 |
-
USER TEXT: "{text[:
|
| 76 |
|
| 77 |
INSTRUCTIONS:
|
| 78 |
-
1.
|
| 79 |
-
2.
|
| 80 |
-
3. Max
|
| 81 |
"""
|
| 82 |
|
| 83 |
try:
|
|
@@ -87,75 +74,71 @@ def agent_reasoning(text, risk_data, provider="SambaNova"):
|
|
| 87 |
if not api_key: return "β οΈ Nebius API Key missing."
|
| 88 |
|
| 89 |
client = OpenAI(base_url="https://api.tokenfactory.nebius.com/v1/", api_key=api_key)
|
| 90 |
-
|
|
|
|
| 91 |
|
| 92 |
-
# --- SPONSOR 2: SAMBANOVA (Llama 3.
|
| 93 |
elif provider == "SambaNova":
|
| 94 |
api_key = os.getenv("SAMBANOVA_API_KEY")
|
| 95 |
if not api_key: return "β οΈ SambaNova API Key missing."
|
| 96 |
|
| 97 |
client = OpenAI(base_url="https://api.sambanova.ai/v1", api_key=api_key)
|
| 98 |
-
|
|
|
|
| 99 |
|
| 100 |
# EXECUTE
|
| 101 |
response = client.chat.completions.create(
|
| 102 |
model=model,
|
| 103 |
messages=[
|
| 104 |
{"role": "system", "content": system_prompt},
|
| 105 |
-
{"role": "user", "content": "Analyze this
|
| 106 |
],
|
| 107 |
temperature=0.6,
|
| 108 |
-
max_tokens=
|
| 109 |
)
|
| 110 |
return response.choices[0].message.content
|
| 111 |
|
| 112 |
except Exception as e:
|
| 113 |
-
return f"
|
| 114 |
|
| 115 |
-
# --- 5.
|
| 116 |
def full_analysis_pipeline(user_text, location, provider):
|
| 117 |
if not user_text.strip(): return "Please enter text.", "No data", "No data"
|
| 118 |
|
| 119 |
-
# 1. Tool Use (Local Model)
|
| 120 |
risk_data = detect_depression_risk(user_text)
|
| 121 |
-
|
| 122 |
-
# 2. Tool Use (Resources)
|
| 123 |
resources = get_crisis_resources(location)
|
| 124 |
-
|
| 125 |
-
# 3. Agent Reasoning (Cloud API)
|
| 126 |
explanation = agent_reasoning(user_text, risk_data, provider)
|
| 127 |
|
|
|
|
|
|
|
|
|
|
| 128 |
return f"""
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
| 131 |
|
| 132 |
### π§ Agent Analysis ({provider})
|
| 133 |
{explanation}
|
| 134 |
|
| 135 |
-
### π Resources
|
| 136 |
{resources}
|
| 137 |
"""
|
| 138 |
|
| 139 |
-
# --- 6. EXAMPLES
|
| 140 |
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.
|
| 141 |
-
|
| 142 |
On a different note, the defensive stats for the basketball team have improved significantly. Allowing 15% fewer points per possession is a game changer.
|
| 143 |
-
|
| 144 |
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."""
|
| 145 |
|
| 146 |
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.
|
| 147 |
-
|
| 148 |
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.
|
| 149 |
-
|
| 150 |
-
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."""
|
| 151 |
|
| 152 |
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.
|
| 153 |
-
|
| 154 |
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.
|
| 155 |
-
|
| 156 |
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."""
|
| 157 |
|
| 158 |
-
# --- 7. UI
|
| 159 |
with gr.Blocks(title="Depression Risk Agent") as demo:
|
| 160 |
gr.Markdown("# π§ Early Depression Detection Agent (MCP)")
|
| 161 |
gr.Markdown("Agentic system using **Mental-Longformer** (Tool) + **Multi-Provider Reasoning** (Nebius/SambaNova).")
|
|
@@ -169,18 +152,17 @@ with gr.Blocks(title="Depression Risk Agent") as demo:
|
|
| 169 |
placeholder="[Post 1] ...\n\n[Post 2] ...\n\n(Context >100 words recommended)"
|
| 170 |
)
|
| 171 |
|
| 172 |
-
|
| 173 |
-
gr.Markdown("### 2. Try Thesis Patterns")
|
| 174 |
with gr.Row():
|
| 175 |
btn_low = gr.Button("π’ Low Risk", size="sm", variant="secondary")
|
| 176 |
btn_mod = gr.Button("π‘ Moderate", size="sm", variant="secondary")
|
| 177 |
btn_high = gr.Button("π΄ High Risk", size="sm", variant="secondary")
|
| 178 |
|
| 179 |
-
|
| 180 |
-
gr.Markdown("### 3. Settings")
|
| 181 |
with gr.Row():
|
| 182 |
-
|
| 183 |
-
|
|
|
|
| 184 |
|
| 185 |
submit = gr.Button("π Run Analysis Agent", variant="primary", size="lg")
|
| 186 |
|
|
@@ -195,16 +177,11 @@ with gr.Blocks(title="Depression Risk Agent") as demo:
|
|
| 195 |
- `get_crisis_resources(location)`: Returns localized help.
|
| 196 |
""")
|
| 197 |
|
| 198 |
-
# HANDLERS
|
| 199 |
submit.click(full_analysis_pipeline, inputs=[input_text, loc_dropdown, provider_dropdown], outputs=output)
|
| 200 |
|
| 201 |
btn_low.click(lambda: example_low, None, input_text)
|
| 202 |
btn_mod.click(lambda: example_mod, None, input_text)
|
| 203 |
btn_high.click(lambda: example_high, None, input_text)
|
| 204 |
|
| 205 |
-
# --- 8. LAUNCH ---
|
| 206 |
if __name__ == "__main__":
|
| 207 |
-
demo.launch(
|
| 208 |
-
mcp_server=True,
|
| 209 |
-
theme=gr.themes.Soft()
|
| 210 |
-
)
|
|
|
|
| 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. TOOL LOADING ---
|
| 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 |
+
# Fallback logic
|
| 27 |
for key in resources:
|
| 28 |
+
if location and key.lower() in location.lower():
|
| 29 |
return resources[key]
|
| 30 |
return resources["Global"]
|
| 31 |
|
| 32 |
def detect_depression_risk(text: str) -> dict:
|
| 33 |
+
"""Analyzes text using Mental-Longformer (eRisk 2025)."""
|
| 34 |
+
# Thesis Aggregation Logic
|
|
|
|
|
|
|
|
|
|
| 35 |
processed_text = text.replace("\n", "\n\n")
|
| 36 |
results = classifier(processed_text)[0]
|
| 37 |
prob = next((r['score'] for r in results if r['label'] == 'LABEL_1'), 0)
|
| 38 |
|
| 39 |
+
if prob < 0.40: level = "Low Risk (Isolated Pattern)"
|
| 40 |
+
elif 0.40 <= prob < 0.60: level = "Moderate Risk (Echo Chamber Pattern)"
|
| 41 |
+
else: level = "High Risk (Depressed Pattern)"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
+
return {"probability": prob, "risk_level": level, "word_count": len(processed_text.split())}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
+
# --- 4. AGENT REASONING (UPDATED MODELS) ---
|
| 46 |
def agent_reasoning(text, risk_data, provider="SambaNova"):
|
| 47 |
"""
|
| 48 |
Uses Sponsor APIs to interpret the clinical data.
|
|
|
|
| 50 |
client = None
|
| 51 |
model = None
|
| 52 |
|
| 53 |
+
# SYSTEM PROMPT (Thesis-Informed)
|
| 54 |
system_prompt = f"""
|
| 55 |
+
You are an empathetic Clinical AI Agent.
|
| 56 |
|
| 57 |
CLINICAL DATA (Mental-Longformer):
|
| 58 |
- Risk Level: {risk_data['risk_level']}
|
| 59 |
- Probability: {risk_data['probability']:.1%}
|
| 60 |
- Input Length: {risk_data['word_count']} words
|
| 61 |
|
| 62 |
+
USER TEXT SNIPPET: "{text[:800]}..."
|
| 63 |
|
| 64 |
INSTRUCTIONS:
|
| 65 |
+
1. Acknowledge the user's situation based on the text.
|
| 66 |
+
2. Explain the risk level using thesis terms: 'Nocturnal Posting' (High), 'Supportive Responder' (Moderate), or 'Healthy External Focus' (Low).
|
| 67 |
+
3. Be compassionate. Max 80 words.
|
| 68 |
"""
|
| 69 |
|
| 70 |
try:
|
|
|
|
| 74 |
if not api_key: return "β οΈ Nebius API Key missing."
|
| 75 |
|
| 76 |
client = OpenAI(base_url="https://api.tokenfactory.nebius.com/v1/", api_key=api_key)
|
| 77 |
+
# Using the chat version of Kimi K2
|
| 78 |
+
model = "moonshotai/Kimi-K2-Chat"
|
| 79 |
|
| 80 |
+
# --- SPONSOR 2: SAMBANOVA (Llama 3.3) ---
|
| 81 |
elif provider == "SambaNova":
|
| 82 |
api_key = os.getenv("SAMBANOVA_API_KEY")
|
| 83 |
if not api_key: return "β οΈ SambaNova API Key missing."
|
| 84 |
|
| 85 |
client = OpenAI(base_url="https://api.sambanova.ai/v1", api_key=api_key)
|
| 86 |
+
# UPDATED MODEL ID
|
| 87 |
+
model = "Meta-Llama-3.3-70B-Instruct"
|
| 88 |
|
| 89 |
# EXECUTE
|
| 90 |
response = client.chat.completions.create(
|
| 91 |
model=model,
|
| 92 |
messages=[
|
| 93 |
{"role": "system", "content": system_prompt},
|
| 94 |
+
{"role": "user", "content": "Analyze this."}
|
| 95 |
],
|
| 96 |
temperature=0.6,
|
| 97 |
+
max_tokens=200
|
| 98 |
)
|
| 99 |
return response.choices[0].message.content
|
| 100 |
|
| 101 |
except Exception as e:
|
| 102 |
+
return f"Reasoning Error ({provider}): {str(e)}"
|
| 103 |
|
| 104 |
+
# --- 5. PIPELINE ---
|
| 105 |
def full_analysis_pipeline(user_text, location, provider):
|
| 106 |
if not user_text.strip(): return "Please enter text.", "No data", "No data"
|
| 107 |
|
|
|
|
| 108 |
risk_data = detect_depression_risk(user_text)
|
|
|
|
|
|
|
| 109 |
resources = get_crisis_resources(location)
|
|
|
|
|
|
|
| 110 |
explanation = agent_reasoning(user_text, risk_data, provider)
|
| 111 |
|
| 112 |
+
# Color logic
|
| 113 |
+
color = "green" if risk_data['probability'] < 0.4 else "orange" if risk_data['probability'] < 0.6 else "red"
|
| 114 |
+
|
| 115 |
return f"""
|
| 116 |
+
<div style="border-left: 5px solid {color}; padding-left: 10px;">
|
| 117 |
+
<h2 style="color:{color}; margin:0;">{risk_data['risk_level']}</h2>
|
| 118 |
+
<h3 style="margin-top:0;">Probability: {risk_data['probability']*100:.1f}%</h3>
|
| 119 |
+
</div>
|
| 120 |
|
| 121 |
### π§ Agent Analysis ({provider})
|
| 122 |
{explanation}
|
| 123 |
|
| 124 |
+
### π Recommended Resources
|
| 125 |
{resources}
|
| 126 |
"""
|
| 127 |
|
| 128 |
+
# --- 6. EXAMPLES ---
|
| 129 |
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.
|
|
|
|
| 130 |
On a different note, the defensive stats for the basketball team have improved significantly. Allowing 15% fewer points per possession is a game changer.
|
|
|
|
| 131 |
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."""
|
| 132 |
|
| 133 |
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.
|
|
|
|
| 134 |
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.
|
| 135 |
+
Went hiking with some friends last weekend which was nice. Good to get outside and move around."""
|
|
|
|
| 136 |
|
| 137 |
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.
|
|
|
|
| 138 |
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.
|
|
|
|
| 139 |
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."""
|
| 140 |
|
| 141 |
+
# --- 7. UI ---
|
| 142 |
with gr.Blocks(title="Depression Risk Agent") as demo:
|
| 143 |
gr.Markdown("# π§ Early Depression Detection Agent (MCP)")
|
| 144 |
gr.Markdown("Agentic system using **Mental-Longformer** (Tool) + **Multi-Provider Reasoning** (Nebius/SambaNova).")
|
|
|
|
| 152 |
placeholder="[Post 1] ...\n\n[Post 2] ...\n\n(Context >100 words recommended)"
|
| 153 |
)
|
| 154 |
|
| 155 |
+
gr.Markdown("### 2. Thesis Patterns (Click to Load)")
|
|
|
|
| 156 |
with gr.Row():
|
| 157 |
btn_low = gr.Button("π’ Low Risk", size="sm", variant="secondary")
|
| 158 |
btn_mod = gr.Button("π‘ Moderate", size="sm", variant="secondary")
|
| 159 |
btn_high = gr.Button("π΄ High Risk", size="sm", variant="secondary")
|
| 160 |
|
| 161 |
+
gr.Markdown("### 3. Agent Settings")
|
|
|
|
| 162 |
with gr.Row():
|
| 163 |
+
# RENAMED to be clearer
|
| 164 |
+
loc_dropdown = gr.Dropdown(["Global", "US", "Malaysia"], value="Global", label="Crisis Resource Region")
|
| 165 |
+
provider_dropdown = gr.Dropdown(["SambaNova", "Nebius (Kimi K2)"], value="SambaNova", label="Reasoning Brain")
|
| 166 |
|
| 167 |
submit = gr.Button("π Run Analysis Agent", variant="primary", size="lg")
|
| 168 |
|
|
|
|
| 177 |
- `get_crisis_resources(location)`: Returns localized help.
|
| 178 |
""")
|
| 179 |
|
|
|
|
| 180 |
submit.click(full_analysis_pipeline, inputs=[input_text, loc_dropdown, provider_dropdown], outputs=output)
|
| 181 |
|
| 182 |
btn_low.click(lambda: example_low, None, input_text)
|
| 183 |
btn_mod.click(lambda: example_mod, None, input_text)
|
| 184 |
btn_high.click(lambda: example_high, None, input_text)
|
| 185 |
|
|
|
|
| 186 |
if __name__ == "__main__":
|
| 187 |
+
demo.launch(mcp_server=True, theme=gr.themes.Soft())
|
|
|
|
|
|
|
|
|