RECIPE: document per-checkpoint eval worker
Browse files
RECIPE.md
CHANGED
|
@@ -144,13 +144,40 @@ the job's own public URL → start the 30-min watchdog → train (GPU 0) → fin
|
|
| 144 |
+ the matching API key also works if you prefer those backends; then the Jobs-proxy
|
| 145 |
plumbing is unnecessary.)
|
| 146 |
|
| 147 |
-
### Evaluation (
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
|
| 155 |
---
|
| 156 |
|
|
@@ -199,6 +226,7 @@ A standalone version (`run_eval.sh`) runs the same comparison on any checkpoint.
|
|
| 199 |
| `train_lora.py` | trainer + worker wiring, reward, LoRA config, upload & heartbeat callbacks |
|
| 200 |
| `run_job.sh` | job entrypoint: setup, seam patch, 3 processes, watchdog, final eval |
|
| 201 |
| `run_eval.sh` | standalone base-vs-adapter eval job |
|
|
|
|
| 202 |
| `eval_adapter.py` | held-out eval loop (pass@1, agreement breakdown) |
|
| 203 |
| `prepare_tasks.py` + `data/` | pinned, hash-checked task materialization (+ `docker_image` patch) |
|
| 204 |
| `serve_policy.sh` / `serve_env.sh` | the two servers, for multi-machine setups |
|
|
|
|
| 144 |
+ the matching API key also works if you prefer those backends; then the Jobs-proxy
|
| 145 |
plumbing is unnecessary.)
|
| 146 |
|
| 147 |
+
### Evaluation (two layers)
|
| 148 |
|
| 149 |
+
**Per-checkpoint, live** — a separate eval-worker job (`run_eval_watch.sh`, 1×H200)
|
| 150 |
+
polls the adapter repo; every time a new `checkpoint-N` appears it hot-loads it as a
|
| 151 |
+
LoRA into its running vLLM (runtime LoRA updates, no restart) and evals it on a fixed
|
| 152 |
+
100-task test subset. Base-model cells are computed once and reused. Results:
|
| 153 |
+
`eval/<checkpoint-N>_results.json` + a rolling **`eval/summary.json` — the live
|
| 154 |
+
learning curve**. Launch it alongside training:
|
| 155 |
+
|
| 156 |
+
```bash
|
| 157 |
+
uv run --with 'huggingface_hub>=1.29' python - <<'EOF'
|
| 158 |
+
import os
|
| 159 |
+
from huggingface_hub import run_job
|
| 160 |
+
token = os.popen("hf auth token").read().strip()
|
| 161 |
+
run_job(
|
| 162 |
+
image="vllm/vllm-openai:v0.31.0",
|
| 163 |
+
command=["bash", "-c",
|
| 164 |
+
"pip -q install huggingface_hub && "
|
| 165 |
+
"hf download YOU/lfm-opencode-lora-rl-code --local-dir /app && "
|
| 166 |
+
"bash /app/run_eval_watch.sh"],
|
| 167 |
+
flavor="h200", timeout="48h",
|
| 168 |
+
env={"ADAPTER_REPO": "YOU/LFM2.5-2.6B-opencode-lora-RL", "N_TASKS": "100"},
|
| 169 |
+
secrets={"HF_TOKEN": token},
|
| 170 |
+
expose_public=[8000],
|
| 171 |
+
token=token,
|
| 172 |
+
)
|
| 173 |
+
EOF
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
**Final, full** — after training, the training job itself restarts vLLM with the
|
| 177 |
+
final adapter and runs all 250 test tasks twice (base vs final) →
|
| 178 |
+
`eval/final_results.json`. (`purpose="eval"` is required when passing
|
| 179 |
+
`eval_sampling`.) A standalone version (`run_eval.sh`) runs the same comparison on
|
| 180 |
+
any checkpoint.
|
| 181 |
|
| 182 |
---
|
| 183 |
|
|
|
|
| 226 |
| `train_lora.py` | trainer + worker wiring, reward, LoRA config, upload & heartbeat callbacks |
|
| 227 |
| `run_job.sh` | job entrypoint: setup, seam patch, 3 processes, watchdog, final eval |
|
| 228 |
| `run_eval.sh` | standalone base-vs-adapter eval job |
|
| 229 |
+
| `run_eval_watch.sh` + `eval_watch.py` | per-checkpoint eval worker (live learning curve) |
|
| 230 |
| `eval_adapter.py` | held-out eval loop (pass@1, agreement breakdown) |
|
| 231 |
| `prepare_tasks.py` + `data/` | pinned, hash-checked task materialization (+ `docker_image` patch) |
|
| 232 |
| `serve_policy.sh` / `serve_env.sh` | the two servers, for multi-machine setups |
|