RAG 引用校验:答案写得顺,不代表证据站得住
RAG 引用校验答案写得顺不代表证据站得住一、RAG 的可信度来自引用RAG 系统常见问题不是答案错而是答案看起来很有道理但其实没有证据支持。模型可能从多个 chunk 拼出一段流畅的结论也可能把相似但过期的旧信息当作当前事实。更隐蔽的情况是引用列了三篇文档但仔细看会发现有一篇是错的、有一篇用户没权限看、第三篇引用的段落已经被更新了。如果引用只是装饰性的脚注用户无法判断答案是否真的可信。我曾测试过一个 RAG 系统问退款需要几天系统回答需要 30 天引用退款政策 v2。答案很顺、引用也对上了但退款政策 v2 是三个月前的版本现在的 v4 明确规定是 7 天。系统不是没有更新索引而是旧 chunk 还在、缓存还在、模型也忠实地用了旧资料。这是典型的引用了但没校验版本的问题。还见过更糟糕的情况引用列表里有一篇文档实际上已经被删除了但向量索引没同步检索结果仍然返回了旧 chunk。用户点击引用链接跳转到 404信任感瞬间归零。引用校验不能只检查是否存在还要检查是否有效、是否可见、是否为当前版本。RAG 引用校验要检查答案里的每一个关键事实是否真的被当前有效的证据所支持。不是为了增加技术复杂度而是为了从一个最基础的问题做起用户凭什么相信这个答案。二、先拆生成链路引用校验应该在答案返回用户之前执行。不是让模型自己说我有依据那相当于让裁判同时当运动员。而是让独立的系统模块检查答案中的每一个事实主张claim是否都能对应到某个可见的、当前有效的文档片段。flowchart TD A[用户问题] -- B[检索相关文档] B -- C[重排筛选 Top-N] C -- D[模型生成答案] D -- E[系统拆解答案为 Claim 列表] E -- F{每条 Claim 是否有有效证据} F --|全部有| G[返回答案 引用] F --|部分缺失| H[删除或标注无证据部分] F --|全部缺失| I[拒答 — 无足够依据] H -- G引用校验的核心逻辑citation_check: require_citation_per_claim: true # 每个事实主张必须对应证据 verify_doc_current_version: true # 引用的必须是当前有效版本 verify_user_visible: true # 用户有权限看这篇文档 reject_missing_evidence: true # 没证据就不输出 mark_partial_support: true # 部分支持也要标注清楚这里有一个实现上的取舍校验是在模型生成之后的模块完成还是在 prompt 里就引导模型标注 citation。两种方式各有优势——prompt 引导的引用更自然但可能遗漏系统校验更严格但可能误杀。实际项目中建议两者结合prompt 要求模型结构化输出引用系统再做二次校验。三、把答案拆成结构化的 claim与其让模型输出一段自然语言再去事后解析不如在 prompt 设计时就要求模型输出结构化的 claim 列表。每条 claim 独立对应一个或多个 citation方便系统做逐条校验。type VerifiedClaim struct { Text string json:text CitationIDs []string json:citation_ids Status string json:status // verified, missing_evidence, unverified }如果某条 claim 没有证据支持应该在返回前删除它或者标注为以下信息来自模型推断非知识库内容。不要把无证据的内容混进最终答案当作可信事实。分拆 claim 的做法在实际中会遇到一个挑战模型输出的 claim 粒度不一致。有的返回退款需要 7 天有的返回退款需要 7-14 个工作日具体取决于支付方式。后者可能需要两个 citation 分别覆盖。建议在 prompt 中给出 claim 拆分的示例引导模型把复合事实拆成原子命题。四、引用要检查权限、版本和多源支持引用正确还远不够。引用的文档用户能看吗版本是当前的吗如果一份文档支持观点 A、另一份支持观点 B模型可以只挑了 A 来回答吗引用校验需要覆盖权限检查被引用文档的 ACL 是否包含当前用户版本检查引用的必须是当前有效版本不是旧版本删除检查已删除的文档不应出现多源完整性如果多份文档结论不一致答案要呈现分歧而非只挑有利的citation_guard: check_acl: true check_kb_version: true check_doc_not_deleted: true show_quote_snippet: true allow_multiple_sources_per_claim: true require_all_sources_visible: true多源完整性值得单独展开说。如果一个知识库里同时存在最低消费 100 元2024 版政策和最低消费 50 元2025 版政策模型可能只引用 2024 版因为它在检索结果中排名更高。引用校验应该检测到存在多个版本且结论冲突要求模型呈现差异而非省略。这对于内部政策、合同条款、产品规格等场景尤其重要。还要记录每次引用失败的原因。是检索阶段就没找到相关文档是找到了但用户没权限看是引用的文档版本已过期还是模型纯粹编造了一个不存在的引用不同的失败原因意味着完全不同的优化方向。只有分类记录后续改进才有依据。引用校验的最终目标是用户可以点开每一条引用看到原文片段确认答案来自于真实的知识库而非模型的想象力。做不到这一步RAG 就只是包装得好看的生成模型和直接调 API 本质没有区别。五、总结RAG 引用校验不是装饰性的脚注功能。它要求系统把答案拆成可验证的事实主张逐条检查证据是否存在、是否可见、是否有效、是否完整。答案写得顺不代表证据站得住。让用户相信 RAG 的答案靠的不是模型自信的语气而是每一条事实背后可追溯的引用。