Files
Video-Tree-TRM5/research-wiki/designs/2026-07-16-gate-speedup-design.md

128 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# gate 验证提速设计(v3):连续并发 gate + Redis 复用
> 2026-07-16。背景:Video-MME 900 训练实测,epoch 1 单题型 gate 双臂验证 ~3h(两臂串行 × 块串行 × 题型串行三重串行,~6 题型/step)→ step ~18h,3 epochs 不可行。v1 设计的"预灌 BaselineCache"经 Codex 审查发现统计致命伤已废弃(见 §7)。本版方案:**②″ 连续并发 gate**(题型并行 + 双臂并行 + 逐对连续早停,一次调度重构)+ **③ Redis 复用保障**。统计内核(e-值公式、四出口、配对翻转、信息量阶梯、题尽/试用期通道)一行不动。
## 1. 统计合法性(②″ 的前提)
| 论点 | 依据 |
|---|---|
| 块=8 不是统计需要 | TRM4 注释原文"块大小=推理并发度,块内跑满"——并发 8 时代的工程遗迹。e-process 为 anytime-valid 上鞅(Ville 不等式),在**预先声明的样本顺序**下任意时刻停下判定假阳率仍 ≤ 1/e_confirm;逐对判定是比逐块更细的合法 optional stopping |
| **统计消费必须按固定阶梯序前缀,不得按完成到达序**(Codex v2 复审 C1) | 到达序消费不合法:base 臂可缓存命中瞬间返回、cand 臂必新鲜跑,两臂延迟不对称,配对完成时间由 cand 延迟主导;若 cand 延迟与对错相关(走满 40 步的慢轨迹更易错),早到翻转对系统性偏向 W 型 → e-值虚高 → 假接受。**修法**:推理全并发乱序执行,但 (W,L) 更新与 gate_decision 只在"阶梯序最长已配齐前缀"延伸时推进——判定顺序回到预先声明的阶梯序,无条件合法;INFRA 单元视为"已解决(剔除)"不阻塞前缀推进 |
| 冻结后 in-flight 结果丢弃合法 | 在固定前缀消费下,停止时刻 τ 之后的样本不进入统计是标准 optional stopping;丢弃不引入偏差(到达序消费下则不成立,故必须配合上一条) |
| 题型间并行无实质依赖 | 各题型 agent 只加载自己的 skill 文件(12 题型各有专属 .md),A 型 accept 改 A 的文件,对 B 型推理内容零影响。现行字母序滚动版本只是记账先后,非实质依赖。唯一共享文件 default-strategy.md 仅在题型缺专属文件时 fallback——本次 12 型全有专属文件,不触发;**启动时 fail-fast 断言:同 step 内多个题型不得映射同一 target_file**,违反即中止(RuntimeError,防未来配置漂移) |
## 2. 改动 ②″:连续并发 gate 调度器
### 2.1 新流程(替换 `_gate_batch_skills` 串行 for + `validate.py` 块循环)
```text
step 内 gate 阶段:
Phase A. 并行进化:全部案例包题型(剔除 cooldown)gather 调 evolve_single_skill
无真实改动的题型照旧写 skipped step_report 退出
Phase B. 装配:每题型 阶梯出题(排除本 step 案例单元, 截断 n_max=40) + 物化候选目录
Phase C. 连续监控调度(推理乱序并发 × 统计前缀有序):
所有 (题型, 单元, 臂) 任务按「题型 round-robin × 题型内阶梯序」交错压入共享并发池(32)
base 臂任务:BaselineCache 命中 → 立即完成;miss → 新鲜跑基线版本,非 INFRA 回写缓存
cand 臂任务:跑该题型候选目录
事件循环(每题型持有前缀指针,初始 0):
单元两臂齐 → 标记该单元"已解决"(配对翻转 / 任一臂 INFRA 则剔除,护栏计数 §2.3)
若阶梯序前缀因此延伸 → 沿前缀逐单元消费:更新 (W,L,n_used) → gate_decision
判定 ≠ continue → 冻结该题型:排队未启任务撤销(启动前查冻结标志),
in-flight 任务跑完落库但不计入(τ 之后样本,合法丢弃)
前缀之外已完成的单元暂存,等前缀推进到它时才消费(统计顺序 = 预声明阶梯序)
某题型前缀消费完全部单元仍 continue → n_remaining=0 → 题尽第四出口(provisional/inertia)
Phase D. 汇总:按字母序对已判定题型依次执行现有 _accept_skill / _record_rejected_skill
(文件不相交,顺序仅为确定性;gate_evidence/step_report/quadrant_pairs 照写)
```
### 2.2 保留与消解
| 项 | 处置 |
|---|---|
| e-值公式 / 四出口 / w_net_min / delta_min / lambda_dir / futility | **不动**(判定函数 `gate_decision` 原样,只是调用时机从"每块末"变"每对完成") |
| 信息量阶梯出题 + 案例单元排除 + n_max=40 | **不动**(发射顺序即阶梯序) |
| BaselineCache(miss 新鲜跑、INFRA 不写、内容寻址) | **不动**(无预灌;epoch 1 冷缓存,base 臂新鲜跑但与所有臂共享并发池) |
| provisional → probation 试用 / epoch 末结算回滚 / cooldown / 黑名单 | **不动** |
| `gate_block=8` 分块 | **消解删除**(config 键与 validate 块循环一并移除;CLAUDE.md §4.7 #6 需在 commit 标注本次语义修订:块序贯 → 阶梯序前缀逐对序贯,判据不变) |
| 每块两个 run_id(`_b{i}_base/_cand`) | **替换**为每臂一个 run_id(`..._gate_{slug}_base` / `_cand`)。溯源口径变化:predictions 不再携带块信息,gate_evidence 行以 **ladder_rank(阶梯序号)替代 block_idx** 补足调度溯源 |
| step 重跑幂等(**修复现行潜伏 bug**) | 现行 `_run_step` 只清 rollout run_id,gate 派生 run_id 的旧行从不清理,崩溃重跑会累积重复 predictions(HarnessLog 无主键去重)。**新增**:step 开始时一并清理 `{step_run_id}_gate_%` 的 predictions/traces 及该 (epoch, step) 的 gate_evidence / quadrant_pairs / step_report 旧行 |
| 断点粒度 | **明确声明**:gate 内无断点(与现行块方案一致),checkpoint 仍为 step 粒度;崩溃重跑该 step 时由上一行的清理保证干净重放,Redis/BaselineCache 命中使重放近零成本 |
| n_remaining 口径 | 等价迁移:= 阶梯计划中前缀尚未消费的单元数;题尽判定与现行一致 |
### 2.3 INFRA 护栏(并行下的等价迁移)
现行:跨块累计 error 率,分母 ≥10 且 > gate_guard_err(0.10) → 中止训练。迁移为**每题型运行时计数器**:分子=该题型 INFRA 单元数(任一臂),分母=该题型已完成推理的单元次数(两臂各计,缓存命中不计),阈值与中止行为不变。判定在每次单元完成事件时检查,先于配对更新。
### 2.4 并发与调度事实
- **实现级约束**(Codex I1):并发控制为 gate 调度器持有的单一共享 `asyncio.Semaphore(concurrency)`,单元级推理任务在该信号量下执行;不得沿用"每次 run_inference 各建信号量"(否则并行臂叠加超限)。峰值在飞请求恒 ≤32
- **公平调度**(Codex I2):任务发射严格按题型 round-robin 轮转(题型内按阶梯序),防止大题型占满槽饿死小题型;冻结题型立即停止补发
- **进化并行的并发契约**(Codex I3):`GovernedLLMClient` 已在 rollout 中承受 32 路并发调用(治理栈全线程/协程安全),6 路 gather 进化无新增风险;设计约束:Phase A-C 只读训练 state,**Phase D 是唯一写 state 的阶段**(probation/cooldown/rejected_buffer/changed_task_types 均在 Phase D 按字母序串行落账)
- 浪费上界:每题型判定瞬间 in-flight 的任务 ≤ 并发宽度;排队未启动的全部省下。相比"全发不早停"省 ~50-70% token,相比现行块早停多耗 ≤32 题次/题型
## 3. 改动 ③:Redis 复用保障
| 措施 | 说明 |
|---|---|
| 缓存键成分不动 | 消息内容(skills/prompts v1 正文、冻结题池、`build_batches(seed=epoch)` 确定性批次)与盐(run_id 派生自 `infer_adhoc`)零变化 → 重启后 rollout / 诊断 / 进化调用命中已写缓存 |
| gate 臂 run_id 变化的影响 | ②″ 将 `_b{i}_base` 改为 `_base`,今日旧 gate 调用(仅 Action Reasoning 部分块)的盐失配不复用——量小(~100 题次),可接受,如实记录 |
| `.env` `REDIS_CACHE_TTL` 86400→604800 | 仅一行;只影响未来写入,保障多天训练中断重启后早期调用仍在 |
| 一次性续期今日键 | 重启前运行一次(运维动作,不入库代码):`conda run -n Video-Tree-TRM python -c``.env` 的 REDIS_URL,`for k in scan_iter('llm_cache:*'): 0 < ttl(k) < 604800 and expire(k, 604800)` |
| 复用边界(诚实声明) | Agent 逐步追加 messages,某步 miss(如原调用 503 未入缓存 / TTL 过期)后该轨迹后续全 miss 并可能分叉——复用是"命中前缀零成本"的尽力而为,非全量保证。今日实测命中率 42% 佐证机制有效 |
## 4. 非功能四维
| 维度 | 保障 |
|---|---|
| 持久化 | predictions/traces 逐题落库(HarnessLog 单连接+锁,不变);BaselineCache 逐条原子写(不变);判定即写 gate_evidence/step_report |
| 幂等 | step 重跑前清 rollout run_id **及全部 gate 派生行**(§2.2 修复项,现行代码只清前者);BaselineCache 同键同值重写无害 |
| 断点续跑 | checkpoint 粒度仍为 step(gate 中途崩溃 → 重启重跑该 step,与现行一致);Redis/BaselineCache 命中使重跑近零成本 |
| 原子性 | 判定冻结为内存事件,落库单条原子;无跨文件半写窗口 |
## 5. 前序行为审计
| 现有行为 | 处置 |
|---|---|
| 题型串行 for(字母序滚动版本) | **替换**:题型并行,accepts 按字母序统一合并(内容等价,记账顺序确定) |
| 进化串行 | **替换**:题型间 gather 并行(rejected_buffer / budget per-type 独立,无共享) |
| 块序贯(8/块)+ 两臂串行 | **替换**:逐对连续序贯 + 全臂共享并发池 |
| base 臂缓存 miss 新鲜跑 / INFRA 不写缓存 | **保留** |
| INFRA 护栏(分母≥10 且 >10% 中止) | **等价迁移**(§2.3) |
| cooldown / skipped / 无改动跳过 + step_report | **保留** |
| gate_evidence / quadrant_pairs / candidate_correctness 增量合并 | **保留** |
| e-process 判定与四出口、题尽通道、probation | **不动** |
## 6. 测试
- 单测(调度器,注入假 run_inference 与可控延迟):
- **前缀有序性(核心)**:构造"阶梯尾部单元先完成"的乱序到达,断言 (W,L) 更新顺序严格等于阶梯序、前缀未齐时不判定;
- 同一组固定对错序列下,前缀逐对判定结果(action/W/L/E)与旧块序贯逐块判定一致(早停点可更早,判定方向一致);
- 过线后排队任务不再启动(计数断言),in-flight 结果不改变已冻结 (W,L);
- step 重跑幂等:预插旧 gate 行 → 重跑 step → 断言无重复行(C2 修复);
- fail-fast:两题型映射同一 target_file 时启动即报错;
- 题尽路径:单元耗尽 → 第四出口与现行一致;
- INFRA:单臂 INFRA 单元剔除不入配对,护栏计数阈值触发中止;
- 题型并行:两题型交错完成,互不污染彼此 (W,L) 与判定。
- 单测(进化并行):两题型 gather 进化,rejected_buffer 各自独立生效。
- 集成:小型真实 workspace 跑一个 step,断言 gate_evidence/step_report/quadrant_pairs 落库完整、accepts 正确推进版本。
- 回归:validate/gate_ladder/runner 现有测试全绿(块相关测试改写为连续语义)。
## 7. 已否决备选(含 v1 失败记录)
- **①(v1)预灌 BaselineCache**:❌ 两个致命伤。(a) 统计:冷启动阶梯按 seed 基线"错题优先"选题,预灌使 base 臂 = 选题依据的同一份旧样本;对选中的 seed 错题 base 被钉死为错、新鲜 cand 以概率 p 答对 → W 系统性膨胀,候选无改进也会假接受。现行"miss 后新鲜跑"的测量-选题独立性是刻意设计,不可省。(b) resume 污染:预灌用"当前"skill 内容算 hash,resume 时已进化题型会把 v1 旧预测灌到新内容 hash 下,base 臂错误命中(Codex Critical ×2,均已验证)。
- **到达序消费配对(②″ 初稿)**:❌ base 缓存命中/cand 必新鲜跑的延迟不对称 + 对错-延迟相关,使早到翻转对偏向 W 型,e-值虚高假接受;改为阶梯序前缀消费(§1)。
- **B. 小题型合并进化 default-strategy.md**:future work。合并 gate 池(9+14+17+23=63 单元)可达正式接受线且信号更密,但存在子群伤害风险(平均变好掩盖单型受损)且叠加变量;本轮跑 A(小题型走 provisional+probation 通道),其结果作为 B 的对照证据。
- **top-K 题型/step**:用户否决,保留全部有错题型进化。
- **砍 gate_n_max / 放宽 e 阈值**:动统计参数,收益已被 ②″ 覆盖。
- **块轮次锁步(②′)**:被更优的连续监控取代(锁步有轮末空转,连续无)。
## 8. 预期收益
| 项 | 现状 | ②″ 后 |
|---|---|---|
| step 内 gate(~6 题型) | 三重串行 ~9-18h | 共享 32 并发连续跑,**~1.5-2.5h**(≈总需题次×单题时长/32) |
| 进化阶段(~6 次 LLM) | 串行 ~30-60min | 并行 ~10min |
| 3 epochs(5 step/epoch + epoch 末 val/holdout) | 数天-一周 | **~1.5-2.5 天** |
改动面:`app/harness/validate.py`(块循环→连续调度器)、`app/harness/runner.py`(`_gate_batch_skills` 并行装配)、`config`(删 gate_block)、`.env` 一行、运维一次性续期。