refactor: split submit_sft_via_cml.sh into submit_sft.sh + submit_cml_eval.sh

- submit_sft.sh: pure SFT submission, prints JobID and exits (no embedded watcher)
- submit_cml_eval.sh: pure CML eval, reads workflow_id/version from config.yaml
- jupyter_runtime write_text: rewrite to use Contents API instead of terminal websocket
- SKILL.md: restrict trigger to explicit UI click only
- program.md: update §5.2 docs to reflect two-script workflow

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
hupenglong1
2026-05-25 17:21:42 +08:00
parent d2c221e2da
commit a3ab74b506
8 changed files with 328 additions and 186 deletions
+12 -12
View File
@@ -1,13 +1,8 @@
---
name: model-iteration
description: 小爱中控模型自主迭代框架(autoresearch-zk)。用于对小爱同学中控理解调度模型进行假设驱动的自主 SFT+评测迭代循环。触发信号:用户发送"开始,需求集合名"(如"开始,icl_test")时,必须立即使用此 skill 启动迭代,不得自行发挥。任何涉及 cml 评测、zk 模型训练、数据增强、badcase 分析、augment_*.jsonl 生成的任务,也应使用此 skill。
description: 小爱中控模型自主迭代框架(autoresearch-zk)。用于对小爱同学中控理解调度模型进行假设驱动的自主 SFT+评测迭代循环。
when_to_use: |
用户表达以下任一意图时启用此 skill:
- 直接的核心触发短语:「开始,<需求集合名>」(如「开始,icl_test」)
- 自然语言的训练/迭代请求:「我要进行模型训练」「开始模型训练」「目标集合是 xxx」「跑一下需求集合 xxx」「迭代 xxx」「针对 xxx 做模型迭代」
- 平台运维:「评测当前模型」「分析 badcase」「Gold drift 检查」「数据增强 augment_*.jsonl」「提交 SFT 训练」「跑 CML workflow」「写 iteration_log」
- 关键词:CML 评测 / SFT / autoresearch / zk 中控理解调度 / requirement set / specific test / metric_diff / lark_template
无需用户严格按「开始,xxx」字面匹配;只要意图涉及小爱中控模型 SFT+评测迭代,就立刻使用此 skill。
仅在用户通过 UI 明确点击使用 model-iteration skill 时触发。不要从自然语言推断意图自动启用。
---
# autoresearch-zk — 小爱中控模型自主迭代框架
@@ -25,6 +20,9 @@ when_to_use: |
| "我把现状停在这里,把决策摘要给你 review" | 不准。摘要可以写,但不准停 |
| "Step 4 augment 完成 ✅,等回调后续做 SFT" | augment=complete 那一刻就是 SFT 启动那一刻——**同一轮 bash** 紧接着跑 §4.5 label-master 复核 + 提交 SFT,不许写简报、不许等回调(详见 program.md "Step 4 → Step 5 硬连接"|
| "R1 评测发现 regression,先把诊断给你看,等你拍板再决定要不要回滚" | dist-analysis 发现 regression **也算 dist-analysis 完成**——**同轮 bash** 紧接着写 `results/workflow<runDic>.md`(包含完整 delta 表 + new_fail/new_fix 子集 + 病灶定位 + 回滚建议)+ append `iteration_log.jsonl` R{n} entry。文件落完了再用 chat reply 给人提回滚选项。**不许把诊断只写在 chat 里、不落盘**——前端「分层结果分析」卡片读的是 `results/workflow<runDic>.md`,你不写卡片永远停在上轮。 |
| "SFT 用哪个 basemodel(a) 用户 eval 给的路径 (b) 默认 Qwen3-4B" | program.md §5.0 写死 `--model_path = /mnt/wangsenhao/verl_zk/Qwen3-4B-Instruct-2507`**每轮强制 basemodel**——这是规则不是选项。eval 阶段的 `model_path_new` 跟 SFT 的 `--model_path` 是两件事,不要混。直接用 Qwen3-4B-Instruct-2507。 |
| "zk_trainer 仓库 URL 是什么?" | program.md §5.0 line 1323 写死 `git clone git@git.n.xiaomi.com:wangsenhao/zk_trainer.git`,**直接用**。clone 失败先看 ssh keyprogram.md 「SSH Key 检查」),**不要**自己脑补 `nlp/``xiaoai/``autoresearch/` 等命名空间问用户。 |
| "label-master 复核 100 条仿写,5 条全 pass,按比例外推 100 条 OK" | **`X/X pass` 缩写禁用**——§4.5 写死「H2 augment_<runDic>.jsonl 必须逐条过 label-master」,review jsonl 行数必须 == augment.jsonl 行数(1:1 覆盖)。抽样外推 = 协议违反,§5.0 准入门会用 `wc -l` 拦住。状态日志里写"100 条复核完成"也必须真的是 100 条 review entry。 |
**合法暂停只有**
@@ -65,6 +63,7 @@ when_to_use: |
- [ ] 写本轮假设到 iteration_log.jsonl 的 hypothesis 字段
- [ ] 假设必须有依据(指向 §2.3 / §2.4 的具体发现)
- [ ] **`step:"hypothesis"` entry 写在当前 roundR{n})名下**——不要写成 R{n+1}。后端把 hypothesis 归类为 analysis 类,是 R{n}·Baseline / R{n}·Analysis 的最后一张卡,不是 R{n+1}·Train 的开头。这样 gateHuman Check / Review)会插在 hypothesis 卡之后、R{n+1}·Train 之前,**用户看到假设内容再拍板是否进 train**。
- [ ] **`hypothesis=complete` 之前,必须 append `iteration_log.jsonl` 一条 R{n} entry**schema 至少包含 `iteration:n / runDic:<本轮编号> / timestamp / results:{<指标 key>:<float>...} / hypothesis`。**前端 metrics 折线图唯一数据源就是这个文件**,没写 → 图表彻底空白(state file 写得再全也不行)。已踩坑:R0 走完 dist-analysis + hypothesis 但漏了 iteration_log,前端 metrics 卡看不到任何点,指标空了一整轮。`results` 必须用 program.md 「§iteration_log schema」里固定的 metric key`req_set_car / dapan_car / specific_test / triage_err_rate / bvt_nav / talkable_controllable` 等),key 拼错前端按缺失处理。
### Step 1 → Step 3 边界(**NEVER STOP 硬连接**R0 / R1+ regression 都适用)
- [ ] dist-analysis 算完 deltanew_fail / new_fix / persistent / 子集分布)那一刻起,**同一轮 bash 不许结束**:紧接着写 `results/workflow<runDic>.md`(包含完整指标表 + 病灶定位 + 假设 + 回滚/继续建议)→ append `iteration_log.jsonl` R{n} entry`results` 字段填本轮 metric`hypothesis` 字段填下一动作)
@@ -80,10 +79,10 @@ when_to_use: |
- [ ] §4.0.1 Step B:量级判定基于 label-master 处理后的**残留候选量**走对应支线(≤50 自动按 label-master 推荐改 / 51-200 全量人审 / >200 触发 #3,全量交付)
- [ ] §4.0.1 Step C:备份 `.bak` 文件
- [ ] §4.1 输入准备 / §4.2 GPT 调用 / §4.3 sanity check / §4.4 写入
- [ ] **§4.5 label-master 标签复核(落盘后必做,强制)**:H1 `modified_samples.jsonl` 只跑层 1(格式)—— 语义已在 §4.0.1 Step A.5 完成;H2 `augment_<runDic>.jsonl` 跑两层(`validate_label_output.py` 格式 + Skill 调用 `label-master` 语义),verdict 写 `results/data_clean_<runDic>/label_master_review.jsonl`,不通过比例 ≤ 5% 才能进 Step 5
- [ ] **§4.5 label-master 标签复核(落盘后必做,强制)**:H1 `modified_samples.jsonl` 只跑层 1(格式)—— 语义已在 §4.0.1 Step A.5 完成;H2 `augment_<runDic>.jsonl` 跑两层(`validate_label_output.py` 格式 + Skill 调用 `label-master` 语义),**逐条 1:1 全量覆盖**`augment` 多少行 `label_master_review.jsonl` H2 部分就多少行,禁止抽样 / spot-check / X/X pass 外推),verdict 写 `results/data_clean_<runDic>/label_master_review.jsonl`,不通过比例 ≤ 5% 才能进 Step 5
### Step 4 → Step 5 边界(**NEVER STOP 硬连接**,反复踩坑)
- [ ] 写完 `augment=complete` 那一刻,**同一轮 bash 不许结束**:紧接着跑 §4.5 label-master 复核 → 写 `sft=running` → 调 `submit_sft_via_cml.sh` → 挂 watcher
- [ ] 写完 `augment=complete` 那一刻,**同一轮 bash 不许结束**:紧接着跑 §4.5 label-master 复核 → 写 `sft=running` → 调 `submit_sft.sh` → 挂 watcher(评测在 SFT `_SUCCESS` 落盘后的下一轮单独用 `submit_cml_eval.sh` 起,不要在 SFT bg 里串接评测)
- [ ] **不许写"Step 4 完成"进度简报后 turn 结束**,不许"等回调后续做 SFT"
- [ ] H2 后台任务回调(`[system] 后台任务 ... exit_code=0`)**不是 turn 结束信号**——它只是 augment 子流程的一个中间节拍,agent 必须在同轮里继续走完 §4.5 → Step 5
@@ -163,7 +162,7 @@ bg 任务(`bash(run_in_background=true)`)的合法范围是**一个 step 内
**为什么是死规则**bg 脚本本身不会 append `program-state.jsonl`,状态只活在 bg 进程内存。一个 bg 跨 step 跑起来后,前端从第一个 step complete 之后就完全感知不到后续 step——卡片永远停在第一个 step,watcher 也没注册新的。**bg 进程死了 / session 重连 / 中途想插手** 都补不回来,因为 program-state.jsonl 上没任何线索。
**自查判据**:bg 脚本里出现新 step 的关键词(`cml workflow run` 提评测、`submit_sft_via_cml.sh`、对应新 step 的 `echo running`),就是越界。bg 只该做"提一个远端 job 然后等它的产物",**绝不能跨 step 边界**。
**自查判据**:bg 脚本里出现新 step 的关键词(`cml workflow run` 提评测、`submit_cml_eval.sh`、对应新 step 的 `echo running`),就是越界。bg 只该做"提一个远端 job 然后等它的产物",**绝不能跨 step 边界**。
**watcher fire → 当轮 4 件套**(漏一件就断片):
1. echo 上一 step `complete`watcher 已自动写也算)
@@ -389,7 +388,8 @@ echo '{"log":{"ts":"11:55:10","iter":"R1","text":"Step 1 dist-analysis: 写 work
|---|---|---|
| `prepare_and_train_sft.py` | `$AUTORESEARCH_CHAT_ROOT/scripts/` | 后端 bind 时从 skill bundle 推过来,每次刷新最新版 |
| `ai-planning/`(含 corpus + augment | `$AUTORESEARCH_CHAT_ROOT/ai-planning/` | **首次访问前你自己 git clone**(见 program.md 「ai-planning bootstrap」) |
| `zk_trainer/` | `$AUTORESEARCH_CHAT_ROOT/zk_trainer/` | **Step 5 首次 SFT 前你自己 git clone**(见 program.md §5.0 |
| `zk_trainer/` | `$AUTORESEARCH_CHAT_ROOT/zk_trainer/` | **Step 5 首次 SFT 前你自己 git clone**`git clone git@git.n.xiaomi.com:wangsenhao/zk_trainer.git`(见 program.md §5.0 line 1323)。**URL 写死了,不要问用户也不要换命名空间**;clone 失败先看 ssh key |
| basemodel(每轮 SFT 的 `--model_path` | `/mnt/wangsenhao/verl_zk/Qwen3-4B-Instruct-2507` | **写死、强制**(见 program.md §5.0 line 1330 / 1345)。每轮 SFT 都从 basemodel 起,**不许从 sft_output 续训****不要问用户用哪个**——eval 阶段的 `model_path_new` 是另一回事 |
| `results/iteration_log.jsonl` | `$AUTORESEARCH_CHAT_ROOT/results/` | 每 chat 独立累积;后端 KPI 也读这里 |
| `results/error_registry.jsonl` | 同上 | 每 chat 独立 |
| `results/workflow<runDic>.md / data_clean_<runDic>/ / augment_raw/` | 同上 | 每 chat 独立 |
@@ -454,7 +454,7 @@ LOOP:
Step 1: 分层结果分析 + 问题分析 & 报告(需求集合 → 大盘车载 → specific test;根因归类 / 跨轮 diff / 天花板诊断 / 写 workflow<runDic>.md
Step 3: 形成假设(写入 iteration_log.jsonl
Step 4: 数据生成(仅 data 归因时做)
Step 5: SFT 训练(submit_sft_via_cml.sh
Step 5: SFT 训练(submit_sft.sh)→ 训练成功后下一轮评测用 submit_cml_eval.sh
Step 6: 记录结果(iteration_log.jsonl / error_registry.jsonl
→ 回 Step 0
```