Parsing PDFs for RAG: from PyPDF to dots.ocr
The first link in the pipeline is the one nobody looks at: text extraction. Why not all PDFs are equal, four tools in order of power (and requirements), and three questions to pick the right one without wasting GPU time.
The video loads only if you ask: no request to YouTube before the click.
The video is in Italian; this page is the written version in English.
A carefully built RAG that answers badly. The first reaction is to blame the language model, the second the embeddings. Almost always the problem sits before both: at the moment the text is extracted from the PDFs. If parsing drops a table or shuffles the columns, nothing downstream can repair it. It is the classic garbage in, garbage out, and it counts double because the error goes into the database and stays there.
Not all PDFs are equal
A PDF can hold text in two ways that have nothing in common.
"Digital" PDF "Scanned" PDF
text is encoded as characters each page is an image
→ just read it → an OCR has to "look" at it
Digital PDFs are most modern books, papers and manuals: the text is already inside the file, you can select it with the mouse. Scanned PDFs are photocopies, old books, digitised paperwork: pixels, not letters. Then there are the mixed ones: native text for the body, but tables, formulas and charts pasted in as images. Those are the deceptive ones, because basic tools work on them “fine” and silently lose the part that mattered.
The practical rule that settles half the cases: open the PDF and try to select the text. If you can, the first level is enough.
Level 1: PyPDF and PyMuPDF
These are the foundations. Lightweight libraries, no models, instant: hundreds of pages per second.
from pypdf import PdfReader
reader = PdfReader("book.pdf")
for page in reader.pages:
text = page.extract_text()
PyMuPDF (fitz) does the same faster and adds extraction of images, links and metadata.
Neither does OCR, understands tables or recognises layout: on a digital PDF with linear text
they are excellent, on everything else they lose structure without saying so. The
knowledge bot built on game-design books uses
PyPDF and never needed anything more: 232 chapters, 5,234 chunks, digital PDFs.
Level 2: the specialists, Docling and Marker
When structure matters, you need tools that understand the page rather than read it.
Docling (IBM Research) combines two models: one recognises the layout (headings, paragraphs, tables, figures, footnotes), the other rebuilds tables cell by cell, merged and nested ones included. The number that stands out is table accuracy, 97.9%. It runs on CPU and on a Mac, about four seconds per page, and returns Markdown or JSON ready for chunking.
from docling.document_converter import DocumentConverter
result = DocumentConverter().convert("report.pdf")
markdown = result.document.export_to_markdown()
Marker (Datalab) is a complete OCR pipeline: base text, scanned-page recognition, layout, Markdown. Its strengths are mathematical formulas, converted to LaTeX, and languages: more than ninety. GPU optional, and it also runs on the accelerator of Apple Silicon Macs. If you work with scientific papers, this is the one.
Level 3: dots.ocr, one model for everything
Here the approach changes. Docling and Marker are pipelines: one model for layout, one for OCR, one for tables, chained. dots.ocr is a single vision-language model that looks at the page image and directly produces structured output: text, tables as HTML, formulas as LaTeX, even charts as SVG.
Pipeline: PDF → layout → OCR → tables → output (three models)
dots.ocr: PDF → VLM → output (just one)
On benchmarks it is state of the art, and on text and tables it beats some well-known commercial models. The price is hardware: it needs an NVIDIA GPU with at least 8 GB of memory, installation goes through CUDA, and it does not run on a Mac. It is the tool for a server that has to digest difficult scans in bulk, not for a laptop.
How to choose: three questions
| Question | If the answer is… | Then |
|---|---|---|
| What kind of PDF do I have? | Selectable text | PyPDF or PyMuPDF, and you are done |
| Complex tables, multi-column layout | Docling | |
| Formulas, scientific papers | Marker | |
| Hard scans, charts, all of the above | dots.ocr | |
| What hardware do I have? | CPU only, or a Mac | Docling or Marker |
| NVIDIA GPU | dots.ocr becomes an option | |
| What do I really need? | Fast, “good enough” extraction | The lowest level that works |
| Absolute fidelity of tables and formulas | The highest level the hardware can run |
Can the text be selected?
├── YES → PyPDF / PyMuPDF
└── NO, or tables and formulas are critical
├── NVIDIA GPU available? → dots.ocr
├── tables matter most → Docling (CPU/Mac)
├── formulas matter most → Marker (CPU/Mac/MPS)
└── general case without GPU → Docling
The typical mistake: one parser for all
You pick PyPDF because it is fast, try it on two clean PDFs, it works, and you run it on a thousand mixed company documents. The RAG answers badly and nobody understands why: the contract tables are gone, the report headers got mixed into the body, the charts became empty strings. Broken text went into the vector database, and the model quotes it with complete confidence.
The approach that works is a triage: classify documents before extracting them (digital, complex, scanned) and route each one to the parser it deserves. Not all to the most powerful: reprocessing a digital PDF with dots.ocr wastes hours and GPU time and improves nothing.
Where the field is going
2020-2023 modular pipelines: OCR → layout → post-processing
2024 integrated frameworks: Docling, Marker
2025+ unified models: one VLM looks at the page and does it all
The direction is clear: from chains of components to single models that understand the whole page. But it does not make the simple tools obsolete. For a digital PDF, PyPDF remains the smartest choice: no dependencies, no waiting, no model to download. It is worth asking whether the weakest link in your system is precisely the first one.
In short
| Concept | In one line |
|---|---|
| Why it matters | Badly extracted text enters the database and no model repairs it |
| The test to run first | If the PDF’s text can be selected, PyPDF or PyMuPDF is enough |
| Docling | Layout and tables (97.9%) on CPU and Mac |
| Marker | Formulas to LaTeX, 90+ languages, Mac too |
| dots.ocr | One model, top quality, but an NVIDIA GPU is mandatory |
| How to choose | PDF type, hardware, required precision; then a per-document triage |
- RAG
- OCR
- Docling
Related lessons
- What RAG is: letting a model read your documents
A model does not know your files. RAG lets it consult them at question time: search first, then answer. It is the difference between a closed-book and an open-book exam.
- Chunking: how documents get split
The most underrated choice in the whole RAG pipeline. What the system can find depends on how you cut the text: bad chunking wastes the best embedding model and the best LLM.
- Building a local RAG, from PDF to answer
The full pipeline on a single machine: extract the text from PDFs, index it, query it. With the places where it actually trips up and how to tell whether it is working.