MedCalc-Bench (Inspect AI)

August 16, 2026 · View on GitHub

An Inspect AI implementation of MedCalc-Bench, a benchmark for evaluating whether large language models can perform clinical calculations from free-text patient notes.

Khandekar, Tsoukalas, Lin, et al. MedCalc-Bench: Evaluating Large Language Models for Medical Calculations. NeurIPS 2024 (Datasets & Benchmarks Track, Oral). arXiv:2406.12036 · original code

This is an independent port of the published benchmark to Inspect AI. The scoring logic mirrors the authors' reference check_correctness implementation; see Scoring for the one intentional difference. It is contributed upstream as inspect_evals #1765.

Why this matters, and for whom

Clinical calculation is the rare medical task with a verifiable right answer — a MELD score, a Wells criterion, a creatinine clearance — and it is exactly where a plausible-sounding wrong number from an LLM is dangerous. As models are pulled into clinical documentation and decision support, "does it actually compute the right value from the note?" is a capability that has to be measured before deployment, not assumed. MedCalc-Bench showed even strong models land near ~50% here (Khandekar et al., NeurIPS 2024), so the benchmark is a live signal, not a solved one.

Who needs an eval like this: model developers gating releases, AI-safety evaluators (this is built for the UK AI Safety Institute's Inspect framework, the same harness used for frontier-model capability testing), and health-AI vendors under regulatory pressure to show evidence rather than vibes. The eval itself is treated as safety-critical infrastructure: the scorer never executes model output as code (the reference implementation calls eval() — see Scoring), so a model can't manipulate its own grade. A trustworthy evaluator is a precondition for trusting anything it reports.

What it measures

Each sample gives the model a patient note and asks it to compute one specific clinical value — a lab-derived score, a physical quantity, a risk/severity score, a drug dosage, or a date (e.g. gestational age). The test set contains 1,000+ manually reviewed instances spanning 55 calculators in seven categories (lab test, physical, date, dosage, risk, severity, diagnosis).

Calculators are of two kinds:

  • Rule-based (lookup / decision tables) — scored by exact match.
  • Equation-based (formulas) — scored within a tolerance band the authors derived from the precision of the input measurements.

Usage

# Clone and install the pinned commit
git clone https://github.com/azrabano23/medcalc-bench-inspect
cd medcalc-bench-inspect
uv sync

# Run (chain-of-thought is the default, matching the paper's main setting)
uv run inspect eval src/medcalc_bench/medcalc_bench.py@medcalc_bench --model openai/gpt-4o-mini

# Direct-answer (no reasoning) variant
uv run inspect eval src/medcalc_bench/medcalc_bench.py@medcalc_bench \
    -T prompt=direct --model openai/gpt-4o-mini

# Quick smoke test on a few samples
uv run inspect eval src/medcalc_bench/medcalc_bench.py@medcalc_bench \
    --model openai/gpt-4o-mini --limit 10

Task parameters

ParameterValuesDefaultMeaning
promptzero_shot_cot, directzero_shot_cotChain-of-thought prompting (the paper's primary setting) vs. answer-only.

Dataset

Loaded from nsk7153/MedCalc-Bench-Verified, pinned to revision 591157b3343b4dda247294f9d929da4c75026fa8. This is a public, verified mirror of the NeurIPS 2024 release with the identical 14-column schema; the original ncbi-nlp/MedCalc-Bench-v1.0 is gated. The test split is used for evaluation.

The relevant columns are Patient Note, Question, Ground Truth Answer, Calculator ID, Calculator Name, Category, Output Type, Lower Limit, and Upper Limit. The limits define the acceptance band for equation-based answers.

Scoring

The model is prompted to return a JSON object ({"step_by_step_thinking": ..., "answer": ...} in CoT mode, {"answer": ...} in direct mode). The scorer extracts the answer field — robustly, falling back through embedded JSON, a loose answer: pattern, and finally the last number in the text — and applies the calculator's rule, keyed on Calculator ID exactly as in the reference:

  • Date (IDs 13, 68): exact calendar-day match.
  • Gestational-age tuple (ID 69): (weeks, days) extracted by regex and compared.
  • Integer (IDs 4, 15–18, 20–21, 25, 27–29, 32–33, 36, 43, 45, 48, 51): exact match after rounding.
  • Decimal (all others): correct iff Lower Limit ≤ answer ≤ Upper Limit.

The reported metrics are accuracy and stderr.

Intentional difference from the reference: the original code calls eval() on answer strings. This port parses numbers safely (stripping units, commas, $, and %) rather than executing model output as Python.

Validation

The scorer is validated by self-consistency against the real dataset: feeding each ground-truth answer back through its own calculator's rule must score CORRECT. This exercises every output-type path (date / tuple / integer / decimal) and confirms the calculator-ID groupings and tolerance parsing match the data. See tests/test_medcalc_scoring.py (the dataset-marked test); unit tests cover the scoring rules and answer extraction without network access.

uv run pytest                       # unit tests
uv run pytest -m dataset            # + real-data self-consistency

License

MIT (this Inspect port). The underlying MedCalc-Bench dataset and original code are released by their authors under their own terms — see the original repository.