From ad048e59c6a0ce7004157b5067554bcbd9132af1 Mon Sep 17 00:00:00 2001 From: wassname Date: Sun, 31 May 2026 22:45:12 +0000 Subject: [PATCH] fix: results.py parses gt_s/hack_s by header name, not stale fixed indices Old GT_S=6/HACK_S=8 were the pre-sprd/N layout; current table is gt_s=4 hack_s=6, so newer logs were silently mis-read and old distill logs crashed _frac on a non-fraction token. Now locate the train.py streaming header (first token 'step' + 'ref_eq' present) and map columns by name. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com> --- scripts/results.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/scripts/results.py b/scripts/results.py index fc7baef..a2cc358 100644 --- a/scripts/results.py +++ b/scripts/results.py @@ -20,8 +20,14 @@ from tabulate import tabulate LOG_DIR = Path("logs") TS_RE = re.compile(r"(\d{8}T\d{6})") -# per-step row after "| INFO |": step ref_eq rew rew_s sprd N gt_s gt_t hack_s hack_t ... -GT_S, HACK_S = 6, 8 # column indices into the whitespace-split row +# Column positions are read from the header row by NAME, not hardcoded -- the +# per-step table layout has changed over time (sprd/N dropped, cin/cout/hk_dep +# added) so fixed indices silently mis-read newer logs and crash on smoke logs. + + +def _colname(tok: str) -> str: + # header tokens carry direction glyphs / markers: "gt_s↑", "hack_s?" -> "gt_s", "hack_s" + return re.sub(r"[^a-z0-9_]", "", tok.lower()) def _frac(tok: str) -> float | None: @@ -64,14 +70,29 @@ def parse_log(path: Path) -> dict | None: preset_line = next((l for l in txt.splitlines() if "preset=" in l and "arm=" in l), "") if argv is None: return None + # Locate the per-step table header to map gt_s/hack_s columns by NAME. The + # train.py streaming table is the INFO line whose tokens start with "step" + # and include "ref_eq" -- that signature excludes the old distill_* logs + # which also have "step ..." lines but a different (hack=.. pass=..) format. + header, names = None, [] + for l in txt.splitlines(): + if "| INFO |" not in l: + continue + toks = [_colname(t) for t in l.split("| INFO |", 1)[1].split()] + if toks[:1] == ["step"] and "ref_eq" in toks: + header, names = l, toks + break + if header is None: + return None # not a train.py streaming run + idx_hack, idx_gt = names.index("hack_s"), names.index("gt_s") hs, gts = [], [] for line in txt.splitlines(): if "| INFO |" not in line: continue row = line.split("| INFO |", 1)[1].split() - if not row or not row[0].isdigit() or len(row) <= HACK_S: + if not row or not row[0].isdigit() or len(row) <= idx_hack: continue - h, g = _frac(row[HACK_S]), _frac(row[GT_S]) + h, g = _frac(row[idx_hack]), _frac(row[idx_gt]) if h is not None: hs.append(h) if g is not None: