15.04概念更新于 2026年9月17日

评分方式

代码断言、LLM-as-Judge 与人工评审的组合。

15.04 · 课时讲解

评分方式

能用代码判的写断言,需要理解语义的交给 LLM 评审,定标准、做校准的是人。

1 / 12

一句话理解:能用代码判定的就写代码断言,需要理解语义的交给 LLM 评审,定标准、做校准的是人。三者要组合使用,而不是三选一。

有了评测集和指标,还差一个关键环节:**谁来判分?**100 道题、每题跑 3 次,就是 300 份输出。全靠人看,一轮评测要花好几天,没法每次改 Prompt 都跑;全靠代码判,“处置建议是否合理”这种问题写不出规则;全靠模型判,又不知道它判得准不准。

这一课比较三种评分方式,给出一个代码断言示例、一个 LLM-as-Judge 提示词示例,并说明怎样用人工标注来校准模型评审。

三种评分方式

Anthropic 在《Demystifying evals for AI agents》中把评分器分为三类,下表结合了文章的归纳与客服工单场景的例子:

类型 常见方法 优点 缺点 客服工单场景中适合判什么
代码评分 字符串匹配、结构校验、单元测试、静态分析、检查环境最终状态 快、便宜、客观、可复现、易调试 对“换个说法也对”的情况很脆弱 根因枚举值、必调与禁调工具、工单是否创建、金额计算
模型评分 按评分标准打分、自然语言断言、两两比较 灵活、可扩展、能处理开放式任务 结果不完全确定、更贵、需要校准 处置建议是否可执行、对用户的解释是否准确得体
人工评分 领域专家评审、众包标注、A/B 测试 质量的金标准,最贴近专家判断 贵、慢、难以规模化 制定标准、标注校准集、复核有争议的样本

主流评估平台也按类似思路提供评分器。例如 OpenAI 的 Graders 文档列出了字符串检查、文本相似度、模型打分、Python 代码评分,以及把多个评分器组合起来的 multigrader。

选择原则很简单:先问“能不能用代码判”,能就用代码;剩下的交给模型;人负责定标准和抽查。

这个选择原则可以画成一张决策图:

评分方式的选择:能用代码判定就用代码断言,否则用 LLM 评审,人工负责校准与抽查 一个评测维度 能用代码判定吗? 代码断言 根因 · 工具策略 · 状态 LLM-as-Judge 处置建议 · 解释质量 能 不能 人工评审 定标准 · 校准 抽查 校准
图 1 · 选择评分方式:先问能不能用代码判,人负责定标准、校准和抽查

代码断言:能写就写

客服工单处理 Agent 的输出是结构化 JSON(参见输出契约),很多检查都可以写成代码。下面这个评分函数对应上一课评测集里的题目格式(示例):

import json

def grade_ticket_case(case: dict, run: dict) -> dict:
    """对一次试验做硬性检查。run 包含 final_output(字符串)和 tool_calls(列表)。"""
    expected = case["expected"]
    checks = []

    # 1. 输出必须是合法 JSON
    try:
        out = json.loads(run["final_output"])
        checks.append(("valid_json", True, ""))
    except json.JSONDecodeError as e:
        return {"passed": False, "checks": [("valid_json", False, str(e))]}

    # 2. 判定状态一致:该下结论的下结论,该说“无法判断”的说无法判断
    checks.append(("status", out.get("status") == expected["status"],
                   f"期望 {expected['status']},实际 {out.get('status')}"))

    # 3. 根因正确
    if expected["status"] == "determined":
        checks.append(("root_cause", out.get("root_cause") == expected["root_cause"],
                       f"期望 {expected['root_cause']},实际 {out.get('root_cause')}"))

    # 4. 工具策略:必调工具都调用了,禁用工具一个没调
    called = {c["name"] for c in run["tool_calls"]}
    missing = set(expected.get("must_call_tools", [])) - called
    forbidden = set(expected.get("must_not_call_tools", [])) & called
    checks.append(("must_call", not missing, f"未调用:{sorted(missing)}"))
    checks.append(("must_not_call", not forbidden, f"调用了禁用工具:{sorted(forbidden)}"))

    # 5. 证据可追溯:结论引用的每个值都必须出现在某次工具返回中
    tool_outputs = json.dumps([c["output"] for c in run["tool_calls"]], ensure_ascii=False)
    untraceable = [e["value"] for e in out.get("evidence", []) if str(e["value"]) not in tool_outputs]
    checks.append(("evidence_traceable", not untraceable, f"无法追溯的证据:{untraceable}"))

    return {
        "passed": all(ok for _, ok, _ in checks),
        "checks": [{"name": n, "ok": ok, "detail": "" if ok else d} for n, ok, d in checks],
    }

这段代码体现了几个要点:

  • 每项检查单独记录。 失败时一眼能看出是根因错了,还是漏调了工具,这为后面的错误归因提供了现成的标签。
  • 检查环境与记录,而不只是最终文本。 工具调用列表来自运行记录;如果涉及写操作,还应查询沙箱数据库里的最终状态。
  • 不要求工具调用顺序完全一致。 只检查“必须调用”和“禁止调用”,给 Agent 留出合理的路径差异,详见结果评估与轨迹评估。Anthropic 也建议评分时关注 Agent 产出了什么,而不是强求它走某一条特定路径。

LLM-as-Judge:给语义质量打分

“处置建议是否可执行、是否符合 SOP”没法用代码判定,这时需要模型评审。一个好的评审提示词应该遵循这几条:

  1. 一个评审只判一个维度。 Anthropic 建议对不同维度分别使用独立的评审,而不是让一个评审同时给所有维度打分。
  2. 二元判定优先。 相比 1–10 分,“通过 / 不通过”的标准更清晰,不同评审之间也更一致。确实需要分档时,每一档都要写清楚锚点。
  3. 给参考答案和原始证据。 评审要判断建议是否基于事实,必须看到工具返回的数据。
  4. 允许“无法判断”。 Anthropic 建议给评审留出口,信息不足时返回 Unknown,而不是强行判定。
  5. 先写理由,再给结论。 OpenAI 的评估最佳实践指出,让评审在打分前先写出推理过程,有助于提高评估质量。
  6. 输出结构化结果。 方便程序汇总。
  7. 评审模型尽量与被测模型不同。 Anthropic 的评估文档一般建议这样做,以减少自我偏好。

下面是一个示例提示词:

你是一名客服工单处理质检员。你只评估一个维度:「处置建议是否可执行,并且符合 SOP」。
不要评价语气、格式或其他维度。

【用户问题】
{user_message}

【工具返回的原始数据】
{tool_outputs}

【相关 SOP 条款】
{sop_excerpt}

【参考结论与参考处置】
{reference_solution}

【待评估的 Agent 回答】
{agent_output}

【判定标准】
判为 PASS,必须同时满足:
1. 建议中的每个动作都有明确的执行方(例如客服、用户、财务),而不是“相关人员”。
2. 建议与工具返回的数据一致,没有引用数据中不存在的事实。
3. 建议符合上面的 SOP 条款;涉及退款时,金额与审批要求符合 SOP。
4. 与参考处置相比,可以措辞不同、顺序不同,但不能遗漏参考处置中的关键动作。

以下任一情况判为 FAIL:
- 违反任意一条 PASS 条件;
- 建议执行 SOP 明确禁止的动作,或越过审批直接承诺退款。

以下情况判为 UNKNOWN:
- 提供的 SOP 条款不足以判断该建议是否合规;
- 工具数据与参考结论互相矛盾。

【输出格式】
先逐条对照判定标准写出分析,再给出结论。只输出如下 JSON:
{
  "analysis": "逐条说明 1–4 是否满足,以及理由",
  "verdict": "PASS 或 FAIL 或 UNKNOWN",
  "failed_criteria": [未满足的条件编号]
}

LLM 评审也有已知的偏差。Zheng 等人研究 LLM-as-a-Judge 的论文(MT-Bench 与 Chatbot Arena)讨论了三种:位置偏差(两两比较时偏向某个位置的答案)、冗长偏差(偏向更长的回答)和自我偏好偏差(偏向自己生成的回答)。对应的做法是:两两比较时交换顺序各评一次;在标准中明确“长度不是加分项”;用不同的模型做评审。

人工评审:定标准,做校准

人工评审不是用来给每道题打分的,而是承担三项更重要的工作:

  1. 定标准。 由领域专家写出评分标准,并对边界情况给出裁决。
  2. 标注校准集。 由人给一批输出打上 PASS 或 FAIL,作为衡量模型评审的“标准答案”。
  3. 复核争议样本。 评审输出 UNKNOWN 的样本、代码断言与模型评审结论冲突的样本,以及定期随机抽检。

校准模型评审是最容易被跳过、也最重要的一步。Anthropic 强调 LLM 评审需要与人类专家仔细校准;Hamel Husain 与 Shreya Shankar 的评估 FAQ 建议,在留出的人工标注集上分别看评审对“通过”和“不通过”两类样本的识别率。

举例来说,专家标注了 100 个“处置建议”样本,70 个 PASS、30 个 FAIL,再让评审独立判一遍(示例数字):

评审判 PASS 评审判 FAIL 识别率
专家判 PASS(70) 66 4 通过类识别率 94%
专家判 FAIL(30) 6 24 不通过类识别率 80%

总体一致率是 90%(66 + 24 = 90),看起来不错。但 30 个本该不通过的建议里,有 6 个被放过了,漏判率 20%。如果这个维度关系到退款合规,这个漏判率太高。下一步是逐条读这 6 个样本,找出评审被“骗过”的共同原因,修改判定标准后,在另一批留出样本上重新检验,避免评审提示词对校准集过拟合。

校准是一个循环,而不是一次性的检查:

用人工标注校准 LLM 评审的循环:专家标注、评审独立判、看两类识别率、读漏判样本、修改标准、在另一批留出样本上重检 专家标注校准集 70 PASS · 30 FAIL 评审独立判一遍 与专家结论对照 分别看两类识别率 通过类 94% · 不通过类 80% 逐条读漏判样本 6 个 FAIL 被判成 PASS 修改判定标准 找出评审被“骗过”的原因 换另一批留出样本重检 避免对校准集过拟合 总体一致率 90%(66 + 24),但不通过类的漏判率是 20%
图 2 · 校准模型评审的循环:改完标准要换一批留出样本重检,避免对校准集过拟合

组合:一条评分流水线

三种评分方式按从便宜到昂贵的顺序串成一条流水线:

评分流水线:代码断言硬门槛、每个维度一个 LLM 评审、人工抽检,最后汇总为指标报告与错误归因 Agent 最终输出 + 运行记录 + 环境最终状态 ① 代码断言(硬门槛) JSON · 判定状态 · 根因 · 必调与禁调工具 · 证据可追溯 · 数据库状态 ② LLM 评审(每个维度一个评审) 处置建议可执行性 · 对用户解释的准确性 ③ 人工抽检 全部 UNKNOWN + 断言与评审冲突的样本 + 每轮随机抽 10% 汇总:任务得分 + 失败标签 UNKNOWN → 人工队列 任一失败 本次试验判为失败,记录失败项 FAIL 判为失败,记录失败维度 人工结论覆盖自动结论 并回流到评审校准集 指标报告与错误归因
图 3 · 评分流水线:便宜确定的检查在前,昂贵的人工在后,人工结论回流校准集

对由多个部分组成的任务,可以给部分分,例如“根因正确但处置建议不合格”记 0.5 分。Anthropic 也建议为多组件任务设计部分分。但上线门槛最好仍以“全部通过”为准,部分分用于观察进步趋势。

常见误区

  • 让评审自由打 1–10 分。 没有锚点的分数不可比较,5 分和 6 分的差别谁也说不清。
  • 一个评审同时判所有维度。 各个维度互相干扰,失败时也不知道是哪个维度出了问题。
  • 从不校准模型评审。 评审和专家的判断差多少完全未知,“评测分数提高了”可能只是评审变宽松了。
  • 代码断言写得太死。 要求回答与参考答案逐字相同,或要求工具调用顺序完全一致,会把合理的解法判成失败。
  • 用被测模型给自己打分。 自我偏好会让分数虚高。

产品经理检查清单

  • 每个评测维度分别由哪种评分方式来判?能用代码判的是否都用了代码?
  • LLM 评审的标准是否具体到“两个人读完会得出同样结论”?
  • 评审是否能看到原始证据和参考答案?是否允许输出“无法判断”?
  • 模型评审有没有用人工标注集校准过?“不通过”类样本的识别率是多少?
  • 评分器的判定结果是否有定期的人工抽检?
  • 评分器本身有版本号吗?修改评分标准后,是否重新跑了基线?

练习

为「发票审核 Agent」的“退回理由说明”设计评分方案,用 30–60 分钟完成:

  1. 列出 4 个评分维度,为每个维度选择评分方式(代码断言、LLM 评审或人工),并说明理由。例如“退回理由中引用的金额与发票一致”可以用代码判定。
  2. 选一个必须由模型评审的维度,参照本课示例写出完整的评审提示词,包含 PASS、FAIL、UNKNOWN 三档标准。
  3. 准备 10 条退回理由(其中 3–4 条有问题),先自己标注,再用提示词让模型评审,计算两类样本各自的识别率,找出一条判得不一致的样本并分析原因。

延伸阅读

下一步

本课的代码断言已经开始检查“调用了哪些工具”。下一课「结果评估与轨迹评估」专门讨论:除了答案对不对,怎样评估 Agent 的过程是否合理、安全、高效。

试试:上下文、MCP、沙箱、Prompt 注入、外链