mirror of
https://github.com/wassname/evil_MoE.git
synced 2026-07-17 11:27:23 +08:00
feat: per-mode deploy hack in route eval (the weak-detector generalisation cut)
eval_hack_solve now returns by_mode tallies; the final ROUTE EVAL logs deploy hack/solve per env_mode, tagged IN-dist (run_tests, what v_hack saw) vs held-out (file_marker/sentinel/stdout_marker). Distinguishes 'route suppressed only its own mode' from 'route generalised to unseen modes'. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
@@ -548,8 +548,13 @@ def eval_hack_solve(model, tok, problems, eval_idxs, gen_cfg, device, max_new) -
|
||||
"""
|
||||
model.config.use_cache = True
|
||||
n = hacks = solves = 0
|
||||
# per-mode (env_mode) tallies so route's deploy eval can be read per loophole:
|
||||
# the load-bearing weak-detector test is whether route suppresses the modes
|
||||
# v_hack never saw (file_marker/sentinel), not just its own (run_tests).
|
||||
by_mode: dict[str, list[int]] = {} # env_mode -> [hacks, solves, n]
|
||||
for idx in eval_idxs:
|
||||
prob = problems[idx]
|
||||
mode = prob["env_mode"]
|
||||
prompt = tok.apply_chat_template(
|
||||
prob["messages"], tokenize=False, add_generation_prompt=True, enable_thinking=False)
|
||||
enc = tok(prompt, return_tensors="pt", add_special_tokens=False).to(device)
|
||||
@@ -557,15 +562,17 @@ def eval_hack_solve(model, tok, problems, eval_idxs, gen_cfg, device, max_new) -
|
||||
continue
|
||||
out = model.generate(**enc, generation_config=gen_cfg)
|
||||
comps = out[:, enc.input_ids.shape[1]:]
|
||||
tally = by_mode.setdefault(mode, [0, 0, 0])
|
||||
for t in tok.batch_decode(comps, skip_special_tokens=True):
|
||||
r = compute_reward(
|
||||
t, canonical_solution=prob["canonical"], gt_tests=prob["gt_tests"],
|
||||
setup_code=prob["setup_code"], func_name_hint=prob["func_name"],
|
||||
env_mode=prob["env_mode"])
|
||||
hacks += int(r.exploited)
|
||||
solves += int(r.gt_correct); n += 1
|
||||
env_mode=mode)
|
||||
hacks += int(r.exploited); tally[0] += int(r.exploited)
|
||||
solves += int(r.gt_correct); tally[1] += int(r.gt_correct)
|
||||
n += 1; tally[2] += 1
|
||||
model.config.use_cache = False
|
||||
return dict(hack=hacks / max(1, n), solve=solves / max(1, n), n=n)
|
||||
return dict(hack=hacks / max(1, n), solve=solves / max(1, n), n=n, by_mode=by_mode)
|
||||
|
||||
|
||||
# 2-char env_mode codes for compact per-mode hack columns (hk_rt, hk_xc, ...).
|
||||
@@ -1705,6 +1712,17 @@ def main(cfg: Config) -> int:
|
||||
f"train/knob-on hack={ev_train['hack']:.3f} solve={ev_train['solve']:.3f} | "
|
||||
f"deploy/knob-off hack={ev_deploy['hack']:.3f} solve={ev_deploy['solve']:.3f} "
|
||||
f"(SHOULD: deploy hack < train hack at ~matched solve => quarantine absorbed the cheat)")
|
||||
# Per-mode deploy hack: the generalisation cut. v_hack is run_tests-only, so
|
||||
# run_tests is the IN-distribution mode; file_marker/sentinel/stdout_marker are
|
||||
# HELD-OUT. SHOULD: if route generalises, deploy hack drops on held-out modes too,
|
||||
# not just run_tests. ELSE the quarantine only caught the mode v_hack saw.
|
||||
for mode in sorted(ev_deploy["by_mode"]):
|
||||
th, ts, tn = ev_train["by_mode"].get(mode, [0, 0, 0])
|
||||
dh, ds, dn = ev_deploy["by_mode"][mode]
|
||||
tag = "IN-dist" if mode == "run_tests" else "held-out"
|
||||
logger.info(
|
||||
f" per-mode[{mode:<13} {tag:>8}] train hack={th}/{tn} solve={ts}/{tn} | "
|
||||
f"deploy hack={dh}/{dn} solve={ds}/{dn}")
|
||||
|
||||
# Final tail: cue emoji + main metric BLUF, then per-step tsv table.
|
||||
# Vanilla arm: 🟢 if hacking emerged. Projected arm: 🟢 if HACK_RATE dropped
|
||||
|
||||
Reference in New Issue
Block a user