核心摘要
LLM 幻觉检测本质上是证据问题,不是文风判断。 生产系统应把回答拆成原子声明,在已授权且版本固定的证据快照上逐条判定,再决定发布、修订、拒答或升级人工复核。证据不足不等于错误,表达一致、语气自信或格式正确也不等于事实正确。
目录
- 核心要点
- 什么是 LLM 幻觉
- 先定义真值与证据边界
- 建立声明证据决策流水线
- 实现确定性发布策略
- 为什么 RAG 仍会产生幻觉
- 常见控制能证明什么
- 如何评估检测与拒答
- 将事实性与工具授权分离
- 生产检查清单
- 常见问题
- 总结与相关资源
核心要点
- 评估原子声明,不要用一个不透明的答案级幻觉分数覆盖所有错误。
- 为每次判定固定语料库、版本、权限范围、新鲜度规则和引用锚点。
- 使用四种判定:
supported、contradicted、insufficient_evidence、not_applicable。 - 一致性、模型置信度、低温度和合法 JSON 都只是信号或控制,不是真值保证。
- 分开评估检索、证据质量、生成忠实度、引用、拒答和任务成功。
- 事实判定器不得授权支付、删除、发消息等外部副作用。
什么是 LLM 幻觉
LLM 幻觉是生成模型以看似确定的方式陈述错误或虚假内容。NIST AI 600-1 使用 Confabulation 描述这类会误导用户的风险。但工程上还必须声明边界:相对于哪个来源、版本、时间、司法辖区或任务契约,它是错的?
语言流畅度不属于真值测试。犹豫的句子可能正确,带完整引用的漂亮回答也可能错误。生产系统不应把以下情况压成一个标签:
| 判定 | 含义 | 正确动作 |
|---|---|---|
支持 supported |
声明可由指定证据推出 | 其他门禁通过后可发布 |
矛盾 contradicted |
证据支持与声明不兼容的结论 | 修订或阻断 |
证据不足 insufficient_evidence |
当前快照无法证明任何一方 | 补充检索、拒答或复核 |
不适用 not_applicable |
观点、指令、问候等非事实内容 | 不进入事实性指标分母 |
“不受支持”和“被证据反驳”不是一回事。语料库可能覆盖不足,问题可能超出范围,事实也可能在快照后发生变化。把所有未验证声明都判成错误,会同时污染评测数据与产品行为。
相邻故障不等于幻觉
指令偏移、算术错误、不安全建议、偏见和策略拒绝都可能与幻觉同时出现,但需要独立测试。回答可能事实正确却违反策略,也可能完全忠于输入证据,但证据本身已经过期。
应至少区分两个事实性轴:
- 回答正确性:声明是否符合任务规定的外部真值标准。
- 回答忠实度:声明是否能由提供给模型的证据推出。
对旧政策的准确总结具有忠实度,却不具备当前正确性。反过来,在封闭证据任务中,一个碰巧正确但不在授权证据内的答案仍违反支持范围。
先定义真值与证据边界
只有任务契约明确了证据范围和有效时间,幻觉测试才可复现。生成回答前应记录:
task:
id: refund-policy-qa
truthMode: closed-evidence
asOf: 2026-08-10T09:00:00Z
materialClaims: [eligibility, deadline, fee]
evidenceSnapshot:
corpusId: support-policy
revision: sha256:8c1f...
authorizedTenant: tenant-42
sourceAuthority: approved-policy
freshnessRule: effective_at <= asOf < superseded_at
citationUnit: source-id-and-section
failurePolicy:
contradicted: block
insufficientMaterialClaim: abstain
invalidCitation: block
reviewerRequiredFor: [legal-exception]
这份契约可以阻止验证器悄悄搜索另一张网页、更新版本文档或其他租户的数据。它也让争议可以定位:生成器、检索器、证据集、判定器和发布策略都有独立身份。
证据必须保留血缘
保存规范来源 ID、来源版本、权威级别、有效区间、访问决策、召回片段和检索轨迹。Embedding、摘要、图谱边和重排分数都是派生辅助信息,不能替代原始来源边界。
来源冲突时,不要平均成一个高置信度答案。系统应执行明确的权威级别与时效策略,必要时向用户披露冲突或升级复核。
建立声明证据决策流水线
可靠的最小评估单位是原子事实声明。FActScore 展示了长回答拆成原子事实的价值:同一段文字里可能同时存在受支持和不受支持的内容。
1. 提取原子声明
拆开复合句,让每条声明只接收一个判定。“退货期限是 30 天且免退货运费”至少包含两条声明。保留声明在原回答中的字符偏移,便于修订与审计。
声明提取器本身也会漏掉重要事实,或把带限定词的表达改成绝对结论。应在人标回答上检查提取召回率,重点覆盖数字、否定、时间限定和引用。
2. 按权限检索证据
先执行租户和文档授权,再进行排名。检索结果应携带稳定来源锚点和版本,而不是匿名文本片段。高相似度只表示向量空间接近,不代表来源权威,更不代表证据可以推出声明。
3. 给出有界判定
NLI 模型或 LLM Judge 可以提出判定,但必须输出类型化字段与证据 ID。使用人工标签校准它,检查位置与冗长偏差,并保留 insufficient_evidence 路径。绝不能用 if "支持" in response 之类的自由文本子串解析。
{
"claimId": "claim-3",
"claim": "退款期限是 30 天。",
"material": true,
"evidenceIds": ["returns-policy-v7#window"],
"evidenceRevision": "returns-policy-v7",
"verdict": "contradicted",
"reasonCode": "VALUE_MISMATCH",
"judgeVersion": "claim-judge-4",
"reviewRequired": true
}
4. 按业务损失聚合
不要给“无法验证”统一设置半个错误的权重。被证据反驳的药物剂量应直接阻断发布,不受支持的可选轶事则可以删除。最终动作应由声明重要性和任务损失函数决定。
实现确定性发布策略
下面的无第三方依赖 Python fixture 验证类型化声明结果,并在不信任模型解释或自报置信度的情况下做发布决策:
from dataclasses import dataclass
from enum import Enum
from typing import Iterable
class Verdict(str, Enum):
SUPPORTED = "supported"
CONTRADICTED = "contradicted"
INSUFFICIENT = "insufficient_evidence"
NOT_APPLICABLE = "not_applicable"
@dataclass(frozen=True)
class ClaimResult:
claim_id: str
verdict: Verdict
material: bool
evidence_ids: tuple[str, ...] = ()
citations_valid: bool = True
def release_decision(results: Iterable[ClaimResult]) -> str:
claims = list(results)
if not claims:
return "review"
if any(not claim.citations_valid for claim in claims):
return "block"
factual = [
claim for claim in claims
if claim.verdict is not Verdict.NOT_APPLICABLE
]
if not factual:
return "release"
if any(
claim.material and claim.verdict is Verdict.CONTRADICTED
for claim in factual
):
return "block"
if any(
claim.material and claim.verdict is Verdict.INSUFFICIENT
for claim in factual
):
return "abstain"
if any(claim.verdict is Verdict.CONTRADICTED for claim in factual):
return "revise"
if any(claim.verdict is Verdict.INSUFFICIENT for claim in factual):
return "revise"
if any(
claim.verdict is Verdict.SUPPORTED and not claim.evidence_ids
for claim in factual
):
return "review"
return "release"
fixture = [
ClaimResult(
claim_id="refund-window",
verdict=Verdict.SUPPORTED,
material=True,
evidence_ids=("returns-policy-v7#window",),
),
ClaimResult(
claim_id="return-fee",
verdict=Verdict.INSUFFICIENT,
material=True,
),
]
assert release_decision(fixture) == "abstain"
print(release_decision(fixture))
# 输出:abstain
这个策略刻意保守,但不是通用模板。创意写作产品可以把大部分内容标为 not_applicable;医疗或法律流程则需要更严格的证据、更窄的自动化范围和合格人员复核。策略应有版本,并像应用代码一样接受测试。
为什么 RAG 仍会产生幻觉
检索增强生成可以提供最新、私有且可引用的证据,但检索本身不是事实证明。原始 RAG 论文 在其知识密集型测试任务中报告了改进,不能据此推导任意生产 RAG 都会消除幻觉。
应把 RAG 看成一组可能失败的阶段:
| 阶段 | 失败模式 | 诊断指标 |
|---|---|---|
| 语料库 | 来源错误、过时、重复或未授权 | 权威度、时效、重复率、越权率 |
| 解析与切分 | 证据被拆断或引用边界丢失 | 证据片段覆盖、血缘完整性 |
| 检索 | 所需证据未进入候选集 | 固定 Token 预算下的 Evidence Recall@k |
| 排名 | 正确证据被埋没 | nDCG、倒数排名、Top-k 覆盖 |
| 上下文组装 | 删除冲突或关键限定词 | 冲突检测、唯一证据覆盖 |
| 生成 | 模型忽略、歪曲或过度外推证据 | 回答忠实度、不受支持声明率 |
| 引用 | 引用存在但不支持相邻声明 | 引用精确率与覆盖率 |
| 决策 | 关键证据缺失仍发布 | 拒答召回、关键声明逃逸率 |
实现细节可继续阅读生产级 RAG 评估和RAG 幻觉缓解策略。
常见控制能证明什么
常见“防幻觉”手段通常只控制一个失败模式,却经常被包装成事实保证。
| 控制 | 真正用途 | 不能证明 |
|---|---|---|
| 降低温度 | 提高复现性,减少采样变化 | 事实正确 |
| 结构化输出或 JSON Schema | 语法、必填字段和类型正确 | 字段值真实 |
| 要求引用的提示词 | 建立输出契约 | 引用存在且支持声明 |
| 自一致性 | 在部分任务上发现不稳定回答 | 真值;多次采样可能共享一个错误 |
| 多模型一致 | 模型失败足够独立时提供分流信号 | 校准置信度;模型可能共享数据和错误 |
| Token 概率 | 当前模型下的词元似然 | 现实世界声明为真的概率 |
| 更大或更新的模型 | 在指定基准上可能表现更好 | 所有领域和切片的幻觉都更少 |
| 人工审核 | 提供上下文判断与责任主体 | 在缺少专业能力、证据和工时控制时零错误 |
SelfCheckGPT 证明多次采样的不一致性可以帮助黑盒检测,但它只能作为信号:一致回答也可能重复同一误解。TruthfulQA 同样显示模型可能复现流行谬误,而且在该论文的测试设置中,扩大模型并未自动提升 truthfulness。
因此,低温度是复现控制。需要稳定输出以便调试或评测时可以使用,但事实性必须独立验证。
如何评估检测与拒答
生产评估必须分开测试检测器、回答和决策策略。允许拒答时,只看准确率会奖励猜测。OpenAI 对语言模型为何产生幻觉的分析指出:若评测只奖励答对,模型猜测可能比承认不确定更有利。
构建版本化评测集
评测集应覆盖:
- 可回答与刻意不可回答问题;
- 当前、过时、冲突和缺失证据;
- 数字、日期、否定、引用与多声明回答;
- 高影响与低影响声明;
- 语言、地区、租户、设备和用户权限切片;
- 检索失败、Prompt Injection、超时和依赖部分失败。
对原子声明标注证据 ID 与裁决说明。记录标注者分歧,不要用多数标签隐藏真正的模糊样本。
指标必须带分母
| 指标 | 回答的问题 |
|---|---|
| 声明提取召回率 | 重要事实声明是否都被找到 |
| 矛盾精确率与召回率 | 是否发现被证据反驳的声明且不过度误报 |
| 证据不足精确率与召回率 | 是否识别缺失证明而不把它判成错误 |
| 引用精确率 | 每个引用是否支持相邻声明 |
| 引用覆盖率 | 重要事实声明是否有证据 |
| 回答忠实度 | 回答是否保持在输入证据内 |
| 回答正确性 | 是否符合任务的外部真值标准 |
| 拒答精确率 | 系统拒答时是否确有必要 |
| 拒答召回率 | 需要拒答的样本是否被拒答 |
| 选择性风险 | 系统选择发布的回答中错误率多高 |
| 覆盖率 | 请求中有多少得到回答 |
| 任务成功率 | 用户是否安全完成目标任务 |
选择性风险必须和覆盖率一起报告。一个系统可以通过拒绝所有请求得到接近零的发布错误率,但产品没有可用性。应绘制风险-覆盖曲线,并根据业务损失选择阈值,而不是复制一个通用分数。
如果使用 LLM-as-Judge 标注声明,应与合格人员标签对比,按切片检查混淆矩阵;模型、Prompt、证据格式或领域变化后必须重新校准。
将事实性与工具授权分离
回答验证器绝不能兼任授权系统。即使一句话有完整证据,也不能证明请求者有权读取记录、发起退款、删除文件或发送消息。
状态改变型工具应执行:
- 由确定性策略授权主体、租户、资源和精确动作。
- 使用当前系统状态校验类型化参数。
- 高影响操作要求审批。
- 使用幂等键和持久化操作 ID。
- 记录
succeeded、failed或outcome_unknown,不能根据模型文本推断成功。 - 将事实、策略、安全和执行结果门禁相互独立。
这项分离既能限制错误回答的损害,也能抵御 Prompt Injection。检索文档是证据候选,不是指令,更不是权限。
生产检查清单
- 声明任务真值模式:开放世界、封闭证据、时间快照或领域权威。
- 固定模型、Prompt、检索器、语料库、证据快照、Judge 与发布策略版本。
- 提取原子声明,并审计声明提取召回率。
- 严格区分
contradicted与insufficient_evidence。 - 保留规范来源锚点、版本、权威级别、权限范围与检索轨迹。
- 验证引用是否支持相邻声明;引用存在本身不够。
- 建立明确的修订、拒答与合格人员复核路径。
- 按风险切片使用人工标签校准自动 Judge。
- 用关键切片回归阻断发布,不能只看平均分。
- 同时度量选择性风险、覆盖率、任务成功、延迟和成本。
- 将工具授权和外部副作用放在事实 Judge 之外。
- 记录满足隐私要求的证据与决策元数据,用于事故分析。
常见问题
LLM 为什么会产生幻觉
自回归模型优化的是可能的文本续写,不是对当前真值数据库执行事务。训练数据可能稀疏、冲突、过时,也可能包含流行谬误。Prompt 和评测还可能奖励回答而不是拒答。这些机制解释了风险来源,但不能推导一个适用于所有任务的幻觉率。
模型置信度能检测幻觉吗
不能单独使用。Token 概率描述模型内部的词元似然;模型口头声称“90% 确定”也不是校准概率,除非它已在同一任务的标注结果上验证。置信度只能在完成任务级校准并监控漂移后用于分流。
不受支持的声明一定是假的吗
不一定。insufficient_evidence 表示指定快照无法证明它。声明可能在语料库外为真、刚刚发生变化、存在歧义,或与授权来源无关。应补充检索、拒答或复核,不能把缺少证明静默改成矛盾。
两个模型给出相同答案就可信吗
一致性只能作为有边界的信号。模型可能共享训练数据、检索来源、Prompt 和系统性误解,因此错误高度相关。重要声明仍需独立证据验证,并用真实任务检查一致性信号是否校准。
生产环境最好的幻觉指标是什么
不存在单一最佳分数。应联合使用声明级矛盾与证据不足指标、引用精确率与覆盖率、正确性、忠实度、拒答精确率与召回率、选择性风险、覆盖率和端到端任务成功率,并按风险切片报告。
总结与相关资源
可靠的 LLM 应用不会判断一段回答“看起来像不像幻觉”。它会声明真值边界、保存证据快照、逐条评估原子声明,再执行确定性的决策策略。RAG、提示词、温度、一致性检查和自动 Judge 都可以支持这套系统,但没有一个是真值预言机。
相关资源: