AW Dev Rethought

βœ‚οΈ Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away - Antoine de Saint-ExupΓ©ry

🧠 AI with Python – βœ‚οΈ RAG Systems: Document Chunking Strategies 🐍


Description:

A document may contain the answer while retrieval still misses the evidence. One reason is how the document was split before embedding.

Chunking divides documents into units that can be embedded and retrieved. A useful chunk contains enough context to make sense while remaining focused and within the model's input limit.


βœ‚οΈ Three Strategies to Compare

This lab uses fictional Markdown policies and compares:

Strategy Demo configuration Trade-off
Fixed 120 characters, no overlap Simple; may cut sentences or separate context
Overlap 120 characters, 40 repeated Retains nearby context but indexes repeated text
Section-aware Split at ## headings; 240-character fallback Keeps sections together, while still bounding long sections

The character counts make the example easy to inspect. They are demonstration settings, not recommended production defaults.


πŸ“š Preserve the Source While Splitting

A basic window advances by size - overlap:

for start in range(0, len(text), size - overlap):
    end = min(start + size, len(text))
    chunk_text = text[start:end]
    if end == len(text):
        break

The notebook validates 0 <= overlap < size and attaches a document ID, title, section, version hash, and character offsets to each chunk. An assertion checks that every chunk still matches its original source slice.

The section splitter recognises Markdown level-two headings. Oversized sections fall back to bounded windows, so even this strategy can split a sentence. Tables, PDFs, and complex layouts need appropriate parsing rather than assuming this small splitter handles every document.


πŸ” Embed and Retrieve Consistently

Use the same model for documents and questions:

vectors = model.encode(
    [chunk["text"] for chunk in chunks],
    normalize_embeddings=True,
    convert_to_numpy=True,
)
index = faiss.IndexFlatIP(vectors.shape[1])
index.add(np.asarray(vectors, dtype="float32"))

For normalised vectors, inner-product search ranks by cosine similarity. FAISS metric documentation

Check token lengths before embedding. Characters and tokens are different units, and text beyond an embedding model's sequence limit may be truncated. The notebook checks each chunk against the loaded model's limit. Sentence Transformers input limits


βœ… Evaluate the Evidence

We use four questions with known evidence sentences. A hit requires a top-two result from the correct document containing the complete sentence.

Strategy Chunks Indexed characters Questions with complete evidence in top 2
Fixed 13 1,461 3/4
Overlap 18 2,061 4/4
Section-aware 13 1,317 4/4

In this example, overlap adds 600 indexed characters compared with the fixed windows. Section chunks omit the heading syntax from the embedded body while retaining section names as metadata.

This is a small, strict diagnostic. Different strategies return different amounts of text, and exact sentence containment does not capture every form of relevant evidence. The results do not establish a universal winner.


πŸ“Œ Key Takeaways

  • Chunk boundaries affect the evidence available to retrieval.
  • Overlap repeats context and increases indexed text.
  • Structure-aware splitting still needs a size limit and appropriate parsing.
  • Preserve source metadata and check model token limits.
  • Tune on representative questions, inspecting both retrieval misses and unnecessary context.

Code Snippet:

None

Link copied!

Comments

Add Your Comment

Comment Added!