Solving tips
- Chunking is the first stage of every RAG pipeline: bad chunks cap retrieval quality no matter how good the embedder is.
- The overlap keeps context that straddles a chunk boundary from being lost, but it also creates the classic infinite-loop trap.
- Guard the step size: if overlap >= chunk_size the window never advances, so clamp it and always move forward by at least one word.
Before a document can be retrieved by a RAG system it has to be split into chunks small enough to embed and to fit an LLM’s context window. Naive splitting drops context that spans a boundary, so production chunkers repeat a few words between neighbors. Your job is to build that chunker.
How chunking with overlap works
Treat the text as a list of whitespace-separated words. Slide a window of chunk_size words across the list. After emitting a chunk, advance the window by chunk_size - overlap words, so the next chunk starts by repeating the last overlap words of the previous one. Repeat until every word has been covered.
The trap: if overlap is greater than or equal to chunk_size, the step chunk_size - overlap is zero or negative and the window never moves forward, looping forever. You must prevent that.
Task
Complete chunk_text(text, chunk_size, overlap=0):
- Split
text into words on whitespace. If there are no words, return [].
- Emit chunks of at most
chunk_size words, joined back into strings with single spaces.
- Between consecutive chunks, share
overlap words. Clamp overlap so the window always advances by at least one word (never allow an infinite loop).
- If the text has fewer than
chunk_size words, return a single chunk containing all of it.
Example
text = "one two three four five six seven"
chunk_text(text, chunk_size=3, overlap=1)
# -> ["one two three", "three four five", "five six seven", "seven"]
chunk_text("short text", chunk_size=10, overlap=2)
# -> ["short text"]
Constraints
chunk_size >= 1. Assume the caller passes a positive chunk_size.
overlap may be passed as any non-negative int; clamp it internally so chunk_size - overlap >= 1.
- Split and join on single spaces; you do not need to preserve the original whitespace runs.
- No external libraries beyond the standard library and typing.
Approach
Tokenize on whitespace, then walk an index across the word list with a step of chunk_size - overlap. Clamp overlap to at most chunk_size - 1 up front so the step is always at least one word, which is what guarantees the loop terminates. Each slice is joined back into a space-separated string; the final slice is naturally shorter when the words run out.
Solution
from typing import List
def chunk_text(text: str, chunk_size: int, overlap: int = 0) -> List[str]:
words = text.split()
if not words:
return []
# Clamp overlap so the window always advances by >= 1 word (no infinite loop).
overlap = max(0, min(overlap, chunk_size - 1))
step = chunk_size - overlap
chunks = []
i = 0
n = len(words)
while i < n:
chunk_words = words[i:i + chunk_size]
chunks.append(" ".join(chunk_words))
i += step
return chunks
Walkthrough
On text = "one two three four five six seven" (7 words) with chunk_size=3, overlap=1:
overlap clamps to min(1, 2) = 1, so step = 3 - 1 = 2.
i=0: words[0:3] -> "one two three".
i=2: words[2:5] -> "three four five" (note three is the shared overlap word).
i=4: words[4:7] -> "five six seven".
i=6: words[6:9] -> "seven" (slice past the end just returns what remains).
i=8 >= 7, loop stops. Result: ["one two three", "three four five", "five six seven", "seven"].
For chunk_text("short text", 10, 2): 2 words < chunk_size, so the first slice words[0:10] grabs both, i jumps past the end, and the result is the single chunk ["short text"].
Complexity & notes
- Time is O(n) in the number of words when
overlap is a small constant: each word is copied a bounded number of times (once per chunk it appears in, which is ceil(chunk_size / step)). With near-maximal overlap that constant grows, but the classic small-overlap case is linear. Space is O(total output size).
- The single most important line is the clamp
overlap = max(0, min(overlap, chunk_size - 1)). Without it, overlap = chunk_size gives step = 0, i never advances, and the function loops forever, appending the same chunk until it runs out of memory. Interviewers specifically probe for this.
- Python slicing past the end (
words[6:9] on a 7-element list) safely returns the tail, so no special-casing of the last chunk is needed.
- This is word-level chunking, the simplest useful unit. Production RAG often chunks on tokens (to respect the embedder’s real limit) or on sentence and paragraph boundaries (to keep chunks semantically clean); the sliding-window-with-overlap skeleton is identical in all three.