> ## Documentation Index
> Fetch the complete documentation index at: https://niceeval.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# NiceEval 里的 LLM-as-judge: 给开放式输出打分

> t.judge / session.judge / turn.judge 如何用独立评判模型评估事实性、闭合式质量和摘要忠实度，以及模型解析优先级和严重级。

judge 断言是第五种评分机制，和 [Assert](/zh/concepts/assert) 里的四种并列。用在“对不对靠规则说不清”的地方——开放式行文、语气、事实一致性、摘要质量。评判模型和被测 agent **完全分离**，避免自评：同一个模型给自己的输出打分，天然会打得偏高。

```ts theme={null}
t.judge.autoevals.factuality(reference).atLeast(0.8);   // 与参考文本的事实一致性
t.judge.autoevals.closedQA("回答是否适合 10 岁小孩理解?");
t.judge.autoevals.summarizes(sourceDocument);            // 是否忠实摘要
t.judge.autoevals.closedQA("自定义评分标准描述", { on: t.reply });
```

## judge 的三种固定形状

`t.judge.autoevals` 只暴露三种固定形状，评什么都落进其中之一：

* **`closedQA(question, opts?)`** —— 闭合式判断：输出满不满足这条标准？适合打分标准明确的检查（"语气是否礼貌、具体""是否没有编造政策细节"）。
* **`factuality(reference, opts?)`** —— 输出和你给的参考文本之间的事实一致性。
* **`summarizes(source, opts?)`** —— 输出是否忠实摘要了某个源文档。

`{ on }` 指定被评的值，默认值按接收者决定（见下文）；`{ model }` 单次覆盖评判模型。

## judge 挂在哪：`t`、`session`、`turn`

和作用域断言一样，judge 调用遵守同一条规则：**接收者决定默认材料，不是调用方式决定**：

```ts theme={null}
t.judge.autoevals.closedQA("...")        // 默认评主 session 的完整对话文本
session.judge.autoevals.closedQA("...")  // (t.newSession() 的返回值)默认评这条 session 的对话文本
turn.judge.autoevals.closedQA("...")     // (t.send() 的返回值)默认只评这一轮的 turn.message
```

`t.judge` / `session.judge` 是 session 级，适合评整段对话的回答质量或跨轮一致性；`turn.judge` 是 turn 级，只看这一轮的消息——多轮 eval 里不同轮次需要不同评分标准时用它：

```ts theme={null}
const turn1 = await t.send("这张图里有什么?");          // 第一轮:看图
const turn2 = await t.send("背景是什么颜色?");          // 第二、三轮:纯文字追问,考跨轮记忆
const turn3 = await t.send("中间那个形状是什么颜色的?");

t.judge.autoevals
  .closedQA("助手是否始终基于第一轮的图片作答?")
  .atLeast(0.7);

turn3.judge.autoevals.closedQA("这一轮是否回答了形状颜色?").gate();
```

要评的不是对话本身——沙箱 diff、文件内容或其它材料——不管挂在哪个接收者上，都用 `{ on }` 显式传：

```ts theme={null}
t.judge.autoevals.closedQA("生成的代码是否是地道的 TypeScript?", {
  on: t.sandbox.diff.get("src/handler.ts"),
}).atLeast(0.7);
```

## judge 模型解析优先级

评判模型按从具体到笼统解析：

```
单次调用的 { model } 选项
  ↓
这个 eval 的 judge.model
  ↓
全局配置的 judge.model
```

```ts theme={null}
// niceeval.config.ts —— 全局默认
defineConfig({ judge: { model: "anthropic/claude-haiku-4-5" } });

// 某个需要更强模型的 eval
defineEval({
  judge: { model: "anthropic/claude-opus-4-8" },
  async test(t) {
    t.judge.autoevals.factuality(reference);  // 这个 eval 用 claude-opus-4-8
  },
});

// 单次调用覆盖
t.judge.autoevals.closedQA("rubric", { on: t.reply, model: "openai/gpt-4o" });
```

## 严重级：judge 默认 soft

judge 调用和其它断言一样是评分函数，遵守 [Assert · gate 与 soft 严重级](/zh/concepts/assert#gate-与-soft-严重级) 同一套机制——只是**默认值**和大多数值匹配器不同：

```ts theme={null}
t.judge.autoevals.closedQA("语气是否礼貌?");              // 不带阈值 → soft，纯记分，永不让 eval 失败
t.judge.autoevals.closedQA("语气是否礼貌?").atLeast(0.7); // soft + 阈值 → 只在 --strict 下才算失败
t.judge.autoevals.closedQA("语气是否礼貌?").gate();       // 提升为 gate → 低于阈值立刻失败
```

不调 `.atLeast()` 也不调 `.gate()` 时，裸的 judge 调用纯粹记一个质量分——会显示在 eval 的分数徽章上，但单独永远不会让运行失败。这是 judge 合理的默认值：一个概率模型在给另一个概率模型的输出打分，把每次没打满分都当硬失败会让整套 eval 变得脆弱、动不动就红。只有当被评的属性真的是硬底线时（比如"回复不能编造账户信息"），才用 `.gate()`。

## 相关阅读

* [Assert](/zh/concepts/assert) — gate / soft 严重级的完整规则，以及 judge 分数最终折进的判决规则。
* [Drive](/zh/concepts/drive) — `t.send()`、`t.newSession()`，以及 `t.judge` / `session.judge` / `turn.judge` 各自挂在哪个 handle 上。
* [Evals](/zh/concepts/evals) — judge 分数如何折进 eval 生命周期和 outcome 类型。
