Use case / LLM

Get Documents Ready for AI

Extract a document into clean, structured data that preserves reading order, headings, tables, and images, with positional bounding box data available for each object. The results are verifiable evidence objects ready to index, retrieve, cite and pass to your LLM or RAG pipeline.

GNN
Structured data
Positional data
Chunking
Verifiable Evidence Objects
Grounding
  • Source exactly where the answers come from in the document.
  • Ensure transparency and verifiability in your AI workflows.
Chunking for retrieval

Keep context small without losing structure

Chunking breaks a long Markdown document into focused passages that can be embedded and retrieved independently. PyMuPDF keeps the extracted text tied to its source page and position, so retrieved answers can retain useful provenance.

01

Start with a budget

Choose a maximum token count that fits your embedding model and retrieval window. Smaller chunks are more precise; larger chunks carry more context.

02

Keep provenance

Store each chunk's text with its page and position metadata from GNN layout analysis, so answers can link back to the original document.

03

Tune, then reassemble

Test retrieval quality at your target size. Reassemble adjacent chunks into a larger context window when a question needs more surrounding detail.

Chunk the document in both small & large sets

Use smaller chunks for precise retrieval, then reassemble them when the LLM needs a broader section to answer confidently.

The following code sample demonstrates this "small-to-big" retrieval pattern.

import pymupdf

cd = pymupdf.to_chunks("input.pdf", max_tokens=200) # 10 chunks
big = cd.reassemble_chunks(max_tokens=1200) # 2 chunks: c0 pages 1-3, c1 pages 4-6

# --- your code: replace with your retriever and LLM ---
def search(query):
    return "c3" # a small-chunk id is returned from your index

def llm(query, context, bboxes):
    return f"answer grounded in {len(context)} characters"
# --- end of your code ---

query = "Can you tell me about the construction process here?"
# from cd, the 200 token index with many small chunks
small = cd.get(search(query))

# "context" becomes the first large chunk that contains at least one source element
also present in small.
context = next(
    (b for b in big
    if set(small.metadata.element_ids)
    & set(b.metadata.element_ids)),
    None
)

# then send the large contextual chunk to the LLM
answer = llm(query, context.text, context.metadata.bboxes)
print("Answer:", answer)

# compare token counts for both small & big
print(small.id, small.metadata.token_count,
    small.metadata.page_start, small.metadata.page_end,
    "->",
    context.id, context.metadata.token_count,
    context.metadata.page_start, context.metadata.page_end)
# -> c3 117 1 1 -> c0 1093 1 3
Find out more

Preserve the layout, not just the text

See how PyMuPDF captures the spatial structure behind tables, columns, and positioned content.

Explore Layout
Extract as Markdown

One extraction step, usable everywhere

Generate a Markdown file your AI tooling can work with directly. Because the output remains human-readable, it is also easy to inspect, version, and debug.

import pymupdf

doc = pymupdf.open("annual-report.pdf")
markdown = doc.to_markdown()

with open("annual-report.md", "w", encoding="utf-8") as output:
  output.write(markdown)
PyMuPDF Logo

© 2026 Artifex Software Inc. All rights reserved.