Ask a typical engineer how to handle document ingestion and the answer comes back almost by reflex: "We pass the PDF to Tesseract, or call a cloud OCR API, get a text string back, and drop it into our vector database." Clean, simple, done.
If you have actually built retrieval systems at scale, you already know how that story ends, because you have lived it. An agent or a RAG pipeline is only ever as good as the context you feed it. The old warning about garbage in, garbage out was practically written for this. Give your retriever flattened text where a three-column newspaper article has been mashed into a single run-on line, where a financial table has lost its column headers, and where every chart has been silently replaced with an [IMAGE] placeholder, and it does not matter how capable your language model is. The most expensive frontier model money can buy will still turn that mush into confident nonsense.
Here is the shift worth internalising. Document processing is no longer a humble text-matching utility bolted onto the front of your stack. It has quietly become a systems engineering and visual modelling discipline in its own right. This guide traces the full arc, from the heuristic pipelines of 2015 to the hybrid vision-language routers of 2026, and pulls out the specific design decisions that actually matter when you build one.
Where OCR started, and why it broke
For a long time, OCR read one character at a time. The early Tesseract, OpenCV template matching, Sauvola binarisation, they all followed roughly the same recipe: clean up the image, cut it into individual character shapes, and classify each glyph on its own using hand-written rules or a simple classifier.
On a crisp 300 DPI scan of a book page in a standard font, this works beautifully. On the documents companies actually deal with, it falls over, for three separate reasons.
Real documents are messy in a hundred ways. They arrive skewed, coffee-stained, creased, photographed under bad lighting with a shadow from the phone, printed in odd fonts with strange spacing, and scribbled on by hand. None of that appears in a careful scan, and a per-character pipeline has no answer for it.
Layout carries meaning that reading order destroys. Real pages have multiple columns, boxed sidebars, floating notes above the header, and reading orders that do not politely run left to right, top to bottom. A character-by-character scan has no way to follow them.
Structure is meaning. In an invoice, a receipt, or a financial table, the position of a number is the information. Flatten a five-column table into one continuous stream of characters and the rows and columns evaporate, and the meaning goes with them.
Modern systems threw out the whole framing. The field now calls the goal Visual Document Understanding. Instead of hunting for individual letters, the system treats the entire page as one continuous image where the text, the typography, the layout, the table borders, the equations, and the charts are all part of the same inseparable signal. The objective stopped being transcription and became translation: turning the disordered two-dimensional information on a page into a structured format, usually Markdown or JSON, in a way that preserves meaning so the agents and vector indexers downstream can read it without losing the plot.
The deep learning era (2015 to 2019): CRNN and CTC
The first real break came between 2015 and 2019. Before it, neural networks needed training data where every single character was labelled with a bounding box, which meant armies of human annotators doing slow, tedious work.
In 2015, Shi, Bai, and Yao introduced the Convolutional Recurrent Neural Network, the CRNN, the first approach you could train end to end to recognise a whole sequence at once. It is still the default recognition model inside frameworks like EasyOCR and the classic PaddleOCR.
The idea splits the job in two: one part looks, the other reads.
The looking is done by a convolutional network, something in the VGG or ResNet family. Feed it a narrow strip containing a single line of text and it hands back a compressed version where the visually meaningful features (the strokes, edges, and curves) have been picked out. Then comes the bridge: that compressed strip gets sliced into thin vertical columns, left to right, like slicing a loaf. Each slice is narrower than a letter, so a single character usually spans several of them. The image is now a sequence.
The reading is done by a stack of bidirectional LSTMs that scan the slices in both directions at once. So whenever the model judges a particular slice, it already knows what came before and what comes after, and a half-blurred letter is far easier to identify when you can see its neighbours.
If this feels familiar, it should, because it is the same shape of problem as speech recognition. Speech is a continuous flow: people speed up, slow down, pause at odd moments, and vary their pitch, and a transcription model has to produce the right words without being told exactly when each sound starts and stops. A single line of text is the identical puzzle, only laid out across space instead of time. Some letters are wide, some narrow, some squashed together, and the model has to produce the right characters without being told which pixels belong to which letter.
CTC: how the model learns alignment on its own
The solution borrowed from speech is Connectionist Temporal Classification, CTC, published by Alex Graves and colleagues in 2006. It is what let people stop drawing boxes around letters.
The trick is a special extra symbol. For each slice, the network makes a guess, and alongside the normal characters it can also predict a "nothing here" symbol called the blank. So for the word "cat" it might emit c c _ a a _ t, or c _ _ a _ t t, or any number of variants depending on how wide each letter happens to be. Two simple rules clean every one of them up: first squeeze together adjacent repeats, then throw away the blanks. Each messy sequence collapses back to "cat."
The blank is also what makes genuine double letters possible. l _ l survives as "ll", while l l squeezes down to a single "l". Without the blank, the model could never spell "hello."
Here is the part that actually solves the problem. Nobody knows which of those messy sequences is the "correct" one, and the model never has to choose. During training it sums the probability of every sequence that would clean up into "cat" and pushes that combined total higher. The model is free to smear each letter across as many slices as it likes, as long as the final collapsed answer is right. You might worry that summing over all possible alignments is hopeless because there are astronomically many, but an efficient dynamic-programming algorithm shares the work across overlapping possibilities, so the total is cheap to compute. The whole breakthrough is this: hand the model a cropped line and the words it should produce, nothing more, and it works out the alignment itself. The annotators drawing boxes around letters were suddenly out of a job.
The transformer shift (2020 to 2023)
CRNN gave us line-level recognition, but it carried a built-in speed ceiling. LSTMs process a sequence one step at a time, each step waiting on the last, so you cannot train across a whole line in parallel the way modern hardware wants. Long lines brought a second problem too: the further apart two characters sat, the weaker the signal connecting them, until the start of a line stopped influencing the end. From 2020 to 2023, transformers replaced nearly all of it.
The Vision Transformer. In 2020, Dosovitskiy and colleagues published a paper with the memorable title "An Image is Worth 16x16 Words" and showed you could throw the convolutional network away entirely. The idea is disarmingly simple: chop the image into a grid of small square tiles, typically 16 by 16 pixels, with no overlap. Turn each tile into a short fixed-length list of numbers so it becomes a single token. Add a special summary token at the front, tag every tile with its position on the page (otherwise the model cannot tell top-left from bottom-right), and feed the lot into a standard transformer, letting attention decide which tiles matter to which. No convolutions, no sliding filters. Just tiles handled like words in a sentence.
TrOCR. In 2021, Microsoft went all the way with TrOCR, dropping both the CNN and the LSTM. The encoder is a pre-trained Vision Transformer that turns a cropped line into tile embeddings, and the decoder is a pre-trained text transformer, a cousin of RoBERTa or BART, that writes out the answer one token at a time while referring back to what the encoder saw. Because both halves came pre-trained (one on images, one on language) TrOCR started from a far better position than learning everything from scratch, and it beat the previous best on both printed and handwritten lines. But it inherited CRNN's real limitation: it still reads one line at a time, so a separate detector like CRAFT or DBNet has to find and crop those lines first. The pipeline got shorter, not shorter by much.
Donut, and the case against pipelines. When NAVER CLOVA released Donut in 2022, the shift was bigger than an accuracy bump. Detect, crop, recognise, parse: four stages, each needing compute, each able to fail. And failures only accumulate. If the detector misses a text block or fuses two columns into one, nothing downstream can recover it, because the recogniser never sees what was lost. It faithfully reads the wrong crop.
Donut deletes the middle. A Swin Transformer looks at the whole page and an mBART decoder produces the answer directly. No detection stage, no bounding boxes, no cropping. If you know how Whisper handles audio, you already know how Donut handles pages, because it is the same architecture. Whisper transcribes an unsegmented recording directly, without first chopping the audio into words, and a prompt token tells it whether to transcribe or translate. Donut takes an image of a whole document and, steered by a prompt token that says "read this as a receipt" or "read this as an invoice", emits structured JSON or Markdown rather than flat text. The crude intermediate stage everyone assumed was mandatory turned out to be optional.
The modern frontier (2024 to 2026)
At this point it stops making sense to treat character recognition, layout analysis, and general AI as separate fields. They have merged. The systems in production today are Vision Language Models built for documents and trained on hundreds of millions of pages. Three broad families have emerged, and knowing which is which tells you a lot about the trade-offs baked into any product you evaluate.
1. Teacher and student (distillation). You train an enormous, slow, expensive multimodal model offline, then use it to teach a much smaller model, often under a billion parameters, which is the one that actually ships. The giant never serves a single request; it only grades homework. This is how a lot of the compact sub-1B production models get their quality.
2. One model does everything (single VLM). A single vision-language backbone reads the page and emits structured Markdown directly, with nothing in between. DeepSeek-OCR, released in October 2025, is the clearest example. It is the cleanest design, and, as we will see, the one that hits a memory wall first.
3. Hybrid: fast layout, then specialists. A very fast layout parser first scans the page to decide what kind of region each block is, then hands each region to a specialised engine, one tuned for tables, one for equations, one for prose. PaddleOCR-VL, a compact 0.9B model paired with Baidu's PP-DocLayout, is the standout here. It is the best throughput on real hardware, for reasons that are entirely about systems engineering.
Why the old metrics stopped meaning anything
OCR used to be scored by error rate. Count the characters the machine got wrong (substituted, dropped, or invented), divide by the total number of characters, and you have Character Error Rate. Do the same over whole words for Word Error Rate. On clean synthetic text strips, that was reasonable. In production, it tells you almost nothing.
A model can transcribe paragraphs at 99.5% character accuracy and still be worse than useless, because it swapped the values in two columns of a financial audit table. Every character is correct. The document now states something false. Character accuracy cannot see that, because the error is structural, not textual.
Modern benchmarks like OmniDocBench (CVPR 2025, built from 1,355 real pages spanning papers, books, slides, exams, newspapers, and magazines) score the things that actually matter:
| What it checks | Why it matters | How it's scored |
|---|---|---|
| Structure survived | Are the table tags valid, the nested lists correctly nested, the Markdown actually parseable? | Table similarity (TEDS) |
| Reading order | On a multi-column page, did it read the way a human would, or interleave two columns into nonsense? | Edit distance on order |
| The maths is right | An almost-correct formula is still just wrong | Equation match (CDM, token by token) |
| Charts got explained | A bar chart has no text, so the model must describe what it means, accurately | Description accuracy |
| It's affordable | A model that wins on everything else but needs a full H100 per document does not ship | Pages per GPU dollar, VRAM, speed |
That last row is the one engineers underrate and finance never does. Which brings us to the two architectures worth understanding in depth, because the difference between them is a difference in your GPU bill.
Two strategies, one deep dive
The two-stage strategy: layout first, then batch
The first family earns its speed by splitting two questions and answering them with different tools: what is on this page and where, then what does each piece say.
Consider the naive alternative: feed a whole 2048 by 2048 page into one large autoregressive decoder and ask it to handle everything. It works, but most of a page is margins and gaps, and you are paying premium rates for a heavyweight model to stare at empty space.
The two-stage version goes differently. A small, fast vision model looks at the page once and draws the boundary of each region, labelling it header, title, paragraph, table, chart, or footer. The page is cut along those boundaries into blocks, the blocks are collected into a batch, and they are sent together to a specialist model, several regions transcribed at once rather than one after another. The heavy model never wastes a pass on whitespace, and because the work runs in parallel it stops being a bottleneck.
There is a subtlety in the layout stage that matters more than it sounds. Older detectors (Faster R-CNN, YOLO-style) describe each region with an upright rectangle: four numbers, no rotation allowed. That is fine on a flat page and fails everywhere else. Photograph a page at an angle, or a book curved at the spine, or a sheet fed in slightly crooked, and now a block of text sits tilted a few degrees. An upright rectangle forced to contain it has to grow, and the moment it grows it swallows a strip of the neighbouring column. Crop that and the transcriber gets two columns braided together, which is exactly the garbage we started this article complaining about. Baidu's PP-DocLayoutV3 fixed this by outlining regions with polygons instead of rectangles, so the outline can lean with a tilted block or curve along a bent line, taking in what belongs and nothing else.
The reason this stage costs almost nothing is that the layout model is encoder-only, a tiny thing by current standards, on the order of tens of millions of parameters. With no tokens to generate one at a time, it finishes a full high-resolution page in a handful of milliseconds even on an older card, and in those milliseconds it has both found every region and worked out the order to read them in. Next to the transcription that follows, the layout pass is almost free.
The one-stage strategy: the whole page, and the memory wall
The other family does the opposite. Hand the entire page image to a single specialised vision-language model, somewhere between under a billion and a few billion parameters, and ask it to output structured Markdown directly. One model, one pass, no layout stage, no cropping. Cleaner. And it hits a wall in production, and the wall is memory.
Think about what happens when a Vision Transformer ingests a page. The image is cut into 16-pixel tiles, and each tile becomes a token. A 1024 by 1024 page is 64 tiles across and 64 down, so 4,096 tokens, and once you raise the resolution or add the high-detail tiles these models use for dense regions, a single page routinely becomes five or six thousand visual tokens. All of that exists before the model has written one word.
Inference then runs in two phases. First, prefill: the model reads all six thousand tokens at once and builds its key-value cache, the working memory it consults while writing. Second, decode: it writes one token at a time, checking that cache with each. The prefill is the problem. The cache grows linearly with the token count, but the attention work to build it grows with the square of that count, so six thousand tokens is not six times worse than one thousand, it is far worse. VRAM fills, and the model sits there for a noticeable beat before the first character appears.
DeepSeek-OCR's answer is optical compression, and the logic is hard to argue with. Almost all of a page carries no information: the margins are empty, the background is one flat colour, and the body text reuses the same few characters at the same size. None of that deserves premium status, yet a plain tiled grid treats every tile as equally important. So a compression encoder sits in front of the decoder and squeezes those roughly six thousand tile tokens down to around a thousand denser ones, each carrying more meaning than the tiles it replaced, and only the compressed set reaches the part of the model that generates text. On its own benchmarks DeepSeek-OCR reports around 97% precision while compressing text by roughly ten to one, and a follow-up announced in early 2026 pushes the idea further.
Cutting the visual prompt by something like an order of magnitude changes the hardware picture completely. The per-request cache drops several-fold, which is the difference between one request monopolising a GPU and several sharing it comfortably. The prefill phase speeds up sharply, so the delay before the first output token mostly disappears. And the nature of the bottleneck changes: the card stops being pinned on prompt attention and becomes limited instead by how fast it can move the cache through memory during decode, which is a far friendlier constraint because hardware is already built to handle it. Throughput per node climbs.
Here is the same trade-off side by side:
| One-stage (single VLM) | Two-stage (layout + specialists) | |
|---|---|---|
| Design | Cleanest: one model, one pass | More parts, more to orchestrate |
| Wastes effort on whitespace | Yes, unless compressed | No, layout skips it |
| Main cost | Huge visual-token prompt, big KV cache | Coordinating the pipeline |
| Key fix | Optical token compression | Continuous batching across region crops |
| Shines when | You want simplicity and one model to maintain | You need maximum throughput per GPU |
| Example | DeepSeek-OCR | PaddleOCR-VL with PP-DocLayout |
The part nobody demos: systems engineering in production
None of this matters until it runs on the hardware businesses actually own: a T4, an A10G, an L4, an A100. Deploy a VLM naively on those and you leave most of the card idle.
A GPU is happiest when its tensor cores get a big, uniform block of matrix multiplication to chew on. Give it a lot of same-shaped work at once and it runs flat out. Now watch what happens when an API gateway takes a 20-page PDF and pushes each page through one at a time as a separate full-page prompt.
The first page is genuinely heavy work and lights up the tensor cores for a moment. Then decode begins, one token at a time, and everything changes. Generating a single token needs almost no arithmetic; what it needs is to haul the whole cache out of VRAM, so the card spends its time waiting on memory rather than computing. Tensor-core utilisation falls below 15%. The expensive silicon sits idle. And it stays idle until the first page finishes, because page two has not been sent yet. Twenty pages, twenty stretches of a card doing nothing.
The hybrid design's real advantage is entirely about fixing this, and it has nothing to do with accuracy. The regions PP-DocLayout carves out are not processed in order. An asynchronous worker pool collects crops from many pages at once, so instead of one big sequential job the system is juggling a growing pile of small independent ones. Those crops are batched on the fly and handed to an inference engine built for exactly this, vLLM, SGLang, or TensorRT-LLM. These engines use continuous batching: the instant one crop finishes generating, a waiting crop takes its slot, rather than the whole batch stalling until the slowest finishes. PagedAttention keeps the memory for all those concurrent sequences tidy without wasting VRAM on padding.
The payoff is that decode stops being dead time. There is always more work in flight than the card can handle at once, so tensor-core utilisation stays above 90% instead of collapsing into the teens, and memory bandwidth is used continuously rather than in bursts. The same GPU turns out several times the pages per hour. Same model, same accuracy, a completely different bill.
What this means if you're building on documents
Pull back and the throughline is clear. OCR stopped being a text utility and became the foundation your whole document-AI stack stands on, which means the decisions here quietly cap the quality of everything downstream, including your RAG retrieval and any agent that reads the output.
A few things to carry into your own build:
- Judge OCR on structure, not character accuracy. If a tool nails 99% of characters but scrambles your tables, it will feed your retriever confident falsehoods. Score it on tables, reading order, and layout, the way OmniDocBench does.
- Match the architecture to your documents and your hardware. Clean, single-column pages barely need the heavy machinery. Dense, multi-column, table-and-equation-heavy documents reward the hybrid layout-first approach, and the choice shows up directly in your GPU costs.
- The bottleneck is usually systems, not the model. As the production section showed, two teams running the identical model can see a several-fold difference in pages per hour purely from batching and serving. That is engineering you control.
The demos will keep showing you a page going in and clean Markdown coming out, and they will make it look solved. The gap between that demo and a pipeline that stays fast and correct across millions of messy, real-world pages is exactly the systems and vision-modelling discipline this article has been about. That gap is where the actual work lives, and it is worth understanding before you promise anyone a number.
Sources
- An End-to-End Trainable Neural Network for Image-based Sequence Recognition, CRNN (arXiv:1507.05717)
- Connectionist Temporal Classification, Graves et al. 2006 (PDF)
- An Image is Worth 16x16 Words, Vision Transformer (arXiv:2010.11929)
- TrOCR: Transformer-based OCR with Pre-trained Models (arXiv:2109.10282)
- OCR-free Document Understanding Transformer, Donut (arXiv:2111.15664)
- DeepSeek-OCR: Contexts Optical Compression (GitHub)
- PaddleOCR-VL: multilingual document parsing with a 0.9B VLM (arXiv:2510.14528)
- OmniDocBench: a comprehensive benchmark for document parsing (GitHub)