LearnThatStack Ace your next interview

Retrieval-Augmented Generation (RAG)

Checked Sep 2026 2 code snippets

The model

  • RAG fetches relevant text at query time and adds it to the prompt. The model answers from that evidence, not only from what it learned in training.
  • Two paths meet at the index. The indexing path chunks and embeds documents when they change. The query path embeds each question with the same model and finds the nearest chunks.
  • Answer quality depends on retrieval. If the right chunk never reaches the prompt, the model is back to guessing.
  • Retrieve wide, then narrow. Fetch 20 to 100 candidates cheaply, rerank them, and send the model the best 3 to 8.
  • Measure retrieval and generation apart. RAG cuts hallucinations but doesn't end them, because the model can still misread good evidence.
Documentswiki, PDFs, ticketsIndexchunk vectors + textYour apprewrite, rerankLLMwrites the answerINDEXchunk + embedQUERYquery vectortop 50 chunksbest 5 + questionanswer + citations
Indexing runs when documents change. Queries use the same embedding model, and a chunk the search misses never reaches the LLM.

How RAG works

how an answer gets made, and what RAG fixes

The pipeline, step by step

List the indexing stepsParse, chunk, embed, then store the vectors with metadata.
List the query stepsRewrite, embed, retrieve, rerank, build the prompt, then generate.

TrapEmbed queries and chunks with the same model, or their vectors won't compare.

What RAG fixes

Name the problem it solvesThe model's knowledge ends at a cutoff and misses your private data.
Say why hallucinations remainRetrieval can miss, and the model can misread good passages.

TipEdit a document and the next answer changes, with no retraining.

TrapIf retrieval misses, the model usually answers from memory anyway.

RAG, fine-tuning or long context

Pick RAGFor large, changing or private data, citations and per-user access.
Pick fine-tuningTo change behavior, like format, style or a narrow task.
Pick long contextWhen a small, stable document set fits in the prompt.
Find when stuffing the whole corpus is cheaperBelow breakeven, which is fixed cost over the saving per query.

TipPrompt caching cuts repeat prefill to about a tenth. That raises the breakeven for stuffing more than tenfold.

TrapFine-tuning is a weak way to add facts. The model blends them and can't cite a source.

Chunk documents

split text into pieces that search well

Chunk size and overlap

Say why not embed whole documentsOne vector averages all its topics, so the answer gets lost.
Pick a chunk sizeThe smallest unit that answers a typical question.
Set the overlap10 to 20 percent, so an idea cut at an edge stays whole in a chunk.

TipSmall chunks match sharply but lose context. Large ones stand alone but blur the match.

TrapWith overlap, search can return near-copies. Dedupe neighbors before you build the prompt.

Pick a chunking strategy

Chunk uniform text, or set a baselineFixed-size. Cut every N tokens, plus overlap.
Chunk messy proseRecursive. Split by paragraph, then sentence, then word.
Chunk Markdown, HTML or codeStructural. Follow headings, tags, syntax trees or table rows.
Chunk text that changes topic with no markupSemantic. Cut where the embedding distance between sentences jumps.

TipStart structural when the corpus has real markup. Headings double as metadata for filters and citations.

TrapSemantic chunking costs an extra embedding pass and often loses to recursive. Measure it first.

Keep context around small chunks

Search small chunks, but send the model moreParent-document retrieval. Match small chunks, send their parents.
Fix chunks that lost their subject or dateContextual retrieval. Index each with an LLM note on where it sits.
Index tables and imagesEmbed a text stand-in, but send the model the original.

TipContextual retrieval changes what you index. Parent-document retrieval changes what you send.

TrapOne big chunk isn't the same. Its single vector blurs the match a small chunk keeps sharp.

Hybrid search & reranking

find the right chunks and put the best first

Keyword, dense or hybrid search

queryBM25denseRRFrerankprompt
hybridBM25 and dense search run at once. RRF merges the lists, then a reranker keeps the best.
Find a pasted SKU or error codeBM25. It matches exact terms and weights rare ones up.
Find a paraphrase with no shared wordsDense search. It matches meaning, not wording.
Say why hybrid beats either aloneThey fail on different queries, so both together lift recall.
Pick SPLADE or ColBERT over hybridMainly out of domain, where single-vector models drift.

TipColBERT keeps one vector per token, so its index is about ten times larger.

Merge ranked lists with RRF

score(d) = sum over lists of 1 / (k + rank)k = 60A: keyword rank 2, dense rank 31/62 + 1/63 = 0.0320B: keyword rank 1, not in dense1/61 = 0.0164
Say what RRF usesEach document's rank in each list, never its raw score.
Say why not add raw scoresBM25 is unbounded and cosine runs from -1 to 1. They don't compare.
Say what k doesIt softens the top ranks, so no single list dominates.

TrapRRF drops the margin, so a clear winner and a near-tie look alike. Add a reranker when that matters.

Choose k, and skip near-copies

Pick k, the number of chunks keptTest several values. Pick where the hit rate stops rising.
Set k per stageFetch 20 to 50 candidates, then send the model 3 to 8.
Keep near-copies out of the promptMMR. Each pick loses points for repeating one already picked.

TipToo small a k drops the right chunk. Too large adds noise, tokens and latency.

TrapPlain top-k often returns near-copies of one passage and pushes out a second source.

Rerank the shortlist

# bi-encoder: two passes, compared laterscore = cosine(embed(query), embed(doc))# cross-encoder: one pass over the pairscore = model(query, doc)
Say why a cross-encoder is more accurateIt reads query and chunk together, so every token sees every other.
Say why it only reranks a shortlistNothing caches, so every candidate costs a full model pass.
Pick an LLM reranker insteadWhen relevance needs instructions, or you have no labels.

TipA common cascade has a cross-encoder cut 100 to 10, then an LLM judge those 10.

TrapA reranker can't bring back a chunk that retrieval missed.

Rewrite & route queries

turn what the user typed into a good search

Rewrite follow-up questions

User: Do you refund annual plans?User: and after 30 days?Search: annual plan refund after 30 days
Say why not embed the latest messageA follow-up often names no topic, so its vector lands nowhere useful.
Choose what the generator seesThe original message. Only the search uses the rewrite.

TrapA bad rewrite fails quietly, since retrieval still returns confident chunks. Log both forms.

Expand, split or use HyDE

Fix a short or vague queryExpansion. Search several phrasings and fuse the lists.
Handle a question about two topicsDecomposition. Search each part, since one vector matches neither.
Search with a drafted answerHyDE. Embed a drafted answer, which looks more like a passage.
Make HyDE saferSearch with the question and the draft, then fuse with RRF.

TipEach one adds retrieval or LLM calls, so latency rises. Split a query only when it really has two parts.

TrapA HyDE draft can invent names or numbers that pull the search toward the wrong documents.

Prompt, context & citations

fit the best chunks in and make answers checkable

Fill the prompt template

System: Answer only from the context.If it has no answer, say you don't know.Cite sources as [1], [2].[1] (handbook.pdf, p.12) <chunk text>[2] (faq.md) <chunk text>Question: How many vacation days do I get?
Label every chunkGive each one an id and a source to cite.
Place the chat historyIn its own slot, never inside the context block.

TrapRetrieved text is untrusted data, not instructions. Mark the context block clearly.

Ground answers and check citations

Say what a grounded answer isEach claim traces to a chunk. If none answers, the model says so.
Catch a made-up citation idCheck each cited id against the ids you sent.
Catch a real id that doesn't back the claimRequire a verbatim quote, match it, then check entailment.

TipTrack the share of citations you reject as a live metric.

TrapCitation ids are local to one prompt, not global document ids. Your app maps each back to its source.

Order and trim the context

234567891011121startmiddleend

Numbers are rerank positions, in prompt order. Rank 1 opens the context, rank 2 closes it, and the weakest chunks sit in the middle.

Say what lost in the middle meansModels use a long prompt's start and end best, and its middle worst.
Fix lost in the middleSend fewer chunks, and put the best ones at the edges.
Assemble the final contextDedupe, fill a token budget by rerank score, then order.

TipCount tokens with the model's tokenizer, and cap chunks per document.

TrapA bigger context window doesn't flatten the curve. Test by moving a known answer through every position.

Handle sources that disagree

Handle an outdated sourcePrefer the current one. Mention the old version only if it helps.
Handle conflicting opinions or findingsSummarize each view neutrally, each with its citation.
Handle a source that's likely falseIgnore it and answer from the reliable sources.
Handle answers that fit togetherMerge them into one answer. Don't frame it as a debate.

TipStore an effective date, version and authority on every chunk, so ranking can prefer current, trusted text.

Evaluate & debug

measure retrieval and answers, then find what broke

Retrieval metrics

Tune a retriever that feeds a rerankerRecall@k, the share of relevant chunks in the top k.
Score when only the top result gets readMRR, the mean of 1 / rank of the first relevant hit.
Score graded relevance where order mattersnDCG, which discounts each hit by its position.

TipMRR looks only at the first hit, so it misleads on questions that need several passages.

TrapRecall@k can score 1.0 while the answer sits at rank 20.

Grade the answers

Check the answer sticks to its contextFaithfulness. Supported claims divided by all claims.
Check it answers the question askedAnswer relevancy. Rebuild the question from the answer and compare.
Grow evaluation from prototype to productionRetrieval hit rate, answer checks per release, then live signals.

TipAnswer correctness needs a reference answer. Faithfulness and relevancy don't.

TrapLLM judge scores drift when the judge model changes. Pin its version and check it against human labels.

Build an eval set from scratch

Seed questions from the corpusAn LLM writes questions a chunk answers. That chunk is the label.
Add the cases that break systemsReal user queries, multi-hop questions and unanswerable ones.

Tip100 human-checked items beat 10,000 unchecked ones. Freeze and version the set.

TrapQuestions made from a chunk copy its wording, so retrieval looks better than it will in production.

Find where a chunk got lost

Check the document is indexedFetch it by id. Missing means ingestion failed.
Check the chunk can be found at allSearch for its own text. A miss means a stale vector or wrong namespace.
Check the filtersDrop tenant, ACL and metadata filters. They hide valid hits.
Check its rankAt rank 30 it's a ranking problem, often a wording mismatch.

TipIf the chunk did reach the prompt, retrieval worked and generation failed.

TrapLog the query that was actually embedded, not the one the user typed.

Where RAG fails

Name the failures before generationMissing content, ranked too low, or trimmed out of the context.
Name the failures in the answerNot extracted, wrong format, wrong level of detail, incomplete.
Debug high recall with wrong answersAnswer from the gold chunk alone. If that fails, fix generation.

TipYou can only validate a RAG system in operation, so log every stage.

TrapRecall labeled per document counts a hit even when the model saw only half the answer.

Agentic, graph & SQL RAG

when one search pass isn't enough

Agentic RAG and multi-hop questions

Say what makes RAG agenticThe model decides at run time to search, search again or stop.
Say what agentic RAG buys and costsIt recovers from a weak first search, but cost and paths vary.
Answer a question that needs two lookupsLoop. Plan each next query from what the last search found.

TipThe bridge entity that links the hops isn't in the question, so one search can't find it.

TrapCap it at two or three hops. One bad hop poisons every later one.

GraphRAG

Say what GraphRAG buildsAn LLM extracts entities and relations, then summarizes clusters.
Say when it's worth itWhen entities are stable and questions span many documents.

TrapEvery update means re-extracting and re-summarizing. For plain lookups, hybrid search plus a reranker is cheaper.

Self-RAG and Corrective RAG

searchgradeanswerweakrewrite
grade loopGood chunks go to the answer. Weak ones trigger a rewrite and one more search.
Say what Self-RAG doesIt trains the model to emit reflection tokens that judge retrieval.
Say what Corrective RAG doesA small grader rates the retrieved set. Bad grades trigger web search.

TrapProduction copied the control flow, not the training. Cap the loops, or latency and cost double.

RAG over SQL tables and APIs

Say what you retrieveThe schema, sample values and verified queries, not the rows.
Run generated SQL safelyA read-only role, a timeout and a row cap. Show the SQL too.

TipIndex the distinct values of low-cardinality columns, and resolve names before writing SQL.

TrapEntity linking fails most often. Users type Acme Corp while the column holds ACME CORPORATION.

Freshness, access & security

keep the index current and each tenant's data apart

Keep the index fresh

Drive updates from change eventsCDC and webhooks, plus a scheduled reconcile for missed events.
Re-embed only what changedKey chunks by doc id and content hash, and re-embed only new hashes.
Hide deleted documents at onceFilter them at query time too, since index deletes lag.
Swap embedding models without downtimeDual-write to a second index, backfill, test on a golden set, canary.

TipStore raw chunk text next to each vector. A model migration has to re-embed it.

TrapAfter an edit, delete the document's chunks below the new version, or a shorter document leaves stale ones behind.

Tenants and access control

Enforce who can see a chunkfilter={"tenant_id": session.tenant_id, "acl": {"$in": principals}}Pre-filter inside the search, never in the prompt.
Get the caller's user and group idsResolve them on the server from the session, never from the request.
Pick an index layoutShared for scale, namespaces to contain leaks, separate for isolation.

TrapThe index lags behind permission changes. Re-check access in the source system before showing a citation.

Security threats

Stop indirect prompt injectionTreat chunks as data, and gate tool calls.
Stop corpus poisoningVet sources, review before indexing, and keep provenance.
Stop an over-permissioned retrieverSearch as the person asking, not as the app.
Protect the vector storeVectors partly reveal their text. Guard them like the documents.

TipAnyone who can write to the corpus can write to your prompt.

TrapDelimiting chunks helps, but it isn't a control. The real controls sit outside the model.

Speed, caching & high stakes

cut latency, cache safely, and handle high-stakes answers

Cut latency

Say where the time goesMostly the LLM. Search takes tens of ms, decode takes seconds.
Pick the latency targetTime to first token at p95. Streaming hides decode.
Remove serial LLM callsMerge the rewrite and router calls, or search while they run.
Search 100M+ vectors under a latency targetShard, quantize, rescore, and partition on a filter every query has.

TipPrefill grows with context, so cutting 12 chunks to 5 is faster and often more accurate.

TrapWith scatter-gather, p99 is set by the slowest shard, not the average one.

Cache without leaking or going stale

List the cache layersEmbeddings, search results, rerank scores, prompt prefix, answers.
Build a cache keyInclude the model version, index version, tenant and access scope.
Use a semantic cache safelyKeep the threshold high. Skip numeric and time-sensitive queries.

TipProvider prompt caching only hits when the retrieved chunks come after the fixed prefix.

TrapLeave the tenant out of the key and one user's answer is served to another.

Design for legal or medical stakes

Say what the goal becomesMinimize wrong answers. Refusing counts as success.
Filter on authority and dateMake jurisdiction and effective date hard pre-filters.
Check every sentenceMatch each sentence to its cited span. Drop what doesn't match.

TipReport the risk-coverage curve. At what answer rate does error stay under your limit?

TrapThe best text match can still be legally wrong, like a superseded statute.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 56 questions it links, not just the 6 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.