satiregram/HealthDataOps-Env
0
1#!/usr/bin/env python32"""3Gradio interactive demo for HealthDataOps-Env.4Deployed as a Hugging Face Space with tag: openenv5 6Run locally:7 PYTHONPATH=. python3 app.py8"""9 10import os11import sys12import json13 14sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))15 16import gradio as gr17from env.health_data_ops_env import HealthDataOpsEnv18 19# ─── Helpers ──────────────────────────────────────────────────────────────────20 21def format_obs(obs: dict) -> str:22 return json.dumps(obs, indent=2)23 24def run_task1(is_valid: bool, issue_type: str, issue_desc: str):25 env = HealthDataOpsEnv()26 obs, info = env.reset()27 obs_str = format_obs(obs)28 29 issues = []30 if issue_type != "none" and issue_desc.strip():31 issues.append({"issue_type": issue_type, "description": issue_desc.strip()})32 33 action = {"is_valid": is_valid, "issues": issues}34 _, reward, _, info2 = env.step(action)35 36 result = {37 "task": info2["task_completed"],38 "reward": round(reward, 3),39 "action_submitted": action40 }41 return obs_str, json.dumps(result, indent=2)42 43def run_task2(anomaly_types_raw: str):44 env = HealthDataOpsEnv()45 obs, info = env.reset()46 # Skip task 1 quickly47 env.step({"is_valid": True, "issues": []})48 # Now task 249 obs, info = env._load_current_task()50 obs_str = format_obs(obs)51 52 records = obs.get("batch_records", [])53 lines = [l.strip() for l in anomaly_types_raw.strip().splitlines() if l.strip()]54 severity_map = {55 "none": "low", "missing_field": "medium",56 "outlier_vital": "high", "privacy_risk_pii": "high", "duplicate": "low"57 }58 anomalies = []59 for i, rec in enumerate(records):60 atype = lines[i] if i < len(lines) else "none"61 atype = atype if atype in severity_map else "none"62 anomalies.append({63 "record_id": rec["record_id"],64 "anomaly_type": atype,65 "severity": severity_map[atype],66 "suggested_action": "Review record.",67 "confidence_score": 0.868 })69 70 action = {"anomalies": anomalies}71 _, reward, _, info2 = env.step(action)72 result = {"task": info2["task_completed"], "reward": round(reward, 3)}73 return obs_str, json.dumps(result, indent=2)74 75def run_task3(risk: str, diet: str, activity: str, med_timing: str):76 env = HealthDataOpsEnv()77 obs, _ = env.reset()78 env.step({"is_valid": True, "issues": []})79 dummy_records = [{"record_id": "X", "anomaly_type": "none", "severity": "low",80 "suggested_action": "N/A", "confidence_score": 0.5}]81 env.step({"anomalies": dummy_records})82 obs, info = env._load_current_task()83 obs_str = format_obs(obs)84 85 action = {86 "risk_assessment": risk,87 "dietary_adjustments": diet,88 "medication_timing_adjustments": med_timing if med_timing.strip() else None,89 "safe_activity_recommendation": activity90 }91 _, reward, _, info2 = env.step(action)92 result = {"task": info2["task_completed"], "reward": round(reward, 3)}93 return obs_str, json.dumps(result, indent=2)94 95def run_full_heuristic():96 """Run the full heuristic baseline and return results."""97 from baseline.run_baseline import (98 HealthDataOpsEnv, heuristic_task1, heuristic_task2, heuristic_task399 )100 env = HealthDataOpsEnv()101 obs, info = env.reset()102 dispatch = [heuristic_task1, heuristic_task2, heuristic_task3]103 scores = {}104 log = []105 terminated = False106 while not terminated:107 idx = info["task_index"]108 action = dispatch[idx](obs)109 obs, reward, terminated, info = env.step(action)110 scores[info["task_completed"]] = round(reward, 3)111 log.append(f" {info['task_completed']}: {reward:.3f}")112 113 avg = sum(scores.values()) / len(scores)114 log.append(f"\n Overall Average: {avg:.3f}")115 return "\n".join(log), json.dumps(scores, indent=2)116 117# ─── UI ───────────────────────────────────────────────────────────────────────118 119with gr.Blocks() as demo:120 121 gr.HTML("""122 <div class="header">123 <h1>🏥 HealthDataOps-Env</h1>124 <p>An OpenEnv AI agent training environment for Health Informatics · 125 <a href="https://huggingface.co" target="_blank">🤗 Hugging Face</a></p>126 </div>127 """)128 129 with gr.Tabs():130 131 # ── Tab 0: Quick Demo ──────────────────────────────────────────────────132 with gr.Tab("⚡ Quick Demo (Heuristic Agent)"):133 gr.Markdown("""134Run the built-in heuristic baseline agent across all 3 tasks instantly.135No API key needed.136 """)137 run_btn = gr.Button("▶ Run Full Heuristic Baseline", variant="primary")138 with gr.Row():139 log_out = gr.Textbox(label="Task Scores", lines=8)140 json_out = gr.JSON(label="Score JSON")141 run_btn.click(fn=run_full_heuristic, outputs=[log_out, json_out])142 143 # ── Tab 1: Diet Validator ──────────────────────────────────────────────144 with gr.Tab("🥗 Task 1 — Diet Validator"):145 gr.Markdown("""146**Difficulty:** Easy 147Submit a validation action for a newly generated patient diet plan.148 """)149 is_valid = gr.Checkbox(label="Mark plan as valid?", value=True)150 issue_type = gr.Dropdown(151 choices=["none","allergen_conflict","imbalanced_macros","wrong_meal_frequency","other"],152 value="none", label="Issue Type (if any)"153 )154 issue_desc = gr.Textbox(label="Issue Description", placeholder="e.g. Peanuts found in plan despite allergy")155 t1_btn = gr.Button("Submit Action", variant="primary")156 with gr.Row():157 t1_obs = gr.Textbox(label="Observation", lines=12)158 t1_result = gr.JSON(label="Result")159 t1_btn.click(fn=run_task1, inputs=[is_valid, issue_type, issue_desc], outputs=[t1_obs, t1_result])160 161 # ── Tab 2: EHR Triage ─────────────────────────────────────────────────162 with gr.Tab("🏥 Task 2 — EHR Triage"):163 gr.Markdown("""164**Difficulty:** Medium 165Enter one anomaly type per line (10 lines for 10 records). 166Options: `none` · `missing_field` · `outlier_vital` · `privacy_risk_pii` · `duplicate`167 """)168 anomaly_input = gr.Textbox(169 label="Anomaly Types (one per line, 10 lines)",170 lines=10,171 value="\n".join(["none"] * 10),172 placeholder="none\nmissing_field\noutlier_vital\n..."173 )174 t2_btn = gr.Button("Submit Action", variant="primary")175 with gr.Row():176 t2_obs = gr.Textbox(label="Observation (batch_records)", lines=20)177 t2_result = gr.JSON(label="Result")178 t2_btn.click(fn=run_task2, inputs=[anomaly_input], outputs=[t2_obs, t2_result])179 180 # ── Tab 3: Weather Health ─────────────────────────────────────────────181 with gr.Tab("🌤 Task 3 — Weather Health"):182 gr.Markdown("""183**Difficulty:** Hard 184Craft a weather-aware health recommendation for the generated patient + weather profile.185 """)186 risk = gr.Textbox(label="Risk Assessment", lines=2,187 placeholder="Describe the patient's health risks today…")188 diet = gr.Textbox(label="Dietary Adjustments", lines=2,189 placeholder="Specific food/recipe recommendations…")190 activity = gr.Textbox(label="Safe Activity Recommendation", lines=2,191 placeholder="Exercise or activity guidance…")192 med_timing = gr.Textbox(label="Medication Timing Adjustments (optional)", lines=1,193 placeholder="Leave blank if N/A")194 t3_btn = gr.Button("Submit Action", variant="primary")195 with gr.Row():196 t3_obs = gr.Textbox(label="Observation", lines=12)197 t3_result = gr.JSON(label="Result")198 t3_btn.click(fn=run_task3, inputs=[risk, diet, activity, med_timing],199 outputs=[t3_obs, t3_result])200 201 # ── Tab 4: About ──────────────────────────────────────────────────────202 with gr.Tab("📋 About"):203 gr.Markdown("""204## HealthDataOps-Env205An OpenEnv AI agent training environment for Health Informatics professionals.206 207### Tasks208| Task | Difficulty | Domain |209|------|-----------|--------|210| Patient Diet Plan Validator | Easy | Clinical Nutrition |211| EHR Anomaly Detection & Triage | Medium | Data Quality / HIPAA |212| Weather-Aware Health Recommendations | Hard | Personalized Medicine |213 214### Reward Function215| Signal | Reward |216|--------|--------|217| Correct issue identification | +0.20 |218| Correct severity classification | +0.15 |219| Medically safe recommendation | +0.25 |220| Contradicted medical guidelines | −0.30 |221| Repeated / loop action | −0.10 |222| Full task completion bonus | +0.10 |223 224### Links225- [GitHub Repository](https://github.com) 226- Built with Python · Pydantic · Faker · Gradio227 """)228 229if __name__ == "__main__":230 demo.launch()231 