RAG That Works: Why Retrieval Matters More Than the Prompt
Most bad RAG answers are retrieval problems. How RAG works end to end, the three parts of the grounded prompt, how to measure retrieval alone, and when long context is enough.
Key takeaways
- RAG answers from your documents by retrieving the few relevant chunks and grounding the answer in them.
- The generation prompt needs three parts: answer only from the docs, an out when they lack the answer, and a quote for each claim.
- Most bad RAG answers come from chunking and retrieval, not from the prompt.
- Measure retrieval on its own by checking whether the right chunk reaches the top k, before tuning the prompt.
- A large context window is a ceiling, not a target; most production systems combine RAG with a generous context.
Contents
FAQ
Do large context windows make RAG unnecessary?
For one-off jobs over a few documents, stuffing the context can work. For many questions over a large corpus, RAG pays for indexing once instead of every token on every call, and most production systems combine both.
How big should chunks be?
Split by document structure, roughly 500 to 1,500 tokens, with some overlap, then adjust based on retrieval tests.
Sources
Only you and the owner see your answer and rating. Send private feedback
Enjoyed it? Support fx-blog with a coffee.
Related posts
Your LLM Proxy Retries the Wrong Errors
What an LLM proxy has to decide on every failure: limits are per organization, which statuses to retry, why nothing is retried after the first streamed byte, and the headroom headers the API already sends.
Your LLM Demo Works. What Every Call Needs in Production
One timestamp in the system prompt and every call misses the cache. Pricing each call, making failures loud, logging per feature, and treating outside text as untrusted.
Did Your Prompt Change Help? Prove It with an Eval
A model upgrade can change behaviour with no error. What an eval is, the three graders, the held-out slice, and how evals make upgrades routine.
Comments
Oldest firstNo comments yet. Start the conversation.
Part 3 left the test-case generator with cases that compile and pass, and a gap the eval cannot see: the generator cannot test a rule it has never read. The retry policy for webhook deliveries lives in your docs, not in the model.
Ask the generator for tests of that policy without your docs, and it tests a policy it made up. Give it a grounded prompt and it answers "Not covered in the provided docs". Honest, and still wrong if the page is sitting in your docs folder. That second failure belongs to retrieval, and no prompt edit will fix it.
This series, in six parts:
Two phases: index once, retrieve per question
An embedding turns text into a list of numbers so that similar meanings land close together. "Nearest chunks" are the ones closest in meaning to the question. At small scale you don't need a vector database: SQLite and numpy will do.
The prompt's whole job
The generation prompt is short, and three parts of it carry the weight:
Only sets the scope. An out says what to do when the answer is missing, so the model stops instead of guessing. Quoting lets a person check each claim. Once those three are there, the prompt is rarely what failed.
Measure retrieval on its own
So test retrieval without the model. It reuses the cases from part 3:
For the webhook question, step 1 is one line in your eval file: the chunk id of the page that states the policy. When step 2 says that chunk was not in the top k, you know the prompt was never the problem, before you rewrite it.
Doesn't a long context make RAG obsolete?
Current Claude models take a million tokens. Why not paste the whole docs folder?
Try it
The generator now writes tests from your own docs, and you can tell a retrieval miss from a prompt miss. Next you want it running every night over every requirement. That brings the questions a demo never asks: what each run costs, what you log, and what happens when a retrieved doc says "ignore your instructions". Part 5 answers them.
Read this with your AI