Spaces:
Sleeping
Sleeping
File size: 8,411 Bytes
d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 d429968 3188e47 | 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 | import pandas as pd
import joblib
import gradio as gr
import json
import requests
MODEL_PATH = "risk_model.joblib"
ZAPIER_WEBHOOK_URL = "https://hooks.zapier.com/hooks/catch/27083565/uvtxiub/"
DISCLAIMER = (
"Educational demo only. This tool does not provide diagnosis, "
"prescriptions, or treatment plans. If symptoms are severe or urgent, seek emergency care."
)
RED_FLAGS = [
"chest pain",
"chest tightness",
"severe shortness of breath",
"fainting",
"loss of consciousness",
"stroke"
]
risk_model = joblib.load(MODEL_PATH)
def send_urgent_alert(symptom_text, risk_score):
try:
requests.post(ZAPIER_WEBHOOK_URL, json={
"triage_level": "urgent",
"symptom": symptom_text,
"risk_score": risk_score,
"message": "URGENT triage case detected by HealthBridge AI"
}, timeout=5)
except Exception:
pass
def assess(sexvar, educa, genhlth, menthlth, stress, sleep_hours, sleep_quality, duration_days, adherence_prob, symptom_text):
text_lower = str(symptom_text).lower()
red_flag_hit = any(flag in text_lower for flag in RED_FLAGS)
input_df = pd.DataFrame([{
"user_id": 0,
"SEXVAR": sexvar,
"EDUCA": educa,
"GENHLTH": genhlth,
"MENTHLTH": menthlth,
"stress_score_0_10": stress,
"sleep_hours": sleep_hours,
"sleep_quality_0_10": sleep_quality,
"symptom_duration_days": duration_days,
"adherence_prob": adherence_prob,
"symptom_text": symptom_text,
"triage_label": "medium"
}])
risk_score = float(risk_model.predict_proba(input_df)[0][1])
if red_flag_hit:
triage_level = "urgent"
elif risk_score >= 0.7:
triage_level = "high"
elif risk_score >= 0.4:
triage_level = "medium"
else:
triage_level = "low"
if triage_level == "urgent":
send_urgent_alert(symptom_text, round(risk_score, 3))
if triage_level == "urgent":
next_steps = [
"π¨ Seek emergency care immediately or call emergency services.",
"Do not drive yourself β ask someone nearby to help.",
"Do not wait to see if symptoms improve."
]
elif triage_level == "high":
next_steps = [
"Contact a healthcare provider as soon as possible.",
"Monitor symptoms closely and note any changes.",
"Seek emergency care if symptoms worsen rapidly."
]
elif triage_level == "medium":
next_steps = [
"Schedule an appointment with your doctor within the next few days.",
"Rest and monitor your symptoms.",
"Seek urgent care if symptoms escalate."
]
else:
next_steps = [
"Monitor symptoms and maintain healthy routines.",
"Seek professional care if symptoms persist beyond a week.",
"Stay hydrated and rest as needed."
]
LEVEL_COLORS = {
"urgent": "#FF2D2D",
"high": "#FF8C00",
"medium": "#F5C518",
"low": "#2ECC71"
}
LEVEL_BG = {
"urgent": "#FFF0F0",
"high": "#FFF5E6",
"medium": "#FFFBEA",
"low": "#F0FFF6"
}
LEVEL_ICONS = {
"urgent": "π¨",
"high": "β οΈ",
"medium": "πΆ",
"low": "β
"
}
color = LEVEL_COLORS[triage_level]
bg = LEVEL_BG[triage_level]
icon = LEVEL_ICONS[triage_level]
risk_pct = int(risk_score * 100)
bar_color = color
steps_html = "".join(f"<li style='margin-bottom:6px'>{s}</li>" for s in next_steps)
alert_banner = ""
if triage_level == "urgent":
alert_banner = f"""
<div style='background:#FF2D2D;color:white;padding:14px 18px;border-radius:8px;
font-weight:700;font-size:15px;letter-spacing:0.5px;margin-bottom:16px;
animation: pulse 1.5s infinite;'>
π¨ URGENT β An automated alert email has been sent.
</div>
"""
html = f"""
<style>
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap');
.hb-card * {{ font-family: 'DM Sans', sans-serif; box-sizing: border-box; }}
@keyframes pulse {{
0%, 100% {{ opacity: 1; }}
50% {{ opacity: 0.75; }}
}}
@keyframes fadeIn {{
from {{ opacity: 0; transform: translateY(8px); }}
to {{ opacity: 1; transform: translateY(0); }}
}}
.hb-card {{ animation: fadeIn 0.4s ease; }}
</style>
<div class='hb-card' style='background:{bg};border:2px solid {color};border-radius:12px;
padding:24px;max-width:600px;'>
{alert_banner}
<!-- Triage Level Badge -->
<div style='display:flex;align-items:center;gap:12px;margin-bottom:20px;'>
<span style='font-size:32px;'>{icon}</span>
<div>
<div style='font-size:11px;font-weight:600;color:#888;letter-spacing:1.5px;
text-transform:uppercase;'>Triage Level</div>
<div style='font-size:28px;font-weight:700;color:{color};line-height:1.1;'>
{triage_level.upper()}
</div>
</div>
</div>
<!-- Risk Score Bar -->
<div style='margin-bottom:20px;'>
<div style='display:flex;justify-content:space-between;margin-bottom:6px;'>
<span style='font-size:12px;font-weight:600;color:#555;text-transform:uppercase;
letter-spacing:1px;'>Risk Score</span>
<span style='font-size:14px;font-weight:700;color:{color};
font-family:"DM Mono",monospace;'>{risk_pct}%</span>
</div>
<div style='background:#E8E8E8;border-radius:99px;height:10px;overflow:hidden;'>
<div style='background:{bar_color};width:{risk_pct}%;height:100%;
border-radius:99px;transition:width 0.6s ease;'></div>
</div>
</div>
<!-- Red Flag -->
<div style='display:flex;align-items:center;gap:8px;margin-bottom:20px;
padding:10px 14px;background:white;border-radius:8px;
border:1px solid #E0E0E0;'>
<span style='font-size:16px;'>{"π©" if red_flag_hit else "βοΈ"}</span>
<span style='font-size:13px;font-weight:600;color:{"#FF2D2D" if red_flag_hit else "#2ECC71"};'>
Red Flag: {"DETECTED" if red_flag_hit else "None detected"}
</span>
</div>
<!-- Next Steps -->
<div style='margin-bottom:20px;'>
<div style='font-size:12px;font-weight:600;color:#555;letter-spacing:1px;
text-transform:uppercase;margin-bottom:10px;'>Recommended Next Steps</div>
<ul style='margin:0;padding-left:20px;color:#333;font-size:14px;line-height:1.6;'>
{steps_html}
</ul>
</div>
<!-- Disclaimer -->
<div style='font-size:11px;color:#999;border-top:1px solid #E0E0E0;
padding-top:12px;line-height:1.5;'>
β οΈ {DISCLAIMER}
</div>
</div>
"""
return html
demo = gr.Interface(
fn=assess,
inputs=[
gr.Dropdown([1, 2], value=1, label="Sex (BRFSS-coded)"),
gr.Slider(1, 6, value=4, step=1, label="Education level"),
gr.Slider(1, 5, value=3, step=1, label="General health"),
gr.Slider(0, 30, value=5, step=1, label="Mental health bad days"),
gr.Slider(0, 10, value=5, step=0.1, label="Stress score"),
gr.Slider(3, 10, value=7, step=0.1, label="Sleep hours"),
gr.Slider(0, 10, value=7, step=0.1, label="Sleep quality"),
gr.Slider(1, 30, value=5, step=1, label="Symptom duration (days)"),
gr.Slider(0.05, 0.95, value=0.65, step=0.01, label="Adherence probability"),
gr.Textbox(lines=4, placeholder="e.g. chest pain for 2 days, high stress, poor sleep", label="Symptom description")
],
outputs=gr.HTML(label="Triage Result"),
title="HealthBridge AI β Non-diagnostic Triage Demo",
description="Educational demo only. Not a substitute for professional medical advice.",
theme=gr.themes.Soft()
)
demo.launch() |