How to evaluate a decision model on your own data
Written by Jakub Rusinowski · Last updated
Public scores tell you which models are worth testing. Only your own data tells you which one to deploy. Use the community Decision Index and DecisionBench to pick two or three candidates. Then label 200 real examples from your own tickets or emails, run every candidate on the same rows, and compare them pair by pair, on accuracy, calibration, coverage at your threshold, failures and latency. One headline accuracy number hides almost everything that decides whether a model is safe to automate.
Three kinds of evidence, and how far to trust each
Every score on a decision model's page carries a label saying who measured it, because that is the first thing to know about any number:
| Evidence | Who runs it | What it is good for | What to watch |
|---|---|---|---|
| Community Decision Index | A community leaderboard, not the model's authors | Comparing many models on one fixed suite. Scores are chance-corrected: 0 is random guessing, 100 is perfect | One snapshot, one set of questions. A model can be tuned towards a public suite |
| DecisionBench | An open, reproducible harness, built by Hanno Labs, the team behind Bosun | Re-running a model yourself on frozen rows with a pinned dataset revision, and reading every task separately | Its authors also build a model it ranks. The data is open, so check the task-level results rather than taking that on trust |
| The authors' own benchmark | The model's authors, on their own suite or on a public harness | Learning what the authors optimised for | Not independently reproduced. Treat it as a claim until someone else runs it |
None of these is wrong, and none answers your question, which is how the model does on your distribution. The hub's other benchmarks table lists every author and harness score in the library with its provenance, and the same model often looks very different from one row to the next.
| Model | Suite | What was scored | Score | ECE | Who measured it | Source |
|---|---|---|---|---|---|---|
| Bosun v3.1 0.6B Hanno Labs | DecisionBench 1.0 (Hanno Labs) | Applied suite (22,700 rows) +1 more row on the model page | 83.2% | 0.0588 | Benchmark built by the same team that built this model | Source ↗ |
| THX-01 322M HAL-X AI | Support-ticket classification, 15 categories (HAL-X AI internal set) | 2,843 tickets in Azerbaijani, Russian, English and Turkish — average of 4 test sets | 98.4% | 0.003 | Authors' own internal benchmark — not independently reproduced | Source ↗ |
| THX-01 322M HAL-X AI | Held-out multilingual documents (HAL-X AI internal set) | Number lookup (exact value) +2 more rows on the model page | 93.4% | — | Authors' own internal benchmark — not independently reproduced | Source ↗ |
| THX-01 322M HAL-X AI | 39-task multilingual decision suite (HAL-X AI) | Mean over 39 held-out tasks | 84.2% | 0.066 | Authors' own internal benchmark — not independently reproduced | Source ↗ |
| OpenDecider-nano Manjunath Janardhan | typed-decisions (Antz AI harness, 2,000 decisions) | Test split | 79.6% | — | Run by the authors on a public third-party harness | Source ↗ |
| OpenDecider-nano Manjunath Janardhan | 200 general decisions (BANKING77, BoolQ, Yelp, ChaosNLI) | 200 decisions | 68% | 0.092 | Run by the authors on a public third-party harness | Source ↗ |
| Bosun v3.1 1.7B Hanno Labs | DecisionBench 1.0 (Hanno Labs) | Applied suite (22,700 rows) +1 more row on the model page | 87.29% | 0.0397 | Benchmark built by the same team that built this model | Source ↗ |
| OpenDecider-small MLX 4-bit Manjunath Janardhan | typed-decisions (Antz AI harness, 2,000 decisions) | Test split | 65.1% | — | Run by the authors on a public third-party harness | Source ↗ |
| OpenDecider-small MLX 4-bit Manjunath Janardhan | 200 general decisions (BANKING77, BoolQ, Yelp, ChaosNLI) | 200 decisions | 74.5% | — | Run by the authors on a public third-party harness | Source ↗ |
| d1-omni-600M Liquid AI | Decision Index 0.2.1 suite, scored by Liquid AI with the official scorer | Balanced skill · 0.2.1 | 15.95 | — | Run by the authors on a public third-party harness | Source ↗ |
| d1-omni-600M Liquid AI | Public benchmarks read as decisions (Liquid AI’s own run) | Mean of 7 (SQuAD 2.0, Civil Comments, MASSIVE, PubMedQA, BoolQ, XNLI, PAWS-X) | 78.4% | — | Authors' own internal benchmark — not independently reproduced | Source ↗ |
| OpenDecider-small Manjunath Janardhan | typed-decisions (Antz AI harness, 2,000 decisions) | Test split | 67.2% | — | Run by the authors on a public third-party harness | Source ↗ |
| OpenDecider-small Manjunath Janardhan | 200 general decisions (BANKING77, BoolQ, Yelp, ChaosNLI) | 200 decisions | 73.5% | 0.087 | Run by the authors on a public third-party harness | Source ↗ |
| d1-3B Liquid AI | Decision Index 0.2.1 suite, scored by Liquid AI with the official scorer | Balanced skill · 0.2.1 | 48.57 | — | Run by the authors on a public third-party harness | Source ↗ |
| d1-3B Liquid AI | Public benchmarks read as decisions (Liquid AI’s own run) | Mean of 7 (SQuAD 2.0, Civil Comments, MASSIVE, PubMedQA, BoolQ, XNLI, PAWS-X) +1 more row on the model page | 82.9% | — | Authors' own internal benchmark — not independently reproduced | Source ↗ |
| d1-3B Liquid AI | 11 public image benchmarks read as decisions (Liquid AI’s own run) | Mean, at most 1,000 rows each | 74.1% | — | Authors' own internal benchmark — not independently reproduced | Source ↗ |
Benchmark built by the same team that built this model · Run by the authors on a public third-party harness · Authors' own internal benchmark — not independently reproduced. Every row is a different suite; the Decision Index column above is the only shared yardstick.
Read it as a shortlist, not a ranking: a model that scores well on more than one kind of evidence is worth your 200 labelled rows.
Running DecisionBench yourself
DecisionBench evaluates the model's own probability for each candidate answer. It does not parse generated text, so it measures exactly what a decision model returns in production. Its README describes the shortest path: install the package, download the model at a fixed commit, and run a smoke test on the pinned suite.
pip install git+https://github.com/Hanno-Labs/decision-bench.git
# Download an exact model revision, never a moving branch
hf download Hanno-Labs/bosun-v3.1-0.6b \
--revision aaa9dd06d4d6501b33df61942472fed9284bc5e6 \
--local-dir models/bosun-v3.1-0.6b
# Smoke test first; drop --smoke for the full run
decision-bench run-hf task_specs/decisionbench-dev.toml \
models/bosun-v3.1-0.6b results/bosun-v3.1-0.6b --smokeCheck the project's list of supported adapters before you run anything else: if your model is listed, use its runner. Every run writes raw.jsonl, summary.json and manifest.json to its output folder, and the manifest hashes them, so a result can be checked against its inputs later.
Four rules keep your numbers comparable with everyone else's:
- Pin both revisions. The model at a commit hash, and the dataset at the revision the project publishes for result submissions. A moving branch gives you a number nobody can reproduce.
- Report the applied suite and the reasoning track separately. DecisionBench 1.0 has a 22,700-row applied suite and a separate 1,200-row reasoning track, and its authors deliberately do not blend them into one headline. Neither should you.
- Report the whole picture: accuracy, coverage, ECE, NLL, failures (rows the model could not answer or the adapter rejected) and latency, each per view.
- Keep the raw rows. The aggregate tells you which model is ahead. The rows tell you where it fails, which is what you need before you trust it with your traffic.
If you want your result on the public board, the project's guide to submitting results walks through staging a record against the pinned dataset revision and opening a pull request.
Reading someone else's DecisionBench result
Before you lean on a published DecisionBench score, including the ones on our model pages, ask three questions.
Were the task families in the model's training data? Hanno Labs is unusually clear about this for Bosun: its applied-suite rows are held out, but they come from broad task families that Bosun was trained on, and its authors say that does not establish performance on task families it has never seen. They also report that on the separate reasoning track, Jev leads both Bosun models. That is the pattern to expect from any model that tops a benchmark built by its own team: strong in-distribution, less proven outside it. Your tickets are, by definition, outside it.
What kind of model is it, and what kind is it being compared with? DecisionBench records every result with a declared type: a decision model answers all three primitives through a native decision output; a language model produces text that an adapter parses into an answer; a classifier is a fixed-purpose scorer applied to the benchmark through an adapter. Reviewers check the declared type against how the model is actually served. A native decision model and a prompted chat model can sit on the same board, but their probabilities do not come from the same place, so compare calibration within a type before you compare across types.
Which revision was scored? A result names its model commit and its dataset revision. If the model you would download today is a newer commit, the score describes an older model. Re-run it, or treat the number as history.
Build a 200-row eval from your own data
A public suite cannot know your labels, your edge cases or your language. Two hundred real rows can. The method below takes an afternoon.
1. Sample from production, not from memory. Export the last month or two of tickets, emails or forms. Pick rows at random within each label, so a rare label still gets enough examples, then add every hard case you already know about: refunds disguised as complaints, two requests in one message, other languages.
2. Label them twice. Two people label independently. Discard the rows they disagree on, or better, write down why: a row humans cannot agree on is a row no model should be automated on.
3. Write the question exactly as production will. The same instructions, the same option descriptions, the same order. A reworded question is a different test.
4. Split once, then freeze. Use 100 rows to choose thresholds and fit any calibration, and keep 100 untouched for the final comparison. Never tune on the rows you report.
5. Store it as JSON Lines, one decision per line, in the same format the confidence guide's script reads, so one script computes accuracy, ECE and the risk–coverage curve for every model.
Keep the file local. Real tickets carry names, addresses and account numbers, and a local decision model never needs them to leave your machine.
Compare two models pair by pair
With 200 rows, a two-point accuracy gap is usually noise. The honest comparison runs both models on the same rows and looks only at the rows where they disagree:
# paired.py: rows where exactly one of two models was right
# a_ok, b_ok: lists of booleans, one per row, same order
from scipy.stats import binomtest
def paired(a_ok, b_ok):
a_only = sum(a and not b for a, b in zip(a_ok, b_ok))
b_only = sum(b and not a for a, b in zip(a_ok, b_ok))
n = a_only + b_only
p = binomtest(a_only, n, 0.5).pvalue if n else 1.0
print(f"A right, B wrong: {a_only} B right, A wrong: {b_only} p = {p:.3f}")This is the exact form of McNemar's test. Rows both models get right, or both get wrong, say nothing about which is better, so the test ignores them. If the split between the two disagreement counts could easily be chance, treat the models as tied and choose on the other columns: latency, size, licence, calibration. A large p-value with only a handful of disagreements means you need more rows, not a coin toss.
Why one accuracy number is not enough
Two models with the same accuracy can be very different products:
| Check | Why it matters |
|---|---|
| Accuracy per label | 90% overall can hide 40% on the rare label that costs you most |
| Calibration (ECE, NLL) | Decides whether you can set a threshold at all; see accuracy is not calibration |
| Coverage at your threshold | The share of traffic you can actually automate at an error rate you accept |
| Failures | Unsupported question types, inputs over the limit, malformed responses. A model that refuses 3% of rows is 3% less useful, whatever its accuracy |
| Latency on your hardware | Published figures are the vendor's device and setup. Time it on yours |
| Per question type | choice, noul and score behave differently on the same model; score them apart |
Write the six down for each candidate on your frozen 100 rows, and the decision usually makes itself. If it does not, the cheaper or smaller model wins the tie.
| Model | Runs with | Published size | Decision Index 0.2.1 |
|---|---|---|---|
| Bosun v3.1 0.6B Hanno Labs | jev-compatible-server :8000 | 400 MB (Q4_K_M) | 14.32 |
| THX-01 322M HAL-X AI | thx01.server :8095 | 640 MB (F16) | — |
| OpenDecider-nano Manjunath Janardhan | opendecider serve :8000 | 790 MB (BF16) | — |
| Tev1 0.8B Together AI | ollama pull tev1:0.8b | 812 MB (Ollama build) | 12.85 |
| Bosun v3.1 1.7B Hanno Labs | jev-compatible-server :8000 | 1.26 GB (Q5_K_M) | 20.1 |
| Decider 0.8B preview Mapika | decider.serve | 1.4 GB (BF16) | — |
| OpenDecider-small MLX 4-bit Manjunath Janardhan | opendecider (MLX) | 2.26 GB (MLX 4-bit) | — |
| d1-omni-600M Liquid AI | Transformers (trust_remote_code) | 2.35 GB (F32) | — |
| OpenDecider-small Manjunath Janardhan | opendecider serve :8000 | 2.5 GB (Q4_K_M) | — |
| Decider 2B Mapika | decider.serve | 3.8 GB (BF16) | 28.97 |
| Tev1 4B Together AI | ollama pull tev1 | 4.5 GB (Ollama build) | 29.24 |
| d1-3B Liquid AI | Transformers (trust_remote_code) | 6.25 GB (BF16) | — |
| Winnow E4B EldanRing | winnow-inference :8091 | 8.01 GB (Q8_0) | 39.89 |
| Decider 4B Mapika | decider.serve | 8.4 GB (BF16) | 40.7 |
| JevK5 4B alibiserikbay | jevk5-serve :8090 | 9 GB (BF16) | 38.81 |
| Nimble 9B Bespoke Labs | ollama pull nimble | 9.5 GB (Ollama build) | 39.57 |
| Clef-Flash 9B Cloudflare | ollama pull clef-flash | 10.93 GB (Ollama build) | — |
| Winnow 12B EldanRing | winnow-inference :8091 | 12.67 GB (Q8_0) | 50.02 |
| Clef 27B Cloudflare | ollama pull clef | 17.99 GB (Ollama build) | — |
| Decider 35B-A3B (NVFP4) Mapika | decider.serve | 19.6 GB (NVFP4) | 47.11 |
| Rune 26B-A4B v3 Surogate | surogate serve | 51.6 GB (BF16) | 57.44 |
| AutoJev 27B denis-pplx | autojev-serve :8000 | 52.6 GB (BF16 (49 GiB)) | 56.4 |
| Intern-Decision 4B InternLM | reference Python code | — | 37.81 |
| Laya ConvAI Innovations | laya-serve / Python Router | — | 6.04 |
Fit on your hardware: set your GPU or unified memory in the hardware analyzer and this page shows whether each model fits it. Check your hardware
Sources, checked 2026-10-14: DecisionBench README: install, pinned revision, run-hf · DecisionBench: running the evaluation, run artifacts · DecisionBench: submitting results, pinned dataset revision · Hanno Labs: DecisionBench 1.0 and Bosun v3.1 (applied suite, reasoning track) · DecisionBench: declared model types · Community Decision Index leaderboard · statsmodels: McNemar test · SciPy: binomtest.
Frequently asked questions
Is 200 rows really enough?
Enough to rank two or three candidates and spot a bad one, and to see calibration in broad bins. Not enough to certify a rare label: if one label is a small share of your traffic, add rows for it until it has at least 30 or 40 examples on its own.
Can I trust a model's own benchmark?
As a statement of what its authors optimised for, yes. As evidence of how it will do on your data, no. Look for the same model on the community Index or a reproducible harness run by someone else, then test it on your own rows.
Should I use DecisionBench or the Decision Index?
Both, for different jobs. The Index is a quick, independent read across many models; DecisionBench lets you re-run a model yourself, task by task, on pinned data. Neither replaces your own 200 rows.
Keep going
- Decision models (Jev-style System One): run them locally
- Run Jev-style decision models locally with Ollama (Nimble, Tev1)
- Open Jev reproductions beyond Ollama: Winnow, Decider, JevK5, AutoJev, Laya
- Decision-model confidence, thresholds and calibration — use the probabilities safely
- Decision models on images: classify receipts, screenshots and forms locally with Clef
- Decision models on phones, Jetson and laptops
- Ollama /v1/systemone errors and fixes
- Ollama /v1/systemone image errors
- Decision request builder