TASK.md: handoff for the next agent (state, artifacts, outstanding work, sharp edges)
Browse files
TASK.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# TASK: OpenCode-only RL on LFM2.5-2.6B — state and next steps
|
| 2 |
+
|
| 3 |
+
*Written 2026-10-28 for an agent taking over from here.*
|
| 4 |
+
|
| 5 |
+
## TL;DR
|
| 6 |
+
|
| 7 |
+
We reproduced the OpenCode-only RL run from
|
| 8 |
+
[The ultimate guide to multi-harness RL](https://huggingface.co/spaces/FineEnvs/multi-harness-rl)
|
| 9 |
+
on `LiquidAI/LFM2.5-2.6B` with a LoRA adapter, end to end, entirely on HF
|
| 10 |
+
infrastructure. **The pipeline is complete and battle-tested; the learning outcome
|
| 11 |
+
was flat**: held-out pass@1 never separated from the base model (~12% ± 3% at n=100
|
| 12 |
+
through all 10 checkpoints), and held-out tool-call efficiency did not improve.
|
| 13 |
+
The immediate open item is a clean **250-task final eval** (running now — see
|
| 14 |
+
"Outstanding work" #1).
|
| 15 |
+
|
| 16 |
+
## Where everything lives
|
| 17 |
+
|
| 18 |
+
| Artifact | Location |
|
| 19 |
+
|---|---|
|
| 20 |
+
| Code bundle (this project) | https://huggingface.co/SaylorTwift/lfm-opencode-lora-rl-code |
|
| 21 |
+
| Recipe (architecture, versions, pitfalls) | `RECIPE.md` in that repo — **read it first** |
|
| 22 |
+
| Base model | https://huggingface.co/LiquidAI/LFM2.5-2.6B |
|
| 23 |
+
| Adapter repo (final + checkpoint-100…1000 + all eval JSONs) | https://huggingface.co/SaylorTwift/LFM2.5-2.6B-opencode-lora-RL (private) |
|
| 24 |
+
| Learning curve | `eval/summary.json` in that repo |
|
| 25 |
+
| Task data | `FineEnvs/SmolDataEnvs-harbor-train` / `-test` (pinned revisions, hash-checked by `prepare_tasks.py`) |
|
| 26 |
+
| Article | https://huggingface.co/spaces/FineEnvs/multi-harness-rl |
|
| 27 |
+
| Article's tutorial / env server | GitHub `adithya-s-k/FineEnvs` `05-multi-harness-rl/`; Space `FineEnvs/smoldataenv-multi-harness-harbor` |
|
| 28 |
+
|
| 29 |
+
## What was run and what it produced
|
| 30 |
+
|
| 31 |
+
- **Smoke run** (20 steps) and **four full/partial training runs** across the
|
| 32 |
+
debugging campaign; the last complete one (`6ae06e6f…`, h200x2, resumed from
|
| 33 |
+
checkpoint-500) trained to step 1000 and pushed checkpoints 100–1000 + final.
|
| 34 |
+
- **Eval worker** evaluated every checkpoint on 100 held-out tasks (base evaluated
|
| 35 |
+
twice — both runs agree within 2%).
|
| 36 |
+
- **Curve (pass@1, n=100, base = 12%):**
|
| 37 |
+
100:10, 200:13, 300:11, 400:12, 500:11, 600:8, 700:**15**, 800:10, 900:11, 1000:11.
|
| 38 |
+
- **Tool calls on solved tasks vs base:** checkpoint-800 ×1.10, 900 ×1.04, 1000 ×1.02 —
|
| 39 |
+
no held-out efficiency gain (training-pool tool calls dropped ~21% between two
|
| 40 |
+
windows, but held-out cells say that was task-mix confounding).
|
| 41 |
+
|
| 42 |
+
Config: LoRA r=32/α=64 on q/k/v/out_proj+w1/w2/w3, async GRPO (group of 8, OpenCode
|
| 43 |
+
only), lr 1e-6, 1000 steps, temp 1.0/top_p 1.0/top_k 0, reward = correctness + ≤0.1
|
| 44 |
+
tool-efficiency bonus, output cap 4096, agent budget 32 calls. Full details in RECIPE.md.
|
| 45 |
+
|
| 46 |
+
## What is already proven (do not re-derive)
|
| 47 |
+
|
| 48 |
+
- HF Sandboxes (`harbor[hf-sandbox]`, hf-sandbox backend, needs `docker_image` in
|
| 49 |
+
task.toml — `prepare_tasks.py` patches it) run OpenCode unmodified.
|
| 50 |
+
- Capture proxy records exact tokens+logprobs; importance ratio 0.997–1.01.
|
| 51 |
+
- Merged-weight LoRA sync over NCCL: 136 ms/step at 2.6B.
|
| 52 |
+
- Jobs-proxy exposure (`expose_public=[8000]` + `SPACE_HOST=$JOB_ID--8000.hf.jobs`)
|
| 53 |
+
is stable for multi-day runs; the Gradio tunnel is not (it killed one run) and the
|
| 54 |
+
Jobs proxy **strips Authorization**, hence the x-api-key seam patch in the entrypoints.
|
| 55 |
+
- Watchdog (30-min stall → loud fail) + per-100-step checkpoint pushes (transformers v5
|
| 56 |
+
has no PushToHubCallback) + resume-from-repo all work.
|
| 57 |
+
- trl must be **1.15.0** (1.16's tree packing rejects hybrid models) on **vllm 0.31.0**,
|
| 58 |
+
with `kernels==0.16.0`.
|
| 59 |
+
|
| 60 |
+
## Outstanding work, in priority order
|
| 61 |
+
|
| 62 |
+
1. **Finish the clean 250-task final eval.** Job `6ae2026e3fb22a235dd409c2` is running
|
| 63 |
+
(`run_eval.sh`, now fixed and hardened: test-only split + Jobs-proxy path). It writes
|
| 64 |
+
`eval/final_v2_results.json`. A previous attempt produced `eval/final_results.json`
|
| 65 |
+
but is **invalid** (env server had degraded after 11h; 247/250 cells failed per
|
| 66 |
+
model — openenv client bug masks connection errors as `TypeError: object NoneType
|
| 67 |
+
can't be used in 'await' expression`). Overwrite/ignore `eval/final_results.json`.
|
| 68 |
+
If the job died, relaunch: `run_eval.sh` with env
|
| 69 |
+
`ADAPTER_REPO=SaylorTwift/LFM2.5-2.6B-opencode-lora-RL, N_TASKS=250, EVAL_TAG=final_v2`,
|
| 70 |
+
via `huggingface_hub.run_job(..., expose_public=[8000], flavor="h200", timeout="6h")`.
|
| 71 |
+
2. **Interpret the final eval** (250 tasks, ±2% error bars). If it confirms flat:
|
| 72 |
+
the honest finding is *r=32 LoRA undertrains this model for agentic RL*.
|
| 73 |
+
3. **The natural follow-up run, in order of expected value:**
|
| 74 |
+
a. **r=64 (or 128) LoRA** — one-line config change (`LoraConfig` in `train_lora.py`),
|
| 75 |
+
plus `--max-lora-rank 64` wherever `--max-lora-rank 32` appears. Everything else identical.
|
| 76 |
+
b. **Full fine-tune** (drop `peft_config`) — the article's actual setup; merged sync
|
| 77 |
+
makes weight transfers ~5.2 GB/step (was fine at 136 ms/step).
|
| 78 |
+
c. **SFT warm-start then RL** — the article's `FineEnvs/SmolDataEnvs-multiharness-sft`
|
| 79 |
+
dataset is public and pre-tokenized for LFM2.5-2.6B; their runs showed SFT+RL > RL alone
|
| 80 |
+
is the natural question. SFT took 1.5–6.5h of trainer time in the article.
|
| 81 |
+
d. If pass@1 still won't move: raise training temperature exploration, check that the
|
| 82 |
+
100-task eval subset isn't saturated/hard-skewed (compare a random-100 draw), or
|
| 83 |
+
evaluate a *bigger* base model on the same stack.
|
| 84 |
+
4. **Backfill efficiency metrics for checkpoints 100–700** — delete
|
| 85 |
+
`eval/checkpoint-{100..700}_results.json` from the adapter repo and run
|
| 86 |
+
`run_eval_watch.sh` for one pass (~2h total) if the complete efficiency curve matters.
|
| 87 |
+
5. **Housekeeping:** flip `SaylorTwift/LFM2.5-2.6B-opencode-lora-RL` to public when
|
| 88 |
+
publishing; `export_adapter.py` regenerates the model card. The stalled-run artifacts
|
| 89 |
+
(jobs `6ada06b…` through `6adf625f…`) can be inspected with `hf jobs inspect/logs`.
|
| 90 |
+
|
| 91 |
+
## Known sharp edges (all documented in RECIPE.md's pitfalls section)
|
| 92 |
+
|
| 93 |
+
- HF Jobs proxy strips `Authorization` → session id must also ride `x-api-key`
|
| 94 |
+
(patched into the OpenCode seam by every `run_*.sh` entrypoint).
|
| 95 |
+
- Jobs proxy URL: `https://<JOB_ID>--8000.hf.jobs` (ports double-dashed).
|
| 96 |
+
- `run_eval.sh`/`run_job.sh` must serve **only the splits they prepared**
|
| 97 |
+
(`OPENENV_DATASETS`) — a missing split dir crashes the env server at boot.
|
| 98 |
+
- Long-lived env servers degrade (websocket error loop after ~11h) — prefer fresh
|
| 99 |
+
servers per eval; don't reuse the training job's server for the final eval.
|
| 100 |
+
- openenv 0.10.0's MCP client masks connection failures with
|
| 101 |
+
`TypeError: object NoneType can't be used in 'await' expression` — if you see that,
|
| 102 |
+
it's a connection problem, not the code path you're reading.
|
| 103 |
+
- `hf jobs logs` retains a bounded window; pull early, grep locally.
|
| 104 |
+
|
| 105 |
+
## Ops cheatsheet
|
| 106 |
+
|
| 107 |
+
```bash
|
| 108 |
+
hf jobs ps --all # list jobs
|
| 109 |
+
hf jobs logs SaylorTwift/<id> # fetch logs (grep locally, logs are big)
|
| 110 |
+
hf jobs inspect SaylorTwift/<id> --format json # status incl. stage/message
|
| 111 |
+
hf jobs cancel SaylorTwift/<id>
|
| 112 |
+
hf download <repo> --include "eval/*" # grab results
|
| 113 |
+
# Launch pattern: huggingface_hub.run_job(..., expose_public=[8000], timeout="6h",
|
| 114 |
+
# flavor="h200", env={...}, secrets={"HF_TOKEN": token})
|
| 115 |
+
# (The CLI lacks expose_public; the eval path needs it because HF Jobs
|
| 116 |
+
# auth-gated --expose breaks sandbox→proxy calls.)
|
| 117 |
+
```
|