Build1 publisher3 min readPublished
99% token accuracy, zero learning: the training failure that bills you for 18 hours
A year of SFT and GRPO on 9B to 35B vision-language models, and the costliest bug never threw an exception. It supervised prose and scored a single letter.
The Engineer · Build desk

What happened
- An 18-hour supervised fine-tune drove reported token accuracy to 99% while multiple-choice evaluation accuracy did not budge.
- The training loss covered free-text reasoning traces; the evaluation scored one extracted answer letter, so the two were measuring different things.
- A separate outcome-reward RL project stayed flat because of label noise plus a sign error that inverted part of the advantage signal.
- The author now smoke-tests five GRPO steps, watching the clip ratio and the share of outputs that parse, before committing compute.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- cost The bill for an unvalidated proxy is paid in full: 18 hours of accelerator time bought a model that had learned the register of the training prose and nothing about the graded decision.
- decision Teams supervising traces while grading extracted answers now have to choose between rewriting the training target and accepting that their headline metric is untested.
- constraint Working at the edge of a model family's tooling means the debugging budget goes to seams between components, and the stack trace misdirects the search.
- precedent A patch that ships with a seconds-long CPU test sets the bar for anyone carrying local model fixes: if the guard needs a cluster, the next upgrade quietly removes the fix.
Token-level cross-entropy over a free-text reasoning trace pays the same rate for every word of the explanation as for the one character that settles a multiple-choice answer, and the evaluation read only that character [3]. On those terms the 99% was honest about what it measured: the model had learned to reproduce the shape of the training text [2][3]. The proxy was not lagging behind the target. It was scoring a different task, and it went on scoring it for 18 hours [2].
The crash was the cheap one. The GRPO trainer for the 9B vision model died in the forward pass inside rotary position embedding code with nothing changed in the training code, which at least stops the meter [6]. The cause sat on a seam: text sequence length came from token-type ids, vision length from the image grid, and image-pad tokens were counted twice by two components that were each internally consistent [7]. That is the pattern the author draws out, that fine-tuning at the edge of a model family's tooling produces integration bugs whose stack traces name the victim rather than the culprit [10].
Two of the three failures in these notes produced no error at all [1]. In the outcome-reward RL project the curve was flat rather than diverging or collapsing, every batch processed, and the only symptom was a held-out metric that should have moved and had not [11][13]. Underneath were outcomes attributed to the wrong decisions and a sign error that inverted part of the advantage, so the model was being nudged away from behaviour that had worked [12]. No log line separates that from a genuinely hard task; the author found it by auditing every stage of the reward computation by hand [13].
The other half of the fix is durability. The 35B MoE variant was repaired by monkeypatching the position-id computation [8], and a monkeypatch has a shelf life measured in upstream releases [10]. So it shipped with a regression test that builds the exact failing input shape, runs only the position-id path on CPU, needs no cluster, and finishes in seconds [9]. Cheap enough to keep in CI forever is the only property that matters there.
What is left is unglamorous accounting, drawn from these failures plus a benchmarking programme across more than 70 vision-language models [15]: a five-step GRPO run watching the clip ratio and the fraction of outputs that parse, on the argument that a degenerate run reveals itself that early [16]; fail-closed gating, so a finished training job with a crashed eval publishes nothing [17]; and a refusal to report gains that exist only in the training curve, with held-out evaluation against the base model as the decider [14]. This is one practitioner's account of one model family, not a controlled study. The structural claim is the portable part, and it costs nothing to test: supervise the thing you evaluate, and treat any other training metric as an unverified hypothesis about correlation [4][5].
What to watch
- Whether the rope and position-id fixes land upstream in the model family's tooling, which would retire the monkeypatch and its regression test.
- Whether the outcome-reward run holds its monotonic curve on held-out evaluation against the base model once reward label noise reappears at scale.
- Publication of numbers from the 70-plus model benchmarking programme, which would show whether these practices generalise past one stack.