Evidence-Driven Goal Loop
导言
我曾把一个看起来很明确的任务交给 AI:阅读 verl 代码,参考已有 GRPO 脚本适配 Kimi3 的减层训练,并在 NPU 上跑通第一个强化学习优化步。两天后,AI 仍在换软件版本、调整层数和重跑 OOM。真正棘手的不是“还没成功”,而是我无法回答领导接下来一定会问的问题:卡在哪里、解决过什么、时间花在哪里、还能不能解决、还要多久、代码是否上仓、中文设计文档在哪里?
这促使我把 Goal 从一句终点描述改造成一个工程控制面:用 goal-definition 先与用户签订任务合同,再让每个 Goal 强制携带 goal-execution,按证据等级执行有界循环。最终目标仍然重要,但每一轮都必须留下新的事实、排除一个原因,或形成一个可交付成果。
先说结论¶
长期 AI 任务最缺的不是坚持,而是控制面。 “没有完成就继续尝试”只定义了循环条件, 没有定义下一次尝试凭什么比上一次更有价值。当模型既没有中间状态,也没有实验门禁和 停止条件时,最容易选择那些看起来在推进、实际信息量很低的动作:换版本、减配置、重跑。
我的设计把原来的一条 Goal 拆成四层:
| 层次 | 回答的问题 | 持久产物 |
|---|---|---|
| Goal Definition | 这次究竟要完成什么 | Goal 合同 |
| Goal Execution | 遇到未知和失败时怎样工作 | 状态机与执行纪律 |
| Process Record | 实际做了什么、得到什么证据 | 过程账本与运行日志 |
| Deliverables | 截止当前已经能交付什么 | 代码、文档、测试与决策包 |
OpenAI Agents SDK 的 tracing 已经能记录 run、generation、function tool、 handoff 和自定义 span,这解决的是“执行轨迹能否被看到”。1 我的 Goal 控制面再向上补一层:为什么要执行这次动作、它对应哪个验收项、失败后何时 停止、到期时必须交付什么。 Trace 是证据来源之一,不是任务合同本身。
为什么 Goal 会空转¶
“把 Kimi3 的 GRPO 在 NPU 上跑通第一步”是一句业务终点,却压缩了至少五类性质不同的 问题:
| 问题层 | 典型未知量 | 无控制面时的错误动作 |
|---|---|---|
| 模型研究 | Kimi3 的结构、配置和加载方式与参考模型有何差异 | 直接复制脚本 |
| 框架适配 | verl 的注册、rollout、logprob、loss 路径要改哪里 |
报一处错改一处 |
| 环境兼容 | Python、PyTorch、CANN、NPU 插件和推理后端能否共存 | 轮盘式升降级 |
| 资源可行性 | 权重、KV cache、activation、梯度和 optimizer state 能否放下 | 不定位阶段就减层 |
| 工程交付 | 代码、脚本、日志、测试和中文设计文档放在哪里 | 等全部成功后再整理 |
原始 Goal 只有一个二元刻度:成功或失败。于是“整体 OOM”和“已经定位为 backward 前的 activation 峰值”都显示为失败;“没找到版本”和“确认两个官方版本组合均不兼容” 也没有区别。Agent 只能通过更多动作表达努力,却不能用未知量减少了多少表达进展。
真正的进展至少满足一项:
- 一个验收项有了可复核证据;
- 一个未知量变成了有来源的事实;
- 一个假设被增强、削弱或排除;
- 故障被缩小到具体阶段、函数、rank、tensor 或依赖;
- 形成了可复现脚本、日志、测试、提交或中文文档;
- 不可继续的问题被转换成领导可以选择的资源、范围或时间决策。
Google SRE 把排障描述为假设—演绎过程:从系统知识、遥测和日志形成候选原因,再用 观察或受控改变寻找支持和反证;它还特别强调保存测试记录,避免复杂长时问题重复走过 同一条路。3 这与我的核心判断一致:失败可以有价值,但前提是它产生了 能改变下一步的证据。
忙碌不是进展
运行了二十条命令、切换三个版本、占用八小时 NPU,都只是活动量。如果它们没有完成验收、增加证据、缩小故障或形成交付,就不能成为下一轮继续消耗预算的理由。
先把任务写成合同¶
第一个 Skill 是
goal-definition。
它不执行任务,只负责与用户分轮澄清,把自然语言愿望变成可验收的 Goal 合同。
直观上,它像开工前的施工图:不是要求一开始知道全部答案,而是确保终点、边界、 预算、权限和验收方式已经明确。可以通过只读调查获得的仓库、提交和环境事实由 AI 自己检查;会改变成功定义、风险或成本的问题才交给用户决策。
一份可执行合同至少包含:
| 合同部分 | 必须回答什么 |
|---|---|
| 目标与非目标 | 完成什么,明确不做什么 |
| 环境基线 | 仓库、提交、机器、软件栈、数据和已有成功基线 |
| 事实与未知 | 哪些已经证实,哪些只是假设,最低成本验证是什么 |
| 验收标准 | 可观察完成条件、证据位置和验收人 |
| 交付物 | 代码、脚本、中文设计文档、运行手册和报告到哪里 |
| 里程碑 | 每个阶段的退出条件,不只写日期 |
| 预算 | 时间、算力、费用、重试、版本切换和高成本实验上限 |
| 权限 | 哪些动作已授权,哪些需要审批,哪些禁止 |
| 停止与升级 | 何时 BLOCKED、ESCALATE 或 ROLLBACK |
| 汇报 | 节奏、对象和必须回答的管理问题 |
每个验收项都必须同时写观察条件和证据。例如“跑通第一步”可以拆成:
- Kimi3 配置和模型入口被
verl正确识别,以单测、加载日志和提交 SHA 证明; - 减层配置可显式指定,层数检查正确,以配置、测试和运行日志证明;
- rollout 与 reward 完成,以分阶段、分 rank 日志证明;
- backward 和首个 optimizer step 完成,以 step 日志和参数更新证据证明;
- 代码、脚本、中文设计文档和运行手册到达约定仓库位置。
合同有 DRAFT 和 READY 两个关键状态。关键验收、预算、权限或升级路径缺失时,只能
保持 DRAFT;非阻塞问题可以采用推荐默认值,但必须写进“待确认假设”。只有用户确认
关键条款,或明确授权采用列出的默认值,Goal 才能进入 READY。
Goal 不能在执行中偷偷缩水
如果物理显存不足,只能提出“增加资源”“降低序列长度”“减少模型层数”三类决策及影响,不能自行把 32K 目标改成 4K 后宣布原 Goal 已完成。范围变化必须保留原条款、记录证据并由用户确认。
再把执行变成受控搜索¶
第二个 Skill 是
goal-execution。
它是每个 READY Goal 强制携带的执行协议,负责把“继续工作”改成一次次可结束、
可归档的控制周期。
状态机不是为了增加流程感,而是让失败具有位置:
stateDiagram-v2
[*] --> INIT
INIT --> BASELINE
BASELINE --> RECON
RECON --> HYPOTHESIS
HYPOTHESIS --> PROBE
PROBE --> EXPERIMENT: 证据达到门禁
EXPERIMENT --> VERIFY
VERIFY --> INTEGRATE: 验收通过
VERIFY --> RECON: 新证据推翻假设
INTEGRATE --> DONE
BASELINE --> BLOCKED
PROBE --> ESCALATE
EXPERIMENT --> ROLLBACK
- RECON 读取代码、文档、配置和调用链,把未知量变成事实;
- HYPOTHESIS 写出可证伪原因、支持证据、替代解释和最低成本判别方法;
- PROBE 运行最小复现或增加维测,只获取区分假设所需的信息;
- EXPERIMENT 在证据门禁通过后进行受控实验;
- VERIFY 用独立检查验证结果,不以命令退出码代替业务验收;
- INTEGRATE 整理代码、测试、中文文档和远端仓库交付。
每次定时调度只执行一个有界循环:
- 读取当前阶段、剩余验收项、预算和最高优先级未知量;
- 声明本轮唯一的
micro-goal; - 选择
READ、PROBE、EXPERIMENT或INTEGRATE; - 预先登记假设、判别条件、唯一主要变量、成本、风险和回滚;
- 执行一个主要动作,保存脱敏命令、配置、日志、指标和代码差异;
- 区分观察事实与推断,更新假设和替代解释;
- 更新验收、交付、时间、费用和错误签名;
- 主动结束本轮,说明信息增量、下一 micro-goal 和所需决策。
这套循环允许快速迭代,但不允许方向漂移。新证据推翻假设时,应回到 RECON 或
HYPOTHESIS;不能为了显得连续推进,沿错误路径继续堆叠更大的实验。
实验之前先过证据门¶
“有 70% 信心再做实验”方向正确,但百分比很容易沦为模型的自我授权。我的做法是先给 证据分级,再把百分比当作辅助解释:
| 等级 | 证据基础 | 允许动作 |
|---|---|---|
| E0(0–30%) | 猜测或弱类比 | 阅读代码、文档和低成本观测 |
| E1(40–60%) | 稳定错误栈、代码、配置或官方资料 | 最小复现和低成本 Probe |
| E2(70–80%) | 最小复现、受控探针或单变量实验 | 高成本完整实验 |
| E3(90%+) | 重复验证,主要替代解释已排除 | 集成、固化结论和交付 |
高成本实验默认需要 E2。 如果只有 E1,就先做最小加载、单卡 forward、局部 backward 或增加维测;用户可以明确豁免,但豁免、预算和风险也要进入记录。
同类失败通过错误签名去重:
第一次出现时完整归档;无新增证据时只允许再现一次,以确认稳定性。下一次运行必须
增加观测、缩小复现或进行能区分假设的单变量变化。两个循环仍没有信息增量时,停止
这条路径,返回代码调查或进入 ESCALATE。
版本问题也不能靠轮盘解决。切换前先建立 Python、框架、加速器插件、驱动、通信库、 模型代码和推理后端的兼容矩阵;候选版本必须来自 lock 文件、Dockerfile、CI、官方 兼容表、已知成功环境或已定位的 API/ABI 变化。没有新增依据时,最多测试两个候选。
OOM 则必须先回答“在哪个阶段 OOM”:
- 权重加载、rollout、KV cache、logprob、reward;
- backward、optimizer step、通信临时 buffer 或 checkpoint。
每次记录每 rank 峰值、最后成功阶段、模型层数和 dtype、batch/序列长度、并行拓扑、 activation checkpoint、optimizer state 与 KV cache。任何减层、减 batch 或缩短序列 之前,都要说明它预计减少哪一类内存、为什么与当前阶段相关、预计数量级和验证判据。
对于隐蔽分布式故障,goal-execution 固化了我原先的 TSJDEBUG 思路:每轮只在报错
附近增加 2–4 个观测点;由环境变量控制,默认关闭;日志名包含时间戳、run、rank 和
pid;只记录 shape、dtype、device、内存、分支和最后成功点。新日志返回后先更新假设,
再决定下一处观测,避免一边改业务逻辑一边改变可观测性。
把过程写成证据账本¶
聊天上下文会压缩,终端会关闭,/tmp 会被清理,因此 Goal 的事实源必须在仓库中。
默认目录是:
goal_process/<goal-id>/
├── GOAL.md
├── CURRENT_STATUS.md
├── ACCEPTANCE.md
├── DELIVERABLES.md
├── HYPOTHESES.md
├── DECISIONS.md
├── evidence/
├── runs/<timestamp>-C<cycle-id>/
│ ├── ITERATION.md
│ ├── commands.md
│ ├── stdout.log
│ ├── stderr.log
│ ├── metrics.json
│ └── changes.patch
├── reports/
└── HANDOVER.md
CURRENT_STATUS.md 是覆盖更新的一分钟摘要,运行目录则是追加式历史。每轮
ITERATION.md 都要记录 micro-goal、已有证据、唯一主要变量、预期观察、判别规则、
实际结果、错误签名、信息增量和下一步。这样新 Agent 接手时可以从状态和证据恢复,
而不是重新猜上一位 Agent 做过什么。
OpenAI Agents SDK 可以按 run 汇总 request、输入 token、缓存输入、输出 token 和
reasoning token;官方文档也提醒,第三方 adapter 的 usage 上报可能不完整。2
因此我的仓库规则要求:预计或实际超过 20 分钟的执行启用 RMB-Cost.md,把缓存未命中
输入、缓存命中输入和输出分开计价;价格、汇率或 token 明细未核实时必须标为估算。
渐进交付意味着最终路径仍未跑通,也不能“两天后什么都没有”。合理的中间成果包括:
- 工作分支、WIP 提交和明确的远端状态;
- 参考模型与目标模型的调用链差异;
- 版本兼容矩阵和最小加载脚本;
- 已完成的配置、注册、适配和单测;
- 最小失败复现、精确 OOM 阶段和分 rank 日志;
- 中文软件设计文档、运行手册和已知限制;
- 剩余候选原因、方案 A/B、资源需求和交接包。
给领导一个管理接口¶
领导不应该阅读几百 KB 日志来判断任务是否失控。CURRENT_STATUS.md 必须能直接生成
一份一分钟汇报:
状态:黄
目标:
Kimi3 减层 GRPO 在 NPU 完成首个 optimizer step。
已完成:
模型注册、减层加载、rollout 和 reward;
代码已推送到 <branch>/<sha>。
当前主阻塞:
logprob 重算后进入 backward 时 OOM,
问题已从“整体任务 OOM”收敛到具体阶段。
关键证据:
运行 C006;rank0 峰值;最后成功函数;日志路径。
时间投入:
环境 / 调研 / 实现 / 实验 / 文档交付 / 资源等待。
下一步:
C007 单变量验证 H3,一次实验可区分 activation 与通信临时 buffer。
需要决策:
若证实物理显存不足,选择增加 NPU 或调整验收范围。
“还需要多久”不能给脱离条件的单点数字。更可信的表达是:
这不是回避承诺,而是把工期的不确定性绑定到一个可验证的技术分叉。领导因此能看到: 当前主路径是否可解、哪个假设决定 ETA、什么时候必须做资源或范围决策。
两个 Skill 如何配合¶
两个 Skill 的分工刻意不重叠:
goal-definition与用户交互,生成并确认READYGoal;goal-execution读取合同,初始化过程目录,并持续执行有界循环;- Goal 的范围、验收或权限变化重新回到定义环节,不由执行者静默修改;
- 执行到期但未
DONE时,强制生成交接与决策包。
最短使用入口如下:
先使用 $goal-definition 与我澄清下面的任务。
输出 Goal 合同,明确验收标准、交付物、预算、权限、停止条件、
升级对象、汇报节奏和条件化 ETA。关键条款经我确认后再标记 READY。
任务:
[在这里填写具体任务]
Goal READY 后,使用 $goal-execution 执行。
每轮只推进一个 micro-goal;高成本实验遵守证据门禁;
所有日志、决策、验收、交付和汇报归档到 goal_process/<goal-id>/。
两个 Skill 的仓库源码通过符号链接安装到 ~/.codex/skills/。仓库是唯一可版本化源头,
全局目录只暴露入口,避免复制后形成两份漂移的执行规范。Goal 合同模板、过程文件模板
以及版本/OOM/TSJDEBUG 专项协议都随 Skill 一起维护。
适用边界¶
这套设计适合远程开发、复杂调试、训练/推理实验、多阶段代码交付和任何需要跨会话继续 的长期任务。短小、低风险、几分钟可完成的修改不必创建完整账本,否则流程成本会高于 任务本身。
它能够改善的是:
- 更早暴露未知量、权限缺口和物理资源下限;
- 减少无新证据的重复实验;
- 让失败产生可复用的负结果;
- 在最终成功前持续形成代码、文档和决策材料;
- 让领导能够看到阻塞、预算、可解性和条件化 ETA。
它不能保证上游尚未实现的能力凭空出现,也不能让不足的 HBM 容纳任意配置。若证据表明
问题在当前资源和期限内不可行,正确结果是进入 BLOCKED/ESCALATE,给出证据、替代
路径和所需决策,而不是继续运行来维持“还在努力”的表象。
证据边界
E0–E3、同签名重试一次、无依据版本候选最多两个,以及超过 20 分钟启用费用报告,都是我的本地工程规则,不是 OpenAI 或 Google 的标准。它们目前解决的是可管理性和可复核性;是否提高跨任务成功率,还需要在后续 Goal 中统计首次定位时间、重复失败率、验收完成率和交付及时率。
总结¶
我最终把 Goal 理解为一份任务合同,而不是一句循环咒语;把 Skill 理解为执行操作系统, 而不是一段领域提示;把过程目录理解为证据账本,而不是日志垃圾场;把 Deliverables 理解为渐进形成的成果,而不是最后一刻的二元答案。
一个好的 Goal Loop 不应保证永远继续,而应保证每次继续都有理由。 如果下一轮不能 完成验收、增加证据、缩小故障或形成交付,就应该改变观测方式、降低实验粒度,或者把 问题升级给能够改变资源、范围和期限的人。
最终成功当然最好;但即使没有完全跑通,系统也必须回答:为什么、卡在哪里、做过什么、 时间花在哪里、还能否解决、还要多久,以及现在已经可以交付什么。这才是 AI 长期任务 真正需要的工程闭环。
参考资料¶
-
OpenAI Agents SDK, Tracing. 文档列出了默认 run、agent、generation、function、guardrail 与 handoff spans,并支持自定义 span 和敏感数据控制。 ↩
-
OpenAI Agents SDK, Usage. 文档说明每次 run 可汇总 request、input、cached input、output 和 reasoning token,同时提醒第三方 adapter 的 usage 上报可能不完整。 ↩
-
Chris Jones, Google SRE Book, Effective Troubleshooting. 本文借鉴其观测、假设、受控测试、最小复现和记录原则;具体 Goal 阈值是本地设计。 ↩
