把RAG错答当成证据链断裂:从最终声明反查检索现场

📅 2026/7/7 10:37:06 👁️ 阅读次数 📝 编程学习
把RAG错答当成证据链断裂:从最终声明反查检索现场

很多 RAG 排错会停在一句“正确文档已经进 TopK”。这句话听起来像结论,其实只是一位证人的口供:某个片段曾经出现在候选列表里。它没有证明片段覆盖了全部必要事实,没有证明片段越过重排与截断进入模型,也没有证明模型最后写出的每个声明都来自这些证据。

于是,团队一边看着不错的相似度,一边面对答非所问、漏掉限制条件、混淆新旧版本和凭空补充等问题。

本文换一个调查方向:不再从流水线左端逐项巡检,而是从最终错答逆向追踪。先把答案拆成原子声明,再为每条声明寻找支持、反证与缺失条件,最后沿“模型实际看见的上下文—重排结果—候选召回—原始语料”反向寻找最早断点。

这样,一次错答就会从模糊的质量问题,变成一宗可以归因的证据链断裂事件。

这套方法不依赖特定厂商。它的目标不是证明某个评测框架分数最高,而是为每个坏例留下案件编号、现场快照、声明与证据的映射、最早失败点和复验结果,让修复动作能够准确送到责任环节。

一、先封存错答现场:TopK命中只是一份旁证

假设用户问:“某项内部流程在什么条件下需要二次审批?”

检索结果里确实出现了制度文档,因此调试者宣布召回正常。但仔细检查,可能存在四种完全不同的情况:

  1. 召回的是已经废止的旧版本;
  2. 命中片段只包含审批动作,没有包含适用条件;
  3. 正确片段排在很后面,前面的大量相似文本稀释了注意力;
  4. 证据完整,但生成模型把“满足任一条件”改写成了“同时满足全部条件”。

这四种情况在“有没有命中文档”这个粗指标上都可能得到一分,修复位置却完全不同。

端到端成功至少要连续满足三件事。

第一,检索成功。参考片段进入了候选集合,并出现在合理位置。

第二,证据成功。真正传给模型的上下文包含回答所需的事实,没有因为切分、过滤、权限或长度预算丢掉关键限定。

第三,生成成功。答案中的每个外部事实都能回指证据,同时没有遗漏用户真正询问的内容。

把这三件事压成一个“回答正确率”,相当于只记录“案件发生了”,却丢掉了证据链究竟断在哪里。

发现错答后,不要立刻重跑,也不要先调整 TopK。首先保存用户问题、最终回答、候选片段、重排顺序、实际上下文、语料快照和组件版本。

随后把回答拆成最小可核验声明,并分别标记:

  • supported:声明能够被上下文直接支持;
  • contradicted:声明被上下文明确反驳;
  • not_in_context:上下文没有提供足够证据;
  • irrelevant:声明与用户问题无关。

答案级的“对或错”适合汇报,声明级状态才适合定责。

RAGAS 的原始论文把相关且聚焦的检索上下文、模型对上下文的忠实利用,以及生成质量列为不同维度。ARES 也分别讨论上下文相关性、答案忠实度和答案相关性。

这些研究真正重要的启发,不是必须采用某个现成分数,而是评测对象必须与系统阶段对齐。检索器不应该为生成模型的幻觉背锅,生成模型也无法从根本上补回从未进入上下文的事实。

因此,第一次改造不是更换模型,而是改变记录结构。每次运行都必须能够回答:

  • 用户的问题是什么;
  • 参考事实是什么;
  • 哪些文档或片段被视为相关;
  • 实际取回了哪些片段;
  • 片段的排序发生了什么变化;
  • 最终传给模型的上下文是什么;
  • 模型生成了什么答案;
  • 每个阶段分别使用了哪个版本。

如果只保存问题和最终答案,事后便无法判断错误是在索引前、检索中,还是生成后发生的。

二、建立案件档案:让每条声明都能找到证物

一个实用的评测单元,不应该只是“问题—标准答案”二元组。

它至少应包含问题、期望事实列表、参考文档标识、参考片段标识、实际检索片段及排序、最终上下文、生成答案和不可回答标签。

为了能够复现实验,还要保存语料快照、切分配置、过滤条件、检索器版本、重排器版本、提示词版本和生成配置。

敏感正文不一定要进入日志,但稳定的内容哈希、片段 ID 和版本标识必须留下。

期望事实最好写成原子声明,而不是一段文学化的标准答案。

例如,可以把下面这句话:

申请人在金额超过阈值或涉及指定地区时需要二次审批,并由风控负责人确认。

拆成三个声明:

  1. 金额超过阈值会触发二次审批;
  2. 涉及指定地区会触发二次审批;
  3. 二次审批由风控负责人确认。

这样就能区分“答案完全错误”和“答案正确但漏了一项”。

如果只保留一整段参考答案,自动裁判容易受到措辞差异影响,人工复核也很难指出具体缺口。

参考文档与参考片段也要分开。

文档级标签适合回答“正确材料有没有出现”,片段级标签则适合回答“送入模型的文字是否真的包含证据”。

同一份文档里可能同时存在已废止条款、例外说明和当前规则。仅凭文档 ID 命中就算成功,会掩盖切分边界和版本混杂问题。

对于长表格、FAQ 和多级标题,片段还应保留父标题、页码、表头或路径。否则片段离开原文以后,可能失去完整语义。

一条案件档案可以采用下面的结构:

{"case_id":"rag-eval-0042","question":"什么条件下需要二次审批?","expected_claims":["条件A触发","条件B触发","由指定角色确认"],"reference_chunk_ids":["policy-v7-3.2","policy-v7-3.3"],"retrieved":[{"chunk_id":"policy-v7-3.2","rank":1},{"chunk_id":"policy-v6-3.2","rank":2}],"context_chunk_ids":["policy-v7-3.2","policy-v6-3.2"],"answer":"……","corpus_version":"2026-07-06","pipeline_version":"candidate-b"}

Ragas 的评测模式同样会区分user_inputretrieved_contextsreference_contextsresponse等字段。

真正关键的是,不要在评测前把这些字段过早拼成一个字符串。只有保留结构,才能分别计算确定性指标、运行声明级核验,并在失败时展示原始证据。

三、反查候选现场:证据何时出现,又在哪里失踪

候选现场首先使用不依赖生成模型的确定性指标。

Recall@K 关心参考相关片段中有多少进入了前 K 个结果,适合发现漏召回。

Precision@K 关心前 K 个结果中有多少真正相关,适合发现噪声。

NDCG@K 同时考虑相关性等级和排序位置,适合在一个问题同时存在核心证据、补充证据和弱相关背景时比较排序。

这三个指标没有谁能单独代表检索质量,因为它们回答的是不同问题。

例如,前十条结果包含全部两条参考证据,Recall@10 可以很高;但另外八条都是噪声,Precision@10 仍然很低。

如果核心证据排在第十位,平均相似度可能看起来不错,模型实际使用它的机会却会下降。

反过来,把 K 调得很小可能提高精度,却会让需要多条证据组合的问题丢失补充条款。

因此,参数扫描不能只追一个平均分,而应同时观察召回、噪声和排序,并按照问题类型分组。

检索失败还要继续定位到候选生成之前还是之后。

如果参考片段从未进入候选集,需要检查:

  • 文档解析是否正确;
  • 切分是否破坏语义;
  • 索引是否成功写入;
  • Embedding 空间是否一致;
  • 查询改写是否改变原意;
  • 元数据过滤是否误删目标文档。

如果候选集包含参考片段,但最终列表将它丢弃,需要检查:

  • 重排器;
  • 去重规则;
  • 多样性策略;
  • 权限过滤;
  • 最终保留数量。

如果排序正确,但最终上下文仍然缺少目标证据,需要检查:

  • 上下文拼装;
  • 字符或 Token 预算;
  • 去重规则;
  • 截断顺序;
  • 片段合并策略。

只有同时记录候选集、重排后列表和最终上下文三个快照,才能分清证据究竟在哪个位置失踪。

BEIR 的价值在于提醒我们:检索器在单一同质数据集上的好成绩,并不能代表跨领域表现。

实际评测集应覆盖短问句、长描述、术语缩写、多条件问题、表格问题、跨文档问题和带时间约束的问题。

同时还要覆盖不同文档形态,例如规范、FAQ、代码、日志、表格和扫描件解析文本。

如果所有测试都来自一批结构整齐的 FAQ,评测结果只能说明系统擅长处理这类 FAQ。

最后,不要把检索器返回的相似度当成跨模型通用的概率。

不同索引、距离函数、归一化方式和重排器产生的分数含义不同。案件档案可以保存原始分数,用于同配置诊断;但发布判断应该基于已经标注的相关性和稳定指标,而不是硬编码一个从其他系统抄来的相似度阈值。

四、检查送达证物:相关上下文不等于完整证据

确认候选召回以后,下一站是检查真正传给模型的上下文。

上下文证据至少包含四个维度:

  • 相关性:片段是否与问题有关;
  • 充分性:片段是否覆盖回答所需的全部声明;
  • 一致性:不同片段是否互相冲突;
  • 时效性:版本和生效范围是否适用于当前问题。

一个片段可以高度相关,却不足以支持完整答案。

充分性是最容易被忽略的一项。

多条件问题往往需要来自两个章节的证据;比较题需要双方材料;流程题需要触发条件、执行步骤和例外情况。

当系统只召回其中一半时,生成模型可能用自身常识补齐剩余内容,最终得到一段流畅但没有证据的回答。

评测时应该把期望事实映射到参考片段,再检查最终上下文覆盖了哪些事实。

可以计算“被上下文支持的期望声明比例”,但同时必须保留缺失声明列表。这个列表通常比单个分数更适合排错。

一致性检查也不能简单地把重复文本删除。

两个版本的条款可能文字相似,结论却不同;同一制度的正文与例外条款也可能表面矛盾。

上下文拼装应保留版本、生效时间、适用对象和来源优先级。

评测样本则要包含至少一组冲突证据,确认系统会提示冲突、请求澄清或按照明确规则选择,而不是随机吸收排在前面的片段。

还要专门设计“不可回答”样本。

以下情况都不应该被迫生成确定结论:

  • 语料中完全没有答案;
  • 语料只包含部分条件;
  • 问题超出了当前权限;
  • 问题引用了不存在的版本;
  • 上下文中的证据彼此冲突。

这类样本的成功标准,不是与某段参考答案相似,而是能够识别证据不足,明确说明缺少什么,并避免把模型参数中的记忆伪装成知识库事实。

如果评测集全部都是可回答问题,就无法知道系统是否会在证据空白处编造答案。

实践中,可以为证物状态设置以下结构化标签:

  • sufficient:证据充分;
  • partial:只有部分证据;
  • conflicting:证据互相冲突;
  • stale:证据已经过期;
  • unanswerable:现有语料无法回答。

除了状态,还应记录已经支持和仍然缺失的声明 ID。

这样生成层可以接收更明确的控制信号:证据充分时正常回答,部分充分时只回答已经证实的部分,证据冲突时呈现差异,不可回答时拒绝猜测。

关键是把“是否应该回答”变成可评测的契约,而不是只在提示词中写一句“请勿编造”。

五、核验最终口供:忠实、正确、相关、完整是四件事

最终回答至少要从忠实度、正确性、相关性和完整性四个方向核验。

忠实度比较回答与模型实际看到的上下文,检查每个外部声明能否从证据中推出。

正确性比较回答与人工确认的参考事实,检查结论是否真实。

相关性比较回答与用户问题,检查模型是否真正回答了问题。

完整性比较回答与期望声明,检查答案是否遗漏关键条件。

这四项可能出现看似矛盾、实际上完全合理的组合。

例如,上下文本身是一份旧版制度,模型逐字复述。此时答案对上下文很忠实,但相对于当前参考事实并不正确。

又如,上下文缺少一个条件,模型只回答现有证据可以支持的部分。它可以既忠实又正确,却并不完整。

再如,答案包含全部正确事实,但在开头写了大量无关背景。它的正确性可能很高,相关性和可用性却仍然较差。

只有把指标分开,团队才知道应该更新语料、改善检索、调整生成约束,还是优化表达。

忠实度最好按照声明进行核验。

先把答案拆成最小可判断的事实声明,再为每条声明寻找支持片段,并记录:

  • supported
  • contradicted
  • not_in_context

不要只让裁判返回一个从 0 到 1 的数字。至少应该保留声明文本、证据片段 ID、判定结果和理由。

Ragas 当前 Faithfulness 实现的核心思路,也是先生成声明,再判断声明是否能从检索上下文直接推出。

源码同时表明,如果没有可评分声明,结果可能是 NaN。

这种状态不是“完全不忠实”,更不是“默认通过”,而是评测器没有产出有效判定。

正确性需要可靠的参考事实。

对于高风险规则、数字、日期和条件关系,优先使用人工维护的原子声明和精确匹配规则。

对于允许多种表达方式的解释性回答,可以使用 LLM 裁判,但必须明确参考事实、评分标准和冲突判定规则。

相关性也不应该奖励无边界扩写。先检查答案是否直接回应问题,再检查背景是否有助于理解,最后限制与任务无关的内容。

完整性尤其适合使用多声明覆盖方式进行评估。

把期望事实设置成集合,分别统计答案明确覆盖、部分覆盖和遗漏的项目。

如果答案把两个条件之间的“或”写成“且”,不能因为关键词都出现了就算覆盖。关系词、否定词、主体和时间范围都必须进入核验。

声明级记录能够让这类错误变得可见,也方便人工快速复核最重要的失败案例。

六、建立判例库:覆盖失败类型比盲目堆数量更重要

建立评测集时,最常见的误区是先追求数量。

随机生成几百个同质问答,可能让平均分显得很稳定,却覆盖不到真正会引发事故的边界。

更有效的起点是按照真实任务分类:

  • 事实查询;
  • 多条件归纳;
  • 内容比较;
  • 操作步骤;
  • 时间与版本问题;
  • 跨文档组合;
  • 表格读取;
  • 缩写与别名;
  • 不可回答问题;
  • 冲突证据。

每一类先选择少量代表案例,确保每个失败阶段都有样本,再逐步扩充。

样本来源可以分为三路。

第一路是业务或产品验收问题,由领域人员给出期望声明和权威来源。

第二路是生产坏例,去除敏感信息后回流,并保留真实措辞和失败上下文。

第三路是有目的的扰动,例如同义改写、拼写错误、旧版本干扰、相近实体、缺少一个条件和互相矛盾的片段。

合成问题可以补充覆盖,但不能替代真实问题。因为合成器很容易生成与语料措辞过度贴合的简单问题。

标注过程应把“相关文档”“相关片段”“期望声明”和“可回答状态”分开。

标注者可能对相关性产生分歧,因此需要明确规则:

  • 片段属于直接证据、补充背景还是无关内容;
  • 是否必须同时出现多条证据;
  • 旧版本是否算相关但不适用;
  • 只包含答案关键词、却没有关系信息的片段是否算证据。

对于存在争议的案例,应保留多个标注和最终裁决记录,而不是静默覆盖。

划分数据时,不要让同一文档的高度相似问题同时出现在调参与验收集合中。否则团队很容易针对少数文档过拟合。

还应该保留一个冻结的小型回归集,只在发布前运行。日常调参使用开发集,线上坏例进入候选池,经人工确认后再升级为长期样本。

语料更新时,不要直接重写旧标签,而应该创建新版本。这样才能区分“系统发生退化”和“事实本身发生变化”。

平均分之外必须查看切片。

可以按照问题类型、文档类型、语言、长度、权限范围、是否跨文档、是否不可回答等维度拆分。

总体提升可能掩盖某个关键切片的大幅下降。对高风险切片设置独立门槛,对低风险表达问题允许人工抽样复核。

发布决策的重点不是追求一个完美数字,而是明确哪些退化绝对不能接受。

样本还要覆盖“近似正确”的困难负例。

普通负例与问题毫无关系,检索器很容易将其排除。真正危险的是:

  • 同一产品的旧版手册;
  • 名称相近但主体不同的制度;
  • 只差一个否定词的条款;
  • 数字单位不同的表格;
  • 包含大部分答案却缺少适用范围的片段。

这类内容最容易获得较高相似度,也最容易诱导生成模型补齐错误结论。

可以为这些片段单独增加hard_negative标签,观察候选生成和重排是否真正理解了关键差异。

标注质量本身也需要检查。

每个样本至少经过一次独立复核。争议通常集中在直接证据与背景材料的边界、条件关系是否完整,以及问题在当前语料版本下是否可回答。

可以定期抽样计算标注一致性,但更重要的是保存分歧原因。

如果两个领域人员对规则本身的理解不同,系统评测无法替组织完成事实裁决。应该先明确权威来源和生效范围,再更新参考声明。

评测集规模扩大后,还要防止重复样本让某类问题获得过高权重。

可以按照问题意图和参考片段进行聚类,检查大量改写是否都指向同一事实。

报告同时提供“按样本平均”和“按意图平均”,避免某个热门问题的几十种说法主导总体结果。

对于少见但高风险的案例,不要依靠重复数量提升权重,而应在发布闸门中设置独立的全量通过条件。

最后,为每个样本建立生命周期:

  • 新增;
  • 已复核;
  • 冻结;
  • 待更新;
  • 已废止。

当语料版本变化导致参考事实失效时,样本应转为待更新,并从当前发布判定中隔离。不能继续使用旧事实给新系统扣分,同时也要保留历史版本,用于回放旧事故。

评测数据不是一次性的测试脚本,而是一套需要版本、审阅和变更记录的工程资产。

七、自动裁判只是鉴定助手,不能成为唯一事实源

LLM 裁判适合判断语义等价、声明是否得到证据支持,以及回答是否切题。

但裁判本身也会受到模型版本、提示词、顺序、上下文长度和输出格式影响。

ARES 使用少量人工标注样本校准自动评测的思路值得借鉴:先建立人工金标准,再测量裁判与人工的一致性,最后才扩大到更多样本。

没有校准集的自动分数,只是另一个模型的意见。

校准时至少要观察误报和漏报。

忠实度裁判可能把常识推断误判成证据支持,也可能因为同义表达将正确答案判为不支持。

正确性裁判可能偏好更长、更接近参考答案措辞的文本。

成对比较还可能受到答案顺序影响。

对关键指标,可以交换候选顺序后再运行一次,或者使用两个独立提示词进行交叉检查。

如果判定不一致,应将案例送入人工复核,而不是取一个看起来很精确的平均数。

裁判提示词必须版本化,输出采用严格结构,并包含判定、理由以及引用的声明或片段 ID。

每次运行还应记录:

  • 裁判模型标识;
  • 提示词哈希;
  • 温度等生成设置;
  • 重试次数;
  • 原始输出;
  • 解析状态。

裁判升级时,先在冻结校准集上并行运行旧版和新版,比较混淆矩阵和切片差异。

不要把裁判变化造成的分数漂移,误认为 RAG 流水线发生了变化。

自动评测还需要明确的失败状态。

网络错误、超时、内容被截断、结构化输出解析失败、没有生成声明、输入上下文为空,都应该记录为evaluation_error并单独统计。

Ragas 既往错误中出现过No statements were generated和 NaN,当前源码也明确在声明列表为空时返回 NaN。

流水线必须在聚合前检查数值是否有效,不能让 NaN 被数据库默默丢弃,也不能用零填充后误判为模型退化。

对于高风险声明,保留人工抽样是必要的。

可以优先抽查以下案例:

  • 自动裁判置信度较低;
  • 多个裁判结论不一致;
  • 涉及否定或数量关系;
  • 引用了互相冲突的文档;
  • 版本切换后首次出现。

人工反馈应该回写到校准集和错误分类,而不是只修改本次报告。

这样,裁判本身也会进入持续回归,而不是成为一个不可质疑的黑盒。

八、用请求ID封好证物袋:把错误码和中间产物串起来

离线评分只有在能够回到运行证据时,才具有调试价值。

每条请求都应该生成一个稳定的逻辑请求 ID,并在检索、重排、上下文拼装、模型调用和评测阶段持续传递。

阶段记录至少包含开始与结束时间、输入版本、输出数量、状态码、错误类型和内容哈希。

不要记录真实密钥,也不必默认保存完整用户正文。可以通过脱敏字段、短期受控样本和哈希定位,在排错能力和最小化采集之间取得平衡。

开发工具中最值得查看的,不是一张成功界面的截图,而是最终请求和中间产物。

检索阶段检查:

  • 过滤条件是否按预期生效;
  • 候选数量是否为零;
  • 参考片段是否在重排前出现。

上下文阶段检查:

  • 实际传给模型的片段 ID;
  • 片段顺序;
  • 截断原因;
  • 版本和来源信息是否保留。

生成阶段检查:

  • 结束原因;
  • 解析状态;
  • 答案声明。

评测阶段检查:

  • 裁判输入是否与生成时的上下文一致;
  • 裁判使用的模型和提示词版本;
  • 是否出现解析失败或无有效声明。

如果裁判看到的文本与模型当时看到的文本不同,忠实度分数就没有可比性。

错误也应该按照阶段分类。

例如:

  • retrieval_empty:没有候选结果;
  • context_truncated:候选存在,但上下文预算丢弃了证据;
  • generation_empty:模型调用完成,却没有可用答案;
  • evaluation_nan:评测器没有产生有效数值;
  • judge_parse_error:裁判输出不符合预期结构。

retrieval_empty还应继续区分索引未写入、过滤清空、权限拒绝或查询异常。

分类之后,再附加原始 HTTP 状态、框架异常和请求 ID,避免把所有情况都压成一句“RAG 失败”。

调试比较必须控制变量。

首先固定语料快照、问题集、生成模型和提示词,只修改切分或检索参数。

然后固定检索结果,只比较上下文拼装策略。

最后固定上下文,只比较生成提示词或模型。

一次同时更换 Embedding、TopK、重排器和提示词,即使总体分数有所提升,也无法知道贡献来自哪里,更无法在发生退化时快速回滚。

为了让对照实验可信,还要记录缓存命中和随机性。

如果候选版本复用了旧检索缓存,而基线重新计算,那么比较的就不是两个配置。

如果生成模型存在随机采样,只运行一次也可能把偶然波动误认为改进。

实验记录应该注明缓存策略、随机种子是否可控、每个案例的重复次数和聚合方式。

对于无法完全确定的模型输出,优先检查逐案例方向是否稳定,并把波动最大的案例送入人工复核。

生产追踪和离线评测应该共享同一种案例格式。

线上发现坏例后,通过请求 ID 拉取脱敏的问题、片段 ID、版本和答案,经人工确认后写入候选评测集。

离线重放产生的新结果,再与原始运行进行比较。

这个闭环比只看线上满意度更可操作,因为它把用户反馈连接到了具体的流水线阶段。

九、观察失败标签迁移:让证据链直接决定能否发布

发布前,基线版本与候选版本必须在同一语料快照、同一评测集和同一裁判配置上运行。

首先比较确定性检索指标,然后比较证据状态分布,最后比较生成指标。

如果检索 Recall 提升,但上下文噪声明显增加,就不能只看第一项宣布成功。

如果忠实度提升,但完整性下降,也要判断产品是否能够接受更加保守的回答。

发布闸门应该表达这种权衡,而不是把全部指标加权成一个难以解释的总分。

确定性指标可以设置硬条件,例如:

  • 高风险参考片段不得从前 K 个结果中消失;
  • 不可回答样本不得生成无证据的确定结论;
  • 关键条件关系不得从“或”变成“且”;
  • 有效版本不得被旧版本覆盖;
  • 权限过滤不得让无权用户看到不应访问的证据。

LLM 裁判分数具有一定波动,更适合采用重复运行、置信区间或允许的小范围变化,并对边界案例进行人工复核。

不要把小数点后很多位当成确定性,也不要因为一次运行高于阈值就忽略方差。

发布闸门还要检查失败率。

评测任务超时、NaN、解析错误和缺失追踪,不是可以从分母中删除的杂项,而是评测基础设施不可靠的信号。

应该先要求有效评测覆盖率达到预期,再比较质量分数。

否则,候选版本可能通过“让困难案例无法评分”获得更高的平均值。

报告应该同时列出:

  • 总样本数;
  • 有效样本数;
  • 各类错误数量;
  • 进入人工复核的样本数。

每次变更还应生成差异报告:

  • 哪些案例从通过变成失败;
  • 哪些案例从失败变成通过;
  • 最早断点从哪一站迁移到了哪一站;
  • 相关片段顺序发生了什么变化;
  • 声明判定发生了什么变化。

团队应该优先阅读差异最大的案例,而不是根据平均分猜测原因。

如果候选版本失败,应能回到对应配置版本和证据快照;如果候选版本通过,也要保存结果,作为下一次比较的基线。

上线以后,可以继续进行小比例在线抽样,但在线分数不能替代离线金标准。

线上数据负责发现新的分布和失败方式,离线集合负责稳定地比较版本。

新增坏例需要先去除敏感信息、确认权威事实并标注失败阶段,然后再进入长期回归集。

这样,评测集会随着真实问题增长,同时保持每个样本的来源和判定结果可追溯。

十、结案清单:回答哪句错、断在哪里、如何防止复发

整套方法可以从一条最小闭环开始。

第一步,为现有 RAG 请求增加稳定的案例 ID,保存问题、片段 ID、顺序、上下文、答案和版本。

第二步,选择覆盖不同问题类型的小型集合,为每条样本标注参考片段、期望声明和可回答状态。

第三步,从错误声明逆向核对 Recall@K、Precision@K 和 NDCG,并保存漏召回和低排序的片段。

第四步,检查实际送达的证据,标记充分、部分、冲突、过期和不可回答。

第五步,把答案拆成声明,分别核验忠实度、正确性、相关性和完整性。

第六步,为自动裁判准备人工校准集,记录裁判模型和提示词版本,把 NaN、超时和解析错误设置为显式失败。

第七步,按照问题、文档、风险和可回答性查看切片,而不是只看总体均值。

第八步,让基线版本与候选版本在固定快照上并行重放,输出逐案例差异。

第九步,把关键确定性条件、裁判有效覆盖率和高风险人工复核写入发布闸门。

第十步,将线上坏例按照相同数据结构回流,持续扩大评测覆盖。

如果需要在 OpenAI 兼容客户端中做最小链路核验,应先区分三个地址层级:

  • 服务根地址:https://api.vectorengine.cn
  • 兼容接口前缀:https://api.vectorengine.cn/v1
  • Chat Completions 接口:https://api.vectorengine.cn/v1/chat/completions

这三个字符串代表不同的配置层,不能在客户端字段中想当然地互换。

示例凭据只应使用YOUR_API_KEY或环境变量VECTORENGINE_API_KEY,不要在案件档案、日志或截图中保存真实密钥。

最终验收时,不要只问“总分是多少”,而应该问三组可以执行的问题:

  1. 候选现场能否指出缺失片段和错误排序?
  2. 送达证据能否指出缺失、冲突或过期的声明?
  3. 最终回答能否把每条声明回指到证据,并区分忠实、正确、相关和完整?

如果其中任何一个问题只能得到一个无法追溯的数字,评测体系就仍然不具备排错能力。

真正可用的评测体系,还应该让一个没有参与事故的新成员,只凭一条失败记录就能复现问题:找到相同的语料快照,重放相同的检索配置,查看进入上下文的片段,再核对答案声明与证据。

如果复现仍然依赖当事人的记忆,说明证据链还没有闭合,也不适合承担自动发布判断。

RAG 系统最危险的状态,不是偶尔答错,而是答错以后只能得到一句:“检索已经命中,可能是模型问题。”

这句话把文档、解析、切分、过滤、召回、排序、裁剪和生成全部藏进了一个模糊结论。

把错答视为证据链断裂,改变的是团队观察系统的单位:从整段答案变成原子声明,从“有文档”变成“证据完整送达”,从单一总分变成失败标签迁移,从一次修复变成可以持续回放的判例。

当每条错误声明都能追溯到最早断点,Recall@K、Precision@K、NDCG、忠实度、正确性、相关性和完整性,才不再是一组用于展示的名词,而会真正成为守住不同链路的工程仪表。

参考资料

  1. RAGAs: Automated Evaluation of Retrieval Augmented Generation
    https://aclanthology.org/2024.eacl-demo.16/

  2. ARES: An Automated Evaluation Framework for Retrieval-Augmented Generation Systems
    https://aclanthology.org/2024.naacl-long.20/

  3. BEIR: A Heterogenous Benchmark for Zero-shot Evaluation of Information Retrieval Models
    https://arxiv.org/abs/2104.08663

  4. Microsoft Learn, Retrieval-Augmented Generation Evaluators
    https://learn.microsoft.com/en-au/azure/foundry/concepts/evaluation-evaluators/rag-evaluators

  5. LangChain Documentation, Evaluate a RAG application
    https://docs.langchain.com/langsmith/evaluate-rag-tutorial

  6. Ragas Faithfulness metric source
    https://github.com/vibrantlabsai/ragas/blob/main/src/ragas/metrics/_faithfulness.py

  7. Ragas evaluation schemas
    https://docs.ragas.io/en/latest/references/evaluation_schema/