fix: clear gate-derived rows on step rerun (idempotency)

This commit is contained in:
2026-07-17 00:57:53 -04:00
parent 9e8a254fbb
commit ea6bec5421
2 changed files with 123 additions and 9 deletions
+54 -9
View File
@@ -602,6 +602,52 @@ def _write_skip_report(
)
def _clear_step_rows(db_path: str, *, baseline_run_id: str, epoch: int, step: int) -> None:
"""清空一个 step 的全部旧行(rollout + gate 派生),保证崩溃重跑幂等。
修复前序潜伏 bug:旧实现只清 rollout run_idgate 派生 run_id
`{step_run_id}_gate_%`)从不清理,重跑会累积重复 predictionsHarnessLog
无主键去重),_load_run_rows 的 dict 覆盖使结果依赖 SELECT 顺序。
gate_evidence / quadrant_pair 以 (run_id, epoch, step) 过滤删除;
表不存在(首个 step)时跳过。step_report 为按文件名覆盖写的 JSON,天然幂等。
参数:
db_path: harness.db 路径。
baseline_run_id: 基线 rungate_evidence/quadrant_pair 的 run_id 维度)。
epoch: 轮次(1-based)。
step: epoch 内 step 序号(0-based)。
返回:
无。
关键实现细节:
predictions/traces 的 gate 行按 LIKE 前缀删除,'_' 通配显式转义
(ESCAPE)钉死字面匹配,避免 `..._s1` 误匹配 `..._s10` 类前缀陷阱。
"""
from app.harness.inference import PREDICTIONS_SCHEMA, TRACES_SCHEMA
from app.harness.log import HarnessLog
step_run_id = f"{baseline_run_id}_e{epoch}_s{step}"
with HarnessLog(db_path, step_run_id, register_run=False) as log:
log.create_table("predictions", PREDICTIONS_SCHEMA)
log.create_table("traces", TRACES_SCHEMA)
for table in ("predictions", "traces"):
log.execute(f"DELETE FROM {table} WHERE run_id=?", (step_run_id,))
log.execute(
f"DELETE FROM {table} WHERE run_id LIKE ? ESCAPE '\\'",
(step_run_id.replace("_", r"\_") + r"\_gate\_%",),
)
for table in ("gate_evidence", "quadrant_pair"):
exists = log.query(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table,)
)
if exists:
log.execute(
f"DELETE FROM {table} WHERE run_id=? AND epoch=? AND step=?",
(baseline_run_id, epoch, step),
)
# ---------------------------------------------------------------------------
# Runner 主类
# ---------------------------------------------------------------------------
@@ -1096,17 +1142,16 @@ class Runner:
"""单 steprollout → correctness 增量 → 诊断 → 累加 system/tool → 按类 gate。"""
run_id = f"{pools.baseline_run_id}_e{epoch}_s{step}"
from app.harness.inference import PREDICTIONS_SCHEMA, TRACES_SCHEMA
from app.harness.log import HarnessLog
# 幂等:重跑同一 step 前先清旧行,避免断点续跑重复累计双计。
# 先 CREATE TABLE IF NOT EXISTSfresh workspace 首跑时表尚未由 run_inference 建),
# register_run=False 避免只读清理污染 _runs 运行状态。
with HarnessLog(str(self._paths.db_path), run_id, register_run=False) as log:
log.create_table("predictions", PREDICTIONS_SCHEMA)
log.create_table("traces", TRACES_SCHEMA)
log.execute("DELETE FROM predictions WHERE run_id=?", (run_id,))
log.execute("DELETE FROM traces WHERE run_id=?", (run_id,))
# 幂等:重跑同一 step 前清 rollout + 全部 gate 派生旧行(修复潜伏 bug:
# 旧实现只清 rollout,gate 行崩溃重跑会累积重复)。
_clear_step_rows(
str(self._paths.db_path),
baseline_run_id=pools.baseline_run_id,
epoch=epoch,
step=step,
)
await self._rollout_batch(batch, run_id)