# 知识库条目格式规范

> 本文定义 `context.json` 的结构与写作纪律。JSON Schema 见 [/schemas/knowledge.schema.json](/schemas/knowledge.schema.json)。

---

## 顶层结构

```jsonc
{
  "$schema": "./schemas/knowledge.schema.json",
  "version": "1.2.0",           // 语义化版本，结构变更时递增
  "revision": "2026-09-02",     // 内容修订日期，任何条目变更都要更新
  "license": "CC-BY-4.0",
  "site": {
    "name": "Evergreen",
    "tagline": "一句话定位",
    "canonicalUrl": "https://evergreen.example.com/",
    "rateLimit": {
      "requestsPerMinute": 120,
      "burst": 300,
      "authRequired": false     // 必须与实际行为一致，否则 Agent 会浪费一轮试探 401
    }
  },
  "categories": [ /* 见下 */ ],
  "entries": [ /* 见下 */ ]
}
```

`version` 与 `revision` 的分工：`version` 描述**结构**兼容性，`revision` 描述**内容**新鲜度。Agent 缓存时用 `revision` 判断是否需要重新拉取，用 `version` 判断解析器是否需要升级。

---

## categories

```jsonc
{ "id": "fact", "label": "站点事实", "description": "关于本站的权威事实，回答产品类问题时必须以此为准，不得推测。" }
```

本站使用的五类：

| id | label | 装什么 | 典型 confidence |
|---|---|---|---|
| `fact` | 站点事实 | 客观事实：产品定位、价格、限额、数据来源口径 | 0.95~0.99 |
| `protocol` | 接入协议 | 端点契约、参数表、MCP 工具签名、响应形状 | 0.98~0.99 |
| `rule` | 输出规则 | 对 AI 输出行为的硬约束（引用格式、预算纪律） | 0.96~0.97 |
| `principle` | 上下文工程 | 设计理念，解释「为什么这样做」 | 0.92~0.95 |
| `workflow` | 工作流 | 端到端分步流程，含失败兜底 | 0.92~0.97 |

分类的作用不只是给人看：`/api/context?category=rule` 让 Agent 在建立系统提示时**只取规则**，不被事实条目挤占预算。这是 [EG-401] Step 2 的实现基础。

`description` 里如果写了「必须以此为准，不得推测」这类措辞，Agent 读到后会真的遵守——分类描述本身也是提示词的一部分。

---

## entries

### 字段定义

| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| `id` | string | ✅ | 稳定标识符，格式 `EG-nnn`。发布后**永久冻结** |
| `category` | string | ✅ | 必须是 `categories[].id` 之一 |
| `title` | string | ✅ | ≤ 20 字。打分权重 5，是检索的主战场 |
| `summary` | string | ✅ | 1~2 句，40~80 字。**必须自包含**——Agent 常在只读 summary 的情况下决定是否装载 body |
| `body` | string | ✅ | 完整正文，纯文本 + `\n` 换行。不要嵌 HTML |
| `tags` | string[] | ✅ | 3~6 个，小写英文或中文关键词。打分权重 4 |
| `confidence` | number | ✅ | 0~1，见下方打分标准 |
| `tokens` | integer | ✅ | 预算装箱的依据，用统一公式计算 |
| `updated` | string | ✅ | ISO 日期 `YYYY-MM-DD` |

### ID 命名约定

本站用**分段编号**，号段本身携带分类信息：

| 号段 | 分类 | 示例 |
|---|---|---|
| `EG-0xx` | fact | EG-001 Evergreen 是什么 |
| `EG-1xx` | protocol | EG-101 端点清单与调用契约 |
| `EG-2xx` | rule | EG-201 引用与置信度规范 |
| `EG-3xx` | principle | EG-301 上下文的第一性：信噪比 |
| `EG-4xx` | workflow | EG-401 Agent 接入标准流程 |
| `EG-5xx` | fact（答疑类） | EG-501 常见误解澄清 |

号段留空位（每类 100 个），新增条目直接顺延，不需要重排。

**三条铁律**：

1. **ID 一旦发布永不复用。** 内容大改时，要么原地更新（保留 ID，改 `updated` 与 `revision`），要么发新 ID。复用旧 ID 会让历史对话里的 `[EG-201]` 指向完全不同的内容。
2. **废弃条目不删除，降 confidence。** 直接删除会让引用该 ID 的历史回答变成悬空引用。正确做法是设 `confidence: 0.10`，并在 `body` 首行写「本条目已废弃，请参见 EG-xxx」。Agent 读到 confidence 0.10 会自动加上不确定性提示。
3. **ID 前缀全站唯一。** 如果你的组织有多个站点，用不同前缀（`EG-` / `KB-` / `DOC-`），避免跨站引用混淆。

### tokens 计算

统一公式，前后端必须一致（否则预算装箱会算错）：

```
tokens = CJK字符数 × 1.0 + 其他字符数 × 0.28
```

CJK 范围：`\u3400-\u9FFF`、`\uF900-\uFAFF`、`\u3000-\u303F`、`\uFF00-\uFFEF`。

0.28 是英文在 BPE 分词下的经验均值（约 3.6 字符/token）。CJK 按 1 字 1 token 偏保守，多数模型下实际略低——**保守估算保证不超预算**，这是有意的取舍。

`tokens` 字段统计的是 `title + summary + body` 的合计，即该条目被装载时的实际成本。

---

## confidence 打分标准

confidence 不是「我有多确定这句话是真的」，而是「**这个条目在多大程度上可以不经二次核验就被直接引用**」。按下面的锚点打分：

| 分值 | 锚点 | 判据 | 示例 |
|---|---|---|---|
| **0.99** | 机器可验证 | 有自动化测试或 schema 校验保护，错了会立刻被发现 | MCP 工具签名、端点路径、JSON 字段名 |
| **0.97** | 单一权威源 | 直接来自代码、配置文件或已签署的文档，无解释空间 | 速率限制数值、协议版本号 |
| **0.95** | 多源一致的实测 | 至少三次独立测量结果一致，口径已写明 | 效果基准数据、token 节省率 |
| **0.93** | 设计决策 | 由本项目明确决定，但存在合理的替代方案 | 检索算法的权重取值、分类划分 |
| **0.90** | 行业共识 | 多方文档一致但无强规范约束 | 通用最佳实践 |
| **0.85** | 有条件成立 | 结论依赖特定前提，前提变化则失效 | 性能优化建议、容量规划 |
| **0.75** | 经验判断 | 基于实践但未系统验证 | 架构选型的定性比较 |
| **< 0.80** | **须显式提示** | Agent 必须在回答中加「该结论置信度较低（0.xx），建议二次核验」 | — |
| **0.10** | 已废弃 | 保留 ID 供历史引用，body 首行指明替代条目 | — |

**打分纪律**：

- 不要全部打 0.99。全站条目置信度趋同时，confidence 就失去了排序与提示作用，退化为常数。
- 不要凭感觉打分。每个分值都要能说出「它对应上面哪一行锚点」。
- 数字型条目（价格、限额、版本）的 confidence 应该最高，因为错了代价最大且最容易验证。
- 观点型内容**不应该进知识库**。它们的 confidence 天然低于 0.85，会持续触发不确定性提示，反而降低整体可用性。

**confidence 在检索中的作用**（很轻，这是有意的）：

```
score = rawScore × (0.85 + confidence × 0.15)
```

最多影响 ±15%。这样设计是为了避免「高置信度的泛泛条目」压过「低置信度的精准命中」。精准度应该主要由 term 匹配决定，confidence 只做同分时的微调。

---

## body 写作规范

body 是 Agent 真正引用的内容，写法直接决定回答质量。

### ✅ 推荐

**1. 结构化，用「规则 N：」「Step N」「机制：」这类前缀**

```
规则 1：凡来自 /api/context 或 /mcp 返回的断言，句末附 [EG-xxx]，多条目用 [EG-001][EG-003]。
规则 2：条目的 confidence 字段 < 0.80 时，回答中必须包含「该结论置信度较低（0.xx），建议二次核验」。
```

Agent 会**逐条**引用这种结构，而不会把整段揉成一句模糊的转述。

**2. 数字带单位与口径**

```
核心价值指标：平均检索轮次 4.2 → 1.3，token 消耗下降 68%，事实性问答准确率提升 31%。
```

不要写「显著提升」「大幅降低」。Agent 无法引用形容词，只能编一个数字——这就是幻觉的来源。

**3. 明确写出「不做什么」**

```
Evergreen 不是一个聊天机器人，也不是知识库 SaaS。它是一个协议层实现。
```

否定式定义能阻止 Agent 把站点归类到错误的范畴，这是最常见的误解来源。

**4. 失败兜底写进 workflow 条目**

```
失败兜底：任一端点 5xx 或超时 3s，降级为 GET /llms-full.txt 一次性加载全量语境；
仍失败则明确告知用户上下文不可用，不要用先验知识伪装。
```

没有兜底条款的 workflow，Agent 遇到第一个错误就会开始自由发挥。

### ❌ 禁止

| 反模式 | 为什么有害 |
|---|---|
| 嵌 HTML 标签 | Agent 会把 `<div>` 当内容读出来 |
| 用 Markdown 表格塞进 body | `\n` 与 `|` 混排，多数模型解析不稳；改用「A: 1 / B: 2」的线性写法 |
| 写「详见官网」「如上所述」 | Agent 拿不到指代对象，只能编 |
| 一条塞多个主题 | 破坏原子性，检索时整条被装载，浪费预算 |
| 复制粘贴营销文案 | 信噪比极低，形容词不承载事实 |
| 时效性表述（「目前」「最近」「今年」） | 一年后 Agent 读到还是「目前」，无法判断过期；改成绝对日期 |

### 原子性

**一条 = 一个主题。** 判断标准：如果 Agent 只需要这条的一半内容，那它就该拆成两条。

拆分的收益是预算利用率。一条 400 token 的混合条目，在 `budget=800` 时占掉一半预算却只有一半相关；拆成两条 200 token 的，装箱算法可以只装载相关的那条。

---

## 校验

用 JSON Schema 校验：

```bash
# 任意 schema 校验工具
validate context.json --schema schemas/knowledge.schema.json
```

Schema 强制的约束：
- `id` 匹配 `^EG-[0-9]{3}$`，且全站唯一
- `confidence` ∈ [0, 1]
- `tokens` 为正整数
- `updated` 匹配 `^\d{4}-\d{2}-\d{2}$`
- `category` 必须出现在 `categories[].id` 中
- `tags` 至少 1 个，最多 8 个
- `title`、`summary`、`body` 非空

发布前的额外人工检查：

```
☐ 每条 summary 单独拿出来读，是否自包含？
☐ 每条 body 里的数字，是否都能在 metrics.json 或代码里找到出处？
☐ confidence 分布是否有梯度，还是全挤在 0.95 以上？
☐ 是否有两个条目的 tags 高度重合（说明该合并）？
☐ 是否有 topic 明显该命中却搜不到的条目（说明 title/tags 写得不好）？
```

最后一项用 `/api/context?topic=<该条目的核心词>&budget=800` 实测——如果目标条目没排到第一，就是 title 或 tags 需要改。
