How to tell whether your RAG assistant is any good
A test-set approach that needs no code: retrieval, correctness, grounding and honest refusals.
A RAG assistant that answers fluently is not necessarily a RAG assistant that answers correctly. Fluency is the model's strength; correctness depends on the whole pipeline. Without measurement you will ship changes that feel better and quietly make things worse. Here is a practical way to measure, using nothing more complicated than a spreadsheet to start.
Split the system, then measure each half
A RAG system has two jobs, and they fail in different ways:
- Retrieval: did we fetch the right passages?
- Generation: given those passages, did the answer stay faithful to them and address the question?
If you only grade final answers, you cannot tell which half to fix. Grade both.
Step 1: build an evaluation set
Collect 30 to 100 real questions, ideally from actual users or the people who will use the system. For each, record:
- The question, in the user's own words.
- The document and passage that contain the answer.
- A short reference answer, or key facts the answer must include.
- Include some questions that should not be answerable from your documents.
This set is worth more than any tool. Keep it in version control and grow it every time you find a failure.
Step 2: measure retrieval
For each question, run only the retrieval step and check whether the known correct passage appears in the top results.
- Hit rate at k: the share of questions where the right passage is in the top k results.
- Mean reciprocal rank: rewards putting the right passage near the top.
def hit_rate_at_k(eval_set, retrieve, k=5):
hits = 0
for item in eval_set:
results = retrieve(item["question"], top_k=k)
if any(r["source_id"] == item["source_id"] for r in results):
hits += 1
return hits / len(eval_set)
If retrieval is weak, no prompt improvement will save you. Fix chunking, embeddings, search settings or metadata first.
Step 3: measure the answers
For each question, review the generated answer on three separate questions:
- Correct: does it match the reference facts?
- Grounded (faithful): is every claim supported by the retrieved passages, or did the model add something from its own memory?
- Complete and relevant: does it answer what was asked, without padding?
Score each on a simple scale (for example pass, partial, fail) and keep the notes. Human review of a modest sample beats an elaborate automatic score you have not verified.
Step 4: test the "I don't know" behaviour
Ask the questions that cannot be answered from your documents. A good assistant declines or says the information is not available; a poor one invents something plausible. Track the share of unanswerable questions it handles correctly. This is a safety property, not a nicety.
Using a model as a judge, carefully
You can ask another model to grade answers against the reference. It scales well, and it has pitfalls: it tends to prefer longer, confident answers, and it can share the blind spots of the system it grades. If you use it, calibrate: compare its scores with human scores on a sample, and re-check whenever you change the judge prompt.
Track it over time
- Re-run the evaluation after every change to chunking, embeddings, prompts, models or documents.
- Record the scores in a table with the date and what changed.
- Watch for regressions in questions that used to pass, not only the average.
Common mistakes
- Testing with three questions the developer wrote and calling it evaluated.
- Only checking answers that look good.
- Changing several things at once, so you cannot tell what helped.
- Never testing unanswerable questions.
- Trusting an automatic judge without comparing it to human review.
A minimal starter table
| Question | Right passage retrieved? | Answer correct? | Grounded? | Notes |
|---|---|---|---|---|
| ... | yes / no | pass / partial / fail | yes / no | what went wrong |
Try it yourself
Write 20 questions about a document you know well, five of which the document cannot answer. Run your assistant, fill in the table, and pick the single most common failure. Fix only that, re-run the same 20, and see whether the table improved. That loop is the whole discipline.
Keep learning
How this is used in practice
Typical use cases
- Regression tests before a release: a fixed question set scored for retrieval hit-rate and answer grounding.
- Production sampling: review a slice of live answers for unsupported claims.
- Choosing between configurations: compare chunk size, embedding model or reranker on the same set.
General examples of where this idea is applied, not tied to a particular company.
Real-world write-ups
Summaries are ours, in our own words; follow the links for the full detail. Each source was opened and checked on the date shown.
Tools and infrastructure in this guide
Mapped to our tools and tech stack.
Further reading and tools
Official documentation, papers and code referred to in this guide. Links open in a new tab.
More guides
Book a call
Tell us your background and goal — we'll map a course path that fits.
Talk to an advisor