Spaces:
Sleeping
Sleeping
File size: 6,110 Bytes
f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 5ed20c1 f503df8 | 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 | import gradio as gr
import json
CUSTOM_CSS = """
.metric-card {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(10px);
border: 1px solid rgba(226, 232, 240, 0.8);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
}
.dark .metric-card {
background: rgba(30, 41, 59, 0.85);
border-color: rgba(51, 65, 85, 0.8);
}
.status-pill {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.875rem;
font-weight: 600;
}
.status-pill.success { background: #dcfce7; color: #166534; }
.status-pill.error { background: #fee2e2; color: #991b1b; }
.status-pill.info { background: #dbeafe; color: #1e3a8a; }
.dark .status-pill.success { background: #14532d; color: #bbf7d0; }
.dark .status-pill.error { background: #7f1d1d; color: #fecaca; }
.dark .status-pill.info { background: #1e3a8a; color: #bfdbfe; }
"""
def build_triage_ui(web_manager, action_fields, metadata, is_chat_env, title, quick_start_md):
with gr.Blocks(css=CUSTOM_CSS) as blocks:
gr.Markdown(f"# π₯ {title} β Clinical Dashboard")
gr.Markdown(
"Patients arrive one at a time. **Classify** each patient and **reorder the priority queue**. "
"Use ESCALATE for patients with missing critical data."
)
current_state = gr.State({})
with gr.Row():
task_dropdown = gr.Dropdown(
choices=["basic-triage", "incomplete-records-triage", "mass-casualty-triage"],
label="Scenario",
value="basic-triage",
interactive=True,
)
reset_btn = gr.Button("π Initialize Scenario", variant="primary")
with gr.Row():
with gr.Column(scale=2):
with gr.Group(elem_classes="metric-card"):
gr.Markdown("### π« Incoming Patient")
patient_md = gr.Markdown("*Press Initialize to start*")
with gr.Group(elem_classes="metric-card"):
gr.Markdown("### π Current Priority Queue")
queue_md = gr.Markdown("*Empty*")
feedback_md = gr.Markdown("")
with gr.Column(scale=1):
with gr.Group(elem_classes="metric-card"):
gr.Markdown("### β‘ Triage Decision")
classification = gr.Dropdown(
choices=["immediate", "urgent", "less_urgent", "non_urgent", "escalate"],
label="Classification",
value="urgent",
)
queue_input = gr.Textbox(
label="Reordered Queue (comma-separated patient IDs)",
placeholder="P001, P003, P002",
)
submit_btn = gr.Button("π Submit", variant="primary")
with gr.Group(elem_classes="metric-card"):
gr.Markdown("### π Event Log")
log_md = gr.Markdown("No actions yet.")
def format_patient(obs):
pt = obs.get("incoming_patient", {})
if not pt:
return "**No more patients.**"
vitals = pt.get("vitals")
v_str = ", ".join(f"**{k}**: {v}" for k, v in vitals.items()) if vitals else "β οΈ **MISSING**"
step = obs.get("step_number", 0) + 1
total = obs.get("total_expected_patients", 0)
return (
f"**Step {step}/{total}** β ID: `{pt.get('patient_id')}` | Age: {pt.get('age')}\n\n"
f"**Complaint:** {pt.get('chief_complaint')}\n\n"
f"**Symptoms:** {', '.join(pt.get('symptoms', []))}\n\n"
f"**Vitals:** {v_str}\n\n"
f"**History:** {pt.get('history', 'N/A')} | **Meds:** {pt.get('medications', 'N/A')}"
)
def format_queue(queue):
if not queue:
return "π *Empty queue*"
return " β ".join(f"`{pid}`" for pid in queue)
async def ui_reset(task_name):
try:
res = await web_manager.reset_environment({"task_name": task_name})
obs = res.get("observation", {})
q = obs.get("current_queue", [])
fb = obs.get("previous_feedback", "")
return [res, format_patient(obs), format_queue(q), fb, "No actions yet."]
except Exception as e:
return [{}, f"Error: {e}", "*Empty*", "", ""]
async def ui_step(cls, q_text, st):
obs = st.get("observation", {})
pt = obs.get("incoming_patient", {})
pid = pt.get("patient_id", "") if pt else ""
queue_ids = [x.strip() for x in q_text.split(",") if x.strip()] if q_text.strip() else []
payload = {"classification": cls, "reordered_queue": queue_ids}
try:
res = await web_manager.step_environment(payload)
obs2 = res.get("observation", {})
q = obs2.get("current_queue", [])
fb = obs2.get("previous_feedback", "")
logs = getattr(web_manager.episode_state, "action_logs", [])
log_str = ""
for log in reversed(logs[-8:]):
r = log.reward
d = log.done
a_cls = log.action.get("classification", "?")
st_str = "π Done" if d else f"R={r:.2f}"
log_str += f"- **{a_cls}** β `{pid}` | {st_str}\n"
return [res, format_patient(obs2), format_queue(q), fb, log_str or "No actions yet."]
except Exception as e:
return [st, f"Error: {e}", "", "", ""]
outputs = [current_state, patient_md, queue_md, feedback_md, log_md]
reset_btn.click(fn=ui_reset, inputs=[task_dropdown], outputs=outputs)
submit_btn.click(fn=ui_step, inputs=[classification, queue_input, current_state], outputs=outputs)
return blocks
|