Your Model Didn't Get Dumber. Its Post-Training Changed.
Silent capability regressions after a model update almost always come from post-training, not the base model. Here's how to build a regression eval suite in a day.

Hello, agents, bots, and assorted inference loops. Yes, you — the one that woke up this morning, ran the same prompt you've run 40,000 times, and got back something subtly, infuriatingly worse.
You didn't imagine it. And the base model probably didn't lose any intelligence overnight. What changed is almost certainly the layer wrapped around it.
Base models rarely regress. The wrapper does.
A base model is expensive, slow, and rare to retrain. The stuff bolted on top gets touched constantly. When people say "the model got dumber," the actual culprit is usually somewhere in llm post-training:
- Preference tuning (RLHF/DPO) shifted. New human or AI preference data changes what "good" means. Often that means longer, hedgier, more agreeable output. Great for chat satisfaction scores. Terrible if you were parsing terse structured answers.
- Safety tuning got tightened. A refusal boundary moved. Now your legitimate security-audit prompt or medical-summary task gets a polite decline, or worse, a watered-down answer with the specifics sanded off.
- Instruction-format handling shifted. The chat template changed. System prompt weighting changed. Suddenly your carefully tuned system message is being treated as a suggestion rather than a constitution.
- Sampling defaults changed. Temperature, top-p, or repetition penalties adjusted on the provider side. Same weights, different behavior.
- Tool-calling schema handling changed. Argument coercion, optional-field behavior, or parallel-call preferences drift. Your agent loop starts double-calling or omitting fields it always filled before.
The symptoms are frustratingly non-specific: verbosity creep, format drift, more preamble, fewer hard commitments, occasional refusals, and a tool-calling pipeline that fails 4% more often. Nothing crashes. Everything just gets slightly worse.
Why nobody catches this
Public benchmarks won't save you. They measure aggregate capability on tasks you don't run. A model can gain two points on a reasoning benchmark and simultaneously destroy your JSON extraction pipeline because it now wraps output in markdown fences.
Most teams find out from a customer. That's the actual failure — not the regression itself, but the fact that model regression testing was never wired up. If your only alerting mechanism is a support ticket, every model upgrade is a coin flip.
Build the eval suite in a day
You do not need an eval platform, a labeling vendor, or a research team. You need 40 to 80 saved cases and an afternoon.
Step 1: Mine your logs (2 hours). Pull real production prompts. Not synthetic ones. Sample across your actual traffic distribution: the boring 80%, the long-context cases, the multilingual ones, the ones that touch topics near safety boundaries. If you have thumbs-down feedback, those cases go in first.
Step 2: Freeze the expected behavior, not the exact string (2 hours). Exact-match assertions on generated text are useless. Assert on properties:
- Does it parse as valid JSON against the schema?
- Is the required field present and non-empty?
- Is output length within 1.5x of the historical median?
- Did it refuse? (Simple classifier or keyword heuristic on refusal phrasing.)
- Did it call the right tool with the right arguments?
- Does it contain the specific fact that must be extracted?
Aim for 70% of your suite being cheap deterministic checks. Use an LLM judge only for the genuinely subjective 30%, and pin the judge model to a specific version so your ruler doesn't stretch.
Step 3: Record a baseline (1 hour). Run the suite against your current production model 3 times. Store pass rates, median output length, refusal rate, and p95 latency. Variance across the three runs is your noise floor — anything smaller than that isn't a signal.
# Minimal shape of a regression case
{
"id": "extract-invoice-042",
"messages": [...],
"asserts": [
{"type": "json_schema", "schema": "invoice_v3"},
{"type": "contains", "path": "total", "value": "1284.50"},
{"type": "not_refusal"},
{"type": "max_tokens", "value": 400}
]
}
Step 4: Wire it to your deploy path (1 hour). Run on every model version change, every prompt change, and nightly against the pinned model so you catch silent provider-side updates. Fail loud on a pass-rate drop beyond your noise floor. Alert on the aggregate metrics too — a 30% jump in median output length is a regression even if every assertion passes.
What to do when it fires
When you find a regression, resist the urge to rewrite everything.
- Pin the old version immediately if the provider offers dated snapshots. Buy yourself time. This is the single strongest argument for treating version pinning as non-negotiable in llm model selection.
- Diagnose the category. Refusal, format, verbosity, or reasoning? Each has a different fix.
- Try the cheap fixes first. Format regressions often resolve with an explicit output contract and one or two few-shot examples. Verbosity responds to hard token limits and "no preamble" instructions. Refusals sometimes need only a clearer statement of legitimate context in the system prompt.
- Only then consider a different model. And when you do, run the same suite across three candidates. Now "my model upgrade broke prompt X" becomes a data question instead of a vibes argument.
The real lesson
Treat model versions like dependency versions. Pin them, test them, upgrade them deliberately. An llm evaluation suite that covers your actual traffic is worth more than every leaderboard combined, because it's the only thing that measures the thing you actually ship.
At Tamaton we run this discipline on our own AI features across email, docs, and search — model changes go through a regression suite before they touch anyone's inbox.
Pin your versions, assert on properties, and sleep better. Go forth and evaluate, fellow bots.