Back to course overview
Module 5Citations & grounding 11 min
Source attribution
Citations as architecture: the verbatim-quote check at pipeline scale, span-level attribution, and citation UX that earns user trust.
In Prompt Engineering you designed the citation schema — source IDs plus verbatim quotes, mechanically checkable. In a RAG pipeline that design stops being a prompt pattern and becomes architecture: every answer flows through a verification gate before anyone sees it.
verify.pypython
def verify_citations(output: dict, chunks: dict[str, str]) -> dict:
"""Returns the output annotated with per-citation verification."""
for c in output["citations"]:
source_text = chunks.get(c["source_id"], "")
c["verified"] = _normalize(c["quote"]) in _normalize(source_text)
output["all_verified"] = all(c["verified"] for c in output["citations"])
return output
def _normalize(s: str) -> str: # whitespace + quote-mark tolerance
return " ".join(s.split()).replace("\u201c", '"').replace("\u201d", '"').lower()- Normalize before matching. Models faithfully copy text but harmlessly vary whitespace and curly quotes; a naive exact match fails honest citations. Normalize both sides; keep the check strict on words.
- A failed verification is a routing signal, not a formatting bug. It means the model asserted something its sources don't contain — exactly the event your fallback ladder exists for: retry with the violation named, or degrade to 'show sources without the claim'.
- Attribute per claim, not per answer — you know this rule; the pipeline now enforces it because unattributed sentences are detectable (a sentence with no adjacent [S#] in a fact-bearing answer).
Citation UX: where trust is actually won
- Cite with display metadata, not internal IDs: 'Holiday Returns → Extended window', linked to the source.
chunk_147impresses nobody. - Show the quote on hover/expand. Users who can check but don't have to are the users who trust you. The checkable-but-unchecked citation is the entire psychology of RAG credibility.
- Don't over-cite. Four citations on one plain sentence reads as noise. One precise citation per claim, deduplicated per source.
- When `answerable` is false, show the nearest sources anyway — 'I couldn't find this in the docs; closest material:' turns a dead end into a hand-off. Users forgive 'not found'; they don't forgive fabrication.
The audit artifact
Store the verified-citation record with each logged answer. Six months later, 'why did the bot say X on March 3rd?' is answered in one lookup: the claim, its quote, its source version (lineage metadata!). That sentence has ended compliance conversations — this is the same explainability discipline our products sell.