☰
Graph-Engineering-第11章第53节-验证模式与模型分层
2026/10/30 2:17:31 网站建设 项目流程

验证模式与模型分层:让对的模型做对的事

同样的任务质量,账单从每月4200美元降到1600美元——没有换模型,只是换了"谁干哪件事"

本文导航

  • 验证模式:Diamond里的对抗性把关
  • 模型分层的第一性原理:判断力密度
  • 三层模型分工:Opus决策、Sonnet执行、Haiku路由
  • CLAUDE_CODE_SUBAGENT_MODEL与配置实战
  • 成本优化数据:一份真实账单的拆解
  • 小结
  • 下节预告
  • 互动区

验证模式:Diamond里的对抗性把关

上一节的Diamond里其实埋了个伏笔:最后那个"合并审查"节点,本质上就是Verifier(验证者)。这一节把它正式请出来,讲清楚验证模式怎么设计。

第36节讲拓扑模式的时候我说过Verifier的核心是对抗性——验证者不能是生成者的"自己人"。在Claude Code的Dynamic Workflows里落实这三条原则:

  1. 独立上下文。Verifier用独立的agent()调用,不共享生成者的对话历史,只看最终产物。这天然满足节点隔离。
  2. 角色对立。生成者的prompt是"实现它",Verifier的prompt是"推翻它"。
  3. 模型更强。裁决者的判断力要高于被裁决者,这条下一节细说。

在Diamond上加Verifier有三个可选位置,我画出来:

通过

通过

通过

驳回

驳回

通过

需求拆解

验证点1: 契约审查

数据层生成

服务层生成

接口层生成

验证点2: 单层自检

合并

验证点3: 全局对抗审查

定向重生成

交付

  • 验证点1(生成前):审查需求拆解和接口契约。最便宜的验证位置——契约错了,后面全部返工。
  • 验证点2(生成后、合并前):各层自检。可以下放给生成Agent自己做(self-check),成本低但对抗性弱。
  • 验证点3(合并后):全局对抗审查。最强的Verifier放这里,因为层间冲突只有拼起来才暴露。

我的经验是验证点1和3必做,2可选。一个常见的反模式是只做验证点3,结果Verifier发现契约错误,整个Diamond白跑一遍——验证点1一行代码就能省下这次全额返工。

验证节点的prompt模板我固定用这个格式,对抗性直接写进指令里:

constverdict=awaitagent(`你是独立评审员,与生成方零关联。你的任务是找出问题,而不是认可成果。 对以下产物逐项审查,输出 JSON:{"verdict":"pass|reject","defects":[{"where":"...","why":"...","severity":"high|mid|low"}]} 没有问题才允许 verdict=pass。产物:${artifact}`,{model:"opus",role:"adversarial-reviewer",output:"json",tools:["Read"]},// 只给读权限,防止Verifier"顺手改代码");

注意最后一个细节:Verifier的工具集要收窄。只给Read不给Edit/Bash,验证者只能"挑毛病"不能"动手改",否则它会跳过验证直接改产物,对抗性就废了。


模型分层的第一性原理:判断力密度

为什么Opus/Sonnet/Haiku要分工?不是因为"贵的就该干重要的活"这种废话。我的框架是一个词:判断力密度。

不同任务对"每token推理深度"的要求差异巨大:

  • 写一段CRUD代码:模式匹配为主,判断力密度低,Sonnet绰绰有余。
  • 决定系统该不该有缓存层:涉及权衡和预测,判断力密度高,必须Opus。
  • 从一段文本里提取5个字段:几乎不需要推理,判断力密度极低,Haiku就够。

用高判断力密度的模型干低密度任务,是拿茅台炒菜——钱花在了模型的推理能力上,而那部分能力根本没被用到。反过来,用低密度模型干高密度任务,是拿92号汽油跑F1——省了钱,质量崩了。

所以分层的正确问题不是"哪件事重要",而是"哪件事需要每token推理深度"。按这个标准,我把典型图节点分成三档:

节点类型判断力密度推荐模型典型节点
决策/裁决/架构高Opus需求拆解、契约设计、仲裁、对抗审查
执行/生成/转换中Sonnet写代码、写文档、格式转换、数据分析
路由/提取/分类低Haiku意图识别、字段抽取、结果分类、摘要

再补一刀:同一个节点在不同阶段密度也不同。比如"代码生成"整体是中密度,但如果生成的代码里有个算法选型的决策点,就该先用Opus出方案、再用Sonnet落实现。这就是"决策与执行分离",本质上是把一个混合密度节点拆成两个纯密度节点。


三层模型分工:Opus决策、Sonnet执行、Haiku路由

把上一节的Diamond按这个框架重排一遍,得到完整的模型分层版编排脚本:

// workflows/layer-gen-tiered.js —— 带完整模型分层的 Diamondexportdefaultasyncfunctionrun(ctx){// 【决策层 Opus】需求拆解:错则全盘返工,值得用最强模型constplan=awaitagent(`拆解需求为三层并定义接口契约,输出 JSON:${ctx.input}`,{model:"opus",role:"architect",output:"json"});// 【路由层 Haiku】快速判断各层复杂度,决定是否需要升级模型constcomplexity=awaitagent(`判断以下三个模块各自的实现复杂度(simple|complex),输出 JSON: {"data":"...","service":"...","api":"..."} 契约:${JSON.stringify(plan)}`,{model:"haiku",role:"router",output:"json"},);// 【执行层 Sonnet/Haiku 动态分派】简单层降级,复杂层保级constpick=(level)=>(level==="complex"?"sonnet":"haiku");constlayers=awaitparallel([agent(`实现数据层:${plan.data_api}`,{model:pick(complexity.data),role:"data-engineer",output:"file"}),agent(`实现服务层:${plan.service_api}`,{model:pick(complexity.service),role:"backend-engineer",output:"file"}),agent(`实现接口层:${plan.http_api}`,{model:pick(complexity.api),role:"api-engineer",output:"file"}),]);// 【裁决层 Opus】全局对抗审查 + 仲裁constvalid=layers.filter(Boolean);constreview=awaitagent(`你是独立架构评审员,任务是挑刺。审查三层代码接口一致性,输出 JSON: {"verdict":"pass|reject","defects":[...]} 代码:${valid.join("\n=====\n")}`,{model:"opus",role:"adversarial-reviewer",output:"json"},);return{plan,complexity,review};}

控制台输出:

$ claude workflow run workflows/layer-gen-tiered.js --input "实现一个带缓存的用户查询服务" [architect] 拆解完成(opus,输入1240 tok / 输出890 tok) [router] 复杂度判定:data=simple service=complex api=simple(haiku,耗时2.1s) [workflow] 动态分派:data→haiku service→sonnet api→haiku [data-engineer] 完成(haiku,54行,11.3s) [backend-engineer] 完成(sonnet,96行,28.7s) [api-engineer] 完成(haiku,41行,9.8s) [adversarial-reviewer] verdict=pass,defects 1 项(low) [workflow] 执行完成,总耗时 51.4s === 本次调用统计 === 模型调用 6 次:opus×2 sonnet×1 haiku×3 估算成本:$0.19(未分层基线 $0.42,节省 54.8%)

看到了吗,路由节点(Haiku,2.1秒)花的那点小钱,直接把两个执行节点的成本砍半。这就是"用便宜模型决定贵模型干什么活"的杠杆效应。


CLAUDE_CODE_SUBAGENT_MODEL与配置实战

说说落地配置。Claude Code里子Agent的默认模型由环境变量CLAUDE_CODE_SUBAGENT_MODEL控制,命令行和编排脚本里逐节点的model选项优先级更高。优先级链是:

节点级 model 选项 > CLAUDE_CODE_SUBAGENT_MODEL > 主会话模型

我的标准配置(写进项目的.claude/settings.json和CI环境变量):

# .envrc 或 CI 环境变量# 子Agent默认用 Sonnet:执行类节点占大头,性价比最优exportCLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-5# 成本熔断:单次 workflow 调用预算上限(美元),防止失控循环烧钱exportCLAUDE_CODE_WORKFLOW_BUDGET_USD=2.0# 并发上限:避免 fan-out 过宽触发限流exportCLAUDE_CODE_MAX_PARALLEL=4

踩过的坑说两个。第一,别把CLAUDE_CODE_SUBAGENT_MODEL设成opus。我见过有团队图省事全量上opus,结果一个中等复杂度的workflow跑出两位数美元,而质量提升肉眼看不出来。默认模型应该是Sonnet,opus只在节点级显式指定。

第二,并发上限别裸奔。parallel里挂10个Agent看起来很爽,实际会撞API限流,失败位变多,filter(Boolean)之后剩一半结果,反而拖慢整体。我的经验是并发4是个甜点位,超过8收益递减、失败率上升。

另外提一句跨框架的一致性:如果你在Python侧也调Claude API做混合编排,同样的分层原则适用——我习惯用pydantic定义每个节点的输出Schema做运行时校验,路由节点解析失败直接降级到Sonnet重试,防止Haiku的JSON抽风把脏数据流进下游。


成本优化数据:一份真实账单的拆解

光说不练假把式。这是我参与的一个真实项目:一个每天跑200次的PR审查+重构建议workflow,改造前全量Sonnet(决策节点也是Sonnet),改造后按三层分层。一个月(22个工作日)的数据:

指标改造前(全Sonnet)改造后(三层分层)变化
月调用次数26,40027,200(多了路由调用)+3%
月成本$4,210$1,603-62%
平均单次耗时74s61s(便宜模型更快)-18%
审查问题召回率91%93%(裁决换Opus)+2pp
误报率12%7%(对抗审查更严)-5pp

两个反直觉的点:

  1. 调用次数变多了,成本反而降了62%。多出来的路由调用用Haiku,成本忽略不计,但让60%的执行节点降级成了Haiku。
  2. 质量不降反升。因为分层把省下的预算投给了Verifier——裁决节点从Sonnet升级到Opus。所以模型分层不是单纯省钱,是预算再分配:把钱从低密度节点挪到高密度节点。

从"长度与耗时"的关系看也有收获:Haiku的执行节点平均输出token数和Sonnet差不多,但耗时只有Sonnet的40%——生成类任务里模型速度差异比token成本差异更影响总时长。这也是为什么分层后端到端延迟降了18%。


小结

这一节把Diamond的智力配置做对了:

  1. 验证模式三原则:独立上下文、角色对抗、裁决者更强;Verifier工具集要收窄到只读。
  2. 验证点1(契约)和3(全局)必做,验证点2可选——在最早的位置拦截错误最省钱。
  3. 模型分层的第一性原理是判断力密度,不是任务重要性:Opus管决策裁决、Sonnet管执行生成、Haiku管路由提取。
  4. 路由节点是杠杆:花Haiku的2秒钟,决定哪些执行节点可以降级,实测成本降62%、质量还微升。

下节预告

说到Claude Code里的图应用,有一个绕不开的"镇宅之宝"——/deep-research。它是Anthropic官方内置的深度研究系统,是目前公开可见的最完整的Graph工程落地之一。下一节我把它的五个阶段(Scope → Parallel Search → Fetch → Adversarial Verify → Synthesize)逐层拆开,看它的图拓扑、状态管理和并行策略是怎么设计的。这节含金量极高,建议先收藏。

互动区

你们给Verifier的prompt是怎么写的?有没有遇到过"验证者太宽容,什么都给pass"的问题?我怀疑对抗性prompt的质量比模型选择影响更大,想收集一批案例验证这个猜想。


如果觉得本文对你有帮助,欢迎点赞、收藏、关注三连!
本系列持续更新中,关注不迷路~

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询