RAG评测指标:召回率、样本平均召回率、召回达标率基线设置

先分清两个指标,很多人在这里混淆:

  1. RAG 场景召回率:预期应该被召回的chunk集合,有多少被成功召回
  2. 平均召回率 Mean Recall:每条样本单独算 Recall,再求平均(衡量检索能不能把问题相关的 chunk 尽量捞全)
  3. 召回达标率:样本级指标,统计多少条样本的单样本 Recall ≥ 阈值(样本通过率)

公式:

image

image

image

基准值没有唯一固定数字,取决于业务风险等级、检索 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 '❌不通过'}")

image

 

三、基准关键影响因素(设置基准前必须确认,否则基准无效)

  1. 检索 TopK: Top5 和 Top10 的召回率完全不一样。基准必须绑定固定 TopK。

例:Top5 基线 Recall=0.8;改成 Top10,召回率会上涨,但精确率下降。测试漂移时 TopK 不能改动。

  1. 标注基准集质量:基准 QA 样本里的expected_chunk_ids必须人工标注:回答该问题必须用到的全部 chunk。标注漏标 / 多标会导致召回率虚高或虚低。
  2. Chunk 分片大小: chunk 切得越小,单 chunk 承载信息越少,一个问题会关联更多 chunk → 召回率更难拉满。
  3. 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:

  1. 验证原始标注测试集文本不变,排除 QA 样本本身改动
  2. 校验 Embedding:用固定文本批量算向量相似度,判断是否存在向量漂移
  3. 校验向量库:查看新增入库文档的主题分布,判断是否文档分布漂移
  4. 排除其他干扰:TopK、chunk 分片、reranker、检索过滤条件有没有改动

如果上面几项都没改动,召回持续下降 → 基本判定是数据漂移

4.3 测试流程:

  1. 在稳定、干净的基准知识库跑一遍 10 条标准 QA,得到初始基线:平均召回率(baseline_mean_recall)\召回达标率

例:基线跑出来 Mean Recall=0.83,基线达标率 0.9,那么系统基线就取 0.83、 0.9,而不是硬套 0.8。

⚠️ 优先采用实测基线值,其次才是参考行业阈值。漂移测试核心看相对下降幅度,而不是单纯绝对值。

  1. 灌入漂移数据 / 更新知识库后,再次评测得到current_mean_recall和新达标率
  2. 告警规则(组合使用更稳妥)
    • 相对降幅规则: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.  追求召回率 = 1.0:要求所有相关 chunk 全部召回。代价是召回大量无关段落,精确率暴跌,Agent 幻觉变多。RAG 需要召回率和精确率做权衡。
  2.  只看绝对值,不看相对变化:大数据向量库漂移测试,相对下降幅度比绝对值更重要。
  3.  混淆 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
posted @ 2026-09-24 17:04  sunshine_coast  阅读(35)  评论(0)    收藏  举报