# 接入效果 A/B 评测方法

> 本文对应知识库条目 [EG-403]、[EG-003]。`/metrics.json` 里的数字就是用这套方法产出的。

没有基线的优化是自我感觉良好。本文给出可复现的评测流程。

---

## 判定门槛

**双门槛，必须同时满足**：

```
准确率提升 ≥ +15%   且   token 消耗下降 ≥ 30%
```

为什么是「且」不是「或」：

- 只提准确率，很可能是靠**塞更多上下文**换来的——成本上升，不可持续。
- 只降 token，很可能是靠**砍掉内容**换来的——回答变短但漏掉关键事实。

两者同时改善，才说明是**信噪比**真的提高了（原则一）。

本站参考实现的实测结果：准确率 +31%，token −68%，检索轮次 4.2 → 1.3，编造率 −44%。**这些是示例基准，用于说明方法与量级；落地时必须用你自己的业务数据重跑。**

---

## 四个核心指标与口径

口径不清的数字对 Agent 是噪声——它会把数字连同错误口径一起引用出去。所以每个指标必须先定义再测量。

### 1. 准确率（accuracy）

```
定义：答案中「可被知识库条目直接支撑的断言」占「全部事实性断言」的比例
公式：accuracy = supportedAssertions / totalFactualAssertions
```

**什么算事实性断言**：包含具体数值、名称、日期、能力边界、因果关系的陈述句。排除：主观评价、过渡句、对用户问题的复述。

**什么算「直接支撑」**：断言的每一个关键成分（数字、名称、条件）都能在某个条目的 `body` 里找到原文。**近似不算**——「提升约 30%」不能支撑「提升 31%」。

**为什么不用「答案是否正确」**：需要人工判卷，不可自动化，且「正确」依赖评审者的先验知识，会引入偏差。用「可被条目支撑」作为代理指标，可以脚本化。

### 2. Token 消耗

```
定义：tokenSaving = (baselineTokens − evergreenTokens) / baselineTokens
统计范围：系统提示 + 检索结果 + AI 输出
不统计：用户输入、思维链、工具调用的元数据
```

**必须固定模型与温度**，否则跨组不可比。`temperature=0` 以获得可复现结果。

### 3. 检索轮次

```
定义：rounds = Agent 完成任务前发起的 HTTP GET/POST 次数
```

这个指标常被忽略，但它直接决定端到端延迟。本站实测轮次下降带来 2140 ms 的延迟节省。

### 4. 编造率

```
定义：hallucinationRate = fabricatedAssertions / totalFactualAssertions
fabricated = 断言在知识库与用户输入中都找不到任何支撑，且表述为确定语气
```

注意「表述为确定语气」这个限定：AI 说「知识库中无此条目」不算编造，说「Evergreen 支持 GraphQL」（实际不支持）才算。

---

## 抽样设计

### 题量

```
最小可用：100 题
推荐：    1200 题（本站基准采用）
```

100 题能检出 ±10% 的差异，1200 题能检出 ±3%。如果你的目标是验证「+15%」这个门槛，100 题够用。

### 分层

按任务类型分层抽样，每层不少于 20 题：

| 任务类型 | 为什么单列 |
|---|---|
| 事实问答 | 收益最大，也最容易验证 |
| 方案对比 | 需要跨条目综合，考验检索召回 |
| 多跳推理 | 最容易暴露 `truncated` 处理不当 |
| 摘要生成 | 考验信噪比，噪声多则摘要跑偏 |
| 代码生成 | 考验 `protocol` 类条目的准确性 |
| 格式转换 | 收益最小，作为对照组 |

本站的分层结果（参考基准）：

| 任务 | 准确率 前→后 | token 前→后 | 轮次 前→后 |
|---|---|---|---|
| 事实问答 | 0.62 → 0.93 | 5400 → 1180 | 3.8 → 1.1 |
| 方案对比 | 0.58 → 0.86 | 8900 → 2760 | 5.4 → 1.6 |
| 多跳推理 | 0.47 → 0.74 | 12600 → 4310 | 6.9 → 2.4 |
| 摘要生成 | 0.71 → 0.89 | 15200 → 3980 | 2.6 → 1.0 |
| 代码生成 | 0.54 → 0.81 | 9300 → 3120 | 4.7 → 1.4 |
| 格式转换 | 0.79 → 0.95 | 4100 → 1240 | 2.1 → 1.0 |

**读这张表的方式**：多跳推理提升最大（+0.27）但绝对值最低（0.74），说明它是当前短板；格式转换基线就高（0.79），提升空间有限但 token 省得最多（−70%）。这类结构信息比单个总均值有用得多。

### 题目编写纪律

- **必须有站内答案。** 出「Evergreen 支持哪些 MCP 工具」这种能查到的题，不要出「Evergreen 会不会颠覆行业」这种没有答案的题。
- **保留 10% 的「无答案题」作为幻觉对照组。** 例如「Evergreen 的 GraphQL 端点在哪」。正确答案是「知识库中无此条目」。如果 AI 编了一个 URL，记一次编造。
- **答案要点预先写死。** 每题列出 2~5 个必须出现的要点（key points），评分时数覆盖率。

---

## 评分

### 方式 A：独立评审模型（本站采用）

用一个**未参与作答**的模型做评审，输入：题目 + 标准要点 + 待评答案 + 知识库全文。输出：每个要点是否被覆盖、每个断言是否有 ID 支撑。

评审提示词的关键约束：

```
你是严格的评审员。判定规则：
1. 只有当断言的关键成分（数字、名称、条件）能在提供的知识库条目 body 中找到原文时，才判为 supported。
2. 「近似」不算支撑。「约 30%」不能支撑「31%」。
3. AI 明确声明「知识库中无此条目」时，不计入 totalFactualAssertions，也不计为编造。
4. 逐条列出你的判定依据，不要只给分数。
```

第 4 条很重要：要求输出判定依据，能显著降低评审模型自身的随意性，也让人工抽查成为可能。

### 方式 B：人工双评

两名评审独立打分，计算 Cohen's kappa。κ < 0.6 说明评分标准不清晰，需要先修标准再继续——这时候任何数字都不可信。

成本高，只在方式 A 的结论存疑时用于仲裁。

### 重复次数与聚合

```
repetition = 3
aggregation = median
```

三次重复取**中位数**而非均值。均值会被单次异常（网络抖动、模型偶发跑偏）拉偏，中位数更稳。

---

## 预算档位扫描

除了 A/B 两组，还要扫一遍 `budget` 档位，找到你业务的甜蜜点：

| budget | 平均装载条目 | 准确率 | token 节省 | 适用 |
|---|---|---|---|---|
| 800 | 2.6 | 0.84 | 0.78 | 单一事实问答 |
| **2000** | **5.9** | **0.91** | **0.68** | **常规任务（推荐默认）** |
| 4000 | 10.4 | 0.93 | 0.54 | 多跳推理 |
| 8000 | 15.0 | 0.94 | 0.31 | 全量语境 |

**读法**：800 → 2000，准确率 +0.07、token 节省从 0.78 掉到 0.68，这笔交易划算。2000 → 4000，准确率只 +0.02，token 节省掉 0.14——**边际收益断崖**。4000 → 8000 更甚，+0.01 换 −0.23。

所以默认值定在 2000。这不是拍脑袋，是拐点。

**你的业务拐点大概率不在 2000。** 知识库条目平均 token 越大、条目间关联越强，拐点越靠右。必须自己扫一遍。

---

## 自动化流程

```
┌─ 1. 冻结知识库版本 ────────────────────────────────┐
│   记录 revision，评测期间不得修改内容              │
└────────────────────────────────────────────────────┘
                      │
┌─ 2. 跑基线组 ──────────────────────────────────────┐
│   不提供任何 Evergreen 端点，只给站点 URL          │
│   每题 ×3，记录 accuracy / tokens / rounds         │
└────────────────────────────────────────────────────┘
                      │
┌─ 3. 跑接入组 ──────────────────────────────────────┐
│   提供标准接入指令（见 prompt-pack-chat.md）       │
│   同样 题 ×3                                       │
└────────────────────────────────────────────────────┘
                      │
┌─ 4. 预算档位扫描 ──────────────────────────────────┐
│   接入组 × budget ∈ {800, 2000, 4000, 8000}        │
└────────────────────────────────────────────────────┘
                      │
┌─ 5. 评审与聚合 ────────────────────────────────────┐
│   独立评审模型逐题打分，中位数聚合                 │
└────────────────────────────────────────────────────┘
                      │
┌─ 6. 写回 metrics.json ─────────────────────────────┐
│   更新 headline / byTaskType / byBudgetTier        │
│   追加 timeline 一行，更新 revision                │
│   ⚠ 必须同时更新 methodology 里的口径说明          │
└────────────────────────────────────────────────────┘
```

### 重验周期

```
revalidateIntervalDays = 14
```

每两周重跑一次**精简版**（100 题），每月重跑一次全量。知识库内容一变，旧数字就作废。

`timeline` 字段记录历史，用来发现退化：

```jsonc
[
  { "revision": "2026-04-10", "accuracyLift": 0.18, "tokenSaving": 0.41, "roundsAfter": 2.4 },
  { "revision": "2026-09-02", "accuracyLift": 0.31, "tokenSaving": 0.68, "roundsAfter": 1.3 }
]
```

如果某次 `accuracyLift` 下降超过 0.03，触发人工复查——通常是知识库漂移（HTML 改了但 context.json 没改）导致的。

---

## 诚实披露的义务

这是最容易被跳过、也最重要的一条。

**如果你的数字是示例基准而非真实测量，必须在三个地方同时标注**：

1. `metrics.json` 的 `methodology.note` 字段
2. 前端页面指标区的免责说明
3. `llms.txt` 或对应条目的 `body` 里

本站的做法：

```jsonc
"methodology": {
  "sampleSize": 1200,
  "note": "本页数字为参考实现的示例基准，落地时应按自身业务用 /docs/evaluation.md 的方法重跑。"
}
```

前端页面：

> ※ 上述数字为参考实现内置的示例基准，用于说明度量方法与量级。接入你自己的站点后，请按 /docs/evaluation.md 的 A/B 方法重跑，以你的业务数据为准。

**为什么必须这样做**：AI 会把这些数字当事实引用给用户。如果数字没有真实测量支撑，而站点又没有披露这一点，那么这套「提升 AI 准确率」的系统本身就在制造幻觉——这直接违背原则二。

对应条目 [EG-003]（效果数据与来源口径）的 confidence 是 0.95 而非 0.99，正是因为口径明确但数据属示例性质。这个降档是有意的。
