StrongCapybara's picture
feat: complete environment redesign β€” classification + queue output model
5ed20c1
Raw
History Blame Contribute Delete
6.11 kB
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