Go Deeper 6 min read Updated Sep 11, 2026

Document Loaders and Text Splitters

The retrieval and RAG guide covered the five-stage pipeline (load, split, embed, store, retrieve) but moved quickly past the first two stages to get to the interesting part. In practice, load and split are where a lot of RAG quality problems actually start, so they're worth a closer look on their own.

Loaders: getting your documents into LangChain's format

A document loader reads a source and turns it into LangChain Document objects, each one holding a chunk of text plus metadata (source file, page number, and anything else you attach). LangChain ships loaders for most common sources out of the box:

from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader, CSVLoader

pdf_docs = PyPDFLoader("policy.pdf").load()
web_docs = WebBaseLoader("https://example.com/article").load()
csv_docs = CSVLoader("customers.csv").load()

The pattern is the same regardless of source: instantiate the loader, call .load(), get back a list of Document objects. There are well over a hundred loaders in the ecosystem covering everything from Notion pages to Slack exports, so before writing a custom parser for a given source, it's worth checking whether one already exists.

Splitters: why chunk size is the decision that actually matters

A full PDF or web page is almost always too big to hand to an embedding model as one unit, and too big to usefully retrieve as a single result. Text splitters break documents into smaller chunks before embedding, and the default, sensible choice for most text is RecursiveCharacterTextSplitter, which tries to split on paragraph breaks first, then sentences, then words, only falling back to a hard character cut when it has to:

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(pdf_docs)

Chunk size and overlap: the tradeoff you're actually making

Too big, and retrieval gets noisy: a chunk that covers three unrelated topics means a query about one of them pulls in the other two as irrelevant context, diluting what the model actually needs.
Too small, and chunks lose context: a chunk that's a single sentence fragment, cut off mid-idea, often doesn't carry enough meaning on its own to be useful even if it's semantically the right match.

chunk_overlap (letting consecutive chunks share some text at the boundary) softens the "cut off mid-idea" problem by ensuring an idea split across a chunk boundary is still fully present in at least one of the two chunks. A common starting point is 500 to 1000 characters per chunk with 10 to 20 percent overlap, but the honest answer is that the right numbers depend on your documents and your queries, and the only reliable way to know if a change helped is to actually measure it against a set of test questions rather than guess.

Where this connects: that's exactly the kind of measurement LangSmith's evaluation tooling is built for, running your retrieval pipeline against a fixed dataset of questions so you can tell whether a chunking change actually improved results instead of just feeling like it should have.
Share this guide

Was this guide helpful?

Thanks for the feedback!

Want more hands-on AI builds like this?

APA Mastery runs live, practical sessions on working with modern AI tools - not just theory.

See What's On →
← PreviousLCEL: Composing Chains