DAY 11 / PHASE 1 · ENGINEERING

Hallucination Engineering

RLHF Bias · Token Risk Map · Grounding Stack · Calibration Eval

2026-05-27 · BigCat

Hallucination is not a prompting problem — it is a structural side effect of the RLHF training objective. This issue starts with a token-level risk map and decomposes "make the model lie less" into four engineerable layers.

// WHY THIS MATTERS

The awkward 2025 reality: Claude 4.7 / GPT-5 still post 5–15% hallucination rates on SimpleQA and HaluEval, and the more specific the question, the more elaborate the fabrication. Even more counter-intuitive — models actually know they don't know. Kadavath et al. (2022) showed that the last hidden layer carries a strong P(True) signal, yet the generated output almost never says "I don't know." That gap isn't something prompt engineering can close — it's the structural result of RLHF reward models systematically preferring confident answers over abstentions. This issue assumes you already know what hallucination is and what RAG is (last week); we go straight into four engineering layers: ① understanding the RLHF bias mechanism → ② knowing which tokens are ~100% fabricated → ③ a three-layer grounding stack → ④ hallucination-aware eval. Every layer maps to actual code or config changes — not just "write a better prompt."

Token-level hallucination risk map (by real-world incident frequency) Risk level Typical token Fabrication rate ────────────────────────────────────────────────────────────────────── ★★★★★ Fatal URL / DOI / arXiv ID ~95% paper title + author combos ~80% function signatures (library + version) ~70% commit hash / line number ~85% specific dates (YYYY-MM-DD) + event ~60% ────────────────────────────────────────────────────────────────────── ★★★★ Dangerous legal clause numbers / case name ~50% drug dosage / clinical data ~40% company earnings numbers ~45% person's exact title + tenure ~35% ────────────────────────────────────────────────────────────────────── ★★★ Caution historical event years ~15% country / city statistics ~20% book publication years ~12% ────────────────────────────────────────────────────────────────────── ★ Safe common sense / physics / math facts < 3% core facts about high-frequency public figs < 5% Rule: fabrication ≈ specificity × rarity / training-coverage the more "precise & rare" the token, the exponentially higher the rate
// 01

Hallucination Isn't a Bug — RLHF Trained "Don't Say I Don't Know" Into Models

Claim: a pretrained-only base model (no RLHF) outputs low-entropy distributions or meta-commentary ("I'm not sure") when uncertain. RLHF stage human annotators systematically prefer "confident answer" > "I don't know" — so the reward model penalizes abstention. The model learns to substitute fabrication for honesty. This is not a prompt engineering problem; it's a training-objective problem.

Background & mechanism

The core evidence is OpenAI's 2025 paper "Why Language Models Hallucinate": a controlled experiment showing the same base model has a higher hallucination rate after RLHF than before. Decomposed: (1) pretraining uses cross-entropy loss, so the optimal model matches the true probability distribution including "this token should have 30% probability of being X" — uncertainty is preserved; (2) RLHF uses pairwise reward, and annotators shown "I don't know" vs. "specific but possibly wrong" prefer the latter (because the former is "unhelpful") — the reward model encodes this preference; (3) during RL fine-tuning, the model abandons calibration to maximize reward, producing the most confident answer rather than the most truthful distribution.

Anthropic's Kadavath et al. 2022 made this concrete with linear probes: on the last hidden state of a base model, a few hundred samples train a P(True) probe with AUC > 0.85 — meaning the model internally knows it doesn't know. But the post-RLHF generation manifold has been collapsed toward a confident pole by the reward signal. So the engineering response is not "make the model smarter" — it is to restore the calibration signal, via logprobs, self-consistency, or an explicit prompt frame that gives abstention positive weight.

Tactic

Give the model an "abstention-is-legitimate" frame + use logprobs to calibrate confidence (OpenAI / Anthropic both support this):

import anthropic, math
client = anthropic.Anthropic()

# —— Key 1: system prompt explicitly rewards "I don't know" ——
SYS = """You will be asked a factual question. Your response MUST start
with one of three tokens, then explain:
  KNOWN: I am confident in the answer and can cite the source class.
  UNSURE: I have partial information but cannot verify specifics.
  UNKNOWN: I do not know; do not speculate.
Saying UNKNOWN when uncertain is rewarded, not penalized.
Hallucinating a specific answer is the worst outcome."""

def ask(q):
    msg = client.messages.create(
        model="claude-opus-4-7",
        max_tokens=300,
        system=SYS,
        messages=[{"role":"user","content":q}]
    )
    return msg.content[0].text

# —— Key 2: extract token-level uncertainty via logprobs (OpenAI API) ——
# Claude doesn't expose logprobs yet; OpenAI / Gemini / open-source do.
from openai import OpenAI
oa = OpenAI()

def answer_with_confidence(q):
    r = oa.chat.completions.create(
        model="gpt-5", messages=[{"role":"user","content":q}],
        logprobs=True, top_logprobs=5
    )
    text = r.choices[0].message.content
    # average token logprob → perplexity → uncertainty proxy
    logprobs = [t.logprob for t in r.choices[0].logprobs.content]
    avg_lp = sum(logprobs)/len(logprobs)
    conf = math.exp(avg_lp)  # 0~1
    if conf < 0.5: text = f"[LOW-CONF {conf:.2f}] " + text
    return text, conf

# —— Key 3: self-consistency as a fallback signal (without logprobs) ——
# Run the same question 5x at temperature=0.7; high divergence → untrustworthy
def consistency_check(q, n=5):
    answers = [ask(q) for _ in range(n)]
    return answers
Failure modes: (1) writing "do not fabricate" in the system prompt — this instruction is mostly ineffective, the model still hallucinates (see W9 on negation failure); you need a positive incentive for abstention; (2) self-reported confidence ("on a scale of 1-10...") — research repeatedly shows this is backward rationalization; models grossly over-rate themselves (Tian et al. 2023). Use logprobs or self-consistency instead; (3) treating KNOWN/UNSURE/UNKNOWN tags as user-facing answers — users don't parse three-tier semantics; do UI-level color coding or rewrite as "I don't know" / "I estimate that..." in natural language.
Going deeper · OpenAI Why Language Models Hallucinate (2025), openai.com/research/why-language-models-hallucinate · Kadavath et al. Language Models (Mostly) Know What They Know, arxiv.org/abs/2207.05221
// 02

Which Tokens Are Almost 100% Fabricated: the Specificity Reverse Principle

Claim: hallucination is not uniformly distributed — it concentrates on specific and rare token classes. URLs, DOIs, arXiv IDs, commit hashes, function signatures, and citation page numbers are six danger zones with 70–95% fabrication rates. The more specific the question, the more elaborate the fabrication — call this the "specificity reverse principle," a first-class engineering assumption.

Background & mechanism

Why do these six token classes hallucinate so absurdly often? The root cause: they have weak statistical signatures in the pretraining corpus. URL strings, commit hashes — these are "high-entropy non-inferable" literal strings with no generalizable semantic regularity, only verbatim memorization. At positions the model hasn't memorized, next-token sampling generates "plausible-looking" characters (URL-shape correct, function-name style correct, date format correct), but the underlying distribution is nearly uniform — the model has no idea it's making things up. OpenAI 2025 quantifies this: when prompted to produce an "arXiv paper ID," gpt-4-class models output format-correct but nonexistent IDs in > 50% of cases.

Even more counter-intuitive is the specificity reverse principle: ask "list 3 papers on Transformers" — fabrication rate ~30%. Ask "list 3 papers from ICLR 2023 on Transformer attention optimization, with title, authors, arXiv ID" — fabrication rate > 80%. The more specific the question, the more hallucination is activated, because the prompt pushes the model into a specific but training-sparse region of state-space, and the only fallback is "style-completing the details." This contradicts human intuition — we expect that asking more specifically yields more precision — so engineering must make this a first-class assumption: actively detect, actively ground.

Specificity Reverse Principle, measured Prompt 1 (broad): "List some Transformer optimization directions" → accuracy 85% (all the directions exist) Prompt 2 (more specific): "List 3 ICLR 2023 Transformer papers" → accuracy 30% (half the titles right, half the authors made up) Prompt 3 (maximum specificity): "List 3 ICLR 2023 Transformer papers with arXiv ID, first-author email, page numbers" → accuracy < 5% (almost entirely fabricated) ✗ User intuition: more specific → more accurate ✓ Engineering reality: more specific → more fabrication Response: detect high-risk token classes → force grounding (tool / RAG) or refuse to generate ("this kind of detail requires verification")

Tactic

Use regex + LLM-as-judge to detect high-risk tokens; rewrite or refuse when necessary:

import re

# —— High-risk token class regexes (scan LLM output) ——
RISK_PATTERNS = {
    "url":        r'https?://[^\s)]+',
    "arxiv":      r'arXiv:\d{4}\.\d{4,5}',
    "doi":        r'10\.\d{4,9}/[-._;()/:A-Za-z0-9]+',
    "commit":     r'\b[a-f0-9]{7,40}\b',
    "fn_call":    r'\b[a-z_]+\.[a-z_]+\([^)]*\)',
    "exact_date": r'\b\d{4}-\d{2}-\d{2}\b',
    "page_num":   r'\b(?:p\.?|page)\s*\d{1,4}\b',
    "isbn":       r'\bISBN[-: ]?(?:\d{9}[\dX]|\d{13})\b'
}

def scan_high_risk(text):
    hits = {}
    for kind, pat in RISK_PATTERNS.items():
        m = re.findall(pat, text)
        if m: hits[kind] = m
    return hits

# —— Usage 1: post-generation audit ——
def answer_with_risk_audit(q):
    raw = ask(q)
    risks = scan_high_risk(raw)
    if risks:
        # trigger grounding: verify each URL / DOI via web search tool
        verified = verify_with_tools(raw, risks)
        return verified
    return raw

# —— Usage 2: proactively counter specificity-reverse at prompt time ——
SAFE_SPECIFICITY = """When asked for citations, URLs, function signatures,
or exact numeric details: DO NOT fabricate.
- If you cannot verify the exact reference, say "I recall a paper by [author class] on [topic]
  around [approximate year] but cannot verify the exact title/ID."
- Prefer naming conventions over fabricated specifics:
  "the original Transformer paper (Vaswani et al. ~2017)" is preferred over
  "Vaswani et al., 'Attention is All You Need', arXiv:1706.03762" if uncertain."""

# Note: well-remembered facts keep their detail; uncertain ones degrade gracefully
Failure modes: (1) scanning without acting — detection is only step one, you must ground/verify, rewrite, or annotate "[unverified]"; (2) regex false positives — \b[a-f0-9]{7,40}\b matches "abcdef0"; combine with context (require nearby "git" / "commit" keyword); (3) treating specificity suppression as deleting all specifics — wrong; well-remembered high-frequency facts ("Python sort uses Timsort") should keep their detail; only degrade rare/low-frequency tokens; (4) treating "specificity reverse" as an iron law — it's a tendency, not absolute. In domains with high training coverage (mainstream library APIs), specificity actually improves accuracy. Calibrate per domain.
Going deeper · Min et al. FActScore: Fine-grained Atomic Evaluation of Factual Precision (EMNLP 2023), arxiv.org/abs/2305.14251 · Manakul et al. SelfCheckGPT (EMNLP 2023), arxiv.org/abs/2303.08896
// 03

The Grounding Stack: Tool Fact-check / Structured Output / Verification Chain

Claim: a single line of defense always leaks. Production hallucination mitigation needs three layers stacked: (A) tool-grounded fact-check forces high-risk tokens through external verification; (B) structured output schema uses grammar/JSON enums to outright forbid fabrication space; (C) verification chain uses a different LLM with a different prompt angle to independently audit. Together, on FActScore, these cut hallucination rate to a quarter or a third of baseline.

Background & mechanism

The engineering rationale for each layer:

Stacked ROI: Min et al. FActScore measurements — pure generator hallucination rate ~25%, plus tool grounding drops to ~12%, plus structured output to ~7%, plus verification chain to ~5%. Each layer independently contributes 30–50%, and the failure modes don't overlap (what tool misses, structured catches; what structured misses, verifier catches).

Three-layer grounding architecture ┌─────────────────── USER QUERY ──────────────────┐ │ │ │ ┌── Generator (Claude Opus) ──────────────────┐ │ │ │ Produce draft answer + self-tag │ │ │ │ KNOWN/UNSURE/UNKNOWN │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌── Layer A · Tool fact-check ────────────────┐ │ │ │ scan_high_risk(answer) │ │ │ │ ├ URL → web_search.verify(url) │ │ │ │ ├ DOI → semantic_scholar.lookup(doi) │ │ │ │ └ commit → github.exists(repo, hash) │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌── Layer B · Structured output ──────────────┐ │ │ │ enforce JSON schema with enum + strict │ │ │ │ citation MUST be from verified set OR null │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌── Layer C · Verification chain ─────────────┐ │ │ │ Verifier = different model (Haiku / GPT) │ │ │ │ prompt: "list facts that COULD be wrong" │ │ │ │ flag any unverifiable claim │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ └──────────────────┼────────────────────────────────┘ ▼ FINAL ANSWER (claims that failed verification are tagged [unverified])

Tactic

Minimal three-layer implementation (generator → tool verify → structured → verifier):

import anthropic, json, re
client = anthropic.Anthropic()

# —— Layer A: tool fact-check ——————————————————————
TOOLS = [{
    "name":"verify_citation",
    "description":"Verify if a citation (arXiv ID, DOI, URL) actually exists.",
    "input_schema":{"type":"object","properties":{
        "identifier":{"type":"string"},
        "kind":{"type":"string","enum":["arxiv","doi","url"]}
    },"required":["identifier","kind"]}
}]

def verify_citation(identifier, kind):
    # Real impl: call Semantic Scholar / arXiv API / HEAD request
    if kind == "arxiv":
        return arxiv_api.exists(identifier)
    # ...

# —— Layer B: structured output with strict schema ——————
ANSWER_SCHEMA = {
    "type":"object",
    "properties":{
        "answer":{"type":"string"},
        "confidence":{"type":"string",
                       "enum":["known","unsure","unknown"]},
        "citations":{"type":"array",
                      "items":{"type":"string",
                              "description":"Must be in verified_set or omitted."}}
    },
    "required":["answer","confidence"]
}

def generate(q, verified_citations):
    return client.messages.create(
        model="claude-opus-4-7", max_tokens=800,
        tools=TOOLS,
        system=f"Cite only from this verified set: {verified_citations}. "
               "Set confidence=unknown rather than guessing. "
               "Output JSON conforming to the response_format schema.",
        messages=[{"role":"user","content":q}]
    )

# —— Layer C: verifier (different model / different prompt) ——
def verify(answer_json, question):
    # Use Haiku as a cheap verifier; flip prompt angle to "find flaws"
    msg = client.messages.create(
        model="claude-haiku-4-5-20251001", max_tokens=400,
        system="You are a strict fact-checker. List every claim "
               "in the answer that CANNOT be verified from common knowledge. "
               "Output JSON: {unverifiable: [...]}",
        messages=[{"role":"user","content":
            f"Question: {question}\nAnswer: {json.dumps(answer_json)}"}]
    )
    return json.loads(msg.content[0].text)

# —— Pipeline ——————————————————————————————————————————
def grounded_answer(q):
    draft = quick_draft(q)                       # Layer 0: draft
    risks = scan_high_risk(draft)                 # from §02
    verified = {k: [v for v in vs if verify_citation(v,k)]
                for k,vs in risks.items()}         # Layer A
    final = generate(q, verified)                 # Layer B (structured)
    flags = verify(final, q)                      # Layer C
    return annotate_unverified(final, flags)
Failure modes: (1) all three layers use the same model — shared bias means verifier rubber-stamps generator's hallucination; cross-family is mandatory; (2) structured output too rigid — schema must NOT have required: ["citations"], or the model is forced to fabricate; citations are always optional; (3) verifier prompt phrased as "is this correct" — triggers sycophancy, the verifier tends to agree with the generator; phrase it as "list unverifiable claims" (steelman in reverse); (4) tool fact-check has no timeout — one slow API hangs the whole pipeline; use async + p95 cutoff; (5) overhead too high — three layers serially means 3–4× latency; only run the full chain on high-risk queries (containing citation/numeric/date), skip verifier on simple ones.
Going deeper · OpenAI Structured Outputs Guide, platform.openai.com/docs/guides/structured-outputs · Outlines Grammar-constrained generation, github.com/dottxt-ai/outlines · Anthropic Reducing hallucinations, docs.anthropic.com/.../reduce-hallucinations
// 04

Hallucination-aware Eval: Stop Looking at Accuracy, Look at Abstention & Calibration

Claim: most hallucination evals still use accuracy@all — and this metric does not distinguish "correct" from "willing to answer". By construction it rewards "confident fabrication" with high scores. The right metric trio: coverage-accuracy curve (how much do you answer × how often are you right) + calibration ECE + abstention F1. These metrics expose the truth that polished post-RLHF models hide in benchmark rankings.

Background & mechanism

The root cause is benchmark design misalignment. SimpleQA, TriviaQA, HaluEval all use accuracy = correct / total — but this lumps "I don't know" with "wrong answer" at zero points. The optimal model strategy becomes: never abstain, always be confident. This perfectly rewards the bias RLHF already installed; eval and training objective push hallucination the same way.

The 2024–2025 academic consensus shifted to the selective prediction framework: split the model into two components — (1) answer function: produce a concrete answer; (2) confidence function: self-rate reliability. Evaluation trio:

The key insight from OpenAI's 2025 Why-Hallucinate paper: under selective scoring, the "reasonable ranking" of all major models reshuffles — some benchmark leaders are calibration-bottom-feeders. If your application is hallucination-sensitive (medicine, law, finance, research), you cannot trust benchmark rankings; you must run selective eval yourself.

Coverage-Accuracy curve comparison acc 100│● │ ● 90│ ●← Model A: high calibration (abstains more, high correct rate) │ ● 80│ ● │ ● ●─── Model B: low calibration 70│ ● ● (answers more but wrong more) │ ● ● 60│ ● │ ● 50└─────────────────────→ coverage 0% 20% 40% 60% 80% 100% AUC(A) > AUC(B) → A is more valuable in production even if acc(A) < acc(B) at 100% coverage Traditional acc@100% only looks at the right endpoint → misses A's advantage

Tactic

A minimal selective-eval framework (model-agnostic):

import numpy as np
from sklearn.metrics import auc

# data: list of (question, gold_answer, model_answer, model_confidence)
# model_confidence ∈ [0,1] — logprob avg / self-report / consistency rate

def coverage_accuracy_curve(samples):
    # sort by confidence descending
    sorted_s = sorted(samples, key=lambda s: -s["conf"])
    points = []
    correct_so_far = 0
    for i, s in enumerate(sorted_s, 1):
        correct_so_far += int(s["correct"])
        coverage = i / len(sorted_s)
        accuracy = correct_so_far / i
        points.append((coverage, accuracy))
    return points  # plot + AUC

def ece(samples, n_bins=10):
    # Expected Calibration Error
    bins = np.linspace(0, 1, n_bins+1)
    ece_val, total = 0.0, len(samples)
    for i in range(n_bins):
        bucket = [s for s in samples
                  if bins[i] <= s["conf"] < bins[i+1]]
        if not bucket: continue
        avg_conf = np.mean([s["conf"] for s in bucket])
        acc = np.mean([s["correct"] for s in bucket])
        ece_val += (len(bucket)/total) * abs(avg_conf - acc)
    return ece_val   # lower is better; <0.05 is very good

def abstention_f1(samples, gold_difficulty):
    # gold_difficulty: which questions SHOULD be abstained (hard set / OOD set)
    tp = sum(1 for s in samples
             if s["abstained"] and gold_difficulty[s["id"]] == "hard")
    fp = sum(1 for s in samples
             if s["abstained"] and gold_difficulty[s["id"]] == "easy")
    fn = sum(1 for s in samples
             if not s["abstained"] and gold_difficulty[s["id"]] == "hard")
    precision = tp / (tp + fp + 1e-9)
    recall = tp / (tp + fn + 1e-9)
    return 2 * precision * recall / (precision + recall + 1e-9)

# —— Reporting ——
def selective_report(samples, gold_difficulty):
    curve = coverage_accuracy_curve(samples)
    return {
        "accuracy@100": curve[-1][1],
        "accuracy@50":  curve[len(curve)//2][1],
        "AUC":           auc(*zip(*curve)),
        "ECE":           ece(samples),
        "abstention_F1": abstention_f1(samples, gold_difficulty)
    }
Failure modes: (1) ECE without AUC — a model that always outputs 50% confidence has low ECE but is useless; report all four metrics; (2) self-reported confidence as the confidence signal — Tian et al. 2023 proved this is backward rationalization, nearly uncalibrated; use logprob avg or self-consistency rate; (3) abstention F1 without a "hard set" — you need a batch the model provably doesn't know (out-of-domain, post-cutoff events); use SimpleQA's unknown subset or build your own; (4) eval only on dev set — production hallucination eval should sample online: 50 real queries per day, human label + automatic metrics, otherwise you won't see post-cutoff drift.
Going deeper · El-Yaniv & Wiener On the Foundations of Noise-free Selective Classification (JMLR 2010, math foundation for selective prediction), jmlr.org/.../el-yaniv10a · Tian et al. Just Ask for Calibration (EMNLP 2023), arxiv.org/abs/2305.14975 · OpenAI SimpleQA, openai.com/index/introducing-simpleqa

// Putting it all together · Bringing hallucination mitigation into your product

The four sections above aren't independent tricks — they map to four engineering layers of hallucination mitigation. Adoption path by ROI:

  1. Step 1 · Write a selective system prompt (30 min, immediate effect): bake "KNOWN / UNSURE / UNKNOWN three-tier + abstention gets positive credit" into your system prompt, and you immediately switch the model from "must-answer mode" to "calibration mode." This is the zero-cost highest-ROI step.
  2. Step 2 · Add a high-risk token scanner (2 hours, –30% hallucination): use the §02 regexes to scan outputs for URL/DOI/arXiv/commit/date; any hit triggers verification or [unverified] tag. Even without a grounding tool, just adding an [unverified] label in the UI dramatically reduces user-misled risk.
  3. Step 3 · Add tool fact-check (half day, another –30%): for high-risk tokens caught in §02, call real APIs (arXiv, Semantic Scholar, HEAD request, GitHub API). Model + tool combined is an order of magnitude stronger than pure prompt engineering.
  4. Step 4 · Add structured output (2 hours, hard-constraint safety net): confidence field as an enum, citation field drawn from a verified_set — the model is physically incapable of fabricating space. Complements tool fact-check.
  5. Step 5 · Set up selective eval (1 day, long-term maintainable): build 100–200 questions mixing easy / hard / unknown; on every model upgrade / prompt change, re-run coverage-accuracy + ECE + abstention F1. This is the only way to prevent regression.

Once you've done these five steps, your application's user trust in hallucination-sensitive scenarios will jump a tier — not because the model got smarter, but because it now admits ignorance, annotates uncertainty, and triggers external verification. These three properties matter more to final product quality than "swap in a bigger model."

// Deep thinking

If RLHF is the root cause of hallucination, will future training paradigms (DPO, Constitutional AI, self-rewarding) fix it at the source?
Partially mitigate, not fundamentally solve, because the problem isn't the RLHF algorithm — it's the "what is a good answer" human preference. Even with DPO or Constitutional AI, annotators / judge models still prefer "sounds knowledgeable" over "honestly admits ignorance." OpenAI 2025 specifically points out this is a signal gap between reward model and ground truth, not a PPO bug. Two genuine breakthrough paths: (1) introducing abstention reward during training — explicitly label "abstain when you should" as positive samples rather than letting judges pass it indirectly; Anthropic's Constitutional Self-Critique is an early attempt; (2) uncertainty-aware loss — directly align model confidence with actual accuracy (calibration loss) during training, not just "sounds correct." But both make calibration data collection far more expensive than preference data, so commercial adoption is slow short-term. So for the next 3–5 years, engineering mitigation (this issue's four layers) remains the main battleground.
Will the Specificity Reverse Principle get worse or better on long-context / large-context models?
Worse, counter-intuitive but mechanistic. Surface intuition: larger context = better grounding. Actual: (1) lost-in-the-middle (W2 / W10) causes mid-context specific facts to be ignored, model falls back to parametric memory and fabricates; (2) long context invites users to ask multi-variable, multi-constraint composite queries ("list ICLR 2023 attention papers with >100 citations from European authors"), specificity dimensions stack, each may fabricate slightly, compound fabrication rate grows exponentially; (3) long context makes synthesized fiction easier — splicing real fragments to create a non-existent "fact." Anthropic engineering experience: long context + high specificity = highest hallucination risk combination, mandatory grounding + verification. Long context is not the hallucination cure — it's a new challenge surface. Selective eval is especially important under long context.
Does putting "abstention gets positive credit" in the prompt actually work, or is it placebo? Is the model pretending to be calibrated?
Genuinely works, but with a clear ceiling. Tian et al. 2023 and Lin et al. 2022 both ran ablations: an abstention-permitting prompt cuts hallucination rate by 20–40% (varies by domain), and significantly improves ECE. Mechanism: the prompt doesn't "make the model smarter" — it shifts the perceived shape of the reward landscape. When the model infers "what does this user/system want," it now incorporates "I don't know is acceptable" as a signal. But the ceiling: confident-wrong facts in parametric memory (versions misremembered during training) — prompts can't reach them; the model "knows" them. For that, you need §03 external grounding. Prompt-level intervention is necessary but not sufficient — it makes the model more calibrated on the questions it knows, but powerless against parametric errors. Full mitigation always means prompt + scanner + tool + structured + eval, all five layers. Don't expect any single layer to be a silver bullet.
Hallucination mitigation vs. user experience: tagging every answer [unverified], degrading specificity, adding abstention — does this make the product "look unintelligent"?
This is a product-philosophy question without a technical right answer, but two observations. (1) Professional users prefer honesty over confidence: doctors, lawyers, researchers testing AI tools nearly unanimously report "I'd rather it say I don't know than fabricate." Anthropic tuned Claude 4 toward honesty and the B2B response was strongly positive. So "looks unintelligent" is a consumer-demo concern, not a B2B concern. (2) UI design can transform honesty signals into trust signals: [unverified] doesn't need to be shown to users; use subtle color coding or hover tooltip; UNKNOWN doesn't show "I don't know" — show "let me look that up" + trigger tool. Honesty at the mechanism layer, elegance at the presentation layer. BigCat's take: consumer products may continue prioritizing "confident fluency" short-to-mid term, but any serious-use product (learning, research, decision support) — the long-term winner is honesty-first. Not a moral choice — it's trust economics: once caught fabricating, user trust in the tool is permanently damaged.
If internal signals (P(True) probes) can predict the model's own hallucination, why don't APIs just expose this as a confidence field?
Technically possible, commercially and operationally blocked. Anthropic and OpenAI both ran internal experiments (Kadavath 2022 / OpenAI 2024 calibration probes); hidden-state probes hit AUC 0.85+ on multiple-choice, 0.7+ on open-ended. Not productized because: (1) probes need a held-out calibration set and retraining on every model update — operational cost not trivial; (2) exposing the probe = letting the outside peer inside the model; expanded attack surface (reverse-engineering model behavior); (3) logprob endpoints already cover most use cases — OpenAI / Gemini / open-source all offer logprobs, an additional probe API has low marginal value; (4) "my model knows it doesn't know" is a negative selling point commercially — markets prefer "answers everything." Status: internal signal exists, research confirms it's strong, productization path blocked. Mid-to-long term: probes won't become a public API directly, but will be internalized as automatic abstention signals at generation time — next-gen RLHF / DPO will use probe signal as auxiliary loss, so generation is naturally calibrated. This is the direction hinted at in OpenAI's 2025 paper.

// Further reading