jvonrad commited on
Commit
5101600
·
verified ·
1 Parent(s): 251ba47

Upload run_benchmarks.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. run_benchmarks.py +127 -0
run_benchmarks.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Standalone downstream-benchmark runner for XScript checkpoints on any GPU.
3
+
4
+ Isambard-AI is walled off by a CPU-minutes quota, so we export the trained
5
+ checkpoints to a (private) HF repo and evaluate them elsewhere. This script
6
+ pulls the checkpoints + tokenizers + bundled `xscript` source from that repo,
7
+ lays them out exactly as `xscript.paths` expects, and runs the lm-eval-harness
8
+ benchmarks (Global-MMLU / Belebele / XNLI) via the same `eval-bench` harness
9
+ used on-cluster -- so scores are directly comparable.
10
+
11
+ Quick validation pass over everything (recommended first):
12
+ pip install -r requirements.txt
13
+ # install a torch build matching your CUDA first, e.g.:
14
+ # pip install torch --index-url https://download.pytorch.org/whl/cu121
15
+ export HF_TOKEN=hf_... # needed while the repo is private
16
+ python run_benchmarks.py --repo jvonrad/xscript-eval --limit 200
17
+
18
+ Full suite (all examples):
19
+ python run_benchmarks.py --repo jvonrad/xscript-eval
20
+
21
+ Results land in ./xscript_bench/results/bench/<run>_final.json (one per run),
22
+ plus a combined summary.json. Send those JSONs back for analysis.
23
+ """
24
+ import argparse
25
+ import json
26
+ import os
27
+ import sys
28
+ from pathlib import Path
29
+
30
+
31
+ def main() -> None:
32
+ ap = argparse.ArgumentParser(description=__doc__,
33
+ formatter_class=argparse.RawDescriptionHelpFormatter)
34
+ ap.add_argument("--repo", required=True, help="HF repo id holding the export")
35
+ ap.add_argument("--repo-type", default="model", choices=["model", "dataset"])
36
+ ap.add_argument("--workdir", default="./xscript_bench")
37
+ ap.add_argument("--limit", type=float, default=None,
38
+ help="examples per task (omit for full suite)")
39
+ ap.add_argument("--runs", nargs="*", default=None,
40
+ help="subset of friendly model names (default: all in models.json)")
41
+ ap.add_argument("--tasks", nargs="*", default=None,
42
+ help="override task list (default: the run's training languages)")
43
+ ap.add_argument("--num-fewshot", type=int, default=0)
44
+ ap.add_argument("--batch-size", type=int, default=8)
45
+ ap.add_argument("--keep-checkpoints", action="store_true",
46
+ help="keep each 4GB checkpoint after eval (default: delete to save disk)")
47
+ args = ap.parse_args()
48
+
49
+ from huggingface_hub import hf_hub_download, list_repo_files
50
+
51
+ work = Path(args.workdir).resolve()
52
+ scratch = work / "xscript"
53
+ (scratch / "runs").mkdir(parents=True, exist_ok=True)
54
+ (scratch / "tokenizers").mkdir(parents=True, exist_ok=True)
55
+ os.environ["XSCRIPT_SCRATCH"] = str(scratch)
56
+ os.environ["XSCRIPT_RESULTS"] = str(work / "results")
57
+
58
+ dl = dict(repo_id=args.repo, repo_type=args.repo_type, local_dir=str(scratch.parent / "_repo"))
59
+ repo_files = list_repo_files(args.repo, repo_type=args.repo_type)
60
+
61
+ # 1) bundled xscript source -> importable
62
+ src_root = scratch.parent / "_repo"
63
+ for f in repo_files:
64
+ if f.startswith("src/xscript/"):
65
+ hf_hub_download(filename=f, **dl)
66
+ sys.path.insert(0, str(src_root / "src"))
67
+
68
+ # 2) tokenizers (small)
69
+ for f in repo_files:
70
+ if f.startswith("tokenizers/"):
71
+ local = hf_hub_download(filename=f, **dl)
72
+ dest = scratch / f
73
+ dest.parent.mkdir(parents=True, exist_ok=True)
74
+ if not dest.exists():
75
+ dest.symlink_to(local)
76
+
77
+ # 3) model manifest (friendly name -> real tokenizer)
78
+ models = json.loads(Path(hf_hub_download(filename="models.json", **dl)).read_text())
79
+ runs = args.runs or sorted(models)
80
+ missing = [r for r in runs if r not in models]
81
+ if missing:
82
+ sys.exit(f"models not in repo: {missing}\navailable: {sorted(models)}")
83
+ print(f"[bench] {len(runs)} model(s) to evaluate: {runs}")
84
+
85
+ import torch
86
+ from xscript.eval import bench
87
+ if not torch.cuda.is_available():
88
+ print("[bench] WARNING: no CUDA device -- this will be very slow on CPU.")
89
+
90
+ summary = {}
91
+ for i, run in enumerate(runs, 1):
92
+ tok = models[run]["tok"]
93
+ print(f"\n===== [{i}/{len(runs)}] {run} (tok={tok}, limit={args.limit}) =====")
94
+ ckpt_rel = f"runs/{run}/checkpoints/final.pt"
95
+ local_ckpt = hf_hub_download(filename=ckpt_rel, **dl)
96
+ dest = scratch / ckpt_rel
97
+ dest.parent.mkdir(parents=True, exist_ok=True)
98
+ if not dest.exists():
99
+ dest.symlink_to(local_ckpt)
100
+ try:
101
+ scores = bench.run(run, tok, tag="final", tasks=args.tasks,
102
+ num_fewshot=args.num_fewshot, limit=args.limit,
103
+ log_wandb=False, batch_size=args.batch_size)
104
+ summary[run] = scores
105
+ except Exception as exc:
106
+ print(f"[bench] {run} FAILED: {type(exc).__name__}: {exc}")
107
+ summary[run] = {"error": f"{type(exc).__name__}: {exc}"}
108
+ finally:
109
+ if not args.keep_checkpoints:
110
+ # free the ~4GB blob (both the symlink target in HF cache and our link)
111
+ try:
112
+ real = Path(local_ckpt).resolve()
113
+ dest.unlink(missing_ok=True)
114
+ real.unlink(missing_ok=True)
115
+ except OSError as exc:
116
+ print(f"[bench] cleanup warning for {run}: {exc}")
117
+
118
+ out = work / "results" / "summary.json"
119
+ out.parent.mkdir(parents=True, exist_ok=True)
120
+ out.write_text(json.dumps({"limit": args.limit, "num_fewshot": args.num_fewshot,
121
+ "scores": summary}, indent=2))
122
+ print(f"\n[bench] wrote {out}")
123
+ print(f"[bench] per-run JSON in {work / 'results' / 'bench'}")
124
+
125
+
126
+ if __name__ == "__main__":
127
+ main()