23f2002275 commited on
Commit
bcf5fdb
·
1 Parent(s): 7c1bf5c

fix(jobs): bump bitsandbytes to 0.47 (cu128 binary) so GPU dequant works in HF Job runtime image

Browse files
Files changed (2) hide show
  1. scripts/hf_jobs_helper.py +74 -0
  2. scripts/job_train.sh +4 -1
scripts/hf_jobs_helper.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tiny helper to query HF Jobs API directly (bypasses CLI rate-limit on /whoami-v2).
2
+
3
+ Usage:
4
+ python scripts/hf_jobs_helper.py list # list recent jobs (newest first)
5
+ python scripts/hf_jobs_helper.py inspect <id> # full inspect of one job
6
+ python scripts/hf_jobs_helper.py logs <id> # stream logs of one job
7
+
8
+ Requires HF_TOKEN env var.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import os
14
+ import sys
15
+ import urllib.request
16
+
17
+ API = "https://huggingface.co/api/jobs"
18
+ USER = "Pratham-math"
19
+
20
+
21
+ def _auth_headers() -> dict:
22
+ tok = os.environ.get("HF_TOKEN", "")
23
+ if not tok:
24
+ raise SystemExit("HF_TOKEN env var not set")
25
+ return {"Authorization": f"Bearer {tok}"}
26
+
27
+
28
+ def _get(url: str) -> str:
29
+ req = urllib.request.Request(url, headers=_auth_headers())
30
+ with urllib.request.urlopen(req, timeout=30) as r:
31
+ return r.read().decode("utf-8", errors="replace")
32
+
33
+
34
+ def list_jobs() -> None:
35
+ body = _get(f"{API}/{USER}?limit=10")
36
+ jobs = json.loads(body)
37
+ for j in jobs:
38
+ st = (j.get("status") or {}).get("stage", "?")
39
+ msg = (j.get("status") or {}).get("message", "")
40
+ flavor = j.get("flavor", "?")
41
+ created = j.get("createdAt", "?")
42
+ img = (j.get("dockerImage") or "")[:55]
43
+ print(f"{j['id']} | {st:>10} | {flavor:>14} | {created} | {img}")
44
+ if msg:
45
+ print(f" msg: {msg}")
46
+
47
+
48
+ def inspect(job_id: str) -> None:
49
+ body = _get(f"{API}/{USER}/{job_id}")
50
+ print(json.dumps(json.loads(body), indent=2))
51
+
52
+
53
+ def logs(job_id: str) -> None:
54
+ # Use HfApi.fetch_job_logs (SSE-aware) but pass namespace explicitly so it
55
+ # never calls /whoami-v2 (which is rate-limited).
56
+ from huggingface_hub import HfApi
57
+
58
+ api = HfApi(token=os.environ["HF_TOKEN"])
59
+ out = sys.stdout.buffer # write raw bytes to dodge cp1252 on Windows
60
+ for line in api.fetch_job_logs(job_id=job_id, namespace=USER, follow=False):
61
+ out.write((line + "\n").encode("utf-8", errors="replace"))
62
+ out.flush()
63
+
64
+
65
+ if __name__ == "__main__":
66
+ cmd = sys.argv[1] if len(sys.argv) > 1 else "list"
67
+ if cmd == "list":
68
+ list_jobs()
69
+ elif cmd == "inspect":
70
+ inspect(sys.argv[2])
71
+ elif cmd == "logs":
72
+ logs(sys.argv[2])
73
+ else:
74
+ raise SystemExit(f"unknown command: {cmd}")
scripts/job_train.sh CHANGED
@@ -20,7 +20,10 @@ pip install -q hydra-core omegaconf wandb 'huggingface_hub>=0.28' tyro
20
  # Core ML deps.
21
  # NOTE: trl 1.2 imports `is_trackio_available` from transformers, which is not
22
  # present in 4.49.0. Use a newer transformers line in jobs.
23
- pip install -q transformers==4.56.2 accelerate==1.5.2 peft==0.14.0 bitsandbytes==0.45.1
 
 
 
24
  pip install -q datasets==4.7.0
25
  # Keep TRL pinned for OpenEnv path but bypass resolver deadlock with datasets pin.
26
  pip install -q --no-deps trl==1.2.0
 
20
  # Core ML deps.
21
  # NOTE: trl 1.2 imports `is_trackio_available` from transformers, which is not
22
  # present in 4.49.0. Use a newer transformers line in jobs.
23
+ # bitsandbytes 0.45.1 only ships up to cuda124 binary; vllm 0.18.0 pulls torch
24
+ # with the cu128 wheel, so we MUST use a bnb release that ships libbitsandbytes_cuda128.so
25
+ # (0.47.0 is the first stable line that does). Confirmed against PyPI Apr 2026.
26
+ pip install -q transformers==4.56.2 accelerate==1.5.2 peft==0.14.0 'bitsandbytes>=0.47.0,<0.48'
27
  pip install -q datasets==4.7.0
28
  # Keep TRL pinned for OpenEnv path but bypass resolver deadlock with datasets pin.
29
  pip install -q --no-deps trl==1.2.0