--- id: ocr-documents title: OCR and Document Understanding code: OD subtitle: Train CTC OCR, pick a document stack, retrieve pages with MaxSim and approve fields against exact source spans. hue: 165 sources: phases/04-computer-vision/19-ocr-document-understanding, phases/12-multimodal-ai/22-document-diagram-understanding, phases/12-multimodal-ai/23-colpali-vision-native-rag, phases/19-capstone-projects/04-multimodal-document-qa, projects/document-extraction-desk source_hash: 31f050e1ba845909 --- ## Classical OCR pipeline type: architecture from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md ```arch node | img | 1,1 | Image | | client node | det | 2,1 | Text detection | DB, EAST, CRAFT | model node | box | 3,1 | Bounding boxes | word or line | store node | crop | 4,1 | Crop each region | fixed height | process node | rec | 4,2 | Recognition | CRNN + CTC | model node | txt | 3,2 | Text strings | | store node | lay | 2,2 | Layout ordering | reading order | process node | out | 1,2 | Reading-order text | | client edge | img | det | edge | det | box | edge | box | crop | edge | crop | rec | edge | rec | txt | edge | txt | lay | edge | lay | out | ``` ## Tasks in code type: task-table from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/04-computer-vision/19-ocr-document-understanding/code/main.py, phases/12-multimodal-ai/22-document-diagram-understanding/code/main.py, phases/12-multimodal-ai/23-colpali-vision-native-rag/code/main.py, phases/19-capstone-projects/04-multimodal-document-qa/code/main.py | Task | Code | |---|---| | CTC loss | `ctc_loss(log_probs, targets, ...)` | | Greedy CTC decode | `greedy_ctc_decode(log_probs, blank=0)` | | Line recogniser | `TinyCRNN(vocab_size=40, hidden=128, feat=32)` | | Production OCR | `PaddleOCR(lang="en").ocr(image_path)` | | LayoutLMv3 input | `layoutlm_input(tokens)` | | Donut JSON schema | `donut_schema("invoice")` | | Top-k pages by MaxSim | `retrieve(query, pages, k=3)` | ## Train a CRNN with CTC type: annotated-code lang: python from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/04-computer-vision/19-ocr-document-understanding/code/main.py ```python vocab = ["_"] + list("0123456789abcdefghijklmnopqrstuvwxyz") # blank at index 0 model = TinyCRNN(vocab_size=len(vocab)) opt = torch.optim.Adam(model.parameters(), lr=1e-3) imgs, targets, target_lens = build_batch(strings, vocab) # height 32 log_probs = model(imgs) # (W', N, vocab) input_lens = torch.full((8,), log_probs.size(0), dtype=torch.long) loss = F.ctc_loss(log_probs, targets, input_lens, target_lens, blank=0, reduction="mean", zero_infinity=True) opt.zero_grad(); loss.backward(); opt.step() # ~3 to ~0.2 in 200 steps ``` ## MaxSim late interaction type: annotated-code lang: python from: phases/12-multimodal-ai/23-colpali-vision-native-rag/code/main.py, phases/19-capstone-projects/04-multimodal-document-qa/code/main.py ```python def maxsim(query_tokens, patches): s = 0.0 for q in query_tokens: # one vector per query token best = max(cosine(q, p) for p in patches) # best page patch s += best # sum over query tokens return s scored = [(p.doc_id, maxsim(query.tokens, p.patches)) for p in pages] scored.sort(key=lambda x: -x[1]) # top-k pages idx = build_index(prune=True) # DocPruner on, 50% patches hits = idx.retrieve(q, k=3) ``` ## Commands type: command-table span: 2 from: projects/document-extraction-desk/README.md, projects/document-extraction-desk/solution/cli.py, phases/19-capstone-projects/04-multimodal-document-qa/code/ts/README.md, phases/19-capstone-projects/04-multimodal-document-qa/code/main.py | Command | What it does | |---|---| | `python3 cli.py sample.txt --schema schema.json --output output/review.html` | Builds the HTML review desk and a JSON report | | `--proposals ` | Loads external OCR or model candidates | | `--approve ` | Applies decisions downloaded from the HTML desk | | `python3 scripts/project_test.py document-extraction-desk --all --solution --strict` | Grades the reference solution | | `python main.py` | Runs the capstone MaxSim and DocPruner scaffold | | `npm start` | Runs the viewer self-check once and exits 0 | | `npm run serve` | Starts the viewer HTTP server on 127.0.0.1 | ## Vision-first document QA type: flow from: phases/19-capstone-projects/04-multimodal-document-qa/docs/en.md 1. **Ingest**: render each PDF page to a 1536x2048 PNG. Keep `{doc_id, page_num, image_path}`. 2. **Embed**: run ColQwen2.5-v0.2. Get ~2048 patch vectors of dim 128 per page. 3. **Prune**: DocPruner keeps the highest-signal half of the patches. 4. **Query**: embed query tokens. Run MaxSim. Return the top-k pages. 5. **Synthesize**: give the query and the top-5 page images to the VLM. Cite (doc_id, page). 6. **Evidence**: draw the cited bounding boxes as overlays in the viewer. 7. **OCR fallback**: run Nougat or dots.ocr on equation-dense pages. 8. **Eval**: report ViDoRe v3 nDCG@5 and M3DocVQA against OCR-then-text. ## Formulas and numbers type: concepts from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/12-multimodal-ai/23-colpali-vision-native-rag/docs/en.md - **CTC collapse**: merge repeats, then remove blanks. "h h h _ _ e e l l _ l l o _ _" gives "hello". - **CER**: Levenshtein distance divided by the reference length. WER is the same per word. - **MaxSim**: $\sum_i \max_j \cos(q_i, p_j)$ over query tokens $q_i$ and page patches $p_j$. - **ColPali storage**: 50 pages x 729 patches x 128 dims x 4 bytes = ~18 MB raw, ~2.3 MB after 8x PQ. - **Text-RAG storage**: 50 chunks x 768 dims x 4 bytes = ~150 kB. ColPali is ~120x more raw, ~15x after PQ. - **ViDoRe**: ColPali-v1 scores ~80% nDCG@5. Text-RAG scores ~50-60%. ## Defaults and limits type: defaults from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/19-capstone-projects/04-multimodal-document-qa/docs/en.md, projects/document-extraction-desk/solution/main.py | Setting | Default | Note | |---|---|---| | CER target | < 2% | On clean scans | | CRNN input height | 32 | CNN pools height to 1. Width is time | | Page render | 180 DPI | PyMuPDF in the capstone | | DocPruner | 50% | Under 0.5% accuracy loss | | Schema fields | 1 to 30 | Lowercase names, unique labels | | Document size | 100000 | Characters at most | | Candidates | 300 | Proposals at most per review | ## Pick a document stack type: concepts from: phases/12-multimodal-ai/22-document-diagram-understanding/docs/en.md, phases/12-multimodal-ai/23-colpali-vision-native-rag/docs/en.md, phases/04-computer-vision/19-ocr-document-understanding/docs/en.md - **Printed invoices at scale**: LayoutLMv3 + rules. Cost-efficient. - **Mixed, handwritten, forms**: VLM-native (PaliGemma 2 or Qwen2.5-VL). - **arXiv papers**: Nougat for math, a VLM for figures. - **Regulated**: OCR pipeline + VLM validator as a cross-check. - **Receipts with fixed structure**: fine-tune Donut. - **Pure-text documents**: text-RAG. It is simpler and uses less storage. - **Visually rich PDFs**: ColPali for quality, VisRAG for scale. ## Troubleshooting type: troubleshooting from: projects/document-extraction-desk/solution/main.py, projects/document-extraction-desk/solution/cli.py, projects/document-extraction-desk/stages/03-review-and-approve/docs/en.md, phases/12-multimodal-ai/22-document-diagram-understanding/docs/en.md, phases/12-multimodal-ai/23-colpali-vision-native-rag/docs/en.md | Symptom | Cause | Fix | |---|---|---| | "Approval belongs to another document version" | Text changed, `sourceSha256` differs | Review the new version again | | "Proposal does not match its exact source span" | Quote is not at `start`, `end` | Fix the offsets of the proposal | | "Use an ISO date: YYYY-MM-DD" | Date field text is not ISO | Correct the source text | | Field state is ambiguous | Two Seats quotes | Choose one span with `--approve` | | Donut fails on a paper | OCR-free models are specialists | Use Nougat for papers | | Chart data missing in RAG | OCR drops chart data | Embed page images with ColPali | ## Abbreviations type: glossary from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/12-multimodal-ai/22-document-diagram-understanding/docs/en.md, phases/12-multimodal-ai/23-colpali-vision-native-rag/docs/en.md - **CTC**: Connectionist Temporal Classification. Trains without per-timestep labels. - **CRNN**: conv features + BiLSTM + CTC. The 2015 baseline. - **VLM-OCR**: a vision-language model trained or prompted for OCR. - **DocVQA**: the document VQA standard. The most-cited score. - **ViDoRe**: Visual Document Retrieval Evaluation. Metric is nDCG@5. - **PQ**: product quantization. Shrinks storage ~8x. ## Questions type: qa from: phases/04-computer-vision/19-ocr-document-understanding/docs/en.md, phases/12-multimodal-ai/22-document-diagram-understanding/docs/en.md, phases/12-multimodal-ai/23-colpali-vision-native-rag/docs/en.md, projects/document-extraction-desk/README.md - **Why CTC?** It trains without character-level alignment. - **When do OCR pipelines still win?** Massive scan scale, deterministic failures, auditable output. - **Why MaxSim over a mean?** Each query token picks its best patch. Irrelevant patches do not wash it out. - **Do offsets prove the value is right?** No. They prove provenance. A reviewer confirms the field.