Chunk by meaning while preserving document structure
How to study this lesson
Read one section, trace the worked example, and try the knowledge check. Bookmark saves a shortcut; notes appear in My notebook. Mark lesson complete is your own assessment and does not mark its lab passed.
By the end, you can
- Explain the evidence boundary created by a chunk.
- Compare fixed windows, structural chunks, and semantic boundary heuristics.
- Preserve stable citations and parent context during indexing.
The retriever can only return what the index preserves
Retrieval-augmented generation conditions an answer on retrieved material rather than relying solely on model parameters. The original RAG paper combines retrieval and generation in a defined model setting. In a software application, the same broad pattern creates an engineering pipeline: ingest documents, construct retrievable units, find candidates, select evidence, and produce an answer whose claims can be checked against that evidence.
Chunking determines the units available to later stages. If a policy exception is separated from the rule it qualifies, a retriever can return a misleadingly complete-looking passage. If every document is one huge chunk, relevant details may be diluted and context budgets exhausted. The aim is to preserve answer-bearing relationships while making candidate selection efficient. There is no universal chunk size that solves every document type.
Start from the source structure
Parse headings, paragraphs, lists, tables, code blocks, and document metadata before applying a generic window. A table row often needs its column headers to be interpretable. A code example may need its language and function context. A subsection can inherit a document title and version without copying the entire document into every chunk. Store parent links so retrieval can expand context when a small hit lacks necessary qualifiers.
Suppose a policy has a 90-word rule followed by a 40-word exception. A fixed 100-word boundary splits the exception midway. A structure-aware chunk can preserve the 130-word rule-and-exception pair if its budget allows. If it does not, preserve the relation through parent and sibling metadata so the answer builder can retrieve the exception alongside the rule. Splitting text is easy; preserving its semantics requires explicit decisions.
Semantic boundaries are estimates
A semantic chunker can compare representations of adjacent sentences or sentence windows and place a boundary when topic similarity drops. Sentence embeddings provide one possible representation. The mechanism requires a threshold, minimum size, maximum size, and fallback for long passages. Similarity measures topic relatedness imperfectly; a crucial exception can use different vocabulary while belonging with the preceding rule.
In the code, four hand-supplied two-dimensional vectors stand in for sentence representations. Neighbor similarities are high, low, then high. A threshold of 0.5 creates two groups. These vectors are synthetic and do not perform natural-language understanding. The example isolates boundary logic so a learner can inspect what a real embedding model would influence. Do not call a word-count splitter semantic merely because it appears in a RAG application.
A worked context and overlap budget
A 1,200-token document split into 300-token windows with a 50-token overlap advances by 250 tokens each step. This produces overlapping evidence and increases indexed token volume. Overlap can preserve context near boundaries, but duplicate passages may occupy several top retrieval positions. Deduplicate or diversify candidate selection so one repeated paragraph does not crowd out a necessary second source.
Use stable chunk IDs tied to document identity, revision, and span. A citation should resolve to the source that was actually indexed, not whatever happens to live at a mutable URL later. Keep text offsets or section anchors and a content hash. If a parser changes whitespace or table layout, preserve enough mapping to find the original evidence. Citation stability is an ingestion responsibility as much as a generation feature.
Evaluate chunks with real questions
Compare chunking policies on answer-bearing spans, retrieval recall, context cost, and final grounded correctness. Include questions that require an exception, a table header, a cross-reference, and two adjacent paragraphs. A visually tidy set of equal-sized chunks can still lose the evidence needed for the question. Conversely, a semantic splitter may add computation without improving retrieval on a strongly structured corpus.
Start with a structural baseline, then add semantic boundaries where failures justify them. Record parser and chunker versions so changes can be reproduced. When a question fails, inspect whether the evidence was ingested, whether it survived chunking, whether it was retrieved, and whether it was used correctly. This stage-by-stage diagnosis prevents repeated prompt tuning from trying to repair information that never reached the model.
Explore a retrieval trade-off
These synthetic scores have already been normalized to the same scale. This is a weighted blend, not reciprocal rank fusion.
Try 0%, 50%, and 100%. Which ranking would you choose for an exact error code? For a paraphrased question? Validate that decision on queries rather than one example.
Work through the code
Hand-authored vectors simulate two topic clusters. Adjacent cosine similarity triggers boundaries. The example does not create embeddings, parse real documents, enforce a token limit, or establish that semantic splitting improves a corpus.
import math
sentences = ["Queue setup.", "Queue timeout.", "Invoice total.", "Invoice fee."]
vectors = [(1.0, 0.0), (0.9, 0.1), (0.0, 1.0), (0.1, 0.9)]
def cosine(left, right):
dot = sum(a * b for a, b in zip(left, right))
norm = math.sqrt(sum(a * a for a in left) * sum(b * b for b in right))
return dot / norm if norm else 0.0
groups = [[0]]
similarities = []
for index in range(1, len(sentences)):
similarity = cosine(vectors[index - 1], vectors[index])
similarities.append(round(similarity, 3))
if similarity < 0.5:
groups.append([])
groups[-1].append(index)
print(similarities)
print(groups)
print([" ".join(sentences[index] for index in group) for group in groups])
[0.994, 0.11, 0.994] [[0, 1], [2, 3]] ['Queue setup. Queue timeout.', 'Invoice total. Invoice fee.']
Run Python snippets locally with the prerequisites named above. The module coding lab runs directly in your browser.
Pause and reason
A retrieved table row says 30, 60, 90 but lacks headers and units. Which ingestion change would make the evidence usable?
Check your understanding
A semantic splitter detects a vocabulary shift between a rule and its exception. What should the designer consider?
Your notes
Explain the mechanism in your own words. Add a failure you want to test.
Go deeper with primary sources
- Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
- Dense Passage Retrieval for Open-Domain Question Answering
- The Probabilistic Relevance Framework: BM25 and Beyond
- Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods
- Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks