fix: pipeline排序/runDic映射/label-master repeatable/达标优先级

- pipeline items 按 first_ts 自然时间排序,去掉 hardcoded section_order
- augment step-detail 去掉 R{n-1} 偏移,直接用本轮 runDic(与 resolve_run_ids.sh 实际行为对齐)
- 加 BundledSkill.repeatable 字段,label-master 标记 repeatable:true 跳过 duplicate detection
- SKILL.md/program.md: 目标集≥95%最高优先级,未达标前其他集合轻微下降不回滚
- SKILL.md/program.md: 禁止正则脚本替代 label-master 语义复核
- program.md: 每轮 SFT 前必须展示训练数据组成
- resolve_run_ids.sh: 修正注释(SFT_RUNDIC = 当轮 eval workflow id)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wangsenhao
2026-05-26 14:10:32 +08:00
parent d2bb525e38
commit a09d4afacd
7 changed files with 103 additions and 32 deletions
+31 -8
View File
@@ -178,13 +178,17 @@ for k in prev:
3. **specific test**
**达标条件**
- 需求集合 ≥ 95%
- 大盘集(车载)降幅 ≤ 0.3%
- specific test 降幅 ≤ 1%
- 需求集合(目标集) ≥ 95%**最高优先级**
- 大盘集(车载)降幅 ≤ 0.3%(次要)
- specific test 降幅 ≤ 1%(次要)
⚠️ **优先级铁律**:目标集上 95% 是主线任务。只要目标集还没到 95%,其他集合的轻微下降(大盘 ≤1%、specific ≤2%)**不构成回滚理由**,应继续迭代优化目标集。只有目标集已达 95% 后,才需要关注并修复其他集合的 regression。
**决策**
- 全部达标 → 部署(`python modules/cloudml_deploy.py <rl_checkpoint>`),记录,循环结束
- 达标 → 在 Step 1 内继续做问题分析(见下文),**分析顺序:需求集合 → 车载大盘 → specific test**
- 目标集未达标 → 继续迭代(即使其他集合有轻微下降也不回滚)
- 目标集已达标但其他集合超限 → 微调修复其他集合
- 分析顺序:**需求集合 → 车载大盘 → specific test**
> **首次评测差异**:由于新旧模型相同,"降幅"和"vs 基线"无意义(均为 0)。此轮只记录各集合的**绝对准确率**作为 baseline,不做达标/不达标判定,不触发部署。直接在 Step 1 内分析基准模型的错误分布,为后续迭代建立对照基准。
@@ -655,6 +659,12 @@ for r in b_rows:
> 若 Step 1 显示全部达标 → 跳过 Step 3–5,直接部署。
> ⛔ **CRITICAL: hypothesis=complete 后禁止空手结束 turn**。写完 hypothesis 到 program-state.jsonl 之后,当前 turn 内必须做下面两件之一(不能都不做就结束):
> - 命中 HiTL → 写 `human-check` gate entry (running) → chat reply 给用户选项
> - 不命中 HiTL → 写 `augment=running` → 开始 Step 4
>
> **"turn 预算不够"不是合法理由**——没有自动 wake 机制,turn 结束 = session 永久停止。已踩坑:agent 在 R0 hypothesis=complete 后误判"turn 用满"而空手结束,用户看到 pipeline 卡在 hypothesis 不动、无任何后续(session `qf1ni1jh`25/50 turns 实际只用一半)。
### 4. 数据生成(GPT-5.4 从 badcase 增强)
**只在 §2.4 归因为 `data` 时做。** 其他归因直接跳过 Step 4,按下表路由:
@@ -743,18 +753,19 @@ with open(out_csv, 'w', encoding='utf-8-sig') as fp:
候选阶段(246 条等量级)的 CSV 必须写到 `output/relabel_candidates_<runDic>.csv` 让分析卡片可读;确认修改阶段(用户审核后落盘的 135 条)写入 `results/data_clean_<runDic>/modified_samples.jsonl` 让数据增强卡片可读。**不要混落**——把候选 CSV 写到 `/tmp/` 或 `data_clean_/` 都会让 UI 看不到。
> **runDic 命名语义(backend 已对齐,改 backend 时勿 revert**augment 类产物(`data_clean_<N>/`、`augment_raw/augment_<N>_raw.jsonl`、`zk_intent/augment_<N>.jsonl`、`label_master_review.jsonl`)的 `<N>` 永远是**「源轮次的 runDic」**,也就是 `R{n-1}.runDic`——agent 在 R{n} 跑 augment 时处理的是 R{n-1} 评测落地的错例,文件命名沿用 R{n-1} 的 workflow id。Backend step-detail 端点 (`server.py` 内 `_step_artifact_paths('augment', ...)` 调用方) 在 `step=='augment'` 时也是查 `R{n-1}` 的 runDic,跟落盘命名一一对应。其他 stepcml / dist-analysis / hypothesis / gold-drift)的产物按本轮自己的 runDic 命名,没有偏移。**不要把 augment 产物改名成 R{n} 的 runDic**——会同时打破历史归档和 backend 解析
> **runDic 命名语义(backend 已对齐)**augment 类产物(`data_clean_<N>/`、`augment_raw/augment_<N>_raw.jsonl`、`zk_intent/augment_<N>.jsonl`、`label_master_review.jsonl`)的 `<N>` = `$SFT_RUNDIC` = **当轮 eval 落盘后 `resolve_run_ids.sh` 取到的 max(已落盘 workflow)**。由于 resolve 是在当轮 eval 的 `lark_template.json` 落盘之后调用的,此时 max 就是当轮 eval 自身的 workflow id。Backend step-detail 端点对 augment 也直接用本轮(`per_round[R{n}]`的 runDic 去读。其他 stepcml / dist-analysis / hypothesis / gold-drift)的产物同理按本轮自己的 runDic 命名。
>
> ⚠️ **runDic 不许手算**augment 落盘、SFT yaml、归档目录、cml workflow run 用的 runDic **必须**从 `scripts/resolve_run_ids.sh` 取,不准 agent 自己 `ls workflow5 | tail -1` 然后心算 +1。规则简单到没必要靠模型:
>
> ```bash
> eval "$(./scripts/resolve_run_ids.sh)"
> # 现在 shell 里有:
> # $SFT_RUNDIC = R{n-1}.runDic augment 落盘 / yaml / 归档全用这个,不 +1)
> # $EVAL_RUNDIC = R{n-1}.runDic + 1 (仅 cml workflow run 时使用,唯一一次 +1)
> # $SFT_RUNDIC = max(已落盘 workflow) = 当轮 eval 的 workflow id
> # augment 落盘 / yaml / 归档全用这个
> # $EVAL_RUNDIC = SFT_RUNDIC + 1(仅下一轮 cml workflow run 提交时使用)
> ```
>
> 已踩坑:R2 augment 把 `data_clean_<N>/` 写成了 `EVAL_RUNDIC`(多 +1 一次),跳过了 R1.runDic 整段命名空间,前端 augment 卡片直接读不到。**写 augment / SFT / 归档脚本时一律用 `$SFT_RUNDIC`,不要写 `${RUNDIC}` 也不要写 `${EVAL_RUNDIC}`**。
> **写 augment / SFT / 归档脚本时一律用 `$SFT_RUNDIC`,不要写 `${RUNDIC}` 也不要写 `${EVAL_RUNDIC}`**。
>
> 🚨 **调用时序(CRITICAL**`resolve_run_ids.sh` **只能在当轮 CML eval 的 `lark_template.json` 已落盘之后调用**。禁止在 eval 提交前或 watcher 等待期间预先调用——此时 max workflow 仍是上一轮的值,会导致 SFT_RUNDIC 偏移 -1(已踩坑:R0 workflow17823 评测中提前 resolve 得到 17822augment 文件全部错位)。正确时序:`cml step=complete` → `resolve_run_ids.sh` → augment/SFT。每次进入 augment/SFT 步骤前**必须重新调用**,不许复用之前缓存的值。
@@ -1262,6 +1273,8 @@ python skills/label-master/scripts/validate_label_output.py \
**层 2:语义复核(Skill 调用 label-master Agent,仅 H2**
**禁止用正则/规则脚本替代 LLM 语义判断**。层 2 不是格式校验,是"该 query 在 label-master 知识体系下是否应该标成这个 label"的语义问题。**唯一合法实现方式是调用 `Skill(skill="label-master")`**label-master 已标记 `repeatable: true`,可在同一 run 内多次调用)。已踩坑:R1 agent 写了个检查 hist 里有没有导航触发词的正则脚本充当"layer 2",完全没走语义判断,导致错误样本全量混入训练集。
H1 在 §4.0.1 Step A.5 已经过 label-master 推荐覆盖,这里**不再重跑**。H2 仿写是 §4.2 GPT 新增的样本,没经过 Step A.5,必须在此补一次语义判定:
🚨 **覆盖率硬规则**`label_master_review.jsonl` 里 H2 部分的行数**必须等于** `augment_<runDic>.jsonl` 的行数(1:1 全量覆盖)。**禁止抽样、禁止"前 N 条 spot-check"、禁止"5/5 pass 推 100 OK"**——§5.0 准入门会用 `wc -l` 拦。已踩坑:R17817 跑了 5 条样本就上报"100 条 pass",被 §5.0 退回。
@@ -1485,6 +1498,16 @@ python prepare_and_train_sft.py prepare --regen_from_csv --output_dir ./sft_data
> 验证集文件名不能含 `valid`/`test`/`eval`HF datasets 会推断错误的 split),脚本自动重命名为 `part-0.jsonl`。
⚠️ **每轮 SFT 前必须在 log 中展示训练数据组成**
`prepare_and_train_sft.py` 会 glob 目录下**所有** `augment_*.jsonl`。agent 在每轮 SFT 前必须在 program-state log 中列出最终参与训练的文件及行数:
```jsonl
{"log":{"ts":"...","iter":"R3","text":"SFT 数据组成: all_train.jsonl(35379) + augment_17829.jsonl(210) = 35589 条 | 排除: augment_17828.jsonl(150) rename .pre_R3R2 pattern 导致导航 bvt 劣化)"}}
```
必须展示:(1) 参与训练的所有文件及行数 (2) 被排除的旧轮文件及排除原因(如果有)。
#### 5.2 启动训练(cml 任务,R29 起统一走这条路径)
R23-R28 期间用本地 `nohup python3 prepare_and_train_sft.py train ...` 启动,会因登出/网络/会话退出而中断,并占用本地工作机 8 卡 GPU。**R29 起统一改为 cml custom_train submit 提交训练任务**,由 CloudML 调度到 `bj-nlp` 队列的 h20-96g 8 卡,本地零占用。