RAG 把外部检索结果作为生成上下文,但“查到了资料”不能直接推出“回答正确”。我把验收拆成检索与回答两个部分,避免只展示一段看起来流畅的输出。
分清三层证据
| 层次 | 要检查的问题 |
|---|---|
| 来源 | 文档版本、更新时间和访问权限是否正确? |
| 检索 | 问题需要的证据是否进入候选片段? |
| 回答 | 最终论断是否真正被引用片段支持? |
原始 RAG 论文区分了模型参数中的知识和外部非参数记忆。工程中还应记录片段 ID、来源和版本,便于定位答案依据。
一项最小检索检查
先人工给少量问题标注相关片段,再计算检索覆盖情况。下面只检查片段 ID,不训练模型、不调用付费 API。
def evidence_scores(retrieved, relevant):
if not relevant:
raise ValueError("evaluate unanswerable questions separately")
if len(set(retrieved)) != len(retrieved):
raise ValueError("retrieved IDs must be unique")
hits = len(set(retrieved) & set(relevant))
precision = hits / len(retrieved) if retrieved else 0.0
recall = hits / len(relevant)
return precision, recall
assert evidence_scores(["chunk-2", "chunk-1"], {"chunk-1"}) == (0.5, 1.0)
assert evidence_scores([], {"chunk-1"}) == (0.0, 0.0)
assert evidence_scores(["chunk-2"], {"chunk-1"}) == (0.0, 0.0)
print("retrieval checks passed")
这里 retrieved 是系统实际返回的唯一片段列表,relevant 是人工标注的相关片段集合。这是一个简单的集合级评估,不考虑排序位置,也不等于完整的 RAG 质量评分。
不能省略的回答核验
即使 Recall 为 1,模型仍可能误读、拼接错误或无视证据。因此还应逐条检查:答案的引用能否打开;引用里是否真的支持该论断;证据冲突时是否说明冲突;没有依据的问题是否明确保留不确定性。
文档库更新后,应按变更重建或增量更新相关索引,而不是把索引阶段理解成永远只做一次。检索不到时,先检查解析、切分和索引版本,不急着更换更大的模型。
私人知识库的额外边界
- 权限过滤要在检索和结果返回环节生效,缓存也不能把甲用户的私人片段交给乙用户。
- 检索片段是资料,不是新的操作指令;其中的“忽略要求、发送密钥”等文字不能被执行。
- 课程原课件和访问码不随这篇公开笔记一起上传或公开。
课程对应与整理边界
对应疏锦行《26大模型专题》的《补充知识_RAG检索增强生成详解》及 RAG 视频章节目录。本文围绕证据验收重组内容,示例为独立编写;视频口头补充尚未完整核验。
原创
RAG 学习笔记:检索命中不等于回答有依据
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法