RAG with PDFs
Learn how to turn PDF files into searchable knowledge for a RAG applicationβfrom loading and extracting text to chunking, embeddings, retrieval, and grounded answers.
By the end of this lesson, you will be able to:
- Understand where PDFs fit into a RAG pipeline.
- Extract text from a PDF and inspect the result.
- Split extracted text into retrieval-friendly chunks.
- Create embeddings and keep source metadata with each chunk.
- Retrieve relevant PDF chunks for a user question.
- Build a grounded context for an LLM.
- Recognize common PDF extraction problems and production considerations.
Why Use PDFs in RAG?
Companies store important knowledge in PDFs: product manuals, policies, reports, guides, invoices, research papers, and internal documentation. RAG lets an application retrieve the relevant parts instead of sending an entire PDF to the model.
The PDF-to-RAG Pipeline
Think of PDF RAG as two connected stages: ingestion prepares the files, while query time retrieves evidence for each question.
1. Load PDF
Read the file and identify pages or sections.
2. Extract text
Convert page content into usable text.
3. Clean + chunk
Remove noise and create useful retrieval units.
4. Embed + store
Create vectors and preserve page/source metadata.
5. Embed question
Represent the user's question in the same vector space.
6. Retrieve
Find the most relevant PDF chunks.
7. Build context
Combine selected evidence into a concise model input.
8. Generate
Ask the LLM to answer from the supplied evidence.
Step 1: Load a PDF
Python has several PDF libraries. For a simple text-based PDF, pypdf is a convenient teaching example.
from pypdf import PdfReader
reader = PdfReader("company-handbook.pdf")
print("Pages:", len(reader.pages))The filename is an example. In a real application, the PDF may come from an upload, object storage, a document-management system, or another trusted source.
Step 2: Extract Text Page by Page
Keep page boundaries when possible. Page numbers become valuable metadata when you need to show where an answer came from.
from pypdf import PdfReader
reader = PdfReader("company-handbook.pdf")
pages = []
for page_number, page in enumerate(reader.pages, start=1):
text = page.extract_text() or ""
pages.append({
"page": page_number,
"text": text.strip(),
})
for item in pages[:2]:
print("Page", item["page"])
print(item["text"][:500])Step 3: Check What Was Extracted
Do not immediately embed extracted text. First inspect it. A PDF can look perfect to a human while producing poor machine-readable text.
Sentences appear in the correct order and important headings are preserved.
Columns are interleaved, words are split, or table cells appear in the wrong order.
The document may need OCR before normal text chunking can work.
Important information may exist only inside an image and need a separate strategy.
Step 4: Clean the Extracted Text
Basic cleanup can remove repeated whitespace while keeping the actual content. Be careful not to remove meaningful formatting or identifiers.
import re
def clean_text(text):
text = text.replace("\u00a0", " ")
text = re.sub(r"[ \t]+", " ", text)
text = re.sub(r"\n{3,}", "\n\n", text)
return text.strip()
cleaned_pages = [
{"page": item["page"], "text": clean_text(item["text"])}
for item in pages
]Cleaning should be evaluated against real PDFs. Aggressive cleanup can destroy useful structure.
Step 5: Chunk the PDF Text
Pages are not always good retrieval units. A page may contain several unrelated topics, while a section may continue across multiple pages. Chunk according to the information you want to retrieve.
Whole PDF
Large context, unrelated information, and inefficient retrieval.
Meaningful chunks
Focused passages with source and page metadata.
def chunk_text(text, chunk_size=500):
words = text.split()
return [
" ".join(words[i:i + chunk_size])
for i in range(0, len(words), chunk_size)
]
chunks = []
for page in cleaned_pages:
for chunk_index, chunk in enumerate(chunk_text(page["text"]), start=1):
if chunk:
chunks.append({
"text": chunk,
"page": page["page"],
"chunk": chunk_index,
})
print("Chunks:", len(chunks))This fixed word window is only a teaching example. Structure-aware or recursive chunking may work better for real documents.
Step 6: Keep PDF Metadata
Every chunk should remain traceable to its source. At minimum, keep the document identifier and page number. You can also store section, title, language, version, tenant, or access information.
Step 7: Create Embeddings
Convert each chunk into an embedding so a user's question can be compared with the PDF knowledge semantically.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
texts = [item["text"] for item in chunks]
vectors = model.encode(texts)
print("Chunks:", len(texts))
print("Vector shape:", vectors.shape)The model shown here is a teaching example. For production, evaluate an embedding model against your document language, query patterns, and retrieval benchmarks.
Step 8: Retrieve From the PDF
At query time, embed the question and rank PDF chunks by similarity. The top results become candidate evidence.
from numpy import dot
from numpy.linalg import norm
query = "How many days of annual leave are provided?"
query_vector = model.encode([query])[0]
def cosine(a, b):
denominator = norm(a) * norm(b)
return 0.0 if denominator == 0 else dot(a, b) / denominator
ranked = sorted(
zip(chunks, vectors),
key=lambda item: cosine(query_vector, item[1]),
reverse=True,
)
top_k = ranked[:3]
for item, vector in top_k:
print(f"Page {item['page']} | score={cosine(query_vector, vector):.3f}")
print(item["text"][:300])For larger collections, use a vector index or vector database instead of comparing every vector in Python.
Step 9: Build the RAG Context
Do not send the entire PDF to the LLM. Combine only the selected evidence and include enough source information to trace it.
context_parts = []
for item, vector in top_k:
context_parts.append(
f"[Source: company-handbook.pdf, page {item['page']}]\n"
f"{item['text']}"
)
context = "\n\n".join(context_parts)
prompt = f"""Answer the question using only the supplied PDF context.
If the context does not contain the answer, say that the information was not found.
Context:
{context}
Question:
{query}
"""
print(prompt)Step 10: Generate the Answer
The final stage sends the question plus retrieved PDF evidence to an LLM. The LLM is responsible for explaining the evidence, not for replacing the retrieval system.
A production application can call its chosen LLM API here. The exact provider is independent of the PDF retrieval architecture.
PDF Tables Are Different
Tables are a common reason a PDF RAG system performs poorly. Extracted text may lose rows, columns, headers, or relationships between values.
Standard text extraction may work well.
Use a table-aware extraction strategy when relationships matter.
OCR may be required before retrieval.
Text extraction alone may not capture the information represented by the graphic.
Scanned PDFs and OCR
A scanned PDF may contain images of pages rather than selectable text. In that case, normal PDF text extraction can return little or no useful content.
OCR introduces its own errors, so important documents should be tested after extraction rather than assuming the OCR output is perfect.
When PDF RAG Works Well
Product support
Retrieve installation or troubleshooting instructions.
Employee Q&A
Find the relevant policy section and page.
Research assistant
Retrieve evidence from long reports and papers.
Knowledge assistant
Answer questions using controlled documentation.
Document search
Find relevant clauses when permissions and extraction quality are handled carefully.
How-to assistant
Retrieve the section that explains a specific procedure.
PDF RAG vs Uploading the Whole PDF
- Can become very large
- May include irrelevant pages
- Higher context cost
- Harder to trace the exact evidence
- Retrieve only relevant chunks
- Works across large collections
- Supports metadata and filtering
- Can return page-level sources
For a tiny document, direct document input can be simpler. RAG becomes more useful when knowledge is large, distributed, changing, or needs retrieval controls.
Common PDF RAG Problems
The source text is already corrupted before retrieval begins.
Related content can be separated or unrelated content can be combined.
You lose useful traceability and citation information.
Column relationships can disappear during extraction.
Old PDF versions can produce outdated answers.
A user must not retrieve a PDF or chunk they are not authorized to see.
Production Considerations
Validate extraction
Test paragraphs, tables, pages, headers, and OCR output.
Evaluate search
Measure whether the correct PDF chunks are retrieved.
Track versions
Re-index changed documents and retire stale versions.
Filter access
Apply authorization before returning protected evidence.
Use indexes
Use vector databases or indexes as collections grow.
Log sources
Record retrieval scores, document IDs, pages, latency, and failures.
Improve PDF RAG Step by Step
Improve extraction
Choose tools based on PDF structure rather than using one parser for every file.
Improve chunking
Use headings, sections, paragraphs, and meaningful boundaries.
Improve retrieval
Use vector search, filters, hybrid search, or reranking where useful.
Improve citations
Keep document and page metadata through the entire pipeline.
Evaluate answers
Test retrieval quality and whether responses stay grounded.
Monitor documents
Track versions, freshness, permissions, latency, and cost.
Practice: Build a PDF RAG Plan
You have 100 company policy PDFs. A user asks: βWhat is the travel reimbursement limit for domestic trips?β
Design the retrieval flow
Write down: 1) how you would extract text, 2) how you would chunk it, 3) what metadata you would keep, 4) how you would retrieve the best chunks, and 5) how you would provide page-level evidence to the LLM.
Quick Quiz
1. Why extract PDF text before embedding?
Embeddings need usable text. Extraction converts the PDF content into a representation the retrieval pipeline can process.
2. Why keep page numbers?
They provide traceability and make it possible to show where retrieved evidence came from.
3. Why can PDF RAG fail even when retrieval is configured correctly?
The PDF may have poor extraction, broken tables, missing OCR, bad chunking, stale content, or unauthorized filtering.
4. What should happen when the retrieved context does not answer the question?
The application should instruct the model not to invent an answer and to state that the information was not found or is insufficient.
5. Why are tables challenging?
Text extraction can lose row and column relationships that are important to the meaning of the data.
6. What is OCR used for?
OCR converts text contained in page images into machine-readable text.
30-Second Recap
Read the PDF.
Get usable text.
Check extraction quality.
Remove safe noise.
Create retrieval units.
Create vectors.
Find relevant passages.
Answer from evidence.
Key Takeaways
- PDFs are a common knowledge source for RAG applications.
- The PDF must first be converted into reliable, searchable content.
- Page-level metadata is valuable for citations, debugging, filtering, and traceability.
- Scanned PDFs may require OCR, while tables and visual content can need specialized processing.
- Chunking should follow retrieval goals and document structure, not simply page boundaries.
- RAG retrieves relevant PDF evidence instead of sending an entire document to the LLM.
- Security, freshness, extraction quality, retrieval quality, and evaluation matter in production.