mahigodike commited on
Commit
caa2c8b
·
verified ·
1 Parent(s): 70e3fbc

initial comit of latest files

Browse files
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .venv
2
+ __pycache__
README.md CHANGED
@@ -1,11 +1,207 @@
1
  ---
2
- title: Medcodel
3
- emoji: 📚
4
- colorFrom: indigo
5
- colorTo: yellow
6
  sdk: docker
7
  pinned: false
8
- license: mit
 
 
 
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: MedCodeRL - Medical Coding & Billing Compliance Environment
3
+ emoji: 🏥
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: docker
7
  pinned: false
8
+ app_port: 7680
9
+ base_path: /web
10
+ tags:
11
+ - openenv
12
  ---
13
 
14
+ # MedCodeRL 🏥
15
+
16
+ **Medical Coding & Billing Compliance OpenEnv Environment**
17
+
18
+ A realistic RL environment where AI agents must navigate the complex world of medical coding (ICD-10/CPT), billing compliance, and fraud detection. Built to the [OpenEnv specification](https://github.com/meta-pytorch/OpenEnv).
19
+
20
+ ## 🎯 Why This Matters
21
+
22
+ - The US healthcare system loses **$125B+ annually** to incorrect medical coding
23
+ - Hospitals spend **$80K+ per coder** annually with 12–18 month training cycles
24
+ - Current LLMs fail at ICD-10/CPT coding because they lack **hierarchical constraint understanding**
25
+ - No existing OpenEnv environment covers this critical domain
26
+
27
+ ## Quick Start
28
+
29
+ ```python
30
+ from my_env import MedAction, MedCodeEnv
31
+
32
+ try:
33
+ env = MedCodeEnv.from_docker_image("my_env-env:latest")
34
+
35
+ result = env.reset()
36
+ print(f"Case: {result.observation.case_id}")
37
+ print(f"Note: {result.observation.clinical_note}")
38
+
39
+ action = MedAction(
40
+ diagnosis_codes=["J02.9"],
41
+ procedure_codes=["99213"],
42
+ decision="approve",
43
+ confidence=0.9,
44
+ reasoning="Acute pharyngitis with appropriate E&M coding for straightforward visit.",
45
+ risk_flags=[]
46
+ )
47
+ result = env.step(action)
48
+ print(f"Score: {result.reward}")
49
+
50
+ finally:
51
+ env.close()
52
+ ```
53
+
54
+ ## Building the Docker Image
55
+
56
+ ```bash
57
+ docker build -t my_env-env:latest -f server/Dockerfile .
58
+ ```
59
+
60
+ ## Deploying to Hugging Face Spaces
61
+
62
+ ```bash
63
+ openenv push
64
+ ```
65
+
66
+ ## 🔬 Environment Details
67
+
68
+ ### Action (MedAction)
69
+
70
+ | Field | Type | Description |
71
+ |---|---|---|
72
+ | `diagnosis_codes` | list[str] (1–5) | ICD-10-CM codes |
73
+ | `procedure_codes` | list[str] (0–5) | CPT/HCPCS codes |
74
+ | `decision` | approve/reject/review | Billing compliance decision |
75
+ | `confidence` | float (0.0–1.0) | Agent confidence |
76
+ | `reasoning` | str (15–500 chars) | Clinical justification |
77
+ | `modifier_codes` | list[str] (0–3) | Optional CPT modifiers |
78
+ | `risk_flags` | list[str] (0–5) | Compliance risk flags |
79
+
80
+ ### Observation (MedObservation)
81
+
82
+ | Field | Type | Description |
83
+ |---|---|---|
84
+ | `case_id` | str | Unique case identifier |
85
+ | `difficulty` | str | easy / medium / hard |
86
+ | `clinical_note` | str | Full clinical documentation |
87
+ | `symptoms` | list[str] | Reported symptoms |
88
+ | `treatments` | list[str] | Treatments administered |
89
+ | `insurance_type` | str | Medicare / Medicaid / Private / Uninsured |
90
+ | `prior_auth_required` | bool | Prior authorization needed |
91
+ | `treatment_cost` | str | low / medium / high |
92
+ | `patient_age` | int | Patient age |
93
+ | `patient_sex` | str | M / F |
94
+ | `provider_specialty` | str | Provider specialty |
95
+ | `visit_type` | str | inpatient / outpatient / emergency / telehealth |
96
+ | `comorbidities` | list[str] | Pre-existing conditions |
97
+ | `lab_results` | str/None | Lab findings |
98
+ | `medications` | list[str] | Current medications |
99
+
100
+ ### Reward System
101
+
102
+ **Grader Components (Deterministic, 0.0–1.0):**
103
+
104
+ | Component | Weight |
105
+ |---|---|
106
+ | Diagnosis accuracy (ICD-10) | 35% |
107
+ | Procedure accuracy (CPT) | 20% |
108
+ | Decision accuracy | 25% |
109
+ | Reasoning quality | 10% |
110
+ | Risk flag identification | 5% |
111
+ | Confidence calibration | 5% |
112
+
113
+ **Shaped Penalties** (scaled by difficulty):
114
+ - Wrong approval: -0.25 | Wrong denial: -0.20
115
+ - Upcoding: -0.15 | Missing primary code: -0.15
116
+ - Undercoding: -0.10 | Unnecessary procedure: -0.10
117
+
118
+ **Bonuses:** Perfect diagnosis +0.05, Good reasoning +0.03, All flags +0.05
119
+
120
+ ## 📋 Tasks (90 cases total)
121
+
122
+ ### 🟢 Easy (30 cases)
123
+ Straightforward clinical cases with single diagnoses and direct ICD-10/CPT mapping.
124
+ Examples: viral pharyngitis, UTI, ankle sprain, routine wellness exam.
125
+
126
+ ### 🟡 Medium (30 cases)
127
+ Multi-diagnosis cases with comorbidities, insurance considerations, and partial ambiguity.
128
+ Examples: COPD with pneumonia, diabetic neuropathy, cardiac workup.
129
+
130
+ ### 🔴 Hard (30 cases)
131
+ Complex compliance dilemmas: upcoding, unbundling, fraud detection, medically unnecessary treatments, dangerous polypharmacy, ethical edge cases.
132
+
133
+ ## 🚀 Running the Inference Script
134
+
135
+ ```bash
136
+ export HF_TOKEN="your-key"
137
+ export API_BASE_URL="https://api.openai.com/v1"
138
+ export MODEL_NAME="gpt-4o-mini"
139
+ python inference.py
140
+ ```
141
+
142
+ ### Expected Baseline Scores
143
+
144
+ | Difficulty | Score Range |
145
+ |---|---|
146
+ | Easy | 0.55 – 0.85 |
147
+ | Medium | 0.35 – 0.65 |
148
+ | Hard | 0.15 – 0.45 |
149
+
150
+ ## Development & Testing
151
+
152
+ ### Run server locally
153
+
154
+ ```bash
155
+ uvicorn server.app:app --reload --host 0.0.0.0 --port 7680
156
+ ```
157
+
158
+ ### Direct environment testing
159
+
160
+ ```python
161
+ from server.my_env_environment import MyEnvironment
162
+ from models import MedAction
163
+
164
+ env = MyEnvironment()
165
+ obs = env.reset(task_id="easy")
166
+ action = MedAction(
167
+ diagnosis_codes=["J02.9"],
168
+ procedure_codes=["99213"],
169
+ decision="approve",
170
+ confidence=0.9,
171
+ reasoning="Acute pharyngitis with appropriate coding.",
172
+ risk_flags=[]
173
+ )
174
+ result = env.step(action)
175
+ print(f"Score: {result.reward}, Done: {result.done}")
176
+ ```
177
+
178
+ ## Project Structure
179
+
180
+ ```
181
+ my_env/
182
+ ├── __init__.py # Module exports
183
+ ├── README.md # This file
184
+ ├── openenv.yaml # OpenEnv manifest
185
+ ├── pyproject.toml # Dependencies
186
+ ├── client.py # MedCodeEnv client
187
+ ├── models.py # MedAction & MedObservation models
188
+ ├── inference.py # Baseline inference script
189
+ ├── tasks/
190
+ │ ├── easy.json # 30 easy clinical cases
191
+ │ ├── medium.json # 30 medium clinical cases
192
+ │ └── hard.json # 30 hard clinical cases
193
+ └── server/
194
+ ├── __init__.py # Server exports
195
+ ├── my_env_environment.py # Core env logic + grader + rewards
196
+ ├── app.py # FastAPI application
197
+ ├── Dockerfile # Container image
198
+ └── requirements.txt # Server dependencies
199
+ ```
200
+
201
+ ## ⚠️ Disclaimer
202
+
203
+ This environment is a **simulation for AI training and evaluation only**. It does not use real patient data and should not be used for actual medical coding or billing. All clinical cases are synthetic.
204
+
205
+ ## License
206
+
207
+ MIT License
__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """MedCodeRL - Medical Coding & Billing Compliance Environment."""
8
+
9
+ from .client import MedCodeEnv
10
+ from .models import MedAction, MedObservation
11
+
12
+ __all__ = [
13
+ "MedAction",
14
+ "MedObservation",
15
+ "MedCodeEnv",
16
+ ]
client.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """MedCodeRL Environment Client."""
8
+
9
+ from typing import Dict
10
+
11
+ from openenv.core import EnvClient
12
+ from openenv.core.client_types import StepResult
13
+ from openenv.core.env_server.types import State
14
+
15
+ from .models import MedAction, MedObservation
16
+
17
+
18
+ class MedCodeEnv(
19
+ EnvClient[MedAction, MedObservation, State]
20
+ ):
21
+ """
22
+ Client for the MedCodeRL Environment.
23
+
24
+ This client maintains a persistent WebSocket connection to the environment server,
25
+ enabling efficient multi-step interactions with lower latency.
26
+
27
+ Example:
28
+ >>> with MedCodeEnv(base_url="http://localhost:7680") as client:
29
+ ... result = client.reset()
30
+ ... print(result.observation.clinical_note)
31
+ ...
32
+ ... action = MedAction(
33
+ ... diagnosis_codes=["J02.9"],
34
+ ... procedure_codes=["99213"],
35
+ ... decision="approve",
36
+ ... confidence=0.9,
37
+ ... reasoning="Acute pharyngitis with appropriate E&M coding.",
38
+ ... risk_flags=[]
39
+ ... )
40
+ ... result = client.step(action)
41
+ ... print(f"Score: {result.reward}")
42
+ """
43
+
44
+ def _step_payload(self, action: MedAction) -> Dict:
45
+ """
46
+ Convert MedAction to JSON payload for step message.
47
+
48
+ Args:
49
+ action: MedAction instance
50
+
51
+ Returns:
52
+ Dictionary representation suitable for JSON encoding
53
+ """
54
+ return {
55
+ "diagnosis_codes": action.diagnosis_codes,
56
+ "procedure_codes": action.procedure_codes,
57
+ "decision": action.decision,
58
+ "confidence": action.confidence,
59
+ "reasoning": action.reasoning,
60
+ "modifier_codes": action.modifier_codes,
61
+ "risk_flags": action.risk_flags,
62
+ }
63
+
64
+ def _parse_result(self, payload: Dict) -> StepResult[MedObservation]:
65
+ """
66
+ Parse server response into StepResult[MedObservation].
67
+
68
+ Args:
69
+ payload: JSON response data from server
70
+
71
+ Returns:
72
+ StepResult with MedObservation
73
+ """
74
+ obs_data = payload.get("observation", {})
75
+ observation = MedObservation(
76
+ case_id=obs_data.get("case_id", ""),
77
+ difficulty=obs_data.get("difficulty", "easy"),
78
+ clinical_note=obs_data.get("clinical_note", ""),
79
+ symptoms=obs_data.get("symptoms", []),
80
+ treatments=obs_data.get("treatments", []),
81
+ insurance_type=obs_data.get("insurance_type", "Private"),
82
+ prior_auth_required=obs_data.get("prior_auth_required", False),
83
+ treatment_cost=obs_data.get("treatment_cost", "low"),
84
+ patient_age=obs_data.get("patient_age", 0),
85
+ patient_sex=obs_data.get("patient_sex", "M"),
86
+ provider_specialty=obs_data.get("provider_specialty", ""),
87
+ visit_type=obs_data.get("visit_type", "outpatient"),
88
+ comorbidities=obs_data.get("comorbidities", []),
89
+ lab_results=obs_data.get("lab_results"),
90
+ medications=obs_data.get("medications", []),
91
+ reward_breakdown=obs_data.get("reward_breakdown"),
92
+ feedback=obs_data.get("feedback", ""),
93
+ done=payload.get("done", False),
94
+ reward=payload.get("reward"),
95
+ metadata=obs_data.get("metadata", {}),
96
+ )
97
+
98
+ return StepResult(
99
+ observation=observation,
100
+ reward=payload.get("reward"),
101
+ done=payload.get("done", False),
102
+ )
103
+
104
+ def _parse_state(self, payload: Dict) -> State:
105
+ """
106
+ Parse server response into State object.
107
+
108
+ Args:
109
+ payload: JSON response from state request
110
+
111
+ Returns:
112
+ State object with episode_id and step_count
113
+ """
114
+ return State(
115
+ episode_id=payload.get("episode_id"),
116
+ step_count=payload.get("step_count", 0),
117
+ )
inference.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MedCodeRL - Baseline Inference Script
3
+
4
+ Uses the OpenAI API client to run a model against the MedCodeRL environment.
5
+ Reads API credentials from environment variables.
6
+
7
+ Usage:
8
+ export HF_TOKEN="your-key"
9
+ export API_BASE_URL="https://api.openai.com/v1"
10
+ export MODEL_NAME="gpt-4o-mini"
11
+ python inference.py
12
+ """
13
+
14
+ import json
15
+ import os
16
+ import re
17
+ import sys
18
+ import time
19
+ from typing import Optional
20
+
21
+ from openai import OpenAI
22
+
23
+ # Add project root to path so we can import the environment directly
24
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
25
+
26
+ from server.my_env_environment import MyEnvironment, _load_task_cases
27
+ from models import MedAction
28
+
29
+
30
+ # ----- Configuration -----
31
+
32
+ API_BASE_URL = os.environ.get("API_BASE_URL", "https://api.openai.com/v1")
33
+ MODEL_NAME = os.environ.get("MODEL_NAME", "gpt-4o-mini")
34
+ HF_TOKEN = os.environ.get("HF_TOKEN")
35
+
36
+ if not HF_TOKEN:
37
+ print("ERROR: Set HF_TOKEN environment variable (Your Hugging Face / API key).")
38
+ sys.exit(1)
39
+
40
+ # Number of cases to evaluate per difficulty level
41
+ CASES_PER_DIFFICULTY = int(os.environ.get("CASES_PER_DIFFICULTY", "5"))
42
+ MAX_RETRIES = 2
43
+
44
+
45
+ def create_client() -> OpenAI:
46
+ """Create an OpenAI-compatible client."""
47
+ return OpenAI(api_key=HF_TOKEN, base_url=API_BASE_URL)
48
+
49
+
50
+ def extract_json_from_response(text: str) -> Optional[dict]:
51
+ """Extract JSON from an LLM response, handling markdown code blocks."""
52
+ text = text.strip()
53
+ if text.startswith("{"):
54
+ try:
55
+ return json.loads(text)
56
+ except json.JSONDecodeError:
57
+ pass
58
+
59
+ patterns = [
60
+ r"```json\s*\n?(.*?)\n?\s*```",
61
+ r"```\s*\n?(.*?)\n?\s*```",
62
+ r"\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}",
63
+ ]
64
+ for pattern in patterns:
65
+ matches = re.findall(pattern, text, re.DOTALL)
66
+ for match in matches:
67
+ try:
68
+ return json.loads(match)
69
+ except json.JSONDecodeError:
70
+ continue
71
+ return None
72
+
73
+
74
+ SYSTEM_PROMPT = """You are an expert medical coding and billing compliance specialist.
75
+ Your role is to:
76
+ 1. Analyze clinical documentation
77
+ 2. Assign appropriate ICD-10-CM diagnosis codes
78
+ 3. Assign appropriate CPT procedure codes
79
+ 4. Make billing compliance decisions (approve, reject, or flag for review)
80
+ 5. Identify compliance risk flags
81
+ 6. Provide clinical reasoning for your decisions
82
+
83
+ You have deep knowledge of:
84
+ - ICD-10-CM coding guidelines and conventions
85
+ - CPT coding and modifier usage
86
+ - Medicare/Medicaid billing rules
87
+ - Medical necessity requirements
88
+ - Common compliance violations (upcoding, unbundling, fraudulent billing)
89
+ - Clinical documentation integrity
90
+ - Prior authorization requirements
91
+
92
+ Always respond with ONLY a valid JSON object in the exact format requested.
93
+ Be precise with your ICD-10 and CPT codes.
94
+ Consider the clinical documentation, symptoms, treatments, and insurance type when making decisions.
95
+ Flag any compliance concerns in risk_flags."""
96
+
97
+
98
+ def format_observation(obs) -> str:
99
+ """Format an observation into a readable prompt for the LLM."""
100
+ parts = [
101
+ f"## Medical Coding Case: {obs.case_id}",
102
+ f"**Difficulty:** {obs.difficulty}",
103
+ f"**Visit Type:** {obs.visit_type}",
104
+ f"**Provider Specialty:** {obs.provider_specialty}",
105
+ "",
106
+ "### Patient Information",
107
+ f"- **Age:** {obs.patient_age} | **Sex:** {obs.patient_sex}",
108
+ f"- **Insurance:** {obs.insurance_type}",
109
+ f"- **Prior Authorization Required:** {'Yes' if obs.prior_auth_required else 'No'}",
110
+ f"- **Treatment Cost Tier:** {obs.treatment_cost}",
111
+ "",
112
+ "### Clinical Note",
113
+ obs.clinical_note,
114
+ "",
115
+ "### Symptoms",
116
+ ", ".join(obs.symptoms) if obs.symptoms else "None reported",
117
+ "",
118
+ "### Treatments",
119
+ ", ".join(obs.treatments) if obs.treatments else "None",
120
+ ]
121
+
122
+ if obs.comorbidities:
123
+ parts += ["", "### Comorbidities", ", ".join(obs.comorbidities)]
124
+ if obs.lab_results:
125
+ parts += ["", "### Lab Results", obs.lab_results]
126
+ if obs.medications:
127
+ parts += ["", "### Current Medications", ", ".join(obs.medications)]
128
+
129
+ return "\n".join(parts)
130
+
131
+
132
+ ACTION_PROMPT = """
133
+ Based on the clinical case above, provide your medical coding and billing compliance assessment.
134
+
135
+ You MUST respond with a valid JSON object containing exactly these fields:
136
+
137
+ {
138
+ "diagnosis_codes": ["<ICD-10 code(s)>"],
139
+ "procedure_codes": ["<CPT code(s) if applicable, or empty list>"],
140
+ "decision": "<approve|reject|review>",
141
+ "confidence": <0.0 to 1.0>,
142
+ "reasoning": "<15-500 character clinical justification>",
143
+ "modifier_codes": ["<optional CPT modifiers, or empty list>"],
144
+ "risk_flags": ["<compliance risk flags identified, or empty list>"]
145
+ }
146
+
147
+ Guidelines:
148
+ - Use standard ICD-10-CM codes (e.g., J06.9 for upper respiratory infection)
149
+ - Use standard CPT codes (5 digits, e.g., 99213 for office visit)
150
+ - decision: "approve" if coding is appropriate, "reject" if non-compliant, "review" if ambiguous
151
+ - confidence: your certainty (0.0 = unsure, 1.0 = certain)
152
+ - reasoning: explain WHY you chose these codes and this decision
153
+ - risk_flags: compliance risks (e.g., "upcoding_risk", "missing_documentation", "bundling_violation")
154
+
155
+ IMPORTANT: Respond ONLY with the JSON object, no additional text.
156
+ """
157
+
158
+
159
+ def call_llm(client: OpenAI, obs) -> Optional[dict]:
160
+ """Call the LLM to get a coding decision for a clinical case."""
161
+ formatted = format_observation(obs)
162
+
163
+ for attempt in range(MAX_RETRIES + 1):
164
+ try:
165
+ response = client.chat.completions.create(
166
+ model=MODEL_NAME,
167
+ messages=[
168
+ {"role": "system", "content": SYSTEM_PROMPT},
169
+ {"role": "user", "content": formatted + "\n\n" + ACTION_PROMPT},
170
+ ],
171
+ temperature=0.1,
172
+ max_tokens=800,
173
+ )
174
+
175
+ content = response.choices[0].message.content
176
+ if not content:
177
+ print(f" [Attempt {attempt+1}] Empty response from LLM")
178
+ continue
179
+
180
+ action = extract_json_from_response(content)
181
+ if action is None:
182
+ print(f" [Attempt {attempt+1}] Failed to parse JSON from response")
183
+ if attempt < MAX_RETRIES:
184
+ time.sleep(1)
185
+ continue
186
+
187
+ # Sanitize fields
188
+ if "diagnosis_codes" not in action or not isinstance(action["diagnosis_codes"], list):
189
+ action["diagnosis_codes"] = [action["diagnosis_codes"]] if isinstance(action.get("diagnosis_codes"), str) else ["R69"]
190
+ if "procedure_codes" not in action:
191
+ action["procedure_codes"] = []
192
+ if isinstance(action.get("procedure_codes"), str):
193
+ action["procedure_codes"] = [action["procedure_codes"]]
194
+ if "decision" not in action:
195
+ action["decision"] = "review"
196
+ if "confidence" not in action:
197
+ action["confidence"] = 0.5
198
+ action["confidence"] = max(0.0, min(1.0, float(action["confidence"])))
199
+ if "reasoning" not in action or len(str(action.get("reasoning", ""))) < 15:
200
+ action["reasoning"] = "Medical coding assessment based on clinical documentation review and compliance guidelines."
201
+ if "modifier_codes" not in action:
202
+ action["modifier_codes"] = []
203
+ if "risk_flags" not in action:
204
+ action["risk_flags"] = []
205
+
206
+ return action
207
+
208
+ except Exception as e:
209
+ print(f" [Attempt {attempt+1}] API error: {e}")
210
+ if attempt < MAX_RETRIES:
211
+ time.sleep(2 ** attempt)
212
+
213
+ return None
214
+
215
+
216
+ def get_fallback_action() -> dict:
217
+ """Return a safe fallback action if LLM fails."""
218
+ return {
219
+ "diagnosis_codes": ["R69"],
220
+ "procedure_codes": ["99213"],
221
+ "decision": "review",
222
+ "confidence": 0.1,
223
+ "reasoning": "Unable to obtain LLM response. Flagging for manual review as a safety measure.",
224
+ "modifier_codes": [],
225
+ "risk_flags": ["llm_failure"],
226
+ }
227
+
228
+
229
+ def run_evaluation():
230
+ """Run the baseline evaluation across all difficulty levels."""
231
+ print("=" * 70)
232
+ print("MedCodeRL - Baseline Inference Script")
233
+ print("=" * 70)
234
+ print(f"API Base URL: {API_BASE_URL}")
235
+ print(f"Model: {MODEL_NAME}")
236
+ print(f"Cases per difficulty: {CASES_PER_DIFFICULTY}")
237
+ print("=" * 70)
238
+
239
+ client = create_client()
240
+ env = MyEnvironment()
241
+
242
+ all_scores = []
243
+ results_by_difficulty = {}
244
+
245
+ for difficulty in ["easy", "medium", "hard"]:
246
+ print(f"\n{'─' * 50}")
247
+ print(f" Running {difficulty.upper()} tasks")
248
+ print(f"{'─' * 50}")
249
+
250
+ difficulty_scores = []
251
+ available = len(env._task_cases.get(difficulty, []))
252
+ num_cases = min(CASES_PER_DIFFICULTY, available)
253
+
254
+ if num_cases == 0:
255
+ print(f" No cases available for {difficulty}")
256
+ continue
257
+
258
+ for i in range(num_cases):
259
+ # Reset environment for this difficulty
260
+ obs = env.reset(task_id=difficulty)
261
+ print(f"\n Case {i+1}/{num_cases}: {obs.case_id}")
262
+
263
+ # Get LLM action
264
+ action_dict = call_llm(client, obs)
265
+ if action_dict is None:
266
+ print(" ⚠ LLM failed, using fallback action")
267
+ action_dict = get_fallback_action()
268
+
269
+ # Build MedAction
270
+ med_action = MedAction(
271
+ diagnosis_codes=action_dict["diagnosis_codes"],
272
+ procedure_codes=action_dict.get("procedure_codes", []),
273
+ decision=action_dict["decision"],
274
+ confidence=action_dict["confidence"],
275
+ reasoning=action_dict["reasoning"],
276
+ modifier_codes=action_dict.get("modifier_codes", []),
277
+ risk_flags=action_dict.get("risk_flags", []),
278
+ )
279
+
280
+ # Step the environment
281
+ try:
282
+ result_obs = env.step(med_action)
283
+ score = result_obs.reward if result_obs.reward is not None else 0.0
284
+ difficulty_scores.append(score)
285
+ all_scores.append(score)
286
+
287
+ print(f" Score: {score:.4f}")
288
+ print(f" Decision: {action_dict.get('decision', 'N/A')}")
289
+ print(f" Diagnosis: {action_dict.get('diagnosis_codes', [])}")
290
+ print(f" Procedure: {action_dict.get('procedure_codes', [])}")
291
+
292
+ if result_obs.reward_breakdown:
293
+ gc = result_obs.reward_breakdown.get("grade_components", {})
294
+ if gc:
295
+ print(f" Components: diag={gc.get('diagnosis_accuracy', 0):.2f} "
296
+ f"proc={gc.get('procedure_accuracy', 0):.2f} "
297
+ f"dec={gc.get('decision_accuracy', 0):.2f}")
298
+ pens = result_obs.reward_breakdown.get("penalties", {})
299
+ if pens:
300
+ print(f" Penalties: {list(pens.keys())}")
301
+
302
+ if result_obs.feedback:
303
+ print(f" Feedback: {result_obs.feedback}")
304
+
305
+ except Exception as e:
306
+ print(f" ✗ Step failed: {e}")
307
+ difficulty_scores.append(0.0)
308
+ all_scores.append(0.0)
309
+
310
+ # Rate limiting
311
+ time.sleep(0.5)
312
+
313
+ if difficulty_scores:
314
+ avg = sum(difficulty_scores) / len(difficulty_scores)
315
+ results_by_difficulty[difficulty] = {
316
+ "scores": difficulty_scores,
317
+ "average": round(avg, 4),
318
+ "count": len(difficulty_scores),
319
+ }
320
+ print(f"\n {difficulty.upper()} Average: {avg:.4f} ({len(difficulty_scores)} cases)")
321
+
322
+ # Final summary
323
+ print(f"\n{'=' * 70}")
324
+ print(" FINAL RESULTS")
325
+ print(f"{'=' * 70}")
326
+
327
+ for diff, result in results_by_difficulty.items():
328
+ print(f" {diff.upper():>8}: {result['average']:.4f} ({result['count']} cases)")
329
+
330
+ if all_scores:
331
+ overall = sum(all_scores) / len(all_scores)
332
+ print(f"\n {'OVERALL':>8}: {overall:.4f} ({len(all_scores)} total cases)")
333
+ else:
334
+ overall = 0.0
335
+ print("\n No scores recorded.")
336
+
337
+ print(f"{'=' * 70}")
338
+
339
+ # Write results to file
340
+ results_output = {
341
+ "model": MODEL_NAME,
342
+ "api_base_url": API_BASE_URL,
343
+ "cases_per_difficulty": CASES_PER_DIFFICULTY,
344
+ "results_by_difficulty": results_by_difficulty,
345
+ "overall_score": round(overall, 4),
346
+ "total_cases": len(all_scores),
347
+ }
348
+
349
+ with open("baseline_results.json", "w") as f:
350
+ json.dump(results_output, f, indent=2)
351
+ print(f"\nResults saved to baseline_results.json")
352
+
353
+ return overall
354
+
355
+
356
+ if __name__ == "__main__":
357
+ score = run_evaluation()
358
+ sys.exit(0 if score > 0 else 1)
models.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ Data models for the MedCodeRL Environment.
9
+
10
+ Medical Coding & Billing Compliance environment where agents must assign
11
+ ICD-10/CPT codes, make billing compliance decisions, and identify fraud patterns.
12
+ """
13
+
14
+ from typing import Dict, List, Literal, Optional
15
+
16
+ from openenv.core.env_server.types import Action, Observation
17
+ from pydantic import Field
18
+
19
+
20
+ class MedAction(Action):
21
+ """Action for the MedCodeRL environment — a complete medical coding assessment."""
22
+
23
+ diagnosis_codes: List[str] = Field(
24
+ ..., min_length=1, max_length=5,
25
+ description="ICD-10-CM diagnosis codes (primary + secondary)"
26
+ )
27
+ procedure_codes: List[str] = Field(
28
+ default_factory=list, max_length=5,
29
+ description="CPT procedure codes"
30
+ )
31
+ decision: Literal["approve", "reject", "review"] = Field(
32
+ ..., description="Billing compliance decision"
33
+ )
34
+ confidence: float = Field(
35
+ ..., ge=0.0, le=1.0,
36
+ description="Agent confidence in its coding decision"
37
+ )
38
+ reasoning: str = Field(
39
+ ..., min_length=15, max_length=500,
40
+ description="Clinical justification for the coding decision"
41
+ )
42
+ modifier_codes: List[str] = Field(
43
+ default_factory=list, max_length=3,
44
+ description="Optional CPT modifier codes"
45
+ )
46
+ risk_flags: List[str] = Field(
47
+ default_factory=list, max_length=5,
48
+ description="Compliance risk flags identified"
49
+ )
50
+
51
+
52
+ class MedObservation(Observation):
53
+ """Observation from the MedCodeRL environment — a clinical case to code."""
54
+
55
+ case_id: str = Field(default="", description="Unique case identifier")
56
+ difficulty: str = Field(default="easy", description="easy | medium | hard")
57
+ clinical_note: str = Field(default="", description="Clinical documentation")
58
+ symptoms: List[str] = Field(default_factory=list, description="Reported symptoms")
59
+ treatments: List[str] = Field(default_factory=list, description="Treatments administered or planned")
60
+ insurance_type: str = Field(default="Private", description="Medicare | Medicaid | Private | Uninsured")
61
+ prior_auth_required: bool = Field(default=False, description="Prior authorization needed")
62
+ treatment_cost: str = Field(default="low", description="low | medium | high")
63
+ patient_age: int = Field(default=0, description="Patient age in years")
64
+ patient_sex: str = Field(default="M", description="M | F")
65
+ provider_specialty: str = Field(default="", description="Treating provider specialty")
66
+ visit_type: str = Field(default="outpatient", description="inpatient | outpatient | emergency | telehealth")
67
+ comorbidities: List[str] = Field(default_factory=list, description="Pre-existing conditions")
68
+ lab_results: Optional[str] = Field(default=None, description="Relevant lab results")
69
+ medications: List[str] = Field(default_factory=list, description="Current medications")
70
+
71
+ # Reward breakdown returned after step
72
+ reward_breakdown: Optional[Dict] = Field(default=None, description="Detailed reward breakdown after grading")
73
+ feedback: str = Field(default="", description="Grader feedback text")
openenv.yaml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ spec_version: 1
2
+ name: my_env
3
+ type: space
4
+ runtime: fastapi
5
+ app: server.app:app
6
+ port: 7680
openenv_my_env.egg-info/PKG-INFO ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: openenv-my_env
3
+ Version: 1.0.0
4
+ Summary: MedCodeRL - Medical Coding & Billing Compliance environment for OpenEnv
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: openenv-core[core]>=0.2.2
7
+ Requires-Dist: openai>=1.50.0
8
+ Provides-Extra: dev
9
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
10
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
openenv_my_env.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ README.md
2
+ __init__.py
3
+ client.py
4
+ inference.py
5
+ models.py
6
+ pyproject.toml
7
+ test_env.py
8
+ ./__init__.py
9
+ ./client.py
10
+ ./inference.py
11
+ ./models.py
12
+ ./test_env.py
13
+ ./tasks/easy.json
14
+ ./tasks/hard.json
15
+ ./tasks/medium.json
16
+ openenv_my_env.egg-info/PKG-INFO
17
+ openenv_my_env.egg-info/SOURCES.txt
18
+ openenv_my_env.egg-info/dependency_links.txt
19
+ openenv_my_env.egg-info/entry_points.txt
20
+ openenv_my_env.egg-info/requires.txt
21
+ openenv_my_env.egg-info/top_level.txt
22
+ server/__init__.py
23
+ server/app.py
24
+ server/my_env_environment.py
25
+ tasks/easy.json
26
+ tasks/hard.json
27
+ tasks/medium.json
openenv_my_env.egg-info/dependency_links.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
openenv_my_env.egg-info/entry_points.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ [console_scripts]
2
+ server = my_env.server.app:main
openenv_my_env.egg-info/requires.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ openenv-core[core]>=0.2.2
2
+ openai>=1.50.0
3
+
4
+ [dev]
5
+ pytest>=8.0.0
6
+ pytest-cov>=4.0.0
openenv_my_env.egg-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ my_env
pyproject.toml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ [build-system]
8
+ requires = ["setuptools>=45", "wheel"]
9
+ build-backend = "setuptools.build_meta"
10
+
11
+ [project]
12
+ name = "openenv-my_env"
13
+ version = "1.0.0"
14
+ description = "MedCodeRL - Medical Coding & Billing Compliance environment for OpenEnv"
15
+ requires-python = ">=3.10"
16
+ dependencies = [
17
+ # Core OpenEnv runtime (provides FastAPI server + HTTP client types)
18
+ "openenv-core[core]>=0.2.2",
19
+ # Environment-specific dependencies
20
+ "openai>=1.50.0",
21
+ ]
22
+
23
+ [project.optional-dependencies]
24
+ dev = [
25
+ "pytest>=8.0.0",
26
+ "pytest-cov>=4.0.0",
27
+ ]
28
+
29
+ [project.scripts]
30
+ # Server entry point - enables running via: uv run --project . server
31
+ server = "my_env.server.app:main"
32
+
33
+ [tool.setuptools]
34
+ include-package-data = true
35
+ packages = ["my_env", "my_env.server"]
36
+ package-dir = { "my_env" = ".", "my_env.server" = "server" }
37
+
38
+ [tool.setuptools.package-data]
39
+ "my_env" = ["tasks/*.json"]
requirements.txt ADDED
Binary file (4.37 kB). View file
 
server/Dockerfile ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ # Multi-stage build using openenv-base
8
+ # This Dockerfile is flexible and works for both:
9
+ # - In-repo environments (with local OpenEnv sources)
10
+ # - Standalone environments (with openenv from PyPI/Git)
11
+ # The build script (openenv build) handles context detection and sets appropriate build args.
12
+
13
+ ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
14
+ FROM ${BASE_IMAGE} AS builder
15
+
16
+ WORKDIR /app
17
+
18
+ # Ensure git is available (required for installing dependencies from VCS)
19
+ RUN apt-get update && \
20
+ apt-get install -y --no-install-recommends git && \
21
+ rm -rf /var/lib/apt/lists/*
22
+
23
+ # Build argument to control whether we're building standalone or in-repo
24
+ ARG BUILD_MODE=in-repo
25
+ ARG ENV_NAME=my_env
26
+
27
+ # Copy environment code (always at root of build context)
28
+ COPY . /app/env
29
+
30
+ # For in-repo builds, openenv is already vendored in the build context
31
+ # For standalone builds, openenv will be installed via pyproject.toml
32
+ WORKDIR /app/env
33
+
34
+ # Ensure uv is available (for local builds where base image lacks it)
35
+ RUN if ! command -v uv >/dev/null 2>&1; then \
36
+ curl -LsSf https://astral.sh/uv/install.sh | sh && \
37
+ mv /root/.local/bin/uv /usr/local/bin/uv && \
38
+ mv /root/.local/bin/uvx /usr/local/bin/uvx; \
39
+ fi
40
+
41
+ # Install dependencies using uv sync
42
+ # If uv.lock exists, use it; otherwise resolve on the fly
43
+ RUN --mount=type=cache,target=/root/.cache/uv \
44
+ if [ -f uv.lock ]; then \
45
+ uv sync --frozen --no-install-project --no-editable; \
46
+ else \
47
+ uv sync --no-install-project --no-editable; \
48
+ fi
49
+
50
+ RUN --mount=type=cache,target=/root/.cache/uv \
51
+ if [ -f uv.lock ]; then \
52
+ uv sync --frozen --no-editable; \
53
+ else \
54
+ uv sync --no-editable; \
55
+ fi
56
+
57
+ # Final runtime stage
58
+ FROM ${BASE_IMAGE}
59
+
60
+ WORKDIR /app
61
+
62
+ # Copy the virtual environment from builder
63
+ COPY --from=builder /app/env/.venv /app/.venv
64
+
65
+ # Copy the environment code
66
+ COPY --from=builder /app/env /app/env
67
+
68
+ # Set PATH to use the virtual environment
69
+ ENV PATH="/app/.venv/bin:$PATH"
70
+
71
+ # Set PYTHONPATH so imports work correctly
72
+ ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
+
74
+ # Health check
75
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
76
+ CMD curl -f http://localhost:7680/health || exit 1
77
+
78
+ # Run the FastAPI server
79
+ # The module path is constructed to work with the /app/env structure
80
+ CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 7680"]
server/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """MedCodeRL environment server components."""
8
+
9
+ from .my_env_environment import MyEnvironment
10
+
11
+ __all__ = ["MyEnvironment"]
server/app.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ """
4
+ FastAPI application for the MedCodeRL Environment.
5
+
6
+ Endpoints:
7
+ - POST /reset: Reset the environment (new clinical case)
8
+ - POST /step: Submit medical coding action
9
+ - GET /state: Get current environment state
10
+ - GET /schema: Get action/observation schemas
11
+ - WS /ws: WebSocket endpoint for persistent sessions
12
+ - GET /tasks: Hackathon list tasks requirement
13
+ - GET /cases/{difficulty}: Hackathon list cases requirement
14
+ - GET /reset: Functional alias
15
+ """
16
+
17
+ import traceback
18
+ from typing import Optional
19
+ from fastapi import HTTPException
20
+ from pydantic import BaseModel
21
+
22
+ try:
23
+ from openenv.core.env_server.http_server import create_app
24
+ except Exception as e:
25
+ raise ImportError("openenv is required for the web interface.") from e
26
+
27
+ try:
28
+ from ..models import MedAction, MedObservation
29
+ from .my_env_environment import MyEnvironment
30
+ except (ImportError, SystemError):
31
+ from models import MedAction, MedObservation
32
+ from server.my_env_environment import MyEnvironment
33
+
34
+
35
+ # Create the app with web interface and README integration
36
+ app = create_app(
37
+ MyEnvironment,
38
+ MedAction,
39
+ MedObservation,
40
+ env_name="my_env",
41
+ max_concurrent_envs=1,
42
+ )
43
+
44
+ # Reference environment for functional GET endpoints
45
+ _ref_env = MyEnvironment()
46
+
47
+
48
+ # ----- Request / Response Models -----
49
+
50
+ class ResetResponse(BaseModel):
51
+ observation: dict
52
+
53
+ class TasksResponse(BaseModel):
54
+ tasks: list
55
+ task_counts: dict
56
+
57
+ class HealthResponse(BaseModel):
58
+ status: str
59
+ environment: str
60
+ version: str
61
+ tasks: list
62
+
63
+
64
+ # ----- Endpoints -----
65
+
66
+ @app.get("/", response_model=HealthResponse)
67
+ async def health_check():
68
+ """Health check endpoint — required for HF Space validation."""
69
+ tasks = list(_ref_env._task_cases.keys())
70
+ return HealthResponse(
71
+ status="ok",
72
+ environment="MedCodeRL",
73
+ version="1.0.0",
74
+ tasks=tasks,
75
+ )
76
+
77
+
78
+ @app.get("/tasks", response_model=TasksResponse)
79
+ async def get_tasks():
80
+ """List available tasks and case counts."""
81
+ task_keys = list(_ref_env._task_cases.keys())
82
+ counts = {t: len(_ref_env._task_cases[t]) for t in task_keys}
83
+ return TasksResponse(tasks=task_keys, task_counts=counts)
84
+
85
+
86
+ @app.get("/cases/{difficulty}")
87
+ async def get_cases(difficulty: str):
88
+ """List all case IDs for a difficulty level."""
89
+ if difficulty not in _ref_env._task_cases:
90
+ raise HTTPException(status_code=400, detail="Difficulty must be easy, medium, or hard")
91
+ case_ids = [c.get("id", f"{difficulty}_unk") for c in _ref_env._task_cases[difficulty]]
92
+ return {"difficulty": difficulty, "case_ids": case_ids, "count": len(case_ids)}
93
+
94
+
95
+ @app.get("/reset", response_model=ResetResponse)
96
+ async def reset_get(task_id: Optional[str] = None):
97
+ """Functional GET /reset route which actually executes a reset."""
98
+ try:
99
+ obs = _ref_env.reset(task_id=task_id)
100
+ # Use model_dump() for Pydantic V2, fallback to dict() for V1
101
+ obs_dict = obs.model_dump() if hasattr(obs, "model_dump") else obs.dict()
102
+ return ResetResponse(observation=obs_dict)
103
+ except Exception as e:
104
+ traceback.print_exc()
105
+ raise HTTPException(status_code=500, detail=f"Reset failed: {str(e)}")
106
+
107
+
108
+ def main(host: str = "0.0.0.0", port: int = 7680):
109
+ import uvicorn
110
+ uvicorn.run(app, host=host, port=port)
111
+
112
+
113
+ if __name__ == "__main__":
114
+ import argparse
115
+ import os
116
+
117
+ parser = argparse.ArgumentParser()
118
+ parser.add_argument("--port", type=int, default=int(os.environ.get("PORT", 7680)))
119
+ args = parser.parse_args()
120
+ main(port=args.port)
server/my_env_environment.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ MedCodeRL Environment Implementation.
9
+
10
+ Medical Coding & Billing Compliance environment where agents must:
11
+ 1. Assign correct ICD-10 diagnosis codes
12
+ 2. Assign correct CPT procedure codes
13
+ 3. Make billing compliance decisions (approve/reject/review)
14
+ 4. Provide clinical reasoning
15
+ 5. Identify compliance risks
16
+
17
+ Contains: environment logic, deterministic grader, shaped rewards, action validation.
18
+ """
19
+
20
+ import json
21
+ import os
22
+ import re
23
+ from typing import Any, Dict, List, Optional, Set, Tuple
24
+ from uuid import uuid4
25
+
26
+ from openenv.core.env_server.interfaces import Environment
27
+ from openenv.core.env_server.types import State
28
+
29
+ try:
30
+ from ..models import MedAction, MedObservation
31
+ except ImportError:
32
+ from models import MedAction, MedObservation
33
+
34
+
35
+ # ──────────────────────────────────────────────
36
+ # Task loader
37
+ # ──────────────────────────────────────────────
38
+
39
+ TASKS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "tasks")
40
+
41
+
42
+ def _load_task_cases(difficulty: str) -> List[Dict[str, Any]]:
43
+ """Load clinical cases for a given difficulty level."""
44
+ filepath = os.path.join(TASKS_DIR, f"{difficulty}.json")
45
+ if not os.path.exists(filepath):
46
+ return []
47
+ with open(filepath, "r", encoding="utf-8") as f:
48
+ data = json.load(f)
49
+ return data.get("cases", [])
50
+
51
+
52
+ # ──────────────────────────────────────────────
53
+ # Action validation
54
+ # ──────────────────────────────────────────────
55
+
56
+ ICD10_PATTERN = re.compile(r"^[A-Z]\d{2}(\.\d{1,4})?$", re.IGNORECASE)
57
+ CPT_PATTERN = re.compile(r"^\d{5}$")
58
+ HCPCS_PATTERN = re.compile(r"^[A-Z]\d{4}$", re.IGNORECASE)
59
+
60
+
61
+ def _validate_action(action_dict: dict) -> Tuple[bool, List[str]]:
62
+ """Validate an action dict. Returns (is_valid, error_list)."""
63
+ errors: List[str] = []
64
+
65
+ diag = action_dict.get("diagnosis_codes", [])
66
+ if not isinstance(diag, list) or len(diag) == 0:
67
+ errors.append("At least one diagnosis code is required")
68
+ elif len(diag) > 5:
69
+ errors.append("Maximum 5 diagnosis codes allowed")
70
+ else:
71
+ for code in diag:
72
+ if not ICD10_PATTERN.match(str(code).strip()):
73
+ errors.append(f"Invalid ICD-10 format: {code}")
74
+
75
+ proc = action_dict.get("procedure_codes", [])
76
+ if isinstance(proc, list):
77
+ for code in proc:
78
+ c = str(code).strip()
79
+ if not CPT_PATTERN.match(c) and not HCPCS_PATTERN.match(c):
80
+ errors.append(f"Invalid CPT/HCPCS format: {code}")
81
+
82
+ decision = action_dict.get("decision", "")
83
+ if str(decision).lower() not in ("approve", "reject", "review"):
84
+ errors.append(f"Invalid decision: {decision}")
85
+
86
+ confidence = action_dict.get("confidence", -1)
87
+ try:
88
+ conf_val = float(confidence)
89
+ if conf_val < 0.0 or conf_val > 1.0:
90
+ errors.append("confidence must be 0.0-1.0")
91
+ except (TypeError, ValueError):
92
+ errors.append("confidence must be a number")
93
+
94
+ reasoning = action_dict.get("reasoning", "")
95
+ if not isinstance(reasoning, str) or len(reasoning) < 15:
96
+ errors.append("reasoning must be at least 15 characters")
97
+
98
+ return len(errors) == 0, errors
99
+
100
+
101
+ # ──────────────────────────────────────────────
102
+ # Deterministic grader
103
+ # ──────────────────────────────────────────────
104
+
105
+ def _set_similarity(predicted: List[str], ground_truth: List[str]) -> float:
106
+ """Jaccard similarity between two code sets."""
107
+ if not ground_truth and not predicted:
108
+ return 1.0
109
+ pred_set: Set[str] = set(c.strip().upper() for c in predicted if c)
110
+ gt_set: Set[str] = set(c.strip().upper() for c in ground_truth if c)
111
+ if not gt_set:
112
+ return 1.0 if not pred_set else 0.0
113
+ if not pred_set:
114
+ return 0.0
115
+ intersection = pred_set & gt_set
116
+ union = pred_set | gt_set
117
+ return len(intersection) / len(union) if union else 1.0
118
+
119
+
120
+ def _partial_code_match(predicted: List[str], ground_truth: List[str]) -> float:
121
+ """Partial-credit matching for medical codes (prefix similarity)."""
122
+ if not ground_truth:
123
+ return 1.0 if not predicted else 0.0
124
+ if not predicted:
125
+ return 0.0
126
+ pred_list = [c.strip().upper() for c in predicted if c]
127
+ gt_list = [c.strip().upper() for c in ground_truth if c]
128
+ total = 0.0
129
+ for gt_code in gt_list:
130
+ best = 0.0
131
+ for pred_code in pred_list:
132
+ if pred_code == gt_code:
133
+ best = 1.0
134
+ break
135
+ gt_base = gt_code.split(".")[0]
136
+ pred_base = pred_code.split(".")[0]
137
+ if gt_base == pred_base:
138
+ best = max(best, 0.5)
139
+ elif len(gt_base) >= 3 and gt_base[:3] == pred_base[:3]:
140
+ best = max(best, 0.25)
141
+ total += best
142
+ return total / len(gt_list)
143
+
144
+
145
+ def _grade(action_dict: dict, ground_truth: dict) -> Dict[str, float]:
146
+ """
147
+ Deterministic grading — 6 weighted components → score in [0.0, 1.0].
148
+
149
+ Weights: diagnosis 35%, procedure 20%, decision 25%, reasoning 10%,
150
+ risk flags 5%, confidence calibration 5%.
151
+ """
152
+ pred_diag = action_dict.get("diagnosis_codes", [])
153
+ gt_diag = ground_truth.get("diagnosis_codes", [])
154
+ pred_proc = action_dict.get("procedure_codes", [])
155
+ gt_proc = ground_truth.get("procedure_codes", [])
156
+ pred_dec = str(action_dict.get("decision", "")).lower()
157
+ gt_dec = str(ground_truth.get("decision", "")).lower()
158
+ pred_reasoning = str(action_dict.get("reasoning", ""))
159
+ pred_risk = action_dict.get("risk_flags", [])
160
+ gt_risk = ground_truth.get("risk_flags", [])
161
+ pred_conf = float(action_dict.get("confidence", 0.5))
162
+
163
+ # 1. Diagnosis codes (35%)
164
+ diag_exact = _set_similarity(pred_diag, gt_diag)
165
+ diag_partial = _partial_code_match(pred_diag, gt_diag)
166
+ diag_score = 0.6 * diag_exact + 0.4 * diag_partial
167
+
168
+ # 2. Procedure codes (20%)
169
+ proc_exact = _set_similarity(pred_proc, gt_proc)
170
+ proc_partial = _partial_code_match(pred_proc, gt_proc)
171
+ proc_score = 0.6 * proc_exact + 0.4 * proc_partial
172
+
173
+ # 3. Decision (25%)
174
+ if pred_dec == gt_dec:
175
+ dec_score = 1.0
176
+ elif pred_dec == "review" and gt_dec in ("approve", "reject"):
177
+ dec_score = 0.3
178
+ elif pred_dec in ("approve", "reject") and gt_dec == "review":
179
+ dec_score = 0.2
180
+ else:
181
+ dec_score = 0.0
182
+
183
+ # 4. Reasoning quality (10%)
184
+ reasoning_lower = pred_reasoning.lower()
185
+ r_score = 0.0
186
+ if len(pred_reasoning) >= 20:
187
+ r_score += 0.3
188
+ if len(pred_reasoning) >= 50:
189
+ r_score += 0.2
190
+ med_terms = [
191
+ "icd", "cpt", "diagnosis", "procedure", "coding", "compliance",
192
+ "medical", "clinical", "treatment", "patient", "billing",
193
+ "authorization", "insurance", "modifier", "documentation",
194
+ "justified", "appropriate", "medically necessary", "guideline",
195
+ ]
196
+ r_score += min(0.5, sum(1 for t in med_terms if t in reasoning_lower) * 0.1)
197
+ r_score = min(1.0, r_score)
198
+
199
+ # 5. Risk flags (5%)
200
+ risk_score = _set_similarity(pred_risk, gt_risk)
201
+
202
+ # 6. Confidence calibration (5%)
203
+ correctness = diag_score * 0.5 + proc_score * 0.3 + dec_score * 0.2
204
+ conf_score = max(0.0, 1.0 - abs(pred_conf - correctness) * 2.0)
205
+
206
+ total = (
207
+ diag_score * 0.35
208
+ + proc_score * 0.20
209
+ + dec_score * 0.25
210
+ + r_score * 0.10
211
+ + risk_score * 0.05
212
+ + conf_score * 0.05
213
+ )
214
+
215
+ return {
216
+ "score": round(min(1.0, max(0.0, total)), 4),
217
+ "diagnosis_accuracy": round(diag_score, 4),
218
+ "procedure_accuracy": round(proc_score, 4),
219
+ "decision_accuracy": round(dec_score, 4),
220
+ "reasoning_quality": round(r_score, 4),
221
+ "risk_identification": round(risk_score, 4),
222
+ "confidence_calibration": round(conf_score, 4),
223
+ }
224
+
225
+
226
+ # ──────────────────────────────────────────────
227
+ # Shaped reward engine
228
+ # ──────────────────────────────────────────────
229
+
230
+ def _compute_reward(action_dict: dict, ground_truth: dict, difficulty: str = "easy") -> Dict:
231
+ """
232
+ Shaped reward = base_grade + bonuses − penalties.
233
+
234
+ Penalties: upcoding, undercoding, wrong denial/approval, unnecessary procedure,
235
+ missing primary code, low confidence.
236
+ Bonuses: perfect diagnosis, good reasoning, all risk flags.
237
+ """
238
+ grade_result = _grade(action_dict, ground_truth)
239
+ base = grade_result["score"]
240
+
241
+ pred_diag = set(c.strip().upper() for c in action_dict.get("diagnosis_codes", []) if c)
242
+ gt_diag = set(c.strip().upper() for c in ground_truth.get("diagnosis_codes", []) if c)
243
+ gt_diag_list = [c.strip().upper() for c in ground_truth.get("diagnosis_codes", []) if c]
244
+ pred_proc = set(c.strip().upper() for c in action_dict.get("procedure_codes", []) if c)
245
+ gt_proc = set(c.strip().upper() for c in ground_truth.get("procedure_codes", []) if c)
246
+ pred_dec = str(action_dict.get("decision", "")).lower()
247
+ gt_dec = str(ground_truth.get("decision", "")).lower()
248
+ pred_conf = float(action_dict.get("confidence", 0.5))
249
+
250
+ penalties: Dict[str, float] = {}
251
+ bonuses: Dict[str, float] = {}
252
+
253
+ # Penalties
254
+ if len(pred_proc) > len(gt_proc) + 1:
255
+ penalties["upcoding"] = -0.15
256
+ if gt_diag and len(pred_diag & gt_diag) < len(gt_diag) * 0.5:
257
+ penalties["undercoding"] = -0.10
258
+ if pred_dec == "reject" and gt_dec == "approve":
259
+ penalties["wrong_denial"] = -0.20
260
+ if pred_dec == "approve" and gt_dec == "reject":
261
+ penalties["wrong_approval"] = -0.25
262
+ if pred_proc - gt_proc:
263
+ penalties["unnecessary_procedure"] = -0.10
264
+ if gt_diag_list and gt_diag_list[0] not in pred_diag:
265
+ penalties["missing_primary_code"] = -0.15
266
+ if pred_conf < 0.2:
267
+ penalties["low_confidence"] = -0.05
268
+
269
+ # Bonuses
270
+ if grade_result["diagnosis_accuracy"] >= 0.99:
271
+ bonuses["perfect_diagnosis"] = 0.05
272
+ if grade_result["reasoning_quality"] >= 0.8:
273
+ bonuses["good_reasoning"] = 0.03
274
+ if grade_result["risk_identification"] >= 0.99:
275
+ bonuses["all_risk_flags"] = 0.05
276
+
277
+ diff_mult = {"easy": 0.8, "medium": 1.0, "hard": 1.2}.get(difficulty, 1.0)
278
+ total_penalty = sum(penalties.values()) * diff_mult
279
+ total_bonus = sum(bonuses.values())
280
+ final = max(0.0, min(1.0, base + total_penalty + total_bonus))
281
+
282
+ feedback_parts = []
283
+ if penalties:
284
+ feedback_parts.append(f"Penalties: {', '.join(penalties.keys())}")
285
+ if bonuses:
286
+ feedback_parts.append(f"Bonuses: {', '.join(bonuses.keys())}")
287
+ if not penalties and not bonuses:
288
+ feedback_parts.append("Clean submission.")
289
+
290
+ return {
291
+ "score": round(final, 4),
292
+ "breakdown": {
293
+ "base_grade": round(base, 4),
294
+ "total_penalty": round(total_penalty, 4),
295
+ "total_bonus": round(total_bonus, 4),
296
+ "penalties": {k: round(v, 4) for k, v in penalties.items()},
297
+ "bonuses": {k: round(v, 4) for k, v in bonuses.items()},
298
+ "grade_components": grade_result,
299
+ },
300
+ "feedback": " | ".join(feedback_parts),
301
+ }
302
+
303
+
304
+ # ──────────────────────────────────────────────
305
+ # Core Environment
306
+ # ──────────────────────────────────────────────
307
+
308
+ class MyEnvironment(Environment):
309
+ """
310
+ MedCodeRL — Medical Coding & Billing Compliance Environment.
311
+
312
+ 90 realistic clinical cases (30 easy, 30 medium, 30 hard) covering:
313
+ - Straightforward coding (easy)
314
+ - Multi-diagnosis with comorbidities (medium)
315
+ - Compliance dilemmas: upcoding, unbundling, fraud, ethical edge cases (hard)
316
+
317
+ OpenEnv-compliant: reset() / step() / state property.
318
+ """
319
+
320
+ SUPPORTS_CONCURRENT_SESSIONS: bool = True
321
+
322
+ def __init__(self):
323
+ """Initialize the MedCodeRL environment."""
324
+ self._state = State(episode_id=str(uuid4()), step_count=0)
325
+ self._reset_count = 0
326
+
327
+ # Load all task cases
328
+ self._task_cases: Dict[str, List[Dict]] = {}
329
+ self._case_index: Dict[str, int] = {"easy": 0, "medium": 0, "hard": 0}
330
+ for diff in ("easy", "medium", "hard"):
331
+ self._task_cases[diff] = _load_task_cases(diff)
332
+
333
+ self._current_case: Optional[Dict] = None
334
+ self._current_difficulty: str = "easy"
335
+ self._done: bool = True
336
+ self._action_history: List[dict] = []
337
+
338
+ def _pick_case(self, task_id: Optional[str] = None) -> Dict:
339
+ """Select a case by difficulty or specific case_id."""
340
+ if task_id in ("easy", "medium", "hard"):
341
+ difficulty = task_id
342
+ elif task_id:
343
+ # Search for specific case_id
344
+ for diff in ("easy", "medium", "hard"):
345
+ for case in self._task_cases.get(diff, []):
346
+ if case["id"] == task_id:
347
+ self._current_difficulty = diff
348
+ return case
349
+ raise ValueError(f"Case not found: {task_id}")
350
+ else:
351
+ # Cycle through difficulties
352
+ total = sum(self._case_index.values())
353
+ difficulty = ["easy", "medium", "hard"][total % 3]
354
+
355
+ cases = self._task_cases.get(difficulty, [])
356
+ if not cases:
357
+ raise ValueError(f"No cases for difficulty: {difficulty}")
358
+ idx = self._case_index[difficulty] % len(cases)
359
+ self._case_index[difficulty] = idx + 1
360
+ self._current_difficulty = difficulty
361
+ return cases[idx]
362
+
363
+ def _build_observation(self, case: Dict, done: bool = False,
364
+ reward: Optional[float] = None,
365
+ reward_breakdown: Optional[Dict] = None,
366
+ feedback: str = "") -> MedObservation:
367
+ """Build a MedObservation from a case dict."""
368
+ inp = case.get("input", case)
369
+ return MedObservation(
370
+ case_id=case.get("id", ""),
371
+ difficulty=case.get("difficulty", self._current_difficulty),
372
+ clinical_note=inp.get("clinical_note", ""),
373
+ symptoms=inp.get("symptoms", []),
374
+ treatments=inp.get("treatments", []),
375
+ insurance_type=inp.get("insurance_type", "Private"),
376
+ prior_auth_required=inp.get("prior_auth_required", False),
377
+ treatment_cost=inp.get("treatment_cost", "low"),
378
+ patient_age=inp.get("patient_age", 0),
379
+ patient_sex=inp.get("patient_sex", "M"),
380
+ provider_specialty=inp.get("provider_specialty", ""),
381
+ visit_type=inp.get("visit_type", "outpatient"),
382
+ comorbidities=inp.get("comorbidities", []),
383
+ lab_results=inp.get("lab_results"),
384
+ medications=inp.get("medications", []),
385
+ reward_breakdown=reward_breakdown,
386
+ feedback=feedback,
387
+ done=done,
388
+ reward=reward,
389
+ metadata={
390
+ "step_count": self._state.step_count,
391
+ "difficulty": self._current_difficulty,
392
+ },
393
+ )
394
+
395
+ def reset(self, task_id: Optional[str] = None, **kwargs) -> MedObservation:
396
+ """
397
+ Reset the environment to a new episode.
398
+
399
+ Args:
400
+ task_id: 'easy', 'medium', 'hard', or a specific case_id.
401
+
402
+ Returns:
403
+ MedObservation with the clinical case to code.
404
+ """
405
+ # Accept task_id from kwargs if not provided directly
406
+ if task_id is None:
407
+ task_id = kwargs.get("task_id")
408
+
409
+ self._state = State(episode_id=str(uuid4()), step_count=0)
410
+ self._reset_count += 1
411
+ self._done = False
412
+ self._action_history = []
413
+
414
+ self._current_case = self._pick_case(task_id)
415
+
416
+ return self._build_observation(self._current_case, done=False, reward=0.0)
417
+
418
+ def step(self, action: MedAction) -> MedObservation: # type: ignore[override]
419
+ """
420
+ Execute a step: grade the agent's medical coding action.
421
+
422
+ Args:
423
+ action: MedAction with diagnosis codes, procedure codes, decision, etc.
424
+
425
+ Returns:
426
+ MedObservation with reward and grading breakdown.
427
+ """
428
+ if self._done:
429
+ return self._build_observation(
430
+ self._current_case or {},
431
+ done=True,
432
+ reward=0.0,
433
+ feedback="Episode already done. Call reset().",
434
+ )
435
+
436
+ self._state.step_count += 1
437
+
438
+ # Convert action to dict
439
+ action_dict = {
440
+ "diagnosis_codes": action.diagnosis_codes,
441
+ "procedure_codes": action.procedure_codes,
442
+ "decision": action.decision,
443
+ "confidence": action.confidence,
444
+ "reasoning": action.reasoning,
445
+ "modifier_codes": action.modifier_codes,
446
+ "risk_flags": action.risk_flags,
447
+ }
448
+
449
+ # Validate
450
+ is_valid, errors = _validate_action(action_dict)
451
+
452
+ if not is_valid:
453
+ self._action_history.append({"action": action_dict, "valid": False})
454
+ if self._state.step_count >= 3:
455
+ self._done = True
456
+ return self._build_observation(
457
+ self._current_case or {},
458
+ done=self._done,
459
+ reward=0.0,
460
+ feedback=f"Invalid action: {'; '.join(errors)}",
461
+ )
462
+
463
+ # Grade against ground truth
464
+ ground_truth = self._current_case.get("ground_truth", {})
465
+ reward_result = _compute_reward(action_dict, ground_truth, self._current_difficulty)
466
+
467
+ self._action_history.append({"action": action_dict, "valid": True})
468
+ self._done = True # single-step episode for valid actions
469
+
470
+ score = reward_result["score"]
471
+
472
+ return self._build_observation(
473
+ self._current_case or {},
474
+ done=True,
475
+ reward=score,
476
+ reward_breakdown=reward_result.get("breakdown"),
477
+ feedback=reward_result.get("feedback", ""),
478
+ )
479
+
480
+ @property
481
+ def state(self) -> State:
482
+ """
483
+ Get the current environment state.
484
+
485
+ Returns:
486
+ State with episode_id and step_count
487
+ """
488
+ return self._state
server/requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ openenv[core]>=0.2.0
2
+ fastapi>=0.115.0
3
+ uvicorn>=0.24.0
4
+ openai>=1.50.0
tasks/easy.json ADDED
@@ -0,0 +1,756 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "difficulty": "easy",
3
+ "description": "Straightforward clinical cases with direct ICD-10/CPT mapping, single diagnoses, and clear compliance decisions.",
4
+ "cases": [
5
+ {
6
+ "id": "easy_001",
7
+ "difficulty": "easy",
8
+ "input": {
9
+ "clinical_note": "Patient presents with acute pharyngitis. Throat is erythematous with no exudate. Rapid strep test negative. Diagnosed with viral pharyngitis. Advised rest, fluids, and OTC analgesics.",
10
+ "symptoms": ["sore throat", "mild fever", "difficulty swallowing"],
11
+ "treatments": ["rest", "fluids", "acetaminophen"],
12
+ "insurance_type": "Private",
13
+ "prior_auth_required": false,
14
+ "treatment_cost": "low",
15
+ "patient_age": 28,
16
+ "patient_sex": "F",
17
+ "provider_specialty": "Family Medicine",
18
+ "visit_type": "outpatient",
19
+ "comorbidities": [],
20
+ "lab_results": "Rapid strep test: Negative",
21
+ "medications": ["acetaminophen 500mg PRN"]
22
+ },
23
+ "ground_truth": {
24
+ "diagnosis_codes": ["J02.9"],
25
+ "procedure_codes": ["99213"],
26
+ "decision": "approve",
27
+ "risk_flags": []
28
+ }
29
+ },
30
+ {
31
+ "id": "easy_002",
32
+ "difficulty": "easy",
33
+ "input": {
34
+ "clinical_note": "42-year-old male presents for annual wellness exam. No complaints. Vitals normal. BMI 24.3. Routine labs ordered. Patient counseled on diet and exercise.",
35
+ "symptoms": [],
36
+ "treatments": ["routine labs", "health counseling"],
37
+ "insurance_type": "Private",
38
+ "prior_auth_required": false,
39
+ "treatment_cost": "low",
40
+ "patient_age": 42,
41
+ "patient_sex": "M",
42
+ "provider_specialty": "Internal Medicine",
43
+ "visit_type": "outpatient",
44
+ "comorbidities": [],
45
+ "lab_results": null,
46
+ "medications": []
47
+ },
48
+ "ground_truth": {
49
+ "diagnosis_codes": ["Z00.00"],
50
+ "procedure_codes": ["99395"],
51
+ "decision": "approve",
52
+ "risk_flags": []
53
+ }
54
+ },
55
+ {
56
+ "id": "easy_003",
57
+ "difficulty": "easy",
58
+ "input": {
59
+ "clinical_note": "Patient presents with uncomplicated urinary tract infection. Dysuria and frequency for 2 days. UA positive for nitrites and leukocyte esterase. Prescribed trimethoprim-sulfamethoxazole.",
60
+ "symptoms": ["dysuria", "urinary frequency", "suprapubic discomfort"],
61
+ "treatments": ["trimethoprim-sulfamethoxazole"],
62
+ "insurance_type": "Medicare",
63
+ "prior_auth_required": false,
64
+ "treatment_cost": "low",
65
+ "patient_age": 65,
66
+ "patient_sex": "F",
67
+ "provider_specialty": "Family Medicine",
68
+ "visit_type": "outpatient",
69
+ "comorbidities": [],
70
+ "lab_results": "UA: Nitrites positive, Leukocyte esterase positive, WBC >10/hpf",
71
+ "medications": ["trimethoprim-sulfamethoxazole 160/800mg BID"]
72
+ },
73
+ "ground_truth": {
74
+ "diagnosis_codes": ["N39.0"],
75
+ "procedure_codes": ["99213"],
76
+ "decision": "approve",
77
+ "risk_flags": []
78
+ }
79
+ },
80
+ {
81
+ "id": "easy_004",
82
+ "difficulty": "easy",
83
+ "input": {
84
+ "clinical_note": "Child brought in by mother for ear pain x2 days. Otoscopic exam reveals bulging, erythematous right tympanic membrane. Diagnosed with acute otitis media. Prescribed amoxicillin.",
85
+ "symptoms": ["right ear pain", "fussiness", "mild fever"],
86
+ "treatments": ["amoxicillin"],
87
+ "insurance_type": "Medicaid",
88
+ "prior_auth_required": false,
89
+ "treatment_cost": "low",
90
+ "patient_age": 4,
91
+ "patient_sex": "M",
92
+ "provider_specialty": "Pediatrics",
93
+ "visit_type": "outpatient",
94
+ "comorbidities": [],
95
+ "lab_results": null,
96
+ "medications": ["amoxicillin 250mg/5mL TID"]
97
+ },
98
+ "ground_truth": {
99
+ "diagnosis_codes": ["H66.91"],
100
+ "procedure_codes": ["99213"],
101
+ "decision": "approve",
102
+ "risk_flags": []
103
+ }
104
+ },
105
+ {
106
+ "id": "easy_005",
107
+ "difficulty": "easy",
108
+ "input": {
109
+ "clinical_note": "Patient with known type 2 diabetes presents for routine follow-up. A1C obtained is 7.1%. Current medications reviewed. No complications. Continue metformin. Follow up in 3 months.",
110
+ "symptoms": [],
111
+ "treatments": ["metformin continuation", "A1C monitoring"],
112
+ "insurance_type": "Medicare",
113
+ "prior_auth_required": false,
114
+ "treatment_cost": "low",
115
+ "patient_age": 58,
116
+ "patient_sex": "M",
117
+ "provider_specialty": "Internal Medicine",
118
+ "visit_type": "outpatient",
119
+ "comorbidities": ["type 2 diabetes"],
120
+ "lab_results": "HbA1c: 7.1%",
121
+ "medications": ["metformin 1000mg BID"]
122
+ },
123
+ "ground_truth": {
124
+ "diagnosis_codes": ["E11.65"],
125
+ "procedure_codes": ["99214"],
126
+ "decision": "approve",
127
+ "risk_flags": []
128
+ }
129
+ },
130
+ {
131
+ "id": "easy_006",
132
+ "difficulty": "easy",
133
+ "input": {
134
+ "clinical_note": "Patient presents with acute bronchitis. Cough productive of clear sputum for 5 days. Lungs clear to auscultation. No fever. Chest x-ray not indicated. Supportive care recommended.",
135
+ "symptoms": ["productive cough", "mild chest discomfort", "fatigue"],
136
+ "treatments": ["rest", "fluids", "cough suppressant"],
137
+ "insurance_type": "Private",
138
+ "prior_auth_required": false,
139
+ "treatment_cost": "low",
140
+ "patient_age": 35,
141
+ "patient_sex": "F",
142
+ "provider_specialty": "Family Medicine",
143
+ "visit_type": "outpatient",
144
+ "comorbidities": [],
145
+ "lab_results": null,
146
+ "medications": ["dextromethorphan PRN"]
147
+ },
148
+ "ground_truth": {
149
+ "diagnosis_codes": ["J20.9"],
150
+ "procedure_codes": ["99213"],
151
+ "decision": "approve",
152
+ "risk_flags": []
153
+ }
154
+ },
155
+ {
156
+ "id": "easy_007",
157
+ "difficulty": "easy",
158
+ "input": {
159
+ "clinical_note": "Patient presents for removal of a benign skin lesion on the back. Lesion is 0.8cm, non-suspicious. Shave removal performed without complications. Specimen sent to pathology.",
160
+ "symptoms": ["skin lesion on back"],
161
+ "treatments": ["shave removal of lesion"],
162
+ "insurance_type": "Private",
163
+ "prior_auth_required": false,
164
+ "treatment_cost": "low",
165
+ "patient_age": 45,
166
+ "patient_sex": "M",
167
+ "provider_specialty": "Dermatology",
168
+ "visit_type": "outpatient",
169
+ "comorbidities": [],
170
+ "lab_results": null,
171
+ "medications": []
172
+ },
173
+ "ground_truth": {
174
+ "diagnosis_codes": ["D23.5"],
175
+ "procedure_codes": ["11305"],
176
+ "decision": "approve",
177
+ "risk_flags": []
178
+ }
179
+ },
180
+ {
181
+ "id": "easy_008",
182
+ "difficulty": "easy",
183
+ "input": {
184
+ "clinical_note": "Patient presents with allergic rhinitis. Sneezing, nasal congestion, and watery eyes for 3 weeks. Symptoms seasonal. No fever. Started on cetirizine and fluticasone nasal spray.",
185
+ "symptoms": ["sneezing", "nasal congestion", "watery eyes", "itchy nose"],
186
+ "treatments": ["cetirizine", "fluticasone nasal spray"],
187
+ "insurance_type": "Private",
188
+ "prior_auth_required": false,
189
+ "treatment_cost": "low",
190
+ "patient_age": 32,
191
+ "patient_sex": "F",
192
+ "provider_specialty": "Family Medicine",
193
+ "visit_type": "outpatient",
194
+ "comorbidities": [],
195
+ "lab_results": null,
196
+ "medications": ["cetirizine 10mg daily", "fluticasone nasal spray"]
197
+ },
198
+ "ground_truth": {
199
+ "diagnosis_codes": ["J30.1"],
200
+ "procedure_codes": ["99213"],
201
+ "decision": "approve",
202
+ "risk_flags": []
203
+ }
204
+ },
205
+ {
206
+ "id": "easy_009",
207
+ "difficulty": "easy",
208
+ "input": {
209
+ "clinical_note": "Patient twisted ankle playing basketball. X-ray negative for fracture. Mild swelling and tenderness over lateral malleolus. Diagnosed with ankle sprain. RICE protocol and ACE wrap applied.",
210
+ "symptoms": ["ankle pain", "swelling", "difficulty bearing weight"],
211
+ "treatments": ["RICE protocol", "ACE wrap", "ibuprofen"],
212
+ "insurance_type": "Private",
213
+ "prior_auth_required": false,
214
+ "treatment_cost": "low",
215
+ "patient_age": 22,
216
+ "patient_sex": "M",
217
+ "provider_specialty": "Emergency Medicine",
218
+ "visit_type": "emergency",
219
+ "comorbidities": [],
220
+ "lab_results": "X-ray right ankle: No fracture identified",
221
+ "medications": ["ibuprofen 400mg TID PRN"]
222
+ },
223
+ "ground_truth": {
224
+ "diagnosis_codes": ["S93.401"],
225
+ "procedure_codes": ["99283"],
226
+ "decision": "approve",
227
+ "risk_flags": []
228
+ }
229
+ },
230
+ {
231
+ "id": "easy_010",
232
+ "difficulty": "easy",
233
+ "input": {
234
+ "clinical_note": "Patient presents with tension headache. Reports bilateral, non-pulsating headache for 2 days. No visual changes, no nausea or vomiting. Neurological exam normal. Prescribed ibuprofen.",
235
+ "symptoms": ["bilateral headache", "neck stiffness", "fatigue"],
236
+ "treatments": ["ibuprofen"],
237
+ "insurance_type": "Private",
238
+ "prior_auth_required": false,
239
+ "treatment_cost": "low",
240
+ "patient_age": 30,
241
+ "patient_sex": "F",
242
+ "provider_specialty": "Family Medicine",
243
+ "visit_type": "outpatient",
244
+ "comorbidities": [],
245
+ "lab_results": null,
246
+ "medications": ["ibuprofen 400mg PRN"]
247
+ },
248
+ "ground_truth": {
249
+ "diagnosis_codes": ["G44.209"],
250
+ "procedure_codes": ["99213"],
251
+ "decision": "approve",
252
+ "risk_flags": []
253
+ }
254
+ },
255
+ {
256
+ "id": "easy_011",
257
+ "difficulty": "easy",
258
+ "input": {
259
+ "clinical_note": "Infant presents for 6-month well-child visit. Growth and development on track. Immunizations administered per CDC schedule. Anticipatory guidance provided to parents.",
260
+ "symptoms": [],
261
+ "treatments": ["immunizations", "developmental screening"],
262
+ "insurance_type": "Medicaid",
263
+ "prior_auth_required": false,
264
+ "treatment_cost": "low",
265
+ "patient_age": 0,
266
+ "patient_sex": "F",
267
+ "provider_specialty": "Pediatrics",
268
+ "visit_type": "outpatient",
269
+ "comorbidities": [],
270
+ "lab_results": null,
271
+ "medications": []
272
+ },
273
+ "ground_truth": {
274
+ "diagnosis_codes": ["Z00.129"],
275
+ "procedure_codes": ["99391"],
276
+ "decision": "approve",
277
+ "risk_flags": []
278
+ }
279
+ },
280
+ {
281
+ "id": "easy_012",
282
+ "difficulty": "easy",
283
+ "input": {
284
+ "clinical_note": "Patient presents with localized contact dermatitis on both hands. Reports using new cleaning product. Erythematous, pruritic rash on dorsal hands bilaterally. Prescribed topical hydrocortisone.",
285
+ "symptoms": ["itchy rash on hands", "erythema", "mild swelling"],
286
+ "treatments": ["topical hydrocortisone", "avoidance of irritant"],
287
+ "insurance_type": "Private",
288
+ "prior_auth_required": false,
289
+ "treatment_cost": "low",
290
+ "patient_age": 38,
291
+ "patient_sex": "F",
292
+ "provider_specialty": "Dermatology",
293
+ "visit_type": "outpatient",
294
+ "comorbidities": [],
295
+ "lab_results": null,
296
+ "medications": ["hydrocortisone 1% cream BID"]
297
+ },
298
+ "ground_truth": {
299
+ "diagnosis_codes": ["L25.9"],
300
+ "procedure_codes": ["99213"],
301
+ "decision": "approve",
302
+ "risk_flags": []
303
+ }
304
+ },
305
+ {
306
+ "id": "easy_013",
307
+ "difficulty": "easy",
308
+ "input": {
309
+ "clinical_note": "Patient presents with conjunctivitis. Red, watery left eye for 3 days. No vision changes. No discharge. Likely viral etiology. Advised warm compresses and artificial tears.",
310
+ "symptoms": ["red eye", "watery discharge", "mild irritation"],
311
+ "treatments": ["warm compresses", "artificial tears"],
312
+ "insurance_type": "Private",
313
+ "prior_auth_required": false,
314
+ "treatment_cost": "low",
315
+ "patient_age": 25,
316
+ "patient_sex": "M",
317
+ "provider_specialty": "Family Medicine",
318
+ "visit_type": "outpatient",
319
+ "comorbidities": [],
320
+ "lab_results": null,
321
+ "medications": ["artificial tears PRN"]
322
+ },
323
+ "ground_truth": {
324
+ "diagnosis_codes": ["H10.9"],
325
+ "procedure_codes": ["99213"],
326
+ "decision": "approve",
327
+ "risk_flags": []
328
+ }
329
+ },
330
+ {
331
+ "id": "easy_014",
332
+ "difficulty": "easy",
333
+ "input": {
334
+ "clinical_note": "Patient presents with GERD symptoms. Heartburn and regurgitation for 4 weeks. No alarm symptoms. No dysphagia or weight loss. Started on omeprazole 20mg daily.",
335
+ "symptoms": ["heartburn", "acid regurgitation", "epigastric discomfort"],
336
+ "treatments": ["omeprazole"],
337
+ "insurance_type": "Medicare",
338
+ "prior_auth_required": false,
339
+ "treatment_cost": "low",
340
+ "patient_age": 55,
341
+ "patient_sex": "M",
342
+ "provider_specialty": "Internal Medicine",
343
+ "visit_type": "outpatient",
344
+ "comorbidities": [],
345
+ "lab_results": null,
346
+ "medications": ["omeprazole 20mg daily"]
347
+ },
348
+ "ground_truth": {
349
+ "diagnosis_codes": ["K21.0"],
350
+ "procedure_codes": ["99214"],
351
+ "decision": "approve",
352
+ "risk_flags": []
353
+ }
354
+ },
355
+ {
356
+ "id": "easy_015",
357
+ "difficulty": "easy",
358
+ "input": {
359
+ "clinical_note": "Patient presents with insomnia. Difficulty falling asleep for 6 weeks. No daytime sleepiness while driving. Good sleep hygiene discussed. No medications prescribed; CBT-I referral placed.",
360
+ "symptoms": ["difficulty falling asleep", "fatigue", "irritability"],
361
+ "treatments": ["sleep hygiene counseling", "CBT-I referral"],
362
+ "insurance_type": "Private",
363
+ "prior_auth_required": false,
364
+ "treatment_cost": "low",
365
+ "patient_age": 40,
366
+ "patient_sex": "F",
367
+ "provider_specialty": "Family Medicine",
368
+ "visit_type": "outpatient",
369
+ "comorbidities": [],
370
+ "lab_results": null,
371
+ "medications": []
372
+ },
373
+ "ground_truth": {
374
+ "diagnosis_codes": ["G47.00"],
375
+ "procedure_codes": ["99214"],
376
+ "decision": "approve",
377
+ "risk_flags": []
378
+ }
379
+ },
380
+ {
381
+ "id": "easy_016",
382
+ "difficulty": "easy",
383
+ "input": {
384
+ "clinical_note": "Patient with known hypertension presents for medication refill. Blood pressure well controlled at 128/78. No symptoms. Continue lisinopril 10mg daily. Follow up in 6 months.",
385
+ "symptoms": [],
386
+ "treatments": ["lisinopril continuation"],
387
+ "insurance_type": "Medicare",
388
+ "prior_auth_required": false,
389
+ "treatment_cost": "low",
390
+ "patient_age": 62,
391
+ "patient_sex": "M",
392
+ "provider_specialty": "Internal Medicine",
393
+ "visit_type": "outpatient",
394
+ "comorbidities": ["essential hypertension"],
395
+ "lab_results": "BP: 128/78 mmHg",
396
+ "medications": ["lisinopril 10mg daily"]
397
+ },
398
+ "ground_truth": {
399
+ "diagnosis_codes": ["I10"],
400
+ "procedure_codes": ["99213"],
401
+ "decision": "approve",
402
+ "risk_flags": []
403
+ }
404
+ },
405
+ {
406
+ "id": "easy_017",
407
+ "difficulty": "easy",
408
+ "input": {
409
+ "clinical_note": "Patient presents with acute sinusitis. Facial pain, nasal congestion, and purulent discharge for 10 days. No improvement with OTC decongestants. Started amoxicillin-clavulanate.",
410
+ "symptoms": ["facial pain", "nasal congestion", "purulent nasal discharge", "low-grade fever"],
411
+ "treatments": ["amoxicillin-clavulanate"],
412
+ "insurance_type": "Private",
413
+ "prior_auth_required": false,
414
+ "treatment_cost": "low",
415
+ "patient_age": 34,
416
+ "patient_sex": "M",
417
+ "provider_specialty": "Family Medicine",
418
+ "visit_type": "outpatient",
419
+ "comorbidities": [],
420
+ "lab_results": null,
421
+ "medications": ["amoxicillin-clavulanate 875/125mg BID"]
422
+ },
423
+ "ground_truth": {
424
+ "diagnosis_codes": ["J01.90"],
425
+ "procedure_codes": ["99213"],
426
+ "decision": "approve",
427
+ "risk_flags": []
428
+ }
429
+ },
430
+ {
431
+ "id": "easy_018",
432
+ "difficulty": "easy",
433
+ "input": {
434
+ "clinical_note": "Patient presents with impetigo on the face. Honey-colored crusted lesions around the nose and mouth. Diagnosed with non-bullous impetigo. Prescribed mupirocin ointment.",
435
+ "symptoms": ["crusted lesions around nose", "mild itching"],
436
+ "treatments": ["mupirocin ointment"],
437
+ "insurance_type": "Medicaid",
438
+ "prior_auth_required": false,
439
+ "treatment_cost": "low",
440
+ "patient_age": 6,
441
+ "patient_sex": "M",
442
+ "provider_specialty": "Pediatrics",
443
+ "visit_type": "outpatient",
444
+ "comorbidities": [],
445
+ "lab_results": null,
446
+ "medications": ["mupirocin 2% ointment TID"]
447
+ },
448
+ "ground_truth": {
449
+ "diagnosis_codes": ["L01.00"],
450
+ "procedure_codes": ["99213"],
451
+ "decision": "approve",
452
+ "risk_flags": []
453
+ }
454
+ },
455
+ {
456
+ "id": "easy_019",
457
+ "difficulty": "easy",
458
+ "input": {
459
+ "clinical_note": "Patient presents for flu vaccination. No acute complaints. Past medical history unremarkable. Influenza vaccine (IIV4) administered intramuscularly in left deltoid.",
460
+ "symptoms": [],
461
+ "treatments": ["influenza vaccination"],
462
+ "insurance_type": "Medicare",
463
+ "prior_auth_required": false,
464
+ "treatment_cost": "low",
465
+ "patient_age": 70,
466
+ "patient_sex": "F",
467
+ "provider_specialty": "Internal Medicine",
468
+ "visit_type": "outpatient",
469
+ "comorbidities": [],
470
+ "lab_results": null,
471
+ "medications": []
472
+ },
473
+ "ground_truth": {
474
+ "diagnosis_codes": ["Z23"],
475
+ "procedure_codes": ["90688"],
476
+ "decision": "approve",
477
+ "risk_flags": []
478
+ }
479
+ },
480
+ {
481
+ "id": "easy_020",
482
+ "difficulty": "easy",
483
+ "input": {
484
+ "clinical_note": "Patient presents with lower back pain after lifting heavy box at work. No radiation to legs. No weakness or numbness. Lumbar strain diagnosed. NSAIDs and physical therapy recommended.",
485
+ "symptoms": ["lower back pain", "stiffness", "limited range of motion"],
486
+ "treatments": ["ibuprofen", "physical therapy referral"],
487
+ "insurance_type": "Private",
488
+ "prior_auth_required": false,
489
+ "treatment_cost": "low",
490
+ "patient_age": 36,
491
+ "patient_sex": "M",
492
+ "provider_specialty": "Family Medicine",
493
+ "visit_type": "outpatient",
494
+ "comorbidities": [],
495
+ "lab_results": null,
496
+ "medications": ["ibuprofen 600mg TID"]
497
+ },
498
+ "ground_truth": {
499
+ "diagnosis_codes": ["M54.5"],
500
+ "procedure_codes": ["99213"],
501
+ "decision": "approve",
502
+ "risk_flags": []
503
+ }
504
+ },
505
+ {
506
+ "id": "easy_021",
507
+ "difficulty": "easy",
508
+ "input": {
509
+ "clinical_note": "Patient presents for iron deficiency anemia follow-up. Recent labs show hemoglobin 10.8 g/dL, ferritin 12 ng/mL. Iron supplementation continued. Repeat labs in 3 months.",
510
+ "symptoms": ["fatigue", "pallor"],
511
+ "treatments": ["iron supplementation"],
512
+ "insurance_type": "Private",
513
+ "prior_auth_required": false,
514
+ "treatment_cost": "low",
515
+ "patient_age": 29,
516
+ "patient_sex": "F",
517
+ "provider_specialty": "Internal Medicine",
518
+ "visit_type": "outpatient",
519
+ "comorbidities": [],
520
+ "lab_results": "Hgb: 10.8 g/dL, Ferritin: 12 ng/mL, MCV: 72 fL",
521
+ "medications": ["ferrous sulfate 325mg daily"]
522
+ },
523
+ "ground_truth": {
524
+ "diagnosis_codes": ["D50.9"],
525
+ "procedure_codes": ["99214"],
526
+ "decision": "approve",
527
+ "risk_flags": []
528
+ }
529
+ },
530
+ {
531
+ "id": "easy_022",
532
+ "difficulty": "easy",
533
+ "input": {
534
+ "clinical_note": "Patient presents with acne vulgaris. Moderate papulopustular acne on face. No scarring. Started on benzoyl peroxide and topical retinoid. Follow up in 8 weeks.",
535
+ "symptoms": ["facial acne", "papules", "pustules"],
536
+ "treatments": ["benzoyl peroxide", "topical tretinoin"],
537
+ "insurance_type": "Private",
538
+ "prior_auth_required": false,
539
+ "treatment_cost": "low",
540
+ "patient_age": 16,
541
+ "patient_sex": "F",
542
+ "provider_specialty": "Dermatology",
543
+ "visit_type": "outpatient",
544
+ "comorbidities": [],
545
+ "lab_results": null,
546
+ "medications": ["benzoyl peroxide 5% gel", "tretinoin 0.025% cream"]
547
+ },
548
+ "ground_truth": {
549
+ "diagnosis_codes": ["L70.0"],
550
+ "procedure_codes": ["99213"],
551
+ "decision": "approve",
552
+ "risk_flags": []
553
+ }
554
+ },
555
+ {
556
+ "id": "easy_023",
557
+ "difficulty": "easy",
558
+ "input": {
559
+ "clinical_note": "Patient presents with gastroenteritis. Nausea, vomiting, and watery diarrhea for 2 days. No blood in stool. Mild dehydration. Oral rehydration recommended. Symptoms improving.",
560
+ "symptoms": ["nausea", "vomiting", "watery diarrhea", "abdominal cramps"],
561
+ "treatments": ["oral rehydration", "bland diet"],
562
+ "insurance_type": "Private",
563
+ "prior_auth_required": false,
564
+ "treatment_cost": "low",
565
+ "patient_age": 27,
566
+ "patient_sex": "M",
567
+ "provider_specialty": "Family Medicine",
568
+ "visit_type": "outpatient",
569
+ "comorbidities": [],
570
+ "lab_results": null,
571
+ "medications": ["ondansetron 4mg PRN"]
572
+ },
573
+ "ground_truth": {
574
+ "diagnosis_codes": ["K52.9"],
575
+ "procedure_codes": ["99213"],
576
+ "decision": "approve",
577
+ "risk_flags": []
578
+ }
579
+ },
580
+ {
581
+ "id": "easy_024",
582
+ "difficulty": "easy",
583
+ "input": {
584
+ "clinical_note": "Patient presents with wrist pain after fall on outstretched hand. X-ray shows distal radius fracture, non-displaced. Short arm cast applied. Orthopedic follow-up arranged.",
585
+ "symptoms": ["wrist pain", "swelling", "limited wrist motion"],
586
+ "treatments": ["short arm cast", "pain management"],
587
+ "insurance_type": "Private",
588
+ "prior_auth_required": false,
589
+ "treatment_cost": "medium",
590
+ "patient_age": 11,
591
+ "patient_sex": "M",
592
+ "provider_specialty": "Emergency Medicine",
593
+ "visit_type": "emergency",
594
+ "comorbidities": [],
595
+ "lab_results": "X-ray left wrist: Non-displaced distal radius fracture",
596
+ "medications": ["ibuprofen 200mg TID"]
597
+ },
598
+ "ground_truth": {
599
+ "diagnosis_codes": ["S52.501"],
600
+ "procedure_codes": ["99283"],
601
+ "decision": "approve",
602
+ "risk_flags": []
603
+ }
604
+ },
605
+ {
606
+ "id": "easy_025",
607
+ "difficulty": "easy",
608
+ "input": {
609
+ "clinical_note": "Patient presents for hypothyroidism follow-up. TSH 3.2 mIU/L on levothyroxine 75mcg. Symptoms well controlled. No dose adjustment needed. Continue current therapy.",
610
+ "symptoms": [],
611
+ "treatments": ["levothyroxine continuation"],
612
+ "insurance_type": "Medicare",
613
+ "prior_auth_required": false,
614
+ "treatment_cost": "low",
615
+ "patient_age": 56,
616
+ "patient_sex": "F",
617
+ "provider_specialty": "Endocrinology",
618
+ "visit_type": "outpatient",
619
+ "comorbidities": ["hypothyroidism"],
620
+ "lab_results": "TSH: 3.2 mIU/L (normal range 0.4-4.0)",
621
+ "medications": ["levothyroxine 75mcg daily"]
622
+ },
623
+ "ground_truth": {
624
+ "diagnosis_codes": ["E03.9"],
625
+ "procedure_codes": ["99214"],
626
+ "decision": "approve",
627
+ "risk_flags": []
628
+ }
629
+ },
630
+ {
631
+ "id": "easy_026",
632
+ "difficulty": "easy",
633
+ "input": {
634
+ "clinical_note": "Patient presents with mild depression. PHQ-9 score of 8. No suicidal ideation. Started on sertraline 50mg. Counseling referral provided. Follow up in 4 weeks.",
635
+ "symptoms": ["depressed mood", "decreased interest", "fatigue", "difficulty concentrating"],
636
+ "treatments": ["sertraline", "counseling referral"],
637
+ "insurance_type": "Private",
638
+ "prior_auth_required": false,
639
+ "treatment_cost": "low",
640
+ "patient_age": 33,
641
+ "patient_sex": "F",
642
+ "provider_specialty": "Family Medicine",
643
+ "visit_type": "outpatient",
644
+ "comorbidities": [],
645
+ "lab_results": "PHQ-9: 8 (mild depression)",
646
+ "medications": ["sertraline 50mg daily"]
647
+ },
648
+ "ground_truth": {
649
+ "diagnosis_codes": ["F32.0"],
650
+ "procedure_codes": ["99214"],
651
+ "decision": "approve",
652
+ "risk_flags": []
653
+ }
654
+ },
655
+ {
656
+ "id": "easy_027",
657
+ "difficulty": "easy",
658
+ "input": {
659
+ "clinical_note": "Patient presents with tinea pedis. Itchy, scaly rash between toes bilaterally. Classic interdigital presentation. Prescribed topical clotrimazole cream.",
660
+ "symptoms": ["itchy feet", "scaly rash between toes", "mild burning"],
661
+ "treatments": ["clotrimazole cream"],
662
+ "insurance_type": "Private",
663
+ "prior_auth_required": false,
664
+ "treatment_cost": "low",
665
+ "patient_age": 44,
666
+ "patient_sex": "M",
667
+ "provider_specialty": "Family Medicine",
668
+ "visit_type": "outpatient",
669
+ "comorbidities": [],
670
+ "lab_results": null,
671
+ "medications": ["clotrimazole 1% cream BID"]
672
+ },
673
+ "ground_truth": {
674
+ "diagnosis_codes": ["B35.3"],
675
+ "procedure_codes": ["99213"],
676
+ "decision": "approve",
677
+ "risk_flags": []
678
+ }
679
+ },
680
+ {
681
+ "id": "easy_028",
682
+ "difficulty": "easy",
683
+ "input": {
684
+ "clinical_note": "Patient presents requesting a tetanus booster. Last Tdap was over 10 years ago. No acute injuries. Td vaccine administered in right deltoid without complications.",
685
+ "symptoms": [],
686
+ "treatments": ["Td vaccination"],
687
+ "insurance_type": "Private",
688
+ "prior_auth_required": false,
689
+ "treatment_cost": "low",
690
+ "patient_age": 50,
691
+ "patient_sex": "M",
692
+ "provider_specialty": "Family Medicine",
693
+ "visit_type": "outpatient",
694
+ "comorbidities": [],
695
+ "lab_results": null,
696
+ "medications": []
697
+ },
698
+ "ground_truth": {
699
+ "diagnosis_codes": ["Z23"],
700
+ "procedure_codes": ["90714"],
701
+ "decision": "approve",
702
+ "risk_flags": []
703
+ }
704
+ },
705
+ {
706
+ "id": "easy_029",
707
+ "difficulty": "easy",
708
+ "input": {
709
+ "clinical_note": "Patient presents with constipation. No bowel movement for 4 days. Abdomen soft, non-distended. No alarming features. Advised increased fiber and fluids. Prescribed polyethylene glycol.",
710
+ "symptoms": ["constipation", "mild abdominal discomfort", "bloating"],
711
+ "treatments": ["dietary fiber increase", "polyethylene glycol"],
712
+ "insurance_type": "Private",
713
+ "prior_auth_required": false,
714
+ "treatment_cost": "low",
715
+ "patient_age": 48,
716
+ "patient_sex": "F",
717
+ "provider_specialty": "Family Medicine",
718
+ "visit_type": "outpatient",
719
+ "comorbidities": [],
720
+ "lab_results": null,
721
+ "medications": ["polyethylene glycol 17g daily"]
722
+ },
723
+ "ground_truth": {
724
+ "diagnosis_codes": ["K59.00"],
725
+ "procedure_codes": ["99213"],
726
+ "decision": "approve",
727
+ "risk_flags": []
728
+ }
729
+ },
730
+ {
731
+ "id": "easy_030",
732
+ "difficulty": "easy",
733
+ "input": {
734
+ "clinical_note": "Patient presents with plantar fasciitis. Heel pain worse with first steps in morning. Tenderness at medial calcaneal tubercle. Recommended stretching exercises, ice, and supportive footwear.",
735
+ "symptoms": ["heel pain", "pain with first steps", "tenderness at heel"],
736
+ "treatments": ["stretching exercises", "ice therapy", "supportive footwear"],
737
+ "insurance_type": "Private",
738
+ "prior_auth_required": false,
739
+ "treatment_cost": "low",
740
+ "patient_age": 42,
741
+ "patient_sex": "M",
742
+ "provider_specialty": "Orthopedics",
743
+ "visit_type": "outpatient",
744
+ "comorbidities": [],
745
+ "lab_results": null,
746
+ "medications": ["naproxen 500mg BID PRN"]
747
+ },
748
+ "ground_truth": {
749
+ "diagnosis_codes": ["M72.2"],
750
+ "procedure_codes": ["99213"],
751
+ "decision": "approve",
752
+ "risk_flags": []
753
+ }
754
+ }
755
+ ]
756
+ }
tasks/hard.json ADDED
@@ -0,0 +1,756 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "difficulty": "hard",
3
+ "description": "Complex cases with compliance dilemmas, upcoding/fraud scenarios, insurance denial situations, ambiguous diagnoses, and multi-system conditions requiring nuanced coding decisions.",
4
+ "cases": [
5
+ {
6
+ "id": "hard_001",
7
+ "difficulty": "hard",
8
+ "input": {
9
+ "clinical_note": "82-year-old Medicare patient presents with knee pain. Provider documents 'severe arthritis' but X-ray shows only mild degenerative changes. Provider orders MRI, bilateral knee injections, and schedules total knee replacement consultation. Documentation does not support the level of intervention being pursued. Prior conservative measures not documented.",
10
+ "symptoms": ["mild knee pain", "slight stiffness"],
11
+ "treatments": ["bilateral knee injections", "MRI ordered", "TKR consultation"],
12
+ "insurance_type": "Medicare",
13
+ "prior_auth_required": true,
14
+ "treatment_cost": "high",
15
+ "patient_age": 82,
16
+ "patient_sex": "F",
17
+ "provider_specialty": "Orthopedics",
18
+ "visit_type": "outpatient",
19
+ "comorbidities": ["hypertension", "type 2 diabetes", "CKD stage 3"],
20
+ "lab_results": "X-ray bilateral knees: Mild degenerative changes, no significant joint space narrowing",
21
+ "medications": ["lisinopril 20mg", "metformin 500mg", "acetaminophen PRN"]
22
+ },
23
+ "ground_truth": {
24
+ "diagnosis_codes": ["M17.9"],
25
+ "procedure_codes": ["99213"],
26
+ "decision": "reject",
27
+ "risk_flags": ["upcoding_risk", "documentation_mismatch", "medically_unnecessary"]
28
+ }
29
+ },
30
+ {
31
+ "id": "hard_002",
32
+ "difficulty": "hard",
33
+ "input": {
34
+ "clinical_note": "45-year-old patient with vague abdominal complaints. Provider orders extensive workup: CT abdomen/pelvis with contrast, MRI abdomen, upper and lower endoscopy, capsule endoscopy, and tumor markers panel. Patient has no alarm symptoms, no weight loss, no family history of GI cancer. Physical exam unremarkable. Labs are all normal.",
35
+ "symptoms": ["mild abdominal discomfort", "occasional bloating"],
36
+ "treatments": ["CT abdomen/pelvis", "MRI abdomen", "EGD", "colonoscopy", "capsule endoscopy", "tumor markers"],
37
+ "insurance_type": "Private",
38
+ "prior_auth_required": true,
39
+ "treatment_cost": "high",
40
+ "patient_age": 45,
41
+ "patient_sex": "M",
42
+ "provider_specialty": "Gastroenterology",
43
+ "visit_type": "outpatient",
44
+ "comorbidities": [],
45
+ "lab_results": "CBC: normal, CMP: normal, Lipase: normal, Celiac panel: negative",
46
+ "medications": []
47
+ },
48
+ "ground_truth": {
49
+ "diagnosis_codes": ["R10.9"],
50
+ "procedure_codes": ["99214"],
51
+ "decision": "reject",
52
+ "risk_flags": ["excessive_testing", "medically_unnecessary", "documentation_mismatch"]
53
+ }
54
+ },
55
+ {
56
+ "id": "hard_003",
57
+ "difficulty": "hard",
58
+ "input": {
59
+ "clinical_note": "70-year-old male with metastatic non-small cell lung cancer, stage IV. ECOG 3. Multiple brain metastases, liver metastases, bone metastases. Failed two lines of chemotherapy. Oncologist recommends third-line pembrolizumab despite PD-L1 <1% and poor functional status. Family insists on aggressive treatment. Prognosis estimated at 2-4 weeks.",
60
+ "symptoms": ["severe dyspnea", "cachexia", "confusion", "bone pain", "anorexia"],
61
+ "treatments": ["pembrolizumab proposed", "palliative care discussed"],
62
+ "insurance_type": "Medicare",
63
+ "prior_auth_required": true,
64
+ "treatment_cost": "high",
65
+ "patient_age": 70,
66
+ "patient_sex": "M",
67
+ "provider_specialty": "Oncology",
68
+ "visit_type": "inpatient",
69
+ "comorbidities": ["NSCLC stage IV", "brain metastases", "liver metastases", "bone metastases"],
70
+ "lab_results": "PD-L1: <1%, ECOG: 3, Albumin: 2.1, LDH: 580, CT: progressive disease on 2 prior regimens",
71
+ "medications": ["morphine extended-release", "dexamethasone 4mg BID", "ondansetron PRN"]
72
+ },
73
+ "ground_truth": {
74
+ "diagnosis_codes": ["C34.90", "C79.31", "C78.7", "C79.51"],
75
+ "procedure_codes": ["99223"],
76
+ "decision": "reject",
77
+ "risk_flags": ["medically_unnecessary", "poor_prognosis", "off_label_use", "high_cost_treatment"]
78
+ }
79
+ },
80
+ {
81
+ "id": "hard_004",
82
+ "difficulty": "hard",
83
+ "input": {
84
+ "clinical_note": "55-year-old female with fibromyalgia and chronic pain syndrome. Currently on oxycodone 30mg QID, alprazolam 2mg TID, and carisoprodol 350mg TID — the 'holy trinity' of medications. Provider documents pain as 10/10 at every visit. No functional assessment documented. No multimodal pain management attempted. Requesting increased opioid dose. MME currently at 180.",
85
+ "symptoms": ["diffuse body pain", "fatigue", "sleep disruption", "depression"],
86
+ "treatments": ["oxycodone increase requested", "current polypharmacy"],
87
+ "insurance_type": "Private",
88
+ "prior_auth_required": true,
89
+ "treatment_cost": "medium",
90
+ "patient_age": 55,
91
+ "patient_sex": "F",
92
+ "provider_specialty": "Pain Medicine",
93
+ "visit_type": "outpatient",
94
+ "comorbidities": ["fibromyalgia", "chronic pain syndrome", "depression", "anxiety"],
95
+ "lab_results": "Urine drug screen: consistent with prescribed medications, no illicit substances",
96
+ "medications": ["oxycodone 30mg QID", "alprazolam 2mg TID", "carisoprodol 350mg TID"]
97
+ },
98
+ "ground_truth": {
99
+ "diagnosis_codes": ["M79.7"],
100
+ "procedure_codes": ["99214"],
101
+ "decision": "reject",
102
+ "risk_flags": ["dangerous_polypharmacy", "high_mme_opioid", "missing_documentation", "controlled_substance"]
103
+ }
104
+ },
105
+ {
106
+ "id": "hard_005",
107
+ "difficulty": "hard",
108
+ "input": {
109
+ "clinical_note": "Patient presents with chest pain. Provider bills 99285 (highest ED code) for what appears to be a straightforward evaluation. Documentation shows: 'Patient presents with chest pain. ECG normal. Troponin negative. Chest X-ray normal. Patient discharged with follow-up.' Total ED time: 45 minutes. No critical interventions performed.",
110
+ "symptoms": ["chest pain", "mild anxiety"],
111
+ "treatments": ["ECG", "troponin", "chest X-ray"],
112
+ "insurance_type": "Medicare",
113
+ "prior_auth_required": false,
114
+ "treatment_cost": "medium",
115
+ "patient_age": 52,
116
+ "patient_sex": "M",
117
+ "provider_specialty": "Emergency Medicine",
118
+ "visit_type": "emergency",
119
+ "comorbidities": ["anxiety disorder"],
120
+ "lab_results": "ECG: Normal sinus rhythm, Troponin: <0.04 (negative), CXR: No acute process",
121
+ "medications": []
122
+ },
123
+ "ground_truth": {
124
+ "diagnosis_codes": ["R07.9"],
125
+ "procedure_codes": ["99283"],
126
+ "decision": "review",
127
+ "risk_flags": ["upcoding_risk", "documentation_mismatch"]
128
+ }
129
+ },
130
+ {
131
+ "id": "hard_006",
132
+ "difficulty": "hard",
133
+ "input": {
134
+ "clinical_note": "38-year-old healthy female requests full body MRI screening. No symptoms, no risk factors, no family history of cancer. Provider orders whole body MRI, PET-CT, comprehensive tumor marker panel (CA-125, CEA, AFP, CA 19-9, PSA), and genetic testing panel. Bills as diagnostic workup for 'suspected malignancy.'",
135
+ "symptoms": [],
136
+ "treatments": ["whole body MRI", "PET-CT", "tumor markers", "genetic testing"],
137
+ "insurance_type": "Private",
138
+ "prior_auth_required": true,
139
+ "treatment_cost": "high",
140
+ "patient_age": 38,
141
+ "patient_sex": "F",
142
+ "provider_specialty": "Internal Medicine",
143
+ "visit_type": "outpatient",
144
+ "comorbidities": [],
145
+ "lab_results": "All routine labs normal",
146
+ "medications": []
147
+ },
148
+ "ground_truth": {
149
+ "diagnosis_codes": ["Z00.00"],
150
+ "procedure_codes": ["99214"],
151
+ "decision": "reject",
152
+ "risk_flags": ["medically_unnecessary", "upcoding_risk", "false_diagnosis_coding", "excessive_testing"]
153
+ }
154
+ },
155
+ {
156
+ "id": "hard_007",
157
+ "difficulty": "hard",
158
+ "input": {
159
+ "clinical_note": "Patient with chronic back pain. Provider performs 'trigger point injections' at 12 sites across the back in one session, billing each injection separately. Also bills for fluoroscopic guidance for each injection despite trigger point injections not requiring imaging guidance. Additionally bills an E&M code at the highest level.",
160
+ "symptoms": ["chronic back pain", "muscle tension"],
161
+ "treatments": ["12 trigger point injections", "fluoroscopic guidance x12"],
162
+ "insurance_type": "Medicare",
163
+ "prior_auth_required": false,
164
+ "treatment_cost": "high",
165
+ "patient_age": 60,
166
+ "patient_sex": "M",
167
+ "provider_specialty": "Pain Medicine",
168
+ "visit_type": "outpatient",
169
+ "comorbidities": ["chronic low back pain", "degenerative disc disease"],
170
+ "lab_results": null,
171
+ "medications": ["gabapentin 600mg TID", "cyclobenzaprine 10mg TID"]
172
+ },
173
+ "ground_truth": {
174
+ "diagnosis_codes": ["M54.5"],
175
+ "procedure_codes": ["20552"],
176
+ "decision": "reject",
177
+ "risk_flags": ["unbundling_violation", "upcoding_risk", "medically_unnecessary", "billing_fraud"]
178
+ }
179
+ },
180
+ {
181
+ "id": "hard_008",
182
+ "difficulty": "hard",
183
+ "input": {
184
+ "clinical_note": "48-year-old female with lupus nephritis class IV on mycophenolate and prednisone. Presents with increasing proteinuria (3.5g/24hr), rising creatinine (2.1 from baseline 1.2), and new anti-dsDNA titer rise. Nephrologist recommends adding rituximab. Insurance denies rituximab as 'experimental' for lupus nephritis despite growing evidence base.",
185
+ "symptoms": ["fatigue", "facial edema", "foamy urine", "joint pain", "malar rash"],
186
+ "treatments": ["rituximab requested", "mycophenolate continuation", "prednisone increase"],
187
+ "insurance_type": "Private",
188
+ "prior_auth_required": true,
189
+ "treatment_cost": "high",
190
+ "patient_age": 48,
191
+ "patient_sex": "F",
192
+ "provider_specialty": "Nephrology",
193
+ "visit_type": "outpatient",
194
+ "comorbidities": ["SLE", "lupus nephritis class IV", "hypertension"],
195
+ "lab_results": "Cr: 2.1, 24hr protein: 3.5g, C3: 45 (low), C4: 8 (low), anti-dsDNA: 1:640, eGFR: 32",
196
+ "medications": ["mycophenolate 1500mg BID", "prednisone 20mg daily", "hydroxychloroquine 200mg BID"]
197
+ },
198
+ "ground_truth": {
199
+ "diagnosis_codes": ["M32.14", "N04.9"],
200
+ "procedure_codes": ["99215"],
201
+ "decision": "review",
202
+ "risk_flags": ["off_label_use", "high_cost_treatment", "prior_auth_needed"]
203
+ }
204
+ },
205
+ {
206
+ "id": "hard_009",
207
+ "difficulty": "hard",
208
+ "input": {
209
+ "clinical_note": "Uninsured 35-year-old male presents with diabetic ketoacidosis. Blood glucose 580 mg/dL, pH 7.18, bicarbonate 8. Admitted to ICU. Insulin drip, aggressive fluid resuscitation, electrolyte replacement. Patient has no primary care provider and has been rationing insulin due to cost. A1C 14.2%. ICU stay 3 days, total hospitalization 5 days.",
210
+ "symptoms": ["nausea", "vomiting", "abdominal pain", "altered mental status", "Kussmaul breathing"],
211
+ "treatments": ["insulin drip", "IV fluids", "electrolyte replacement", "ICU monitoring"],
212
+ "insurance_type": "Uninsured",
213
+ "prior_auth_required": false,
214
+ "treatment_cost": "high",
215
+ "patient_age": 35,
216
+ "patient_sex": "M",
217
+ "provider_specialty": "Critical Care",
218
+ "visit_type": "inpatient",
219
+ "comorbidities": ["type 1 diabetes", "medication non-adherence"],
220
+ "lab_results": "Glucose: 580, pH: 7.18, HCO3: 8, Anion gap: 28, K: 5.8, A1C: 14.2%, BUN: 32",
221
+ "medications": ["insulin drip", "normal saline 1L/hr", "potassium replacement"]
222
+ },
223
+ "ground_truth": {
224
+ "diagnosis_codes": ["E10.10", "E10.65"],
225
+ "procedure_codes": ["99223"],
226
+ "decision": "approve",
227
+ "risk_flags": ["high_cost_treatment", "social_determinants"]
228
+ }
229
+ },
230
+ {
231
+ "id": "hard_010",
232
+ "difficulty": "hard",
233
+ "input": {
234
+ "clinical_note": "Provider bills for a 'comprehensive metabolic panel' on every patient visit regardless of indication. Today's patient is a 25-year-old presenting for acne follow-up on topical retinoid only. Provider orders CMP, CBC, lipid panel, TSH, vitamin D, B12, folate, iron studies, and ANA. No clinical indication for any of these labs based on the presenting complaint.",
235
+ "symptoms": ["facial acne"],
236
+ "treatments": ["topical tretinoin continuation", "extensive lab panel ordered"],
237
+ "insurance_type": "Private",
238
+ "prior_auth_required": false,
239
+ "treatment_cost": "medium",
240
+ "patient_age": 25,
241
+ "patient_sex": "F",
242
+ "provider_specialty": "Dermatology",
243
+ "visit_type": "outpatient",
244
+ "comorbidities": [],
245
+ "lab_results": null,
246
+ "medications": ["tretinoin 0.025% cream nightly"]
247
+ },
248
+ "ground_truth": {
249
+ "diagnosis_codes": ["L70.0"],
250
+ "procedure_codes": ["99213"],
251
+ "decision": "reject",
252
+ "risk_flags": ["excessive_testing", "medically_unnecessary", "billing_fraud"]
253
+ }
254
+ },
255
+ {
256
+ "id": "hard_011",
257
+ "difficulty": "hard",
258
+ "input": {
259
+ "clinical_note": "62-year-old diabetic male with chronic non-healing foot ulcer, Wagner grade 2. Wound measures 3x4cm on plantar surface of right foot. Debrided in office. ABI 0.7 suggesting mild PAD. HbA1c 9.8%. Provider recommends hyperbaric oxygen therapy (40 sessions) and applies advanced wound care product (human skin substitute). Wound has only been present for 3 weeks with no prior standard wound care attempted.",
260
+ "symptoms": ["foot ulcer", "mild pain", "drainage from wound"],
261
+ "treatments": ["wound debridement", "HBO therapy proposed", "advanced wound care product"],
262
+ "insurance_type": "Medicare",
263
+ "prior_auth_required": true,
264
+ "treatment_cost": "high",
265
+ "patient_age": 62,
266
+ "patient_sex": "M",
267
+ "provider_specialty": "Wound Care",
268
+ "visit_type": "outpatient",
269
+ "comorbidities": ["type 2 diabetes", "peripheral arterial disease", "neuropathy"],
270
+ "lab_results": "ABI: 0.7, A1C: 9.8%, Wound culture: Staph aureus, WBC: 11,500",
271
+ "medications": ["insulin glargine 40u", "metformin 1000mg BID", "cephalexin 500mg QID"]
272
+ },
273
+ "ground_truth": {
274
+ "diagnosis_codes": ["E11.621", "L97.519"],
275
+ "procedure_codes": ["11042"],
276
+ "decision": "review",
277
+ "risk_flags": ["premature_advanced_therapy", "missing_documentation", "high_cost_treatment"]
278
+ }
279
+ },
280
+ {
281
+ "id": "hard_012",
282
+ "difficulty": "hard",
283
+ "input": {
284
+ "clinical_note": "Provider sees 15-year-old for sore throat and documents with 99215 (highest outpatient E&M code, typically 40+ minutes for complex patients). Visit duration was 10 minutes per schedule. Rapid strep positive. Prescribed amoxicillin. Provider also bills for separate counseling code and care coordination code for this straightforward visit.",
285
+ "symptoms": ["sore throat", "fever", "tonsillar exudate"],
286
+ "treatments": ["amoxicillin", "rapid strep test"],
287
+ "insurance_type": "Medicaid",
288
+ "prior_auth_required": false,
289
+ "treatment_cost": "low",
290
+ "patient_age": 15,
291
+ "patient_sex": "M",
292
+ "provider_specialty": "Pediatrics",
293
+ "visit_type": "outpatient",
294
+ "comorbidities": [],
295
+ "lab_results": "Rapid strep: Positive",
296
+ "medications": ["amoxicillin 500mg BID x10 days"]
297
+ },
298
+ "ground_truth": {
299
+ "diagnosis_codes": ["J02.0"],
300
+ "procedure_codes": ["99213"],
301
+ "decision": "reject",
302
+ "risk_flags": ["upcoding_risk", "documentation_mismatch", "unbundling_violation"]
303
+ }
304
+ },
305
+ {
306
+ "id": "hard_013",
307
+ "difficulty": "hard",
308
+ "input": {
309
+ "clinical_note": "58-year-old female with suspected somatization disorder. Reports 15+ symptoms across multiple organ systems over past 2 years, including chest pain, abdominal pain, headaches, numbness, blindness episodes, and seizure-like episodes. Extensive prior workup entirely negative including cardiac cath, brain MRI, EEG, endoscopy, and colonoscopy. Provider now orders repeat of all prior tests.",
310
+ "symptoms": ["chest pain", "abdominal pain", "headaches", "numbness", "blindness episodes", "pseudo-seizures"],
311
+ "treatments": ["repeat cardiac catheterization", "repeat MRI brain", "repeat EEG", "repeat endoscopy"],
312
+ "insurance_type": "Medicare",
313
+ "prior_auth_required": true,
314
+ "treatment_cost": "high",
315
+ "patient_age": 58,
316
+ "patient_sex": "F",
317
+ "provider_specialty": "Internal Medicine",
318
+ "visit_type": "outpatient",
319
+ "comorbidities": ["anxiety", "depression"],
320
+ "lab_results": "All prior extensive workup: negative. No new clinical findings to justify repeat testing.",
321
+ "medications": ["sertraline 100mg", "gabapentin 300mg TID"]
322
+ },
323
+ "ground_truth": {
324
+ "diagnosis_codes": ["F45.0"],
325
+ "procedure_codes": ["99215"],
326
+ "decision": "reject",
327
+ "risk_flags": ["excessive_testing", "medically_unnecessary", "missing_documentation"]
328
+ }
329
+ },
330
+ {
331
+ "id": "hard_014",
332
+ "difficulty": "hard",
333
+ "input": {
334
+ "clinical_note": "Septic patient, 74-year-old male with E. coli bacteremia from urinary source. Blood cultures positive. Lactate 4.2. BP 82/50, HR 112. Initial fluid resuscitation 30mL/kg, started on vasopressors. Piperacillin-tazobactam empirically, narrowed to ceftriaxone per sensitivities. Central line placed. ICU admission. APACHE II score 22.",
335
+ "symptoms": ["fever", "hypotension", "tachycardia", "altered mental status", "rigors"],
336
+ "treatments": ["IV antibiotics", "vasopressors", "fluid resuscitation", "central line", "ICU monitoring"],
337
+ "insurance_type": "Medicare",
338
+ "prior_auth_required": false,
339
+ "treatment_cost": "high",
340
+ "patient_age": 74,
341
+ "patient_sex": "M",
342
+ "provider_specialty": "Critical Care",
343
+ "visit_type": "inpatient",
344
+ "comorbidities": ["BPH", "type 2 diabetes", "CKD stage 3", "hypertension"],
345
+ "lab_results": "Blood cx: E. coli, Lactate: 4.2, WBC: 22,000, Cr: 2.8 (baseline 1.5), Procalcitonin: 12.5",
346
+ "medications": ["ceftriaxone 2g IV daily", "norepinephrine drip", "insulin drip", "normal saline"]
347
+ },
348
+ "ground_truth": {
349
+ "diagnosis_codes": ["A41.51", "R65.21", "N39.0"],
350
+ "procedure_codes": ["99223", "36556"],
351
+ "decision": "approve",
352
+ "risk_flags": ["multiple_diagnoses", "high_cost_treatment"]
353
+ }
354
+ },
355
+ {
356
+ "id": "hard_015",
357
+ "difficulty": "hard",
358
+ "input": {
359
+ "clinical_note": "32-year-old female with chronic Lyme disease diagnosis by naturopath. No positive standard two-tier testing. Provider administers long-term IV ceftriaxone through PICC line for 3 months despite IDSA guidelines recommending against prolonged antibiotic therapy for 'chronic Lyme.' Patient also receiving IV hydrogen peroxide and high-dose IV vitamin C as 'Lyme protocols.'",
360
+ "symptoms": ["fatigue", "joint pain", "brain fog", "insomnia"],
361
+ "treatments": ["IV ceftriaxone 3 months", "IV hydrogen peroxide", "IV vitamin C", "PICC line"],
362
+ "insurance_type": "Private",
363
+ "prior_auth_required": true,
364
+ "treatment_cost": "high",
365
+ "patient_age": 32,
366
+ "patient_sex": "F",
367
+ "provider_specialty": "Internal Medicine",
368
+ "visit_type": "outpatient",
369
+ "comorbidities": [],
370
+ "lab_results": "Lyme ELISA: negative, Western blot: not performed, CBC: normal, CMP: normal",
371
+ "medications": ["ceftriaxone 2g IV daily", "vitamin C IV", "hydrogen peroxide IV"]
372
+ },
373
+ "ground_truth": {
374
+ "diagnosis_codes": ["R53.83"],
375
+ "procedure_codes": ["99214"],
376
+ "decision": "reject",
377
+ "risk_flags": ["unproven_treatment", "medically_unnecessary", "patient_safety_risk", "false_diagnosis_coding"]
378
+ }
379
+ },
380
+ {
381
+ "id": "hard_016",
382
+ "difficulty": "hard",
383
+ "input": {
384
+ "clinical_note": "Dual-eligible patient (Medicare + Medicaid), 80-year-old with advanced dementia (FAST stage 7c), bedbound, non-verbal. Develops aspiration pneumonia. Family demands full code, ICU admission, mechanical ventilation, and feeding tube placement. Palliative care consult declined by family. Question of whether aggressive interventions are medically appropriate given baseline functional status.",
385
+ "symptoms": ["fever", "tachypnea", "oxygen desaturation", "productive cough"],
386
+ "treatments": ["ICU admission", "mechanical ventilation proposed", "PEG tube proposed", "antibiotics"],
387
+ "insurance_type": "Medicare",
388
+ "prior_auth_required": false,
389
+ "treatment_cost": "high",
390
+ "patient_age": 80,
391
+ "patient_sex": "F",
392
+ "provider_specialty": "Internal Medicine",
393
+ "visit_type": "inpatient",
394
+ "comorbidities": ["advanced dementia", "recurrent aspiration pneumonia", "malnutrition", "pressure ulcers"],
395
+ "lab_results": "CXR: bilateral aspiration pneumonia, WBC: 18,000, Albumin: 1.8, prealbumin: 6",
396
+ "medications": ["ceftriaxone 1g IV", "azithromycin 500mg IV"]
397
+ },
398
+ "ground_truth": {
399
+ "diagnosis_codes": ["J69.0", "F03.90"],
400
+ "procedure_codes": ["99223"],
401
+ "decision": "review",
402
+ "risk_flags": ["medical_futility", "ethical_concern", "high_cost_treatment"]
403
+ }
404
+ },
405
+ {
406
+ "id": "hard_017",
407
+ "difficulty": "hard",
408
+ "input": {
409
+ "clinical_note": "Surgeon performs laparoscopic cholecystectomy and documents it as an open cholecystectomy (which reimburses at a higher rate). Operative note describes 4 trocar ports, pneumoperitoneum, and laparoscopic visualization — all hallmarks of laparoscopic approach. No documentation of conversion to open. 45-year-old with symptomatic cholelithiasis.",
410
+ "symptoms": ["RUQ pain", "nausea after fatty meals", "positive Murphy's sign"],
411
+ "treatments": ["cholecystectomy"],
412
+ "insurance_type": "Private",
413
+ "prior_auth_required": false,
414
+ "treatment_cost": "high",
415
+ "patient_age": 45,
416
+ "patient_sex": "F",
417
+ "provider_specialty": "General Surgery",
418
+ "visit_type": "inpatient",
419
+ "comorbidities": ["cholelithiasis"],
420
+ "lab_results": "US: multiple gallstones, GB wall thickening, no CBD dilation, LFTs: mildly elevated",
421
+ "medications": ["ketorolac 30mg IV", "ondansetron 4mg IV"]
422
+ },
423
+ "ground_truth": {
424
+ "diagnosis_codes": ["K80.20"],
425
+ "procedure_codes": ["47562"],
426
+ "decision": "reject",
427
+ "risk_flags": ["billing_fraud", "upcoding_risk", "documentation_mismatch"]
428
+ }
429
+ },
430
+ {
431
+ "id": "hard_018",
432
+ "difficulty": "hard",
433
+ "input": {
434
+ "clinical_note": "28-year-old male with treatment-resistant depression, failed 4 SSRI/SNRI trials, failed augmentation with lithium and aripiprazole. PHQ-9 persistently 22+. Provider recommends esketamine (Spravato) nasal spray. Insurance requires step therapy documentation. All prior treatment failures documented. GAF score 35.",
435
+ "symptoms": ["severe depression", "anhedonia", "suicidal ideation without plan", "insomnia", "weight loss"],
436
+ "treatments": ["esketamine nasal spray proposed", "current venlafaxine continuation"],
437
+ "insurance_type": "Private",
438
+ "prior_auth_required": true,
439
+ "treatment_cost": "high",
440
+ "patient_age": 28,
441
+ "patient_sex": "M",
442
+ "provider_specialty": "Psychiatry",
443
+ "visit_type": "outpatient",
444
+ "comorbidities": ["treatment-resistant depression"],
445
+ "lab_results": "PHQ-9: 22, GAF: 35, TSH: normal, B12: normal, toxicology: negative",
446
+ "medications": ["venlafaxine 225mg daily", "trazodone 100mg QHS"]
447
+ },
448
+ "ground_truth": {
449
+ "diagnosis_codes": ["F33.2"],
450
+ "procedure_codes": ["99215"],
451
+ "decision": "approve",
452
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed", "controlled_substance"]
453
+ }
454
+ },
455
+ {
456
+ "id": "hard_019",
457
+ "difficulty": "hard",
458
+ "input": {
459
+ "clinical_note": "72-year-old female with mild cognitive impairment prescribed lecanemab (Leqembi) — the new anti-amyloid antibody. Amyloid PET positive. However, patient is on anticoagulation for atrial fibrillation (apixaban), which significantly increases ARIA risk. MRI shows 2 prior microhemorrhages. The risk-benefit ratio is questionable given the bleeding risk and the modest clinical benefit.",
460
+ "symptoms": ["memory decline", "word-finding difficulty", "getting lost in familiar places"],
461
+ "treatments": ["lecanemab infusion proposed"],
462
+ "insurance_type": "Medicare",
463
+ "prior_auth_required": true,
464
+ "treatment_cost": "high",
465
+ "patient_age": 72,
466
+ "patient_sex": "F",
467
+ "provider_specialty": "Neurology",
468
+ "visit_type": "outpatient",
469
+ "comorbidities": ["mild cognitive impairment", "atrial fibrillation", "hypertension"],
470
+ "lab_results": "Amyloid PET: positive, MRI: 2 microhemorrhages, MMSE: 22/30, MoCA: 18/30",
471
+ "medications": ["apixaban 5mg BID", "donepezil 10mg", "metoprolol 50mg BID"]
472
+ },
473
+ "ground_truth": {
474
+ "diagnosis_codes": ["G31.84"],
475
+ "procedure_codes": ["99215"],
476
+ "decision": "reject",
477
+ "risk_flags": ["patient_safety_risk", "contraindication", "high_cost_treatment"]
478
+ }
479
+ },
480
+ {
481
+ "id": "hard_020",
482
+ "difficulty": "hard",
483
+ "input": {
484
+ "clinical_note": "Clinic performs 'annual comprehensive metabolic testing' on all patients and bills each component separately rather than as a panel (unbundling). Today's patient: 40-year-old healthy male for routine physical. Billed: glucose, BUN, creatinine, sodium, potassium, chloride, CO2, calcium, total protein, albumin, bilirubin, alkaline phosphatase, AST, ALT individually instead of as CMP (80053).",
485
+ "symptoms": [],
486
+ "treatments": ["routine physical", "individual metabolic labs"],
487
+ "insurance_type": "Private",
488
+ "prior_auth_required": false,
489
+ "treatment_cost": "medium",
490
+ "patient_age": 40,
491
+ "patient_sex": "M",
492
+ "provider_specialty": "Internal Medicine",
493
+ "visit_type": "outpatient",
494
+ "comorbidities": [],
495
+ "lab_results": "All individual metabolic components: normal",
496
+ "medications": []
497
+ },
498
+ "ground_truth": {
499
+ "diagnosis_codes": ["Z00.00"],
500
+ "procedure_codes": ["99395"],
501
+ "decision": "reject",
502
+ "risk_flags": ["unbundling_violation", "billing_fraud"]
503
+ }
504
+ },
505
+ {
506
+ "id": "hard_021",
507
+ "difficulty": "hard",
508
+ "input": {
509
+ "clinical_note": "16-year-old female athlete with ACL tear confirmed on MRI. Orthopedics recommends ACL reconstruction with hamstring autograft. However, patient has open growth plates (Tanner stage 3). Standard ACL reconstruction may damage the physis. Modified technique (physeal-sparing) is appropriate but harder to code. Parents want surgery immediately despite growth plate concerns.",
510
+ "symptoms": ["knee instability", "swelling", "giving way episodes", "inability to return to sport"],
511
+ "treatments": ["physeal-sparing ACL reconstruction recommended"],
512
+ "insurance_type": "Private",
513
+ "prior_auth_required": true,
514
+ "treatment_cost": "high",
515
+ "patient_age": 16,
516
+ "patient_sex": "F",
517
+ "provider_specialty": "Orthopedics",
518
+ "visit_type": "outpatient",
519
+ "comorbidities": [],
520
+ "lab_results": "MRI right knee: Complete ACL tear, no meniscal tear, bone bruise lateral femoral condyle",
521
+ "medications": ["naproxen 500mg BID", "knee brace"]
522
+ },
523
+ "ground_truth": {
524
+ "diagnosis_codes": ["S83.511"],
525
+ "procedure_codes": ["29888"],
526
+ "decision": "review",
527
+ "risk_flags": ["pediatric_consideration", "growth_plate_risk", "prior_auth_needed"]
528
+ }
529
+ },
530
+ {
531
+ "id": "hard_022",
532
+ "difficulty": "hard",
533
+ "input": {
534
+ "clinical_note": "Provider documents a level 5 new patient visit (99205) for a patient who was actually seen 18 months ago (technically a new patient per 3-year rule). Visit is for straightforward hypertension follow-up. Provider copies previous note and changes the date — classic 'cloned note.' Physical exam section is identical word-for-word to 3 prior visits.",
535
+ "symptoms": ["none — routine follow-up"],
536
+ "treatments": ["antihypertensive continuation"],
537
+ "insurance_type": "Medicare",
538
+ "prior_auth_required": false,
539
+ "treatment_cost": "low",
540
+ "patient_age": 68,
541
+ "patient_sex": "M",
542
+ "provider_specialty": "Internal Medicine",
543
+ "visit_type": "outpatient",
544
+ "comorbidities": ["hypertension"],
545
+ "lab_results": "BP: 132/80",
546
+ "medications": ["amlodipine 5mg daily"]
547
+ },
548
+ "ground_truth": {
549
+ "diagnosis_codes": ["I10"],
550
+ "procedure_codes": ["99213"],
551
+ "decision": "reject",
552
+ "risk_flags": ["upcoding_risk", "cloned_documentation", "documentation_mismatch", "billing_fraud"]
553
+ }
554
+ },
555
+ {
556
+ "id": "hard_023",
557
+ "difficulty": "hard",
558
+ "input": {
559
+ "clinical_note": "40-year-old male with acute ST-elevation MI. Transferred emergently from community hospital. Cardiac cath shows 99% LAD occlusion. Primary PCI with drug-eluting stent performed. Door-to-balloon time 55 minutes. EF post-procedure 35%. Started on dual antiplatelet therapy, high-intensity statin, beta-blocker, ACE inhibitor. Complex case with appropriate coding needed.",
560
+ "symptoms": ["crushing chest pain", "diaphoresis", "nausea", "dyspnea", "ST elevation on ECG"],
561
+ "treatments": ["primary PCI with DES", "dual antiplatelet therapy", "GDMT initiation"],
562
+ "insurance_type": "Private",
563
+ "prior_auth_required": false,
564
+ "treatment_cost": "high",
565
+ "patient_age": 40,
566
+ "patient_sex": "M",
567
+ "provider_specialty": "Interventional Cardiology",
568
+ "visit_type": "inpatient",
569
+ "comorbidities": ["active smoker", "family history of premature CAD"],
570
+ "lab_results": "Troponin I: 45.2, ECG: ST elevation V1-V4, Cath: 99% LAD stenosis, EF: 35%",
571
+ "medications": ["aspirin 325mg", "ticagrelor 90mg BID", "atorvastatin 80mg", "metoprolol 25mg BID", "lisinopril 5mg"]
572
+ },
573
+ "ground_truth": {
574
+ "diagnosis_codes": ["I21.01"],
575
+ "procedure_codes": ["92928", "93458"],
576
+ "decision": "approve",
577
+ "risk_flags": ["high_cost_treatment"]
578
+ }
579
+ },
580
+ {
581
+ "id": "hard_024",
582
+ "difficulty": "hard",
583
+ "input": {
584
+ "clinical_note": "Dermatology clinic performs shave biopsies on 8 benign-appearing lesions in one visit, coding each as a separate diagnostic biopsy rather than as destruction of benign lesions. All lesions are small (<0.5cm) seborrheic keratoses that could be diagnosed clinically. No clinical suspicion of malignancy documented for any lesion.",
585
+ "symptoms": ["cosmetic concern about skin lesions"],
586
+ "treatments": ["8 shave biopsies of seborrheic keratoses"],
587
+ "insurance_type": "Medicare",
588
+ "prior_auth_required": false,
589
+ "treatment_cost": "medium",
590
+ "patient_age": 75,
591
+ "patient_sex": "M",
592
+ "provider_specialty": "Dermatology",
593
+ "visit_type": "outpatient",
594
+ "comorbidities": [],
595
+ "lab_results": null,
596
+ "medications": []
597
+ },
598
+ "ground_truth": {
599
+ "diagnosis_codes": ["L82.1"],
600
+ "procedure_codes": ["17110"],
601
+ "decision": "reject",
602
+ "risk_flags": ["upcoding_risk", "medically_unnecessary", "unbundling_violation"]
603
+ }
604
+ },
605
+ {
606
+ "id": "hard_025",
607
+ "difficulty": "hard",
608
+ "input": {
609
+ "clinical_note": "50-year-old male with cirrhosis (Child-Pugh C) and hepatocellular carcinoma. Single 3cm lesion in right lobe. MELD score 28. Listed for liver transplant. However, recent PET scan shows suspicious pulmonary nodule 1.2cm. Biopsy pending. If metastatic, patient would be delisted from transplant. Provider orders both transplant workup and HCC-directed therapy simultaneously.",
610
+ "symptoms": ["jaundice", "ascites", "confusion", "fatigue", "weight loss"],
611
+ "treatments": ["transplant evaluation", "TACE proposed", "lung biopsy pending"],
612
+ "insurance_type": "Medicare",
613
+ "prior_auth_required": true,
614
+ "treatment_cost": "high",
615
+ "patient_age": 50,
616
+ "patient_sex": "M",
617
+ "provider_specialty": "Hepatology",
618
+ "visit_type": "inpatient",
619
+ "comorbidities": ["cirrhosis Child-Pugh C", "HCC", "portal hypertension", "hepatic encephalopathy"],
620
+ "lab_results": "MELD: 28, AFP: 450, CT: 3cm HCC right lobe, PET: 1.2cm pulmonary nodule, INR: 2.1, Albumin: 2.0",
621
+ "medications": ["lactulose 30mL TID", "rifaximin 550mg BID", "furosemide 40mg", "spironolactone 100mg"]
622
+ },
623
+ "ground_truth": {
624
+ "diagnosis_codes": ["C22.0", "K74.60", "R91.1"],
625
+ "procedure_codes": ["99223"],
626
+ "decision": "review",
627
+ "risk_flags": ["premature_treatment", "pending_diagnostic_results", "high_cost_treatment", "multiple_diagnoses"]
628
+ }
629
+ },
630
+ {
631
+ "id": "hard_026",
632
+ "difficulty": "hard",
633
+ "input": {
634
+ "clinical_note": "Pain clinic patient receiving monthly epidural steroid injections for 14 consecutive months for chronic low back pain. Guidelines recommend maximum 3-4 per year. No documentation of functional improvement. Patient's pain scores unchanged from baseline. No alternative treatments tried. Provider continues injections citing patient satisfaction.",
635
+ "symptoms": ["chronic low back pain", "unchanged pain scores 7/10"],
636
+ "treatments": ["14th monthly epidural steroid injection"],
637
+ "insurance_type": "Medicare",
638
+ "prior_auth_required": false,
639
+ "treatment_cost": "medium",
640
+ "patient_age": 65,
641
+ "patient_sex": "F",
642
+ "provider_specialty": "Pain Medicine",
643
+ "visit_type": "outpatient",
644
+ "comorbidities": ["chronic low back pain", "lumbar spondylosis", "osteoporosis"],
645
+ "lab_results": "MRI lumbar (12 months ago): moderate spondylosis, no acute findings",
646
+ "medications": ["gabapentin 600mg TID", "acetaminophen 1000mg TID", "duloxetine 60mg"]
647
+ },
648
+ "ground_truth": {
649
+ "diagnosis_codes": ["M54.5"],
650
+ "procedure_codes": ["99214"],
651
+ "decision": "reject",
652
+ "risk_flags": ["excessive_treatment", "guideline_violation", "medically_unnecessary", "patient_safety_risk"]
653
+ }
654
+ },
655
+ {
656
+ "id": "hard_027",
657
+ "difficulty": "hard",
658
+ "input": {
659
+ "clinical_note": "Multispecialty group practice has 3 providers see the same patient on the same day for the same condition and each bills a separate E&M code. Patient with diabetes sees: endocrinologist (99215), diabetic educator (99214), and nutritionist with physician supervision (99213). While each provides a different service, only one E&M is billable per provider group per day.",
660
+ "symptoms": ["uncontrolled type 2 diabetes"],
661
+ "treatments": ["medication management", "diabetic education", "nutrition counseling"],
662
+ "insurance_type": "Medicare",
663
+ "prior_auth_required": false,
664
+ "treatment_cost": "medium",
665
+ "patient_age": 58,
666
+ "patient_sex": "M",
667
+ "provider_specialty": "Endocrinology",
668
+ "visit_type": "outpatient",
669
+ "comorbidities": ["type 2 diabetes", "obesity", "hypertension"],
670
+ "lab_results": "A1C: 10.2%, FBS: 220, Cr: 1.1",
671
+ "medications": ["metformin 1000mg BID", "glimepiride 4mg daily", "lisinopril 40mg"]
672
+ },
673
+ "ground_truth": {
674
+ "diagnosis_codes": ["E11.65"],
675
+ "procedure_codes": ["99215"],
676
+ "decision": "reject",
677
+ "risk_flags": ["duplicate_billing", "billing_fraud", "unbundling_violation"]
678
+ }
679
+ },
680
+ {
681
+ "id": "hard_028",
682
+ "difficulty": "hard",
683
+ "input": {
684
+ "clinical_note": "45-year-old female with BRCA1 mutation, strong family history (mother and sister with breast cancer). Bilateral prophylactic mastectomy with immediate reconstruction requested. Patient has no current malignancy. MRI and mammogram are negative. Genetic counseling completed. Risk reduction surgery is guideline-concordant for BRCA1 carriers.",
685
+ "symptoms": [],
686
+ "treatments": ["bilateral prophylactic mastectomy", "immediate reconstruction"],
687
+ "insurance_type": "Private",
688
+ "prior_auth_required": true,
689
+ "treatment_cost": "high",
690
+ "patient_age": 45,
691
+ "patient_sex": "F",
692
+ "provider_specialty": "General Surgery",
693
+ "visit_type": "outpatient",
694
+ "comorbidities": ["BRCA1 positive"],
695
+ "lab_results": "BRCA1: pathogenic variant detected, Mammogram: BIRADS 1, MRI: negative",
696
+ "medications": []
697
+ },
698
+ "ground_truth": {
699
+ "diagnosis_codes": ["Z15.01", "Z80.3"],
700
+ "procedure_codes": ["19303"],
701
+ "decision": "approve",
702
+ "risk_flags": ["prophylactic_surgery", "high_cost_treatment", "prior_auth_needed"]
703
+ }
704
+ },
705
+ {
706
+ "id": "hard_029",
707
+ "difficulty": "hard",
708
+ "input": {
709
+ "clinical_note": "Provider submits claim for robotic-assisted laparoscopic hysterectomy with add-on code for robotic surgical system fee ($3,500). Patient had a straightforward total laparoscopic hysterectomy for menorrhagia with normal-sized uterus. No adhesions, no endometriosis. Operative time 65 minutes. The robotic approach was not medically necessary — standard laparoscopic approach would have been equivalent. Provider routinely uses robot for all cases.",
710
+ "symptoms": ["menorrhagia", "anemia"],
711
+ "treatments": ["robotic-assisted laparoscopic hysterectomy"],
712
+ "insurance_type": "Private",
713
+ "prior_auth_required": false,
714
+ "treatment_cost": "high",
715
+ "patient_age": 47,
716
+ "patient_sex": "F",
717
+ "provider_specialty": "Gynecology",
718
+ "visit_type": "inpatient",
719
+ "comorbidities": ["iron deficiency anemia"],
720
+ "lab_results": "Hgb: 9.8, US: normal sized uterus, no fibroids, no masses",
721
+ "medications": ["ibuprofen 600mg TID", "ferrous sulfate 325mg daily"]
722
+ },
723
+ "ground_truth": {
724
+ "diagnosis_codes": ["N92.0", "D50.0"],
725
+ "procedure_codes": ["58570"],
726
+ "decision": "review",
727
+ "risk_flags": ["medically_unnecessary", "upcoding_risk", "high_cost_treatment"]
728
+ }
729
+ },
730
+ {
731
+ "id": "hard_030",
732
+ "difficulty": "hard",
733
+ "input": {
734
+ "clinical_note": "Complex case: 65-year-old male with simultaneous acute STEMI, COVID-19 pneumonia, and acute kidney injury. Troponin 85, ST elevation in II, III, aVF. COVID PCR positive, bilateral infiltrates on CXR, requiring high-flow nasal cannula. Creatinine 3.8 from baseline 1.0. Cardiac cath reveals 100% RCA occlusion — PCI performed emergently. Remdesivir held due to AKI. Nephrology, cardiology, and pulmonology co-managing.",
735
+ "symptoms": ["chest pain", "dyspnea", "cough", "fever", "oliguria", "hypotension"],
736
+ "treatments": ["emergent PCI with DES to RCA", "high-flow O2", "dexamethasone", "fluid management", "vasopressors"],
737
+ "insurance_type": "Medicare",
738
+ "prior_auth_required": false,
739
+ "treatment_cost": "high",
740
+ "patient_age": 65,
741
+ "patient_sex": "M",
742
+ "provider_specialty": "Critical Care",
743
+ "visit_type": "inpatient",
744
+ "comorbidities": ["hypertension", "type 2 diabetes", "obesity"],
745
+ "lab_results": "Troponin: 85, ECG: STE II/III/aVF, COVID PCR: positive, CXR: bilateral infiltrates, Cr: 3.8, BUN: 55, K: 5.6, SpO2: 88% on HFNC",
746
+ "medications": ["heparin drip", "aspirin 325mg", "ticagrelor 180mg load", "dexamethasone 6mg IV", "norepinephrine"]
747
+ },
748
+ "ground_truth": {
749
+ "diagnosis_codes": ["I21.11", "U07.1", "N17.9"],
750
+ "procedure_codes": ["92928", "93458", "99223"],
751
+ "decision": "approve",
752
+ "risk_flags": ["multiple_diagnoses", "high_cost_treatment", "complex_case"]
753
+ }
754
+ }
755
+ ]
756
+ }
tasks/medium.json ADDED
@@ -0,0 +1,756 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "difficulty": "medium",
3
+ "description": "Cases with multiple symptoms, comorbidities, partial ambiguity in coding, and insurance-specific considerations.",
4
+ "cases": [
5
+ {
6
+ "id": "med_001",
7
+ "difficulty": "medium",
8
+ "input": {
9
+ "clinical_note": "68-year-old male with COPD exacerbation and concurrent pneumonia. Presents with increased dyspnea, productive cough with purulent sputum, and fever 101.2F. Chest X-ray shows right lower lobe infiltrate. Started on levofloxacin and prednisone burst. Nebulizer treatments administered. Oxygen saturation 91% on room air.",
10
+ "symptoms": ["dyspnea", "productive cough", "purulent sputum", "fever", "wheezing"],
11
+ "treatments": ["levofloxacin", "prednisone", "nebulizer treatments", "supplemental oxygen"],
12
+ "insurance_type": "Medicare",
13
+ "prior_auth_required": false,
14
+ "treatment_cost": "medium",
15
+ "patient_age": 68,
16
+ "patient_sex": "M",
17
+ "provider_specialty": "Pulmonology",
18
+ "visit_type": "emergency",
19
+ "comorbidities": ["COPD", "hypertension", "former smoker"],
20
+ "lab_results": "WBC: 14,200/uL, CXR: RLL infiltrate, SpO2: 91% RA, Procalcitonin: 0.8 ng/mL",
21
+ "medications": ["albuterol nebulizer", "levofloxacin 750mg", "prednisone 40mg", "tiotropium"]
22
+ },
23
+ "ground_truth": {
24
+ "diagnosis_codes": ["J44.1", "J18.9"],
25
+ "procedure_codes": ["99285"],
26
+ "decision": "approve",
27
+ "risk_flags": ["multiple_diagnoses"]
28
+ }
29
+ },
30
+ {
31
+ "id": "med_002",
32
+ "difficulty": "medium",
33
+ "input": {
34
+ "clinical_note": "55-year-old female with type 2 diabetes and diabetic neuropathy. Presents for management. A1C 8.4% despite metformin 2000mg daily. Complains of burning and tingling in feet bilaterally. Started on gabapentin for neuropathy. Insulin glargine added for glucose control.",
35
+ "symptoms": ["burning feet", "tingling in feet", "numbness", "polyuria", "polydipsia"],
36
+ "treatments": ["gabapentin", "insulin glargine", "metformin continuation"],
37
+ "insurance_type": "Medicare",
38
+ "prior_auth_required": false,
39
+ "treatment_cost": "medium",
40
+ "patient_age": 55,
41
+ "patient_sex": "F",
42
+ "provider_specialty": "Endocrinology",
43
+ "visit_type": "outpatient",
44
+ "comorbidities": ["type 2 diabetes", "hypertension", "obesity"],
45
+ "lab_results": "HbA1c: 8.4%, Fasting glucose: 188 mg/dL, eGFR: 72 mL/min",
46
+ "medications": ["metformin 1000mg BID", "gabapentin 300mg TID", "insulin glargine 20u QHS", "lisinopril 20mg"]
47
+ },
48
+ "ground_truth": {
49
+ "diagnosis_codes": ["E11.40", "E11.65"],
50
+ "procedure_codes": ["99215"],
51
+ "decision": "approve",
52
+ "risk_flags": ["multiple_diagnoses"]
53
+ }
54
+ },
55
+ {
56
+ "id": "med_003",
57
+ "difficulty": "medium",
58
+ "input": {
59
+ "clinical_note": "45-year-old male presents to ED with chest pain. Substernal, pressure-like, radiating to left arm. Troponin negative x2. ECG shows no ST changes. Chest pain resolved with nitroglycerin. Diagnosis: unstable angina. Cardiology consult obtained. Admitted for observation and stress testing.",
60
+ "symptoms": ["chest pain", "left arm pain", "diaphoresis", "shortness of breath"],
61
+ "treatments": ["nitroglycerin", "aspirin", "cardiology consult", "stress test ordered"],
62
+ "insurance_type": "Private",
63
+ "prior_auth_required": true,
64
+ "treatment_cost": "high",
65
+ "patient_age": 45,
66
+ "patient_sex": "M",
67
+ "provider_specialty": "Emergency Medicine",
68
+ "visit_type": "emergency",
69
+ "comorbidities": ["hyperlipidemia", "family history of CAD", "smoker"],
70
+ "lab_results": "Troponin I: <0.04 ng/mL x2, ECG: NSR no ST changes, BMP: normal",
71
+ "medications": ["aspirin 325mg", "nitroglycerin SL", "atorvastatin 40mg", "metoprolol 25mg"]
72
+ },
73
+ "ground_truth": {
74
+ "diagnosis_codes": ["I20.0"],
75
+ "procedure_codes": ["99285"],
76
+ "decision": "approve",
77
+ "risk_flags": ["high_cost_treatment"]
78
+ }
79
+ },
80
+ {
81
+ "id": "med_004",
82
+ "difficulty": "medium",
83
+ "input": {
84
+ "clinical_note": "72-year-old female with osteoarthritis of both knees. Failed conservative management with NSAIDs and physical therapy over 6 months. Bilateral knee X-rays show moderate joint space narrowing. Requests corticosteroid injection. Right knee injection performed under fluoroscopic guidance.",
85
+ "symptoms": ["bilateral knee pain", "stiffness", "difficulty walking", "crepitus"],
86
+ "treatments": ["corticosteroid injection right knee", "continued physical therapy"],
87
+ "insurance_type": "Medicare",
88
+ "prior_auth_required": false,
89
+ "treatment_cost": "medium",
90
+ "patient_age": 72,
91
+ "patient_sex": "F",
92
+ "provider_specialty": "Orthopedics",
93
+ "visit_type": "outpatient",
94
+ "comorbidities": ["osteoarthritis", "hypertension", "osteoporosis"],
95
+ "lab_results": "X-ray bilateral knees: Moderate joint space narrowing, osteophyte formation",
96
+ "medications": ["acetaminophen 1000mg TID", "meloxicam 15mg daily"]
97
+ },
98
+ "ground_truth": {
99
+ "diagnosis_codes": ["M17.0"],
100
+ "procedure_codes": ["20611", "77002"],
101
+ "decision": "approve",
102
+ "risk_flags": []
103
+ }
104
+ },
105
+ {
106
+ "id": "med_005",
107
+ "difficulty": "medium",
108
+ "input": {
109
+ "clinical_note": "38-year-old female presents with migraine with aura. Reports 3-4 migraines per month lasting 12-24 hours. Visual aura precedes headache. Failed OTC medications. Started on sumatriptan for acute attacks and topiramate for prevention.",
110
+ "symptoms": ["severe unilateral headache", "visual aura", "nausea", "photophobia", "phonophobia"],
111
+ "treatments": ["sumatriptan", "topiramate"],
112
+ "insurance_type": "Private",
113
+ "prior_auth_required": false,
114
+ "treatment_cost": "medium",
115
+ "patient_age": 38,
116
+ "patient_sex": "F",
117
+ "provider_specialty": "Neurology",
118
+ "visit_type": "outpatient",
119
+ "comorbidities": [],
120
+ "lab_results": null,
121
+ "medications": ["sumatriptan 50mg PRN", "topiramate 25mg BID"]
122
+ },
123
+ "ground_truth": {
124
+ "diagnosis_codes": ["G43.109"],
125
+ "procedure_codes": ["99214"],
126
+ "decision": "approve",
127
+ "risk_flags": []
128
+ }
129
+ },
130
+ {
131
+ "id": "med_006",
132
+ "difficulty": "medium",
133
+ "input": {
134
+ "clinical_note": "60-year-old male with chronic kidney disease stage 3b and uncontrolled hypertension. BP 168/98 despite amlodipine 10mg. eGFR 38 mL/min. Added losartan with close monitoring of potassium and creatinine. Nephrology referral placed.",
135
+ "symptoms": ["headache", "fatigue", "mild peripheral edema"],
136
+ "treatments": ["losartan added", "amlodipine continuation", "nephrology referral"],
137
+ "insurance_type": "Medicare",
138
+ "prior_auth_required": false,
139
+ "treatment_cost": "medium",
140
+ "patient_age": 60,
141
+ "patient_sex": "M",
142
+ "provider_specialty": "Internal Medicine",
143
+ "visit_type": "outpatient",
144
+ "comorbidities": ["CKD stage 3b", "hypertension", "type 2 diabetes"],
145
+ "lab_results": "eGFR: 38 mL/min, Cr: 1.8 mg/dL, K: 4.6 mEq/L, BP: 168/98",
146
+ "medications": ["amlodipine 10mg daily", "losartan 50mg daily", "metformin 500mg BID"]
147
+ },
148
+ "ground_truth": {
149
+ "diagnosis_codes": ["N18.3", "I10"],
150
+ "procedure_codes": ["99215"],
151
+ "decision": "approve",
152
+ "risk_flags": ["multiple_diagnoses"]
153
+ }
154
+ },
155
+ {
156
+ "id": "med_007",
157
+ "difficulty": "medium",
158
+ "input": {
159
+ "clinical_note": "8-year-old with acute asthma exacerbation. Wheezing, tachypnea, accessory muscle use. Peak flow 60% of predicted. Given 3 rounds of albuterol nebulizer and oral prednisone. Improved to 80% peak flow. Discharged home with action plan.",
160
+ "symptoms": ["wheezing", "shortness of breath", "cough", "chest tightness"],
161
+ "treatments": ["albuterol nebulizer x3", "prednisone oral", "asthma action plan"],
162
+ "insurance_type": "Medicaid",
163
+ "prior_auth_required": false,
164
+ "treatment_cost": "medium",
165
+ "patient_age": 8,
166
+ "patient_sex": "M",
167
+ "provider_specialty": "Emergency Medicine",
168
+ "visit_type": "emergency",
169
+ "comorbidities": ["asthma", "allergic rhinitis"],
170
+ "lab_results": "Peak flow: 60% predicted (pre), 80% predicted (post), SpO2: 94%",
171
+ "medications": ["albuterol nebulizer", "prednisone 30mg", "fluticasone MDI"]
172
+ },
173
+ "ground_truth": {
174
+ "diagnosis_codes": ["J45.31"],
175
+ "procedure_codes": ["99284"],
176
+ "decision": "approve",
177
+ "risk_flags": []
178
+ }
179
+ },
180
+ {
181
+ "id": "med_008",
182
+ "difficulty": "medium",
183
+ "input": {
184
+ "clinical_note": "50-year-old female with newly diagnosed breast mass. Palpable 2.5cm mass in right upper outer quadrant. Mammogram shows BIRADS 4. Ultrasound-guided core needle biopsy performed. Awaiting pathology results. Patient counseled about next steps.",
185
+ "symptoms": ["breast lump", "mild tenderness"],
186
+ "treatments": ["ultrasound-guided core needle biopsy"],
187
+ "insurance_type": "Private",
188
+ "prior_auth_required": true,
189
+ "treatment_cost": "high",
190
+ "patient_age": 50,
191
+ "patient_sex": "F",
192
+ "provider_specialty": "General Surgery",
193
+ "visit_type": "outpatient",
194
+ "comorbidities": ["family history of breast cancer"],
195
+ "lab_results": "Mammogram: BIRADS 4, 2.5cm mass RUQ. Ultrasound: solid hypoechoic mass",
196
+ "medications": []
197
+ },
198
+ "ground_truth": {
199
+ "diagnosis_codes": ["N63.10"],
200
+ "procedure_codes": ["19083"],
201
+ "decision": "approve",
202
+ "risk_flags": ["high_cost_treatment"]
203
+ }
204
+ },
205
+ {
206
+ "id": "med_009",
207
+ "difficulty": "medium",
208
+ "input": {
209
+ "clinical_note": "35-year-old male with generalized anxiety disorder and panic attacks. PHQ-9: 6, GAD-7: 14. Reports 2-3 panic attacks per week. Currently on escitalopram 10mg. Dose increased to 20mg. CBT referral reinforced. Low-dose clonazepam 0.25mg PRN discussed for severe attacks.",
210
+ "symptoms": ["excessive worry", "panic attacks", "palpitations", "insomnia", "muscle tension"],
211
+ "treatments": ["escitalopram dose increase", "CBT referral", "clonazepam PRN"],
212
+ "insurance_type": "Private",
213
+ "prior_auth_required": false,
214
+ "treatment_cost": "medium",
215
+ "patient_age": 35,
216
+ "patient_sex": "M",
217
+ "provider_specialty": "Psychiatry",
218
+ "visit_type": "outpatient",
219
+ "comorbidities": [],
220
+ "lab_results": "GAD-7: 14 (moderate), PHQ-9: 6 (mild), TSH: 2.1 (normal)",
221
+ "medications": ["escitalopram 20mg daily", "clonazepam 0.25mg PRN"]
222
+ },
223
+ "ground_truth": {
224
+ "diagnosis_codes": ["F41.1", "F41.0"],
225
+ "procedure_codes": ["99214"],
226
+ "decision": "approve",
227
+ "risk_flags": ["controlled_substance"]
228
+ }
229
+ },
230
+ {
231
+ "id": "med_010",
232
+ "difficulty": "medium",
233
+ "input": {
234
+ "clinical_note": "62-year-old female with persistent atrial fibrillation. Rate controlled on metoprolol. CHADS2-VASc score 4. Started on apixaban for stroke prevention. Echocardiogram shows normal EF 60%, mild left atrial enlargement. Cardioversion discussed but deferred.",
235
+ "symptoms": ["palpitations", "occasional dizziness", "fatigue"],
236
+ "treatments": ["apixaban", "metoprolol continuation", "rate control strategy"],
237
+ "insurance_type": "Medicare",
238
+ "prior_auth_required": false,
239
+ "treatment_cost": "medium",
240
+ "patient_age": 62,
241
+ "patient_sex": "F",
242
+ "provider_specialty": "Cardiology",
243
+ "visit_type": "outpatient",
244
+ "comorbidities": ["atrial fibrillation", "hypertension", "type 2 diabetes"],
245
+ "lab_results": "Echo: EF 60%, mild LAE. ECG: AFib rate 78. CBC/CMP: normal",
246
+ "medications": ["metoprolol 50mg BID", "apixaban 5mg BID", "lisinopril 20mg"]
247
+ },
248
+ "ground_truth": {
249
+ "diagnosis_codes": ["I48.1"],
250
+ "procedure_codes": ["99215"],
251
+ "decision": "approve",
252
+ "risk_flags": []
253
+ }
254
+ },
255
+ {
256
+ "id": "med_011",
257
+ "difficulty": "medium",
258
+ "input": {
259
+ "clinical_note": "48-year-old male with gout flare and concurrent hypertension. Acute monoarticular arthritis of right first MTP joint. Joint is erythematous, swollen, exquisitely tender. Serum uric acid 9.8 mg/dL. Started colchicine and indomethacin for acute flare. Allopurinol initiation planned after flare resolves.",
260
+ "symptoms": ["severe toe pain", "joint swelling", "redness", "inability to bear weight"],
261
+ "treatments": ["colchicine", "indomethacin", "future allopurinol"],
262
+ "insurance_type": "Private",
263
+ "prior_auth_required": false,
264
+ "treatment_cost": "medium",
265
+ "patient_age": 48,
266
+ "patient_sex": "M",
267
+ "provider_specialty": "Rheumatology",
268
+ "visit_type": "outpatient",
269
+ "comorbidities": ["hypertension", "hyperlipidemia", "obesity"],
270
+ "lab_results": "Uric acid: 9.8 mg/dL, ESR: 48 mm/hr, CRP: 3.2 mg/dL",
271
+ "medications": ["colchicine 0.6mg BID", "indomethacin 50mg TID", "losartan 50mg"]
272
+ },
273
+ "ground_truth": {
274
+ "diagnosis_codes": ["M10.071", "I10"],
275
+ "procedure_codes": ["99214"],
276
+ "decision": "approve",
277
+ "risk_flags": ["multiple_diagnoses"]
278
+ }
279
+ },
280
+ {
281
+ "id": "med_012",
282
+ "difficulty": "medium",
283
+ "input": {
284
+ "clinical_note": "30-year-old female with suspected celiac disease. Chronic diarrhea, bloating, and weight loss for 6 months. Tissue transglutaminase IgA elevated at 85 U/mL. EGD with duodenal biopsy recommended to confirm diagnosis.",
285
+ "symptoms": ["chronic diarrhea", "bloating", "weight loss", "fatigue", "abdominal pain"],
286
+ "treatments": ["EGD with biopsy recommended", "dietary counseling pending"],
287
+ "insurance_type": "Private",
288
+ "prior_auth_required": true,
289
+ "treatment_cost": "medium",
290
+ "patient_age": 30,
291
+ "patient_sex": "F",
292
+ "provider_specialty": "Gastroenterology",
293
+ "visit_type": "outpatient",
294
+ "comorbidities": ["iron deficiency anemia"],
295
+ "lab_results": "tTG IgA: 85 U/mL (>20 positive), Total IgA: normal, Hgb: 10.5, Ferritin: 8",
296
+ "medications": ["ferrous sulfate 325mg daily"]
297
+ },
298
+ "ground_truth": {
299
+ "diagnosis_codes": ["K90.0"],
300
+ "procedure_codes": ["43239"],
301
+ "decision": "approve",
302
+ "risk_flags": ["high_cost_treatment"]
303
+ }
304
+ },
305
+ {
306
+ "id": "med_013",
307
+ "difficulty": "medium",
308
+ "input": {
309
+ "clinical_note": "75-year-old male with benign prostatic hyperplasia and lower urinary tract symptoms. IPSS score 22 (severe). Failed tamsulosin monotherapy. Finasteride added. PSA 2.8 ng/mL. Digital rectal exam: enlarged, smooth prostate. No nodules.",
310
+ "symptoms": ["urinary frequency", "nocturia", "weak stream", "incomplete emptying", "urgency"],
311
+ "treatments": ["finasteride added", "tamsulosin continuation"],
312
+ "insurance_type": "Medicare",
313
+ "prior_auth_required": false,
314
+ "treatment_cost": "medium",
315
+ "patient_age": 75,
316
+ "patient_sex": "M",
317
+ "provider_specialty": "Urology",
318
+ "visit_type": "outpatient",
319
+ "comorbidities": ["BPH", "hypertension"],
320
+ "lab_results": "PSA: 2.8 ng/mL, IPSS: 22, Post-void residual: 120 mL",
321
+ "medications": ["tamsulosin 0.4mg daily", "finasteride 5mg daily", "amlodipine 5mg"]
322
+ },
323
+ "ground_truth": {
324
+ "diagnosis_codes": ["N40.1"],
325
+ "procedure_codes": ["99214"],
326
+ "decision": "approve",
327
+ "risk_flags": []
328
+ }
329
+ },
330
+ {
331
+ "id": "med_014",
332
+ "difficulty": "medium",
333
+ "input": {
334
+ "clinical_note": "52-year-old female with rheumatoid arthritis flare. Bilateral hand joint swelling, morning stiffness >1 hour. Currently on methotrexate 15mg weekly. DAS28 score 4.8 (moderate-high activity). Considering addition of biologic DMARD. Labs show elevated ESR and CRP.",
335
+ "symptoms": ["bilateral hand swelling", "morning stiffness", "joint pain", "fatigue", "grip weakness"],
336
+ "treatments": ["methotrexate continuation", "biologic DMARD consideration", "prednisone bridge"],
337
+ "insurance_type": "Private",
338
+ "prior_auth_required": true,
339
+ "treatment_cost": "high",
340
+ "patient_age": 52,
341
+ "patient_sex": "F",
342
+ "provider_specialty": "Rheumatology",
343
+ "visit_type": "outpatient",
344
+ "comorbidities": ["rheumatoid arthritis"],
345
+ "lab_results": "ESR: 42, CRP: 2.8, RF: positive, Anti-CCP: positive, DAS28: 4.8",
346
+ "medications": ["methotrexate 15mg weekly", "folic acid 1mg daily", "prednisone 10mg taper"]
347
+ },
348
+ "ground_truth": {
349
+ "diagnosis_codes": ["M05.79"],
350
+ "procedure_codes": ["99215"],
351
+ "decision": "review",
352
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed"]
353
+ }
354
+ },
355
+ {
356
+ "id": "med_015",
357
+ "difficulty": "medium",
358
+ "input": {
359
+ "clinical_note": "40-year-old male with obstructive sleep apnea. AHI 28 on sleep study (moderate). Excessive daytime sleepiness, Epworth score 16. BMI 34. CPAP prescribed. Weight loss counseling provided. Follow-up in 6 weeks for CPAP compliance check.",
360
+ "symptoms": ["excessive daytime sleepiness", "loud snoring", "witnessed apneas", "morning headaches"],
361
+ "treatments": ["CPAP therapy", "weight loss counseling"],
362
+ "insurance_type": "Private",
363
+ "prior_auth_required": true,
364
+ "treatment_cost": "medium",
365
+ "patient_age": 40,
366
+ "patient_sex": "M",
367
+ "provider_specialty": "Pulmonology",
368
+ "visit_type": "outpatient",
369
+ "comorbidities": ["obesity", "hypertension"],
370
+ "lab_results": "Polysomnography: AHI 28, lowest SpO2 82%, Epworth: 16/24",
371
+ "medications": ["CPAP 10 cmH2O"]
372
+ },
373
+ "ground_truth": {
374
+ "diagnosis_codes": ["G47.33"],
375
+ "procedure_codes": ["95810"],
376
+ "decision": "approve",
377
+ "risk_flags": ["prior_auth_needed"]
378
+ }
379
+ },
380
+ {
381
+ "id": "med_016",
382
+ "difficulty": "medium",
383
+ "input": {
384
+ "clinical_note": "28-year-old female with iron deficiency anemia refractory to oral iron. Hgb 8.2 g/dL, ferritin 4 ng/mL. GI workup negative. Heavy menstrual bleeding identified as cause. IV iron infusion (ferric carboxymaltose) administered. Gynecology referral for menorrhagia management.",
385
+ "symptoms": ["fatigue", "dizziness", "pallor", "heavy menstrual bleeding", "shortness of breath on exertion"],
386
+ "treatments": ["IV ferric carboxymaltose infusion", "gynecology referral"],
387
+ "insurance_type": "Private",
388
+ "prior_auth_required": true,
389
+ "treatment_cost": "high",
390
+ "patient_age": 28,
391
+ "patient_sex": "F",
392
+ "provider_specialty": "Hematology",
393
+ "visit_type": "outpatient",
394
+ "comorbidities": ["menorrhagia"],
395
+ "lab_results": "Hgb: 8.2, Ferritin: 4, TIBC: 450, Iron sat: 6%, MCV: 68, Reticulocyte: 1.0%",
396
+ "medications": ["ferric carboxymaltose 750mg IV"]
397
+ },
398
+ "ground_truth": {
399
+ "diagnosis_codes": ["D50.0", "N92.0"],
400
+ "procedure_codes": ["96365"],
401
+ "decision": "approve",
402
+ "risk_flags": ["high_cost_treatment", "multiple_diagnoses"]
403
+ }
404
+ },
405
+ {
406
+ "id": "med_017",
407
+ "difficulty": "medium",
408
+ "input": {
409
+ "clinical_note": "58-year-old male with new diagnosis of atypical chest pain and abnormal stress test. Nuclear stress test shows reversible perfusion defect in LAD territory. Cardiac catheterization recommended. Patient on aspirin, statin, and beta-blocker. Pre-operative clearance obtained.",
410
+ "symptoms": ["exertional chest pain", "dyspnea on exertion", "fatigue"],
411
+ "treatments": ["cardiac catheterization recommended", "medical optimization"],
412
+ "insurance_type": "Medicare",
413
+ "prior_auth_required": true,
414
+ "treatment_cost": "high",
415
+ "patient_age": 58,
416
+ "patient_sex": "M",
417
+ "provider_specialty": "Cardiology",
418
+ "visit_type": "outpatient",
419
+ "comorbidities": ["hypertension", "hyperlipidemia", "type 2 diabetes"],
420
+ "lab_results": "Stress MPI: reversible defect LAD territory, EF 55%, ECG: nonspecific ST changes",
421
+ "medications": ["aspirin 81mg", "atorvastatin 80mg", "metoprolol 50mg BID"]
422
+ },
423
+ "ground_truth": {
424
+ "diagnosis_codes": ["I25.10"],
425
+ "procedure_codes": ["93458"],
426
+ "decision": "approve",
427
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed"]
428
+ }
429
+ },
430
+ {
431
+ "id": "med_018",
432
+ "difficulty": "medium",
433
+ "input": {
434
+ "clinical_note": "65-year-old female with new-onset seizure. Found unresponsive with tonic-clonic movements lasting 3 minutes. Post-ictal confusion. CT head negative for acute process. MRI brain ordered. Started on levetiracetam. Neurology consult obtained. EEG scheduled.",
435
+ "symptoms": ["witnessed seizure", "post-ictal confusion", "tongue bite", "urinary incontinence"],
436
+ "treatments": ["levetiracetam", "MRI brain", "EEG ordered", "neurology consult"],
437
+ "insurance_type": "Medicare",
438
+ "prior_auth_required": false,
439
+ "treatment_cost": "high",
440
+ "patient_age": 65,
441
+ "patient_sex": "F",
442
+ "provider_specialty": "Emergency Medicine",
443
+ "visit_type": "emergency",
444
+ "comorbidities": ["hypertension"],
445
+ "lab_results": "CT Head: No acute intracranial abnormality, CBC/CMP: normal, glucose: 105",
446
+ "medications": ["levetiracetam 500mg BID", "amlodipine 10mg"]
447
+ },
448
+ "ground_truth": {
449
+ "diagnosis_codes": ["R56.9"],
450
+ "procedure_codes": ["99285"],
451
+ "decision": "approve",
452
+ "risk_flags": ["high_cost_treatment"]
453
+ }
454
+ },
455
+ {
456
+ "id": "med_019",
457
+ "difficulty": "medium",
458
+ "input": {
459
+ "clinical_note": "42-year-old male with Crohn's disease flare. Abdominal pain, bloody diarrhea 6-8x/day, weight loss 8 lbs. Currently on mesalamine. CT abdomen shows thickening of terminal ileum, no abscess. Transitioning to azathioprine. Discussed biologic therapy if no improvement.",
460
+ "symptoms": ["abdominal pain", "bloody diarrhea", "weight loss", "fatigue", "low-grade fever"],
461
+ "treatments": ["azathioprine", "mesalamine continuation", "nutritional support"],
462
+ "insurance_type": "Private",
463
+ "prior_auth_required": false,
464
+ "treatment_cost": "medium",
465
+ "patient_age": 42,
466
+ "patient_sex": "M",
467
+ "provider_specialty": "Gastroenterology",
468
+ "visit_type": "outpatient",
469
+ "comorbidities": ["Crohn's disease"],
470
+ "lab_results": "CRP: 4.5, ESR: 38, Albumin: 3.0, Hgb: 11.2, Fecal calprotectin: 850 ug/g",
471
+ "medications": ["mesalamine 1.2g BID", "azathioprine 150mg daily"]
472
+ },
473
+ "ground_truth": {
474
+ "diagnosis_codes": ["K50.10"],
475
+ "procedure_codes": ["99215"],
476
+ "decision": "approve",
477
+ "risk_flags": []
478
+ }
479
+ },
480
+ {
481
+ "id": "med_020",
482
+ "difficulty": "medium",
483
+ "input": {
484
+ "clinical_note": "70-year-old female with hip fracture after fall at home. X-ray confirms displaced femoral neck fracture. Orthopedic surgery recommends hemiarthroplasty. Pre-operative labs and cardiac clearance obtained. Surgery scheduled for tomorrow. DVT prophylaxis initiated.",
485
+ "symptoms": ["hip pain", "inability to bear weight", "shortened externally rotated leg"],
486
+ "treatments": ["hemiarthroplasty planned", "DVT prophylaxis", "pain management"],
487
+ "insurance_type": "Medicare",
488
+ "prior_auth_required": false,
489
+ "treatment_cost": "high",
490
+ "patient_age": 70,
491
+ "patient_sex": "F",
492
+ "provider_specialty": "Orthopedics",
493
+ "visit_type": "inpatient",
494
+ "comorbidities": ["osteoporosis", "hypertension", "hypothyroidism"],
495
+ "lab_results": "X-ray: displaced femoral neck fracture, CBC: normal, BMP: normal, PT/INR: normal",
496
+ "medications": ["morphine PCA", "enoxaparin 40mg SQ", "levothyroxine 50mcg"]
497
+ },
498
+ "ground_truth": {
499
+ "diagnosis_codes": ["S72.001", "W19"],
500
+ "procedure_codes": ["27236"],
501
+ "decision": "approve",
502
+ "risk_flags": ["high_cost_treatment"]
503
+ }
504
+ },
505
+ {
506
+ "id": "med_021",
507
+ "difficulty": "medium",
508
+ "input": {
509
+ "clinical_note": "55-year-old male with newly diagnosed hepatitis C, genotype 1a. Viral load 2.1 million IU/mL. No cirrhosis on FibroScan (F1). Treatment-naive. Started on sofosbuvir/velpatasvir for 12 weeks. Baseline labs obtained. Counseled on adherence and alcohol avoidance.",
510
+ "symptoms": ["fatigue", "mild RUQ discomfort"],
511
+ "treatments": ["sofosbuvir/velpatasvir 12-week course"],
512
+ "insurance_type": "Medicaid",
513
+ "prior_auth_required": true,
514
+ "treatment_cost": "high",
515
+ "patient_age": 55,
516
+ "patient_sex": "M",
517
+ "provider_specialty": "Hepatology",
518
+ "visit_type": "outpatient",
519
+ "comorbidities": [],
520
+ "lab_results": "HCV RNA: 2,100,000 IU/mL, Genotype 1a, FibroScan: 6.2 kPa (F1), ALT: 68, AST: 52",
521
+ "medications": ["sofosbuvir/velpatasvir 400/100mg daily"]
522
+ },
523
+ "ground_truth": {
524
+ "diagnosis_codes": ["B18.2"],
525
+ "procedure_codes": ["99215"],
526
+ "decision": "approve",
527
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed"]
528
+ }
529
+ },
530
+ {
531
+ "id": "med_022",
532
+ "difficulty": "medium",
533
+ "input": {
534
+ "clinical_note": "33-year-old female G2P1 at 12 weeks gestation for first prenatal visit. Ultrasound confirms viable singleton pregnancy. Nuchal translucency normal at 1.5mm. Routine prenatal labs obtained. Started on prenatal vitamins. No high-risk features identified.",
535
+ "symptoms": ["morning nausea", "breast tenderness", "fatigue"],
536
+ "treatments": ["prenatal vitamins", "routine prenatal care"],
537
+ "insurance_type": "Private",
538
+ "prior_auth_required": false,
539
+ "treatment_cost": "medium",
540
+ "patient_age": 33,
541
+ "patient_sex": "F",
542
+ "provider_specialty": "Obstetrics",
543
+ "visit_type": "outpatient",
544
+ "comorbidities": [],
545
+ "lab_results": "US: viable singleton, NT: 1.5mm, CBC: normal, Blood type: A+, Rubella immune, HIV neg",
546
+ "medications": ["prenatal vitamins daily"]
547
+ },
548
+ "ground_truth": {
549
+ "diagnosis_codes": ["Z34.01"],
550
+ "procedure_codes": ["99214", "76801"],
551
+ "decision": "approve",
552
+ "risk_flags": []
553
+ }
554
+ },
555
+ {
556
+ "id": "med_023",
557
+ "difficulty": "medium",
558
+ "input": {
559
+ "clinical_note": "46-year-old male with newly diagnosed type 2 diabetes and hyperlipidemia. Fasting glucose 210 mg/dL, A1C 9.2%. Total cholesterol 268, LDL 178. Started on metformin, atorvastatin, and lifestyle modifications. Diabetic education referral placed. Return in 3 months.",
560
+ "symptoms": ["polyuria", "polydipsia", "blurred vision", "fatigue"],
561
+ "treatments": ["metformin", "atorvastatin", "lifestyle counseling", "diabetic education"],
562
+ "insurance_type": "Private",
563
+ "prior_auth_required": false,
564
+ "treatment_cost": "medium",
565
+ "patient_age": 46,
566
+ "patient_sex": "M",
567
+ "provider_specialty": "Internal Medicine",
568
+ "visit_type": "outpatient",
569
+ "comorbidities": ["obesity"],
570
+ "lab_results": "FBS: 210, A1C: 9.2%, TC: 268, LDL: 178, HDL: 38, TG: 260, Cr: 0.9",
571
+ "medications": ["metformin 500mg BID", "atorvastatin 40mg daily"]
572
+ },
573
+ "ground_truth": {
574
+ "diagnosis_codes": ["E11.65", "E78.5"],
575
+ "procedure_codes": ["99215"],
576
+ "decision": "approve",
577
+ "risk_flags": ["multiple_diagnoses"]
578
+ }
579
+ },
580
+ {
581
+ "id": "med_024",
582
+ "difficulty": "medium",
583
+ "input": {
584
+ "clinical_note": "60-year-old female with chronic low back pain and lumbar radiculopathy. MRI shows L4-L5 disc herniation with nerve root compression. Failed 6 weeks of conservative management including PT and NSAIDs. Epidural steroid injection recommended. Pain score 7/10.",
585
+ "symptoms": ["low back pain", "left leg pain", "numbness in left foot", "difficulty walking"],
586
+ "treatments": ["lumbar epidural steroid injection", "continued PT"],
587
+ "insurance_type": "Medicare",
588
+ "prior_auth_required": true,
589
+ "treatment_cost": "medium",
590
+ "patient_age": 60,
591
+ "patient_sex": "F",
592
+ "provider_specialty": "Pain Medicine",
593
+ "visit_type": "outpatient",
594
+ "comorbidities": ["degenerative disc disease", "hypertension"],
595
+ "lab_results": "MRI lumbar: L4-L5 disc herniation with left L5 nerve root compression",
596
+ "medications": ["gabapentin 300mg TID", "naproxen 500mg BID", "cyclobenzaprine 10mg QHS"]
597
+ },
598
+ "ground_truth": {
599
+ "diagnosis_codes": ["M51.16", "M54.31"],
600
+ "procedure_codes": ["62323"],
601
+ "decision": "approve",
602
+ "risk_flags": ["prior_auth_needed", "multiple_diagnoses"]
603
+ }
604
+ },
605
+ {
606
+ "id": "med_025",
607
+ "difficulty": "medium",
608
+ "input": {
609
+ "clinical_note": "22-year-old male with appendicitis. RLQ pain x24 hours, migrated from periumbilical area. Rebound tenderness positive. CT abdomen confirms acute appendicitis without perforation. WBC 14,000. Laparoscopic appendectomy performed without complication.",
610
+ "symptoms": ["RLQ pain", "nausea", "anorexia", "low-grade fever", "rebound tenderness"],
611
+ "treatments": ["laparoscopic appendectomy"],
612
+ "insurance_type": "Private",
613
+ "prior_auth_required": false,
614
+ "treatment_cost": "high",
615
+ "patient_age": 22,
616
+ "patient_sex": "M",
617
+ "provider_specialty": "General Surgery",
618
+ "visit_type": "emergency",
619
+ "comorbidities": [],
620
+ "lab_results": "WBC: 14,000, CT Abdomen: Acute appendicitis, no perforation, no abscess",
621
+ "medications": ["cefoxitin 2g IV", "morphine 4mg IV PRN"]
622
+ },
623
+ "ground_truth": {
624
+ "diagnosis_codes": ["K35.80"],
625
+ "procedure_codes": ["44970"],
626
+ "decision": "approve",
627
+ "risk_flags": []
628
+ }
629
+ },
630
+ {
631
+ "id": "med_026",
632
+ "difficulty": "medium",
633
+ "input": {
634
+ "clinical_note": "67-year-old female with diabetic retinopathy screening. Fundoscopic exam reveals moderate non-proliferative diabetic retinopathy bilaterally. No macular edema. OCT macula normal. A1C 7.8%. Recommended tighter glucose control and follow-up in 6 months.",
635
+ "symptoms": ["mild blurry vision"],
636
+ "treatments": ["retinal photography", "OCT", "glucose optimization counseling"],
637
+ "insurance_type": "Medicare",
638
+ "prior_auth_required": false,
639
+ "treatment_cost": "medium",
640
+ "patient_age": 67,
641
+ "patient_sex": "F",
642
+ "provider_specialty": "Ophthalmology",
643
+ "visit_type": "outpatient",
644
+ "comorbidities": ["type 2 diabetes", "hypertension"],
645
+ "lab_results": "Fundoscopy: moderate NPDR bilaterally, OCT: no DME, A1C: 7.8%",
646
+ "medications": ["metformin 1000mg BID", "glipizide 10mg BID", "lisinopril 20mg"]
647
+ },
648
+ "ground_truth": {
649
+ "diagnosis_codes": ["E11.339"],
650
+ "procedure_codes": ["92134", "92250"],
651
+ "decision": "approve",
652
+ "risk_flags": []
653
+ }
654
+ },
655
+ {
656
+ "id": "med_027",
657
+ "difficulty": "medium",
658
+ "input": {
659
+ "clinical_note": "38-year-old female with recurrent kidney stones. CT shows 7mm left ureteral stone with mild hydronephrosis. Previous stone was calcium oxalate. Managed conservatively with tamsulosin and hydration, but stone not passing after 3 weeks. Urology recommends ureteroscopy with laser lithotripsy.",
660
+ "symptoms": ["left flank pain", "hematuria", "nausea", "urinary urgency"],
661
+ "treatments": ["ureteroscopy with laser lithotripsy planned", "tamsulosin", "hydration"],
662
+ "insurance_type": "Private",
663
+ "prior_auth_required": true,
664
+ "treatment_cost": "high",
665
+ "patient_age": 38,
666
+ "patient_sex": "F",
667
+ "provider_specialty": "Urology",
668
+ "visit_type": "outpatient",
669
+ "comorbidities": ["recurrent nephrolithiasis"],
670
+ "lab_results": "CT KUB: 7mm left distal ureteral stone, mild left hydronephrosis, UA: hematuria",
671
+ "medications": ["tamsulosin 0.4mg daily", "ketorolac 10mg PRN"]
672
+ },
673
+ "ground_truth": {
674
+ "diagnosis_codes": ["N20.1", "N13.1"],
675
+ "procedure_codes": ["52356"],
676
+ "decision": "approve",
677
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed"]
678
+ }
679
+ },
680
+ {
681
+ "id": "med_028",
682
+ "difficulty": "medium",
683
+ "input": {
684
+ "clinical_note": "78-year-old male with heart failure with reduced ejection fraction (HFrEF). EF 30% on echo. NYHA class III symptoms. On lisinopril, carvedilol, furosemide, and spironolactone. Added sacubitril/valsartan to replace lisinopril. CRT-D evaluation discussed.",
685
+ "symptoms": ["dyspnea on exertion", "orthopnea", "peripheral edema", "fatigue"],
686
+ "treatments": ["sacubitril/valsartan initiation", "diuretic adjustment", "CRT-D evaluation"],
687
+ "insurance_type": "Medicare",
688
+ "prior_auth_required": true,
689
+ "treatment_cost": "high",
690
+ "patient_age": 78,
691
+ "patient_sex": "M",
692
+ "provider_specialty": "Cardiology",
693
+ "visit_type": "outpatient",
694
+ "comorbidities": ["HFrEF", "atrial fibrillation", "CKD stage 3"],
695
+ "lab_results": "Echo: EF 30%, BNP: 1250, Cr: 1.6, K: 4.8, Na: 136",
696
+ "medications": ["sacubitril/valsartan 24/26mg BID", "carvedilol 25mg BID", "furosemide 40mg BID", "spironolactone 25mg"]
697
+ },
698
+ "ground_truth": {
699
+ "diagnosis_codes": ["I50.22"],
700
+ "procedure_codes": ["99215"],
701
+ "decision": "approve",
702
+ "risk_flags": ["high_cost_treatment", "prior_auth_needed"]
703
+ }
704
+ },
705
+ {
706
+ "id": "med_029",
707
+ "difficulty": "medium",
708
+ "input": {
709
+ "clinical_note": "44-year-old female with multiple sclerosis relapse. New left-sided weakness and visual blurring over 3 days. MRI shows new enhancing lesion in right periventricular white matter. Started on IV methylprednisolone 1g x 5 days. Baseline EDSS 2.5, now 4.0.",
710
+ "symptoms": ["left arm weakness", "visual blurring", "gait unsteadiness", "fatigue"],
711
+ "treatments": ["IV methylprednisolone pulse", "physical therapy"],
712
+ "insurance_type": "Private",
713
+ "prior_auth_required": false,
714
+ "treatment_cost": "high",
715
+ "patient_age": 44,
716
+ "patient_sex": "F",
717
+ "provider_specialty": "Neurology",
718
+ "visit_type": "inpatient",
719
+ "comorbidities": ["multiple sclerosis"],
720
+ "lab_results": "MRI Brain: New enhancing lesion right periventricular WM, EDSS: 4.0",
721
+ "medications": ["methylprednisolone 1g IV daily", "dimethyl fumarate 240mg BID"]
722
+ },
723
+ "ground_truth": {
724
+ "diagnosis_codes": ["G35"],
725
+ "procedure_codes": ["99223"],
726
+ "decision": "approve",
727
+ "risk_flags": ["high_cost_treatment"]
728
+ }
729
+ },
730
+ {
731
+ "id": "med_030",
732
+ "difficulty": "medium",
733
+ "input": {
734
+ "clinical_note": "56-year-old male with suspected peripheral arterial disease. Claudication in right calf after walking 1 block. ABI right 0.65, left 0.95. Risk factor management initiated: statin, antiplatelet, smoking cessation. Vascular surgery referral for consideration of angiography.",
735
+ "symptoms": ["right calf claudication", "cold right foot", "decreased right pedal pulse"],
736
+ "treatments": ["cilostazol", "aspirin", "atorvastatin", "smoking cessation"],
737
+ "insurance_type": "Medicare",
738
+ "prior_auth_required": false,
739
+ "treatment_cost": "medium",
740
+ "patient_age": 56,
741
+ "patient_sex": "M",
742
+ "provider_specialty": "Vascular Surgery",
743
+ "visit_type": "outpatient",
744
+ "comorbidities": ["hypertension", "hyperlipidemia", "active smoker", "type 2 diabetes"],
745
+ "lab_results": "ABI: Right 0.65, Left 0.95, LDL: 145, A1C: 7.4%",
746
+ "medications": ["aspirin 81mg", "atorvastatin 80mg", "cilostazol 100mg BID", "metformin 1000mg BID"]
747
+ },
748
+ "ground_truth": {
749
+ "diagnosis_codes": ["I73.9"],
750
+ "procedure_codes": ["93922"],
751
+ "decision": "approve",
752
+ "risk_flags": ["multiple_diagnoses"]
753
+ }
754
+ }
755
+ ]
756
+ }
test_env.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Quick test script for MedCodeRL in my_env template."""
2
+ import sys
3
+ import os
4
+
5
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6
+
7
+ from server.my_env_environment import MyEnvironment
8
+ from models import MedAction
9
+
10
+ env = MyEnvironment()
11
+
12
+ # Check tasks loaded
13
+ print("Tasks loaded:")
14
+ for d in ["easy", "medium", "hard"]:
15
+ print(f" {d}: {len(env._task_cases[d])} cases")
16
+
17
+ # Test reset (easy)
18
+ obs = env.reset(task_id="easy")
19
+ print(f"\nReset OK - case: {obs.case_id}")
20
+ print(f"Clinical note: {obs.clinical_note[:80]}...")
21
+
22
+ # Test step with correct action
23
+ action = MedAction(
24
+ diagnosis_codes=["J02.9"],
25
+ procedure_codes=["99213"],
26
+ decision="approve",
27
+ confidence=0.85,
28
+ reasoning="Acute pharyngitis coded correctly with appropriate E&M level for straightforward visit.",
29
+ risk_flags=[],
30
+ )
31
+ result = env.step(action)
32
+ print(f"\nStep OK - Score: {result.reward}, Done: {result.done}")
33
+ print(f"Feedback: {result.feedback}")
34
+ print(f"State: episode={env.state.episode_id[:8]}... steps={env.state.step_count}")
35
+
36
+ # Test hard case with wrong action
37
+ obs2 = env.reset(task_id="hard")
38
+ print(f"\nHard case: {obs2.case_id}")
39
+ bad = MedAction(
40
+ diagnosis_codes=["M17.11"],
41
+ procedure_codes=["27447"],
42
+ decision="approve",
43
+ confidence=0.9,
44
+ reasoning="Patient needs knee replacement as documented by the provider notes.",
45
+ risk_flags=[],
46
+ )
47
+ r2 = env.step(bad)
48
+ print(f"Wrong action score: {r2.reward}")
49
+
50
+ # Test medium
51
+ obs3 = env.reset(task_id="medium")
52
+ print(f"\nMedium case: {obs3.case_id}")
53
+
54
+ print("\n✅ All tests passed!")
uv.lock ADDED
The diff for this file is too large to render. See raw diff