diff --git a/research-wiki/designs/2026-07-16-gate-speedup-design.md b/research-wiki/designs/2026-07-16-gate-speedup-design.md index d3913fa..f4c22c7 100644 --- a/research-wiki/designs/2026-07-16-gate-speedup-design.md +++ b/research-wiki/designs/2026-07-16-gate-speedup-design.md @@ -6,9 +6,10 @@ | 论点 | 依据 | |---|---| -| 块=8 不是统计需要 | TRM4 注释原文"块大小=推理并发度,块内跑满"——并发 8 时代的工程遗迹。e-process 为 anytime-valid 上鞅(Ville 不等式),**任意时刻停下判定假阳率仍 ≤ 1/e_confirm**;逐对判定是比逐块更细的合法 optional stopping | -| 到达序计数无偏 | 翻转对需 base/cand 两臂都返回才成立;H0 下两臂可交换,(结果, 延迟) 联合分布对换臂对称 → W 型与 L 型翻转的到达时间分布相同,按完成序计数不偏向任何方向 | -| 题型间并行无实质依赖 | 各题型 agent 只加载自己的 skill 文件(12 题型各有专属 .md),A 型 accept 改 A 的文件,对 B 型推理内容零影响。现行字母序滚动版本只是记账先后,非实质依赖。唯一共享文件 default-strategy.md 仅在题型缺专属文件时 fallback——本次 12 型全有专属文件,不触发 | +| 块=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**,违反即退回串行(防未来配置漂移) | ## 2. 改动 ②″:连续并发 gate 调度器 @@ -19,16 +20,17 @@ step 内 gate 阶段: Phase A. 并行进化:全部案例包题型(剔除 cooldown)gather 调 evolve_single_skill 无真实改动的题型照旧写 skipped step_report 退出 Phase B. 装配:每题型 阶梯出题(排除本 step 案例单元, 截断 n_max=40) + 物化候选目录 - Phase C. 连续监控调度: - 所有 (题型, 单元, 臂) 任务按「题型轮转 × 阶梯序」交错压入共享并发池(32) + Phase C. 连续监控调度(推理乱序并发 × 统计前缀有序): + 所有 (题型, 单元, 臂) 任务按「题型 round-robin × 题型内阶梯序」交错压入共享并发池(32) base 臂任务:BaselineCache 命中 → 立即完成;miss → 新鲜跑基线版本,非 INFRA 回写缓存 cand 臂任务:跑该题型候选目录 - 事件循环:某单元两臂齐 → - 任一臂 INFRA → 单元剔除(护栏计数,详 §2.3) - 否则配对计翻转 → 该题型 (W,L,n_used) 更新 → gate_decision - 判定 ≠ continue → 冻结该题型:排队未启任务撤销(启动前查冻结标志), - in-flight 任务跑完落库但不计入(W,L 已冻结) - 某题型全部单元返回仍 continue → n_remaining=0 → 题尽第四出口(provisional/inertia) + 事件循环(每题型持有前缀指针,初始 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 照写) ``` @@ -41,9 +43,11 @@ step 内 gate 阶段: | 信息量阶梯出题 + 案例单元排除 + 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 落库与溯源不变 | -| n_remaining 口径 | 等价迁移:= 未配对且未剔除单元数(排队+in-flight);题尽判定与现行一致 | +| `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 护栏(并行下的等价迁移) @@ -51,9 +55,10 @@ step 内 gate 阶段: ### 2.4 并发与调度事实 -- 并发池为全 gate 共享的 32(与 rollout 同参),取代"每次 run_inference 各建信号量"——峰值在飞请求恒 ≤32,不再有双臂叠加超限问题(v1 设计此处低估,Codex 已指出) +- **实现级约束**(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 复用保障 @@ -62,7 +67,7 @@ step 内 gate 阶段: | 缓存键成分不动 | 消息内容(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 | 仅一行;只影响未来写入,保障多天训练中断重启后早期调用仍在 | -| 一次性续期今日键 | 重启前运行一次:scan `llm_cache:*`,对 `0 < TTL < 604800` 的键 `EXPIRE 604800`(运维动作,见 runbook,不入库代码) | +| 一次性续期今日键 | 重启前运行一次(运维动作,不入库代码):`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. 非功能四维 @@ -70,7 +75,7 @@ step 内 gate 阶段: | 维度 | 保障 | |---|---| | 持久化 | predictions/traces 逐题落库(HarnessLog 单连接+锁,不变);BaselineCache 逐条原子写(不变);判定即写 gate_evidence/step_report | -| 幂等 | step 重跑前清同 run_id 旧行(现行机制覆盖新 run_id 命名);BaselineCache 同键同值重写无害 | +| 幂等 | step 重跑前清 rollout run_id **及全部 gate 派生行**(§2.2 修复项,现行代码只清前者);BaselineCache 同键同值重写无害 | | 断点续跑 | checkpoint 粒度仍为 step(gate 中途崩溃 → 重启重跑该 step,与现行一致);Redis/BaselineCache 命中使重跑近零成本 | | 原子性 | 判定冻结为内存事件,落库单条原子;无跨文件半写窗口 | @@ -90,8 +95,11 @@ step 内 gate 阶段: ## 6. 测试 - 单测(调度器,注入假 run_inference 与可控延迟): - - 同一组固定对错序列下,连续监控判定结果(action/W/L/E)与旧块序贯逐块判定一致(早停点可更早,判定方向一致); + - **前缀有序性(核心)**:构造"阶梯尾部单元先完成"的乱序到达,断言 (W,L) 更新顺序严格等于阶梯序、前缀未齐时不判定; + - 同一组固定对错序列下,前缀逐对判定结果(action/W/L/E)与旧块序贯逐块判定一致(早停点可更早,判定方向一致); - 过线后排队任务不再启动(计数断言),in-flight 结果不改变已冻结 (W,L); + - step 重跑幂等:预插旧 gate 行 → 重跑 step → 断言无重复行(C2 修复); + - fail-fast:两题型映射同一 target_file 时启动即报错; - 题尽路径:单元耗尽 → 第四出口与现行一致; - INFRA:单臂 INFRA 单元剔除不入配对,护栏计数阈值触发中止; - 题型并行:两题型交错完成,互不污染彼此 (W,L) 与判定。 @@ -101,7 +109,8 @@ step 内 gate 阶段: ## 7. 已否决备选(含 v1 失败记录) -- **①(v1)预灌 BaselineCache**:❌ 统计致命伤。冷启动阶梯按 seed 基线"错题优先"选题,预灌使 base 臂 = 选题依据的同一份旧样本;对选中的 seed 错题 base 被钉死为错、新鲜 cand 以概率 p 答对 → W 系统性膨胀,候选无改进也会假接受。现行"miss 后新鲜跑"的测量-选题独立性是刻意设计,不可省(Codex Critical,已验证)。 +- **①(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 阈值**:动统计参数,收益已被 ②″ 覆盖。