SaylorTwift HF Staff
Add held-out eval (base vs adapter) + standalone eval job + final eval stage in training job
c511323 verified Download prepare_tasks.py from SaylorTwift/lfm-opencode-lora-rl-code: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/SaylorTwift/lfm-opencode-lora-rl-code/resolve/main/prepare_tasks.py
- Command line
-
hf download hf://SaylorTwift/lfm-opencode-lora-rl-code/prepare_tasks.py
-
curl -L -o prepare_tasks.py https://huggingface.co/SaylorTwift/lfm-opencode-lora-rl-code/resolve/main/prepare_tasks.py
4.53 kB
| """Materialize the pinned 1,000 train / 250 test SmolDataEnvs tasks for HF Sandboxes. | |
| Adapted from the FineEnvs env Space's prepare.py (same pinned revisions, same | |
| instruction and grader hash checks), with one change: every task.toml gets | |
| [environment] docker_image = "docker.io/savatar101/env-data-agent-train:base" | |
| because Harbor's hf-sandbox backend needs a prebuilt image and will not build the | |
| task's environment/Dockerfile. The Dockerfile is a one-line FROM of exactly this | |
| image, so the sandbox runs bit-identical content. | |
| Run once at job startup, then point OPENENV_DATASETS at the output: | |
| python prepare_tasks.py --output /app/prepared | |
| export OPENENV_DATASETS=/app/prepared/datasets/train,/app/prepared/datasets/test | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import shutil | |
| import tomllib | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent | |
| # All tasks share this one base image (their Dockerfile is `FROM <this>` + WORKDIR). | |
| DOCKER_IMAGE = "docker.io/savatar101/env-data-agent-train:base" | |
| DATASETS = { | |
| "train": ( | |
| "FineEnvs/SmolDataEnvs-harbor-train", | |
| "4719635555de1666f374d847baebb500d368e493", | |
| ), | |
| "test": ( | |
| "FineEnvs/SmolDataEnvs-harbor-test", | |
| "b130595b579fc6026ad5762925a9a3b40e72f5bb", | |
| ), | |
| } | |
| GRADER_SHA256 = "16f906e9248fa8b7e1141939e425e88e59d52d65e98e360bbacef3720a43629f" | |
| def task_rows(split): | |
| return json.loads((ROOT / "data" / f"{split}.json").read_text()) | |
| def prepare(destination, splits=("train", "test")): | |
| import tomli_w | |
| from huggingface_hub import snapshot_download | |
| destination = Path(destination).resolve() | |
| for split in splits: | |
| rows = task_rows(split) | |
| repo, revision = DATASETS[split] | |
| source = Path( | |
| snapshot_download( | |
| repo, | |
| repo_type="dataset", | |
| revision=revision, | |
| allow_patterns=[f"tasks/{r['name']}/*" for r in rows], | |
| max_workers=16, | |
| ) | |
| ) | |
| for row in rows: | |
| folder = source / "tasks" / row["name"] | |
| instruction = (folder / "instruction.md").read_bytes() | |
| if hashlib.sha256(instruction).hexdigest() != row["instruction_sha256"]: | |
| raise ValueError(f"Historical task instruction changed: {split}/{row['name']}") | |
| grader = (folder / "tests/grader.py").read_bytes() | |
| if hashlib.sha256(grader).hexdigest() != GRADER_SHA256: | |
| raise ValueError(f"Expected corrected numeric-only Harbor grader: {folder}") | |
| target = destination / "datasets" / split / "tasks" / row["name"] | |
| target.mkdir(parents=True, exist_ok=True) | |
| for rel in ( | |
| "instruction.md", | |
| "task.toml", | |
| "environment/Dockerfile", | |
| "environment/pull_bucket.py", | |
| "tests/grader.py", | |
| "tests/test.sh", | |
| ): | |
| dst = target / rel | |
| dst.parent.mkdir(parents=True, exist_ok=True) | |
| shutil.copyfile(folder / rel, dst) | |
| spec = tomllib.loads((target / "task.toml").read_text()) | |
| spec["environment"]["memory_mb"] = 4096 | |
| spec["environment"]["cpus"] = 1 | |
| # hf-sandbox runs a prebuilt image instead of building environment/Dockerfile. | |
| spec["environment"]["docker_image"] = DOCKER_IMAGE | |
| # Cluster user IDs may not exist inside the sandbox user namespace. | |
| spec["environment"].setdefault("env", {})["TAR_OPTIONS"] = "--no-same-owner" | |
| (target / "task.toml").write_text(tomli_w.dumps(spec)) | |
| print(f"{split}: {len(rows)} tasks -> {destination / 'datasets' / split}") | |
| # Overlap guard, as in the original. | |
| if set(splits) == {"train", "test"}: | |
| def names(split): | |
| return {r["name"] for r in task_rows(split)} | |
| notebooks = [ | |
| {r.get("notebook") for r in task_rows(s)} - {None} for s in ("train", "test") | |
| ] | |
| if names("train") & names("test") or notebooks[0] & notebooks[1]: | |
| raise ValueError("Train/test overlap") | |
| print("no train/test overlap") | |
| if __name__ == "__main__": | |
| p = argparse.ArgumentParser(description=__doc__) | |
| p.add_argument("--output", type=Path, default=ROOT / "prepared") | |
| p.add_argument("--splits", nargs="+", default=["train", "test"], choices=["train", "test"]) | |
| a = p.parse_args() | |
| prepare(a.output, tuple(a.splits)) | |