把 LLM Judge 当成最终判定结论是很多团队在做 Eval 时
很多公司在推 AI Agent 落地时,习惯用一个更强的大模型(比如 GPT-4o 或 Claude 3.5)来给 Agent 的输出打分。但问题是,如果你发现 Judge 经常报同一个错,却一直把它留在 Judge 环节,你其实是在为已经发现的 Bug 支付重复的“租金”。因为 Judge 慢、贵,而且不确定,每次跑 Eval 结果可能都不一样。
当 Judge 反复指出某个问题(例如:摘要中引用了原文不存在的章节)时,不要依赖 Judge 继续判,而要思考:有没有 Tier 1 或 Tier 2 的方法能抓到它?
下一篇
防止AI写代码把数据库删库:gate.cat 实操分享 →
真正高效的实操应该是建立一个“棘轮机制(Ratchet)”,把那些重复出现的 Judge 结论,尽可能地向低层级(更确定、更便宜)的检查机制迁移。
我把证据强度分成了三个层级,这在实际部署工作流时非常关键:
- Tier 1(不可伪造的证明): 比如 JSON 格式是否正确、文件是否存在、是否编译通过、是否超时。这是绝对的硬指标,速度极快且免费。
- Tier 2(统计信号): 比如输出与任务规格的 Embedding 相似度、长度分布、Diff 结果是否为空。它依赖于 Agent 无法控制的基准线,具有确定性。
- Tier 3(Model-as-Judge): 纯粹的模型观点。这只能作为信号,不能作为最终裁决。
当 Judge 反复指出某个问题(例如:摘要中引用了原文不存在的章节)时,不要依赖 Judge 继续判,而要思考:有没有 Tier 1 或 Tier 2 的方法能抓到它?
在这个例子里,可以通过简单的字符串匹配(检查引用标题是否在原文中出现)将其升级为 Tier 1 检查。
type Finding = {
claim: string; // Judge 反复抱怨的问题
sourceText: string; // Agent 没写过的内容(原文)
citedSections: string[];
};
// 升级到 Tier 1:将主观观点转化为不可伪造的事实检查
function citationsExist(f: Finding): { pass: boolean; missing: string[] } {
const missing = f.citedSections.filter(
(s) => !f.sourceText.includes(s)
);
return { pass: missing.length === 0, missing };
}
// 升级到 Tier 2:如果完全匹配太死板,则用 Embedding 相似度对比基准线
function citationGroundedness(
f: Finding,
embed: (t: string) => number[],
cos: (a: number[], b: number[]) => number
): number {
const src = embed(f.sourceText);
const scores = f.citedSections.map((s) => cos(embed(s), src));
return scores.reduce((a, b) => a + b, 0) / (scores.length || 1);
}在公司内部推行这套逻辑后,你会发现 80% 的生产环境失败(比如 JSON 格式崩了、路径幻觉、响应为空)其实都能通过 Tier 1 和 Tier 2 拦截掉。把确定性的东西交给代码,把模糊的争议留给 Judge,这样 Eval 流程才能跑得快且稳。