LLM 当裁判省的是人力,费的是心思:评分标准写不清楚,同一个输出能被同一个模型打出两种分。这一期我围绕 LLM-as-a-Judge 的评分标准设计拆出四条可执行的经验,并在 4sapi(https://4sapi.com)上把整套评测流程跑通了一遍。
一、开篇痛点:评测结果时灵时不灵,先怀疑评分标准
把打分交给 LLM 之后,我遇到的第一个问题不是模型不行,而是分数不稳定。具体症状我列过四类:
- 同一批输出,隔天重跑一遍,分数分布完全不同,昨天通过的上线门禁今天就不通过了;
- 换一个评判模型,用同一套标准评同一批样本,居然能得出相反的排序结论;
- 让评判模型"综合判断"质量,它输出一大段模棱两可的评语,最后却给不出一个可统计的分数;
- 评测脚本跑是能跑,但没人敢拿它的结果做决策,因为谁都不确定它靠不靠谱。
排查到最后,问题几乎都出在评分标准上。模糊的提示词等于放手让评判模型自由发挥,评估不一致只是表象,真正被浪费的还有每一次评测的 token——让一个 LLM 对着含糊的标准写长篇评语,等于花钱买噪音,买回来的还是不可复现的结果。
这一期我把评分标准设计拆成四条经验:问题原子化、只评客观事实、只评 prompt 明确要求的内容、用 golden set 校准。每一条我都放在 4sapi(https://4sapi.com)的评测流水线上实测过,下面逐个拆开。
二、原理速览:LLM-as-a-Judge 到底在做什么
LLM-as-a-Judge 的思路不复杂:把"评估另一个模型输出质量"这件事,从人肉打分变成一次普通的 LLM 调用。评测脚本把评分标准和待评输出拼进 prompt,发给评判模型,拿回分数,再汇总统计。
我的评测脚本
│ 拼入评分标准 + 待评输出
v
4sapi 网关(https://4sapi.com)
│ 统一格式 / 鉴权 / 限流 / 计费
v
评判模型
│ 输出结构化评分 JSON
v
评测脚本汇总分数 → 一致性报告
这条链路里,评判模型的能力只决定评测上限,评分标准才决定实际水平。标准写得含糊,模型就只能靠感觉打分,感觉这个东西恰恰是最不稳定的;标准写得可判定,分数才有统计意义,结果才能进 CI、进上线门禁。
我最开始踩的坑就在这里:背景里全是"高质量""清晰""有用"这类模糊提示,评判模型不知道这些词指什么,就会自己脑补一套标准,换一个会话脑补得还不一样——这就是评测不一致的根源,也是 token 浪费的根源。
三、经验一:问题原子化,互不重叠
第一条经验:评分标准里的每个问题,只问一件事,并且问题之间不重叠。
反例是这样的标准:"请评估回答是否清晰、完整、有帮助。"这一句话里至少混着三个维度,而"清晰""完整""有帮助"之间边界模糊——一个回答可以逻辑清晰但漏了关键步骤,评判模型会卡在"该给哪个维度打分"上反复横跳。
我现在的写法是把每个维度拆成独立的问题,每个问题只对应一个可以判真伪的事实:
| 拆分前(模糊) | 拆分后(原子化) |
|---|---|
| 回答是否清晰、完整、有帮助 | Q1:回答是否包含完整的接入步骤? |
| Q2:回答中的代码示例能否直接运行? | |
| Q3:回答是否解释了每一步的作用? |
原子化带来的收益是实打实的三个:
- 每个问题可以单独统计通过率,评测跑完能直接定位到底是哪个维度崩了,而不是对着一个总分猜;
- 问题之间不重叠,就不会出现"同一个缺陷被两个问题各扣一次分"的重复惩罚;
- 每个问题足够小,评判模型的判定空间被压缩,分数自然更稳定。
判断标准是否够原子,我有一个简单的检查办法:如果回答某个问题需要同时参考两个独立事实,就说明它还能再拆。拆到每个问题只有一个谓词为止。
四、经验二:只评客观事实,用 MUST 表述
第二条经验:只让评判模型评估客观事实,不要让它做主观审美。
"语气是否自然""读起来是否舒服"这类标准,人都不一定能达成一致,让模型评更是各说各话。能进评分标准的,必须是"可以被判定为真或假"的事实,判定结果不依赖打分者的偏好。
把标准写成可判定命题,我借用 RFC 2119 的术语体系,用 MUST / MUST NOT 来表述:
- MUST:必须满足的条件,不满足即不通过;
- MUST NOT:禁止出现的情况,出现即不通过;
- MAY:可选的加分项,不参与硬性判定。
对比一下两种写法:
- 模糊版:"回答应该给出 API 的接入方式。"
- 可判定版:"回答 MUST 包含 base_url 的完整配置示例;回答 MUST NOT 遗漏鉴权参数的说明。"
"应该"是主观的,"MUST"是可验证的。评判模型对 MUST 条款的判定只有两种结果:满足或不满足,分数不再依赖它当时的心情。把标准里的"应该""尽量""最好"全部替换成 MUST / MUST NOT 之后,我的评测一致率明显回升,因为留给模型自由裁量的空间几乎没有了。
五、经验三:只评 prompt 中明确要求的内容
第三条经验:评分标准里出现的每一项,都必须在 prompt 里能找到出处,绝不添加 prompt 之外的要求。
评判模型有一个坏习惯:它会自己脑补评价维度。我遇到过最典型的例子:评测任务里只要求模型"输出一份 JSON 配置",评分标准里却写着"是否包含 Markdown 标题"——这一条 prompt 根本没要求,评判模型却会当真去检查,然后给输出扣分。这就是脑补,脑补出来的分数和任务本身毫无关系。
我用来拦截脑补的做法有四条:
- 评分标准与 prompt 逐条对照,标准里的每个动词都要能对应到 prompt 里的某句话;
- prompt 里明确写了"必须输出 JSON"的,标准里才允许出现"是否输出合法 JSON";
- prompt 里没有提出的能力要求,标准里一律不出现;
- 每次修改 prompt,同步审查一遍评分标准,防止标准与任务脱节。
只评明确要求的内容,评测结果才是在回答"这个输出是否满足任务要求",而不是在回答"模型觉得这个输出怎么样"。前者是验收,后者是观后感,评测体系要的是前者。
六、经验四:用 golden set 校准评判模型
第四条经验:评分标准写得好不好,用专家标注的 golden set 来验收,而不是靠感觉。
golden set 是一组已经由专家标好判定的样本:输入、输出、标准答案、专家评分,一一对应。校准流程是:
专家标注 golden set(输入 / 输出 / 专家分)
│
v
用评分标准驱动评判模型打分
│
v
对比模型分与专家分
│
v
不一致 → 修改评分标准或更换评判模型 → 重新评测
│
v
一致率达到目标 → 标准验收通过,可进入批量评测
一致性怎么量化?最朴素的是准确率:模型分与专家分完全一致的样本占比。样本量大之后,还可以用加权一致率,把"错一档"和"错两档"区分开,错得离谱的样本权重更高。
校准不是一次性的。换了评判模型、改了评分标准、任务描述有调整,都要重跑一遍 golden set。我的实测经验是:多数不一致并不是模型笨,而是标准里混进了主观表述——把主观词改写成 MUST 条款之后,一致率通常立刻回升,这说明校准真正校准的是评分标准,而不是模型。
七、把评测提示词工程化:评分标准进配置
四条经验落到工程上,是让评测提示词变成可维护的资产,而不是散落在脚本里的一段话。我的做法有五点:
- 评分标准写成 YAML 或 JSON 配置,独立于评测脚本存放,改标准不用改代码;
- 每条标准带编号,编号在评测报告里直接引用,分数异常时能定位到具体条款;
- 标准进版本管理,标准变了,历史评测结果才有解释依据,否则前后分数对不上账;
- 评测提示词由模板拼接:固定系统提示 + 评分标准 + 待评输出 + 输出格式要求,四段分离;
- 输出格式明确要求评判模型只输出 JSON,例如 {"pass": true},禁止长篇评语。
第四、五点合起来解决评测场景最核心的两件事:结果可直接统计,token 消耗被压到最低。评判模型不写小作文,账单上省下来的部分,在批量评测里非常可观。
八、接入 4sapi 跑 judge 评测:Python 示例
实操环节。评测脚本用 OpenAI 兼容客户端接入 4sapi(https://4sapi.com),base_url 指向统一网关,一次 API 调用完成一次判定:
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["4SAPI_API_KEY"],
base_url="https://4sapi.com/v1", # 统一网关地址
)
# 评分标准:原子化 + MUST 表述,独立于脚本维护
RUBRIC = [
"Q1: 回答 MUST 包含 base_url 的完整配置示例。",
"Q2: 回答 MUST NOT 遗漏鉴权参数的说明。",
"Q3: 回答 MUST 输出合法的 JSON 结构。",
]
JUDGE_SYSTEM = (
"系统指令:作为评测员,只依据评分标准判定客观事实,"
"不得引入标准之外的要求。只输出 JSON,格式:"
'{"results": [{"question": "...", "pass": true}]}'
)
def parse_judge_json(raw: str) -> dict:
"""去掉可能的代码围栏后解析 JSON。"""
raw = raw.strip()
if raw.startswith("```"):
raw = raw.split("\n", 1)[1].rsplit("```", 1)[0].strip()
return json.loads(raw)
def judge_once(output_text: str) -> dict:
prompt = (
"以下是待评输出:\n\n"
f"{output_text}\n\n"
"请逐条判定:\n"
+ "\n".join(RUBRIC)
)
resp = client.chat.completions.create(
model="judge-model", # 换成实际使用的评判模型
messages=[
{"role": "system", "content": JUDGE_SYSTEM},
{"role": "user", "content": prompt},
],
temperature=0, # 评测场景固定为 0,不做随机采样
max_tokens=512, # 收紧输出上限,防止写长篇评语
)
return parse_judge_json(resp.choices[0].message.content)
def run_eval(outputs: list[str]) -> dict:
summary = {"pass": 0, "fail": 0, "samples": len(outputs)}
for text in outputs:
result = judge_once(text)
for item in result["results"]:
summary["pass" if item["pass"] else "fail"] += 1
return summary
# 用法:run_eval([model_a_output, model_b_output, ...])
几个容易踩的细节:
- temperature 固定为 0:评测场景不需要随机性,同样的输入必须得到同样的判定;
- max_tokens 收紧:配合"只输出 JSON"的约束,把评判模型的发挥空间和 token 开销一起关掉;
- 每个问题独立判定:通过率逐条统计,比一个总分更容易定位问题出在哪个标准上;
- 批量评测前先跑一遍 golden set:确认一致率达标再全量执行,别拿全量账单试错。
九、评测模式对比与成本控制
把三种评测方式放在一起看,差异一目了然:
| 评测方式 | 一致性 | 单样本成本 | 可追溯性 |
|---|---|---|---|
| 人工评测 | 高,但费时 | 人力成本高 | 依赖评审记录 |
| 裸 LLM 打分(无结构化标准) | 低,波动大 | 中,评语冗长烧 token | 差,无法解释分数 |
| 结构化标准 + golden set 校准 | 高,可复现 | 低,只输出 JSON | 好,逐条标准可定位 |
成本控制的核心是别让评判模型"发挥"。同样一个样本,模糊标准可能让模型输出 500 个 token 的评语,结构化标准只要 50 个 token 的 JSON——批量评测上万条样本时,差距直接反映在账单上。
另外三个降本手段是我常用的:固定系统提示,让同一段上下文反复命中缓存读取价;批量样本合并提交,减少请求次数;评测任务与正式业务调用分开计费标签,成本归因一目了然。配合 4sapi 网关的用量统计,评测成本可以按标准、按模型、按批次拆开看。
十、成本与风险提示
把这一期的坑集中列一下:
- judge 评测也是完整的 LLM 调用,每一条样本都计费;全量评测前先抽样跑一遍,估算总 token 再决定规模,评测跑崩的账单可比模型贵多了;
- 评判模型不是万能的,它同样可能被超长输出带偏,长文本评测建议分段判定,避免"长度压倒内容";
- 标准过严会误杀、过松会漏检;golden set 校准的通过率目标,要根据业务可接受的风险定,不是越高越好;
- 评测结果只能证明"满足评分标准",不能替代业务侧的人工抽检,关键变更仍然要人工复核;
- 这里讨论的是合法的 API 接入、评测架构设计与计费优化,不涉及任何绕过官方限制的做法。
十一、评分标准验收清单
- 每个问题只问一个可判定的事实
- 问题之间不重叠,不会重复扣分
- 全部使用 MUST / MUST NOT 表述客观事实
- 标准中的每一条都能在 prompt 里找到出处
- golden set 校准一致率达到目标值
- 输出格式固定为 JSON,temperature 固定为 0
- 评分标准独立成配置并进版本管理
- 换模型或改标准后重跑校准
总结
LLM-as-a-Judge 的价值在于把评测从人肉劳动变成可重复的调用,但这一切的前提是评分标准经得起推敲:问题原子化保证每个维度独立可统计,MUST 表述保证判定可验证,只评 prompt 明确要求的内容杜绝脑补,golden set 校准保证标准与人类评分对齐。四步走完,评测脚本才敢接进上线门禁。我在 4sapi(https://4sapi.com)的评测流水线上,现在每个评分标准上线前都会先过一遍验收清单——评测的一致性和 token 账单,会随标准质量一起变好。欢迎在评论区发表想法,一起聊聊 LLM-as-a-Judge 的评分标准设计。