Pairwise comparisons are half the story. For judges calibrated against your
own grades, corrected pass rates, CI deploy gates, and the quality-gated
canary, see Judges & calibration; the Evals page’s
Judges and Live switches tabs.
Requirements
- Request logging enabled, with at least 5 distinct prompts captured (comparisons sample from your logs).
- Wallet balance: eval generations and judge calls bill as normal usage, disclosed before you start a run.
Running a comparison
Dashboard → Evals → Comparisons → Run a comparison (owner/admin). The tab is table-first: every past comparison is a row with its result inline, and the guided flow walks you through:1
Write a rubric
Describe what “good” means for your traffic, in plain English, e.g.
“Answers must be factually correct, concise, and follow the system
prompt’s tone. Penalize hallucinated product features.”
2
Pick models
Your baseline (what you run today) and up to 3 candidates. 5–500 samples.
Optionally choose the judge (a strong instruct model is pre-selected).
3
4
Wait a few minutes
Runs process in the background; progress is visible live. Then open the
report.
How many samples?
Enough that the answer means something. A win rate is a statistic, and a small one carries a margin of error wide enough to hide the truth:
Every report shows the 95% confidence interval next to the win rate, and
marks a run inconclusive when that interval straddles 50%, because a run
that can’t tell the models apart should say so, not hand you a number that
looks like a decision.
Use 30+ to point a direction. Use 100–500 when you intend to actually switch
models on the result. The dialog shows the estimated cost in dollars before
you commit, so you can trade confidence against spend with your eyes open.
Judging modes
Direct quality (default): the judge picks whichever answer better satisfies your rubric. Use it to ask “is the cheap model good enough?” Match reference: the judge compares each answer against a stored reference and picks whichever is closer to it. The reference is the answer you already trust: the reply your current model actually gave (when sampling logged traffic), or the assistant turn in a curated dataset. Use it to ask “does this model reproduce what we already ship?”, the natural check for a cheaper model, or for a fine-tune against the model it was distilled from.How scoring works
- Fresh generations: every model answers the same sampled prompts anew; logged responses are never reused, so the comparison is same-conditions.
- Position-bias control: the judge sees each pair twice with the answers swapped. A model must win both orderings to score a win; anything inconsistent counts as a tie.
- Final answers only: reasoning traces (
<think>blocks) are stripped before judging, so thinking models are scored on what they actually answer, not their scratchpads. - Win rate = wins + half of ties, over all judged samples, reported with a 95% confidence interval, and flagged inconclusive when that interval straddles even odds.
- Cost & savings: the actual billed cost of running the same prompts on each model; savings is relative to the baseline. Judge cost is shown separately.
From the API
Comparisons run from CI too: queue one after a deploy, poll it, and gate on the result.sample_filters takes tag, segment (an auto-detected
traffic segment), model, dataset_id, or
trace_replay:
winRate, savingsPct, and avgLatencyMs per candidate;
GET /v1/evals/{id}/samples returns the individual test cases. See the
Evals API reference.
Creating a run spends your wallet, so it needs an owner/admin key. Reads
(list, get, samples) work with any workspace key.
Tool-using traffic
Agent traffic benchmarks first-class, not as an afterthought:- Logged requests keep their tool definitions, and every generated model is offered the same tools, so a candidate answering agent traffic can act, not just talk.
- A reply that acted renders canonically as
[tool call] name(args): the same notation in stored references, generated answers, and what the judge reads, so an incumbent’s tool call and a candidate’s tool call compare byte-for-byte fairly. - Two deterministic assertions gate on actions:
tool_called(value = the tool name that must be invoked) andno_tool_call. - The stored-answer baseline includes exchanges where the incumbent’s answer was a tool call, so agent steps are no longer silently excluded from bake-offs.
Whole-run replay
Against the stored-answer baseline, check Replay whole agent runs (or passsample_filters.trace_replay: true): completed runs are sampled whole, and at
every step the candidate sees exactly the history and tools your agent saw;
its chosen action is judged head-to-head against the recorded one. The report
adds a run-level number: runs the candidate drove without losing a single
step. A run is only as good as its worst action, so this can’t be rescued by
twenty good steps hiding one bad one.
One honest boundary: the candidate’s divergent actions are judged, never
followed. Replay measures action fidelity against a real trajectory, not
free-running behavior. For live whole-run quality, monitor with
trace-unit judges.
Limitations
Runs are resumable and billing is exactly-once: every generation and judge call settles under a deterministic request id, so an interrupted run resumes where it stopped without double-billing.Acting on the result
A won eval is only worth something if you can act on it. Point a model alias at the winner and your next request routes there. No redeploy, no code change:canary_percent first and move the traffic
over gradually.