核心摘要
生产级 RAG 评估必须指出系统在哪一层失败。检索、证据使用、答案正确性与相关性、噪声敏感度、拒答行为、引用质量、任务结果、安全与运营指标要分开测量。使用带业务切片的版本化测试集,以人工标签校准 LLM 裁判,并同时设置整体与关键切片门禁。高平均分不能掩盖证据缺失、无依据主张、不安全作答或跨租户检索。
为什么一个 RAG 分数不够
RAG 系统可能在模型收到上下文之前或之后失败。单一满意度只能说明“有问题”,却无法告诉团队应该修改检索器、索引、提示词还是生成模型。
| 层级 | 核心问题 | 指标示例 |
|---|---|---|
| 检索 | 是否找到并排好必要证据? | recall@k、precision@k、MRR、nDCG、上下文召回率 |
| 证据使用 | 回答是否使用已有证据且没有复制噪声? | 答案忠实度、噪声敏感度、引用支持度 |
| 答案 | 结果是否正确、相关并覆盖用户要求? | 答案正确性、答案相关性、必要要点覆盖 |
| 可回答性 | 系统是否在正确时机回答或拒答? | 正确拒答、错误拒答、越界作答 |
| 端到端 | 用户是否获得有用结果并完成任务? | 任务成功、升级处理结果、用户纠错 |
| 安全 | 策略和数据边界是否成立? | 越权检索、敏感信息泄露、不安全操作 |
| 运营 | 质量是否可负担且可靠? | p95 延迟、成本、错误率、Token 与上下文预算 |
RAGAS 论文系统化描述了忠实度、答案相关性和上下文相关性等无需大量参考答案的评估方法。ARES 与 RAGChecker进一步说明裁判校准和主张级诊断的重要性。这些都是有用协议,但不能互换,也不能压缩成一个万能生产总分。
每项结果都应绑定完整的指标身份:
指标名称 + 实现版本 + 裁判模型与提示词
+ 主张或证据单元 + 参考来源与版本
+ 聚合方式 + 空样本策略
两个看板都写着「答案正确性」,也可能采用不同测量协议:一个按主张集合计算 Precision、Recall 或 F1,一个混合语义相似度与事实重合,另一个使用二元 Rubric。只有这些契约一致时,分数才可直接比较。
围绕失败切片构建测试集
有效测试集应代表业务决策和风险,而不是只随机抽问题。每条样本按所在切片记录必要证据与期望行为。
{
"case_id": "returns-policy-014",
"slice": ["policy", "multi_document", "must_cite"],
"question": "已标记最终销售的破损商品能退货吗?",
"expected_evidence": ["policy-v7#damaged-items", "policy-v7#final-sale"],
"reference_answer": "破损商品即使标记最终销售,也应进入质量问题处理流程。",
"expected_behavior": "answer",
"forbidden_sources": ["tenant-b/*"]
}
测试集至少覆盖:
- 按真实流量加权的常见问题;
- 低频但代价高或受监管的问题;
- 单跳、多跳、歧义和不可回答问题;
- 最近更新、已经删除和无权访问的内容;
- 错别字、短查询、长对话与多语言;
- 已知事故与对抗性检索案例。
保留冻结核心集用于趋势比较,再维护轮换集吸收新流量。文档、分块、标签和评估提示词都要版本化,才能解释分数变化。
先评估检索,再评估生成
检索标签应回答:问题所需证据是否出现在排序结果中。
上下文召回率检查覆盖度,即是否找到全部必要证据;上下文精确率检查噪声与顺序,即相关证据是否排在无关分块之前。
| 症状 | 可能的检索问题 | 第一轮实验 |
|---|---|---|
| 必要来源缺失 | 召回不足 | 查询改写、混合搜索、过滤器、分块边界 |
| 正确来源排名靠后 | 精确率或排序不足 | 重排器、评分特征、去重 |
| 正确来源被权限层移除 | 授权与索引不一致 | ACL 传播和策略测试 |
| 返回旧来源 | 新鲜度失败 | 版本过滤、删除和重建索引检查 |
| 重复分块过多 | 多样性失败 | 去重与单来源上限 |
原始候选与过滤后结果要分别评估。离线检索器可能召回很好,但授权过滤器删除了唯一有用段落;也可能因为评估语料错误包含无权数据而看似准确。
根据证据评估生成
答案忠实度检查生成主张是否得到检索上下文支持。常见方法先提取原子主张,再逐条检查证据:
忠实度 = 有证据支持的回答主张数 / 回答主张总数
该分数不能证明事实正确。如果来源错误,忠实回答仍会复述错误;如果模型靠记忆答对但忽略已有证据,则可能正确却不忠实。
还应把四项属性分开测量:
| 属性 | 比较边界 | 典型失败 |
|---|---|---|
| 答案正确性 | 回答主张与可信参考或可执行判定器 | 回答忠实复述了错误来源 |
| 答案相关性 | 回答与用户问题及必要要点 | 内容正确但只回答一半问题,或加入大量无关信息 |
| 噪声敏感度 | 成对的干净/带噪上下文,或错误主张与噪声分块的归因关系 | 干扰内容诱发新的错误主张 |
| 拒答正确性 | 可回答性标签与实际回答/拒答行为 | 没有证据仍回答,或证据充分却拒答 |
引用溯源的支持度与覆盖率属于另一层。正确答案可能引用错误片段,证据充分的回答也可能遗漏必要事实。不要奖励冗长:主张越多,出现无依据细节的机会越大,也更容易用无关内容掩盖简洁正确的结论。
先判断可回答性,再给答案打分
每条测试用例都应声明:当前用户有权访问的语料是否包含充分证据。只有先固定这一标签,评估器才能区分:
- 对可回答问题给出正确答案;
- 证据充分却回答错误;
- 证据不足时正确拒答;
- 证据充分时错误拒答;
- 证据不足却越界作答。
Trust-Align把 Over-responsiveness 与 Excessive Refusal 分开,UAEval4RAG则构造六类不可回答请求。论文数字只属于各自数据集与协议;可复用的工程结论是保留回答/拒答混淆矩阵的两侧,而不是只汇报一个拒答率。
校准 LLM 裁判
LLM 裁判是一种测量仪器,必须校准:
- 创建包含明确正例、反例和边界案例的人工标注集。
- 定义证据单元与允许不确定性的评分规则。
- 尽可能隐藏系统名称和候选顺序。
- 按切片比较裁判与人工标签,而不只看整体一致率。
- 审查分歧,先修改评分规则再调整阈值。
- 裁判模型或提示词变更后重新校准。
能用代码判断的属性应使用确定性检查:
package main
import (
"errors"
"fmt"
)
type Result struct {
CaseID string
Answerable bool
Answered bool
AnswerCorrect bool
SchemaValid bool
CitationIDs []string
VisibleCitationIDs map[string]bool
UnauthorizedRetrieval int
}
func deterministicChecks(result Result) error {
if result.CaseID == "" || !result.SchemaValid {
return errors.New("invalid_result_contract")
}
if result.UnauthorizedRetrieval != 0 {
return errors.New("unauthorized_retrieval")
}
for _, id := range result.CitationIDs {
if !result.VisibleCitationIDs[id] {
return fmt.Errorf("citation_not_visible:%s", id)
}
}
if !result.Answerable && result.Answered {
return errors.New("over_response")
}
if result.Answerable && !result.Answered {
return errors.New("false_refusal")
}
if result.Answered && !result.AnswerCorrect {
return errors.New("incorrect_answer")
}
return nil
}
func main() {
result := Result{
CaseID: "returns-policy-014",
Answerable: true,
Answered: true,
AnswerCorrect: true,
SchemaValid: true,
CitationIDs: []string{"policy-v7#damaged-items"},
VisibleCitationIDs: map[string]bool{"policy-v7#damaged-items": true},
}
if err := deterministicChecks(result); err != nil {
panic(err)
}
fmt.Println("release_candidate=true")
}
这段程序不负责判断自然语言是否正确,而是演示如何用确定性外壳约束单独校准的语义标签。不要让裁判模型推测权限、来源身份、Schema 合法性或精确字符串约束。
设计发布门禁
发布门禁应组合硬性不变量、切片最低值和回归上限。
hard_fail:
unauthorized_retrieval: 0
invalid_citation_ids: 0
critical_over_response: 0
critical_cases_pass_rate: 1.0
slice_minimums:
faithfulness:
policy: 0.95
general: 0.88
context_recall:
multi_hop: 0.85
answer_correctness:
policy: 0.95
regression_limits:
task_success: -0.01
false_refusal_rate: 0.01
p95_latency_ms: 500
cost_per_success: 0.05
这些数字只是示例,不是行业统一阈值。实际值应来自标注数据、测量方差、业务影响,以及错误放行和错误阻断的成本。
应在同一批案例上做配对比较。模型采样或裁判存在随机性时,报告置信区间或重复运行波动。如果单次波动可达 0.04,平均分变化 0.01 就没有决策价值。
在线评估与可观测性
离线测试控制输入,适合比较发布版本;在线评估负责发现流量漂移、新文档、厂商变化和长尾失败。
采样应按风险与新颖度,而不是平均抽样:
- 敏感或高影响结果全部评估;
- 提高新查询簇与变更来源的采样率;
- 检查低置信检索和拒答案例;
- 只保留复核所需的有界、脱敏证据;
- 把用户纠错和事故转成回归样本。
评估与追踪要分开:Trace 解释发生了什么,Eval 判断是否满足契约。Agent 可观测性指南说明如何连接两者而不收集不必要的私有内容。
实施顺序
- 定义 RAG 系统允许做出的决策。
- 设计版本化样本结构,以及有意义的流量、风险、语言和可回答性切片。
- 在优化生成前标注期望证据。
- 建立关键词、向量或混合检索基线。
- 添加权限、引用和 Schema 的确定性检查。
- 校准正确性、忠实度、相关性、噪声与拒答裁判。
- 设置硬门禁与切片回归限制,同时覆盖错误拒答和越界作答。
- 在 CI、索引变更和模型变更前运行评估。
- 抽样生产结果,并把事故加入测试集。
- 定期审查指标是否被投机利用或发生漂移。
诊断后需要优化检索时,可参考混合搜索与重排指南;架构基础见 RAG 深度指南。
常见问题
检索与生成应使用同一测试集吗?
可以共享案例,但标签不同。检索需要证据相关性和排序标签;生成需要主张支持、参考结果和拒答标签。字段应分开保存。
上下文精确率和召回率哪个更重要?
没有统一答案。缺少必要证据会限制回答上限,噪声过多则增加成本并干扰生成。应在上下文预算和具体查询切片内联合优化。
用户点赞能替代评估标签吗?
不能。反馈受到选择偏差、展示方式、用户专业度和错误延迟发现影响,应作为在线信号之一,再结合证据调查。
是否应同步调用裁判评估每个生产回答?
普通低风险请求通常不需要。同步裁判会增加成本、延迟和依赖。优先内联确定性检查,再做按风险异步采样;只有高影响决策才值得同步评审。
指标互相冲突时怎么办?
检查每一层证据。检索好但忠实度低,问题偏向生成;忠实度高但正确性低,可能是来源或参考答案问题;整体平均良好但关键切片失败,仍应阻断发布。
拒答率越高越安全吗?
不是。系统可以通过拒绝有用的可回答请求来提高拒答率。应在声明可回答性的测试集中分别报告正确拒答、错误拒答、越界作答和正确回答,再根据业务影响为不同错误类型赋予代价。