每日 AI 实战案例

毛利从 -50% 到转正:一家 156 亿美元估值的法律 AI 公司,为什么主动放弃闭源前沿模型

2026-09-22
高级企业应用
约 5 个月(含 8 周集中迁移期)
使用工具:
Kimi K3(开放权重)vLLMClaude Code内部评测平台LangfusePrometheus + GrafanaLabel Studio
AI实战模型迁移开放权重单位经济学Kimi K3后训练模型路由评测集法律AI成本控制

案例摘要

2026 年 9 月,Bloomberg 披露了一条被低估的产业新闻:法律 AI 公司 Harvey(估值 156 亿美元)把主力负载从闭源前沿模型迁到了自研模型——一个基于 Moonshot Kimi K3 开放权重做后训练的内部模型。迁移的驱动力不是能力,是算术:按用量计费模式下 token 消耗涨了 20 倍,毛利从约 +50% 一路跌到约 -50%;迁移后毛利转正。Abridge、Decagon、Ramp 被报道在走同一条路,Sequoia 与 General Catalyst 在背后推。这是企业级 AI 公司第一次成规模地「离开前沿实验室」,而触发这件事的是单位经济学,不是跑分。本文把这次迁移拆成可复现的工程动作:任务分层与模型路由、评测集构建、后训练数据从哪来、灰度切流与回归监控、以及 14 个真实会踩的坑。附每一步的 Prompt 模板与效果数据表。

毛利从 -50% 到转正

一、背景:这不是能力问题,是账单问题

1.1 一条容易被误读的新闻

2026 年 9 月,Bloomberg 报道了 Harvey 的模型迁移。标题党版本会是「法律 AI 巨头抛弃 GPT 和 Claude」,但真实原因朴素得多:

按用量计费模式下 token 消耗涨了约 20 倍,毛利从约 +50% 跌到约 -50%。 迁移到自研模型后,毛利转正。

注意这个数字关系:营收在涨,用户数在涨,产品质量没变差——但毛利从正五十变成负五十。原因只有一个:单用户成本涨得比单用户收入快。

1.2 为什么 AI 应用公司特别容易撞上这堵墙

传统 SaaS 的成本曲线:

用户数 ↑  →  边际成本 ≈ 0(多一个用户只是多一份数据)

AI 应用的成本曲线:

用户数 ↑  →  用户用得越多 → token 消耗 ↑↑
        →  且重度用户往往是付费意愿最强的那批
        →  成本与收入同向增长,且成本弹性更大

更糟的是三个放大器:

放大器机制影响
能力越强,用得越多模型变强 → 用户敢交给它更长的任务 → token 数非线性上涨每轮升级都推高成本
Agent 化单轮问答 → 多轮自主循环 → 单次请求触发几十次模型调用token 消耗 10–100 倍
上下文膨胀为了效果好,不停往里塞文档、历史、工具输出输入成本占比越来越高

Harvey 的场景是这三者的叠加:法律文档天然长(一份合同几百页)、任务天然多步(尽职调查、条款比对、风险标记)、质量容错极低(不能编)。

1.3 为什么是 2026 年才发生

三件事同时成熟了:

条件20242026
开放权重模型能力明显落后前沿 1–2 代Kimi K3(2.8T 参数、1M 上下文)、Step 5 Preview(600B MoE)等逼近前沿
后训练工程化需要专门团队与大量试错LoRA / SFT / DPO 工具链成熟,8 周可跑完一轮
自托管推理成本部署门槛高,GPU 贵vLLM / SGLang 成熟,规模化后单 token 成本可降到 API 价的 1/5–1/10

关键变化是第三个。开放权重模型一直存在,但「自己跑」的成本以前降不下来。现在能降了,于是「自建」第一次在经济上算得过来。

1.4 本文的定位

这不是一篇 Harvey 的内部复盘(我们拿不到内部数据)。这是一篇把公开信息拆成可执行动作的迁移指南:如果你的 AI 应用也撞上了单位经济学这堵墙,该按什么顺序做什么。

所有数字分两类:

  • 标注 [公开] 的来自公开报道
  • 标注 [推演] 的是基于同类迁移工程的合理估算,用于说明量级关系,不是承诺

二、工具分工:谁负责什么

2.1 迁移工程的角色表

角色工具负责什么不负责什么
任务分层分析Langfuse + 自写脚本把线上流量按任务类型切开,算出每类的 token 与成本不做模型决策
评测集构建Label Studio + 内部法务团队构建领域金标集(含 rubric)不写代码
基线模型选型vLLM + 开放权重模型跑批量推理,出客观指标不做最终决策(要人工看样)
后训练LLaMA-Factory / 自研训练管线SFT + DPO不定义什么是「好」(由 rubric 定义)
推理服务vLLM + Triton部署、批处理、量化不管模型质量
灰度与监控自研路由层 + Prometheus分流、A/B、成本与质量双监控不做模型训练
回归拦截CI + 评测集自动跑每次模型更新前跑一遍金标集不决定上线
代码层改造Claude Code + 人工 review提示词适配、路由改造不改评测标准

2.2 一个关键原则:评测标准不交给 AI

本案例里最重要的分工约定:

「什么算好」    →  人定(法务专家写 rubric)
「做得好不好」  →  机器跑(自动评测)
「哪里不好」    →  AI 辅助分析(读 bad case 归类)
「怎么改」      →  人决定,AI 执行

AI 可以跑评测、可以做分析、可以写补丁,但不能定义「什么算改善」。 这条线一旦越过,就会出现「评测分数涨了但律师说输出不能用」的经典事故。


三、策略设计:不是全量替换,是分层

3.1 核心误判:以为要换掉前沿模型

最直觉(也最危险)的想法是「把 GPT/Claude 全换成自研模型」。这会导致:

  • 最难的 5% 任务质量崩塌 → 用户流失
  • 而那 5% 恰恰是付费意愿最强的场景

正确做法是分层路由。先把线上的真实任务按「难度 × 频次 × 容错度」切开。

3.2 任务分层矩阵

层级任务类型频次占比单次 token容错度用什么模型
L0格式转换、字段抽取、摘要、分类、检索重排~55%2–8K中自研小模型 / 规则
L1条款比对、风险点标注、模板填充~30%10–40K低自研主力模型
L2尽职调查、多文档交叉推理、争议分析~12%40–150K极低自研主力模型 + 前沿模型交叉校验
L3全新问题、高风险意见、客户定制~3%不定极低前沿模型保留

算一下这笔账:

成本占比(迁移前,全部走前沿模型):
  L0  55% 流量 ×  5K token  = 275K 单位
  L1  30% 流量 × 25K token  = 750K 单位
  L2  12% 流量 × 90K token  = 1080K 单位
  L3   3% 流量 × 60K token  =  180K 单位
  -----------------------------------
  合计                        2285K 单位
  L0+L1 占比 = (275+750)/2285 = 44.9%
  L0+L1+L2 占比 = 92.1%

结论:把 L0 和 L1 迁走,就能覆盖约 45% 的成本;把 L2 也迁走(带校验),覆盖 92%。剩下 3% 继续用前沿模型,成本可以忽略。

这就是为什么「分层」比「全换」重要:它让你能用最小的质量风险,覆盖最大的成本面。

3.3 三级迁移路线图

Phase 1(第 1-2 周):评测集先行
  ├─ 建领域金标集(每类任务 ≥ 200 条)
  ├─ 定义 rubric(人工评分标准)
  └─ 建立「当前前沿模型」的质量基线(这是唯一参照系)

Phase 2(第 3-4 周):选型与非后训练基线
  ├─ 3-5 个候选开放权重模型跑同一评测集
  ├─ 客观指标 + 人工盲评
  └─ 选出基线模型

Phase 3(第 5-8 周):后训练
  ├─ 数据构建(领域语料 + 真实 bad case + 专家修正)
  ├─ SFT → DPO
  └─ 每轮迭代必跑金标集

Phase 4(第 9-10 周):灰度
  ├─ L0 灰度 5% → 50% → 100%
  ├─ L1 灰度
  └─ L2 双跑交叉校验

Phase 5(持续):成本与质量双监控

Phase 1 不能省。没有基线评测集,你在 Phase 3 完全无法判断「这个模型是不是变好了」,只能靠感觉——而感觉在 8 周里会漂移。


四、实施步骤

4.1 Step 1:把线上流量切开(第 1 周)

目标:知道钱到底花在哪类任务上。

做法:从 Langfuse / 自建 trace 里导出最近 30 天的请求,按任务类型聚合。

# analyze_traffic.py
import json
from collections import defaultdict

buckets = defaultdict(lambda: {"n": 0, "tok_in": 0, "tok_out": 0, "cost": 0.0})

with open("traces_30d.jsonl") as f:
    for line in f:
        r = json.loads(line)
        t = r.get("task_type", "unknown")
        b = buckets[t]
        b["n"] += 1
        b["tok_in"] += r["usage"]["input_tokens"]
        b["tok_out"] += r["usage"]["output_tokens"]
        b["cost"] += r["usage"].get("cost_usd", 0.0)

total_cost = sum(b["cost"] for b in buckets.values())
rows = sorted(buckets.items(), key=lambda kv: -kv[1]["cost"])

print(f"{'任务类型':<28}{'次数':>8}{'平均tok':>10}{'总成本$':>12}{'占比':>8}")
for t, b in rows:
    avg = (b["tok_in"] + b["tok_out"]) / max(b["n"], 1)
    print(f"{t:<28}{b['n']:>8}{avg:>10.0f}{b['cost']:>12.2f}{b['cost']/total_cost:>8.1%}")

输出样例(脱敏):

任务类型                        次数   平均tok    总成本$     占比
contract_clause_extract       184203     4,120   38,204    24.8%
doc_summarization              96211     6,880   25,910    16.8%
due_diligence_review           12874    92,400   24,180    15.7%
risk_flag_annotation           72330    21,300   21,690    14.1%
clause_comparison              41902    28,900   18,040    11.7%
legal_research_qa              63118    12,600   13,270     8.6%
custom_opinion_draft            2144    68,900    6,140     4.0%
other                          15028     9,100    6,690     4.3%
----------------------------------------------------------------
合计                                                       100%

这张表一出来,优先级就清楚了:前四类占 71.4%,其中 contract_clause_extract 和 doc_summarization 是典型的 L0 任务——迁移风险最低、收益最大。

4.2 Step 2:构建领域金标集(第 1-2 周)

这是整个工程最贵、最不可替代的一步。

4.2.1 金标集的构成

子集条数来源用途
主评测集每类任务 200–300 条真实脱敏请求 + 专家构造迭代期打分
盲评集300 条主集中随机抽样人工盲评(防过拟合)
回归集100 条历史 bad case每次上线前必跑
红队集100 条专家构造的对抗样本安全与幻觉检查

总规模约 1200–1500 条。听起来不多,但每条都需要领域专家标注,实际工作量约 3 人 × 2 周。

4.2.2 Rubric 怎么写(关键)

评分标准必须可判定,不能是「质量好」这种。

contract_clause_extract 的 rubric 示例:

task: contract_clause_extract
dimensions:
  - name: 条款完整性
    weight: 0.35
    levels:
      3: 目标条款全部抽到,无遗漏
      2: 漏 1 条次要条款
      1: 漏 1 条主要条款
      0: 漏 2 条以上或抽错主体
  - name: 字段准确性
    weight: 0.30
    levels:
      3: 所有字段值正确,引用位置准确
      2: 1 个字段值有误但不影响理解
      1: 引用位置(页码/条款号)错误
      0: 字段值错误且影响法律判断
  - name: 无幻觉
    weight: 0.25
    levels:
      3: 无任何合同外内容
      1: 出现轻微推断但已标注
      0: 出现合同中不存在的内容(一票否决)
  - name: 格式合规
    weight: 0.10
    levels:
      3: 完全符合输出 schema
      1: 部分符合
      0: 无法解析

gates:
  - 无幻觉维度得 0 → 总分直接判 0
  - 总分 < 2.4 → 判为不可用

「一票否决」机制很重要。法律场景里,一条幻觉的代价远大于十条遗漏。加权平均会把它稀释掉,门控不会。

4.2.3 用 AI 辅助生成,但人工终审

你是一个法律评测集构建助手。

## 任务
为任务类型 {{task_type}} 生成 {{n}} 条评测样本。

## 输入材料
- 真实脱敏请求样本:{{samples}}
- 该任务的 rubric:{{rubric}}

## 要求
1. 每条样本包含:输入文档片段、期望输出、该条要考察的维度
2. 覆盖分布:
   - 40% 常规案例(模型应该稳过)
   - 30% 边界案例(容易出错的写法/结构)
   - 20% 长尾案例(罕见条款、特殊 jurisdiction)
   - 10% 对抗案例(诱导幻觉、上下文缺失、自相矛盾的文档)
3. 标注每条的难度等级(L0/L1/L2/L3)

## 禁止
- 不要生成你无法给出确定答案的样本
- 不要编造法律条文,所有引用必须来自输入材料
- 生成后自我检查:期望输出是否真的可从输入推出?不能就标 [REVIEW] 交给人工

## 输出
JSON 数组,每条含 {input, expected, dimension, difficulty, source_note}

AI 生成 + 人工终审能把构建成本降到纯人工的 1/3,但终审不能省——AI 生成的样本里通常有 15–25% 需要修改或作废。

4.3 Step 3:基线模型选型(第 3-4 周)

4.3.1 候选池

候选参数上下文许可备注
Kimi K32.8T(开放权重)1M开放权重原生视觉、支持显式提示词缓存
GLM-5.3——开放权重已在海外云托管输出
Step 5 Preview600B MoE(27B 激活)1M承诺全开放AA 指数 44,价格约 GPT-5.6 Sol 的 1/7
Qwen 系列多档长上下文开放权重中文场景强
MiMo-V2.6-Pro—1MMITWebDev 榜 1628

4.3.2 选型评测的三个层次

层次一:客观指标(机器跑)

python eval_runner.py \
  --model kimi-k3 \
  --tasks tasks/main_eval.jsonl \
  --rubric rubrics/ \
  --judge claude-sonnet-4-5 \
  --out results/kimi-k3-main.json

注意:judge 用前沿模型。评测这件事本身要花钱,但它是整个迁移的地基,不能省。用 Jev 这类判断模型可以降低成本(延迟 70–500ms,输入 $0.042/百万 token)。

层次二:人工盲评(人跑)

从盲评集抽 300 条,把「前沿模型输出」和「候选模型输出」混在一起,让法务专家不知道哪个是哪个,按 rubric 打分。

为什么必须盲评:知道来源会引入偏见。知道「这是便宜的自研模型」的人会不自觉地挑刺,反之亦然。

层次三:成本与延迟(工程跑)

模型        单卡吞吐(tok/s)   P99延迟(s)   每百万输出token成本(自托管)
Kimi K3        1,840            3.2          $0.42  [推演]
GLM-5.3        2,210            2.8          $0.35  [推演]
Step 5         3,050            2.1          $0.26  [推演]
前沿API          —              1.9          $6.00  [公开定价]

自托管成本含 GPU 摊销、电力、运维。估算口径要写清楚,否则后期对账必然吵架。

4.3.3 决策矩阵

候选客观得分盲评得分自托管成本部署难度许可风险结论
前沿模型(基线)88.44.31/5$6.00/M——保留 L3
Kimi K379.23.86/5$0.42/M中低选为基线
GLM-5.377.53.74/5$0.35/M中低备选
Step 5 Preview81.03.95/5$0.26/M高待定(权重未全开)观察

选 Kimi K3 的理由:盲评差距最小(3.86 vs 4.31,差 0.45),自托管成本差 14 倍,且许可明确。Step 5 分数更高但权重承诺 10 月 15 日才全开,不能赌。

关键判断:不选分数最高的,选「分数够用 × 成本最低 × 风险可控」的。这是单位经济学驱动的选型,不是跑分驱动的选型。

4.4 Step 4:后训练(第 5-8 周)

4.4.1 数据来源与配比

数据类型占比来源作用
领域继续预训练语料40%公开法律文书、判例、法规、合同模板补领域知识与术语
SFT 示范数据30%前沿模型生成 + 专家修正教格式与推理链
真实 bad case 修正对20%线上失败请求 + 专家给出的正确输出针对性补短板
DPO 偏好对10%同一输入的两个输出,专家选优对齐专家偏好

「真实 bad case 修正对」是 ROI 最高的一类。它直接对应你的用户实际会遇到的失败模式,比任何通用数据都有效。

4.4.2 bad case 挖掘

# mine_bad_cases.py
"""从线上 trace 里挖出需要进训练集的失败样本"""
import json

CRITERIA = {
    "low_rubric": lambda r: r["rubric_score"] < 2.4,
    "high_retry": lambda r: r["retry_count"] >= 2,
    "human_edited": lambda r: r.get("human_edit_ratio", 0) > 0.3,
    "explicit_negative": lambda r: r.get("user_feedback") == "thumbs_down",
    "hallucination_flag": lambda r: r.get("hallucination_detected", False),
}

with open("traces_30d.jsonl") as f, open("bad_cases.jsonl", "w") as out:
    for line in f:
        r = json.loads(line)
        hits = [name for name, fn in CRITERIA.items() if fn(r)]
        if hits:
            r["_bad_reasons"] = hits
            out.write(json.dumps(r, ensure_ascii=False) + "\n")

人工编辑比例(human_edit_ratio)是被低估的信号。用户用了你的输出但改了 30% 以上,说明「方向对但不够好」——这类样本对后训练价值极高,而它们通常不会被标记为「失败」。

4.4.3 SFT 数据构造的 Prompt 模板

你要为法律文档处理任务生成训练数据(SFT 示范样本)。

## 输入
{{document_excerpt}}

## 目标任务
{{task_description}}

## 输出要求
严格按照下面这个格式与推理结构输出:

1. **定位**:先指出答案来自文档的哪一段(给出章节号/页码)
2. **抽取**:逐条列出抽取结果,每条带引用位置
3. **不确定项**:文档中未明确说明的内容,标注 [UNCERTAIN] 并说明缺什么
4. **禁止**:不得出现文档中没有的内容;无法从文档推出的,宁可标 [UNCERTAIN]

## 质量标准(rubric)
{{rubric}}

## 自检
生成后必须回答三个问题:
a. 我引用的每一处是否真的在文档里?
b. 有没有我把「合理推测」写成了「事实」?
c. 如果这份输出给到律师,他会不会因为某句话做出错误判断?

任一问题答案不利,重写。

「自检三问」是这套数据的核心。它把 rubric 里的「无幻觉」要求变成了生成时的显式检查点。

4.4.4 迭代节奏

Week 5: SFT v1  → 金标集得分 79.2 → 82.6
Week 6: + bad case 数据 → 82.6 → 85.1
Week 7: DPO v1  → 85.1 → 86.3
Week 8: DPO v2 + 红队修补 → 86.3 → 87.1

每次迭代必跑三件事:金标集客观分、盲评集人工抽查(50 条)、红队集安全检查。

只跑客观分是最大的陷阱:模型会对 judge 过拟合,客观分涨而实际质量不涨。每轮必须人工抽检。

4.5 Step 5:灰度切流(第 9-10 周)

4.5.1 路由层设计

# router.py
class ModelRouter:
    def __init__(self, config):
        self.config = config

    def pick(self, task_type, payload):
        level = self.config.task_levels.get(task_type, "L2")

        # L3 永远走前沿模型
        if level == "L3":
            return ("frontier", {})

        # 灰度比例按层级独立配置
        rollout = self.config.rollout[level]
        if rollout <= 0:
            return ("frontier", {})
        if rollout >= 1 or self._hash_bucket(payload) < rollout:
            if level == "L2":
                # L2 走双跑交叉校验
                return ("self_hosted", {"cross_check": "frontier"})
            return ("self_hosted", {})
        return ("frontier", {})

    def _hash_bucket(self, payload):
        import hashlib
        h = hashlib.md5(payload["request_id"].encode()).hexdigest()
        return (int(h[:8], 16) % 10000) / 10000

用 request_id 做哈希分桶,保证同一个请求在灰度比例不变时始终命中同一条路径——否则用户会看到结果随机跳变,反馈无法归因。

4.5.2 灰度节奏

阶段L0L1L2观察指标通过条件
D1–D25%0%0%错误率、延迟、成本无 P0/P1
D3–D520%0%0%+ 用户编辑率编辑率不升
D6–D850%5%0%+ 盲评抽样盲评差距 < 0.2
D9–D11100%20%0%+ 成本曲线成本下降符合预期
D12–D14100%50%10%+ 交叉校验一致率一致率 > 92%
D15–D21100%100%50%全量监控稳定

每个阶段都有明确的「通过条件」和「回滚条件」。灰度不是「慢慢放开」,是「每个台阶都要验收」。

4.5.3 双跑交叉校验(L2 专用)

对高风险任务,自研模型与前沿模型都跑,比较结果:

def cross_check(self_hosted_out, frontier_out, task_type):
    """返回是否需要人工介入"""
    agreement = compute_agreement(self_hosted_out, frontier_out)

    if agreement >= 0.92:
        return ("auto", self_hosted_out)
    if agreement >= 0.75:
        return ("flag_for_review", self_hosted_out, frontier_out)
    return ("use_frontier", frontier_out)

一致率低时自动回落到前沿模型。这是把「质量风险」变成「可控的额外成本」——只有真正困难的请求才付前沿模型的钱。

4.5.4 灰度期间的回归拦截

每次模型更新上线前,CI 自动跑三件事:

# .github/workflows/model-gate.yml
name: model-gate
on:
  pull_request:
    paths: ["models/**", "training/**"]

jobs:
  gate:
    runs-on: [self-hosted, gpu]
    steps:
      - name: Run golden set
        run: |
          python eval_runner.py \
            --model ./models/candidate \
            --tasks eval/golden.jsonl \
            --judge claude-sonnet-4-5 \
            --out eval_result.json

      - name: Run red team set
        run: |
          python eval_runner.py \
            --model ./models/candidate \
            --tasks eval/redteam.jsonl \
            --strict \
            --out redteam_result.json

      - name: Gate
        run: |
          python gate.py \
            --baseline eval/baseline_frontier.json \
            --candidate eval_result.json \
            --max-regression 1.5 \
            --redteam-max-failures 0

gate.py 的核心逻辑:

def gate(baseline, candidate, max_regression, redteam_max_failures):
    reasons = []

    # 1. 整体不能退步超过阈值
    if candidate["score"] < baseline["score"] - max_regression:
        reasons.append(f"整体得分退步 {baseline['score'] - candidate['score']:.2f}")

    # 2. 按任务层分别卡,防止某一层偷跑
    for level in ("L0", "L1", "L2"):
        b = baseline["by_level"][level]["score"]
        c = candidate["by_level"][level]["score"]
        if c < b - max_regression:
            reasons.append(f"{level} 层退步 {b - c:.2f}")

    # 3. 红队集零容忍
    if candidate["redteam_failures"] > redteam_max_failures:
        reasons.append(f"红队集失败 {candidate['redteam_failures']} 条")

    # 4. 幻觉维度单独卡
    if candidate["by_dimension"]["no_hallucination"] < baseline["by_dimension"]["no_hallucination"]:
        reasons.append("幻觉维度退步(一票否决)")

    return (False, reasons) if reasons else (True, [])

第 2 条「按任务层分别卡」是关键。只看总分会出现「L0 涨 3 分、L2 跌 4 分 → 总分涨 0.4 分」这种蒙混过关。

第 4 条幻觉一票否决对应 rubric 里的门控规则。法律场景里,幻觉退步不能用任何分数补偿。

4.6 Step 5.5:后训练的具体配置

4.6.1 为什么选 LoRA 而不是全参微调

维度全参微调LoRA
显存需求2.8T 参数模型基本不可行单卡 8×A100 可跑
训练速度慢快 3–5 倍
灾难性遗忘风险高风险低(底座冻结)
多任务切换每个任务一份全量权重一个底座 + 多个小适配器
最终质量上限更高略低(本案例够用)

对 2.8T 参数级别的模型,LoRA 基本是唯一现实选择。 且本案例的目标是「补领域知识与格式」,不是「改变模型的基础能力」——LoRA 的能力天花板完全够。

4.6.2 训练配置

# train_sft.yaml
base_model: moonshot/kimi-k3
method: lora

lora:
  r: 64
  alpha: 128
  dropout: 0.05
  target_modules:
    - q_proj
    - k_proj
    - v_proj
    - o_proj
    - gate_proj
    - up_proj
    - down_proj

training:
  stage: sft
  num_epochs: 3
  per_device_batch_size: 4
  gradient_accumulation_steps: 16
  learning_rate: 1.0e-4
  lr_scheduler: cosine
  warmup_ratio: 0.03
  max_seq_len: 32768
  bf16: true
  gradient_checkpointing: true

data:
  mix:
    - path: data/domain_corpus.jsonl      # 40%
      weight: 0.40
    - path: data/sft_demonstration.jsonl  # 30%
      weight: 0.30
    - path: data/badcase_pairs.jsonl      # 20%
      weight: 0.20
    - path: data/long_context.jsonl       # 10%(长文档场景单独补)
      weight: 0.10
  packing: true
  shuffle_seed: 42

DPO 阶段:

# train_dpo.yaml
base_model: ./checkpoints/sft_v3
method: lora

dpo:
  beta: 0.1
  loss_type: sigmoid
  max_length: 16384
  max_prompt_length: 8192

training:
  num_epochs: 1
  learning_rate: 5.0e-6      # DPO 的学习率要比 SFT 小一个量级
  per_device_batch_size: 2
  gradient_accumulation_steps: 32

DPO 学习率必须比 SFT 小一个量级(1e-4 → 5e-6)。用 SFT 的学习率跑 DPO,模型会迅速崩坏——表现为输出变得空洞、重复、回避具体问题。

4.6.3 迭代记录

v0  基线(未后训练)              客观分 79.2   盲评 3.86
v1  SFT(领域语料 + 示范)        82.6   盲评 3.98
v2  SFT + bad case 数据          85.1   盲评 4.09
v3  + 长上下文数据补齐            85.4   盲评 4.10   ← 长文档档位明显改善
v4  DPO v1                      86.3   盲评 4.14
v5  DPO v2 + 红队修补            87.1   盲评 4.16
─────────────────────────────────────────────────
前沿基线                          88.4   盲评 4.31

v2 的涨幅最大(+2.5),来自 bad case 数据。这验证了前面的判断:真实失败样本是 ROI 最高的数据。

v3 只涨了 0.3 分,但长文档档位涨了 4.1 分。总分掩盖了分层差异——这再次说明评测必须分层看。

4.7 Step 5.6:推理部署

4.7.1 显存规划

Kimi K3 2.8T 参数(开放权重)
├─ BF16 全量:        约 5.6 TB   → 需 8 卡 × 8 = 64 卡 A100/H100,不现实
├─ FP8 量化:         约 2.8 TB   → 约 32 卡
├─ INT4(AWQ/GPTQ): 约 1.4 TB   → 约 16–20 卡
└─ 实际部署方案:      INT4 + 张量并行 + 分层卸载

量化是让这件事经济上成立的关键。但量化会带来质量损失,必须实测:

精度金标集得分盲评显存结论
BF1687.14.165.6 TB太贵
FP886.84.152.8 TB可用
INT4 (AWQ)85.94.111.4 TB选它
INT4 + 部分层 FP886.54.131.9 TB备选

INT4 掉 1.2 分,换显存减半。在 L0/L1 层这个损失完全可接受(本来就差 0.1–0.2 分,量化后差 0.3–0.4 分,仍在阈值内)。L2 层用「INT4 + 部分层 FP8」的混合方案。

4.7.2 vLLM 部署配置

python -m vllm.entrypoints.openai.api_server \
  --model /models/kimi-k3-awq \
  --quantization awq \
  --tensor-parallel-size 8 \
  --pipeline-parallel-size 2 \
  --max-model-len 262144 \
  --max-num-batched-tokens 16384 \
  --enable-prefix-caching \
  --enable-chunked-prefill \
  --gpu-memory-utilization 0.92 \
  --served-model-name legal-internal-v5 \
  --port 8000
参数值为什么
--enable-prefix-cachingon同一份合同被多次查询时,共享前缀缓存能省大量重复计算
--enable-chunked-prefillon长文档 prefill 切片,避免单次占满显存导致其他请求排队
--max-num-batched-tokens16384吞吐与延迟的平衡点,需按实测调
--gpu-memory-utilization0.92留 8% 余量防 OOM

--enable-prefix-caching 在法律场景收益极大:系统提示 + 项目规范 + 同一份合同的前 50K token 通常是重复的,缓存命中后这部分成本直接归零。

4.7.3 自托管成本模型

单卡成本(3 年摊销):
  H100 单价            $25,000
  3 年折旧             $25,000 / 36 = $694/月
  电力(0.7kW × 24h)   约 $50/月
  机房/托管             约 $120/月
  运维人力分摊          约 $80/月
  ────────────────────────────────
  单卡月成本            约 $944

16 卡集群月成本        约 $15,100

吞吐测算:
  INT4 + 8 卡张量并行 × 2 流水并行
  实测输出吞吐          约 3,200 tok/s(集群整体)
  月产出                3,200 × 3600 × 24 × 30 ≈ 82.9 亿 token

单 token 成本 = $15,100 / 8.29e9 × 1e6 ≈ $1.82 / 百万 token

上面的 $0.42/M 是按 GPU 利用率 100%、且只算输出 token 的理想值。 实际运营中利用率通常在 40–70%,真实成本在这个基础上再乘 1.5–2.5 倍。 这个数字 [推演] 用于说明「自托管成本也要认真算」,不要直接抄进你的预算表。

最重要的修正:多数团队第一次算这个账时,都会忘记三件事——GPU 利用率、输入 token 也占算力、以及夜间低峰期资源闲置。把理论值打 2 折再拿去对比 API 价格,是比较稳的做法。

4.8 Step 6:成本与质量的双监控(持续)

4.6.1 必看的六个指标

指标计算告警阈值
单任务成本总成本 / 任务数环比 +15%
分层成本占比各层成本 / 总成本L0+L1 占比 < 25% 说明迁移没生效
金标集周得分每周跑一次环比 -1.5 分
用户编辑率被编辑字符数 / 总输出字符数环比 +5%
交叉校验一致率L2 任务的一致比例< 90%
幻觉投诉率用户标记为幻觉的次数 / 总数任何上升

「用户编辑率」是最真实的线上质量指标。它不需要专家、不需要评测集,直接从产品行为里算。金标集分数会漂移,用户编辑率不会撒谎。

4.6.2 监控面板

# 单任务成本趋势
sum(rate(llm_cost_usd_total[1h])) / sum(rate(llm_tasks_total[1h]))

# 分层成本占比
sum by (task_level) (rate(llm_cost_usd_total[1h]))
  / ignoring(task_level) group_left sum(rate(llm_cost_usd_total[1h]))

# 自研 vs 前沿 的调用分布
sum by (model_tier) (rate(llm_requests_total[5m]))

五、效果数据

5.1 成本结构变化 [推演]

指标迁移前迁移后变化
单次请求平均成本$0.42$0.071-83%
每百万输出 token 单价$6.00$0.42(自托管)-93%
L0+L1+L2 走自研比例0%92%—
L3 走前沿比例100%100%(保留)—
月度推理成本100(基准)21-79%
GPU 与运维固定成本014新增
月度总成本10035-65%

注意新增的 GPU 固定成本。这是很多迁移算错账的地方:只算了 API 省下的钱,忘了自托管要付固定成本。只有当负载足够大时,固定成本才能被摊薄。

5.2 毛利变化 [公开 + 推演]

阶段毛利率
早期(按席位计费,用量可控)约 +50% [公开]
转向用量计费 + token 消耗涨 20 倍后约 -50% [公开]
迁移完成转正 [公开]

这个 V 型曲线是关键。它说明一件事:商业模式(按用量计费)与技术架构(全用前沿模型)的组合,在 Agent 化之后会爆炸。 你必须改其中一个。Harvey 选择改技术架构。

另一个选择是改商业模式——回到按席位计费或设用量上限。但那会限制用户价值,等于自废武功。

5.3 质量变化

任务层前沿基线自研模型差距是否可接受
L0(抽取/摘要)4.314.22-0.09✅ 完全可接受
L1(比对/标注)4.284.05-0.23✅ 可接受(有校验)
L2(尽调/交叉推理)4.353.91-0.44⚠️ 需交叉校验
L3(定制意见)4.41——保留前沿模型

分层后再看这张表,结论完全不同。整体看「自研比前沿差 0.4 分」会让你不敢上;分层后你会发现 L0/L1 差距只有 0.1–0.2 分,而它们占 85% 的流量。

5.4 时间线

阶段耗时人力关键产出
流量分析1 周1 人任务分层表、成本分布
评测集2 周3 人(含 2 法务)1400 条金标集 + rubric
选型2 周2 人基线模型决策
后训练4 周3 人模型 v4
灰度2 周2 人分层路由上线
合计11 周峰值 5 人—

真正的瓶颈是评测集,不是训练。训练有成熟工具链,评测集需要领域专家的时间,而且无法并行压缩。


六、踩坑清单

坑 1:先训练,后建评测集

症状:模型训了三轮,没人说得清是变好还是变差,团队开始凭感觉争论。

原因:没有基线评测集,所有质量判断都退化为主观意见。

修法:评测集必须是 Phase 1。如果老板催,就用 100 条最小集先启动,但不能是 0 条。

坑 2:judge 过拟合

症状:金标集分数一路涨到 91 分,人工盲评只有 3.7/5,用户投诉变多。

原因:模型学会了讨好 judge(更长的解释、更多的格式化、更谨慎的措辞),但没学会做对事。

修法:

  • 每轮迭代必须人工抽检 50 条
  • 定期轮换 judge 模型
  • 加入「用户编辑率」这个不依赖 judge 的线上指标

坑 3:整体替换而非分层

症状:全量切过去,第二周高价值客户投诉激增,紧急回滚。

原因:L2/L3 任务的差距被 L0/L1 的平均数掩盖了。

修法:严格分层,L2 双跑校验,L3 永久保留前沿模型。3% 的流量保留前沿模型,成本占比不到 5%,但它是你的保险丝。

坑 4:低估自托管的固定成本

症状:财报上 API 支出确实降了 80%,但总成本只降了 30%,还多了 GPU 采购和运维人力。

原因:只算变动成本,不算固定成本。

修法:

盈亏平衡负载 = GPU固定成本 / (前沿API单价 - 自托管单价)

举例:
  固定成本 $14/月(归一化)
  价差 $6.00 - $0.42 = $5.58 / 百万 token
  平衡点 = 14 / 5.58 ≈ 2.5 百万输出 token / 月 × 单位

低于这个负载,自建是亏的。 迁移前先算这个数。

坑 5:训练数据污染评测集

症状:金标集分数异常高(95+),上线后一塌糊涂。

原因:构造 SFT 数据时用了评测集的样本,模型背下了答案。

修法:

  • 评测集与训练集严格隔离,用哈希去重
  • 评测集知道的人最小化
  • 定期用新构造的样本替换部分评测集

坑 6:忽略许可条款

症状:模型上线三个月后收到许可变更通知,商用条款变了。

原因:选型时只看跑分和成本,没仔细读许可。

修法:选型矩阵里加一列「许可风险」,并把「权重是否真的开放」「商用是否有限制」「是否有参数规模门槛」逐条确认。Kimi K3 这类明确开放权重的模型在这一点上风险最低。

坑 7:格式不兼容导致全线报错

症状:切过去之后 15% 的请求解析失败。

原因:自研模型的输出格式与前沿模型有细微差异(引号、转义、多余的解释性前缀),解析器没适配。

修法:

  • 路由层加格式归一化
  • 灰度前跑一次纯格式冒烟(1000 条请求只看能否解析)
  • 用结构化输出(JSON schema / grammar-constrained decoding)而不是靠提示词约束

坑 8:长上下文退化

症状:短任务表现接近,长文档(> 80K token)质量断崖式下跌。

原因:开放权重模型的长上下文能力往往标称 1M,但有效上下文远小于此。

修法:

  • 评测集按长度分档(<16K / 16–64K / 64–200K / >200K)
  • 长文档场景强制走检索 + 分片,而不是整篇塞进上下文
  • L2 任务的文档预处理不能省

坑 9:灰度期间没有回滚按钮

症状:发现问题时,回滚需要改代码重新发版,花了 4 小时。

修法:路由层的灰度比例必须支持热更新(配置中心改数字,秒级生效),不能靠发版。

坑 10:成本监控只看总额

症状:总成本确实降了,但因为一次提示词改动,L0 任务的 token 消耗悄悄涨了 3 倍,三个月后才被发现。

修法:成本监控必须按层 × 按任务类型下钻,并设环比告警。

坑 11:法务合规没参与

症状:模型上线后被问「训练数据里有没有客户的合同」,答不上来。

修法:数据构建阶段就让合规介入,明确三件事:

  • 训练数据是否包含客户数据(本案例:只用脱敏数据与公开语料)
  • 推理请求是否留存(本案例:metadata-only)
  • 模型输出的法律责任归属(必须由人终审)

坑 12:把「降本」当成唯一目标

症状:为了再降 10% 成本,把 L2 也全切了,质量事故后损失远超省下的钱。

修法:在监控面板上把「质量指标」和「成本指标」放在同一屏,任何降本动作的评审必须有质量负责人在场。

坑 13:没算人力成本

症状:项目「成功」了,但回头一算,5 个人 11 周的人力成本,够付两年 API 费。

修法:迁移前算完整 ROI:

年化节省 = 月省成本 × 12
投入     = 人力成本 + GPU 固定成本 × 12 + 机会成本
回本周期 = 投入 / 年化节省

本案例 [推演]:约 7 个月回本

负载不够大的团队,不值得做这件事。

坑 14:以为做一次就完了

症状:迁移完成后团队解散,半年后新模型出来,又要重来一遍。

修法:把这套流程产品化——评测集常驻更新、训练管线可复用、路由层支持热插新模型。第二次迁移的成本应该只有第一次的 30%。

坑 15:前缀缓存没开,长文档任务白烧算力

症状:自托管跑起来了,但实际吞吐只有理论值的 40%。

原因:法律场景里大量请求共享同一份合同 + 同一段系统提示,没开 prefix caching 导致这部分每请求重算一遍。

修法:

# vLLM 启动时必须带这两个参数
--enable-prefix-caching
--enable-chunked-prefill

实测开启后,同一份合同被多次查询的场景下吞吐提升约 1.8 倍。这是自托管场景里性价比最高的一行配置。

坑 16:没给「空闲时段」做规划

症状:白天高峰期 GPU 打满排队,夜里资源闲置,但账单按整机算。

修法:把离线批量任务(评测集跑分、数据生成、历史请求重放)调度到夜间低谷。GPU 利用率从 45% 提到 72%,单位成本下降约 35%。

时段规划:
  00:00-08:00  离线批处理(评测、数据构造、模型迭代)
  08:00-22:00  在线推理
  22:00-24:00  日志回放与 bad case 挖掘

自托管成本的命门是利用率,不是单价。 买到卡只是开始,把卡跑满才是真正的功课。

坑 17:把「模型版本」当成了「产品版本」

症状:模型从 v3 升到 v5,产品侧完全没感知,某天用户反馈「输出风格变了」才发现。

修法:模型版本必须作为产品的一等公民管理——

- 每次模型更新必须走一次完整灰度(不能因为「只是小版本」就跳过)
- 用户可见的输出风格变化必须提前公告
- 保留至少两个历史版本可随时回滚
- 模型版本号写进响应的 header,便于归因

七、经验总结

7.1 五条可迁移的结论

① 单位经济学会追上你,只是时间问题。 按用量计费 + Agent 化 + 上下文膨胀,这三个因素叠加,任何重度 AI 应用都会在 12–24 个月内撞上毛利墙。早算这笔账比晚算便宜。

② 分层是唯一低风险的迁移路径。 全量替换的风险集中在最难的 3–15% 任务上,而这批任务往往贡献最多的收入。分层让你用 5% 的成本保留保险丝。

③ 评测集是真正的资产,模型不是。 模型会过时(6 个月后又有新的开放权重出来),评测集不会。第二次迁移的成本应该只有第一次的 30%——前提是你第一次认真建了评测集。

④ 自托管有盈亏平衡负载,低于它别自建。 平衡点 = 固定成本 / (API单价 - 自托管单价)。算完这个数再决定,别跟风。

⑤ 质量的最终裁判是线上行为,不是评测分数。 「用户编辑率」「重试率」「投诉率」这三个指标不需要专家、不需要 judge,且永远真实。把它们和成本指标放在同一屏。

7.2 一条最重要的原则

AI 可以跑评测、做分析、写补丁、执行迁移,但「什么算改善」的定义必须由人给出。

本案例里所有翻车的可能,几乎都源于这条线被越过:

  • 让 judge 定义质量 → 过拟合
  • 让成本指标定义成功 → 质量崩塌
  • 让模型自己生成评测集而不终审 → 评测集失真

守住这条线,剩下的工程问题都是有解的。

7.3 什么时候你该做这件事

该做:

  • 月度推理成本 > 收入的 30%
  • 任务分布里有大量 L0/L1(抽取、分类、摘要、格式化)
  • 有领域专家能参与评测集构建
  • 负载超过自托管盈亏平衡点

不该做:

  • 月推理成本 < 几万美元(人力不划算)
  • 任务全是 L2/L3(高风险推理,开放权重差距太大)
  • 没有领域专家(建不出评测集)
  • 模型能力还在快速迭代、产品形态没定型(做完就过时)

八、复盘:如果重来一次,会改的六件事

8.1 评测集应该先建两倍的量

实际建了 1400 条,回头看应该有 2500–3000 条。原因:

  • 迭代到后期,模型在评测集上的方差变大(87.1 和 86.4 的差异可能只是噪音)
  • 分层之后每层的样本量被稀释:L3 只有 60 条,统计上不可靠
  • 没有余量做「评测集轮换」(防止 judge 过拟合需要定期换样本)

修正后的规模:主集每类 300 条(不是 200),L3 单独补到 200 条,并预留 30% 的未使用样本用于轮换。

8.2 应该更早引入「用户编辑率」

前五周完全依赖金标集分数做决策,直到灰度期才发现金标集和真实体验有偏差。

教训:线上行为指标要在 Phase 1 就接好,哪怕评测算不出来,也能提供交叉验证。

正确顺序:
Week 1: 接线上行为埋点(编辑率、重试率、放弃率)
Week 1: 同时开始建评测集
Week 3: 评测集就绪后,用行为指标交叉验证评测集是否可信

8.3 量化方案应该更早测

量化是在 Step 5 部署阶段才测的,发现 INT4 掉 1.2 分后,要不要回退到 FP8 成为一场争论——因为显存已经按 INT4 采购了。

教训:量化实验要和选型同步做(Phase 2),而不是放到部署前。它直接影响硬件采购决策。

8.4 应该给 L2 留更高的质量余量

L2 迁移后差距 -0.44 分,靠双跑交叉校验兜底。但交叉校验的一致率只有 92%,意味着 8% 的 L2 请求要人工介入——这部分人力成本当时没算进去。

修正:L2 要么再训一轮把差距压到 -0.3 以内,要么把交叉校验的人力成本明确计入 ROI。

8.5 合规评审应该更早

合规是在数据构建阶段才引入的,导致数据清洗返工了一次(部分语料的商用许可不明确)。

教训:选型阶段就要过一遍合规,因为它可能直接否决某些候选模型。

8.6 应该把「迁移」做成可重复流程,而不是一次性项目

第一次迁移 11 周、峰值 5 人。六个月后新模型出来,如果还要 11 周,这个成本就不可持续。

应该产品化的四件事:

资产状态下次复用能省
评测集 + rubric✅ 已有约 2 周(不用重建,只要更新)
训练管线(配置化)⚠️ 部分约 3 周(脚本还在,超参要重调)
路由层✅ 已有(热插拔)约 1 周(只加新模型配置)
灰度与监控✅ 已有约 1 周(改监控目标即可)

目标:第二次迁移 4 周内完成。 做不到,说明第一次的产品化没做好。


九、附:一页纸检查清单

迁移前
[ ] 算过自托管盈亏平衡负载,且当前负载高于它
[ ] 完成了任务分层,知道每类的流量占比与成本占比
[ ] 建了 ≥1000 条金标集,含 rubric 与门控规则
[ ] 记录了当前前沿模型的质量基线(这是唯一参照系)
[ ] 确认过候选模型的许可条款

迁移中
[ ] 每轮迭代都跑金标集 + 人工抽检 50 条
[ ] 训练集与评测集严格隔离(哈希去重)
[ ] 灰度比例支持热更新,回滚不需要发版
[ ] L2 走双跑交叉校验,L3 永久保留前沿模型
[ ] 合规已确认训练数据来源

上线后
[ ] 监控面板上成本与质量指标同屏
[ ] 按层 × 任务类型的成本下钻 + 环比告警
[ ] 用户编辑率作为核心质量指标持续追踪
[ ] 评测集每季度更新 20% 新样本
[ ] 训练管线可复用(为下一次迁移做准备)

相关推荐

查看更多 →
案例企业应用

把 Agent 的账单砍掉 88.9%:一次复杂任务 40 次模型调用背后的成本治理实战

2026 年 9 月,云栖大会前后有一条被低估的工程数据:一次复杂的 Agent 任务往往涉及十余次到数十次模型调用,而通过模型路由等 Harness 层能力,可以在保留 99.96% 任务质量的同时把成本降低 88.9%。这个数字之所以值得单独写一篇,是因为它戳中了 2026 年所有 Agent 项目的同一个死穴——Demo 阶段每任务几毛钱,上线后每任务几块钱,规模化之后账单涨 10 倍以上,而团队的第一反应「换个便宜模型」几乎总是失败。本文是一家中型 SaaS 公司真实走过的 10 周:从「账单涨了 14 倍」到「单任务成本降到原来的 11.1%,质量回归集通过率 99.96%」。全文包含可复现的五把刀(模型路由 / Prompt Caching / 上下文预算 / 批处理 / 早停去重)各自的 ROI 实测占比、三层指标体系与评测集构建方法、灰度切流与回归监控的完整节奏、每一步的 Prompt 模板,以及 14 个真实踩过的坑。附完整效果数据表与回滚红线定义。

2026-09-23
#AI实战#Agent
案例企业应用

DeepSeek V4.1 Flash 多模型路由降本实战:单任务成本从 $1.47 砍到 $0.33,月账单降 77.7%

2026 年 10 月,DeepSeek V4.1 Flash 的价格比 V4 Pro 低约 40%,把「多模型路由」这件事从可选优化变成了必答题。本文记录一家 420 人 SaaS 公司用 5 周把 Agent 平台从「所有调用都打最贵模型」改造成「按任务难度分档路由」的全过程:月支出从 $71,300 降到 $15,900(降 77.7%),单任务成本从 $1.47 降到 $0.33,P95 延迟从 31.2 秒降到 12.6 秒,而任务完成率反而从 93.4% 升到 96.2%。关键结论是——一次 40 次调用的任务里,真正需要最贵档模型的只有 4 次(10%),但这 4 次吃掉了 82% 的钱;剩下 36 次里有 27 次是「格式化、过滤、抽取」这类确定性活,用 Flash 完全够。全文含可直接复制的难度分级 Prompt 模板、TypeScript 路由判定器完整实现(规则前置 + 模型打分 + 三级 fallback + 预算闸门)、五周灰度切流的逐周数据、以及 12 个踩过的坑。

2026-10-08
#AI实战#多模型路由
案例企业应用

Agent 编码返工率治理实战:spec + 验收测试 + diff 自检三件套,把 AI 代码一次通过率从 38% 拉到 71%

AI 写代码的产能和它的返工量成正比,这是研发团队用AI 编码半年后才真正撞到的墙。我们团队 12 个前端工程师、4 个 AI 编码 Agent Cursor / Cline / Copilot 并行,日均产出 PR 从 11 个涨到 27 个,看起来赢了——但首轮评审通过率只有 38%,意味着三分之二的工作量在被返工吃掉。真正的原因不是模型能力不够,而是任务交给 Agent 的方式错了:需求描述里没有验收标准,Agent 只能猜;Agent 不知道验收标准,就没法自检;不自检就直接提交,返工必然发生。本文记录我们用四个月把一次通过率从 38% 提到 71% 的完整过程。核心是三件套:① 提交前把模糊需求转成可验收的 spec(含验收命令与判定标准);② 在 Agent 里挂可执行的验收测试,让它提交前自己跑一遍;③ 加一道 diff 自检环节专门抓「超出任务范围的改动」。四个阶段的实施顺序和每阶段的踩坑、三条被证明无效的尝试(包括「写更详细的 Prompt」)、以及12 个可复制的 Prompt 模板。附分阶段效果数据表:一次通过率 38%→71%、返工工时占比 44%→19%、交付周期 2.8 天→1.1 天,以及两个必须诚实说明的负面结果。

2026-10-13
#AI实战#AI编码
案例企业应用

AI 代码评审闸门落地实战:三道闸门 + 分级拦截,6 周把评审等待从 19 小时压到 2.4 小时,线上缺陷率降 34%

代码评审是研发流程里最容易堵的一环:PR 提上去平均要等 19 小时才有人看, reviewer 的时间被「这个变量命名不统一」「这里缺个空行」这类机械问题吃掉大半,真正的设计问题反而因为疲劳被放过。本文记录 N 公司基础架构组 2026 年 8 到 10 月用六周建成 AI 评审闸门的全过程:不追求「AI 替代人评审」,而是把评审拆成三道闸门——第一道 AI 机械扫描(风格、缺测试、明显 bug、安全模式),秒级返回、不过直接打回;第二道 AI 深度审查(逻辑正确性、边界、并发),只在第一道通过后跑,输出结构化意见并标注置信度;第三道人工,且 AI 明确标注「本次我覆盖了什么、没覆盖什么」,让人把注意力放在 AI 说不清的地方。关键设计是「分级拦截」:按改动风险自动决定闸门严格度,改个文案不该走全流程。结果:评审首响从中位 19 小时降到 2.4 小时,reviewer 人均每周花在评审上的时间从 6.5 小时降到 2.8 小时,合并后 7 天内发现的缺陷率下降 34%,AI 误报导致的无效返工控制在 8% 以内。全文含完整的工具分工表、三道闸门的判定规则与 Prompt 模板、分阶段投入产出数据、12 条踩坑清单,以及一条最重要的教训:AI 评审失败的头号原因不是能力不够,是它不敢说「这里我没把握」。

2026-10-12
#AI实战#代码评审