File size: 2,427 Bytes
ec24fb0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"""Go / no-go for the reasoning-trace model, decided by a rule fixed in advance (before any result is seen).

Compares greedy thinking of the trained model (with its adapter) with greedy thinking of the base model on the SAME held-out
questions: the 400-question SinhalaMMLU dev sample (never used for traces or training) and the 300-question Global-MMLU
non-academic proxy (never used). Paired differences are pooled over both sets.

GO if pooled difference >= +1.5 points AND neither set is worse than -3.0 points. Writes results/rft_decision.json.

  python -m eval.decide_rft --pairs think_base_smmlu_dev_sample400:think_rft_dev400:sinhalammlu \
      think_base_gmmlu_si_val_nonacademic300:think_rft_nonacademic300:gmmlu_si
"""
from __future__ import annotations

import argparse
import json
from pathlib import Path

import numpy as np

from .common import ROOT
from .compare import correctness

MIN_POOLED, MIN_EACH = 1.5, -3.0


def main() -> None:
    ap = argparse.ArgumentParser()
    ap.add_argument("--pairs", nargs="+", required=True, help="base_run:new_run:dataset")
    ap.add_argument("--out", default="rft_decision.json", help="file name under results/")
    args = ap.parse_args()
    diffs, per = [], {}
    for pair in args.pairs:
        b, n, ds = pair.split(":")
        base, new = correctness(ROOT / "results" / b, ds)[0], correctness(ROOT / "results" / n, ds)[0]
        uids = sorted(set(base) & set(new))
        d = np.array([new[u] - base[u] for u in uids], dtype=float)
        per[n] = {"n": len(uids), "base": 100 * float(np.mean([base[u] for u in uids])),
                  "new": 100 * float(np.mean([new[u] for u in uids])), "diff": 100 * float(d.mean())}
        diffs.append(d)
    pooled = np.concatenate(diffs)
    rng = np.random.default_rng(0)
    lo, hi = np.percentile([pooled[rng.integers(0, len(pooled), len(pooled))].mean() for _ in range(5000)], [2.5, 97.5])
    go = bool(100 * pooled.mean() >= MIN_POOLED and all(v["diff"] >= MIN_EACH for v in per.values()))
    out = {"rule": f"pooled diff >= {MIN_POOLED} and each set >= {MIN_EACH}", "per_set": per, "n": len(pooled),
           "pooled_diff": 100 * float(pooled.mean()), "ci95": [100 * float(lo), 100 * float(hi)], "go": go}
    (ROOT / "results" / args.out).write_text(json.dumps(out, indent=2))
    print(json.dumps(out, indent=2))
    print("DECISION:", "GO" if go else "NO-GO")


if __name__ == "__main__":
    main()