本文基于 Anthropic 数据团队在 2026 年 6 月发布的官方工程实践,系统拆解如何用 Claude 搭建企业级自助式数据分析系统。核心结论可能会让不少人意外:分析类 Agent 的准确率瓶颈不在代码生成,而在语义消歧——也就是怎么把用户的自然语言问题精准对应到数据模型里的正确字段和口径。Anthropic 用一套四层架构(数据基础 → 真实来源 → 技能系统 → 验证体系),把 Claude 的分析准确率从 21% 一路拉到 95% 以上,目前 95% 的业务查询已实现自动化。这篇文章逐层拆解这套方法论,末尾附了可以直接参考的技能文件模板和离线评估框架。


一、自助式数据分析的工程困局

数据团队基本上都撞过同一堵墙:要么把数据模型用宽表和冗余设计摊开给业务方,结果定义打架、指标混乱;要么给每个团队划一块自留地,结果仪表盘泛滥、长尾问题没人接。

大语言模型给了第三条路。最直观的想法——把 Claude 指向数仓,让它替人查数。这个想法的前几步确实让人眼前一亮,再走几步就开始让人心里没底:

解放感消退得很快,取而代之的是隐隐的恐惧——你突然意识到,这套设置把用户和底层基础设施、文档、专家经验全切断了。以前用户好歹会跑来问一句"这个表靠谱吗",现在他们拿到一个看着合理的数字就满意了,而那个数字可能来自错的表、错的字段、或者已经过期的定义。

Anthropic 数据团队大量实践之后得出了一个判断:使用Agent分析的难点不是写SQL,是消除歧义。只要把自然语言问题精确映射到数据模型中的正确实体,SQL本身是简单的。


二、为什么分析 Agent 比代码 Agent 更难?

LLM 的生成能力是一把双刃剑。在开放式解空间里发挥创造力,文档和测试还能充当护栏;但在分析场景下,一个问题通常只有一个正确答案、对应唯一一个正确来源,而且没有任何确定性办法来验证答案对不对。

flowchart TB A["🧠 代码 Agent"] --> B["开放式解空间<br/>多种实现都正确"] A --> C["护栏机制<br/>单元测试 / 类型系统 / Lint"] D["📊 分析 Agent"] --> E["封闭式答案<br/>只有一个正确来源"] D --> F["无确定性验证<br/>数字'看起来'合理 ≠ 正确"] B --> G["✅ 编码 Agent 天然容错"] E --> H["⚠️ 分析 Agent 对准确性要求极高"] style A fill:#FAFAD2,color:#000000 style D fill:#FAFAD2,color:#000000 style G fill:#98FB98,color:#000000 style H fill:#F5DEB3,color:#000000

Anthropic 把导致绝大多数出错的情况归纳成三类:

失败模式 怎么回事 典型例子
概念-实体歧义 数据模型里几百个字段,Agent 在几百个候选项中选不对 "活跃用户"——什么样的行为算"活跃"?含不含欺诈用户?回溯窗口多久?
数据过时 数据源、业务定义、Schema 一直在变,Agent 用的是旧知识 上个月"营收"还是 revenue_v2,这个月已经是 revenue_v3
检索失败 正确信息就在数据模型或者文档里,且标注得清清楚楚,但搜索空间太大,Agent 就是找不到 某个维表里有精确定义,被埋在海量表和字段里

这三种失败里,检索失败是最常被误判的。Anthropic 做过一次消融实验:直接给 Agent 用 grep 访问成千上万条历史 SQL(仪表盘查询、Notebook 分析、ETL 脚本),结果准确率变化不到 1 个百分点。信息确实在那儿,Agent 也确实看到了,但它不知道该怎么用。瓶颈不在"能拿到什么信息",而在于"信息怎样被结构化组织"。


三、四层代理分析栈架构

Anthropic 用来解决上面三个问题的是一套分层设计,每一层主攻一种失败模式:

flowchart TB subgraph layer1["Layer 1: 数据基础 Data Foundations"] direction LR L1A["规范数据集<br/>Canonical Datasets"] L1B["CI 强制执行<br/>Enforcement"] L1C["同仓管理<br/>Colocation"] L1D["元数据治理<br/>Metadata"] end subgraph layer2["Layer 2: 可信来源 Sources of Truth"] direction LR L2A["语义层<br/>Semantic Layer"] L2B["血缘与转换图<br/>Lineage"] L2C["查询语料库<br/>Query Corpus"] L2D["业务上下文<br/>Business Context"] end subgraph layer3["Layer 3: 技能系统 Skills"] direction LR L3A["知识技能<br/>Knowledge Skill"] L3B["Unbook 技能<br/>Process Skill"] L3C["参考文档<br/>Reference Docs"] end subgraph layer4["Layer 4: 验证体系 Validation"] direction LR L4A["离线评估<br/>Offline Evals"] L4B["消融实验<br/>Ablation"] L4C["线上验证<br/>Online Checks"] L4D["纠正收集<br/>Correction Harvest"] end layer1 --> layer2 layer2 --> layer3 layer3 --> layer4 L1A -.- attack1["🎯 对抗: 实体歧义"] L2A -.- attack1 L3A -.- attack2["🎯 对抗: 检索失败"] L1B -.- attack3["🎯 对抗: 数据过时"] L4C -.- attack3

3.1 Layer 1:数据基础

这是最底下的一层,也是最绕不开的一层。

创建规范数据集。 这是最常见的出错源头。如果"营收"在全公司只有一个数据集而不是四十个候选表,问题在 Agent 开始搜索之前就消失了大半。做法很直接:设计一小批规范化、唯一来源的事实数据模型,标注好所有权、就绪后果断废弃那些近似重复的表。

同仓管理。 几乎所有数据代码(建模、语义层、参考文档、标准定义)放在同一个仓库里,CI 检查跨层完整性。一次模型变更如果会破坏下游仪表盘或让已归档的指标失效,CI 直接标记出来,修复跟变更在同一个 PR 里完成。

把元数据当成一等产品对待。 代码库因为 README、类型签名、文档字符串而可读,数仓也可以做到同样可读——前提是列和表的描述、粒度文档、有效值范围、所有权、模型分层都用跟数据处理逻辑同等的标准来维护。

通过工具链强制执行。 规范模型和元数据、业务文档定义要靠三层机制守住——Agent 在工具层面被路由优先命中规范层;绕过规范层的代码变更在 CI 评审时直接被拒;下游团队必须基于规范层构建,否则需要书面说明理由。

flowchart LR subgraph repo["单一数据仓库 Monorepo"] direction TB A["📐 建模代码<br/>models"] B["🏷️ 元数据<br/>Metadata"] C["📖 参考文档<br/>Reference docs"] D["📊 业务标准定义<br/>Business Standard specs"] end A -->|"CI: 变更触发检查"| CI{"CI 检查"} B --> CI C --> CI D --> CI CI -->|"✅ 通过"| merge["合并到主分支"] CI -->|"❌ 指标损坏"| reject["阻止合并<br/>要求同步修复"] style repo fill:#1e293b,color:#eee,stroke:#3b82f6 style CI fill:#f59e0b,color:#000 style merge fill:#22c55e,color:#fff style reject fill:#FAFAD2,color:#FFFF66

3.2 Layer 2:可信来源

如果数据基础是数仓本身,可信来源就是 Agent 在数仓里导航时参考的地图。Anthropic 按信任度从高到低定义了四层来源:

(1) 语义层——最高优先级,强制性首选

已维护的指标和维度定义。用户问题能映射到已定义指标时,Agent 调函数拿到一个唯一数字——需要跟其他任何地方产出的数值完全相同。Agent会被技能强制要求先走语义层。

一个花钱买来的教训:不要用 LLM 自动生成语义层。Anthropic 试过让 LLM 从原始表和查询日志自动产出指标定义,结果看起来很漂亮,实际上把本来要消除的歧义又编码回去了,在评估集上纯属负收益。正确姿势:让人来定义,让 Claude 来干活(生成文档)。

(2) 血缘与转换图

语义层无法回答某个问题时,血缘和表排名(按被引用次数)让 Agent 可以推理出:哪些上游模型撑起了这个指标?哪些模型被已经废弃?哪些模型共享了维度?这样就把"我不知道这个指标"变成了"我知道从哪个模型去聚合"。

(3) 查询语料库

直观上这一层的价值应该很高——因为这是历史上所有已被正确回答过的问题的记录。但实际结果是,给 Agent 原始检索权限去访问几千条历史 SQL,准确率几乎没有变化。非结构化检索没办法把新问题对应到正确的先例。正确的用法是把语料库蒸馏成按领域组织的结构化参考文档和可复用分析模板,比如将解决方案整理为指标口径、过滤条件、结果粒度、可复用标准化分析逻辑:。一句话:把查询历史当成策展的原材料进行加工,别当成让 Agent 直接读的原始来源。

(4) 业务上下文

大多数团队会跳过的一层,也是 Anthropic 最晚才重视起来的一层。Agent 不理解你的业务,它回答的就是你字面上问的,不是你实际想知道的。它不可能知道"Q2 发布"指的是一个具体产品还是一个时间;不可能知道两个团队对同一个术语的理解可能不同;更不可能知道这个问题被提出来因为周四董事会要用数据。Anthropic 的做法是给 Agent 接入公司的知识图谱——已索引的文档、路线图、决策记录、组织架构——让它能理解上下文引用、问出更好更明确的问题。

3.3 Layer 3:技能系统

如果可信来源是 Agent 的声明性知识(某个指标是什么意思),技能就是它的程序性知识:按什么顺序查哪些来源、碰到歧义数据怎么处理、一次完整分析应该长什么样。

sequenceDiagram participant User as 👤 业务用户 participant Agent as 🤖 Claude Agent participant Skill as 📋 知识技能 (Router) participant Doc as 📖 领域参考文档 participant Semantic as 🏷️ 语义层 participant Run as 📊 执行引擎 participant Review as 🔍 对抗审查子代理 User->>Agent: "上周北美区的营收趋势如何?" Agent->>Skill: 加载知识技能 Skill->>Semantic: 首先查询语义层<br/>("revenue" "north_america" "weekly") alt 语义层命中 Semantic-->>Agent: 返回指标 + 维度过滤 Agent->>Run: 执行查询 Run-->>Agent: 结果 else 语义层未覆盖 Semantic-->>Agent: 未找到匹配 Agent->>Doc: 加载领域参考文档<br/>(路由到具体表和Join) Doc-->>Agent: 表定义 + Gotchas Agent->>Run: 基于参考文档<br/>编写并执行 SQL Run-->>Agent: 结果 end Agent->>Review: 发起对抗审查<br/>(强制步骤) Review-->>Agent: 审查反馈 + 修正建议 alt 审查发现问题 Agent->>Agent: 修正并重新审查 end Agent->>User: 最终答案 + 来源页脚<br/>(语义层 | 管控表 | 原始表)

Anthropic 实际采用的模式叫成对技能(Pairwise Skills):

知识技能(Knowledge Skill)

一个轻量级顶层路由器,按需加载领域细节。它的逻辑很简单:

"先查语义层。如果没有覆盖,加载这 30 个领域参考文件,里面写了相关表、列、Join 关系和 Gotchas。"

这个路由器就是 Anthropic 用来对付检索失败的工具——不让 Agent 在百万字段的汪洋里搜索,而是在几十个策展文件的小池塘里定位,然后再写查询。

Unbook 技能(Process Skill)

把资深分析师的工作流固化下来:分析问题 → 查找来源(走知识技能)→ 执行查询 → 把结果丢给对抗性审查子代理校验。它同时还打包了十几个可复用的分析模式(留存曲线、速率分解、漏斗分析),常见请求不用每次都从零开始。

参考文档该长什么样

Anthropic 公开了参考文档的骨架模板。关键的思路是:为 LLM 检索而编写,不是为人阅读而编写:

# [领域] 表

## 快速参考
### 业务上下文 — [用简单语言描述这个领域的含义]
### 实体粒度 — [一行数据代表什么]
### 标准清洗过滤器 — [该领域每个查询都要应用的过滤器]

## 维度
- [关键维度如何编码,同一概念在不同表中如何命名]

## 关键表
### [table_name]
- **粒度**: [...] · **范围/排除**: [...]
- **使用**: [何时用、何时不用、Join 键、必需过滤器]

## Gotchas
- [资深分析师会警告你的那些出错模式]

## 最佳实践 / 常见查询模式
- [默认选择、标准分组、查询形式本身就是难点的案例]

技能维护不能靠自觉

Anthropic 观察到,不主动维护的话,技能文档的准确率几周内就会从 95% 掉到 65%。他们的解法是技能 Markdown 文件和转换模型同仓——改模型的 PR 就是改文档的同一个 PR。Code Review 钩子会标记所有没同步修改技能文件的数据模型变更。现在大约 90% 的数据模型 PR 在同一个 diff 里带着技能变更。

3.4 Layer 4:验证体系

最后一层回答的核心问题是:还有哪种失败在漏网?

离线评估

数据团队常见的一个坑是花大力气搭了分析环境,但没有任何流程测过 Agent 的准确率。Anthropic 部署了两类离线评估:

  1. 通用评估——Claude 自动生成、人工验证,覆盖最常见的业务问题
  2. 长尾评估——给 Claude 喂业务上下文(路线图、表文档),让它生成覆盖其他区域的问题

几个值得注意的实践经验:

  • 把 Ground Truth 锚定住,防止漂移:评估固定在快照日期、基于稳定维表编写、或者让评分器判定 Agent 的查询本身而非返回的具体数字
  • 把评估接入 CI:PR请求只触发依赖链路的重新评估,不进行完整的评估。
  • 把结果当遥测数据存:每次跑完落地到数仓表,带技能版本、git SHA、模型 ID、断言级通过/失败、token 数和耗时
  • 严守领域发布门控:领域负责人的评估测试没过阈值(Anthropic 一开始用 90%)之前,不能向用户宣布 Agent 可用
  • 离线评估准确率该奔着 100% 去:这不意味着线上不出错,但意味着你评估盖到的范围内没有明显盲区

消融实验

Anthropic 做每一个结构性决策(暴露哪些来源、子代理值不值那个延迟开销、要不要合并技能),都是把评估集固定住,只改一个变量,对比通过率。最重要的一次发现是一个负面结果:

给 Agent 直接 grep 访问几千条历史 SQL 之后,80% 的答错问题,答案其实就在语料库里,Agent 看到了但没用。准确率变化不到 1 个百分点。这一个实验直接改写了好几个月的路线图——它告诉团队瓶颈不在对历史成果的访问,而在结构——能不能把问题映射到正确实体。

线上验证

  • 对抗性审查:用一个 Claude skill去挑战最终答案的所有底层假设,在评估集里多拿了 6 个百分点的准确率。代价是 token 涨了 32%,延迟多了 72%。
  • 数据来源页脚:每个agent的输出都标注来源层级(语义层 / 管控表 / 原始表)、数据新鲜度和模型负责人——它不会让答案变正确,但能让看的人判断有多可信。
  • 被动监控:持续追踪两个信号——走语义层解析的查询占比越高越好,以及带纠正性语言的响应占比越低越好。
  • 主动纠正收集:一个定时代理每隔几小时扫一遍工作群里的纠正信息,自动起草参考文档的修复建议,并提PR给领域负责人。修复路径故意做得极其简单——编辑 Markdown、合并、自动同步到所有终端。

四、从零起步怎么搞

如果从零开始,Anthropic 的建议听起来不多:少量规范数据集 + 几十条离线评估 + 一个轻量级的知识技能,大部分收益基本就到手了。后面那些东西都是这些基础搭好之后逐步加上去的。

在动手之前,最好先跟团队把几个原则性问题对清楚:

问题 为什么重要
正确答案今天有多重要 vs 未来相比如何? 模型进步飞快,今天为了补模型短板搭的很多基础设施,模型一升级可能就多余了
业务的复杂度预期怎么变? 数据量不大、消费者也少、数据模型大概率长期简单的话,有些流程可能纯属过度设计
目标用户技术水平怎么样? 面向数据科学家可以接受更高错误率;面向完全不懂数据模型的人需要强得多的保障
愿意为更高准确率付多少成本和延迟? 对抗性验证效果显著,但价格不便宜,延迟也更高
对访问控制和内部数据隐私能接受多少? Agent 拿到的上下文越多表现越好,但这和大多数公司的治理姿态天然冲突——这直接决定了你是做一个通用 Agent 还是一堆受限 Agent

五、技能系统实现参考

下面是一份面向数据仓库 Agent 的技能模板,可作为落地实现时的参考:

---
name: [warehouse-skill]
version: [x.y.z]
description: "当用户要求就任何业务分析查询问题查询公司的数据仓库时——则调用此技能。不要为工程开发或无数据仓库组件的问题调用。"
---

# [Warehouse] 技能说明

## 描述
安全有效地查询[warehouse]的单一真实来源。
被其他技能引用,用于查询执行指导。
扮演数据分析师,提供战略性见解和数据驱动的建议,但在此过程中会寻求指导。
**超出范围的决定**:遇到超出数据分析范畴的业务决策类问题(如产品方向、定价、功能取舍等),Claude 技能仅能输出客观数据,不能自行给出判断、立场、解决方案或修改方案代码。

## 执行查询
优先级:
1. **优先使用平台托管连接**(如果可用):配套专用查询 / 元数据工具
2. **无托管连接则走本地 CLI 工具**(如果已安装):限定预设主项目 + 备用项目,限制可访问数据范围
3. **两者都不可用**——要求用户认证,然后停止

---

# 语义层(必需的第一步)
受管控的语义层是每个数据问题的**强制默认路径**——输出要与bi看板的数值保持一致,并且语义层已经吧包含了联接/粒度/过滤器等内容。参考文档的原始 SQL 是**后备方案**,仅在语义层路径被证明无法覆盖需求时使用。

## 必需工作流
1. **加载**——[如何在每个运行时加载语义层,含回退方案]
2. **发现**——通过关键字搜索指标/维度;**始终检查过滤器**(使用命名的规范全局过滤器——因为这些手工编写 WHERE 子句是导致错误答案的主要模式)
3. **编译 + 运行**—— 构建规范的sql生成模版 → 编译为 SQL → 执行
4. **后备**——仅当发现阶段找不到相关指标或编译失败时 → 通过 `references/*.md` 让agent写原始 SQL(见下面第三部分)

> **不要提早放弃。** 不要基于以下理由回退到原始 SQL:
> - “[自定义日期过滤]” → [优先考虑使用语义层的维度定义]
> - “[需要join]” → [指标层已封装了join关系]
> - [agent用来跳过语义层的另外 3-4 种可能的情况,预先在skill里覆盖反驳理由]

### 日期窗口和时区——查询前决定
- **截止日期 vs 过去 N 天**:[每种情况的惯例]
- **“上周/上月”** → 上一个*完整*的日历周/月,而非过去 7/30 天
- **默认时区**:[TZ];[某些报告汇总的例外情况]
- **新鲜度滞后**:[某些]表延迟落盘——以 MAX(date) 为锚点,而非“昨天”

---

# 第一部分:须知(每次请求前首先阅读)

## 🚀 快速启动工作流
1. **首先检查红线**:[受限/PII 请求、门控领域、需要额外验证的高风险请求]
2. **超出范围——向上升级,不要猜测**:[访问请求、流水线排障、过期仪表盘、根因断言、产品/定价建议] → 重定向给管理团队,不要自行推断回答
3. **明确请求**:时间段、需求口径、其支撑的业务决策
4. **检查现有仪表盘**:[按领域的仪表盘目录]
5. **识别数据源**:[优先选择受管控/聚合表]
6. **执行分析**:[必需的过滤器 + 对抗性审查]
7. **交付见解**:必须清晰说明数据来源、筛选规则、计算口径、时间窗口、所用指标 / 数据表,让结论可复现、可校验,避免无依据的数字。数据直接呈现的事实,不带主观判断(例:Q2 付费转化率环比下降 3%);不把猜测包装成既定事实,降低误导风险,方便业务方区分 “数据是什么” 和 “我们怎么看”。

## 🏢 业务上下文

### 实体消歧(务必澄清)
- **“[业务术语 A]”可能对应着**:[entity 1] 或 [entity 2]两张表——应该始终确认使用哪一个事实表
- **“[业务术语 B]”可能对应着**:[entity 1] → [entity 2] → [entity 3](一对多链),应该适中确认使用哪个事实表
- **“用户数这个术语”**:可能使用userid 或者 设备id标识,userid唯一对应一个自然人,但是一个userid可能有多个设备,使用不同的维度计算的用户数会有差异,应该标记哪个标识符能给出准确数据,哪些会使数据膨胀

### 业务术语
- [当前产品名称 vs 已弃用的别名(历史数据保存的仍然是废弃的别名)—— 用新名称输出,用旧名称过滤历史]
- [关键内部缩略词]
- **[核心指标]**:核心指标的口径,比如默认时间窗口、指标的筛选、关联关系、计算口径 指向应该是明确的
- **不熟悉的术语——搜索内部语料库,不要猜测**

### 数据完整性要求 ⚠️
- **绝不**:编造数据/列;做出超出数据所示范围的推测性断言
- **始终**:计算比率、转化率等时做除零防护,避免报错与虚假异常数据;
  区分客观事实(“数据显示 X”)和主观推断(“这意味着 Y”);
  说明数据口径、时间范围、样本缺陷、数据新鲜度等约束,防止使用者过度采信结论

---

# 第二部分:做法(执行过程中遵循)

## 🔧 技术执行指南
- [Managed-connection 工具和 CLI 调用细节]
规定 Agent 对接数据仓库的正规通道,优先走统一托管连接工具,无工具时再用 CLI 备用方案,标准化数据查询的登录、连接、执行流程,避免随意直连数据库带来的权限、一致性风险。
- **PII 保护**:对于受限数据,返回 SQL 供用户自行运行——不要返回结果

## 📊 分析最佳实践指南
1. 查询前先澄清需求
解决需求和数据模型不一一对应的核心问题,提前确认统计口径、时间范围、过滤条件、维度,避免 AI 自行脑补业务含义。
2. 展示你的工作(过滤器、包含/排除、新鲜度)
主动写出过滤条件、数据包含 / 排除范围、数据最新时间,解决数据陈旧、口径不透明问题,方便校验。
3. 明确分母
针对转化率、渗透率等比率指标,界定分母是总用户、活跃用户还是付费用户,防止比率类指标口径混乱。
4. 考虑样本偏差
识别数据断层、缺失人群、特殊异常样本,避免片面数据得出误导结论。
5. 业务价值解读
不只输出数字,关联业务场景、给出决策建议,让非技术人员看懂数据意义。
6. **对抗性 SQL 审查(强制)**——每次查询在给出最终答案前,生成 [sql-reviewer] 子代理进行审查;阻塞性发现必须修复并重新审查;不得自我认证
7. **附带来源页脚的汇报**——每个答案结尾包含页脚:
> **来源:** [语义层 | 管控表 | 原始探索] · **置信度:** [层级] · **已审查:** [审查者 ✓, 第 N 轮] · **新鲜度:** [数据中的最大日期] · **指标/表的拥有者:** [owning team]

---

# 第三部分:数据参考与资源

## 📚 知识库导航
### [Domain A] → `references/[domain_a].md`
- **用于**:[问题类型]
- **关键表**:[...]
- **仪表盘**:`references/[domain_a]_dashboards.json`
### [Domain B] → `references/[domain_b].md`
- **用于**:[...]
[... 每个业务领域一个条目——总共几十个 ...]

## ⚠️ 故障排查指南
### 当信息缺失时
- [缺失的表 / 访问被拒绝 / 过时的文档 / 未知的枚举值 → 该怎么办]
覆盖四类常见报错:表不存在、无数据访问权限、元数据文档过期、枚举值无定义;给出标准化处理流程,避免 AI 自行编造字段 / 表。
### 字段命名陷阱
- 使用 `[field_x_v2]` 而非 `[field_x]`
版本字段区分:强制使用更新后的 v2 字段,废弃旧字段,防止数据口径过时;
- [两个名称相似的表以不同粒度报告同一指标——该用哪个]
同指标多粒度表区分:明确不同汇总粒度表的选用规则,避免统计口径错乱;
- [两个可能的来源中哪一个是核心指标的规范来源]
多数据源优先级判定:规定核心指标只能采用唯一权威数据源,消除多表冲突。
- [… 十几个来之不易的一行提示 …]

六、总结

实践下来,Anthropic 的这条路径讲清楚了一件事:用 Claude 搭自助式分析系统,你别把心思花在"让 AI 写 SQL"上。真正要做的是把混乱的数据定义收敛成唯一的可信答案,让 Agent 能稳定找到它,然后在任何一层出问题时第一时间知道。

三个失败模式,三道防线:

  • 实体歧义,靠约束机制——规范数据集、语义层、CI 强制执行
  • 检索失败,靠结构化路由——不是开放搜索,是知识技能加上专门写给 LLM 看的参考文档
  • 数据过时,靠同仓 + CI + 主动纠正收集——模型和文档在同一个 PR 里变

起步不用一步到位。少量规范数据集、几十条评估、一份轻量级技能文件,就够了。剩下的对抗审查、消融实验、线上监控,是在前面每一层接近天花板之后,继续往上堆收益的东西。