Chapter
RAG & Retrieval
Chunking, ingest, vector stores, hybrid search, reranking, and citations — the production RAG stack interviewers deep-dive.
RAG Pipeline Overview
Retrieval-Augmented Generation grounds model answers in external evidence: ingest documents → index → retrieve relevant snippets → generate with citations. Interviews reward separating the ingest path from the query path and naming what quality means at each stage.
INGEST QUERY
Docs → Parse → Chunk User query
↓ ↓
Embed + metadata Embed / expand query
↓ ↓
Vector + keyword index → Retrieve → Rerank
↓
Prompt + generate
↓
Answer + citations| Stage | Primary risk | Mitigation |
|---|---|---|
| Parse | Lost tables/headers | Format-aware parsers, layout models |
| Chunk | Split mid-thought | Overlap, structure-aware splits |
| Index | Stale / wrong ACL | Incremental sync, filter at query |
| Retrieve | Missed relevant docs | Hybrid + query rewrite |
| Generate | Ignore evidence | Citations required, grounded prompts |
- Baseline: BM25-only or dense-only before adding agents
- Measure retrieval separately from generation (you cannot fix bad retrieval with a smarter prompt forever)
- Propagate document ACLs into every chunk metadata field
- Design for corpus refresh: deletes, updates, version pins
Opening move
Draw ingest and query as two pipelines. State your eval: golden questions with labeled passages + answer quality. That framing alone is a strong signal.
Start simple
Ship naive chunking + hybrid retrieval + citations first. Complexity (HyDE, multi-hop, agents) only after you know which stage fails.
Chunking Strategies
Chunking decides the atomic unit of retrieval. Too large → noisy context and diluted embeddings. Too small → lost coherence and broken tables. Interview answers should name size, overlap, and structure awareness.
| Strategy | How | Pros | Cons |
|---|---|---|---|
| Fixed tokens | N tokens + overlap | Simple, predictable | Splits sentences badly |
| Recursive / semantic | Split by headings then size | Preserves structure | Parser dependent |
| Sentence window | Small embed, large context window | Precise hit, rich gen context | More index complexity |
| Parent-child | Retrieve small, expand to parent | Best of both | Needs hierarchy metadata |
| Proposition / atomic | One fact per chunk | High precision | Expensive preprocessing |
- Choose chunk size relative to embedding model and generation budget (often 200–800 tokens)
- Add 10–20% overlap for narrative docs; less for highly structured specs
- Keep metadata: source id, title, section path, page, ACL, updated_at
- Special-case tables, code, and slide decks — generic splitters destroy them
Document
└─ Parent section (large)
├─ Child chunk A ← embed & retrieve
├─ Child chunk B
└─ Child chunk C
Hit on B → expand to parent → send parent to LLMCommon failure
Embedding a whole PDF as one vector. Retrieval becomes nearest-document, not nearest-passage — answers get vague and unciteable.
What to say
"I'd pick structure-aware chunking with overlap, store parent refs, and tune chunk size against Recall@k on a labeled set — not against gut feel."
Document Ingest & Parsing
Ingest quality caps RAG quality. Parsing PDFs, HTML, Confluence, tickets, and code into clean text with structure is an engineering problem: layout, OCR, boilerplate removal, and incremental updates.
| Source | Hard part | Approach |
|---|---|---|
| Columns, tables, scans | Layout parser + OCR fallback | |
| HTML / wiki | Nav chrome, duplicates | Readability extract, canonicalize URL |
| Tickets / chat | Noise, PII | Filter bots, redact, thread merge |
| Code repos | Symbol boundaries | AST / function-level chunks |
| Shares / Drive | Permissions churn | Sync ACL deltas with content |
- Idempotent ingest: content hash → skip unchanged; upsert/delete by stable doc id
- Preserve provenance: URI, revision, checksum for every chunk
- Strip boilerplate (headers/footers) or embeddings cluster on noise
- Queue-based pipeline with dead-letter for poison documents
Connector → Fetch → Parse → Normalize
↓
Chunk → Embed → Upsert index
↓
Update ACL / tombstone deletes
↓
Emit metrics (lag, fail rate)Freshness SLO
Define max ingest lag (e.g. 15 min for wiki, 24h for archives). Interviewers like an explicit freshness number and how users know data is stale.
Security angle
Always mention PII handling, tenant isolation, and that a user must never retrieve chunks their identity cannot read.
Vector Databases & Indexes
Vector indexes approximate nearest-neighbor search over dense embeddings. Choices (pgvector, Pinecone, Weaviate, Milvus, OpenSearch) trade recall, latency, filtering, ops burden, and cost. Interviews care about ANN algorithms and metadata filters more than brand names.
| Index family | Idea | Tradeoff |
|---|---|---|
| HNSW | Graph walk neighbors | High recall, RAM heavy |
| IVF / PQ | Cluster + compress | Lower memory, tune nprobe |
| Flat / brute | Exact scan | Tiny corpora only |
| Hybrid engines | BM25 + vector in one | Ops simpler, knobs couple |
- Pre-filter vs post-filter ACLs: pre-filter can hurt recall; post-filter wastes candidates
- Plan re-index when embedding model changes — treat it like a schema migration
- Monitor recall@k offline when you change efSearch / nprobe for latency
- Multi-tenant: separate indexes or mandatory tenant_id filters on every query
Embed(query)
↓
ANN candidates (k*overfetch)
↓
Metadata filters (ACL, type, time)
↓
Optional sparse merge (BM25)
↓
Rerank → top-n chunksFilter blindness
If ACL filters remove most ANN hits, recall collapses. Overfetch (retrieve 5–10× k) or use filtered index structures that respect predicates during search.
Decision framework
Start with managed or pgvector for MVP; move to specialized stores when QPS, scale, or hybrid features demand it. State the trigger metrics.
Hybrid Search
Hybrid search combines lexical (BM25/sparse) and dense retrieval. Lexical wins on exact IDs, error codes, and rare tokens; dense wins on paraphrases. Most production RAG systems need both.
| Signal | Strengths | Weaknesses |
|---|---|---|
| BM25 / sparse | Keywords, IDs, exact phrases | Synonyms, paraphrases |
| Dense embed | Semantic match | Rare tokens, numbers |
| Learned sparse (SPLADE) | Expanded terms | Index size, complexity |
| Query rewrite / HyDE | Better recall | Extra latency & drift |
- Retrieve top-k from sparse and dense independently
- Fuse with RRF (reciprocal rank fusion) or weighted score normalization
- Overfetch before fusion if filters will cull results
- A/B fuse weights on nDCG — do not hardcode 0.5/0.5 forever
Dense ranks: d1,d2,d3,... Sparse ranks: s1,s2,s3,... score(doc) = Σ 1 / (k + rank_i(doc)) Sort by fused score → candidates for rerank
Query understanding
Detect exact-match intents (ticket IDs, SKUs) and boost sparse. Detect vague natural language and lean dense. A tiny classifier pays for itself.
Interview signal
Name hybrid + RRF unprompted. Mention that fusion is cheap compared to a cross-encoder and should come before expensive reranking.
Reranking & Context Selection
Rerankers (cross-encoders or LLM-as-judge) reorder a short candidate list with higher precision. Context selection then packs the best evidence into the prompt under token limits — quality, not quantity.
| Stage | Typical k | Cost |
|---|---|---|
| ANN / BM25 retrieve | 50–200 | Low per query |
| Cross-encoder rerank | 20–50 → 5–10 | Medium GPU/API |
| LLM pack / compress | 5–10 → 3–5 | Higher tokens |
| Generate | final context | Highest |
- Rerank only overfetched candidates — never the whole corpus
- Deduplicate near-identical chunks before packing to save tokens
- Diversity: MMR or coverage heuristics so all facets of a multi-part question appear
- Drop chunks below a score threshold; empty context should trigger abstention
Corpus (millions)
→ Hybrid retrieve (~100)
→ Rerank (~10)
→ Pack / compress (~3–5)
→ LLM answerReranker lag
Cross-encoders add 50–200ms+. For tight SLOs, cache rerank results for popular queries or use a lighter late-interaction model.
Talk track
"Retrieve broadly, rerank narrowly, pack deliberately. I'd rather send 3 great chunks than 15 mediocre ones."
Citations, Grounding & Faithfulness
Grounding means claims in the answer are supported by retrieved evidence. Citations make that checkable. Faithfulness evals catch when the model invents details not in context — a top FAANG RAG deep-dive topic.
| Failure | Symptom | Fix |
|---|---|---|
| Hallucinated cite | Link to wrong doc | Force quote spans; verify ids |
| Unsupported claim | Fluent but unbacked | Abstain / lower temperature; require evidence |
| Citation stuffing | Every sentence cites | Cite at claim granularity |
| Stale evidence | Correct source, old rev | Show version/time; refresh index |
- Prompt: answer only from provided context; say "I don't know" otherwise
- Require inline citation markers mapped to chunk ids
- Post-validate: each cited id exists in retrieved set; optional NLI entailment check
- UI: show quote highlights so users can audit without trusting the model
Eval metrics
Mention faithfulness / groundedness scores, citation precision, and human spot-checks. Separate retrieval recall failures from generation faithfulness failures.
Product trust
For enterprise RAG, citations are not polish — they are the adoption gate for legal, support, and medical-adjacent use cases.
Staff depth layer
RAG & Retrieval — Staff Depth
RAG interviews are systems design with an information-retrieval core. Staff answers separate ingest from query, make ACL a first-class filter, define chunking as a quality lever, and refuse to claim 'groundedness' without citations plus an eval set that distinguishes retrieval misses from generator hallucinations.
Anti-patterns → say instead
✕ Security by embedding obscurity
If restricted chunks sit in the index and you only hope users won't retrieve them, similarity search will eventually surface them — especially via paraphrases.
Say instead: Filter at query time with the caller's principals (and/or per-tenant indexes). Sync ACL versions; fail closed when ACL is stale beyond SLO.
✕ Fixed 512-token chunks forever
Tables, code, and FAQs need different boundaries; naive splits destroy answerability and cite the wrong section.
Say instead: Structure-aware chunking (headings, pages, functions) with overlap 10–15%; store parent doc + section path for citations.
✕ Top-k only, no hybrid/rerank
Pure ANN misses lexical needles; unre-ranked top-20 floods the prompt with near-duplicates.
Say instead: Hybrid retrieve 50–100 → cross-encoder or LLM rerank to 5–8 → pack with diversity (MMR) under token budget.
✕ No ingest freshness story
Stale indexes answer with yesterday's policy; interviewers probe delete/update propagation.
Say instead: Webhook/CDC → queue → re-embed changed docs; tombstone deletes; measure index lag p95.
25k employees, ~8k queries/day, 2M pages → ~12M chunks after split. Need ACL-aware Q&A, p95 < 4s, citations.
- Chunk ~400–800 tokens with overlap; estimate 12M chunks × 400 tokens ≈ 4.8B embed tokens.
- One-time embed at $0.02/1M ≈ $96; vector store 12M × 1536 × 4B ≈ 74 GB (+ replicas/HNSW overhead).
- Query path: authZ → hybrid search with ACL metadata filter → rerank → generate with cite-or-refuse.
- Eval: 200–500 golden Qs labeled with must-cite doc IDs; track recall@k, citation precision, groundedness, refusal quality.
- Cost/day: 8k × (2k in + 500 out) ≈ 20M tokens; at $3/1M mid-tier ≈ $60/day gen — dominate spend vs embeds.
- Avg QPS 8k/86400 ≈ 0.09; peak ~2 QPS at 20×
- Retrieval budget 50–150ms; LLM usually dominates p95
- Cache FAQ-like queries: 30–50% hit rate can cut gen spend roughly in half on that cohort
Lead with ACL + hybrid + evals; treat embedding cost as CapEx and generation as OpEx you attack with cache and smaller models.
Cheat sheet
- Ingest path ≠ query path — draw both
- ACL filter-at-retrieval; fail closed
- Hybrid + rerank + citation contract
- Chunk by structure; keep parent metadata
- Golden set: retrieval vs generation metrics
- Index lag, delete tombstones, re-embed on change
- Refuse when evidence insufficient — don't bluff