Skip to content

nb02 · Markdown chunking

Notebook: notebooks/nb02_markdown_chunking_strategies.ipynb · Status: done

The question

Markdown is the bulk of the docs. How should it be split so a code-generation agent gets enough, intact context? Three design principles drove everything:

  • Code-block integrity — a truncated code example is worse than a missing one: the agent receives an incomplete snippet and completes it incorrectly.
  • Heading context — the position of a chunk in the h1 > h2 > h3 hierarchy helps the agent produce correct imports and API calls.
  • Context sufficiency over raw relevance — the relevant criterion is whether a retrieved chunk contains enough (signature + parameters + example) to generate correct code, not topical similarity alone.

Step 1 — Splitter panorama

Five LangChain Markdown splitters were demonstrated on a representative API page and scored on four axes:

SplitterPrincipleControls sizePreserves structureCode integrityHeading metadata
RCTcharacter-based recursiveyesnonono
MHSsplit on headingsnoyes (sections)depends on section sizeyes
MTSMarkdown-aware separatorsyespartialpartialno
EMSTSMarkdown AST parsingno (atoms)yes (perfect)yes (perfect)yes (rich)

No single splitter satisfies all four criteria. EMSTS never breaks a code block or table but emits one atom per element (too granular for retrieval). The selected approach combines EMSTS parsing + merging adjacent atoms + a heading breadcrumb.

Step 2 — Four candidate strategies

IDStrategyIdea
ARCT baselinerecursive character split with heading-aware separators
BMHS + RCTheader split → RCT re-split; heading hierarchy kept in the payload
CAST-MergeEMSTS atoms merged under the same heading up to size — code blocks never split
DAST-Merge + BreadcrumbC, plus a Context: h1 > h2 > h3 prefix injected into the chunk text

Step 3 — How they were evaluated

Each strategy chunked all of kdk/docs into its own Qdrant collection, then was scored with deterministic, source-level metrics (not an LLM-judge-per-chunk rubric):

  • recall@5 / hit@5 — are the gold source files in the Top-5?
  • code_integrity — fraction of retrieved chunks with balanced ``` fences.
  • bundle_efficiency — on-topic chars ÷ total chars in the concatenated Top-K bundle (the agent reads the whole bundle, so wasted chars are wasted context).

The query set is 439 queries auto-mined from the docs — each a page title, section heading, or API symbol, with its source file(s) as ground truth (112 title / 266 symbol / 61 section). This replaced an earlier 46-question FAQ set whose ground-truth sources were empty.

Results

MetricA (RCT)B (MHS+RCT)C (AST-Merge)D (AST+Breadcrumb)
Recall@50.8620.8690.8600.867
Hit@50.9020.9090.8930.902
Code integrity0.9840.9541.0001.000
Bundle efficiency0.0700.1120.1210.142
  • Recall is effectively equal — all four are within ~1 pp (~0.86). File-level retrievability does not distinguish the strategies on this corpus.
  • Code integrity is a strict requirement — character-based A/B leave 2–5% of chunks with unbalanced code fences; AST-based C/D reach 100%. For a code agent, a chunk with an unbalanced fence is worse than a missing chunk.
  • Bundle efficiency is the distinguishing metric — strategy D's breadcrumb approximately doubles on-topic density relative to A (0.142 vs 0.070), so approximately twice as much relevant documentation fits the same context budget.
  • Symbol queries are the most strategy-sensitive — this is the query form an agent uses when looking up a specific API.

Known tradeoff: on bare-symbol lookups, A/B score ~0.857 recall vs D's 0.820 — the breadcrumb slightly reduces symbol-level embedding similarity. In practice an agent's query is closer to "how to use <symbol> in <context>", where the breadcrumb is beneficial rather than detrimental.

Parameter sweep on the selected strategy

Varying chunk_size on strategy D:

chunk_sizeRecall@5IntegrityBundle eff.
5000.8771.0000.147
10000.8671.0000.142
15000.8691.0000.141

chunk_size = 500 scores highest on all three: smaller chunks produce finer-grained sections, so the Top-5 bundle contains less off-topic content.

Verdict

Strategy D — AST-Merge + Breadcrumb, chunk_size = 500. It scores highest on the metrics relevant to code generation (100% integrity, best bundle efficiency) and is approximately equal to the others on recall. This is the Markdown chunker in the ingestion pipeline.

Beyond retrieval: a code-generation check

Deterministic metrics measure retrieval quality, but the real product question is whether an agent fed only the Top-K bundle writes correct Kalisio code. Five Kalisio coding tasks were run through all four strategies; qualitative review found that D's breadcrumb tags (e.g. Context: Globe Mixins > Methods > setStyle) provide clearer hierarchical context than A's raw fragments, which sometimes include unrelated API surface from the same file.