Pranav Srivastava

11 lessons

0/11 done
Lesson 7 of 11·13 min·Advanced
613 min

Trusting the numbers: calibration and shadow tests

What you will learn
  • Define calibration and expected calibration error (ECE) in plain words
  • Read the independent calibration findings on Jev, and their limits
  • Calibrate a probability with a temperature fit, in code
  • Design a shadow test that would catch the failures reviewers actually found

Refresher: what "calibrated" means

Suppose a weather app says "70% chance of rain" on 100 different days. If it is calibrated, it rained on about 70 of them. If it rained on 45, the app is overconfident: it sounds surer than it has earned.

A typed-decision model does the same. When it says 0.9 on a ticket, you want it right about 90 times in 100 such tickets. That property is what lets you write "handle anything above 0.9 automatically". If the property is false, that rule quietly lets errors through.

Expected calibration error (ECE) is a single number for how far off the model is: group answers by stated confidence, compare each group's stated confidence to its real accuracy, average the gaps. Zero is perfect. A model can be very accurate and still badly calibrated, and the reverse.

What independent testers found

One study, by scienthoon, deliberately used 900 support tickets generated by a script on 19 September 2026, so the model could not have seen them, plus three public benchmarks. Here are the reported numbers.

How far off is the stated confidence? (lower is better)
  • OpenBookQA (500)accuracy 94.2% · ECE 0.024
  • CommonsenseQA (1,221)accuracy 88.1% · ECE 0.032
  • HellaSwag (2,000)accuracy 86.1% · ECE 0.029
On well-known public benchmarks, which a model may well have seen in training, the confidence looks respectable. That is the flattering test.

Authors’ advice: do not threshold on the separate confidence field, calibrate per question rather than per model, and treat the output as a ranking until you have calibrated it locally.

The story is in the two tabs. On public benchmarks, which a model may have seen in training, the calibration error is small. On new tasks it is worse, and on the "priority" question, which depended on a company rule not present in the text, Jev averaged 0.74 confidence while being right 44.7% of the time. It was confidently guessing at something unknowable. (scienthoon)

The same study noted:

  • Probabilities are quantised to 0.01 and often exactly 0 or 1, so a correct answer given zero probability cannot be recovered
  • Choice and score answers were overconfident; yes/no was underconfident, so one fix does not suit all
  • Do not threshold on the separate confidence field: it did worse than the highest probability
  • Calibrate per question, not per model

Another reviewer found the same direction across studies (median ECE of 0.071 on a 13-subset public suite as shipped, with the direction varying by domain), and noted that one temperature fitted on 50 labels cut a comparison model's median ECE from 0.180 to 0.080 (xbill). Fifty labels is a small ask.

Calibrate it yourself

The fix is cheap: keep a labelled sample, and learn a correction. This code measures ECE on synthetic overconfident data, then fits one temperature on a small sample. It runs as written.

import math, random

random.seed(5)

def ece(probs, correct, bins=10):
    n, total = len(probs), 0.0
    for b in range(bins):
        lo, hi = b / bins, (b + 1) / bins
        idx = [i for i, p in enumerate(probs) if lo <= p < hi or (b == bins - 1 and p >= hi)]
        if not idx:
            continue
        conf = sum(probs[i] for i in idx) / len(idx)
        acc = sum(correct[i] for i in idx) / len(idx)
        total += len(idx) / n * abs(acc - conf)
    return total

def scale(p, T):
    """Temperature: divide the log-odds by T. T above 1 makes it less confident."""
    p = min(max(p, 1e-4), 1 - 1e-4)
    return 1 / (1 + math.exp(-math.log(p / (1 - p)) / T))

# synthetic: stated confidence is high, but real accuracy is 15 points lower
def sample(n):
    probs = [min(0.999, 0.6 + 0.4 * random.random()) for _ in range(n)]
    correct = [1 if random.random() < max(0.0, p - 0.15) else 0 for p in probs]
    return probs, correct

fit_p, fit_c = sample(50)             # your small labelled sample
test_p, test_c = sample(2000)         # traffic you evaluate on

def nll(T):
    return -sum(math.log(scale(p, T) if c else 1 - scale(p, T)) for p, c in zip(fit_p, fit_c))

best_T = min([t / 10 for t in range(5, 60)], key=nll)
print("ECE as stated:      ", round(ece(test_p, test_c), 3))
print("fitted temperature: ", best_T)
print("ECE after fitting:  ", round(ece([scale(p, best_T) for p in test_p], test_c), 3))

Run it. The error falls once a temperature is fitted on just 50 labelled examples. On real data, do this per question type.

Wording is a release

A quieter finding from the same review: asking the identical question twice changed only 1.33% of answers, but swapping which rubric sat behind "yes" and "no" changed 32.5%.

Same 40 items, same meaning. Only the wording behind yes/no moves.
All answers agree

Asking the identical question twice changed only 1.33% of answers, so the model is steady. But it is steady about the wording, not just the meaning. Small, reasonable-looking edits to your instructions can move a third of your decisions. That is why every prompt change here is a release, and why the Shadow Evaluation Harness matters more, not less.

Two practical rules follow:

  1. Pin the model version you tested. The launch material mentions "Jev 1.13"; a silent version change is a silent behaviour change.
  2. Every edit to your criteria is a release. Re-run your test set. This is exactly the Shadow Evaluation Harness rule.

A shadow test that would have caught the known failures

Run the typed-decision model beside your current process, on real traffic, deciding nothing. Then check:

CheckCatches
Accuracy by confidence bandOverconfidence: does 0.9 really mean 90%?
Accuracy per languageThe drops seen in Russian and Spanish
Accuracy on a "cannot know" setConfident guessing at unknowable questions
Same items, reworded criteriaThe 32.5% wording sensitivity
Same items, run twiceRepeatability
Errors that live passes and this failsRegressions (block on these, whatever the average)
Latency from your regionVendor speed claims vs your network

Then a small canary behind an approval gate. One reviewer's whole pre-registered study ran 5,721 calls for $0.176 at list price (Beri). Testing is not the expensive part.

Chapter summary
  • Calibrated means stated confidence matches real accuracy; ECE measures the gap
  • Independent tests found overconfidence on choice and score answers and underconfidence on yes/no; TypeSafe publishes no calibration metrics
  • A temperature fitted on about 50 labels can help a lot; calibrate per question type
  • Rewording criteria moved 32.5% of answers in one test: prompt edits are releases
  • Shadow first, on your data, with confidence bands, languages, wording, repeatability and regressions; report accuracy with coverage
Check your understanding
  1. The model says 0.9 on 200 tickets and is right on 150. What is its real accuracy there, and is it over- or under-confident?
  2. Why should you not set your auto-handle line from the number in a vendor's blog post?
  3. Your team changes a criteria sentence to be "clearer". What must you do before shipping, and why?

Sources

All pages read on 25 September 2026. Figures were pulled through a summarising fetch tool, so check any number on the linked page before you quote it.

Finished this lesson?

Mark it done — your progress is saved automatically.