What each number means, how scoring works, and how to use the results to decide what to deploy.
Every evaluation run reports four numbers per benchmark file.
The share of benchmark samples the model got right. What counts as "right" depends on the task_type in config.yaml. Different tasks need different scoring logic - a classification task is scored differently than a summarization task.
How closely the model's confidence tracks its actual accuracy. If a model is 90% confident across a bucket of predictions, ECE measures how close the model's actual accuracy on that bucket is to 90%.
Lower is better. ECE under 0.10 means the model's confidence is trustworthy. ECE over 0.20 means the model is confidently wrong often enough to matter - usually worse than being uncertain.
Median and 99th-percentile per-sample inference time. P50 tells you what most requests will experience. P99 tells you what your slowest 1% will experience. The gap between them matters as much as either number alone - a large gap means unpredictable tail latency under load.
XReduce picks a scoring method per benchmark based on the task_type in your config.yaml. Each method answers the question "did the model get it right?" differently:
| Task type | Scoring method | Good for |
|---|---|---|
classify | Exact match | Classification, intent detection, categorization. |
tool_calling | JSON equivalence | Function calling with order-insensitive parameter matching. |
qa | Contains match, or LLM-as-judge | Question answering, factual lookup. |
completion | Contains match | Short-form text completion. |
summarization | Word overlap (over 50%) | Summary generation. |
translation | Exact match | Language translation. |
If you need scoring that doesn't fit a built-in task type - say, semantic equivalence on paraphrased answers, or domain-specific output validation - that's where LLM-as-judge comes in.
Some outputs can't be scored by string comparison. A model asked "what's the capital of France" might answer "Paris," "It's Paris," or "The capital is Paris" - all correct, none exactly matching a single reference. For these cases, XReduce runs a separate judge model that reads the question, the model's answer, and the reference answer, and decides whether they mean the same thing.
The judge is openai/gpt-oss-120b, an open-weight large model run via Groq. It's configured via the judge_model field in config.yaml, and produces binary pass/fail scores for semantic correctness.
LLM-as-judge runs asynchronously alongside the main evaluation. Scores are written to the judge_results table and surface in the XReduce dashboard next to the primary accuracy number.
The current LLM-as-judge surface is narrow - one judge model, one scoring mode, task-type-automatic selection. We're expanding it in the next release cycles:
{question} and {answer} template slots. Useful for domain-specific correctness - a legal correctness judge reads differently than a customer-support correctness judge.None of this changes the shape of the evaluation run - you'll still use xreduce evaluate. What changes is how much of the scoring behavior you control.
A few practical points when looking at a result block:
--baseline. Pass --baseline <run-uuid> to see your current run as a delta from an earlier one. Catches regressions that absolute numbers hide.--show-outputs when debugging. Aggregate accuracy tells you whether the model is working. Per-sample outputs tell you how it's failing - which categories of inputs it gets wrong, where the mistakes cluster. Usually more actionable than the headline number.