Citations are the main way users can trust an AI answer without redoing the work. A claim with a link to its source can be checked in seconds; a claim without one has to be taken on faith. That is why most retrieval-augmented generation (RAG) systems ask models to cite their sources.
The problem is that citations can be wrong in ways that look right. A model can cite a real document that does not support the claim, cite the right document for the wrong sentence, or produce a plausible-looking reference that does not exist at all. This guide covers why citation errors happen, prompting techniques that make citations more accurate, and how to verify them automatically.
How citations go wrong
- Fabricated sources. Without retrieval, models asked for references can produce realistic titles, authors and URLs that do not exist. Never ask a model for sources from memory in a context where accuracy matters.
- Misattribution. The cited source exists and is relevant, but does not say what the claim says.
- Over-citation. Every sentence cites the same source, regardless of where the information came from.
- Uncited synthesis. The model blends retrieved facts with its own knowledge and cites only the parts it retrieved.
- Unsupported filler. Generic statements cite a source because the format demands a citation.
Research on citation quality, such as Gao et al. (2023), "Enabling Large Language Models to Generate Text with Citations," found that even strong models frequently produce citations that do not fully support their statements, which is why verification matters as much as prompting.
Technique 1: give every source a short ID
Label each retrieved passage with a short, unique ID, and ask for those IDs in citations. IDs are easier for models to reproduce exactly than titles or URLs, and easier for your code to check.
<sources>
<source id="S1" title="Refund policy" updated="2026-06-01">
Annual plans can be refunded in full within 30 days of purchase...
</source>
<source id="S2" title="Billing FAQ" updated="2026-08-12">
Pending authorisations usually disappear within 5 business days...
</source>
</sources>Map IDs back to titles and links in your interface, not in the model output.
Technique 2: quote first, then answer
Ask the model to extract the exact quotes that support its answer before writing the answer. Quoting forces it to locate evidence, makes unsupported claims more obvious, and gives your code something concrete to check.
Technique 3: make "not found" a first-class answer
Models fabricate most when the honest answer is unsatisfying. Give an explicit, acceptable response for missing information, and treat it as a success in your evals when the sources really do not contain the answer. Include such cases in your eval set; a system that never says "not found" is guessing.
Technique 4: one claim, one citation
Ask for citations at the claim level, placed immediately after the sentence they support, rather than a list of sources at the end. Claim-level citations make misattribution visible and allow automatic checks per sentence.
Technique 5: separate knowledge from sources
If you allow the model to add general knowledge, make it mark that explicitly ("General knowledge, not from sources:"). Better, for high-stakes domains, forbid it entirely and rely on retrieval.
Verifying citations automatically
Prompting improves citation accuracy; verification catches what prompting misses. Layer checks from cheap to expensive:
| Check | How | Catches |
|---|---|---|
| ID exists | Every cited ID is in the retrieved set | Fabricated sources |
| Quote match | Each quote appears verbatim (or near-verbatim) in its source | Invented quotes |
| Claim support | A model or entailment classifier checks the claim against the quote | Misattribution |
| Coverage | Every factual sentence has a citation | Uncited synthesis |
import re
from difflib import SequenceMatcher
def verify(answer: str, sources: dict[str, str], min_ratio=0.9):
problems = []
for sid, quote in re.findall(r'\[(S\d+)\]\s*"([^"]+)"', answer):
text = sources.get(sid)
if text is None:
problems.append(f"unknown source {sid}")
elif quote not in text:
# allow small differences in whitespace or punctuation
best = max((SequenceMatcher(None, quote, text[i:i+len(quote)]).ratio()
for i in range(0, max(1, len(text) - len(quote)), 20)), default=0)
if best < min_ratio:
problems.append(f"quote not found in {sid}: {quote[:60]}")
return problemsWhen checks fail, you can retry with the error, drop the unsupported claim, or show the answer with a warning. Log failure rates; a rising rate signals problems in retrieval or prompts.
Retrieval quality limits citation quality
A model cannot cite what was not retrieved. If the right passage is missing from the context, the model will either say "not found," which is good, or cite something nearby, which is bad. Improving chunking and retrieval often improves citations more than prompt changes; see RAG chunking strategies compared. And remember that a long context is not a substitute for retrieval; see context windows are not memory.
Showing citations to users
- Make citations clickable and jump to the exact passage, highlighted.
- Show the source title and date; outdated sources are a common source of wrong answers.
- When verification fails for a claim, either remove it or visibly mark it as unverified.
- Let users report a bad citation with one click, and add reported cases to your eval set.
For the system prompt section that sets up grounded answers, see the RAG template in system prompt templates for production. For a second check on high-stakes answers, a grounded self-review step can help; see the red-team yourself prompt.
Citations in long answers and reports
Short answers usually cite one or two sources. Long outputs, such as research summaries, reports and comparisons, bring extra problems: dozens of claims, many sources, and a strong temptation for the model to cite loosely. Three practices help:
- Generate in sections. Produce each section from its own retrieved sources, with its own citations, then assemble. Smaller contexts produce more precise citations.
- Keep a claims table. For high-stakes reports, have the model first output a table of claims, each with a source ID and quote, review or verify the table, and only then write prose from it.
- Cite the newest authoritative source. When several sources say similar things, instruct the model to prefer the most recent official document and to flag conflicts between versions.
Measuring citation quality
Add citation metrics to your eval set:
- Citation precision: the share of citations that support their claim.
- Citation recall: the share of factual claims that have a supporting citation.
- Correct abstention: the share of unanswerable questions answered with "not found."
- Fabrication rate: the share of answers containing unknown IDs or quotes not found in sources.
Track them per release; they move independently of answer accuracy.
Frequently asked questions
Why do LLMs make up citations?
When asked for sources without retrieval, models generate text that looks like a reference based on patterns in training data, which can produce plausible but non-existent sources. Even with retrieval, they may cite a real source that does not support the specific claim.
How do I make an LLM cite its sources accurately?
Give retrieved passages short IDs, ask the model to quote supporting text before answering, require a citation after each claim, provide an explicit "not found" answer, and verify quotes and IDs in code.
Can I automatically check LLM citations?
Yes. Check that cited IDs exist, that quoted text appears in the cited source, and use an entailment model or a calibrated LLM grader to check whether each quote supports its claim.
What should the model do if the sources don't answer the question?
It should say so clearly rather than guessing. Make this an explicit, acceptable answer in the prompt and reward it in your evals when the sources truly lack the information.



