Vibe Engines
YouTube
AI System Design

Design a Document AI Pipeline

Learn AI system design by building a document AI / intelligent document processing pipeline that turns PDFs, scans and forms into structured data step by step.

The numbers to beatingest → OCRpixels → text+coordslayout → extractstructure → fieldsvalidate → outputcorrectness → data

The whole design, in writing

Learn AI system design by building a document AI / intelligent document processing pipeline that turns PDFs, scans and forms into structured data step by step. An interactive guide covering why plain OCR is not enough, preprocessing and OCR, layout understanding, template vs ML/VLM extraction, validation and confidence, human-in-the-loop review, and the unhappy paths (bad scans, varied layouts, hallucinated fields, PII).

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

What is document AI?

Businesses drown in documents — invoices, forms, contracts, receipts, IDs — that humans manually key into systems. You want to turn a messy scanned invoice into clean structured data: {vendor, invoice_no, total, line_items[]}, automatically, at scale. But documents are visual, varied, and full of layout (tables, forms, columns) that a plain text dump throws away.

DocumentsPDF · scan · form
New in this step: Documents.

A document AI (intelligent document processing) pipeline turns unstructured documents into structured data: preprocess and OCR the image, understand its 2D layout, extract fields and tables (increasingly with a VLM reading the doc directly), validate with confidence scores, and route the doubtful cases to a human. Reading the pixels is easy; producing correct structured fields is the system.

What the new pieces do

Documentsclient
Invoices, forms, contracts, receipts — messy, varied, often scanned. The goal: turn them into clean structured data.

Step 1 · OCR alone isn't enough

Text is not structure

The naive approach: run OCR and return the text. OCR is great at reading characters. So why isn't "the text of the document" the same as the structured data you need?

DocumentsPDF · scan · form
The system as it stands at this step.

Run OCR and return the text. Why isn't that the structured data you need?

  1. OCR reads characters but flattens the 2D page into linear text, discarding the spatial relationships that carry meaning: which text is a key vs a value, which numbers belong to which table row/column, what's a header. Structured data needs that layout understanding, not just the raw text.

  2. OCR reads printed text well — that's its job. The gap is structure: turning correctly-read characters into fields and tables requires understanding the page's 2D layout, which raw OCR text doesn't preserve.

  3. Length isn't the issue. The issue is that a linear text dump loses the spatial/layout structure (key-value pairs, tables, columns) that defines what the data actually means.

OCR reads the characters, but flattens the page into a linear text stream, discarding the 2D structure that carries the meaning: which text is a label vs a value, which numbers belong to which table cell, what's a header. Structured data — fields and tables — lives in that spatial layout. So "the text" isn't "the data"; you need to understand the layout and extract structure, not just recognize characters.

Why this piece earns its place

The metric trap here is worth naming out loud, because it is how a pipeline ships broken. OCR engines are graded on character accuracy, and character accuracy compounds: a field is wrong if any single character in it is wrong, so a per-character error rate that reads as excellent becomes a field-level error rate that is far worse, and worst of all on the longest fields — the account numbers and reference IDs a downstream system keys a payment to. Measure accuracy per field, by field type, or you are grading the wrong exam. The same trap catches the test harness: if the acceptance check is whether the text dump contains the string 4471 somewhere, a pipeline that lost every label-to-value link still passes it. There is one case where the text really is the deliverable — full-text search over an archive, where a human reads the hit and supplies the structure themselves. If that is the actual requirement, stop at this step; everything after it is cost you do not need.

Step 2 · A pipeline, not a step

Ingest → understand → extract → validate

Turning a document into trustworthy structured data is several distinct jobs. What are the stages, and what does each contribute?

DocumentsPDF · scan · formDoc AI Serviceingest → extract
New in this step: Doc AI Service.

Run a pipeline: ingest the document → preprocess + OCR (clean the image, read text + coordinates) → layout analysis (understand the 2D structure) → extraction (produce fields and tables) → validation (check + score confidence) → structured output, with low-confidence cases routed to a human. Each stage removes a different failure: OCR handles pixels, layout handles structure, extraction handles meaning, validation handles correctness.

Why this piece earns its place

Drawing the stages is the easy half. The operational half is that each stage persists its own output, versioned. OCR is the expensive one and its result is reusable, so it gets cached — but the key has to be the source file hash and the engine version, because OCR is deterministic per engine, not absolutely. Key on the file alone and the day you move to a handwriting-capable reader, every document you have already touched keeps serving the old engine's text forever, and no cache miss ever tells you. Extraction is the opposite: the schema gains a field, the prompt changes, a better model ships, so it is re-run over history constantly. Fuse the two into one function and every schema tweak repays the whole OCR bill, turning a backfill that should be an afternoon into a budget conversation. Versioning earns its keep the day you find a systematic error. Someone reports a wrong total, you trace it to a recent extractor release, and the only question that matters is which documents it touched. If every record carries the OCR version, the model version and the schema version that produced it, that is a query. If it does not, it is a full reprocess and a diff, on the hope you can still tell the new errors from the old ones.

  • ingest → OCRpixels → text+coords
  • layout → extractstructure → fields
  • validate → outputcorrectness → data

What the new pieces do

Doc AI Servicegateway
Orchestrates the pipeline: preprocess, OCR, understand layout, extract fields/tables, validate, and output structured data.

Step 3 · Read the pixels

Preprocessing & OCR

Real documents are photographed, skewed, low-contrast, or noisy scans. Before understanding anything, you must reliably get the text off the page. What does this stage do?

Doc AI Serviceingest → extractPreprocess + OCRtext + coords
New in this step: Preprocess + OCR.

Preprocess the image — deskew, denoise, adjust contrast, handle rotation and multi-page — then run OCR to extract not just the text but the bounding-box coordinates of every word/line. Those coordinates are crucial: they're what the next stages use to reconstruct layout. Good preprocessing lifts OCR accuracy (garbage pixels → garbage text), and keeping word positions is what lets "reading" become "understanding."

Why this piece earns its place

Preprocessing destroys data silently, which is why the original upload is sacred. Aggressive binarisation or denoising erases thin strokes — a decimal point, a comma, a hyphen inside an ID — and the damage never surfaces as a failed read, because what comes back still parses. A total that lost its decimal point is a perfectly valid number, and nothing downstream questions its shape. So keep the upload untouched forever, treat the cleaned image as a derived artifact you can regenerate, and tune the filters against the scans that fail rather than the ones that already work. Then ask whether this document needs OCR at all. A born-digital PDF carries a text layer with exact character positions, and rendering it to pixels to read them back is a lossy round trip over data that was already perfect. But a text layer is not proof of a native one: a scan that somebody else ran through OCR and saved as searchable carries one too, at unknown quality, and a subset font with no ToUnicode map extracts as mojibake. Branch on evidence — the producer string, whether the glyphs sit invisibly over a full-page image, whether what you pull out is even decodable — not on presence.

  • preprocessdeskew/denoise
  • OCRtext + bounding boxes
  • positionsenable layout

What the new pieces do

Preprocess + OCRservice
Cleans the image (deskew/denoise) and runs OCR to get text plus the coordinates of every word on the page.

Step 4 · Understand the page

Layout analysis

Now the pivotal step. You have located text, but a form, a table, and a paragraph all need to be read differently. How do you recover the document's 2D structure?

Preprocess + OCRtext + coordsLayout2D structure
New in this step: Layout.

You have text with coordinates. How do you recover the document's structure (forms, tables)?

  1. Reading-order flattening is exactly what loses structure — it mixes table cells and separates labels from values. You need to model the 2D layout: detect regions, tables, and key-value relationships from positions.

  2. Without layout, extraction has to guess structure from a jumbled stream, which fails on tables and multi-column forms. Explicit layout understanding gives extraction the spatial structure it needs.

  3. Layout analysis models the page in 2D: it detects blocks/regions, table cells (rows/columns), and the spatial links between field labels and their values. Layout-aware models (e.g. LayoutLM-style, combining text + position + image) or a VLM that sees the page directly recover the structure that linear text loses.

Layout analysis models the page in 2D: detect regions (header, blocks), tables (rows/columns/cells), and key-value relationships (which label owns which value) from the spatial arrangement. Use layout-aware models (LayoutLM-style: text + position + image together) or a VLM that sees the page image directly. This is the crux — it recovers exactly the structure OCR flattened, turning located text into an understood document.

Why this piece earns its place

Whatever produces the structure, insist it comes back as coordinates on a page and not just a tidy object. A wrong total looks identical either way: layout may have merged two columns, or the extractor may have misread a clean cell. Those have opposite fixes and usually different owners, and the output alone cannot separate them — the boxes can. The catch is that a box is only meaningful against the image it was measured on, and preprocessing has already deskewed, rotated and rescaled that image. Record the transform beside the coordinates, or store them in the original page's space, because the cleaned copy is a derived artifact: the day a reviewer opens the source PDF, a highlight computed in the wrong space lands near the value rather than on it, and nobody can tell whether the extractor or the viewer is the liar. Worth settling early too is that this stage runs per page and it is the expensive one. A real corpus is full of pages it has nothing to find on — separator sheets, fax covers, the back page of standing terms — so a cheap classifier deciding which pages get layout analysis at all moves the bill further than any tuning inside the model.

  • regionsheader/blocks
  • tablesrows × columns
  • key-valuelabel ↔ value

What the new pieces do

Layoutlayout
Understands the page as 2D structure — forms, tables, columns, key/value pairs — not a linear stream of text.

Step 5 · Pull the fields

Extraction: templates vs ML vs VLM

Now produce the actual structured output — the fields and tables you want. Documents range from fixed forms to wildly varied invoices. What extraction approach fits?

Preprocess + OCRtext + coordsExtractionVLM / modelLayout2D structure
New in this step: Extraction.

Match the method to the variety. Templates/rules work for fixed layouts (a form that's always identical — extract by position/regex). ML models (layout-aware) handle varied documents by learning to tag fields. Increasingly, a VLM/LLM reads the document (image and/or OCR text) and outputs structured JSON directly to a schema — flexible across document types with little per-template work. Often you classify the document type first, then route to the right extractor.

Why this piece earns its place

The router is the failure the diagram cannot show. A classifier that misroutes is worse than one that abstains, because handing an invoice to a purchase-order extractor does not error — it returns a confident, fully-populated record built on the wrong assumptions. So the classifier needs its own confidence and its own fallback: below the bar, send the document to the general extractor rather than to the nearest specific one, and log the near miss so a new vendor format announces itself instead of quietly degrading. The subtler trap is that in a schema-prompted pipeline the schema is the prompt. Field names and their descriptions are the instruction the VLM reads, so renaming amount_due to read better for the engineers downstream, or sharpening a description to help them, is a model change wearing a data-contract costume — extraction moves on documents nobody touched. Treat a schema edit like a prompt edit and run it against a held-out set before it ships. And give absence a representation of its own, so a field the extractor looked for and could not find reads differently from one it was never asked to look for; a bare null says both, and only one of them is the document's fault.

  • templatefixed forms
  • ML/VLMvaried docs → schema
  • classify + routeper doc type

What the new pieces do

Extractionservice
Turns text + layout into structured fields and tables — via templates, an ML model, or a VLM reading the doc directly.

Step 6 · Is it right?

Validation & confidence

Extraction gives you values — but some are misread, ambiguous, or (with an LLM extractor) hallucinated. When this data feeds payments or records, a confidently-wrong field is dangerous. How do you know which values to trust?

ExtractionVLM / modelValidationschema · confidenceStructured OutJSON · records
New in this step: Validation, Structured Out.

Extracted fields may be misread or hallucinated. How do you know which to trust?

  1. Check each field against its expected type/format (dates, currency, IDs), cross-check with business rules (line items sum to the total, invoice number matches a pattern), and attach a confidence score. Fields that fail checks or score low are flagged rather than trusted — catching misreads and hallucinated values before they reach downstream systems.

  2. Even accurate models misread bad scans and can hallucinate field values, and downstream use (payments/records) makes a wrong value costly. You must validate and score confidence, not blindly trust.

  3. Re-running can help but doesn't catch systematic errors and doubles cost. The robust approach is schema/rule validation plus confidence scoring (and human review for low confidence).

Validate every extracted value: check type/format (a date is a date, currency parses, an ID matches its pattern), apply business rules (line items sum to the total, required fields present), and cross-check across the document. Attach a confidence score to each field. Values that fail a check or score low are flagged, not trusted — this is what catches OCR misreads and, critically, LLM-hallucinated values before they reach payments, records, or contracts.

Why this piece earns its place

The word confidence hides the hardest question on this page: where does the number come from? An OCR engine reports a per-character probability. A tagging model reports a span probability. A VLM emitting JSON reports token logprobs, which are a weak flag at best — they describe how sure the model was of its next token, not whether the value is on the page, and they are uncalibrated, sitting high on invented ones. So in a VLM pipeline the score is something you manufacture: rule outcomes; how the field has behaved on documents from this source before, where a vendor's reference matched one pattern for years and abruptly does not; and disagreement between two unlike extractors. That last one is the re-run option this step's prediction rejects, with half the objection answered — unlike extractors disagree where a repeated one agrees with itself, so it does see systematic error — but the doubled cost stands, so it belongs on a sampled slice or on the handful of fields that move money. Whichever you build, calibrate it against what reviewers actually found, or the threshold downstream is a number with no units. And note that format checks indict a field while cross-field rules indict a record: line items failing to sum names no culprit, and a queue that can only flag fields will pick one arbitrarily and send the reviewer to the wrong place.

  • schematype/format checks
  • rulestotals/patterns cross-check
  • confidenceper field

What the new pieces do

Validationservice
Checks extracted values against schema/format/business rules, assigns confidence, and flags anything doubtful.
Structured Outdata
The result: clean structured data (fields, tables) ready to feed databases, payments, or downstream systems.

Step 7 · Humans on the hard cases

Human-in-the-loop

Some documents are genuinely hard — awful scans, handwriting, unusual layouts — and full automation would either error out or produce wrong data. You can't accept mistakes on critical records, but you also can't review everything by hand. How do you balance automation and accuracy?

Validationschema · confidenceHuman Reviewlow-confidence
New in this step: Human Review.

Use confidence-based human-in-the-loop: auto-accept high-confidence extractions, and route low-confidence ones (or specific critical fields) to a human reviewer who corrects them. This keeps automation high while guaranteeing accuracy where it matters. Crucially, close the feedback loop: human corrections become labeled data that improves the models, so the share needing review shrinks over time. You automate the easy majority and spend human attention only where confidence is low.

Why this piece earns its place

The threshold has a blind spot built into its shape: everything above it is unmeasured by construction. Reviewers only ever generate ground truth for documents that fell below the bar, so the errors you can count are the ones you already caught, while the auto-accepted stream — the part that actually reaches payments — produces no signal at all. Its error rate looks like zero because nothing is looking at it. Sample it: route a small random slice of high-confidence extractions through review anyway, marked as an audit, and you get the false-accept rate the threshold is supposed to be buying you. The flywheel deserves the same skepticism. Corrections are a biased label set by definition, describing only the hard tail, so training on corrections alone drags the model toward the difficult cases and can quietly cost accuracy on the easy majority you never watch. Mix them with sampled ordinary documents, and keep a frozen evaluation set the review queue never feeds.

  • high confauto-accept
  • low confhuman review
  • corrections→ retrain models

What the new pieces do

Human Reviewclient
A review queue for low-confidence extractions; human corrections become labels that improve the models.

Step 8 · The sharp edges

Scans, tables, hallucination & PII

Real document processing hits hard corners: terrible scans and handwriting, endlessly varied layouts, tables spanning pages, LLM hallucination of field values, and sensitive PII/compliance.

DocumentsDoc AI ServicePreprocess + OCRExtractionValidationLayoutStructured OutHuman Review
The system as it stands at this step. · swipe to pan the diagram

Improve bad inputs with preprocessing and robust/handwriting-capable models, and lean on human review when quality is too low. Handle varied layouts with document classification + routing and layout-general models rather than one brittle template. Manage multi-page tables by stitching rows across pages. Guard against hallucination: constrain extractors to ground each field in the document (return the source location/box), and validate — never let a VLM invent a value with no evidence. Treat documents as sensitive: PII redaction, access control, retention, and audit trails for compliance. And run it as an async batch pipeline that scales across document types.

Why this piece earns its place

The compliance problem that sinks these projects is not redaction, it is copies. By the time one document reaches structured output it exists as the original upload, a cleaned image, an OCR text blob, a layout artifact, a cached render in the review queue, and — if the extractor is a hosted model — a request body on somebody else's infrastructure. Each of those is the document. A deletion request has to reach all of them, and the one teams forget is the debugging trail: the stored prompts and responses that make a bad extraction diagnosable are full-text copies of the most sensitive pages you hold. Decide that log's retention window while you are building it, not when legal asks. Which jurisdiction the hosted extractor runs in, and whether its provider retains inputs, are contract questions before they are architecture ones. And note the ordering constraint: you cannot redact what you have not located, so redaction runs after reading, off the same boxes, and the unredacted stage still happened.

You did it

You just designed a document AI pipeline.

DocumentsDoc AI ServicePreprocess + OCRExtractionValidationLayoutStructured OutHuman Review
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • Plain OCR gives characters but flattens the 2D layout — text is not structured data.
  • Run a pipeline: ingest → preprocess/OCR → layout → extraction → validation → structured output.
  • Preprocess then OCR to get located text (words + bounding-box coordinates).
  • Layout analysis recovers 2D structure (tables, key-value pairs) — the crux, via LayoutLM-style models or a VLM.
  • Extract with templates (fixed forms), ML, or a VLM outputting schema JSON; classify + route by doc type.
  • Validate against schema/rules and score confidence to catch misreads and hallucinated fields.
  • Route low-confidence cases to human review; corrections retrain the models and raise the automation rate.

Deep cut · 15:02

Every character right. The total still wrong.

The interactive build above lays out a document AI pipeline: intake and preprocessing, OCR, layout understanding, template and model extraction, validation with confidence, and human review. The film zooms into the one step plain OCR skips: keeping where each word sat. Juno runs a plant nursery. Clack, her reading machine, types every word of each invoice onto a ribbon, and a rule card takes the next number after “total due”. Then Marsh and Sons print a two-column invoice, the ribbon reads straight across both columns, and Juno pays £4,471 for £54 of seed.

  • See the wreck: a page has two directions and a ribbon has one. Flatten it and labels drift away from their values while every character stays correct. Clack prints “100% read”, and it is true. The order is what broke.
  • Take it into the interview: keep bounding boxes, rebuild the layout before extracting, send known layouts to cheap templates and new ones to a layout model, keep a trail from every value back to where it sat, check the page against its own sums, score confidence, and route the doubtful pages to a person whose fixes become training examples. Then name the bill: layout models cost more, templates break on a redesign, vision models can invent a tidy wrong number, and the confidence threshold trades a person’s time against money paid out wrongly.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. Why isn't OCR alone enough to turn a document into structured data?

    Because OCR solves character recognition, not document understanding, and those are different problems. OCR reliably reads the characters on a page and can give you the full text, but in doing so it flattens the inherently 2D page into a linear stream of text, discarding the spatial relationships that actually carry the meaning you need. Structured data is about knowing which piece of text is a field label versus its value, which numbers belong to which cell of which table row and column, what's a header versus a line item — and all of that is encoded in position and layout, not in the characters themselves. For example, OCR can perfectly read "4471", but knowing that "4471" is the invoice number depends entirely on where it sits relative to the label "Invoice #", which the flattened text stream loses. So the raw text of a document is not the same as its structured data; producing fields and tables requires understanding the layout — the spatial arrangement — and extracting structure from it, which is why document AI adds layout analysis and extraction stages on top of OCR rather than treating OCR's output as the answer.

  2. Why is layout analysis the crux of the pipeline?

    Because it recovers exactly the structure that OCR throws away, and that structure is where the meaning lives. After OCR you have located text — every word with its bounding-box coordinates — but a form, a table, and a paragraph all need to be interpreted completely differently, and simply sorting the text into reading order (top-to-bottom, left-to-right) mixes table cells together and separates labels from their values, destroying the very relationships you're trying to extract. Layout analysis instead models the page in two dimensions: it detects regions like headers and blocks, identifies tables and their row/column/cell grid, and infers key-value relationships by figuring out which label spatially owns which value. Modern approaches do this either with layout-aware models such as the LayoutLM family, which fuse the text, its 2D position, and the page image so the model can reason that "this number is in the total row," or with a vision-language model that reads the page image directly and perceives the layout natively. Either way, the principle is that position is a first-class feature, not noise — treating a document as text plus 2D position plus image is what turns a jumble of recognized characters into an understood document, which is why this stage is the pivotal one that makes structured extraction possible.

  3. When do you use templates versus ML/VLM extraction?

    You match the method to how varied the documents are. Templates and rules work well for fixed layouts — a form that is always laid out identically — where you can extract fields by their known position or by regex patterns; this is cheap, exact, and predictable, but brittle, breaking as soon as the layout changes or a new vendor's format appears. ML models, particularly layout-aware ones, handle varied documents by learning to tag and extract fields across different formats rather than relying on a fixed position, which generalizes far better but requires training data and still needs validation. Increasingly, the dominant approach is to use a vision-language model or LLM that reads the document (its image and/or OCR text) and directly outputs structured JSON conforming to a target schema you specify; this is remarkably flexible across document types with little per-template engineering, but it can be wrong or even hallucinate values, so it must be paired with validation. In practice, pipelines often first classify the document type and then route each document to the extractor best suited to it — templates for the truly fixed forms, learned models or a schema-prompted VLM for the varied ones — so you get exactness where layouts are stable and generality where they aren't, rather than forcing one approach onto everything.

  4. Why is validation with confidence scoring essential, especially with LLM/VLM extractors?

    Because extracted values are not automatically trustworthy, and the consequences of a wrong value are often severe. Extraction can misread characters on a bad scan, be genuinely ambiguous about which value a label owns, and — critically when an LLM or VLM is doing the extraction — hallucinate a field value that looks plausible but has no basis in the document. When the structured output feeds payments, financial records, or contracts, a confidently-wrong field is more dangerous than a missing one, because it flows silently into a system that acts on it. Validation converts "the model said X" into "X passes our checks and we're N percent confident." You check each field against its expected type and format (a date parses as a date, currency is well-formed, an ID matches its known pattern), you apply business rules that exploit the document's internal consistency (line items should sum to the stated total, required fields must be present, cross-references should agree), and you attach a confidence score to each field. Anything that fails a check or scores low is flagged rather than trusted, which catches both OCR misreads and hallucinated values before they reach downstream systems. Those confidence scores are also what make the next stage — routing low-confidence cases to human review — possible, so validation is both a safety net and the control signal for automation.

  5. How does human-in-the-loop make the system both scalable and trustworthy over time?

    It uses the confidence score as a dial that routes work between full automation and human judgment, so you get automation on the easy majority and accuracy on the hard minority without having to choose one or the other. High-confidence extractions — the bulk of typical document volume — are auto-accepted and flow straight through, giving you scale, while low-confidence extractions (or specific critical fields that always warrant a check) are routed to a human reviewer who corrects them, guaranteeing accuracy exactly where the model is unsure or the stakes are high. You can't review everything by hand (that defeats the purpose) and you can't accept errors on critical records (that's unsafe), and confidence-gated routing resolves this tension by spending scarce human attention only where it's needed. The crucial second effect is the feedback loop: every human correction is a labeled example of the right answer for a case the model got wrong or was unsure about, and feeding those corrections back to retrain the models steadily improves them, which shrinks the fraction of documents that fall below the confidence threshold. Over time this becomes a flywheel — the automation rate rises, the review burden falls, and the system gets more accurate on exactly the kinds of documents it used to struggle with — so it's simultaneously scalable now and improving continuously.

Check yourself — the answers, and why

Nine steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. Plain OCR isn't enough because it…

    Structured data lives in the spatial layout (labels/values, table cells) OCR discards.

  2. OCR in this pipeline outputs…

    Positions are the bridge from characters to structure; layout and extraction depend on where text is.

  3. Layout analysis recovers structure by…

    Position is a feature; LayoutLM-style models (text+position+image) or a VLM recover what OCR flattened.

  4. Validation + confidence exists to…

    Never trust blindly; cross-check totals/patterns and flag low-confidence values before downstream use.

  5. Human-in-the-loop is gated by…

    Automate the easy majority, review the hard minority, and feed corrections back to raise the automation rate.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Ingest documents: take messy PDFs, scans and forms and turn them into clean structured data — {vendor, invoice_no, total, line_items[]}.
  • Read the page: OCR the pixels into text plus the bounding-box coordinates of every word on the page.
  • Understand layout: recover the 2D structure — tables, columns, and which label owns which value.
  • Extract to a schema: produce the actual fields and tables, via template, ML model, or a VLM emitting JSON.
  • Validate & review: score confidence, catch misreads and hallucinations, and route doubtful cases to a human.

The qualities that shape everything

Each one names the mechanism that buys it.

Structured fields, not just a photo of the page
Layout analysis models the page in 2D — detecting regions, table rows/columns, and which label owns which value — recovering the structure OCR flattens.
Reliable text off messy scans
Preprocess (deskew, denoise, contrast, rotation) then OCR, keeping the bounding-box coordinates of every word so "reading" can become "understanding."
Errors you can locate, not a black box
Decompose into distinct stages — OCR handles pixels, layout handles structure, extraction handles meaning, validation handles correctness — so each uses the right technique and you can measure and route by confidence.
Generalize from fixed forms to wildly varied invoices
Classify the document type first, then route: templates/regex for fixed layouts, layout-aware ML or a schema-prompted VLM emitting JSON for the varied ones.
Never let a confidently-wrong field through
Validate every value against schema/format and business rules (line items sum to the total), attach a per-field confidence score, and flag anything that fails or scores low.
Scale automation without accepting mistakes
Confidence gates a human: auto-accept high-confidence extractions, route low-confidence ones to a reviewer, and feed corrections back as labels that retrain the models.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Layout understanding on top of OCR over treating OCR text as the answer

OCR reads characters perfectly but flattens the 2D page into a linear stream, losing which text is a label vs a value and which numbers belong to which table cell. Knowing "4471" is the invoice number depends on where it sits relative to its label — so you need layout, not just the text.

Layout-aware models (LayoutLM / a VLM) over sorting text into reading order

Reading top-to-bottom, left-to-right is exactly what mixes table cells together and separates labels from their values. Modeling the page in 2D — text plus position plus image — recovers the regions, tables and key-value links a linear reading order destroys.

Schema + business-rule validation with confidence over trusting the extractor because modern models are accurate

Even accurate models misread bad scans and LLM extractors hallucinate plausible-but-wrong values, and a confidently-wrong field feeding payments is worse than a missing one. Type/format checks, cross-checks like line items summing to the total, and a per-field score catch it; blind trust does not.

Classify + route to the right extractor over one brittle template for every document

Templates are cheap and exact on fixed forms but break the moment a new vendor’s layout appears; ML and VLMs generalize across formats but can hallucinate. Classifying the doc type and routing — template for fixed, schema-prompted VLM for varied — gets exactness where layouts are stable and generality where they are not.

Confidence-gated human review over either full automation or reviewing every document

Auto-accepting everything ships hallucinated fields on the hard cases; reviewing everything by hand defeats the automation. Gating on the confidence score auto-processes the easy majority and spends human attention only on the low-confidence minority — and those corrections retrain the models so the review share shrinks.

The answer, out loud

What a strong answer to “Design a Document AI Pipeline” sounds like, first question to last trade-off. It is about 6 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0-3 min

    Say what the output actually is

    Before I draw anything I want to name the output, because it decides the whole design. We're taking invoices, forms, contracts, receipts — scanned, photographed, wildly varied — and producing clean structured data: vendor, invoice number, total, the line items. Not a text dump. That distinction is the whole problem. The tempting read is that this is an OCR project and OCR is a solved problem, so we're mostly done. It isn't, and I'd push back on that early, because everything hard here sits after the characters have already been read correctly.

  2. 3-8 min

    Reading is not understanding

    So the first thing I'd say out loud is that OCR gives me characters and throws away the page. It flattens two dimensions into one stream, and the meaning I need was in the geometry — which text is a label, which is its value, which number belongs to which cell. OCR can read 4471 perfectly and still not tell me it's the invoice number, because that fact lives in where it sits relative to its label. So the pipeline has to understand layout, not just recognise text.

    Built in step 1: Text is not structure
  3. 8-14 min

    Stages, because the failures differ

    I'd draw this as stages rather than one box: ingest, preprocess and OCR, layout analysis, extraction, validation, structured output, with a human review path hanging off validation. The reason isn't tidiness — it's that each stage fails differently and gets fixed differently. OCR handles pixels, layout handles structure, extraction handles meaning, validation handles correctness. Collapse them into one call that reads the document and I lose the ability to say where a wrong total came from, and I lose the confidence signal I need at the end.

    Built in step 2: Ingest → understand → extract → validate
  4. 14-18 min

    Get the text off the page, with positions

    The first real stage is preprocessing and OCR. Deskew, denoise, fix contrast and rotation, then read — and crucially, keep the bounding box of every word, not just the words. Those coordinates are the bridge. Everything downstream, layout and extraction both, depends on where text is and not only on what it says. I'd also clean the image before reading rather than patch afterwards, because OCR errors cascade: bad pixels give bad characters, and no later stage can recover a character that was never read.

    Built in step 3: Preprocessing & OCR
  5. 18-25 min

    Layout is the crux

    Then the pivotal step. I'd model the page in two dimensions — regions, tables with real rows and columns, and key-value links saying which label owns which value. The wrong instinct is to sort the text top-to-bottom, left-to-right and read it as a paragraph, and that is precisely what mixes table cells together and separates labels from their values. I'd reach for a layout-aware model that takes text, position and the image together, LayoutLM-style, or a vision-language model that sees the page directly. Either way the principle is that position is a feature, not noise.

    Built in step 4: Layout analysis
  6. 25-31 min

    Match the extractor to the variety

    For extraction I'd classify the document type first and then route, because one approach doesn't fit everything. A fixed form that never changes is cheapest handled by a template — extract by position or regex, exact and predictable, and brittle the day the layout moves. Varied documents need a learned model, or a VLM prompted with the target schema that emits JSON directly, which is what I'd default to for the long tail of vendor invoices. The price of that flexibility is that it can be confidently wrong, which is exactly why the next stage isn't optional.

    Built in step 5: Extraction: templates vs ML vs VLM
  7. 31-38 min

    Never trust the extractor

    So I'd validate everything. Type and format first — a date parses as a date, currency is well-formed, an ID matches its pattern. Then business rules, which are the strong ones, because documents are internally consistent: line items should sum to the stated total, required fields should be present. And a confidence score per field, so anything that fails a check or scores low is flagged rather than trusted. That catches an OCR misread, and it's the only thing that catches a value the VLM invented — which is the failure I'd worry about most when this output feeds payments.

    Built in step 6: Validation & confidence
  8. 38-43 min

    Spend humans where confidence is low

    The confidence score then gates a human. Auto-accept above the threshold, route below it to a reviewer, and always route the fields where a mistake is expensive. I can't review everything by hand, because that defeats the automation, and I can't accept errors on records that feed contracts. Gating is what resolves that. And I'd close the loop: every correction is a labelled example of a case the model got wrong, so feeding them back shrinks the share of documents that falls below the threshold over time.

    Built in step 7: Human-in-the-loop
  9. 43-45 min

    The trade-off, and what I would do next

    So the trade-off I'd name is automation against trust, and the confidence threshold is where I set it — move it up and I'm buying accuracy with reviewer time, move it down and I'm buying throughput with risk. With more time I'd go at the sharp edges: handwriting and genuinely bad scans, tables that span pages and need stitching, forcing the extractor to ground each field in a location on the document so a hallucinated value has nowhere to hide, and the compliance layer — redaction, access control, retention, audit — because these are somebody's private documents.

What this teaches

Learn AI system design by building a document AI / intelligent document processing pipeline that turns PDFs, scans and forms into structured data step by step. An interactive guide covering why plain OCR is not enough, preprocessing and OCR, layout understanding, template vs ML/VLM extraction, validation and confidence, human-in-the-loop review, and the unhappy paths (bad scans, varied layouts, hallucinated fields, PII).

Key takeaways

  • Plain OCR gives characters but flattens the 2D layout — text is not structured data.
  • Run a pipeline: ingest → preprocess/OCR → layout → extraction → validation → structured output.
  • Preprocess then OCR to get located text (words + bounding-box coordinates).
  • Layout analysis recovers 2D structure (tables, key-value pairs) — the crux, via LayoutLM-style models or a VLM.
  • Extract with templates (fixed forms), ML, or a VLM outputting schema JSON; classify + route by doc type.
  • Validate against schema/rules and score confidence to catch misreads and hallucinated fields.
  • Route low-confidence cases to human review; corrections retrain the models and raise the automation rate.

Concepts covered

  • What is document AI?
  • Text is not structure
  • Ingest → understand → extract → validate
  • Preprocessing & OCR
  • Layout analysis
  • Extraction: templates vs ML vs VLM
  • Validation & confidence
  • Human-in-the-loop
  • Scans, tables, hallucination & PII
RUN IT YOURSELF

The extraction that reads fluently and is wrong

One two-column page as OCR returns it — a box per word — read two ways in your browser: sorted by vertical position, and sorted inside columns found from the geometry. There are no OCR errors in this page, so every difference printed below is reading order alone. Change COLUMN_GAP, hit Run, and watch the fix collapse onto the failure.

HOW TO READ THE CODE — 5 IDEAS
  1. Step 4 names the losing option out loud — “sort the text top-to-bottom, left-to-right and read it as a paragraph”. Run it and 6 of 9 sentences are destroyed; the 3 survivors are exactly the 3 that fit on one line.
  2. Every character was read perfectly. Step 1’s point, measured: the hard part sits after recognition, so grading OCR on characters says nothing about this (steps 1, 3).
  3. The fix is not a better sorter — it is a region. find_columns projects the word boxes onto the x-axis and reports whatever whitespace survives; the same line grouper then runs inside each column (step 4).
  4. Both extractions hold the identical multiset of words, so the y-sorted one raises nothing, parses, and passes any test that greps the text for a value — step 1’s “contains 4471 somewhere” trap, printed.
  5. Downstream it is worse than silent. A same-column run in the y-sorted stream is one line — longest 8 words — so no 24-word chunk fits inside two of them and every full chunk interleaves, embedding a blend of two unrelated passages. Drop COLUMN_GAP under MIN_GUTTER and the detector sees one column — which is also what one full-width heading does to a plain x-projection.
CPython · WebAssembly
built to read the invoice, not just photograph it — make the calls, flatten the layout, run the gauntlet.
Finished this one? 0 / 65 AI System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs