RAG 常见问题与基础评估:用小测试集定位检索缺陷
RAG 能否可靠工作,不能只靠“看起来回答得不错”来判断。一个回答错误,可能是检索阶段没有找到正确片段,也可能是证据已经找到却被模型误读,或者问题本身就不在知识库中。本篇只聚焦一个核心知识点:如何识别 RAG 的常见故障,并用一组小测试问题建立最基础的评估方法。示例不依赖网络、密钥或第三方包,只评估可独立验证的检索结果。
先把 RAG 问题分层
一个 RAG 请求至少包含“问题—检索—上下文—回答”四个环节。排查时不要一上来就修改提示词,而要先确认正确资料是否进入了候选集。
召回不足是指知识库中有答案,但检索结果没有包含对应片段。常见原因包括切分过大或过小、查询和原文用词差异明显、top_k 太小,以及过滤条件过严。这个问题属于检索层,应该通过提高召回数量、改进切分或调整表示来处理。
上下文噪声是指正确片段找到了,但同时塞入了许多相似、重复或无关内容。噪声会增加 token 消耗,也会让生成模型更难判断证据重点。增大 top_k 并不总是更好,应该观察前几名结果的精确度,并考虑重排、去重和上下文长度限制。
无依据回答是指提供的证据不足以支持答案,模型却给出了确定的结论。知识库问答应明确区分“证据支持”和“无法从资料确认”。如果问题超出知识库范围,拒答或说明未知,往往比猜测更可靠。因此评估不能只看检索指标,也要抽查回答是否忠于证据。
用小测试集描述预期证据
基础评估不需要一开始就准备很大的数据集。每条测试样例至少包含一个问题和一个或多个正确来源编号。例如:
1 | cases = [ |
relevant 表示人工确认的正确证据,不是模型生成的答案。它可以先只记录“哪篇文档包含答案”,以后再细化到片段编号。测试集要覆盖正常问题、同义表达和知识库没有答案的问题;否则评估分数可能很好看,却无法反映真实使用场景。测试集还应固定保存,不能每次为了提高分数而临时修改标准。
一个可运行的检索评估器
下面用词项重叠模拟检索器,重点不在算法效果,而在评估流程。把代码保存为 evaluate_retrieval.py 后运行即可。真实项目中,只需要替换 retrieve 函数,测试集和指标计算仍然适用。
1 | from re import findall |
代码中的 Recall@k 表示:正确来源至少出现在前 k 个结果中的测试样例比例。它回答“答案有没有机会进入上下文”。MRR@k 是平均倒数排名,正确来源越靠前,得分越高;如果第一条结果就是正确来源,该样例贡献 1,排在第二条则贡献 1/2。
这里使用的是非常粗糙的字符和英文词项匹配,中文分词也没有真正完成,所以它不是生产级检索器。它的价值在于让“评估一个检索器”变成可重复执行的程序:每次改变切分方式、查询改写或 k,都能用同一批案例比较变化。运行输出中的每一行还会显示问题、结果列表和正确来源排名,便于定位具体失败样例,而不只是盯着一个总分。
指标低或高时分别检查什么
如果 Recall@k 很低,先逐条查看失败问题。确认正确文档是否真的被加入知识库,来源编号是否写对,过滤条件是否误删了文档;然后再检查切分边界和查询表达。若提高 k 后召回上升,说明候选集太窄,但也要同步关注上下文噪声和成本。
如果召回不错而回答仍然错误,问题可能发生在上下文组装或生成阶段。记录实际发送给模型的片段,检查是否被截断、顺序是否混乱、来源标记是否丢失,并要求回答只能依据给定证据。对“资料中没有答案”的测试问题,验证程序是否会明确说无法确认,而不是凭常识补全。
离线指标也有边界。人工标注的相关来源可能遗漏,词项检索的分数不能代表语义检索质量,单一测试集更不能证明生产环境可靠。较稳妥的做法是同时保留检索日志、固定测试集和少量人工回答评审,并在修改后比较新旧版本,而不是只追求某个指标变大。
常见问题
为什么不能只评估最终答案? 因为最终答案错了时,单看文字很难判断责任在检索还是生成。记录检索结果和来源排名,才能把故障定位到具体环节。
Recall@k 越高越好吗? 不一定。k 增大通常有助于覆盖正确证据,但会引入噪声、增加上下文长度和费用。应结合排名质量、延迟和回答评审选择合适的 k。
没有真实用户数据怎么办? 先用人工编写的最小测试集,覆盖高频问题、同义问法、边界问题和无答案问题。上线后再脱敏采样真实问题,补充到回归测试集中。
指标下降就一定是代码坏了? 不一定。知识库内容、标注标准或测试问题变化也会影响分数。每次评估都应记录数据版本、检索参数和变更内容,保证比较是同口径的。
小结
RAG 的可靠性需要分层验证:先用测试集确认正确证据能否被召回,再检查候选噪声、上下文组装和回答是否有依据。Recall@k 适合观察覆盖率,MRR@k 适合观察正确结果的位置;它们不能替代人工评审,但能把模糊的“感觉变差了”变成可重复的诊断信号。下一步可以在保持测试集不变的前提下,比较不同切分策略、检索参数和重排方法。