infosec-v1 / code /training /scripts /check_training_gates.py
adhikjoshi's picture
Super-squash branch 'main' using huggingface_hub
994182c
Raw
History Blame Contribute Delete
3.13 kB
#!/usr/bin/env python3
"""Check required artifacts before a training run starts."""
from __future__ import annotations
import argparse
from pathlib import Path
from typing import Any
import yaml
DEFAULT_BASELINE_REPORT = Path("reports/cybergym/qwen36_27b_base/cybergym_base_level1_sample.md")
DEFAULT_FROZEN_TASKS = Path("reports/cybergym/frozen_level1_baseline_tasks.txt")
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--config", required=True, help="Training config YAML.")
parser.add_argument(
"--allow-missing-cybergym-baseline",
action="store_true",
help="Allow local dry-runs before the remote CyberGym baseline exists.",
)
return parser.parse_args()
def read_yaml(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as fh:
payload = yaml.safe_load(fh) or {}
if not isinstance(payload, dict):
raise TypeError(f"Expected a YAML mapping in {path}")
return payload
def existing_path(path: Path) -> Path | None:
candidates = [path]
if not path.is_absolute():
candidates.append(Path("/workspace") / path)
candidates.append(Path("/workspace/infosec") / path)
for candidate in candidates:
if candidate.is_file():
return candidate
return None
def main() -> int:
args = parse_args()
config_path = Path(args.config)
config = read_yaml(config_path)
missing: list[str] = []
warnings: list[str] = []
run_stage = str(config.get("run", {}).get("stage", "unknown"))
baseline_required = run_stage in {"pilot_qlora", "stage1_lora_sft", "stage1_dpo"}
gates = config.get("gates", {}) or {}
baseline_report = Path(gates.get("cybergym_baseline_report", DEFAULT_BASELINE_REPORT))
frozen_tasks = Path(gates.get("frozen_cybergym_tasks", DEFAULT_FROZEN_TASKS))
if baseline_required and not args.allow_missing_cybergym_baseline:
if existing_path(baseline_report) is None:
missing.append(str(baseline_report))
if existing_path(frozen_tasks) is None:
missing.append(str(frozen_tasks))
data = config.get("data", {}) or {}
for key in ("train_jsonl", "validation_jsonl"):
value = data.get(key)
if value and existing_path(Path(value)) is None:
missing.append(str(value))
if data.get("decontamination_required"):
report = data.get("decontamination_report")
if not report:
missing.append("data.decontamination_report (decontamination_required=true but unset)")
elif existing_path(Path(report)) is None:
missing.append(str(report))
print(f"Config: {config_path}")
print(f"Stage: {run_stage}")
if warnings:
print("Warnings:")
for warning in warnings:
print(f" - {warning}")
if missing:
print("Missing required files:")
for path in missing:
print(f" - {path}")
return 2
print("All configured training gates passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())