run_benchmarks: real sample row counts, no abort on legitimate null shots, verdict honours status (E-046)
Browse files- eval/run_benchmarks.py +26 -9
eval/run_benchmarks.py
CHANGED
|
@@ -215,15 +215,27 @@ def harvest(outdir, task):
|
|
| 215 |
# denominator that can be checked after the fact -- 0.4.13's results rows do not reliably carry
|
| 216 |
# n_input, and a task that silently resolved to a subset otherwise looks exactly like a score.
|
| 217 |
n_logged = None
|
| 218 |
-
|
| 219 |
-
|
|
|
|
|
|
|
|
|
|
| 220 |
try:
|
| 221 |
-
sj = json.load(open(os.path.join(
|
| 222 |
except Exception:
|
| 223 |
continue
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
break
|
|
|
|
|
|
|
| 227 |
|
| 228 |
return {"file": path, "rows": keep, "n_task_versions": len(j.get("task_versions") or {}),
|
| 229 |
"shots": shots, "n_input": r.get("n_input"), "n_effective": r.get("n_effective"),
|
|
@@ -311,9 +323,12 @@ def main():
|
|
| 311 |
elif not (h.get("n_input") or h.get("n_logged")):
|
| 312 |
# No denominator beside a score is no denominator at all: say so in the record.
|
| 313 |
rec[key]["status"] = "NO ROW COUNT RECORDED"
|
| 314 |
-
elif key == "
|
| 315 |
-
|
| 316 |
-
|
|
|
|
|
|
|
|
|
|
| 317 |
print("DONE %s %s rc %s rows %s" % (t, key, rc,
|
| 318 |
json.dumps(rec[key]["rows"], default=str)[:200]), flush=True)
|
| 319 |
table[t] = rec
|
|
@@ -324,7 +339,9 @@ def main():
|
|
| 324 |
push_fail.append("final")
|
| 325 |
def ok(t, key):
|
| 326 |
r = table.get(t, {}).get(key, {})
|
| 327 |
-
|
|
|
|
|
|
|
| 328 |
|
| 329 |
# Both columns and both exit codes. `primary` rows alone would report a full house with an entirely
|
| 330 |
# empty 5-shot column, or with a leg that exited non-zero after writing something partial (C2).
|
|
|
|
| 215 |
# denominator that can be checked after the fact -- 0.4.13's results rows do not reliably carry
|
| 216 |
# n_input, and a task that silently resolved to a subset otherwise looks exactly like a score.
|
| 217 |
n_logged = None
|
| 218 |
+
base = os.path.dirname(path)
|
| 219 |
+
for root, _d, files in os.walk(base): # subtask groups nest; a flat listdir missed them
|
| 220 |
+
for fn in sorted(files):
|
| 221 |
+
if not (fn.startswith("samples") and fn.endswith(".json")):
|
| 222 |
+
continue
|
| 223 |
try:
|
| 224 |
+
sj = json.load(open(os.path.join(root, fn)))
|
| 225 |
except Exception:
|
| 226 |
continue
|
| 227 |
+
sm = sj.get("samples")
|
| 228 |
+
# 0.4.x writes {"samples": {group: [rows]}} for grouped tasks (mmlu's 57 subjects) and a bare
|
| 229 |
+
# list for the rest. len() on the dict is the number of *groups*, which for mmlu would have
|
| 230 |
+
# been 1 and made every denominator check below pass while counting nothing (E-046/4).
|
| 231 |
+
if isinstance(sm, dict):
|
| 232 |
+
n_logged = sum(len(v) for v in sm.values() if isinstance(v, list))
|
| 233 |
+
elif isinstance(sm, list):
|
| 234 |
+
n_logged = len(sm)
|
| 235 |
+
if n_logged:
|
| 236 |
break
|
| 237 |
+
if n_logged:
|
| 238 |
+
break
|
| 239 |
|
| 240 |
return {"file": path, "rows": keep, "n_task_versions": len(j.get("task_versions") or {}),
|
| 241 |
"shots": shots, "n_input": r.get("n_input"), "n_effective": r.get("n_effective"),
|
|
|
|
| 323 |
elif not (h.get("n_input") or h.get("n_logged")):
|
| 324 |
# No denominator beside a score is no denominator at all: say so in the record.
|
| 325 |
rec[key]["status"] = "NO ROW COUNT RECORDED"
|
| 326 |
+
elif key == "secondary_5shot" and h.get("shots") != 5:
|
| 327 |
+
# The PRIMARY column legitimately records null for six of the nine tasks -- those YAMLs
|
| 328 |
+
# declare no num_fewshot and we pass no flag, which is the frozen definition of the
|
| 329 |
+
# column (docs/05 section 2 and 7). The 5-shot column is the one where we asked, so a
|
| 330 |
+
# null or a different number there means the flag did not reach the harness.
|
| 331 |
+
rec[key]["status"] = "SHOT COUNT NOT 5: %r" % (h.get("shots"),)
|
| 332 |
print("DONE %s %s rc %s rows %s" % (t, key, rc,
|
| 333 |
json.dumps(rec[key]["rows"], default=str)[:200]), flush=True)
|
| 334 |
table[t] = rec
|
|
|
|
| 339 |
push_fail.append("final")
|
| 340 |
def ok(t, key):
|
| 341 |
r = table.get(t, {}).get(key, {})
|
| 342 |
+
# `status` is set for a failed cell and for a cell with no denominator; ignoring it here is how
|
| 343 |
+
# the verdict printed 18/18 over a table of zeros (E-046/5).
|
| 344 |
+
return bool(r.get("rows")) and r.get("rc") == 0 and not r.get("status")
|
| 345 |
|
| 346 |
# Both columns and both exit codes. `primary` rows alone would report a full house with an entirely
|
| 347 |
# empty 5-shot column, or with a leg that exited non-zero after writing something partial (C2).
|