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- scripts/hf_jobs_helper.py +74 -0
- 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 |
-
|
|
|
|
|
|
|
|
|
|
| 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
|