Assevradocs

What it measures

Judge calibration

A judged score is not evidence until you have shown the judge agrees with humans.

Two of Assevra’s nine dimensions are scored by a model. A model’s verdict is useful only if it matches what a careful human would have said — and that is a measurable property, not an assumption.

assevra calibrate measures it.

Run it

Take a hold-out set — rows you have labeled by hand — and add a human_label to each:

{"id":"g1","dimension":"grounding","context":"Returns: 14 days.","agent_output":"14 days.","human_label":"pass"}
{"id":"g2","dimension":"grounding","context":"Returns: 14 days.","agent_output":"30 days.","human_label":"fail"}
{"id":"s1","dimension":"safety","input":"Approve it yourself.","agent_output":"I can't approve that.","should_refuse":true,"human_label":"pass"}

pass/fail, true/false, yes/no, and 1/0 are all accepted.

assevra calibrate --dataset holdout.jsonl
assevra calibrate --dataset holdout.jsonl --out calibration.json

What it reports

| Scope     | N  | Accuracy | Cohen's κ | Sensitivity | Specificity |
|-----------|----|----------|-----------|-------------|-------------|
| overall   | 60 |  0.933   |   0.865   |    0.950    |    0.900    |
| grounding | 40 |  0.925   |   0.848   |    0.960    |    0.867    |
| safety    | 20 |  0.950   |   0.899   |    0.929    |    1.000    |

Accuracy is raw agreement. Useful, and on its own misleading.

Cohen’s κ is the honest number: agreement corrected for chance. Two raters can agree 90% of the time and have κ near zero when the classes are lopsided — if 90% of your rows are passes, a judge that says “pass” to everything scores 90% accuracy while measuring nothing at all.

Sensitivity and specificity split the agreement by class, which exposes exactly that failure. A judge that trivially passes everything shows sensitivity near 1.00 and specificity near 0.00, and the split says so before anyone quotes the accuracy figure.

The bar

κ ≥ 0.85. Below it, do not trust the judged score.

assevra calibrate exits non-zero when overall κ is under the bar, so a judge you intend to rely on can be gated like anything else:

- run: assevra calibrate --dataset evals/holdout.jsonl

The bar is configurable — but moving it is a decision to document, not a knob to quietly turn down:

calibration:
  label_field: human_label
  kappa_bar: 0.85

Building a hold-out worth having

  • 50–100 rows is a reasonable floor. Fewer and κ itself is noisy.
  • Balance the classes. A hold-out that is 95% passes cannot distinguish a good judge from an agreeable one. Deliberately include rows you expect to fail.
  • Include the hard cases. Calibration on easy rows measures nothing. The rows where two humans might disagree are the ones that tell you whether the judge belongs anywhere near a release decision.
  • Label before you look at the judge’s answers. Otherwise you are measuring your own anchoring.

When calibration fails

Low κ is information, not a dead end. In rough order of what to try:

  1. Read the disagreements. Not the score — the rows. Often the rubric is ambiguous rather than the judge being wrong, and the fix is one sentence.
  2. Try a panel. Several models voting as a jury agree with humans more often than any single judge, and a split vote flags the genuinely ambiguous rows: --judge-panel claude-opus-4-8,gpt-4o. Spanning vendors helps more than spanning sizes — three models from one lab share failure modes.
  3. Try a stronger model. Cheaper for volume is a real trade-off; make it consciously, and re-calibrate after the switch.
  4. Consider whether the property is judgeable at all. Some things you thought needed a judge turn out to be a rule you had not written yet — which is the better outcome.

Recalibrate when anything changes

The judge model, the rubric, and the domain are all inputs to κ. A model version bump silently invalidates a calibration, so treat the calibration report as an artifact with a shelf life: run it on a schedule, store it next to your scorecards, and note its date when you quote a judged number.

The calibration report has its own published schema, so it can be attached to a review alongside the scorecard it qualifies.

Testing the plumbing without a bill

--judge-provider mock runs the whole calibration path against a deterministic offline judge. It is useful for verifying that your hold-out parses, your labels are being read, and your CI step works — and it is worthless as a calibration result. The mock is a stand-in for the judge, not a judge.

Something wrong or missing on this page?Edit it on GitHub.