feat: train on replayed rollouts — continue (compaction/tool-call) + recheck envs#2962
Draft
faresobeid wants to merge 14 commits into
Draft
feat: train on replayed rollouts — continue (compaction/tool-call) + recheck envs#2962faresobeid wants to merge 14 commits into
faresobeid wants to merge 14 commits into
Conversation
…recheck envs Bump verifiers for the new built-in v1 replay taskset: point a train env at saved rollout records and the source taskset, and each record re-enters training as a fresh task scored by the original env's verifier. Continue resumes from a recorded compaction handoff (any harness) or right after a drawn tool result; recheck replays the finished attempt with a verification turn appended. Zero orchestrator changes — it's all env config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Capability-gate/state delegation seams, pool-worker config round-trips, frozen record globs, snapshot-contract enforcement, and file-based Messages seeding; docs updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…napshot semantics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TrainSource.refresh() re-polls each env's info at ship time (one in-flight refresh, off the ship path) and extends its cycle with new task indices, so a follow-mode replay env pointed at this run's own rollouts/ dir feeds newly recorded tasks back into training. save_rollouts writes tmp+rename so a follower never reads a half-written step file; next_example tolerates an env with no tasks yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-id subdir Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live-tests replay CONTINUE mode with anchor="tool-call": both train envs use the default harness so source rollouts contain real tool calls, and the replay env re-enters them mid-conversation through the harness's INITIAL_MESSAGES file transport. Uses output_dir=outputs-continue to avoid colliding with the recheck debug run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Bump deps/verifiers for the replay-loader cleanup (lazy incremental state, stale freeze-era comments removed; no behavior changes). - gsm8k_recheck.toml: the launch line now points at this config instead of gsm8k.toml, drop the duplicated derivation blurb, add trailing newline. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… bump Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
train_rollouts_<env>.jsonl per step (mirroring eval's convention), so record consumers select an env by filename instead of parsing and discarding other envs' lines; replay configs/docs updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ulti-anchor Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
save_rollouts now returns each line's (offset, length) byte span, and finalize_train_batch writes a derived index_<env>.jsonl beside every train_rollouts_<env>.jsonl (same tmp+rename path): one row per record with selection fields (trace id, task idx/name, reward, policy version, step, branch/turn counts, stop condition) plus the record's byte span. Replay (verifiers bump) uses the index to filter records — replayed names, source reward, branch count — and parse only the selected spans; record files are byte-identical and an absent index means full parse. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…index write - New save_train_records helper (orchestrator/utils.py) does the whole per-env write in one thread: to_record dump, records file, index rows via the replay taskset's index_row/index_path contract, index file. finalize_train_batch now buckets with TrainRollouts.by_env() and gathers one to_thread per env — to_record moves off the event loop. - save_rollouts stays the generic atomic-JSONL primitive; docstring now says what it does (writes dicts, returns byte spans). - Bump deps/verifiers: index selection consolidated into iter_selected_records; index_path/index_row exported for writers. - Fix stale launch comment in gsm8k_recheck_incorrect.toml and the record-glob in the configs skill + docs (*_rollouts_*.jsonl). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Train on replayed rollouts: point a train env at saved rollout records (
<output_dir>/rollouts/step_*/*_rollouts.jsonl) and each record re-enters training as a fresh task, scored by the original env's verifier with its real toolkit. Zero orchestrator changes — the whole feature is the new built-in verifiers v1replaytaskset (PrimeIntellect-ai/verifiers#1933, which this PR's submodule bump pins), driven purely by env config:anchor = "compaction"default, or"tool-call") trains dense mid-trajectory credit: a failed 40-turn rollout that gave one sparse 0.0 becomes a fresh GRPO group seeded exactly at the state where the policy was struggling — the compaction variant additionally trains working from a handoff summary. Compaction restarts are detected structurally from the trace's branch graph (no compaction-prompt matching), so records from different harnesses mix freely.last_reply-style rewards.Group rollouts of one seeded task form a regular GRPO group; uniform-outcome groups drop via the existing zero-advantage filter.
Changes in this repo
deps/verifiersbump → thereplaytaskset + the framework seams it needs (see the verifiers PR for the shared-surface details: Taskset capability/discovery seams,Messages-prompt file transport fordefault/null).docs/configuration.md: new "Replaying Past Rollouts (Continue / Recheck)" section (worked TOML, knobs, harness-support matrix, glob-freezing and mixed-file caveats).skills/configs/SKILL.md: replay-env config pattern.Notes for review
recordsglobs are frozen to concrete files at config validation so every env-server pool worker builds the identical task list — point them at a finished run's records, not a live producer's output dir.setup); the snapshot seam exists in the taskset (records carryingtrace.info["snapshots"]refs restrict resume points to snapshotted anchors and restore during setup) but no runtime implements capture yet.ReplayTaskset.seeds(trace).Verification
TrainEnvConfignarrowstaskset→ReplayConfigand nestedsource→ the source taskset's config type; recheck+anchor conflicts rejected; resolved-config dump→re-validate round trip (the env-server spawn path) is clean;Environmentconstruction under therlmharness passes the capability gates.load_taskspass over real rlm prod records (the /beegfs eval files were rotated away mid-development) and a first live GRPO run with a replay env.🤖 Generated with Claude Code
Update: online self-replay
The replay env can now feed on the run's own records as they are produced (no prior run needed): point
recordsat this run'srollouts/step_*/train_rollouts.jsonl. Orchestrator side:TrainSource.refresh()re-polls envinfoat each ship (one in-flight refresh, off the ship path) and extends the sampling cycle with new task indices;save_rolloutswrites tmp+rename so a follower never reads a half-written step file;next_exampletolerates a follow env with no tasks yet (records appear with the first steps).Update: per-env records + live validation
Train rollout records are now written per env (train_rollouts_.jsonl, mirroring eval). Replay adds
min/max_source_rewardandmax_anchorsknobs. Three live debug runs validate the loop end-to-end: online recheck (17.6k tasks mined), tool-call continue (mid-conversation seeds through the file transport, 0 errors, 100 steps), and incorrect-only recheck (repair rate improved 31.4%→36.9% early→late while base env rose 0.75→0.84). Debug configs: configs/debug/v1/gsm8k_recheck*.toml, gsm8k_continue_tool.toml.Update: rollout record index
save_rolloutsnow returns each line's(offset, length)byte span, andfinalize_train_batchwrites a derivedindex_<env>.jsonlbeside everytrain_rollouts_<env>.jsonl(same tmp+rename atomicity): one row per record with trace id, task idx/name, reward, policy version, step, branch/turn counts, stop condition, and the record's byte span. The replay taskset (verifiers bump) filters records index-side and parses only the selected spans — in a synthetic 500-record file with a 10% pass rate, index-selected loading parsed 10% of the bytes. Record files stay byte-identical; the index is optional and derived — a record source without one is fully parsed as before. Docs:docs/configuration.mdreplay section + configs skill.Update: cleanup pass
Record + index writing moved into one
save_train_recordshelper (orchestrator/utils.py): per-envto_recorddump, records file, index rows via the replay taskset'sindex_row/index_pathcontract, and index file all run in a singleasyncio.to_threadper env (gathered across envs), takingto_recordoff the event loop.save_rolloutsstays the generic atomic-JSONL primitive. Also fixes the stale launch comment ingsm8k_recheck_incorrect.tomland the record glob in the configs skill + docs (*_rollouts_*.jsonl). Verifiers bumped to the consolidatediter_selected_recordsAPI.