Download code/scripts/supervise.py from viai957/align: direct link, hf CLI and curl.
- Browser
- Download file 3.41 kB
-
https://huggingface.co/viai957/align/resolve/main/code/scripts/supervise.py
- Command line
-
hf download hf://viai957/align/code/scripts/supervise.py
-
curl -L -o supervise.py https://huggingface.co/viai957/align/resolve/main/code/scripts/supervise.py
3.41 kB
| #!/usr/bin/env python | |
| """Bounded-retry launch supervisor CLI (stdlib only; no torch import). | |
| python scripts/supervise.py --run-dir RUN [--max-retries 2] [--backoff 30] \ | |
| -- torchrun --nproc_per_node=4 scripts/sft.py configs/sft.toml | |
| Everything after `--` is the child command. See align/utils/supervisor.py for | |
| the retry rules (progress + preflight + non-HALT exit code) and why each exists. | |
| `--run-dir` must be the directory the Trainer writes history.jsonl and | |
| checkpoints/ into; attempts are logged to RUN/supervisor.jsonl. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import sys | |
| from pathlib import Path | |
| # The package is not installed in the venv; without this a bare `python scripts/supervise.py` (the documented | |
| # launch line) dies with ModuleNotFoundError unless PYTHONPATH is exported (same fix as scripts/sft.py). | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from align.utils.supervisor import Supervisor | |
| def _checkpoint_validator(): | |
| """`checkpoint_problem` from the Trainer, imported lazily (it needs torch). | |
| The supervisor module itself stays stdlib-only; THIS entry point is where | |
| the cost is paid, once, so that "progress" means a checkpoint `latest_checkpoint` | |
| would actually resume from. If torch is unavailable the supervisor still | |
| runs, falling back to name-only progress, and says so on stderr. | |
| """ | |
| try: | |
| from align.train.trainer import checkpoint_problem | |
| except Exception as e: # noqa: BLE001 | |
| print(f"supervisor: checkpoint validation unavailable ({type(e).__name__}: {e}); " | |
| "progress is judged by directory name only", file=sys.stderr) | |
| return None | |
| return checkpoint_problem | |
| def main(argv=None) -> int: | |
| ap = argparse.ArgumentParser(description=__doc__.split("\n")[0]) | |
| ap.add_argument("--run-dir", required=True) | |
| ap.add_argument("--max-retries", type=int, default=2) | |
| ap.add_argument("--backoff", type=float, default=30.0, help="base seconds; doubles per retry") | |
| ap.add_argument("--grace", type=float, default=20.0, help="SIGTERM->SIGKILL grace seconds") | |
| ap.add_argument( | |
| "--no-validate-checkpoints", | |
| action="store_true", | |
| help="count a checkpoint dir as progress by NAME only (skips importing torch for the " | |
| "completeness check); a truncated newest dir then counts as progress", | |
| ) | |
| ap.add_argument( | |
| "--retry-on-stop", | |
| action="store_true", | |
| help="also relaunch a run that was stopped by SIGTERM/SIGINT/SIGHUP (exit 143/130/129). " | |
| "Default: an operator's stop is a decision, not a fault, and ends the supervisor", | |
| ) | |
| ap.add_argument("cmd", nargs=argparse.REMAINDER, help="-- child command") | |
| a = ap.parse_args(argv) | |
| cmd = a.cmd[1:] if a.cmd and a.cmd[0] == "--" else a.cmd | |
| if not cmd: | |
| ap.error("no child command given (put it after --)") | |
| res = Supervisor(cmd, a.run_dir, max_retries=a.max_retries, | |
| backoff_s=a.backoff, grace_s=a.grace, retry_on_stop=a.retry_on_stop, | |
| checkpoint_validator=None if a.no_validate_checkpoints | |
| else _checkpoint_validator()).run() | |
| print(f"supervisor: {res.reason} after {res.attempts} attempt(s), " | |
| f"child exits {res.child_codes}", file=sys.stderr) | |
| return res.exit_code | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |