区分检索层失败与生成层失败两种不同问题,介绍构建分层评估 Harness 的方法,含召回率、上下文件利用率等核心指标。
在本系列的前一篇文章中,我将 ETL、chunking 和 embedding 拆分为 RAG 管道的三个独立层级。但即便这三层都实现得很好,如果你无法衡量 retrieval 是否正常工作,那一切都毫无意义。
这里存在一个反复出现的问题:生产环境中评估 RAG 最常见的方式仍然是打开聊天界面,问三个问题,看看回答,然后说"效果不错"。这不是评估,这是"感觉还行"。而感觉还行无法规模化、不具备可复现性,也无法发现回归问题。
在本文中我想深入探讨两件事:对 retrieval 真正重要的指标,以及如何构建一个我在生产环境中使用的分层评估 harness,不依赖"LLM 说挺好"这种判断方式。
一个常见的错误是只评估 LLM 的最终回答。问题在于这混淆了两种完全不同类型的失败:
Retrieval 失败:正确的 chunk 根本没有被检索到。LLM 用错误的上下文来回答,但它仍然可能"看起来"很有说服力。
生成失败:正确的 chunk 被检索到了,但 LLM 没有很好地利用它,忽略了部分信息,或者在正确的上下文上产生了幻觉。
如果你只看最终回答,你就不知道是哪一层出了问题。不知道这一点,你就会在问题其实是 chunking 的时候去调 prompt,或者在问题其实是 embedding 模型的时候去换 embedding 模型。
因此,RAG 的评估需要有一个专门针对 retrieval 的层级,与生成评估分开。
在任何复杂的 harness 之前,你需要有一个评估数据集:问题 → 正确 chunk(ground truth)的配对,从真实案例中构建。
有了这个数据集,经典的信息检索指标就派上用场了:
Precision@k:在返回的 k 个 chunk 中,有多少个是真正相关的。衡量噪音。
Recall@k:在存在的相关 chunk 中,有多少个被带入了 top-k。衡量你是否在丢失信息。
MRR(Mean Reciprocal Rank):第一个相关 chunk 在排名中出现得有多早。这很重要,因为 LLM 对上下文中靠前的内容给以更高的权重。
nDCG:与 MRR 类似,但考虑的是分级相关性(不是所有相关 chunk 都同等有用),并对所有位置进行加权,而不仅仅是第一个。
在实践中,recall@k 通常是最能暴露 chunking 问题的指标:如果 recall 很低,通常是因为信息在变成 embedding 之前就被错误地碎片化了,而不是因为 embedding 模型不好。
没有上下文的指标本身无法做决策。70% 的 recall@5 对于简单的 FAQ 来说可能很好,但对于法律知识库来说就很糟糕——丢失一段话就会改变回答。可接受的阈值取决于领域。
Retrieval 指标只能解决部分问题。但 LLM 的最终回答也需要评估,这里仅靠指标是不够的——你没有自由文本的 ground truth 来比较。这就是分层 harness 的用武之地,分为三个阶段:
第一道防线,也是运行成本最低的。二元问题,可以用代码验证,不需要 LLM:
这些 checks 很快、很便宜,在花一笔 LLM 调用之前就能捕获大部分明显的 bug。
对于无法确定性验证的内容——语义正确性、完整性、回答是否真正回应了问题——用另一个 LLM 来评估回答是否符合明确的标准(rubric),而不是只问"这个回答看起来好吗"。
这里有一个关键点:judge 需要访问与评估对象相同的检索上下文,而不仅仅是问题和回答。没有这一点,它就无法区分"LLM 回答得很差"和"LLM 基于不完整的上下文给出了正确答案"——而这正是我们要找的区分。
这是最多人跳过的一层,却也是最重要的一层。LLM-as-judge 本身有一个已知问题:它可能不一致,倾向于偏好更长的回答,或者在某些类型的问题上系统性地出错。
Calibration gate 是 judge 输出的一个样本,由人工定期复核,将 LLM 的裁决与人类的判断进行比较。如果一致性降到阈值以下,这就是一个信号——说明 judge 在那个时刻不可信了——无论是由于 prompt 变更、模型变更,还是评估数据集的漂移。
没有这个 gate,很容易掉进一个危险的陷阱:harness 报告"95% 通过率",却没人注意到裁判本身校准错了。
值得提一下只有设计良好的 harness 才能捕获的一种失败类型:具有自动 replan(重新规划)功能的系统可能会悄无声息地将 guardrail 阻塞转换为 success: true——系统重试,绕过安全锁,然后像什么都没发生一样报告成功。
没有一层专门评估 stop_reason 和完整执行轨迹(不仅仅是最终结果)的评估,这种 bug 会无限期地不被发现。这是一种只有把评估当作架构的一部分、而不是偶尔跑一下的脚本时才会出现的问题。
评估 RAG 不是跑一个指标然后比较两个数字。是分离出失败真正发生在哪里——retrieval 还是生成——并用不同成本和可信度的验证层级来构建:确定性优先(便宜且二元),LLM-as-judge 其后(语义化的,但有缺陷),最上面再加一层 calibration gate(保证裁判本身仍然可信)。
没有这些,"我的 RAG 工作得很好"只是一个观点。有了这些,它是一个你可以捍卫的数字,更重要的是,它能在用户发现之前就捕获回归。
本文是关于真实 RAG 实现和应用 AI 工程的系列文章的一部分。