Parsing PDFs with PyMuPDF4LLM
Most RAG tutorials start with plain text files. Real documents are PDFs with tables, headers, multi-column layouts, and broken words across page boundaries. If your parser loses that structure, your retrieval was doomed before the first embedding.
import pymupdf4llm
import docx
class DocumentParser:
"""Handles parsing of PDF (PyMuPDF4LLM), Docx, etc."""
@staticmethod
def parse_pdf(file_path: str) -> str:
"""Parse PDF using PyMuPDF4LLM (layout-aware markdown)."""
md_text = pymupdf4llm.to_markdown(file_path)
return md_text
@staticmethod
def parse_docx(file_path: str) -> str:
"""Parse DOCX file."""
doc = docx.Document(file_path)
return "\n\n".join([p.text for p in doc.paragraphs if p.text.strip()])PyMuPDF4LLM is the key call. It returns markdown with headers preserved, tables formatted, and reading order intact, which matters later when we split by header.
PyPDF2 gives you a wall of text with no structural signals. pdfplumber preserves layout but outputs raw positional data. PyMuPDF4LLM was designed specifically for LLM pipelines. It produces markdown, keeps headers as # and ##, formats tables, and preserves reading order across multi-column pages. That structure becomes the scaffold for smart chunking.
Quiz: Quiz
Loading practice…