Bedrock Knowledge Bases Chunking Strategies That Fit Code RAG

Bedrock Knowledge Bases: Chunking Strategies That Fit Code RAG
24 views
Fixed 300-token windows shred functions mid-signature. Pure markdown splitters worship READMEs and ignore the call graph. Code RAG only works when Bedrock Knowledge Bases chunking respects symbols: one coherent unit per function/class (plus a thin caller hint), metadata for repo/language/path, and enough overlap that cross-file types still retrieve. This is the senior playbook for chunking that returns the right function — not a random docstring.
⚡ TL;DR: For Bedrock Knowledge Bases chunking on code, prefer AST-aware chunks (tree-sitter / ts-morph) sized to symbols; fall back to semantic splits for prose docs; use fixed-size only for logs. Attach metadata (repo, path, symbol, language). Keep parent headers in every child chunk. Evaluate with hit-rate@k on real developer questions.
Store choice and filters next: OpenSearch vs pgvector, Bedrock retrieval filters, and RAG evaluation on Bedrock.

Fixed-size: when it still wins

Fixed windows are fine for homogeneous prose and terrible for TypeScript services.
python
# ❌ Fixed-size on source — splits mid-function
def fixed_chunks(text: str, size: int = 800, overlap: int = 100):
    out = []
    i = 0
    while i < len(text):
        out.append(text[i : i + size])
        i += size - overlap
    return out
python
# ✅ Fixed-size only for runbooks / plain ADRs
def fixed_for_prose(path: str, text: str):
    if path.endswith((".md", ".txt")) and "/src/" not in path:
        return fixed_chunks(text, size=1200, overlap=150)
    raise ValueError("use_ast_chunker_for_code")

Semantic chunking for docs

Embed consecutive sentences; cut when cosine similarity drops. Good for ADRs and wiki pages feeding the same KB.
python
import numpy as np

def semantic_breaks(sentence_embeddings: list[np.ndarray], threshold: float = 0.55):
    breaks = [0]
    for i in range(1, len(sentence_embeddings)):
        sim = float(np.dot(sentence_embeddings[i - 1], sentence_embeddings[i]))
        if sim < threshold:
            breaks.append(i)
    breaks.append(len(sentence_embeddings))
    return breaks  # slice sentences[breaks[j]:breaks[j+1]]

AST-aware chunking for code (the default)

Parse with tree-sitter or ts-morph; emit one chunk per exported function/class with signature, body, and a one-line file path header.
typescript
// chunk-ts.ts — illustrative ts-morph chunker
import { Project } from "ts-morph";

export function chunkTypeScript(filePath: string, source: string) {
  const project = new Project({ useInMemoryFileSystem: true });
  const sf = project.createSourceFile(filePath, source);
  const chunks: { id: string; text: string; metadata: Record<string, string> }[] = [];

  for (const fn of sf.getFunctions()) {
    if (!fn.isExported()) continue;
    const name = fn.getName() ?? "anonymous";
    const start = fn.getStartLineNumber();
    const text = `// file: ${filePath}\n// symbol: ${name}\n${fn.getText()}`;
    // ✅ Symbol-bounded chunk with path breadcrumb
    chunks.push({
      id: `${filePath}::${name}`,
      text,
      metadata: { path: filePath, symbol: name, language: "typescript", start: String(start) },
    });
  }

  // ❌ Don’t embed import-only noise as its own retrieval unit
  return chunks.filter((c) => c.text.split("\n").length > 3);
}

Bedrock Knowledge Bases chunking: ingestion knobs that matter

When using Bedrock Knowledge Bases, set chunking strategy explicitly for each data source. For code, prefer ingesting pre-chunked objects (one S3 object or one document per symbol) so the service does not re-split your careful AST units. Put metadata attributes Bedrock can filter later (repo, language, team).
json
{
  "chunkingStrategy": "NONE",
  "comment": "Pre-chunked AST units already in S3; do not re-window"
}
bash
# ✅ Upload one JSON/text object per symbol with metadata sidecar
aws s3 cp chunks/auth/getSession.json s3://kb-code/auth/getSession.json \
  --metadata language=typescript,repo=platform,symbol=getSession
Compare retrieval backends and when pgvector beats OpenSearch in RAG on AWS. Cache hot system prompts with Bedrock Prompt Caching.

Evaluate chunking, don’t argue about it

Metric Target (illustrative)
Hit-rate@5 on golden Qs ≥ 0.85 for symbol questions
Exact-symbol recall ≥ 0.9 when query names the function
Doc-only questions Prefer semantic chunks, not AST
Avg chunk tokens 200–800 for code; avoid 50-token crumbs
python
def hit_at_k(retrieved_ids: list[str], gold_ids: set[str], k: int = 5) -> float:
    return 1.0 if gold_ids.intersection(retrieved_ids[:k]) else 0.0

Closing checklist

✅ Dos
– ✅ AST-chunk code; semantic-chunk prose; fixed-size only for logs
– ✅ Prefix every chunk with file: + symbol:
– ✅ Use chunkingStrategy: NONE when pre-chunked
– ✅ Attach filterable metadata (repo, language, team)
– ✅ Measure hit-rate@k on real engineer questions ❌ Don’ts
– ❌ Don’t fixed-window TypeScript services
– ❌ Don’t index node_modules or generated clients
– ❌ Don’t let KB re-split careful AST units
– ❌ Don’t omit path breadcrumbs
– ❌ Don’t tune chunk size by vibes alone

Related reading

Last updated on September 11, 2026

Watch: 100 Days of AI on YouTube

Short videos from CheatCoders, one AI engineering topic per day.

Open the playlist on YouTube · CheatCoders on YouTube

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

1 Comment

Leave a comment

No account needed. Name and email are optional.