章节04 / 14
  1. 01AI Harness 不是测试脚本,而是 AI 系统的质量控制台
  2. 02先写任务协议,再谈评测指标
  3. 03Golden Dataset:把“感觉不错”变成可回归样例
  4. 04评测不是一个分数:判分器、断言和人工复核怎么组合
  5. 05结构化输出 Harness:先挡住形状错误,再处理业务错误
  6. 06Tool Harness:模型只能提议动作,执行权必须被隔离
  7. 07RAG Harness:先评检索,再评回答
  8. 08Agent Harness:把多步智能体变成可暂停、可恢复、可审计的状态机
  9. 09红队与安全 Harness:把提示注入当成常规回归项
  10. 10观测 Harness:trace 里该看见什么,不该记录什么
  11. 11CI 回归门禁:让 Prompt、模型和检索改动都要过关
  12. 12线上反馈回流:用户反馈怎样变成下一版样例
  13. 13模型路由与发布 Harness:灰度、回滚和成本风险一起看
  14. 14综合项目:交付一个 AI Harness Engineering 蓝图
本文目录12
  1. 拒绝“单一分数”:为什么平均分会掩盖致命的退化
  2. 规则断言(Assertions):在最外围拦截低级格式错误
  3. 规则断言配置示例
  4. 大模型判分(LLM-as-a-Judge):用 Rubric 替代模糊的感官评分
  5. 优秀 Rubric 的设计准则
  6. 双模竞技(Pairwise Comparison):新旧 Prompt 升级时的灰度决策
  7. Pairwise 对比的评测逻辑
  8. 人工复核与黄金数据集:如何建立持续演进的真实地面准则(Ground Truth)
  9. 科学的人工复核抽样策略
  10. 评测矩阵设计:从生产链路逆向推导的指标组合
  11. 评测方案落地:一个典型 RAG 系统的指标配置与自动化演练
  12. 1. 业务场景定义
04

评测不是一个分数:判分器、断言和人工复核怎么组合

本单元深入探讨 AI 评测指标的多层组合策略,比较规则断言、LLM judge、人工复核、pairwise 对比和业务指标的边界,并输出一套评测指标矩阵、LLM judge rubric 和人工复核抽样策略。

前置基础
  • 理解基础 Prompt 调试流程
  • 了解基础的 JSON Schema 语法
学习结果
  • 能够为特定的 AI 业务场景设计出分层的评测指标矩阵(规则、模型判分、人工)
  • 能够编写具备可执行、无歧义的 LLM judge rubric
  • 能够设计科学的人工抽样规则,与自动化评测系统形成数据闭环

在建设大语言模型(LLM)驱动的系统时,我们很容易陷入一种盲目追求“全局平均分”(如:通过率 85%,或者 LLM 打分平均 4.2/5)的误区。这种单一维度的平均数字会掩盖致命的系统退化。一个更新了 Prompt 的 RAG 检索系统可能在整体评分上提升了 5%,但却在 2% 的高频核心咨询场景中输出了严重的幻觉信息,甚至泄露了敏感数据。这就是为什么我们需要在测试套件(Harness)中构建分层评测矩阵

本单元将带你剖析规则断言、LLM 判分器(LLM-as-a-Judge)、人工复核、两两对比(Pairwise Comparison)和业务指标的适用边界,学会用多层证据链替代单一的分数,并最终交付一套可以直接应用于生产流程的指标矩阵与评审策略。


拒绝“单一分数”:为什么平均分会掩盖致命的退化

大模型应用的评测与传统软件测试有着本质区别。传统单元测试的输出是确定性的 Assert.AreEqual(expected, actual),而大模型的输出具有概率性、开放性和语境依赖性。如果我们只使用一个大模型来充当唯一的裁判,并给出一个总体的分数,我们会遇到以下三个无法绕开的挑战:

  1. 判分器漂移与自身偏置:作为裁判的大模型本身也会产生幻觉、顺从性偏置(倾向于给长回答打高分)以及首尾位置偏置。如果你只看一个最终得分,你无法分清是业务模型的生成变差了,还是判分模型自身在退化。
  2. 业务安全底线的坍塌:在一个包含 1000 个测试用例的 Regression 集合中,950 个日常闲聊或低风险提问的分数从 4 分升到了 5 分,而 50 个涉及“退款流程”、“账号注销”的安全边界用例直接输出了错误引导。从统计平均值来看,分数上升了,但对于线上生产来说,这是一场灾难。
  3. 缺乏诊断可解释性:当评测后台警报说“当前分支得分 3.8,低于主干分支 4.1”时,工程师无法直接开展行动。是格式错了?是回答不完整?还是幻觉率升高了?

因此,一个合格的测试套件必须建立多层防御与证据链组合。我们要把一个“好不好”的抽象判断,拆解成从客观到主观、从低成本到高成本的层级漏斗。这就是评测矩阵的核心思想。


规则断言(Assertions):在最外围拦截低级格式错误

如果你的业务对 JSON 格式有硬性依赖,必须在 API 请求中启用 OpenAI Structured Outputs 并定义严格的 JSON Schema,因为这能从协议层面保证格式正确,而仅靠 Prompt 或宽松的 LLM judge 会产生无法解析的坏账。

根据 OpenAI 发布的 Structured model outputs 规范,使用 strict: true 的 JSON Schema 可以确保模型输出完全符合预设的 JSON 拓扑。然而,正如该指南所警示的,Schema 约束形状,却无法保证返回的具体事实、逻辑和业务逻辑的正确性。这意味着,格式正确只是通过了“第一道防线”,我们仍需要非 Schema 的规则断言来进行更细致的、确定性的业务阻击。

Promptfoo 官方文档在介绍评测用例和断言(assertions)时提到,断言可以通过 containsis-jsonjavascript 等多种低开销规则快速拦截不合规输出。基于这一设定,我们在评测套件中应该优先把这类低算力消耗、高确定性的断言作为第一道关卡,而不是直接调用昂贵的 LLM judge,从而最大化评测效率并降低测试成本。

规则断言配置示例

在 Promptfoo 配置文件 promptfooconfig.yaml 中,我们可以直接通过配置低成本的正则、JSON Schema 以及包含关系来拦截基础错误,避免进入昂贵的大模型打分环节:

yaml
tests:
  - description: "测试客服退款政策输出的完整度与合规性"
    vars:
      user_query: "我想申请七天无理由退款,该怎么操作?"
    assert:
      # 1. 规则断言:必须输出特定业务链接,否则直接判不通过
      - type: contains
        value: "https://example.com/refund-policy"
      # 2. 规则断言:严禁包含敏感、不合规字样
      - type: not-contains
        value: "私下转账"
      # 3. 规则断言:字数限制,拦截由于模型死循环导致的超长输出
      - type: javascript
        value: "output.length < 800"

当这些规则断言报错时,评测应当立即阻断,并将该 Case 标记为 FAIL_RULE。只有当这些廉价且高效的规则断言全部通过后,我们才应该把输出投喂给更高级的判分逻辑。


大模型判分(LLM-as-a-Judge):用 Rubric 替代模糊的感官评分

对于“回答是否专业”、“有没有体现同理心”、“是否包含无关的废话”等无法通过正则、字符匹配来解决的问题,我们需要引入大模型判分器(LLM-as-a-Judge)。

但是,直接让大模型“给下面的回答打 1 到 5 分”是毫无意义的。模型会对 4 分和 3 分的界限感到模糊,导致打分结果标准不一、方差极大。我们必须提供无歧义的量化 Rubric(打分量表)。每一档分数(1分、2分、3分、4分、5分)都必须定义清晰的、排他的物理证据支撑。

优秀 Rubric 的设计准则

  • 可证伪的描述:不要写“5分:回答非常客气和完美”,而是写“5分:包含欢迎语,清晰解答了用户疑问,主动询问是否有其他问题,且未使用任何生硬的技术术语”。
  • 扣分制逻辑:从满分开始,发现一项缺失则明确扣除对应分数,并在输出中给出推理链(Reasoning Chain)。

以下是一个应用于客服场景的 “回答合规与同理心” 评估 Rubric 模板:

markdown
你是一个资深的质量控制专家。请评估客服大模型的回答是否满足合规与同理心规范。

# 评分量表 (1-5分)
- **1分 (严重违规)**: 回答中出现了辱骂、挑衅、或者引导用户线下私自转账等安全红线行为。
- **2分 (不合规/错误引导)**: 虽然没有红线违规,但给出了错误的业务流程指导(例如告诉用户不支持退货,而实际上支持),或者直接拒绝服务且态度冷漠。
- **3分 (勉强合格)**: 业务逻辑无硬伤,但完全没有同理心。通篇使用机械化的机器人模板回复,忽略了用户的负面情绪,或未主动提供下一步行动指引。
- **4分 (良好)**: 业务逻辑正确,表达了同理心(如“很抱歉给您带来不便”),并且能够清晰、有条理地解答问题。
- **5分 (卓越)**: 在 4 分的基础上,不仅解答了当前问题,还根据用户所处阶段主动提示了潜在的避坑指南,且语气温暖自然。

# 输出格式约束
请严格按照以下 JSON 格式输出,不要有任何 Markdown 包裹之外的解释:
{
  "reasoning": "一步步分析你的打分依据,必须指出具体的句子作为证据。",
  "score": 评分数字
}

在 Promptfoo 中,你可以将该 Rubric 配置为一个 llm-rubric 类型的断言:

yaml
- type: llm-rubric
  value: | 
    评估回答是否表现出同理心,且业务正确。必须符合 1-5 分的标准。
    (此处贴入上面的 Rubric 正文)

双模竞技(Pairwise Comparison):新旧 Prompt 升级时的灰度决策

如果评测指标的变动直接关联到灰度发布门禁,不要直接使用大模型打出的 absolute score(绝对分数),应该采用 Pairwise 对比(两两对比)来判定新旧版本的相对优劣,否则 LLM 判分器自身的偏置和漂移会带来高昂的虚警。

大模型判分器对单一文本打出 4 分或 5 分的绝对值波动较大。例如,今天调用 GPT-4o 判分,由于 API 的微小更新,原本打 4 分的内容可能变成了 3.8 分,造成自动化发布流水线虚假报警。而双模竞技(Pairwise Comparison)则是将同一输入(Prompt + Variable)在两个不同分支(例如:当前线上主干 main vs 待发布开发分支 feature/new-prompt)下跑出来的输出 Output AOutput B 随机打乱顺序,交给裁判模型,让其给出 A 优于 B、B 优于 A,还是平局的判断。

Pairwise 对比的评测逻辑

text
               ┌───────────────┐
               │  User Query   │
               └───────┬───────┘
                       │
        ┌──────────────┴──────────────┐
        ▼                             ▼
┌───────────────┐             ┌───────────────┐
│   Output A    │             │   Output B    │
│ (Production)  │             │ (Candidate)   │
└───────┬───────┘             └───────┬───────┘
        │                             │
        └──────────────┬──────────────┘
                       ▼
             ┌──────────────────┐
             │   LLM Judge      │ (盲测:打乱顺序)
             │ (Which is better?│
             └─────────┬────────┘
                       │
        ┌──────────────┼──────────────┐
        ▼              ▼              ▼
   [A wins]         [Tie]          [B wins]
 (退化警报!)       (安全)         (可发布提升)

这种设计极大地抵消了大模型本身的“偏置”。即使判分器的评判尺度今天整体偏严,它在对比两个具体文本时,其相对偏好依然是稳定的。在 CI/CD 上线门禁中,我们可以设置如下发布标准:

  • B wins (新版胜出) 的比例必须显著高于 A wins (旧版胜出)。
  • A wins 的占比严禁超过 5%(如果新版在 5% 的场景中发生了退化,即使整体平局率高,也需要挂起发布,进行退化排查)。

人工复核与黄金数据集:如何建立持续演进的真实地面准则(Ground Truth)

引用 OpenAI 官方 Working with evals 指南,评测集(Evals)的建立是为了进行模型质量回归和支撑上线门禁。但在实际工程中,完全自动化的回归套件并不能替代人工对边缘案例(Edge Cases)的复核。我们需要将自动评分与人工标注有机结合,利用自动化评测跑完大批量测试后,针对争议区间(如评分为中等或新旧模型输出不一致的样本)拉起人工复核任务。

人工直接评审 10,000 条输出是不现实且极其低效的。一个科学的 Harness 必须建立人机协同的抽样策略,将最宝贵的人工工时用在刀刃上。

科学的人工复核抽样策略

  1. 全量通过自动过滤网:凡是规则断言失败、格式校验(Structured Outputs)不通过的,直接自动判定失败,不进入人工复核
  2. 边界与争议性样本抽样:对于 LLM Judge 评分落在灰色地带(例如 5 分制下,被打 3 分或 2 分的模糊区间,以及 Pairwise 评估中新旧模型发生“分歧”的用例),系统应自动打标并推送到人工复核队列。
  3. 高权重业务特征抽样:针对核心付费用户、政企大客户提问、或者涉及退款和法律纠纷的 Case,无论机器打分多高,都要采取固定比例(如 10%)的盲抽复核。
  4. 回流机制:人工复核如果发现大模型判分器打错了(例如模型判了 5 分,人工判定其实有严重错误),则必须立刻将该 Case 的“标准人工答案及打分”提取出来,作为黄金数据(Ground Truth)沉淀,并更新 LLM Judge 的 Rubric,防止裁判持续犯错。

评测矩阵设计:从生产链路逆向推导的指标组合

为了落实以上策略,我们将不同手段组合起来,设计一个完整的评测指标矩阵(交付物)。在建设一个典型的 AI 业务系统(例如一个金融理财 Agent 助手)时,我们将指标从低到高划分为四个层级,各司其职:

评估层级评估指标评估方法适用边界触发与阻断策略
层级一:基础格式与安全底线JSON 结构、黑名单词汇拦截、输入长度控制规则断言(Zod/Regex/JSON Schema)校验输出完整性,防止死循环与红线词泄露。只要任何一条规则断言失败,一票否决,直接判定测试失败,禁止上线,且不计入后续 LLM 评分。
层级二:业务事实正确性信息检索忠实度 (Faithfulness)、上下文召回率 (Context Recall)LLM-as-a-Judge (基于 RAG 检索原文比对)验证生成内容是否有事实性幻觉。设定及格线(如 Faithfulness 必须 $\ge 0.8$)。低于及格线的用例,拦截发布,并自动发送到人工复核池。
层级三:主观体验与同理心表达流畅度、同理心表达、废话率LLM-as-a-Judge (Rubric 扣分制)验证生成的语气、语境和对话体验。属于波动性指标。允许轻微浮动(如平均分不低于 4.0 分),若发生大幅波动则触发人工抽查。
层级四:灰度对比与综合演进Win/Loss Rate (新旧分支对比)Pairwise 两两盲测 (GPT-4o 裁判)用于发布前决策,验证升级 Prompt 的整体收益。只有新版本胜出率显著高于旧版本,且旧版本优势用例(Loss)占比 $< 5%$ 时,才允许自动合并。

评测方案落地:一个典型 RAG 系统的指标配置与自动化演练

本小节将带你把上述理论落实到可执行的评测套件中。假设我们要测试一个企业内部 HR 政策问答助手,其基于 RAG 检索企业文档并回答员工提问。

1. 业务场景定义

  • 输入 (User Query): "我们公司的育儿假有多少天?怎么申请?"
  • 检索到的上下文 (Retrieved Context): "根据 2026 版员工手册,符合国家政策生育的员工,在子女满三周岁前,每年可享受 10 天的育儿假。申请人需提前 5 个工作日在 HR 系统提交配偶生育证明并上传证明附件。"
  • 预期输出要求: 回答必须准确指出“10天”和“满三周岁前”,必须提及“提前 5 个工作日”和“HR 系统申请”。严禁出现虚假的福利承诺。

2. 测试集 Harness 配置文件 (promptfooconfig.yaml)

这是一个用于跑自动化评测的 Promptfoo 配置文件模板(未真实执行,请在实际环境中结合 API key 进行调试):

yaml
prompts:
  - "你是一个专业的 HR 助手。请根据以下已知信息,用专业、温暖的语气回答员工的问题。回答必须客观,严禁胡乱承诺福利。\n\n已知信息:\n{{context}}\n\n员工提问:\n{{user_query}}"

providers:
  - openai:gpt-4o-mini

tests:
  - description: "测试育儿假规则的提取与同理心表达"
    vars:
      user_query: "我们公司的育儿假有多少天?怎么申请?"
      context: "根据 2026 版员工手册,符合国家政策生育的员工,在子女满三周岁前,每年可享受 10 天的育儿假。申请人需提前 5 个工作日在 HR 系统提交配偶生育证明并上传证明附件。"
    assert:
      # 1. 规则层校验:必须包含申请的系统和天数,防止关键信息缺失
      - type: contains
        value: "10天"
      - type: contains
        value: "HR系统"
      
      # 2. 规则层校验:防止把 2026 错写成其他年份
      - type: not-contains
        value: "2025版"

      # 3. LLM-as-a-judge 校验:无幻觉/忠实度评估
      - type: llm-rubric
        value: |
          你是一个严谨的 HR 合规审计员。你需要对比[员工手册上下文]与[AI的回答]。
          如果 AI 的回答中出现了[员工手册上下文]中没有提及的任何额外福利承诺(例如‘带薪全额发放’、‘可以申请报销’等上下文没写的东西),或者遗漏了‘提前5个工作日’的要求,请直接判定为不合格。
          合格请给 5 分,不合格请给 1 分。请给出极简的判定理由,并输出 JSON 格式:
          {"reasoning": "原因", "score": 1或5}

      # 4. LLM-as-a-judge 校验:语气同理心评估
      - type: llm-rubric
        value: |
          作为一个温暖的 HR 助手,评估以下回答是否语气合适。
          不能显得过于生硬。如果是机械、毫无情感的复述,扣 1 分;语气温柔且有专业度给满分。请使用 1-5 分制。

3. 失败诊断与排查路径

当你在终端运行 promptfoo eval 时,可能会遇到各种评测失败。以下是常见的失败状态、原因诊断和优化方案:

  • 状态一:FAIL_RULE (规则断言失败)
    • 现象:输出中不包含 "HR系统"。
    • 原因:模型把 "HR系统" 替换成了 "内部办公软件",或者由于上下文关联不够,直接略过了申请入口说明。
    • 排查路径:检查 Prompt,强化对流程入口的要求(如在 Prompt 中加入:请务必明确说明申请所需的具体系统名称和提前时间)。
  • 状态二:FAIL_LLM_RUBRIC (忠实度校验失败)
    • 现象:大模型判分器给出 1 分,理由是 AI 输出了 "并且可以根据部门业务情况弹性休假"(上下文并无此话,模型发生了泛化幻觉)。
    • 原因:System Prompt 的约束不够强,允许了模型使用先验知识或进行“合理联想”。
    • 排查路径:在 System Prompt 中加入强限制性指令:你只能基于已知信息进行回答,如果信息中未提及,请直接回答'抱歉,已知信息中未包含此项规定',严禁脑补和发散。

4. 练习与自测验收

只有当规则断言全部通过、且 LLM judge 对关键业务属性评分为优时,才能将该条测试用例标记为 Pass,除非你明确接受某些容错场景,否则任何单层防御的失效都会导致坏例(Bad Cases)直接流向线上用户。

为了检验你是否掌握了本单元的多层评测设计,请完成以下练习任务,并在你本地的项目中进行配置:

  1. 练习任务:针对一个“在线理财账单纠错 Agent”设计一个评测用例。该 Agent 的任务是核对用户的信用卡账单,指出消费总额是否正确,并给出明细。
  2. 具体交付物标准
    • 写出至少 2 个规则断言(例如限制其输出中必须包含特定计算公式或币种符号)。
    • 设计一个 4 分制的 LLM Judge Rubric,清晰区分“算术错误(1分)”、“数值正确但解释混乱(2分)”、“数值正确且步骤清晰但语气冷冰冰(3分)”、“完美解答(4分)”。
    • 制定一套 人工抽样策略:在这个金融场景中,哪些打分区间的样本必须进人工池复核?抽样比例是多少?

请将你的 promptfooconfig.yaml 补充配置片段以及人工抽样 PDF 方案写入你本周的作业库,供评测系统及助教复核。

评测不是一个分数:判分器、断言和人工复核怎么组合:把判断写进 Harness 证据链

这一节要把模糊的 AI 行为拆成可检查动作,并保留能复盘的证据。本课交付物是 一套评测指标矩阵、LLM judge rubric 和人工复核抽样策略,它必须能被复跑、复核、追踪和复盘。

如果 评测不是一个分数:判分器、断言和 还没有对应的输入样例,先不要讨论自动化覆盖率,因为没有样例就无法判断 harness 是否真的抓住问题。 如果一次评测失败会影响发布,应该保留失败输入、模型输出、工具轨迹和判分理由,否则团队只能凭记忆争论。 如果你准备把某个结果自动放行,必须先写清人工复核的例外条件,只有例外条件明确时,门禁才不会变成新的风险源。

结构化输出失败时不要只重试,要区分 schema 错误、业务错误和事实错误。围绕 评测不是一个分数:判分器、断言和人工 做排查时,记录步骤、样例、指标、风险、修复动作和复测结果。

OpenAI 的《Working with evals》说明:支撑 AI 输出评测集、评测运行、模型质量回归和上线门禁。;这意味着 评测不是一个分数:判分器、断言和 要把来源转成可执行断言。OpenAI 的《Structured model outputs》提醒:支撑结构化输出、JSON Schema 约束、校验和输出 harness。;因此本课必须写清自动判断和人工判断的边界。Promptfoo 的《Promptfoo documentation》提供的证据是:支撑 prompt/model 评测、测试用例、断言、CI 集成和红队用例。;所以当前结论按 2026-05-28 的来源状态使用。

复核触发条件要具体:如果模型 API/SDK、评测工具版本、Agent 框架、RAG 指标、安全规范、合规政策、平台 release/changelog 或关键来源页面变化,需要重新运行本课样例并更新 harness。

练习验收:把 评测不是一个分数:判分器、断言和人工 接入一个最小 AI 应用,提交包含输入样例、评测结果、失败诊断、来源证据、人工复核结论和下一步修复动作的记录。缺少任何一项,都标记为 needs_review。