无答案样本如何虚高RAG召回率
当问题没有相关文档时,直接将其 Recall@K 记为 1,会抬高整体检索评估结果。文章用代码与样本说明:空标注文档集合意味着该指标不适用,不能据此认定检索成功。
AI 深度解读
RAG 的 Recall@K 变高,检索器却可能没有任何进步:只要把「知识库里没有答案」的问题记成满分,评估结果就会被抬高。作者在维护一个开源 RAG 评估项目时遇到了这个问题,并修改了计分逻辑。
这篇文章值得看的地方,是划清了两种能力的边界:找回相关文档,以及证据不足时拒绝回答。对于正在比较切块策略、embedding 模型或 reranker 的团队,这个边界会直接影响选型判断。
没有相关文档,为什么不能算检索满分
Recall@K 衡量的是:前 K 个检索结果,找回了多少应当找到的相关文档。分子是命中的相关文档数,分母是标注的相关文档总数。
问题出在分母为空时。原文给出的朴素实现,把这种情况直接记为 1.0:
def recall_at_k(retrieved_ids, expected_ids):
if not expected_ids:
return 1.0
return len(
set(retrieved_ids) & set(expected_ids)
) / len(set(expected_ids))
要看的是 if not expected_ids 后面的 return 1.0:它没有检查检索结果是否合理,只因没有预期文档,就给了满分。
作者举了一个包含 8 道问题的黄金数据集,也就是预先标好答案依据的评估集。其中 7 道可以从文档库回答,1 道故意设计为不可回答。若把最后一道记为 1.0,平均 Recall@K 为 0.750;将它排除后,平均值约为 0.714。
检索器和返回文档都没变,变化只来自计分规则。不可回答问题占比越高,这种规则造成的分数偏移就可能越明显。
没有可检索的相关文档,代表这道题不适用检索召回指标,不能据此判定检索成功。
原文没有给出这 8 道题的逐题得分,因此这组数字只能用于说明聚合规则的影响,不能当作检索效果的对照实验。
空标注要先查原因,再决定怎么计分
作者的修正,是用 None 表示不适用,让聚合阶段能够识别并排除这些结果:
def recall_at_k(retrieved_ids, expected_ids):
if not expected_ids:
return None
expected = set(expected_ids)
retrieved = set(retrieved_ids)
return len(retrieved & expected) / len(expected)
这里要关注的是 return None。计算均值时必须过滤 None,同时报告实际参与计算的问题数;如果只有 7 道题适用,就应让读报告的人看到这个分母。
但代码还没有解决数据含义的问题。空的 expected_ids 至少可能表示两件事:
- 题目经过确认,文档库里确实没有足够依据。
- 题目本来可以回答,但相关文档漏标了,或者标注尚未完成。
前一种应从检索召回统计中排除,后一种需要修复评估数据。作者建议显式区分这些状态,不能仅凭来源列表为空就认定问题不可回答。
另外,两段函数都没有执行前 K 项截取。使用时需要确认传入的 retrieved_ids 已经限定为前 K 个结果,否则函数名虽然叫 Recall@K,实际统计范围却可能不一致。
不可回答的问题,应该考系统会不会拒答
从 Recall@K 中排除,不等于从整个评估集里删除。不可回答问题仍然有价值,只是应该换一道考题:系统能否识别证据不足,避免生成缺乏依据的答案?
作者提出单独检查拒答行为,包括是否正确说明文档不足、是否仍然强行作答,以及是否误拒了原本可以回答的问题。
这几项和检索召回不能混为一个分数。文档找得全,不保证生成阶段会谨慎回答;系统频繁拒答,也不能证明检索质量好。
作者称,他们已经在开源 RAG evaluation starter 中调整了不可回答问题的处理。项目包含检索评估、答案质量指标和可选的 LLM 评判,核心指标可在本地运行,无需 API key。不过,原文没有提供修正后的生产收益或完整实验结果。
我的判断
我认同这次修正。把不适用的样本记成满分,会让数据集组成干扰检索指标,也容易误导切块、embedding 和 reranker 的比较。
与直接删除所有空标注样本相比,先区分「不可回答」和「漏标」更可靠。否则,漏标问题也会被悄悄排除,均值看起来干净了,数据质量问题却被藏起来。
不过,分开评估只是起点。原文没有明确拒答判定标准,也没说明如何处理部分证据、含糊回答等边界情况。它给出了合理的指标边界,尚未给出一套完整的拒答评估方案。
能拿来做什么
- 检查现有 RAG 评估脚本,尤其是
expected_ids为空时的分支;若直接返回 1.0,就重新核算历史分数。 - 给黄金数据集增加明确的可回答性状态,将确认不可回答与待补标样本分开处理。
- 比较检索方案时,同时展示平均 Recall@K 和适用问题数,并固定数据集、K 值及聚合规则。
- 为日常使用的知识库问答单独保留拒答评估,既检查证据不足时是否强答,也检查有依据时是否误拒。