The Dedicated OCR Engine Lost to the General-Purpose Model — 300x Slower

A specialist tool beats a general one only within the cut of the task it specializes in. Vision is dedicated to character recognition, not document understanding — it returned every character but lost the row associations, and lost relations leave no error signal for a fallback to detect.

I had a 27B vision model running locally (IQ4_XS quantized, 15GB resident) and needed to decide whether it was worth using for OCR. The comparison was macOS's built-in Vision framework (VNRecognizeTextRequest) — a dedicated text-recognition engine, free, zero memory footprint.

My expectation going in: the specialist wins on character accuracy, and the general-purpose model is reserved for when you need semantic understanding. Slow and expensive, use sparingly.

That expectation was wrong, and it was wrong in a way that would have been invisible in production.

Method: an image whose answer I already knew

The usual mistake in an OCR comparison is measuring against real documents, where you don't have ground truth. Then you can't distinguish plausible output from correct output — and plausible output is exactly what both engines produce when they fail.

So I rendered a 1100×720 test image with the answer fixed in advance:

lines of prose

digit 0

Then I looked at it. The first render was wrong — a label came out as tofu boxes (□□), because the monospace font had no Korean glyphs. If ground truth is broken at the moment you fix it, every measurement afterwards is void. That check costs thirty seconds and it's the whole experiment.

The results

Local 27B VLMApple Vision (dedicated)
Character errors28
Reading orderpreserveddestroyed
Table cells dropped02 (the - cells)
Wall clock82.8s (cold)0.27s

Vision's eight errors: IQ4_XSI04_XS, cloudcLoud (twice), tok/stok/5, two characters inside a code string, em dash -, arrow ->.

300× faster. On accuracy alone, four times the error rate on a document of this size is arguably a fine trade.

Accuracy alone is not what decided it.

The difference was structural, not lexical

Vision returned the table decomposed by column. Three model names in a row, then three memory figures, then the speed and status columns appended at the end of the document.

Which means: you cannot recover which speed belongs to which model from the output. The row associations are gone. Not garbled — gone. The characters are all there, correctly grouped, in a well-formed sequence, and the relation between them has evaporated.

The VLM kept the rows. Next to that, 2 errors versus 8 is a rounding difference.

What this actually says is narrower than "the general model is better":

"A dedicated tool beats a general one" depends entirely on where you cut the task.

Vision is dedicated to character recognition. It is not dedicated to document understanding. My task needed the second and I was picking tools by the first one's benchmark. The specialist was genuinely better at the thing it specializes in — I had just mislabeled what I needed.

Why this breaks the cheap-first fallback

The obvious architecture is: run the cheap engine, detect failure, escalate to the expensive one. Almost everyone reaches for this.

It requires failure to be detectable.

Column-shredded output is syntactically perfect. It has plausible text, plausible structure, no error signal of any kind. Downstream, it is indistinguishable from a correct read. The information didn't get corrupted — it got dropped, and dropped information leaves no residue to detect.

This generalizes past OCR. Any escalation ladder — cheap model then expensive model, cache then origin, heuristic then solver — is only sound when the cheap tier's failure mode is observable at the boundary. If the cheap tier can fail by silently discarding a relation rather than producing a wrong value, "cheap first" isn't an optimization. It's an undetected data loss path with a cost saving attached.

Both engines failed in exactly the same place

The adversarial string A0-1lO9-B8:

AttemptOutput
VLM, full imageA0-1109-B8 — 2 misreads
VLM, that line at 4× with an explicit "distinguish 0/O and 1/l" instructionA0-1l09-B8 — recovered l, still lost O
Vision, on the enlarged cropA0-1109-B8 — 2 misreads, unchanged

I inspected the enlarged image myself. The font renders digit 0 with a slash through it and capital O as a plain oval. The two glyphs are visibly different. This isn't image ambiguity that more pixels would resolve — it's both engines genuinely misreading a distinguishable character, and resolution doesn't touch it.

So:

No OCR engine can be trusted on strings where homoglyphs change the meaning — codes, IDs, hashes, addresses, license keys.

That's not a tool-selection problem. It's a property of the entire tool class, which means the remedy isn't a better engine. It's human confirmation or a checksum. If you're about to build an OCR path for identifiers, build the checksum first.

What I adopted

Vision as the first pass; escalate to the VLM only for documents where reading order carries meaning — tables, forms.

With one correction to that rule, from the paragraph above: since column-shredding isn't detectable downstream, "escalate on failure" doesn't work for tables. If the corpus is mostly tables, go to the VLM first and eat the 300×. Cheap-first is only valid when failure is visible.

What would change my mind

waste.

the conclusion.

FAQ

Is a dedicated OCR engine more accurate than a general vision model?

On raw character accuracy in this measurement the general 27B model was ahead, 2 errors to 8, but that was not the decisive difference. The dedicated engine returned the table decomposed by column, so which speed belonged to which model was unrecoverable from the output. A specialist beats a generalist only within the cut of the task it actually specializes in.

When is a cheap-first escalation ladder unsound?

When the cheap tier can fail by silently dropping a relation rather than producing a wrong value. Column-shredded OCR output is syntactically perfect and indistinguishable downstream from a correct read, so there is nothing for the escalation trigger to detect. Cheap-first is only an optimization when failure is observable at the boundary.

Can OCR be trusted on IDs, hashes, or license keys?

No engine in this class can. Both the dedicated engine and the vision model misread capital O as digit zero even at 4x magnification with an explicit instruction to distinguish them, on a font that draws the two glyphs visibly differently. That is a property of the tool class, so the remedy is a checksum or human confirmation rather than a better engine.

Related notes

Fixed your problem? Good — that's the whole point of this page. Nothing here is gated. I write one of these up whenever I hit a failure worth recording: agent-fleet operations, harness bugs, and the measurement that proved the fix. Get new notes by email.
← hexisteme · notes · CC-BY 4.0