Download scripts/materialize_opd_only_modelonly_config.py from Jack04810/agentic-rl-main: direct link, hf CLI and curl.
- Browser
- Download file 5.13 kB
-
https://huggingface.co/Jack04810/agentic-rl-main/resolve/main/scripts/materialize_opd_only_modelonly_config.py
- Command line
-
hf download hf://Jack04810/agentic-rl-main/scripts/materialize_opd_only_modelonly_config.py
-
curl -L -o materialize_opd_only_modelonly_config.py https://huggingface.co/Jack04810/agentic-rl-main/resolve/main/scripts/materialize_opd_only_modelonly_config.py
5.13 kB
| #!/usr/bin/env python3 | |
| """Create a self-contained OPD-only model-only recovery recipe. | |
| DeepSpeed ZeRO-2 optimizer partitions are tied to the original world size, so | |
| the four-rank checkpoint cannot be passed to ``Trainer.train(resume...)`` on | |
| another world size. The student model itself is portable. This utility validates a | |
| base recipe, replaces only the student source and output directory, and writes | |
| the fully resolved YAML consumed by the new run. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from typing import Any | |
| import yaml | |
| PROJECT_ROOT = Path(__file__).resolve().parents[1] | |
| if str(PROJECT_ROOT) not in sys.path: | |
| sys.path.insert(0, str(PROJECT_ROOT)) | |
| from config.loader import load_config | |
| def _require_complete_student_checkpoint(path: Path) -> Path: | |
| checkpoint = path.expanduser().resolve(strict=False) | |
| if not checkpoint.is_dir(): | |
| raise FileNotFoundError(f"Student initialization checkpoint is not a directory: {checkpoint}") | |
| if not (checkpoint / "config.json").is_file(): | |
| raise FileNotFoundError(f"Student initialization checkpoint lacks config.json: {checkpoint}") | |
| weight_files = tuple(checkpoint.glob("*.safetensors")) + tuple(checkpoint.glob("*.bin")) | |
| if not weight_files: | |
| raise FileNotFoundError( | |
| f"Student initialization checkpoint lacks model weights (*.safetensors or *.bin): {checkpoint}" | |
| ) | |
| return checkpoint | |
| def _materialize( | |
| *, | |
| base_config: Path, | |
| student_checkpoint: Path, | |
| output_dir: Path, | |
| output_config: Path, | |
| num_gpus: int, | |
| gradient_accumulation_steps: int | None, | |
| ) -> dict[str, Any]: | |
| """Return and atomically write the resolved model-only recovery recipe.""" | |
| config = load_config(str(base_config)) | |
| checkpoint = _require_complete_student_checkpoint(student_checkpoint) | |
| run_output = output_dir.expanduser().resolve(strict=False) | |
| target = output_config.expanduser().resolve(strict=False) | |
| if checkpoint == run_output or checkpoint in run_output.parents: | |
| raise ValueError( | |
| "The new output directory must not contain the model-initialization checkpoint; " | |
| "use a separate output directory for model-only recovery." | |
| ) | |
| training = config["training"] | |
| dyme_args = training["dyme_args"] | |
| model = config["model"] | |
| # These are deliberately the only training-recipe changes. All OPD loss, | |
| # filtering, evaluation, and checkpoint-evaluation settings stay exactly | |
| # those of the validated four-rank recipe. | |
| model["pretrained_model_path"] = str(checkpoint) | |
| model["teacher_device_map"] = "local" | |
| training["num_gpus"] = num_gpus | |
| training["num_client"] = num_gpus | |
| dyme_args["output_dir"] = str(run_output) | |
| if gradient_accumulation_steps is not None: | |
| dyme_args["gradient_accumulation_steps"] = gradient_accumulation_steps | |
| # A model-only process must not attempt to restore the four-rank ZeRO-2 | |
| # optimizer/RNG partitions even if a future base config supplies one. | |
| dyme_args.pop("resume_from_checkpoint", None) | |
| target.parent.mkdir(parents=True, exist_ok=True) | |
| temporary = target.with_name(f".{target.name}.tmp-{os.getpid()}") | |
| with temporary.open("w", encoding="utf-8") as handle: | |
| yaml.safe_dump(config, handle, allow_unicode=True, sort_keys=False) | |
| os.replace(temporary, target) | |
| return config | |
| def parse_args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser( | |
| description="Materialize a self-contained OPD-only model-only recovery YAML." | |
| ) | |
| parser.add_argument("--base-config", type=Path, required=True) | |
| parser.add_argument("--student-checkpoint", type=Path, required=True) | |
| parser.add_argument("--output-dir", type=Path, required=True) | |
| parser.add_argument("--output-config", type=Path, required=True) | |
| parser.add_argument("--num-gpus", type=int, default=3) | |
| parser.add_argument("--gradient-accumulation-steps", type=int, default=None) | |
| return parser.parse_args() | |
| def main() -> None: | |
| args = parse_args() | |
| if args.num_gpus <= 0: | |
| raise ValueError(f"--num-gpus must be positive, got {args.num_gpus}") | |
| if args.gradient_accumulation_steps is not None and args.gradient_accumulation_steps <= 0: | |
| raise ValueError( | |
| "--gradient-accumulation-steps must be positive when provided, " | |
| f"got {args.gradient_accumulation_steps}" | |
| ) | |
| config = _materialize( | |
| base_config=args.base_config, | |
| student_checkpoint=args.student_checkpoint, | |
| output_dir=args.output_dir, | |
| output_config=args.output_config, | |
| num_gpus=args.num_gpus, | |
| gradient_accumulation_steps=args.gradient_accumulation_steps, | |
| ) | |
| print( | |
| f"Materialized {args.num_gpus}-rank model-only OPD recovery config: " | |
| f"student={config['model']['pretrained_model_path']} " | |
| f"output_dir={config['training']['dyme_args']['output_dir']} " | |
| f"config={args.output_config.expanduser().resolve(strict=False)}", | |
| flush=True, | |
| ) | |
| if __name__ == "__main__": | |
| main() | |