Hallucinations and Model Limitations

The most dangerous LLM failure is not a crash — it is a confident wrong answer. Hallucinations look like expertise: citations, APIs, medical details, legal clauses. Until you treat fluency as orthogonal to truth, every feature you ship will eventually embarrass you in front of a customer or an auditor.

Intuition

An LLM samples plausible continuations. Training rewarded looking like the training distribution, not checking a ledger. When the prompt asks for a fact the weights never reliably stored — or that changed last week — the model still has to emit tokens. Plausible tokens win. That is hallucination: unsupported or false content presented as if it were known.

Sibling limitations share the same root: sensitivity to wording, shallow multi-step reasoning without scaffolding, bias from data, and non-determinism under sampling. Mitigations are engineering: retrieval, tools, validation, evals, and humans on the high-impact path.

How it works

Why hallucinations happen

Taxonomy useful in products

Type Example Typical fix
Factual Wrong capital, fake metric RAG / tools / abstain
Citation Invented DOI or URL Require fetchable sources
Faithfulness Summary adds claims Ground on source text only
Tool / API Invented endpoint fields Schema + live docs tool
Reasoning Arithmetic or logic slip Tools, scratchpads, checks
flowchart TB Q[User question] --> C{Evidence in context or tools?} C -->|yes| A[Answer with citations / fields] C -->|no| U[UNKNOWN / ask clarifying / refuse] A --> V[Validate + policy checks] U --> H[Human or fallback UX]

Broader limitations

Mitigation playbook

  1. Ground — RAG, tools, SQL, calculators for anything that must be true.
  2. Abstain — teach and test “I don’t know” / UNKNOWN paths.
  3. Constrain — structured outputs, low temperature for facts.
  4. Verify — validators, citation link checks, unit tests on extracts.
  5. Evaluate — offline suites for hallucination and faithfulness; sample production traces.
  6. Human-in-the-loop — mandatory for medical, legal, financial, and irreversible actions.

Measuring the problem

You cannot fix what you do not score. Lightweight eval ideas:

Track hallucination rate next to latency and cost. A model that is 200ms faster but invents policy clauses is not a win for a compliance bot.

Product framing for stakeholders

Say clearly: the system drafts; tools and humans certify. UX that shows evidence snippets, confidence labels, and easy “report wrong answer” affordances reduces blind trust. Hide the confidence theater (fake percentage meters) unless they map to a real calibrated signal — users treat “94% sure” as science even when it is not.

In code

Detect empty grounding before you let the model “be helpful”:

def should_abstain(docs: list[str], min_chars: int = 40) -> bool:
    return sum(len(d.strip()) for d in docs) < min_chars


docs = ["", " "]
if should_abstain(docs):
    answer = "UNKNOWN: no supporting documents retrieved."
else:
    answer = "(call model with docs)"
print(answer)

Faithfulness check sketch — every claim sentence must overlap the source (crude but teachable):

def unsupported_sentences(answer: str, source: str) -> list[str]:
    src = source.lower()
    bad = []
    for sent in answer.split("."):
        s = sent.strip()
        if not s:
            continue
        tokens = [t for t in s.lower().split() if len(t) > 3]
        if not tokens:
            continue
        hit = sum(1 for t in tokens if t in src)
        if hit / len(tokens) < 0.3:
            bad.append(s)
    return bad


src = "Refunds arrive in 5 to 7 business days."
ans = "Refunds arrive in 5 to 7 business days. Platinum users get same-day cash."
print(unsupported_sentences(ans, src))

Force an evidence field in structured answers:

import json


def validate_grounded(raw: str) -> dict:
    data = json.loads(raw)
    if data.get("status") == "ok" and not data.get("evidence_spans"):
        raise ValueError("ok answers require evidence_spans")
    if data.get("status") == "unknown" and data.get("answer"):
        raise ValueError("unknown must not include a factual answer")
    return data

Logging for postmortems:

def log_call(prompt_version: str, temperature: float, grounded: bool, text: str):
    return {
        "prompt_version": prompt_version,
        "temperature": temperature,
        "grounded": grounded,
        "preview": text[:160],
    }

What goes wrong

One-line summary

Hallucinations are fluent, unsupported claims from a next-token predictor — contain them with grounding, abstention, validation, evals, and human review.

Key terms