LESSON 54 Β· RAG

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.

40 min readβ€’Beginnerβ€’Generative AI

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.
1

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.

PDFSource document
β†’
ExtractText + structure
β†’
ChunkRetrieval units
β†’
EmbedVectors
QuestionUser query
β†’
RetrieveRelevant chunks
β†’
ContextEvidence
β†’
LLMGrounded answer
Key idea:A PDF is only the source format. RAG needs usable text, chunks, metadata, and searchable representations.
2

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.

INGESTION

1. Load PDF

Read the file and identify pages or sections.

INGESTION

2. Extract text

Convert page content into usable text.

INGESTION

3. Clean + chunk

Remove noise and create useful retrieval units.

INGESTION

4. Embed + store

Create vectors and preserve page/source metadata.

QUERY

5. Embed question

Represent the user's question in the same vector space.

QUERY

6. Retrieve

Find the most relevant PDF chunks.

QUERY

7. Build context

Combine selected evidence into a concise model input.

QUERY

8. Generate

Ask the LLM to answer from the supplied evidence.

3

Step 1: Load a PDF

Python has several PDF libraries. For a simple text-based PDF, pypdf is a convenient teaching example.

</> Python
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.

4

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.

</> Python
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])
Important:Text extraction is not guaranteed to reproduce the visual PDF perfectly. Tables, columns, headers, footers, images, and unusual fonts can require additional processing.
5

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.

GOOD EXTRACTIONReadable paragraphs

Sentences appear in the correct order and important headings are preserved.

PROBLEMATIC EXTRACTIONBroken layout

Columns are interleaved, words are split, or table cells appear in the wrong order.

SCANNED PDFNo text layer

The document may need OCR before normal text chunking can work.

VISUAL ELEMENTSCharts and images

Important information may exist only inside an image and need a separate strategy.

6

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.

</> Python
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.

7

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.

TOO BROAD

Whole PDF

Large context, unrelated information, and inefficient retrieval.

β†’
BETTER

Meaningful chunks

Focused passages with source and page metadata.

</> Python
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.

8

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.

SOURCEcompany-handbook.pdfOriginal document
PAGE42Where the evidence appears
SECTIONLeave policyUseful for filtering
VERSION2026-01Freshness tracking
Why it matters:Metadata lets you show citations, debug retrieval, filter by document/version, and enforce access rules.
9

Step 7: Create Embeddings

Convert each chunk into an embedding so a user's question can be compared with the PDF knowledge semantically.

</> Python
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.

10

Step 8: Retrieve From the PDF

At query time, embed the question and rank PDF chunks by similarity. The top results become candidate evidence.

</> Python
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.

11

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.

</> Python
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)
Grounding rule:Tell the model what evidence it may use and what to do when the evidence is insufficient.
12

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.

USER QUESTIONβ€œHow many days of annual leave?”
RETRIEVED EVIDENCEPage 42 β€” Leave policy
MODEL TASKAnswer from supplied context
RESPONSEAnswer + source/page reference

A production application can call its chosen LLM API here. The exact provider is independent of the PDF retrieval architecture.

13

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.

SIMPLE TEXTParagraphs

Standard text extraction may work well.

TABLERows and columns

Use a table-aware extraction strategy when relationships matter.

SCANNED PAGEImage only

OCR may be required before retrieval.

CHARTVisual meaning

Text extraction alone may not capture the information represented by the graphic.

14

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.

Scanned PDFPage image
β†’
OCRRecognize text
β†’
CleanCorrect extraction noise
β†’
Chunk + indexRAG knowledge

OCR introduces its own errors, so important documents should be tested after extraction rather than assuming the OCR output is perfect.

15

When PDF RAG Works Well

MANUALS

Product support

Retrieve installation or troubleshooting instructions.

POLICIES

Employee Q&A

Find the relevant policy section and page.

REPORTS

Research assistant

Retrieve evidence from long reports and papers.

DOCUMENTATION

Knowledge assistant

Answer questions using controlled documentation.

CONTRACTS

Document search

Find relevant clauses when permissions and extraction quality are handled carefully.

GUIDES

How-to assistant

Retrieve the section that explains a specific procedure.

16

PDF RAG vs Uploading the Whole PDF

Whole PDF in context
  • Can become very large
  • May include irrelevant pages
  • Higher context cost
  • Harder to trace the exact evidence
PDF RAG
  • 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.

17

Common PDF RAG Problems

01Bad extraction

The source text is already corrupted before retrieval begins.

02Wrong chunk boundaries

Related content can be separated or unrelated content can be combined.

03Missing page metadata

You lose useful traceability and citation information.

04Table corruption

Column relationships can disappear during extraction.

05Stale documents

Old PDF versions can produce outdated answers.

06Access-control gaps

A user must not retrieve a PDF or chunk they are not authorized to see.

18

Production Considerations

QUALITY

Validate extraction

Test paragraphs, tables, pages, headers, and OCR output.

RETRIEVAL

Evaluate search

Measure whether the correct PDF chunks are retrieved.

FRESHNESS

Track versions

Re-index changed documents and retire stale versions.

SECURITY

Filter access

Apply authorization before returning protected evidence.

PERFORMANCE

Use indexes

Use vector databases or indexes as collections grow.

OBSERVABILITY

Log sources

Record retrieval scores, document IDs, pages, latency, and failures.

19

Improve PDF RAG Step by Step

1

Improve extraction

Choose tools based on PDF structure rather than using one parser for every file.

2

Improve chunking

Use headings, sections, paragraphs, and meaningful boundaries.

3

Improve retrieval

Use vector search, filters, hybrid search, or reranking where useful.

4

Improve citations

Keep document and page metadata through the entire pipeline.

5

Evaluate answers

Test retrieval quality and whether responses stay grounded.

6

Monitor documents

Track versions, freshness, permissions, latency, and cost.

20

Practice: Build a PDF RAG Plan

You have 100 company policy PDFs. A user asks: β€œWhat is the travel reimbursement limit for domestic trips?”

TASK

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

1. Load

Read the PDF.

2. Extract

Get usable text.

3. Inspect

Check extraction quality.

4. Clean

Remove safe noise.

5. Chunk

Create retrieval units.

6. Embed

Create vectors.

7. Retrieve

Find relevant passages.

8. Ground

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.