Layout-aware parsing with PyMuPDF4LLM
Every vectorless pipeline starts the same way: turn the PDF into a structured representation that exposes headings and page boundaries. Most PDF libraries give you a flat stream of text. PyMuPDF4LLM gives you markdown with heading levels preserved, which is exactly what we need to build a tree.
# Clone the workshop
git clone https://github.com/learnwithparam/vectorless-rag
cd vectorless-rag
# One command to set up and run
make dev
# Or step by step
make setup
make runThe Makefile handles uv, dependency installation, env file creation, and the first run against the Bigtable paper.
import pymupdf4llm
# Method one: get full markdown for structure detection
full_md = pymupdf4llm.to_markdown(str(pdf_path))
# Method two: get page-indexed chunks for accurate pagination
page_chunks = pymupdf4llm.to_markdown(
str(pdf_path),
page_chunks=True,
write_images=False,
embed_images=False,
)
# Build a page-to-text index we can lookup later
page_contents = {i + 1: chunk["text"] for i, chunk in enumerate(page_chunks)}
total_pages = len(page_chunks)We call PyMuPDF4LLM twice. The first call gives us a single markdown string where headings become hash-prefixed lines. The second returns per-page chunks that let us match content back to a specific page number.
Why two parsing calls? The full markdown is what we scan for headings to build the tree hierarchy. The per-page chunks are what we use to assign accurate page ranges to each node. Without the second call, our citations would be rough estimates based on line position.
Quiz: Quiz
Loading practice…