> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chunking Documents

> Explains splitting PDFs into overlapping text chunks using LangChain for embedding and retrieval in RAG pipelines

In this lesson we continue from the document loader step where we loaded `handbook.pdf`. The goal is to split the document into smaller, overlapping chunks (passages) so they can be embedded and stored in a vector store for retrieval-augmented generation (RAG). Proper chunking preserves context, improves retrieval relevance, and improves the quality of LLM responses when using external documents.

## 1. Load the PDF and inspect pages

Use LangChain's PDF loader to read the document as page-level Document objects:

```python theme={null}
from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader("data/handbook.pdf")
pages = loader.load_and_split()

# Inspect basic page count
len(pages)
# Inspect the first page's text (print a slice if long)
pages[0].page_content[:400]
```

This gives you page-level Document objects with `page_content` and default metadata (e.g., `source`, `page`).

## 2. Create a text splitter to produce chunks

We commonly use `RecursiveCharacterTextSplitter` for robust splitting that respects sentence boundaries and reduces awkward cuts. Here we create a splitter configured with a chunk size of 200 characters and 50 characters of overlap between consecutive chunks:

```python theme={null}
from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=50)
chunks = text_splitter.split_documents(pages)
```

Why use a splitter:

* It transforms long pages into passage-sized Documents suitable for embeddings and vector stores.
* It can preserve natural language boundaries (sentences, paragraphs) when configured properly.

## 3. Why chunk with overlap?

Overlap between chunks preserves context across chunk boundaries so that ideas cut near a boundary remain recoverable. Overlap reduces the chance of losing relevant context during retrieval and increases the probability that a retrieved chunk contains a complete thought.

Benefits:

* Better context for LLM prompts when a single chunk lacks all required information.
* Smoother transitions across document segments for multi-sentence ideas.
* Tolerates noisy splits and improves recall at retrieval time.

Tradeoffs:

* Introduces redundancy (more tokens to embed/store).
* Larger total storage and slightly higher retrieval cost.

<Callout icon="lightbulb" color="#1CB2FE">
  Tip: If queries require longer context, increase `chunk_size`. For precise answers on short queries, reduce `chunk_size` but keep a modest `chunk_overlap` (e.g., 25–50 characters).
</Callout>

## 4. Inspect the resulting chunks and metadata

After splitting, inspect chunk count and a sample chunk to confirm expected behavior:

```python theme={null}
len(chunks)
# -> 40
```

Each chunk is a Document-like object containing `page_content` and `metadata` (for example, `source` and `page`). Example representation:

```python theme={null}
chunks[0]
# -> Document(page_content='LakeSide Bicycles Employee Handbook Welcome to the team! LakeSide Bicycles is a company that values quality, innovation, and customer satisfaction. We are passionate about creating and selling', metadata={'source': 'data/handbook.pdf', 'page': 0})
```

Notes on metadata:

* By default, PDF splitting includes `source` and `page` metadata. This is useful for citing sources in model responses.
* When processing multiple documents, robust metadata (filename, URL, document ID) helps trace every chunk to its origin.

## 5. Choosing chunk size and overlap (practical guidance)

Choose `chunk_size` and `chunk_overlap` based on document characteristics, retrieval goals, and the LLM context window. The table below summarizes common scenarios:

| Chunk Size              | Use Case                                                   | Recommendation                                                                        |
| ----------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Small (50–300 chars)    | Short notes, chatty text, fine-grained retrieval           | Good for precise answers; increase overlap slightly (25–75 chars)                     |
| Medium (300–1500 chars) | Typical articles, documentation, manuals                   | Balanced: good precision and context without too much redundancy                      |
| Large (>1500 chars)     | Long-form content when retrieval must return large context | Use when LLM context window is large; keep overlap moderate to avoid large duplicates |

Factors to consider:

* Document structure (long paragraphs vs short bullets).
* Expected query type (fact lookup vs long-answer generation).
* Vector store and embedding cost/performance.
* LLM prompt budget (context window size).

## 6. Summary: chunking workflow

1. Load the document into page-level Documents (e.g., with `PyPDFLoader`).
2. Configure `RecursiveCharacterTextSplitter` with appropriate `chunk_size` and `chunk_overlap`.
3. Call `split_documents(pages)` to produce a list of chunk Document objects.
4. Each chunk contains `page_content` and `metadata` and can be embedded and stored in a vector store for semantic search and RAG.

## 7. Next steps: embeddings and semantic search

After chunking, the typical next steps are:

* Create embeddings for each chunk (e.g., OpenAI embeddings, other models).
* Store embeddings in a vector store (FAISS, Pinecone, Milvus, etc.).
* Implement semantic search and retrieve relevant chunks for LLM prompts.

Useful references:

* LangChain text splitters and document loaders: [https://python.langchain.com/docs/](https://python.langchain.com/docs/)
* Vector stores (FAISS, Pinecone) and embeddings documentation: [https://langchain.readthedocs.io/en/latest/modules/indexes.html](https://langchain.readthedocs.io/en/latest/modules/indexes.html)

A solid understanding of chunking helps ensure your RAG pipeline retrieves coherent, contextually complete passages and produces higher-quality responses from LLMs.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langchain/module/e47b44c9-65c3-46f8-8bed-b075a18ab12b/lesson/fc020e0a-7253-4445-8fff-d30d8d639315" />
</CardGroup>
