Why Models Hallucinate
The mechanism behind confident invention, why asking a model to be accurate does not make it accurate, and the three things that genuinely reduce it: grounding, permission to refuse, and verifiable citations.
The mechanism behind confident invention, why asking a model to be accurate does not make it accurate, and the three things that genuinely reduce it: grounding, permission to refuse, and verifiable citations.
You are adding retries to an API client and ask the model for
the right option name. Back come four tidy lines with a comment
explaining the backoff, built around retry_backoff_seconds=2.
You paste it in and get TypeError: unexpected keyword argument. The library has retry_delay, and has never had
retry_backoff_seconds.
Nothing went wrong in the usual sense. No error, no warning, no hesitation — the model produced the most plausible-looking answer available, and plausible is not the same as true. By the end of this lesson you will know why that happens, which questions provoke it most reliably, why "be accurate" in a prompt does so little, and the three changes that genuinely move the number.
Hallucination is the name for model output that is fluent, confident, correctly formatted, and false. The word is a poor metaphor, because it suggests a malfunction. Nothing malfunctioned. A system that predicts plausible continuations produced a plausible continuation, and there is no separate step where it checks whether that continuation is true.
Picture two dials.
The entire training objective.
Turned up as far as it goes, on every kind of text, billions of times.
Never directly measured.
Where true statements were common in the training text, the plausible continuation happens to be the correct one. Where they were rare, it is not — and the first dial has not moved an inch.
That is what catches people out. With a person, hesitation is a signal — a guesser slows down, hedges, looks away — and it is informative because it is costly. For a model, hedging is a writing style: a confident sentence and a cautious one cost exactly the same to produce.
Random noise would be easy to catch. What you get instead is
correctly shaped, because shape is what the model learned best.
A Python keyword argument is lowercase words joined by
underscores. A citation is author, year, title, journal, volume,
pages. A DOI starts with 10. and a slash. Those patterns are
everywhere in the training text, so they are known cold — far
better known than any rare fact that happens to wear one of
them. When the fact is missing, the shape is still there, and
the shape is what gets filled in.
Think of a forger who has studied ten thousand passports and never one from the country you asked about. What he hands you has a photo page, a machine-readable strip and a serial number in the right format. It will be far more convincing than a blank page, and wrong in the one way that matters.
It also explains why the invented thing is so often the thing
that ought to exist. A library with to_json, from_json and
to_csv is a pattern with an obvious gap in it, so when you ask
how to write YAML, to_yaml is exactly what the pattern
predicts — and exactly what you get. The model is not reporting
on the library. It is completing a series.
A fact is roughly as safe as it was common in the training text. The capital of France survives any amount of paraphrase; a rare, specific string does not. These are the categories where that bites:
A rule of thumb: the more exactly a thing has to match to be worth anything, the less you should accept it unchecked. A paraphrase of a well-known idea has slack, so small errors stay harmless. A URL, a key name or a version number has none — one character off and it is wrong.
Your instruction arrives in the same channel as everything else and is treated the same way: as text that conditions what comes next. It can shift tone, register and format. What it cannot do is hand the model something to check against.
"Do not make things up" asks for a filter on a property the model has no access to. From the inside there is no difference between a fact seen ten thousand times and a phrase assembled a moment ago — both are high-probability continuations, and neither carries a flag saying which it is.
Worse, a firm accuracy instruction can make the failure harder to catch: push hard on confidence and you suppress the hedging language, the one weak signal you had. You get the same wrong answers with the qualifiers stripped off. Asking "are you sure?" fails for the same reason — that is another plausible continuation, and agreement is the plausible continuation of a challenge, so a model will often reverse an answer that was right.
Bad — demands accuracy the model cannot establish, and gets a fluent answer either way.
Good — puts the answer inside the request, so the job is reading rather than recall.
The first prompt contains no documentation at all, so "be accurate" is an instruction with nothing behind it. What it costs you is a wrong key name delivered in the tone of someone who looked it up.
Three changes actually move the number, and they only work together.
Put the facts in the request
Turns a closed-book exam into an open-book one, opened at the right page. Recall is hard and unverifiable; finding a sentence in a document you were just handed is neither.
Make refusing an allowed answer
Otherwise, when the answer is not in the source, the model bridges the gap with something that fits the surrounding text beautifully.
Make the claims checkable by code
A verbatim quote and a source id per claim turns verification into a string comparison — not another model call, and not a careful human read.
Grounding means supplying the source text in the request and requiring the answer to come from it. It turns the closed-book exam into an open-book one — and not merely open-book, but open at the right page. Recall is hard and unverifiable; finding a sentence in a document you were just handed is much easier and far likelier to be right.
Two details decide whether this works or half-works. First, the instruction has to be exclusive. "Using only the source below" is a different instruction from "using the source below". Without the word only, the model blends what you gave it with what it recalls, and the blend is the worst outcome available: mostly correct, quietly wrong in one place, wearing the authority of your document.
Second, the answer has to actually be in the source. If it is not, and refusing is not possible, you have made things worse — the model will bridge the gap with something that fits the surrounding text beautifully. Grounding without a refusal route is a trap, which is why the next fix is not optional.
Refusing is genuinely hard for a model, and the reason matters. In nearly all the text it learned from, a question is followed by an answer; "I don't know" is rare, and where it appears it often reads like a failure. So every prompt carries an instruction you did not write: produce something. Unless you say otherwise, the highest-probability continuation of a question is an answer, whether or not the material for one exists.
The fix is to make not-answering a first-class output: name the exact string, state its condition, and forbid the half-measure.
Bad — asks for a judgement the model cannot make, returned as prose your code cannot read.
Good — names one exact output and the condition for it.
"If you are not sure" gets you "I believe the value is around 30 seconds, though you may want to confirm" — a hallucination wearing a hedge, which your parser treats as an answer and your reader believes.
The third fix changes what you ask for so that a machine can test the answer: prefer output whose truth can be decided by ordinary code against something you already have. Once you are grounded you have the source, so the check is a string comparison — not another model call, not a careful human read. The form that does it is a verbatim quote and a source id on every claim.
Bad — produces authoritative citations a human must check one at a time, against the world.
Good — asks for the same claims plus the evidence, in fields you can test.
Now the verification is ordinary software, and it is short:
"Section 3.2" may not exist, and finding out costs a person a minute per claim — so nobody does it after the third one. The quote version answers the same question in microseconds and cannot be talked round.
Be clear about what this proves. A matching quote shows the sentence is real and really in that report. It does not show the claim follows from it — a real sentence can still be summarised into something it does not say. What it removes is the whole class of invented sources, where most of the damage is.
They lower the rate. They do not take it to zero, and no prompt does. A grounded, refusal-enabled, quote-checked answer can still misread a real source, quote accurately and frame the quote wrongly, or refuse a question the document did answer. They change the odds; that is all.
So the last move is not a prompt at all — it is designing the feature so that being wrong is survivable. Show the source beside the answer, so a reader checks in two seconds instead of trusting. Keep the action reversible. Put a person in front of anything expensive, public or irreversible. Where a wrong answer costs a shrug, lean on the model; where it costs a customer, a human stays in the loop.
And you cannot tell whether any of it helped by reading a few outputs and feeling better. Knowing your rate went from one in five to one in fifty needs a fixed set of inputs and a score — the subject of Measuring Instead of Vibing later on.
You have the mechanism and what follows from it: fluency is free and correctness is not, invention arrives correctly formatted, rare and exact strings are where it lands, and "be accurate" has nothing behind it. Against that, three moves that work — ground the answer, allow a refusal, demand evidence a machine can check.
All three lean on one assumption: that the facts are in the request. Giving the Model Your Data takes that apart. It answers what this lesson did not — who puts the facts there, and how you choose between pasting them in, fetching them at query time, or handing the model a tool to fetch them.
Before that, run the experiment. Take a document you have — a README, a policy, an incident report — and ask a question about it cold, with no source attached. Note the answer. Then paste the document in, add "using only the source below" and a refusal string, and ask something the document genuinely does not cover. If you get the refusal, your instruction is exclusive enough. If you get a confident answer instead, you have just watched the gap being bridged — and you will recognise it everywhere now.
You are a meticulous research assistant. Be accurate and do
not make anything up. Only refer to options that really exist.
Which configuration key sets the connection retry delay in
version 4 of the client library?Answer using only the documentation below. If the answer is
not in it, reply with exactly: NOT_IN_DOCS
--- documentation ---
retry_delay (float) seconds to wait before the first retry
max_retries (int) how many times a request is retried
--- end documentation ---
Which configuration key sets the connection retry delay?Answer from the source below. If you are not sure, say so.Answer using only the source below.
If the source does not contain the answer, reply with exactly:
INSUFFICIENT_CONTEXT
Do not answer partially. A partial answer is worse than
INSUFFICIENT_CONTEXT: the caller cannot tell it from a
complete one.Summarise the incident reports below. Include a citation for
each claim.Payment failures peaked at 14:05 (Incident Report 2231,
section 3.2).Summarise the incident reports below. Return JSON. For every
claim include the report id and one sentence copied word for
word from that report that supports it.THE MECHANISM
fluent trained for directly -> always on
correct never trained for -> only via what you supply
hedging a writing style -> not a confidence report
HIGH-RISK ASKS (ground it, or verify before you use it)
citations, DOIs, pages function and library names
ids, hashes, package names keyword arguments, CLI flags
prices, dates, counts, % anything about your own data
anything recent anything rare, new or unique
WHAT DOES NOT WORK
"be accurate" -> nothing behind it to check
"do not make things up" -> it cannot tell which those are
"be confident" -> drops the hedge, keeps the error
"are you sure?" -> often flips a right answer
WHAT DOES WORK
1 GROUND put the source text in the request
say "using ONLY the source below"
confirm the answer is genuinely in there
2 REFUSE give one exact refusal string, e.g. NOT_IN_SOURCE
forbid partial answers explicitly
count refusals apart from failures
3 CHECK require a verbatim quote + source id per claim
reject a claim whose quote is not in that source
checking is string matching, not a second model
DESIGN RULE
source beside the answer; reversible action; a person
approves anything expensive, public or permanent{
"claims": [
{
"text": "Payment failures peaked in the early afternoon.",
"report_id": "inc-2231",
"quote": "Between 14:00 and 14:10 failures rose to 38%."
}
]
}import re
def normalise(text):
"""Spacing and capitalisation are not disagreements."""
return re.sub(r"\s+", " ", text).strip().lower()
def is_supported(claim, reports):
"""True when the quote is really in the report it names."""
report = reports.get(claim["report_id"], "")
return normalise(claim["quote"]) in normalise(report)
supported = [claim for claim in claims
if is_supported(claim, reports)]