-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
The TriageEngine in src/medex/medical/triage.py is a complete 567-line rule-based ESI triage engine that is never called by the API. The /api/v1/triage/assess endpoint in run_api.py ignores the engine entirely — it sends a free-text prompt to the LLM, attempts fragile regex parsing of the response, and returns hardcoded empty arrays for red_flags and vital_concerns. This makes triage non-functional.
Beyond wiring, a clinical audit against the ESI Handbook v4 (Gilboy et al.) reveals significant protocol deviations that must be corrected for the engine to produce clinically valid assessments.
Current Behavior
- User fills in triage form (chief complaint, vitals, pain level) → UI POSTs to
/api/v1/triage/assess - Endpoint converts structured vitals to a text string, sends to
medex_app.query()(generic LLM call) - Attempts
re.search(r"esi[:\s-]*(\d)", response_text)to extract ESI level — fails because the LLM responds in Spanish and rarely outputs "ESI" literally - Falls back to keyword matching (
"resucitación","crítico") — equally unreliable red_flags: []andvital_concerns: []are always hardcoded empty- Response takes 5-30 seconds (LLM round-trip) for what should be an instantaneous deterministic assessment
Expected Behavior
- Endpoint instantiates
TriageEngineand callsengine.assess()directly - Returns structured
TriageAssessment.to_dict()with real red flags, discriminators, disposition recommendations - Assessment is deterministic, instantaneous, and clinically aligned with ESI v4
Technical Tasks
A. Wire TriageEngine to API Endpoint
- Replace LLM call in
/api/v1/triage/assess(run_api.pyL696-747) with directTriageEngine.assess()call - Map UI vital field names to
VitalSignsdataclass fields:bp_systolic→blood_pressure_systolicbp_diastolic→blood_pressure_diastolicspo2→oxygen_saturation
- Return full
TriageAssessment.to_dict()(includesred_flags,discriminators,disposition,recommended_action) - Fix
MedicalService.is_emergency()signature mismatch — callsTriageEngine.is_emergency(chief_complaint=..., vital_signs=...)but actual signature is(self, text: str)
B. Clinical Hardening — ESI v4 Alignment
-
Fix ESI algorithm flow — The real ESI algorithm verifies vital signs in "danger zone" after estimating ≥2 resources (ESI 3), and upgrades to ESI 2 if vitals are abnormal. The current engine does not perform this post-resource vital sign recheck. Ref: ESI Handbook v4, Decision Point D.
-
Align vital sign thresholds to ESI danger zone:
Vital Sign Current (Critical) ESI Danger Zone Heart Rate >150 / <40 >100 / <50 Systolic BP <80 <90 SpO₂ <88% <92% Resp Rate >35 / <8 >20 / <10 -
GCS 9-13 → ESI 2 — Currently only GCS <9 triggers Level 1. GCS 9-13 (altered sensorium, responds to stimuli) should classify as ESI 2 per protocol.
-
Pain ≥7 as independent ESI 2 discriminator — ESI: "high risk / confused / lethargic / disoriented OR severe pain/distress." Currently pain_scale is only checked inside
_check_high_risk_vitals. Should be an independent Decision Point B check. -
Resource estimation: clinical heuristics, not patient keywords — The current engine searches the patient's text for words like "radiografía" or "laboratorio." The patient doesn't know what resources they need. Implement clinical heuristic mapping:
- Headache + fever → labs + imaging = 2 resources = ESI 3
- Laceration → suture = 1 resource = ESI 4
- Sore throat (no red flags, normal vitals) → 0 resources = ESI 5
-
Improve red flag matching robustness — Current
if flag in textmisses"me duele el pecho"(only matches"dolor de pecho"). Add synonym lists, partial matching, or at minimum expand the sets. -
Age-adjusted vital sign thresholds — HR 140 in a 2-year-old is normal; in a 70-year-old it's critical. At minimum add adult vs. pediatric threshold sets.
-
Missing ESI 2 presentations — Add: acute psychiatric danger to self/others, sexual assault, fever + immunosuppression, acute abdomen in >65y, obstetric emergencies (eclampsia, ectopic, abruption).
Files Affected
| File | Change |
|---|---|
run_api.py (L696-747) |
Replace LLM call with TriageEngine |
src/medex/medical/triage.py |
Clinical hardening (thresholds, flow, resource heuristics) |
src/medex/medical/models.py |
Add age-based threshold support to VitalSigns if needed |
src/medex/medical/service.py (L228) |
Fix is_emergency() signature |
tests/ |
New tests validating ESI classification against known clinical scenarios |
Clinical References
- Gilboy N, Tanabe T, Travers D, Rosenau AM. Emergency Severity Index (ESI): A Triage Tool for Emergency Department Care. Version 4. AHRQ Publication No. 12-0014. 2012.
- ESI Implementation Handbook, Chapter 2: The ESI Algorithm.