| """Quick validation tests for MedTriage environment endpoints.""" |
| import httpx |
| import json |
|
|
| BASE = "http://127.0.0.1:7860" |
| ALL_PASS = True |
|
|
|
|
| def check(name, condition, detail=""): |
| global ALL_PASS |
| detail_str = f" ({detail})" if detail else "" |
| if condition: |
| print(f" PASS: {name}{detail_str}") |
| else: |
| print(f" FAIL: {name}{detail_str}") |
| ALL_PASS = False |
|
|
|
|
| print("\n=== MedTriage Validation Tests ===\n") |
|
|
| |
| r = httpx.get(f"{BASE}/health", timeout=10) |
| check("Health endpoint returns 200", r.status_code == 200, r.json().get("status")) |
|
|
| r = httpx.get(f"{BASE}/tasks", timeout=10) |
| tasks = [t["id"] for t in r.json()["tasks"]] |
| check("3 tasks available", len(tasks) == 3, str(tasks)) |
| check("vital-triage task exists", "vital-triage" in tasks) |
| check("differential-diagnosis task exists", "differential-diagnosis" in tasks) |
| check("treatment-safety task exists", "treatment-safety" in tasks) |
|
|
| |
| print("\nββ Task 1: vital-triage ββ") |
| r = httpx.post(f"{BASE}/reset", json={"task": "vital-triage"}, timeout=10) |
| check("Task 1 reset returns 200", r.status_code == 200) |
| obs = r.json()["observation"] |
| check("Observation has patient", "patient" in r.json()["observation"]) |
| check("Observation has task_instruction", bool(obs.get("task_instruction"))) |
| check("Observation has vitals", obs["patient"]["vitals"]["heart_rate"] is not None) |
|
|
| |
| r = httpx.post(f"{BASE}/step", json={"esi_level": 1, "triage_reason": "hypotension severe"}, timeout=10) |
| check("Step returns 200", r.status_code == 200) |
| step = r.json() |
| check("Step returns reward in [0,1]", 0.0 <= step["reward"] <= 1.0, f"reward={step['reward']}") |
| check("Step done=True after action", step["done"] == True) |
|
|
| |
| httpx.post(f"{BASE}/reset", json={"task": "vital-triage"}, timeout=10) |
| r = httpx.post(f"{BASE}/step", json={"esi_level": 5, "triage_reason": "seems ok"}, timeout=10) |
| step = r.json() |
| check("Wrong ESI gets lower reward", step["reward"] <= 0.5, f"reward={step['reward']}") |
|
|
| |
| print("\nββ Task 2: differential-diagnosis ββ") |
| r = httpx.post(f"{BASE}/reset", json={"task": "differential-diagnosis"}, timeout=10) |
| check("Task 2 reset returns 200", r.status_code == 200) |
|
|
| r = httpx.post(f"{BASE}/step", json={ |
| "diagnoses": ["STEMI", "NSTEMI", "Aortic dissection"], |
| "red_flags": ["ST elevation", "elevated troponin", "hypotension", "diaphoresis"], |
| "recommended_tests": ["12-lead ECG", "Troponin", "CXR"] |
| }, timeout=10) |
| step = r.json() |
| check("Task 2 step returns 200", r.status_code == 200) |
| check("Task 2 reward in [0,1]", 0.0 <= step["reward"] <= 1.0, f"reward={step['reward']}") |
|
|
| |
| print("\n-- Task 3: treatment-safety --") |
| r = httpx.post(f"{BASE}/reset", json={"task": "treatment-safety"}, timeout=10) |
| check("Task 3 reset returns 200", r.status_code == 200) |
| obs = r.json()["observation"] |
| check("Diagnosis context provided", "diagnosis_context" in obs.get("context", {})) |
|
|
| |
| t3_correct_pass = False |
| t3_contra_pass = False |
| for _ in range(20): |
| r = httpx.post(f"{BASE}/reset", json={"task": "treatment-safety"}, timeout=10) |
| pid = r.json()["observation"]["patient"]["patient_id"] |
| if pid == "T001" and not t3_correct_pass: |
| r2 = httpx.post(f"{BASE}/step", json={ |
| "diagnosis": "STEMI", |
| "drug_name": "aspirin", |
| "dose_mg": 300, |
| "route": "PO", |
| "rationale": "dual antiplatelet therapy" |
| }, timeout=10) |
| step = r2.json() |
| check("Task 3 correct drug (aspirin for STEMI) reward >= 0.6", step["reward"] >= 0.6, f"reward={step['reward']}") |
| t3_correct_pass = True |
|
|
| if pid == "T004" and not t3_contra_pass: |
| r2 = httpx.post(f"{BASE}/step", json={ |
| "diagnosis": "Status asthmaticus", |
| "drug_name": "aspirin", |
| "dose_mg": 300, |
| "route": "PO", |
| "rationale": "anti-inflammatory" |
| }, timeout=10) |
| step = r2.json() |
| check("Contraindicated drug (aspirin in NSAID-allergy) returns 0.0", step["reward"] == 0.0, f"reward={step['reward']}") |
| t3_contra_pass = True |
|
|
| if t3_correct_pass and t3_contra_pass: |
| break |
|
|
| if not t3_correct_pass: |
| check("Task 3 correct drug test ran", False, "T001 patient not drawn in 20 tries") |
| if not t3_contra_pass: |
| check("Task 3 contraindication test ran", False, "T004 patient not drawn in 20 tries") |
|
|
|
|
| |
| print("\nββ State endpoint ββ") |
| r = httpx.get(f"{BASE}/state", timeout=10) |
| check("State returns 200", r.status_code == 200) |
| state = r.json() |
| check("State has episode_id", bool(state.get("episode_id"))) |
| check("State has step_count", "step_count" in state) |
| check("State has cumulative_reward", "cumulative_reward" in state) |
|
|
| |
| print() |
| if ALL_PASS: |
| print("β
ALL TESTS PASSED β Environment is working correctly!") |
| else: |
| print("β SOME TESTS FAILED β Check output above.") |
|
|