RAG评测指标:召回率、样本平均召回率、召回达标率基线设置
先分清两个指标,很多人在这里混淆:
- RAG 场景召回率:预期应该被召回的chunk集合,有多少被成功召回
- 平均召回率 Mean Recall:每条样本单独算 Recall,再求平均(衡量检索能不能把问题相关的 chunk 尽量捞全)
- 召回达标率:样本级指标,统计多少条样本的单样本 Recall ≥ 阈值(样本通过率)
公式:
基准值没有唯一固定数字,取决于业务风险等级、检索 TopK、文档分片质量、知识库难度。
下面是行业落地经验值,适合做漂移测试、知识库更新回归测试。
一、分业务场景推荐Mean Recall基准
| 业务场景 | 业务说明 | 推荐基线 Mean Recall | 可接受下限 | 说明 |
|---|---|---|---|---|
| 高严谨场景(合同、法规、运维手册、故障处置文档) | 答案必须完整引用原文,缺信息就容易产生严重幻觉 | ≥0.90 | 0.80 | 关键知识不能漏;一旦相关 chunk 没召回,大概率出错;漂移告警阈值建议下降>0.05 |
| 企业内部知识库、产品说明文档 | 回答需要准确,但少量次要信息缺失可接受 | ≥0.80 | 0.70 | 最常见 RAG 场景,推荐作为你大数据 ETL 向量库测试默认基准 |
| 通用问答知识库(FAQ、简单客服问答) | 只需要找到任意一条相关段落即可 | ≥0.70 | 0.60 | 对召回完整性要求低,更看重 Hit@K |
| 复杂长文档、多源杂乱非结构化文档(日志、工单、扫描 OCR) | 文档噪声大、术语不统一 | ≥0.60 | 0.50 | 属于困难场景,很难做到高召回 |
✅ 如果是企业业务知识库,建议基线目标 Mean Recall ≥0.80;低于 0.7 触发告警。
二、召回达标率(样本通过率)基准
单样本 Recall 合格阈值建议:(单条样本至少召回 70% 的预期相关 chunk 才算这条样本合格)。
| 场景 | 单样本召回合格阈值 | 召回达标率目标 | 达标率下限 | 说明 |
| | 严谨知识库 | | ≥0.9 | ≥90% | 80% | 回答需要完整引用资料,缺 chunk 就容易幻觉 |
| | 普通企业知识库(产品简介、 FAQ) | | ≥0.7 | ≥80% | 70% | 少量关键信息缺失可接受 |
| | 非结构化文档|杂乱工单 | | ≥0.5 | ≥70% | 60% | 只需要命中至少一条核心 chunk |
示例:普通企业知识库,10 条测试样本
目标:平均召回率≥0.8,召回达标率≥0.8(至少 8 条样本单 Recall≥0.7)
✅ 推荐 RAG数据漂移测试默认配置:
- 单样本召回合格阈值:0.7
- 达标率目标:≥80% 含义:10 个测试样本中,至少 8 个样本,单样本召回率≥0.7,才算整体达标。
⚠️ 注意区分:
- Hit@K:只要命中任意 1 个 chunk 就算合格;
- 召回率达标率:要看该样本预期 chunk 的召回比例,要求更高。
- 例:一个样本预期 2 个 chunk,只召回 1 个 → 单样本 recall=0.5,如果阈值 0.7 → 判定这个样本不达标,虽然 Hit@K=1。
# 计算召回率和精确率 def calc_recall_precision(expected_chunk_ids: list, retrieved_chunk_ids: list): expected = set(expected_chunk_ids) retrieved = set(retrieved_chunk_ids) hit_set = expected.intersection(retrieved) hit_count = len(hit_set) expected_count = len(expected) retrieved_count = len(retrieved) recall = hit_count / expected_count if expected_count > 0 else 1.0 precision = hit_count / retrieved_count if retrieved_count > 0 else 0.0 return round(recall, 4), round(precision, 4) #计算hit@K def calc_hit_at_k(expected_chunk_ids: list, retrieved_chunk_ids: list): expected = set(expected_chunk_ids) retrieved = set(retrieved_chunk_ids) return 1 if len(expected & retrieved) > 0 else 0 if __name__ == "__main__": # 10个测试样本 sample_list = [ {"expected": ["c1", "c2"], "retrieved": ["c1", "c3"]}, {"expected": ["c5"], "retrieved": ["c5", "c6"]}, {"expected": ["c9"], "retrieved": ["c10"]}, {"expected": ["c11"], "retrieved": ["c11"]}, {"expected": ["c12", "c13"], "retrieved": ["c12"]}, {"expected": ["c14"], "retrieved": ["c15"]}, {"expected": ["c16"], "retrieved": ["c16", "c17"]}, {"expected": ["c18", "c19"], "retrieved": ["c18", "c19"]}, {"expected": ["c20"], "retrieved": ["c21"]}, {"expected": ["c22", "c23"], "retrieved": ["c23"]}, ] # ========= 配置参数(可修改)========= SAMPLE_RECALL_THRESHOLD = 0.7 # 单样本召回合格线 TARGET_PASS_RATE = 0.8 # 召回达标率目标 # ===================================== recall_all = [] precision_all = [] hit_at_k_all = [] pass_count = 0 # 达标样本计数 for idx, item in enumerate(sample_list, start=1): r, p = calc_recall_precision(item["expected"], item["retrieved"]) hit = calc_hit_at_k(item["expected"], item["retrieved"]) recall_all.append(r) precision_all.append(p) hit_at_k_all.append(hit) # 判断当前样本召回率是否达标 is_pass = r >= SAMPLE_RECALL_THRESHOLD if is_pass: pass_count += 1 print(f"样本{idx}:Recall={r}, Precision={p}, Hit@K={hit}, 是否达标:{is_pass}") avg_recall = sum(recall_all) / len(recall_all) avg_precision = sum(precision_all) / len(precision_all) avg_hit_at_k = sum(hit_at_k_all) / len(hit_at_k_all) recall_pass_rate = pass_count / len(sample_list) # 召回率达标率 print("\n==== 汇总评测结果 ====") print(f"平均召回率 Mean Recall: {avg_recall:.4f}") print(f"平均精确率 Mean Precision: {avg_precision:.4f}") print(f"平均Hit@K: {avg_hit_at_k:.4f}") print(f"达标样本数 / 总样本数:{pass_count}/{len(sample_list)}") print(f"召回率达标率:{recall_pass_rate:.4f}") print(f"设定单样本召回阈值:{SAMPLE_RECALL_THRESHOLD},目标达标率:{TARGET_PASS_RATE}") print(f"整体结论:{'✅通过' if recall_pass_rate >= TARGET_PASS_RATE else '❌不通过'}")

三、基准关键影响因素(设置基准前必须确认,否则基准无效)
- 检索 TopK: Top5 和 Top10 的召回率完全不一样。基准必须绑定固定 TopK。
例:Top5 基线 Recall=0.8;改成 Top10,召回率会上涨,但精确率下降。测试漂移时 TopK 不能改动。
- 标注基准集质量:基准 QA 样本里的
expected_chunk_ids必须人工标注:回答该问题必须用到的全部 chunk。标注漏标 / 多标会导致召回率虚高或虚低。 - Chunk 分片大小: chunk 切得越小,单 chunk 承载信息越少,一个问题会关联更多 chunk → 召回率更难拉满。
- Embedding 模型质量: 弱 Embedding 基线天然偏低;换更强 Embedding,基线会抬升。漂移测试全程 Embedding 模型不能换,基线才有对比意义。
四、漂移测试时,基准怎么使用
4.1 数据漂移是如何产生的
① 文档分布漂移(原始文本侧)
知识库持续灌入大量新类型文档(日志、工单、新领域资料),向量库里面无关向量变多。
- 现象:TopK 检索里混入很多无关 chunk;精确率优先下跌,召回率也会逐步下降
- 例子:基线 Mean Recall=0.83;灌入大量无关文档后,召回掉到 0.76
- 风险:不是 Embedding 坏了,是向量库 “噪声变多”,相关 chunk 被挤到 TopK 以外。
② Embedding 向量漂移(向量空间侧)
相同文本,因为 Embedding 版本、分片策略、文本清洗逻辑改动,生成向量发生偏移。
- 现象:新旧向量不在同一个向量空间,相似文本距离变大;召回率优先大幅下降
- 例子:基线 Mean Recall=0.83;升级 embedding 后,召回直接掉到 0.70
- 风险:知识库存量老向量和新增向量不兼容,本该召回的 chunk 检索不到。
漂移的特点:渐进式、隐性,不像报错直接暴露;单独跑一次评测很难发现,必须保留基线做对比。
4.2 数据漂移测试分层排查思路(定位召回下降是不是漂移导致)
漂移测试的核心逻辑:基线是在干净、原始分布下测出的基准,后续所有更新内容入库后,都拿当前指标和这条基线对比,识别退化
当检测到召回下跌,分层定位,区分漂移 / 其他 bug:
- 验证原始标注测试集文本不变,排除 QA 样本本身改动
- 校验 Embedding:用固定文本批量算向量相似度,判断是否存在向量漂移
- 校验向量库:查看新增入库文档的主题分布,判断是否文档分布漂移
- 排除其他干扰:TopK、chunk 分片、reranker、检索过滤条件有没有改动
如果上面几项都没改动,召回持续下降 → 基本判定是数据漂移
4.3 测试流程:
- 在稳定、干净的基准知识库跑一遍 10 条标准 QA,得到初始基线:平均召回率(baseline_mean_recall)
\召回达标率
例:基线跑出来 Mean Recall=0.83,基线达标率 0.9,那么系统基线就取 0.83、 0.9,而不是硬套 0.8。
⚠️ 优先采用实测基线值,其次才是参考行业阈值。漂移测试核心看相对下降幅度,而不是单纯绝对值。
- 灌入漂移数据 / 更新知识库后,再次评测得到
current_mean_recall和新达标率 - 告警规则(组合使用更稳妥)
- 相对降幅规则:
baseline_mean_recall - current_mean_recall > 0.05,,触发漂移告警(推荐)达标率降幅>0.1 - 绝对值下限规则:
current_mean_recall <0.7,漂移后达标率低于目标值 0.8,直接判定不通过
- 相对降幅规则:
举例: 基线实测 Mean Recall=0.83
数据漂移之后,测得 Mean Recall=0.77
recall_drop = 0.06 >0.05 → 触发漂移告警
五、常见误区
- 追求召回率 = 1.0:要求所有相关 chunk 全部召回。代价是召回大量无关段落,精确率暴跌,Agent 幻觉变多。RAG 需要召回率和精确率做权衡。
- 只看绝对值,不看相对变化:大数据向量库漂移测试,相对下降幅度比绝对值更重要。
- 混淆 Hit@K 和 Recall:Hit@K=0.9 ≠ Mean Recall=0.9。Hit@K 只看有没有找到至少一条相关 chunk,不看有没有找全。
六、推荐一套开箱即用组合阈值(企业知识库 RAG Agent)
- 检索固定 TopK=5
- 平均 Recall 基线目标 ≥0.80
- 单样本 Recall 合格阈值:0.7
- 召回达标率目标 ≥0.8
- 漂移告警:平均召回下降>0.05 OR 当前平均召回率<0.7




浙公网安备 33010602011771号