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()