Lesson 9: Detecting & Reducing Hallucinations
Grounding, RAG, citations, self-checking prompts, and workflow design — the practical toolkit for trustworthy LLM output.
The Verification Toolkit
You cannot eliminate hallucinations — but you can architect systems that catch them. These techniques stack; use more of them for higher-stakes tasks.
1. Grounding (Give the Model Facts)
Never ask the model to recall facts you already have. Put the source material in the prompt:
Answer ONLY using the document below. If the answer is not in the
document, say "Not found in the provided document."
DOCUMENT:
[your data here]
2. RAG (Retrieval-Augmented Generation)
For large knowledge bases, retrieve the relevant chunks (Lesson 5, 13) and ground the answer in them. This is the professional standard for chatbots over your own data.
3. Citations & Traceability
Require the model to cite which part of the provided text supports each claim:
"Answer with inline references like [section 2.3] or [doc 1, para 4]. If a claim is unsupported, label it UNSUPPORTED."
Then a human (or a checker script) can verify.
4. Structured Self-Check Prompts
- Ask the model to quote the evidence before answering.
- Ask it to list assumptions it made.
- Give it the option to say "unknown" — explicitly rewarding honesty over completion.
- Run a second pass: "Review your previous answer. Which claims are not supported by the source? Revise."
5. Post-Processing Checks
| Check | Catches |
|---|---|
| Regex/JSON schema validation | Format hallucinations |
| Known-entity whitelist | Invented names/IDs |
| Citation-to-source matching | Fabricated references |
| Round-trip checks (summarize → re-read) | Drift |
| Human review for high stakes | Everything else |
6. Calibrate the System, Not the Model
| Lever | Effect |
|---|---|
| Lower temperature (0–0.3) | Fewer random inventions |
| Smaller, focused prompts | Less room to drift |
| Grounding + RAG | Eliminates the "recall from nowhere" problem |
| Allowed answer: "I don't know" | Removes the pressure to invent |
| Human-in-the-loop review | Catch what automation misses |
A Simple Grounding Prompt Template
You are a fact-checked assistant. Rules:
1. Answer ONLY from the CONTEXT below.
2. Quote the relevant CONTEXT line before each claim.
3. If CONTEXT does not contain the answer, reply exactly:
"I cannot answer from the provided context."
CONTEXT:
{context}
Key Takeaways
- Ground every important answer in source material — never free-recall.
- Give the model permission to say "I don't know".
- Require citations and add automated checks on top.
- Stack techniques: grounding + RAG + verification + human review.
Next up: Agentic loops — turning LLMs from single-shot answerers into multi-step workers.
# Reducing hallucinations: verify model answers against a source of truth
source = {
"Paris": "Capital of France since 508 AD.",
"Python": "Created by Guido van Rossum in 1991.",
}
def verify_answer(model_answer):
for fact, truth in source.items():
if fact in model_answer:
return f"Verified: {truth}"
return "Unverified - please check the source or add citations."
print(verify_answer("The capital of France is Paris."))
print(verify_answer("The moon is made of cheese."))
# A grounded generation prompt: the model may only use CONTEXT
def grounded_answer(question, context):
# Simple relevance check: does the context mention the topic?
topic = question.split()[-1].strip("?")
if topic.lower() in context.lower():
return f"Based on context: {context}"
return "I cannot answer from the provided context."
print(grounded_answer("Who created Python?", "Python was created by Guido van Rossum in 1991."))
print(grounded_answer("What is the price of tea?", "Python was created by Guido van Rossum in 1991."))Lesson Code (Python)
# Reducing hallucinations: verify model answers against a source of truth
source = {
"Paris": "Capital of France since 508 AD.",
"Python": "Created by Guido van Rossum in 1991.",
}
def verify_answer(model_answer):
for fact, truth in source.items():
if fact in model_answer:
return f"Verified: {truth}"
return "Unverified - please check the source or add citations."
print(verify_answer("The capital of France is Paris."))
print(verify_answer("The moon is made of cheese."))
# A grounded generation prompt: the model may only use CONTEXT
def grounded_answer(question, context):
# Simple relevance check: does the context mention the topic?
topic = question.split()[-1].strip("?")
if topic.lower() in context.lower():
return f"Based on context: {context}"
return "I cannot answer from the provided context."
print(grounded_answer("Who created Python?", "Python was created by Guido van Rossum in 1991."))
print(grounded_answer("What is the price of tea?", "Python was created by Guido van Rossum in 1991."))Console Output
Verified: Capital of France since 508 AD.
Unverified - please check the source or add citations.
Based on context: Python was created by Guido van Rossum in 1991.
I cannot answer from the provided context.Code Visualization Tips
- Draw the 'grounding sandwich': CONTEXT above and below the answer — the model reads facts, then writes within them.
- Diagram the RAG verification loop: Answer → Cite → Check against source → Pass/Reject.
- Make a checklist poster of the 6 levers: grounding, RAG, citations, self-check, post-checks, human review.
Professional Tips & Tricks
- The phrase 'answer only from the context' alone cuts hallucinations dramatically — make it your default.
- Add 'quote the evidence first' for any answer that will be shared externally.
- For numbers: 'if the number is not in the source, say UNKNOWN' — never let the model estimate.
Python Code Judge & Practice Arena
LeetCode StyleRun real Python 3.12 WebAssembly code directly in your browser against automated test suites.
Write a Grounding Prompt
Up next · Continue learning
What Is an Agentic Loop?
One prompt = one answer. An agentic loop = the model plans, acts, observes, and repeats until the job is done.