Crucible
Measure & compare
You changed something — turned on a reranker, swapped a chat model, edited a prompt. Did it actually help, or did the golden set just wiggle? This guide runs two configs through the evaluation framework, reads the three metric families back, and compares them behind a significance test built to not lie to you.
Prerequisites
- A concept-anchored golden set with qrels — build one in Build golden sets.
- A key with
kb:readorruns:read, exported as$ELI_KEY.
1 · Pin the config you are testing
An eval config's params is the full pipeline config the runner applies — not a label. It is also the canonical hash input, so two runs with the same params are directly comparable. The empty params {} means current behavior (retrieval limit 10, no rerank, policy off), so a baseline never drifts:
Isolate one variable
{} (or your current production shape) and the candidate identical except for rerank: true. If you also bump the model and the prompt, a significant difference tells you nothing about which change caused it.2 · Run both — cheap first with component mode
If the change is retrieval-only (a reranker, graph fusion, a bigger candidate pool), run in component mode first: the runner scores recall / nDCG / MRR against the qrels without generating answers — fast and nearly free. Only when retrieval improves do you spend generation tokens on a full system-mode run to confirm the answer metrics followed. Run the golden set under each config from the evals workspace (/w/<workspace>/evals), confirming the cost estimate for system runs.
3 · Read a run's metrics
Pull the three families for one run. Retrieval and abstention numbers are deterministic; RAGAS numbers carry the judge model that produced them.
/api/v1/evals/runs/{id}/metricsBearer · kb:read or runs:readRetrieval, RAGAS, and abstention metrics for one run — overall and broken down by question facet. Deterministic metrics are exact; judge-based metrics report the judge model and prompt version they used.
4 · Compare with significance
The comparison is the point. It runs a paired bootstrap with BCa confidence intervals and a paired permutation test, both seeded and deterministic, and only calls a difference real when both gates pass: the CI excludes 0 and p < 0.05.
/api/v1/evals/runs/compareBearer · kb:read or runs:readPaired comparison of two runs over their shared golden items. Reports per-metric deltas, BCa bootstrap CIs, permutation p-values, and a two-gate significant flag. Refuses to compare runs judged by different judge models.
Query parameters
Read this example honestly: the reranker moved nDCG@10 (+0.08, CI excludes 0, p = 0.004) and truthfulness significantly, but recall and faithfulness did not budge — which is exactly what a reranker should do: it reorders the same retrieved set (so recall is flat) to put better evidence first (so nDCG rises), and better ordering let the model abstain less wrongly (truthfulness up). The test told you what changed and gave you a mechanism.
Two gates, on purpose
p < 0.05is wrong one time in twenty by construction — run enough comparisons and you will "discover" improvements that are noise. Requiring the BCa CI to exclude 0 and the permutation p < 0.05is a deliberately conservative bar that resists false positives. On a small golden set, expect many honest "not significant" results — that is the test working, not failing.5 · Decide, and lock it in
- Significant win on the metric you care about, no significant regression elsewhere → adopt the config.
- No significant difference → the change did not help on this set. Either it does not matter, or the set is too small/narrow to see it — grow the golden set before you trust a null.
- Mixed (nDCG up, faithfulness down) → the trade-off is now explicit and numeric, which is the whole point; decide with eyes open.
Whatever you adopt, the failing items are worth harvesting: promote classified failures from the run back into the golden set (see Build golden sets) so the next comparison is measured against a stricter ruler.
Where to go next