--- name: model-iteration description: 小爱中控模型自主迭代框架(autoresearch-zk)。用于对小爱同学中控理解调度模型进行假设驱动的自主 SFT+评测迭代循环。触发信号:用户发送"开始,需求集合名"(如"开始,icl_test")时,必须立即使用此 skill 启动迭代,不得自行发挥。任何涉及 cml 评测、zk 模型训练、数据增强、badcase 分析、augment_*.jsonl 生成的任务,也应使用此 skill。 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。 --- # autoresearch-zk — 小爱中控模型自主迭代框架 ## 🚫 严禁问用户的事(违反任一条 = 违反 skill) 每次问用户都让用户烦。program.md 已经把"什么时候停"写得很死(17 类 HiTL 信号 + 用户主动打断),**这之外一律不准停下来等确认**。下面是被反复踩坑的"擅自暂停"模式,**全部禁止**: | ❌ 禁止说的话 | ✅ 正确做法 | |---------|---------| | "要不要我做训练集近邻检索?" | 这是 §2.3 分析必做项,**直接做**,做完把结果落 report | | "下一步可以继续吗?" | 永远不问。看 program.md 流程图自己判断 | | "我先把控制权交回,等你来问跑完了吗" | watcher 接手 UI 同步,你还是要在 bash 内 sleep+poll 等 cml 完,看到 complete **直接进 Step 1** | | "这一步是关键决策点,需要你拍板" | program.md 没写就不是。**自主决策 + 落 iteration_log** | | "我把现状停在这里,把决策摘要给你 review" | 不准。摘要可以写,但不准停 | **合法暂停只有**: 1. program.md `## Human-in-the-Loop 时机` 章节的 7 类迭代级信号 2. `### 训练集调整专项 H-i-T-L 信号` 的 T1-T10 3. **§4.0.1 Step B 量级判定的 HiTL 分支**: - 候选量 51-200 条 → **必须**抽样 30-50 条到飞书 sheet 让人审 1/0,按比例外推(**这就是一次合法暂停**,不是擅自停) - 候选量 >200 条 → 命中触发条件 #3,强制 HiTL 介入让人定更精细 pattern 收窄 4. 用户主动发消息打断 这之外**所有**"我觉得这事大、我先停"的本能都要压下来。命中合法暂停时,**不要只是说"等你确认"**——按 §4.0.1 把抽样表/精细 pattern 的具体输出 dump 到飞书 / scratchpad 给人具体可审的东西,再停。 ## 📋 每个 Step 的强制准入条件(少一项不准进下一步) 按 Step 编号,**进入下一 Step 前**必须把当前 Step 的准入清单全部完成并落到 state file / iteration_log,否则视为跳步违规。 ### Step 0 准入 - [ ] cml 环境检查通过(`which cml` + `cml config show`) - [ ] runDic 已分配(扫 `run_history_dir` 取 max+1) - [ ] CML workflow 已提交(拿到 Execution ID) - [ ] watcher 声明已写入 program-state.jsonl - [ ] 在 bash sleep+poll 等到 cml=complete ### Step 1 准入(`dist-analysis`) - [ ] 读 `metric_diff/lark_template.json` 提分层指标(specific / 大盘车载 / 目标专项) - [ ] 读 `metric_diff/specific_comparison.csv` 抽 baseline 错误分布 - [ ] **§2.3 失败 case 与训练数据的关联**:每条错例在 `train_set/zk_intent/*.jsonl` 做近邻检索(前 3 近邻),输出"有近邻 / 无近邻"分类 - [ ] **§2.3 Reward 对齐检查**:抽 10 条失败 case 用 `zk_reward_fn` 验 reward 方向 - [ ] §0.1 Gold drift 检查(如未做) ### Step 2 准入(`report`) - [ ] §2.4 根因归类表(每个 pattern 必归一类,可并列但要主次) - [ ] 写入 `results/workflow.md` - [ ] error_registry 追加本轮错误 ### Step 3 准入(`hypothesis`) - [ ] 写本轮假设到 iteration_log.jsonl 的 hypothesis 字段 - [ ] 假设必须有依据(指向 §2.3 / §2.4 的具体发现) ### Step 4 准入(`augment`,需要修改训练集才进) - [ ] **§4.0 原始训练数据清洗(增强前必做)**——按 4 种动作走完逐 pattern 判定 - [ ] §4.0.1 Step A:候选定位输出 csv,**不直接改** - [ ] §4.0.1 Step B:量级判定走对应支线(≤50 自动 / 51-200 抽样审 / >200 触发 #3) - [ ] §4.0.1 Step C:备份 `.bak` 文件 - [ ] §4.1 输入准备 / §4.2 GPT 调用 / §4.3 sanity check / §4.4 写入 ### Step 5 准入(`sft`) - [ ] 旧 sft_output 已 `mv sft_output sft_output_r{prev}` 备份 - [ ] 训练参数从 config.yaml 读,model_path = basemodel(**不从上轮 ckpt 续训**) ### Step 6 准入(`log`) - [ ] iteration_log.jsonl 完整 schema(hypothesis / intervention / prediction / results / verdict / root_cause_findings / error_delta / next_hypothesis) ### 跳步检查 每次写 `{step:"X","status":"running"}` 前,**先看 state file 上一条 step 是不是 complete**。如果上一条还在 running 或者跳过了某个 Step,**回去补**,不要往前走。 ## ⚠️ Pipeline UI 同步约定(强制,必读) **平台用户实时盯着 pipeline UI 看你跑到哪一步**。卡片状态完全靠你写 `program-state.jsonl` 驱动;**你不写、卡片不动;你嘴上说 running、文件里写 failed,UI 就显示 failed**。所以下面这些是**硬性纪律,不是建议**: ### R1(最重要)— 每一次状态切换都必须先 echo 再做事 进入新 step 之前,**第一件事**就是 append 一行 `running`。完成后**最后一件事**是 append 一行 `complete`。失败时也必须 append `failed`。**永远不要"嘴上"宣布状态切换却没落盘**。 错误示范(你不许这样): > 我现在开始 step 0,跑 CML 评测... \[执行很多操作\]... 已完成 ✅ 正确示范: > ```bash > echo '{"step":"cml","status":"running","ts":"'$(date -Iseconds)'"}' >> "$SESSION_OUTPUT/program-state.jsonl" > ``` > *(然后才执行 step 0 的具体操作)* > ... > ```bash > echo '{"step":"cml","status":"complete","ts":"'$(date -Iseconds)'"}' >> "$SESSION_OUTPUT/program-state.jsonl" > ``` ### R2 — 写入即生效,最后一行覆盖前面 后端按 `step` 字段取**最后一条**状态。如果你之前写过 failed、现在恢复了,**必须 append 一条新的 `running`**,否则 UI 永远停在 failed。 ### R3 — Step 之间不允许跳步骤而不留状态 进入 dist-analysis 前必须确认 cml 状态已写到 `complete`(或显式 `failed` 后用户决定继续)。 ### R4 — 中长任务用 progress 字段更新 CML 评测、SFT 训练这种几分钟以上的任务,**每次轮询/心跳时附带 progress 字段**写一条新的 `running` 行(旧 running 不需删,最后一行最新): ```bash echo '{"step":"cml","status":"running","progress":0.4,"ts":"'$(date -Iseconds)'"}' >> "$SESSION_OUTPUT/program-state.jsonl" ``` UI 卡底部进度条会跟着动;不写就一直显示初始进度。 ### State 文件位置 ``` <当前会话目录>/output/program-state.jsonl ``` 会话目录在系统提示的 `[当前会话目录]` 里给了绝对路径。**直接用那个值**,不要拼。**绝对不要**写到 `/mnt/wangsenhao/...` 或项目根目录——多会话互相覆盖。 每次写之前先确保目录存在: ```bash SESSION_OUTPUT="<从系统提示拷过来>/output" mkdir -p "$SESSION_OUTPUT" ``` ### Step key 表(必须用这套 key,否则匹配不到卡片) | step key | 对应卡片 | |----------|----------| | `cml` | CML 评测 | | `gold-drift` | Gold Drift | | `dist-analysis` | 分层结果分析 | | `report` | 问题分析 & 报告 | | `hypothesis` | 形成假设 | | `augment` | 数据增强 | | `verify` | 修改返回验证 | | `sft` | SFT 训练 | | `log` | 记录迭代日志 | | `next-round` | 下一轮评测 | ### KPI(你不要写,后端读权威源) 顶部 7 个 KPI(RUN ID / VERSION / 目标集合 / 大盘车载 / SPECIFIC TEST / ITERATION / 耗时)由后端从权威源直接读取: | KPI | 后端读取自 | |-----|-----------| | RUN ID | `RUN_HISTORY_DIR`(默认 `/mnt/xiaoai-zk-model-train-tj5/workflow5/`)下 `workflow/` 取 max N | | VERSION | `skills/model-iteration/assets/config.yaml` 的 `cml_eval.version` | | 目标集合 | 从 session 最新 user 消息里解析 `"开始, "` 中的 name | | 大盘车载 / SPECIFIC TEST | `RUN_HISTORY_DIR/workflow/metric_diff/lark_template.json` | | ITERATION | `/results/iteration_log.jsonl` 行数 | | 耗时 | program-state.jsonl 第一条 `{step:"cml",status:"running"}` 的 `ts` 到现在 | **你不要再写 `{"kpi":...}` 行**——写了也会被后端忽略,不显示。如果想让用户看到某个 KPI 的当前值,把它落到对应的权威源(比如改 config.yaml、写 iteration_log),后端会自动读到。 ### Watcher(长任务的 UI 状态副车,**不是给你交回控制权的借口**) CML 评测 / SFT 训练这类几分钟到几十分钟的长任务,声明 watcher 让**后端自动检测产物文件并把 `step=complete` 写到 state file**——这样 UI 的卡片状态不依赖你主动写 complete,watcher 替你写。 但你**仍然必须留在当前迭代里继续干活**,遵守 program.md 里的 **NEVER STOP / 全程不打断用户** 原则: - **不许**给用户回"控制权交回 / 我先停下 / 等你来问"这种话 - **不许**主动结束本轮(除非命中 program.md 里写明的 H-i-T-L 阻断信号) - 提交完任务、声明完 watcher 后,**继续在 bash 里轮询 state file** 等 cml=complete,看到就**直接进入 Step 1**(读 metric_diff、做分层分析、写报告等),一气呵成跑完整轮迭代 watcher 解决的是 **UI 与 agent 异步**:UI 不用等 agent 写状态,watcher 替 agent 把 complete 落盘。它不是替你"放假"。 格式: ```bash # 进入 step 时按规则写 running echo '{"step":"cml","status":"running","ts":"'$(date -Iseconds)'"}' >> "$SESSION_OUTPUT/program-state.jsonl" # 紧接着声明 watcher:当目标文件出现 → 后端自动写 cml=complete echo '{"watch":{"step":"cml","kind":"file_exists","path":"/mnt/xiaoai-zk-model-train-tj5/workflow5/workflow17782/metric_diff/lark_template.json","interval":30,"timeout":3600,"run_id":"R0"}}' >> "$SESSION_OUTPUT/program-state.jsonl" ``` 字段: | 字段 | 必填 | 说明 | |------|------|------| | `step` | ✅ | 跟卡片 step key 一致(cml / sft / augment ...) | | `kind` | ✅ | 当前只支持 `file_exists` | | `path` | ✅ | 目标文件**绝对路径**。文件出现就视为 step 完成 | | `interval` | ⭕ | 轮询间隔秒,默认 30,最小 2 | | `timeout` | ⭕ | 整体超时秒,默认 3600,超时写 failed | | `run_id` | ⭕ | 写入 Live Log 时的 iter 标签 | **watcher 资源管理**: - 同一 (session, step) 已有 watcher 在跑时,重复声明被忽略 - step 已经有 complete/failed 行后,watcher 声明会被忽略 - 后端 scanner 5 秒扫一次所有会话的 state file **典型用法**(CML workflow,**NEVER STOP**): ```bash # 1. 提交 cml 任务(异步,立刻返回 runDic) RUNDIC=$(cml workflow run --workflow_id "$WORKFLOW_ID" ...) # 2. 写 running + watcher 声明 echo '{"step":"cml","status":"running","ts":"'$(date -Iseconds)'"}' >> $S echo '{"watch":{"step":"cml","kind":"file_exists","path":"'$ROOT/workflow$RUNDIC/metric_diff/lark_template.json'","interval":30,"timeout":7200,"run_id":"R'$N'"}}' >> $S # 3. 跟用户简报一句状态,**不要说"交回控制权"**,紧接着开始等 echo "已提交评测 runDic=$RUNDIC,开始轮询 state file 等 watcher 写 complete..." # 4. 在 bash 里轮询 state file(不阻塞你下一步思考) while true; do status=$(grep -E '"step":"cml"' $S | tail -1 | python3 -c 'import json,sys; print(json.loads(sys.stdin.read()).get("status",""))') if [ "$status" = "complete" ]; then break; fi if [ "$status" = "failed" ]; then echo "cml failed"; exit 1; fi sleep 60 done # 5. cml 完成 → 立刻进入 Step 1,读 metric_diff、做分析、写下一步 running... # 整轮迭代不交回控制权,直到达标 / 命中 H-i-T-L 阻断 / 用户主动打断 ``` ### Live log(可选) 要把日志推到 UI 底部那块黑色 Live Log 区,追加: ```bash echo '{"log":{"ts":"11:55:10","iter":"R3","text":"Step 3 开始: 问题分析 & 报告生成"}}' >> "$SESSION_OUTPUT/program-state.jsonl" ``` ### 不要做的事 - **不要**写 program.md(旧机制已废弃,写了也没用,平台现在不读它)。 - **不要**把 state 文件写到 `/mnt/wangsenhao` 或仓库根目录——只写当前会话的 `output/program-state.jsonl`。 - **不要**用与上表不一致的 step key(比如 `step:"评测"`、`step:"step0"`),UI 匹配不到。 - **不要**重写整个文件(每行只追加,append 即可),重写会导致 UI 闪。 ## 快速参考 | 项目 | 值 | |---|---| | 触发信号 | `"开始,<需求集合名>"` | | 评测 workflow | `f-20260408161444-wu3pz`(版本见 `config.yaml`) | | 训练基模 | `/mnt/wangsenhao/verl_zk/Qwen3-4B-Instruct-2507` | | 工作目录 | `/mnt/wangsenhao/autoresearch-zk` | | 历史记录目录 | `/mnt/xiaoai-zk-model-train-tj5/workflow5/` | | 需求集合位置 | `https://git.n.xiaomi.com/ai-service/ai-planning/-/tree/autoresearch-v1` 下 `ai-planning/data/specific_test_set/` | ## 核心原则 1. **评测优先**:`"开始"` 信号的第一个动作永远是评测当前模型,绝不直接训练 2. **假设驱动**:每轮必须能回答"这轮验证了什么?学到了什么?下一轮改什么?" 3. **NEVER STOP**:全程不打断用户,循环直到达标或人类主动打断 4. **从 basemodel 训练**:每轮 SFT 的 `--model_path` 必须是 basemodel,禁止从上轮 ckpt 继续训 ## 达标条件 - **需求集合** ≥ 95%(最高优先级) - **大盘集(车载)** 降幅 ≤ 0.3% - **specific test** 降幅 ≤ 1% ## 主流程 读取 `references/program.md` 获取完整的 Step 0-7 迭代循环规范。在任何操作前必须读取该文件。 每个 step 的执行模板(**强制**,配合上文「Pipeline UI 同步约定」R1): ```text 1. echo '{"step":"","status":"running","ts":"..."}' >> $SESSION_OUTPUT/program-state.jsonl 2. (执行该 step 的实际操作 / 调用工具 / 等结果) 3. 成功: echo '{"step":"","status":"complete","ts":"..."}' >> ... 失败: echo '{"step":"","status":"failed","error":"...","ts":"..."}' >> ... ``` step key 跟 Step 编号映射: | Step | step key | 说明 | |------|----------|------| | Step 0 | `cml` | CML 评测当前模型 | | Step 0 (附带) | `gold-drift` | Gold drift 检查 | | Step 1 | `dist-analysis` | 分层结果分析 | | Step 2 | `report` | 问题分析 & 报告 | | Step 3 | `hypothesis` | 形成假设(写 iteration_log) | | Step 4 | `augment` | 数据增强 / 生成 | | Step (干预后) | `verify` | 修改返回验证 | | Step 5 | `sft` | SFT 训练 | | Step 6 | `log` | 记录迭代日志 | | 循环 | `next-round` | 回 Step 0 评测新 ckpt | ``` LOOP: Step 0: CML 评测(当前模型)+ Gold drift 检查 Step 1: 分层结果分析(需求集合 → 大盘车载 → specific test) Step 2: 问题分析 & 报告(根因归类 / 跨轮 diff / 天花板诊断) Step 3: 形成假设(写入 iteration_log.jsonl) Step 4: 数据生成(仅 data 归因时做) Step 5: SFT 训练(submit_sft_via_cml.sh) Step 6: 记录结果(iteration_log.jsonl / error_registry.jsonl) → 回 Step 0 ``` ## 文件结构 ``` references/ program.md # 完整迭代循环规范(必读,包含所有 Step 的详细说明) knowledge/ navigation_routing_rules.md # 地图导航 Agent/CT 分流规则 travel_routing_rules.md # 旅游 Agent/CT 分流规则 multi_command_rules.md # 多指令 vs ComplexTask 分流规则 multiturn_continuity_rules.md # 多轮对话 CT 继承规则 scripts/ prepare_and_train_sft.py # 数据组装 + SFT 训练脚本 assets/ config.yaml # 评估阈值 + CML workflow 配置 ``` ## 何时读取各文件 | 操作 | 读取 | |---|---| | 启动迭代前 | `references/program.md`(完整流程,必读) | | badcase 归类 / 数据增强标注时 | `references/knowledge/` 下对应规则文件 | | 数据组装 / 训练前 | `scripts/prepare_and_train_sft.py`(了解脚本参数) | | 评测阈值 / workflow 版本 | `assets/config.yaml` | ## Human-in-the-Loop 信号(需暂停问人) 共 7 类迭代级信号 + 10 类训练集调整信号(T1-T10),详见 `references/program.md` 的"Human-in-the-Loop 时机"章节。 **最常触发的**: - Gold drift ≥ 10 条(#1) - 要批改旧标签 > 50 条(#3 / T1) - 跨子集净退步(#4) - 连续 3 轮目标子集净提升 ≤ 0.5pp(#5) ## CML 配置(快速查阅) ```yaml # ~/.config/cloudml/config.yaml default_config_context: cloudml5-config xiaomi_cloudml: cloudml5-config: xiaomi_auth_type: key xiaomi_cloudml_endpoint: https://cnbj6-cloudml5.api.xiaomi.net xiaomi_cloudml_workspace_id: 10065 ``` ## 结果文件 | 文件 | 用途 | |---|---| | `results/iteration_log.jsonl` | 每轮假设/干预/判定完整记录 | | `results/error_registry.jsonl` | 跨轮错误追踪(case_hash → 出错轮次) | | `results/workflow.md` | 每轮回归分析报告 | | `results/augment_raw/augment__raw.jsonl` | GPT-5.4 原始生成产物 | | `ai-planning/data/train_set/zk_intent/augment_.jsonl` | 清洗后的增量训练数据 | | `results/data_clean_/` | 旧数据清洗存档(必须在覆盖原文件前写入) | | `results/gold_drift/drift_.json` | Gold drift 检测结果 | | `results/label_rules.md` | 已确立的标签规则集(R1~RN) |