Recall Module 22’s PDF loader — one Document per page, sometimes thousands of words long. Handing an entire page to an embedding model buries the one relevant sentence a user’s question actually needs inside a huge amount of irrelevant surrounding text, hurting retrieval precision. Text splitters break documents into smaller, genuinely more useful pieces first.
A real piece of text to work with
text = """
LangChain provides a set of building blocks for LLM applications. It includes
chat models, prompt templates, and tools. Agents combine a model with tools in
a loop, deciding what actions to take based on the current state. Retrieval
lets an application ground its answers in real documents, rather than relying
purely on what a model memorized during training. Structured output turns a
model's reply into validated, typed data your application code can actually use.
"""
Example 1: a chunk size that’s too large
from langchain_text_splitters import CharacterTextSplitter
splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0, separator=" ")
chunks = splitter.split_text(text)
print(f"Number of chunks: {len(chunks)}")
for c in chunks:
print("---", len(c), "characters ---")
With chunk_size=1000 on this short text, you’ll likely get back just one chunk — the whole thing, unsplit. For a genuinely long document, an oversized chunk buries the specific, relevant sentence inside a large block, hurting how precisely retrieval can find it.
Example 2: a chunk size that’s too small
from langchain_text_splitters import CharacterTextSplitter
splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=0, separator=" ")
chunks = splitter.split_text(text)
print(f"Number of chunks: {len(chunks)}")
for c in chunks:
print(repr(c))
Now you’ll get many small chunks — and notice some genuinely cut a sentence in half, losing its complete meaning. A chunk too small can leave a retrieved piece without enough surrounding context to actually answer a question on its own.
Example 3: overlap, and why it genuinely helps
from langchain_text_splitters import CharacterTextSplitter
splitter = CharacterTextSplitter(chunk_size=150, chunk_overlap=30, separator=" ")
chunks = splitter.split_text(text)
for c in chunks:
print(repr(c))
print("---")
chunk_overlap=30 means each chunk repeats the last 30 characters of the previous one. This is a genuine, deliberate trade-off: a small amount of duplicated content, in exchange for protecting against a sentence or idea being awkwardly cut exactly at a chunk boundary, with its second half losing connection to its first half.
Example 4: recursive splitting — the practical default
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=150, chunk_overlap=30)
chunks = splitter.split_text(text)
for c in chunks:
print(repr(c))
print("---")
RecursiveCharacterTextSplitter is genuinely smarter than the plain version from Examples 1-3: rather than cutting at a fixed character count regardless of what’s there, it tries splitting on paragraph breaks first, then sentences, then words, only falling back to a hard character cut as a last resort. This is why it’s the practical, real default for most text — it respects the actual structure of the writing wherever it reasonably can.
Example 5: structure-aware splitting for code
from langchain_text_splitters import RecursiveCharacterTextSplitter, Language
python_code = """
def get_weather(city):
return f"Weather data for {city}"
class WeatherService:
def __init__(self, api_key):
self.api_key = api_key
def fetch(self, city):
return get_weather(city)
"""
splitter = RecursiveCharacterTextSplitter.from_language(
language=Language.PYTHON, chunk_size=100, chunk_overlap=0
)
chunks = splitter.split_text(python_code)
for c in chunks:
print(repr(c))
print("---")
Notice this splitter understands Python’s actual structure — it prefers splitting between functions and classes, rather than in the middle of one, keeping each chunk’s code genuinely coherent. This matters directly for code-assistant applications, echoing Module 16’s Agent 10, where a chunk that cuts a function definition in half is far less useful than one that keeps it whole.
Common mistakes worth avoiding
Picking a chunk size without ever looking at what it actually produces. Recall Examples 1 and 2 — the only reliable way to know if a chunk size is genuinely right for your content is to print real chunks and read them, exactly as this module did, rather than trusting a number that “sounds reasonable.”
Using chunk_overlap=0 by default. It’s a smaller file size, but recall Example 3’s real trade-off — zero overlap means any idea that happens to fall exactly on a chunk boundary loses its connection to the content before or after it. A small, deliberate overlap is usually worth its modest cost in duplicated content.
Using the plain CharacterTextSplitter for genuinely structured content, like code. Recall Example 5 — RecursiveCharacterTextSplitter.from_language() understands real code structure; the plain splitter from Examples 1-3 doesn’t, and will cut a function definition in half without any awareness that it’s done something genuinely disruptive.
What you should take away from this module
- Chunk size is a genuine trade-off: too large buries relevant content in noise; too small loses necessary context, sometimes mid-sentence.
chunk_overlapdeliberately duplicates a small amount of content across chunk boundaries, protecting against ideas being awkwardly split apart.RecursiveCharacterTextSplitteris the practical default — it respects paragraph and sentence structure before falling back to a hard character cut.- Structure-aware splitting, like
Language.PYTHON, respects a document’s actual real structure — genuinely important for code and other structured content.
Where this goes next
The next module covers Embeddings — the actual mechanism that turns these text chunks into the numerical vectors a vector store can search by meaning, not just matching words.
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed