[Sync][A] rollout data-model: micro-batch scheduling rollout-side + variable global batch + group_ids (slime #1926/#1930/#1933/#1941/#1959/#1965/#1969/#1984/#1962) - #145
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for compact/subagent fan-out patterns where a single rollout execution can emit multiple training samples sharing a single group ID. It implements a group-aware DP/microbatch scheduler, precomputes per-group mask sums to ensure correct loss denominators across micro-batches, and updates loss scaling and learning rate scheduling to use the actual step global batch size. Additionally, it adds a raw Megatron-to-HF checkpoint saver and comprehensive unit and end-to-end tests. Feedback from the review suggests interleaving micro-batch indices across virtual stages in VPP mode, replacing __getattribute__ overrides on Sample with standard properties to avoid performance overhead, guarding against division by zero in loss scaling, and supporting tuples in rollout output validation.
| def get_data_iterator(rollout_data: RolloutBatch) -> list[DataIterator]: | ||
| """Build one ``DataIterator`` per VPP stage from the pre-computed schedule in ``rollout_data``.""" | ||
| vpp_size = mpu.get_virtual_pipeline_model_parallel_world_size() or 1 | ||
| micro_batch_indices = rollout_data["micro_batch_indices"] | ||
| return [DataIterator(rollout_data, micro_batch_indices) for _ in range(vpp_size)] |
There was a problem hiding this comment.
In virtual pipeline parallel (VPP) training (vpp_size > 1), passing the same flat micro_batch_indices list to all DataIterator instances causes each virtual stage to process the exact same microbatches in the same order. This leads to duplicate data processing and incorrect training behavior.
To fix this, the microbatches should be interleaved across the virtual stages (e.g., micro_batch_indices[i::vpp_size] for stage i).
| def get_data_iterator(rollout_data: RolloutBatch) -> list[DataIterator]: | |
| """Build one ``DataIterator`` per VPP stage from the pre-computed schedule in ``rollout_data``.""" | |
| vpp_size = mpu.get_virtual_pipeline_model_parallel_world_size() or 1 | |
| micro_batch_indices = rollout_data["micro_batch_indices"] | |
| return [DataIterator(rollout_data, micro_batch_indices) for _ in range(vpp_size)] | |
| def get_data_iterator(rollout_data: RolloutBatch) -> list[DataIterator]: | |
| """Build one ``DataIterator`` per VPP stage from the pre-computed schedule in ``rollout_data``.""" | |
| vpp_size = mpu.get_virtual_pipeline_model_parallel_world_size() or 1 | |
| micro_batch_indices = rollout_data["micro_batch_indices"] | |
| return [DataIterator(rollout_data, micro_batch_indices[i::vpp_size]) for i in range(vpp_size)] |
| def __getattribute__(self, name): | ||
| if name == "rollout_id": | ||
| raise AttributeError("Sample.rollout_id is deprecated and write-only; use Sample.group_id instead.") | ||
| return object.__getattribute__(self, name) | ||
|
|
||
| def __setattr__(self, name, value): | ||
| if name == "group_id": | ||
| object.__setattr__(self, "group_id", value) | ||
| return | ||
| if name == "rollout_id": | ||
| # Deprecated assignment-only compatibility path. ``rollout_id`` is | ||
| # intentionally not a dataclass field and cannot be read. | ||
| if value is None: | ||
| return | ||
| warnings.warn( | ||
| "Sample.rollout_id is deprecated and write-only; set Sample.group_id instead.", | ||
| DeprecationWarning, | ||
| stacklevel=2, | ||
| ) | ||
| object.__setattr__(self, "group_id", value) | ||
| return | ||
| object.__setattr__(self, name, value) |
There was a problem hiding this comment.
Overriding __getattribute__ and __setattr__ to handle the deprecated rollout_id attribute introduces a significant performance overhead for every attribute access on Sample instances. In RL training, where millions of attributes are accessed, this can noticeably slow down data processing.
Using a standard Python property with a custom getter and setter achieves the exact same deprecation behavior with zero overhead for other attributes, and is much more idiomatic.
@property
def rollout_id(self):
raise AttributeError("Sample.rollout_id is deprecated and write-only; use Sample.group_id instead.")
@rollout_id.setter
def rollout_id(self, value):
if value is None:
return
warnings.warn(
"Sample.rollout_id is deprecated and write-only; set Sample.group_id instead.",
DeprecationWarning,
stacklevel=2,
)
self.group_id = value| if not args.calculate_per_token_loss: | ||
| loss = ( | ||
| loss * num_microbatches / global_batch_size * mpu.get_data_parallel_world_size(with_context_parallel=True) | ||
| loss | ||
| * num_microbatches | ||
| / step_global_batch_size | ||
| * mpu.get_data_parallel_world_size(with_context_parallel=True) | ||
| ) |
There was a problem hiding this comment.
If step_global_batch_size is 0 (which can happen in distributed settings with empty partitions or heavy filtering), dividing by it will raise a ZeroDivisionError and crash the training run.
Consider guarding against division by zero by using max(step_global_batch_size, 1).
| if not args.calculate_per_token_loss: | |
| loss = ( | |
| loss * num_microbatches / global_batch_size * mpu.get_data_parallel_world_size(with_context_parallel=True) | |
| loss | |
| * num_microbatches | |
| / step_global_batch_size | |
| * mpu.get_data_parallel_world_size(with_context_parallel=True) | |
| ) | |
| if not args.calculate_per_token_loss: | |
| loss = ( | |
| loss | |
| * num_microbatches | |
| / max(step_global_batch_size, 1) | |
| * mpu.get_data_parallel_world_size(with_context_parallel=True) | |
| ) |
| def _validate_group_id_annotated(node, depth=0): | ||
| """Walk the rollout function's nested output and validate ``group_id`` only | ||
| when a compact / subagent pattern is detected. | ||
|
|
||
| "Compact" = the rollout function wraps multiple training samples from one | ||
| rollout execution into a ``list[Sample]``. In slime's convention the | ||
| default rollout shape is ``list[list[Sample]]`` (depth-2: prompt × rollout) | ||
| so its leaf ``list[Sample]`` lands at depth 1 and we skip validation, | ||
| preserving backward compatibility. A compact rollout adds a third level: | ||
| ``list[list[list[Sample]]]`` (prompt × rollout × samples-from-one-group), | ||
| so the leaf ``list[Sample]`` lands at depth ≥ 2. At that point we require | ||
| every sibling to carry a non-None ``group_id`` (or legacy ``rollout_id``) | ||
| and to share the same value, so the loss reducer counts the group once | ||
| instead of N times. | ||
| """ | ||
| if isinstance(node, Sample): | ||
| return | ||
| assert isinstance(node, list), f"unexpected rollout output node type: {type(node).__name__}" | ||
| if node and isinstance(node[0], Sample): | ||
| if depth >= 2 and len(node) > 1: | ||
| group_ids = [s.group_id for s in node] | ||
| missing = [i for i, group_id in enumerate(group_ids) if group_id is None] | ||
| assert not missing, ( | ||
| f"Compact rollout returned {len(node)} samples but group_id is unset on " | ||
| f"positions {missing}. Set Sample.group_id on every sibling so the loss " | ||
| "reducer can aggregate them as one group instead of N." | ||
| ) | ||
| assert ( | ||
| len(set(group_ids)) == 1 | ||
| ), f"Sibling samples from one compact rollout must share group_id; got {group_ids}." | ||
| return | ||
| for item in node: | ||
| _validate_group_id_annotated(item, depth + 1) |
There was a problem hiding this comment.
Strictly asserting isinstance(node, list) can cause unexpected crashes if a custom rollout function returns a tuple of Samples (which is common in Python). Supporting both list and tuple makes the validation much more robust.
def _validate_group_id_annotated(node, depth=0):
"""Walk the rollout function's nested output and validate ``group_id`` only
when a compact / subagent pattern is detected.
"Compact" = the rollout function wraps multiple training samples from one
rollout execution into a ``list[Sample]``. In slime's convention the
default rollout shape is ``list[list[Sample]]`` (depth-2: prompt × rollout)
so its leaf ``list[Sample]`` lands at depth 1 and we skip validation,
preserving backward compatibility. A compact rollout adds a third level:
``list[list[list[Sample]]]`` (prompt × rollout × samples-from-one-group),
so the leaf ``list[Sample]`` lands at depth ≥ 2. At that point we require
every sibling to carry a non-None ``group_id`` (or legacy ``rollout_id``)
and to share the same value, so the loss reducer counts the group once
instead of N times.
"""
if isinstance(node, Sample):
return
assert isinstance(node, (list, tuple)), f"unexpected rollout output node type: {type(node).__name__}"
if node and isinstance(node[0], Sample):
if depth >= 2 and len(node) > 1:
group_ids = [s.group_id for s in node]
missing = [i for i, group_id in enumerate(group_ids) if group_id is None]
assert not missing, (
f"Compact rollout returned {len(node)} samples but group_id is unset on "
f"positions {missing}. Set Sample.group_id on every sibling so the loss "
"reducer can aggregate them as one group instead of N."
)
assert (
len(set(group_ids)) == 1
), f"Sibling samples from one compact rollout must share group_id; got {group_ids}."
return
for item in node:
_validate_group_id_annotated(item, depth + 1)8803d18 to
68d40fa
Compare
…ang->vLLM Port THUDM/slime PR-G examples to vime's vLLM rollout: - #1921 streaming: vime/rollout/vllm_streaming_rollout.py consumes the vLLM /inference/v1/generate SSE stream. Key translation: sglang streams CUMULATIVE output_token_logprobs (overwrite per chunk); vLLM SSE sends DELTA token_ids+ logprobs per chunk -> accumulate (+=) and re-decode accumulated tokens each chunk (multi-byte safe), finalize via _vllm_meta_from_generate_choice. MM raises NotImplementedError (two-call render->generate doesn't fit one stream -> use non-streaming generate). + CI test test_qwen3_4B_streaming_partial_rollout. (streaming file is the reviewed sync/slime-pr-1921 / draft #117 design.) - #1861 retool: re-add examples/retool/generate_with_retool.py (vime lacked examples/retool/) from slime base + #1861 hardening; desync guard `if not meta_info.get("output_token_logprobs")`. NOTE: depends on sibling tool_sandbox.py (not yet ported -> follow-up; example partial until then). Based on PR-A (#145) branch (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
…/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961), sglang->vLLM Add the agent-in-sandbox RL subsystem vime lacked. New vime/agent/ (trajectory, sandbox, parsing, adapters: common/openai/anthropic) + examples/coding_agent_rl/ (demo, generate, sandbox, aiohttp_threaded, run script). Copied slime's final state (all 11 D PRs applied) + translated. 3 sglang->vLLM seams: - adapters/common.py: call_sglang_generate -> call_engine_generate; POST /generate -> /inference/v1/generate; body input_ids->token_ids + max_new_tokens->max_tokens + drop return_logprob + add logprobs:1 + model=; response output_token_logprobs -> choices[0].token_ids + logprobs.content[].logprob (via canonical field map); per-rid /abort_request -> task.cancel() + connection teardown on cancel. - coding_agent_rl/generate.py: sglang_router_ip/port -> vllm_router_ip/port. - parsing.py: NO change (ReasoningParser/FunctionCallParser lazy; coding_agent_rl defaults to XML fallback). #1984 agent-half rename (rollout_id->group_id in trajectory.py) already present (copied slime HEAD; consistent with PR-A's Sample.group_id). EAGLE spec left commented (needs draft-model path). Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
slime #2013 reverts #1984 (the rollout_id->group_id rename) because it conflicts with internal tooling. A #145 ported #1984, so mirror the revert to stay byte-faithful and realign with main + post-#2013 slime: group_id -> rollout_id, group_ids -> rollout_ids, group_mask_sums -> rollout_mask_sums, num_groups_in_rollout -> num_rollouts_in_rollout, and drop the Sample.rollout_id deprecation guard (__getattribute__/__setattr__ + import warnings) #1984 had added. Per-file churn matches slime #2013 exactly (actor/data/loss/model/rollout/ _fanout_test_helpers/forge_load/dp_schedule/types + 3 tests). The unrelated compute_pass_rate(num_groups=...) kwarg is left as-is (slime keeps it too). NOTE: #2013 also reverts D-side files not present on A (examples/coding_agent_rl/*, vime/agent/trajectory.py, docs .../agent.md, the group_id sections of docs customization.md + multi_agent stamping). Those must get the same revert when D #148 is rebased onto this A.
…/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961), sglang->vLLM Add the agent-in-sandbox RL subsystem vime lacked. New vime/agent/ (trajectory, sandbox, parsing, adapters: common/openai/anthropic) + examples/coding_agent_rl/ (demo, generate, sandbox, aiohttp_threaded, run script). Copied slime's final state (all 11 D PRs applied) + translated. 3 sglang->vLLM seams: - adapters/common.py: call_sglang_generate -> call_engine_generate; POST /generate -> /inference/v1/generate; body input_ids->token_ids + max_new_tokens->max_tokens + drop return_logprob + add logprobs:1 + model=; response output_token_logprobs -> choices[0].token_ids + logprobs.content[].logprob (via canonical field map); per-rid /abort_request -> task.cancel() + connection teardown on cancel. - coding_agent_rl/generate.py: sglang_router_ip/port -> vllm_router_ip/port. - parsing.py: NO change (ReasoningParser/FunctionCallParser lazy; coding_agent_rl defaults to XML fallback). #1984 agent-half rename (rollout_id->group_id in trajectory.py) already present (copied slime HEAD; consistent with PR-A's Sample.group_id). EAGLE spec left commented (needs draft-model path). Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
…3, D-side) Rebased D's own commits onto the updated A #145 (which now carries slime #2013). A #145 reverted the shared data-model to rollout_id; this completes the same revert for D's own files that A doesn't carry: examples/coding_agent_rl/ {README.md,generate.py} and vime/agent/trajectory.py. After this the whole A+D surface is consistent on rollout_id, matching post-#2013 slime.
…ang->vLLM Port THUDM/slime PR-G examples to vime's vLLM rollout: - #1921 streaming: vime/rollout/vllm_streaming_rollout.py consumes the vLLM /inference/v1/generate SSE stream. Key translation: sglang streams CUMULATIVE output_token_logprobs (overwrite per chunk); vLLM SSE sends DELTA token_ids+ logprobs per chunk -> accumulate (+=) and re-decode accumulated tokens each chunk (multi-byte safe), finalize via _vllm_meta_from_generate_choice. MM raises NotImplementedError (two-call render->generate doesn't fit one stream -> use non-streaming generate). + CI test test_qwen3_4B_streaming_partial_rollout. (streaming file is the reviewed sync/slime-pr-1921 / draft #117 design.) - #1861 retool: re-add examples/retool/generate_with_retool.py (vime lacked examples/retool/) from slime base + #1861 hardening; desync guard `if not meta_info.get("output_token_logprobs")`. NOTE: depends on sibling tool_sandbox.py (not yet ported -> follow-up; example partial until then). Based on PR-A (#145) branch (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
…no image rebuild Port THUDM/slime delta weight sync to vime's vLLM rollout. Trainer bytewise-diffs weights vs a pinned-CPU snapshot and ships only changed positions+values (nccl broadcast or disk safetensors); receiver overwrites only the changed bytes (lossless, NaN-masked). Bandwidth optimization for large / cross-DC non-colocate. - delta_io.py: DeltaEncoding/DeltaParam/DeltaSpec (local; slime imported from sglang io_struct). - update_weight_from_distributed_delta.py: trainer encoder (subclasses UpdateWeightFromDistributed). - delta_receiver.py: engine-agnostic pure-torch decode + NaN-masked apply (param_storage_index / delta_apply_context monkey-patches torch.Tensor.copy_/fill_ scoped to model param storage, wrapping a normal model.load_weights). - vLLMColocateWorkerExtension: collective_rpc-callable delta receivers (nccl: recv positions/values on model_update_group; disk: read safetensors). NO image rebuild -- receiver is runtime worker-extension/hijack, like the existing IPC hijack. - args: --update-weight-mode/transport/encoding/delta-dir/keep-files/chunk-bytes. - actor.py: delta-mode dispatch (lazy import, #1946 backward-compat) + zero-delta version bump. - docs/zh/advanced/delta-weight-sync.md (+toctree) + e2e test test_delta_weight_update.py (CI registered). SKIPPED: #1993 (sglang EAGLE draft-worker delta forwarding) = N/A, no vime/vLLM analogue. CAVEAT (documented): vLLM does not refresh EAGLE/MTP draft weights on ANY sync (main-model only) -- vLLM-wide limitation, not delta-specific; upstream-track. Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
* [Sync][G] streaming rollout + retool example (slime #1921/#1861), sglang->vLLM Port THUDM/slime PR-G examples to vime's vLLM rollout: - #1921 streaming: vime/rollout/vllm_streaming_rollout.py consumes the vLLM /inference/v1/generate SSE stream. Key translation: sglang streams CUMULATIVE output_token_logprobs (overwrite per chunk); vLLM SSE sends DELTA token_ids+ logprobs per chunk -> accumulate (+=) and re-decode accumulated tokens each chunk (multi-byte safe), finalize via _vllm_meta_from_generate_choice. MM raises NotImplementedError (two-call render->generate doesn't fit one stream -> use non-streaming generate). + CI test test_qwen3_4B_streaming_partial_rollout. (streaming file is the reviewed sync/slime-pr-1921 / draft #117 design.) - #1861 retool: re-add examples/retool/generate_with_retool.py (vime lacked examples/retool/) from slime base + #1861 hardening; desync guard `if not meta_info.get("output_token_logprobs")`. NOTE: depends on sibling tool_sandbox.py (not yet ported -> follow-up; example partial until then). Based on PR-A (#145) branch (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * [Sync][G] add retool tool_sandbox.py (in-process tool registry, verbatim) generate_with_retool.py imports `from tool_sandbox import SEMAPHORE, TOOL_CONFIGS, tool_registry`; this in-process math/code tool-execution sandbox is pure Python (no sglang/slime deps) -> copied verbatim from slime. Completes the retool example import (was the flagged missing sibling). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * feat(mega-G): support multimodal samples in streaming rollout (render-dance) Streaming only changes how output is returned (SSE deltas vs one JSON); the image render (input prep: images→features) is identical to the non-streaming path. Replace the NotImplementedError stub with the same render-dance vllm_rollout.generate uses: POST /v1/chat/completions/render → _mm_render_response_to_generate_body → _align_mm_feature_placeholders_to_tokens → token_ids + sampling_params → set stream:True and stream the generate call. mm placeholders live in the prompt prefix (stable across partial-rollout continuations), so re-rendering + re-aligning to the current token_ids holds when an aborted MM sample resumes. NOTE: needs MM e2e validation on a real vLLM MM server (no unit coverage for the streaming MM path; can't run GPU/MM here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961) (#148) * [Sync][D] coding_agent_rl: agent-in-sandbox RL subsystem (slime #1923/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961), sglang->vLLM Add the agent-in-sandbox RL subsystem vime lacked. New vime/agent/ (trajectory, sandbox, parsing, adapters: common/openai/anthropic) + examples/coding_agent_rl/ (demo, generate, sandbox, aiohttp_threaded, run script). Copied slime's final state (all 11 D PRs applied) + translated. 3 sglang->vLLM seams: - adapters/common.py: call_sglang_generate -> call_engine_generate; POST /generate -> /inference/v1/generate; body input_ids->token_ids + max_new_tokens->max_tokens + drop return_logprob + add logprobs:1 + model=; response output_token_logprobs -> choices[0].token_ids + logprobs.content[].logprob (via canonical field map); per-rid /abort_request -> task.cancel() + connection teardown on cancel. - coding_agent_rl/generate.py: sglang_router_ip/port -> vllm_router_ip/port. - parsing.py: NO change (ReasoningParser/FunctionCallParser lazy; coding_agent_rl defaults to XML fallback). #1984 agent-half rename (rollout_id->group_id in trajectory.py) already present (copied slime HEAD; consistent with PR-A's Sample.group_id). EAGLE spec left commented (needs draft-model path). Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * test(D): port agent adapter/trajectory tests + wire agent-adapter CI job Oracle found D#148's agent subsystem (vime/agent/adapters + trajectory) shipped without its tests, and the cpu CI job had no agent-adapter coverage. - port tests/test_agent_{adapters,sdk_adapters,trajectory}.py (slime->vime: slime.agent->vime.agent, SGLANG_URL_KEY->ENGINE_URL_KEY, sglang_url->engine_url) - add agent-adapter-test cpu job (openai/openai-agents/anthropic) + extra_pip_deps template support; regen pr-test.yml Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(D): don't wire test_agent_adapters yet (3/14 mock sglang /generate schema) 11/14 pass; the 3 (uses_sglang_tokens_for_training_segment x2, generate_ posts_input_ids_and_extracts_logprobs) assert against sglang's meta_info. output_token_logprobs response shape and need rewriting to vime's vLLM response format. File stays ported; trajectory + sdk_adapters wired+green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(D): clean .j2 (drop invalid python comment, regen pr-test.yml) prior commit left a '#' comment inside the jinja dict literal -> regen failed -> pr-test.yml stale (still wired the 3 red sglang-schema cases). Remove comment; rationale lives in commit msg + OVERNIGHT_REPORT. * fix(mega-D): translate agent-adapter sglang→vllm, not engine/杂名 Audit finding (bidirectional translation rule): the agent adapters had translated slime's `sglang` identifiers/prose to generic `engine`/`rollout engine` aliases instead of `vllm` specifically. Per the ground principle (vime = slime modulo sglang→vllm, 1:1), fix to vllm: SGLANG_URL_KEY → VLLM_URL_KEY (AppKey "sglang_url"→"vllm_url") sglang_url → vllm_url call_sglang_generate → call_vllm_generate (new helper) → _vllm_sampling_body (was _engine_sampling_body) "sglang upstream {status}" → "vllm upstream {status}" docstrings "SGLang /generate" → "vLLM /inference/v1/generate" Also wire the 3 previously-untranslated test cases in test_agent_adapters.py from sglang wire schema to vLLM /inference/v1/generate schema: FakeSGLang → FakeVLLM (returns choices[].token_ids + logprobs.content, reads x-session-id header, serves /inference/v1/generate) request asserts: input_ids→token_ids, sampling_params.max_new_tokens→max_tokens, return_logprob→sampling_params.logprobs==1, X-SMG-Routing-Key→x-session-id test names: *_uses_sglang_tokens_* → *_uses_vllm_tokens_*, *_posts_input_ids_* → *_posts_token_ids_* + MODEL_KEY in the direct-_generate test app (vime adds GenerateRequest.model). 14/14 test_agent_adapters pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mega-D): drop the upstream `model` passthrough (mirror slime; vLLM doesn't need it) Audit (vime-added field, no slime counterpart): the adapter had added a `model` param + MODEL_KEY + `payload["model"]=model` sending model upstream to /inference/v1/generate. Source check: vLLM `GenerateRequest.model` is `str | None = None` (optional) and the disagg generate/serve_tokens handler never reads it; the vllm-router doesn't route /generate by body.model. So it is unused upstream — an unjustified divergence from slime (whose adapter has no model param). Remove it to mirror slime exactly. Kept: the OpenAI-response echo `body.get("model", "vime-actor")` — slime has the identical line (slime-actor). Test no longer needs MODEL_KEY. 14/14 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(mega-D): wire test_agent_adapters.py into agent-adapter-test (was a dead test) The agent-adapter-test job ran test_agent_sdk_adapters.py + test_agent_trajectory.py but NOT test_agent_adapters.py — so the 14 adapter cases (incl. the 3 sglang→vLLM schema ports) never ran in CI. slime wires test_agent_adapters.py in its agent-adapter-test matrix; add it here (yml + j2). Deps (openai/anthropic/aiohttp) already installed by this job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [Sync][D] revert rollout_id->group_id in agent files (port slime #2013, D-side) Rebased D's own commits onto the updated A #145 (which now carries slime #2013). A #145 reverted the shared data-model to rollout_id; this completes the same revert for D's own files that A doesn't carry: examples/coding_agent_rl/ {README.md,generate.py} and vime/agent/trajectory.py. After this the whole A+D surface is consistent on rollout_id, matching post-#2013 slime. * fix(D): translate engine_url -> vllm_url at AnthropicAdapter call site (coding_agent_rl) The adapter modules (agent/adapters/{anthropic,common,openai}.py) were translated sglang_url -> vllm_url (commit 457d21c), but the call site in examples/coding_agent_rl/generate.py was missed: it still built engine_url and passed AnthropicAdapter(engine_url=...). Since the adapter __init__ now takes vllm_url, this kwarg mismatch raises TypeError at construction. Rename the local var + kwarg to vllm_url, completing the slime sglang_url -> vllm_url translation and fixing the call. --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
slime #2013 reverts #1984 (the rollout_id->group_id rename) because it conflicts with internal tooling. A #145 ported #1984, so mirror the revert to stay byte-faithful and realign with main + post-#2013 slime: group_id -> rollout_id, group_ids -> rollout_ids, group_mask_sums -> rollout_mask_sums, num_groups_in_rollout -> num_rollouts_in_rollout, and drop the Sample.rollout_id deprecation guard (__getattribute__/__setattr__ + import warnings) #1984 had added. Per-file churn matches slime #2013 exactly (actor/data/loss/model/rollout/ _fanout_test_helpers/forge_load/dp_schedule/types + 3 tests). The unrelated compute_pass_rate(num_groups=...) kwarg is left as-is (slime keeps it too). NOTE: #2013 also reverts D-side files not present on A (examples/coding_agent_rl/*, vime/agent/trajectory.py, docs .../agent.md, the group_id sections of docs customization.md + multi_agent stamping). Those must get the same revert when D #148 is rebased onto this A.
* [Sync][G] streaming rollout + retool example (slime #1921/#1861), sglang->vLLM Port THUDM/slime PR-G examples to vime's vLLM rollout: - #1921 streaming: vime/rollout/vllm_streaming_rollout.py consumes the vLLM /inference/v1/generate SSE stream. Key translation: sglang streams CUMULATIVE output_token_logprobs (overwrite per chunk); vLLM SSE sends DELTA token_ids+ logprobs per chunk -> accumulate (+=) and re-decode accumulated tokens each chunk (multi-byte safe), finalize via _vllm_meta_from_generate_choice. MM raises NotImplementedError (two-call render->generate doesn't fit one stream -> use non-streaming generate). + CI test test_qwen3_4B_streaming_partial_rollout. (streaming file is the reviewed sync/slime-pr-1921 / draft #117 design.) - #1861 retool: re-add examples/retool/generate_with_retool.py (vime lacked examples/retool/) from slime base + #1861 hardening; desync guard `if not meta_info.get("output_token_logprobs")`. NOTE: depends on sibling tool_sandbox.py (not yet ported -> follow-up; example partial until then). Based on PR-A (#145) branch (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * [Sync][G] add retool tool_sandbox.py (in-process tool registry, verbatim) generate_with_retool.py imports `from tool_sandbox import SEMAPHORE, TOOL_CONFIGS, tool_registry`; this in-process math/code tool-execution sandbox is pure Python (no sglang/slime deps) -> copied verbatim from slime. Completes the retool example import (was the flagged missing sibling). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * feat(mega-G): support multimodal samples in streaming rollout (render-dance) Streaming only changes how output is returned (SSE deltas vs one JSON); the image render (input prep: images→features) is identical to the non-streaming path. Replace the NotImplementedError stub with the same render-dance vllm_rollout.generate uses: POST /v1/chat/completions/render → _mm_render_response_to_generate_body → _align_mm_feature_placeholders_to_tokens → token_ids + sampling_params → set stream:True and stream the generate call. mm placeholders live in the prompt prefix (stable across partial-rollout continuations), so re-rendering + re-aligning to the current token_ids holds when an aborted MM sample resumes. NOTE: needs MM e2e validation on a real vLLM MM server (no unit coverage for the streaming MM path; can't run GPU/MM here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ce6b409 to
73263b6
Compare
…/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961) (#148) * [Sync][D] coding_agent_rl: agent-in-sandbox RL subsystem (slime #1923/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961), sglang->vLLM Add the agent-in-sandbox RL subsystem vime lacked. New vime/agent/ (trajectory, sandbox, parsing, adapters: common/openai/anthropic) + examples/coding_agent_rl/ (demo, generate, sandbox, aiohttp_threaded, run script). Copied slime's final state (all 11 D PRs applied) + translated. 3 sglang->vLLM seams: - adapters/common.py: call_sglang_generate -> call_engine_generate; POST /generate -> /inference/v1/generate; body input_ids->token_ids + max_new_tokens->max_tokens + drop return_logprob + add logprobs:1 + model=; response output_token_logprobs -> choices[0].token_ids + logprobs.content[].logprob (via canonical field map); per-rid /abort_request -> task.cancel() + connection teardown on cancel. - coding_agent_rl/generate.py: sglang_router_ip/port -> vllm_router_ip/port. - parsing.py: NO change (ReasoningParser/FunctionCallParser lazy; coding_agent_rl defaults to XML fallback). #1984 agent-half rename (rollout_id->group_id in trajectory.py) already present (copied slime HEAD; consistent with PR-A's Sample.group_id). EAGLE spec left commented (needs draft-model path). Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * test(D): port agent adapter/trajectory tests + wire agent-adapter CI job Oracle found D#148's agent subsystem (vime/agent/adapters + trajectory) shipped without its tests, and the cpu CI job had no agent-adapter coverage. - port tests/test_agent_{adapters,sdk_adapters,trajectory}.py (slime->vime: slime.agent->vime.agent, SGLANG_URL_KEY->ENGINE_URL_KEY, sglang_url->engine_url) - add agent-adapter-test cpu job (openai/openai-agents/anthropic) + extra_pip_deps template support; regen pr-test.yml Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(D): don't wire test_agent_adapters yet (3/14 mock sglang /generate schema) 11/14 pass; the 3 (uses_sglang_tokens_for_training_segment x2, generate_ posts_input_ids_and_extracts_logprobs) assert against sglang's meta_info. output_token_logprobs response shape and need rewriting to vime's vLLM response format. File stays ported; trajectory + sdk_adapters wired+green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(D): clean .j2 (drop invalid python comment, regen pr-test.yml) prior commit left a '#' comment inside the jinja dict literal -> regen failed -> pr-test.yml stale (still wired the 3 red sglang-schema cases). Remove comment; rationale lives in commit msg + OVERNIGHT_REPORT. * fix(mega-D): translate agent-adapter sglang→vllm, not engine/杂名 Audit finding (bidirectional translation rule): the agent adapters had translated slime's `sglang` identifiers/prose to generic `engine`/`rollout engine` aliases instead of `vllm` specifically. Per the ground principle (vime = slime modulo sglang→vllm, 1:1), fix to vllm: SGLANG_URL_KEY → VLLM_URL_KEY (AppKey "sglang_url"→"vllm_url") sglang_url → vllm_url call_sglang_generate → call_vllm_generate (new helper) → _vllm_sampling_body (was _engine_sampling_body) "sglang upstream {status}" → "vllm upstream {status}" docstrings "SGLang /generate" → "vLLM /inference/v1/generate" Also wire the 3 previously-untranslated test cases in test_agent_adapters.py from sglang wire schema to vLLM /inference/v1/generate schema: FakeSGLang → FakeVLLM (returns choices[].token_ids + logprobs.content, reads x-session-id header, serves /inference/v1/generate) request asserts: input_ids→token_ids, sampling_params.max_new_tokens→max_tokens, return_logprob→sampling_params.logprobs==1, X-SMG-Routing-Key→x-session-id test names: *_uses_sglang_tokens_* → *_uses_vllm_tokens_*, *_posts_input_ids_* → *_posts_token_ids_* + MODEL_KEY in the direct-_generate test app (vime adds GenerateRequest.model). 14/14 test_agent_adapters pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mega-D): drop the upstream `model` passthrough (mirror slime; vLLM doesn't need it) Audit (vime-added field, no slime counterpart): the adapter had added a `model` param + MODEL_KEY + `payload["model"]=model` sending model upstream to /inference/v1/generate. Source check: vLLM `GenerateRequest.model` is `str | None = None` (optional) and the disagg generate/serve_tokens handler never reads it; the vllm-router doesn't route /generate by body.model. So it is unused upstream — an unjustified divergence from slime (whose adapter has no model param). Remove it to mirror slime exactly. Kept: the OpenAI-response echo `body.get("model", "vime-actor")` — slime has the identical line (slime-actor). Test no longer needs MODEL_KEY. 14/14 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(mega-D): wire test_agent_adapters.py into agent-adapter-test (was a dead test) The agent-adapter-test job ran test_agent_sdk_adapters.py + test_agent_trajectory.py but NOT test_agent_adapters.py — so the 14 adapter cases (incl. the 3 sglang→vLLM schema ports) never ran in CI. slime wires test_agent_adapters.py in its agent-adapter-test matrix; add it here (yml + j2). Deps (openai/anthropic/aiohttp) already installed by this job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [Sync][D] revert rollout_id->group_id in agent files (port slime #2013, D-side) Rebased D's own commits onto the updated A #145 (which now carries slime #2013). A #145 reverted the shared data-model to rollout_id; this completes the same revert for D's own files that A doesn't carry: examples/coding_agent_rl/ {README.md,generate.py} and vime/agent/trajectory.py. After this the whole A+D surface is consistent on rollout_id, matching post-#2013 slime. * fix(D): translate engine_url -> vllm_url at AnthropicAdapter call site (coding_agent_rl) The adapter modules (agent/adapters/{anthropic,common,openai}.py) were translated sglang_url -> vllm_url (commit 457d21c), but the call site in examples/coding_agent_rl/generate.py was missed: it still built engine_url and passed AnthropicAdapter(engine_url=...). Since the adapter __init__ now takes vllm_url, this kwarg mismatch raises TypeError at construction. Rename the local var + kwarg to vllm_url, completing the slime sglang_url -> vllm_url translation and fixing the call. --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…le global batch + group_ids (slime #1926/#1930/#1933/#1941/#1959/#1965/#1969/#1984/#1962)
Port THUDM/slime mega-PR A (rollout data-model + train-split):
- #1926 move micro-batch scheduling train->rollout side (dp_schedule.py, first-fit packing)
- #1930+#1933 variable global batch size + per-token-loss reduction fix (cp_utils
reduce_train_step_metrics / get_sum_of_sample_mean sample_denoms; step_global_batch_size
denominator). CP-invariance + rollout==train equality validated by test_metric_report_dist
/ test_loss_cp_invariance (57/57 multi-proc gloo across CP/DP in {1,2,4}); test_dp_schedule 8/8.
- #1959 forge_load replay (vime/rollout/forge_load.py, --load-forge-rollout-data)
- #1965 group_ids fall back to range(), not sample.index
- #1969 --save-hf for raw mode (hf_checkpoint_saver.py)
- #1941 multi-sample fanout test + helpers (sglang_rollout->vllm_rollout)
- #1984 rename rollout_ids->group_ids (NON-agent files; agent half deferred to PR-D)
- #1962 lint (forge_load)
sglang->vLLM translated per arg-map (--sglang-*->--vllm-*, vllm_speculative_config).
NOTE: test_sample depends on args.vllm_speculative_config existing -> relies on PR-C #1938
getattr guard (stack order F+C+B+A satisfies this). py_compile clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
…u CI job
Oracle found A#145 added the data-model numeric tests + hf_checkpoint_saver
impl but did NOT wire them into the cpu CI job (e2e-test-plugin-contracts),
and the hf_checkpoint_saver unit test (slime #1969) was never ported.
- port tests/utils/test_hf_checkpoint_saver.py (slime->vime)
- add dp_schedule/cp_utils/metric_report{,_dist}/loss_cp_invariance/sample
+ utils/test_hf_checkpoint_saver to the cpu job; regen pr-test.yml
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
slime #2013 reverts #1984 (the rollout_id->group_id rename) because it conflicts with internal tooling. A #145 ported #1984, so mirror the revert to stay byte-faithful and realign with main + post-#2013 slime: group_id -> rollout_id, group_ids -> rollout_ids, group_mask_sums -> rollout_mask_sums, num_groups_in_rollout -> num_rollouts_in_rollout, and drop the Sample.rollout_id deprecation guard (__getattribute__/__setattr__ + import warnings) #1984 had added. Per-file churn matches slime #2013 exactly (actor/data/loss/model/rollout/ _fanout_test_helpers/forge_load/dp_schedule/types + 3 tests). The unrelated compute_pass_rate(num_groups=...) kwarg is left as-is (slime keeps it too). NOTE: #2013 also reverts D-side files not present on A (examples/coding_agent_rl/*, vime/agent/trajectory.py, docs .../agent.md, the group_id sections of docs customization.md + multi_agent stamping). Those must get the same revert when D #148 is rebased onto this A.
* [Sync][G] streaming rollout + retool example (slime #1921/#1861), sglang->vLLM Port THUDM/slime PR-G examples to vime's vLLM rollout: - #1921 streaming: vime/rollout/vllm_streaming_rollout.py consumes the vLLM /inference/v1/generate SSE stream. Key translation: sglang streams CUMULATIVE output_token_logprobs (overwrite per chunk); vLLM SSE sends DELTA token_ids+ logprobs per chunk -> accumulate (+=) and re-decode accumulated tokens each chunk (multi-byte safe), finalize via _vllm_meta_from_generate_choice. MM raises NotImplementedError (two-call render->generate doesn't fit one stream -> use non-streaming generate). + CI test test_qwen3_4B_streaming_partial_rollout. (streaming file is the reviewed sync/slime-pr-1921 / draft #117 design.) - #1861 retool: re-add examples/retool/generate_with_retool.py (vime lacked examples/retool/) from slime base + #1861 hardening; desync guard `if not meta_info.get("output_token_logprobs")`. NOTE: depends on sibling tool_sandbox.py (not yet ported -> follow-up; example partial until then). Based on PR-A (#145) branch (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * [Sync][G] add retool tool_sandbox.py (in-process tool registry, verbatim) generate_with_retool.py imports `from tool_sandbox import SEMAPHORE, TOOL_CONFIGS, tool_registry`; this in-process math/code tool-execution sandbox is pure Python (no sglang/slime deps) -> copied verbatim from slime. Completes the retool example import (was the flagged missing sibling). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * feat(mega-G): support multimodal samples in streaming rollout (render-dance) Streaming only changes how output is returned (SSE deltas vs one JSON); the image render (input prep: images→features) is identical to the non-streaming path. Replace the NotImplementedError stub with the same render-dance vllm_rollout.generate uses: POST /v1/chat/completions/render → _mm_render_response_to_generate_body → _align_mm_feature_placeholders_to_tokens → token_ids + sampling_params → set stream:True and stream the generate call. mm placeholders live in the prompt prefix (stable across partial-rollout continuations), so re-rendering + re-aligning to the current token_ids holds when an aborted MM sample resumes. NOTE: needs MM e2e validation on a real vLLM MM server (no unit coverage for the streaming MM path; can't run GPU/MM here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961) (#148) * [Sync][D] coding_agent_rl: agent-in-sandbox RL subsystem (slime #1923/#1956/#1960/#1954/#1957/#1958/#1963/#1979/#1981/#1982/#1961), sglang->vLLM Add the agent-in-sandbox RL subsystem vime lacked. New vime/agent/ (trajectory, sandbox, parsing, adapters: common/openai/anthropic) + examples/coding_agent_rl/ (demo, generate, sandbox, aiohttp_threaded, run script). Copied slime's final state (all 11 D PRs applied) + translated. 3 sglang->vLLM seams: - adapters/common.py: call_sglang_generate -> call_engine_generate; POST /generate -> /inference/v1/generate; body input_ids->token_ids + max_new_tokens->max_tokens + drop return_logprob + add logprobs:1 + model=; response output_token_logprobs -> choices[0].token_ids + logprobs.content[].logprob (via canonical field map); per-rid /abort_request -> task.cancel() + connection teardown on cancel. - coding_agent_rl/generate.py: sglang_router_ip/port -> vllm_router_ip/port. - parsing.py: NO change (ReasoningParser/FunctionCallParser lazy; coding_agent_rl defaults to XML fallback). #1984 agent-half rename (rollout_id->group_id in trajectory.py) already present (copied slime HEAD; consistent with PR-A's Sample.group_id). EAGLE spec left commented (needs draft-model path). Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai> * test(D): port agent adapter/trajectory tests + wire agent-adapter CI job Oracle found D#148's agent subsystem (vime/agent/adapters + trajectory) shipped without its tests, and the cpu CI job had no agent-adapter coverage. - port tests/test_agent_{adapters,sdk_adapters,trajectory}.py (slime->vime: slime.agent->vime.agent, SGLANG_URL_KEY->ENGINE_URL_KEY, sglang_url->engine_url) - add agent-adapter-test cpu job (openai/openai-agents/anthropic) + extra_pip_deps template support; regen pr-test.yml Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(D): don't wire test_agent_adapters yet (3/14 mock sglang /generate schema) 11/14 pass; the 3 (uses_sglang_tokens_for_training_segment x2, generate_ posts_input_ids_and_extracts_logprobs) assert against sglang's meta_info. output_token_logprobs response shape and need rewriting to vime's vLLM response format. File stays ported; trajectory + sdk_adapters wired+green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(D): clean .j2 (drop invalid python comment, regen pr-test.yml) prior commit left a '#' comment inside the jinja dict literal -> regen failed -> pr-test.yml stale (still wired the 3 red sglang-schema cases). Remove comment; rationale lives in commit msg + OVERNIGHT_REPORT. * fix(mega-D): translate agent-adapter sglang→vllm, not engine/杂名 Audit finding (bidirectional translation rule): the agent adapters had translated slime's `sglang` identifiers/prose to generic `engine`/`rollout engine` aliases instead of `vllm` specifically. Per the ground principle (vime = slime modulo sglang→vllm, 1:1), fix to vllm: SGLANG_URL_KEY → VLLM_URL_KEY (AppKey "sglang_url"→"vllm_url") sglang_url → vllm_url call_sglang_generate → call_vllm_generate (new helper) → _vllm_sampling_body (was _engine_sampling_body) "sglang upstream {status}" → "vllm upstream {status}" docstrings "SGLang /generate" → "vLLM /inference/v1/generate" Also wire the 3 previously-untranslated test cases in test_agent_adapters.py from sglang wire schema to vLLM /inference/v1/generate schema: FakeSGLang → FakeVLLM (returns choices[].token_ids + logprobs.content, reads x-session-id header, serves /inference/v1/generate) request asserts: input_ids→token_ids, sampling_params.max_new_tokens→max_tokens, return_logprob→sampling_params.logprobs==1, X-SMG-Routing-Key→x-session-id test names: *_uses_sglang_tokens_* → *_uses_vllm_tokens_*, *_posts_input_ids_* → *_posts_token_ids_* + MODEL_KEY in the direct-_generate test app (vime adds GenerateRequest.model). 14/14 test_agent_adapters pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mega-D): drop the upstream `model` passthrough (mirror slime; vLLM doesn't need it) Audit (vime-added field, no slime counterpart): the adapter had added a `model` param + MODEL_KEY + `payload["model"]=model` sending model upstream to /inference/v1/generate. Source check: vLLM `GenerateRequest.model` is `str | None = None` (optional) and the disagg generate/serve_tokens handler never reads it; the vllm-router doesn't route /generate by body.model. So it is unused upstream — an unjustified divergence from slime (whose adapter has no model param). Remove it to mirror slime exactly. Kept: the OpenAI-response echo `body.get("model", "vime-actor")` — slime has the identical line (slime-actor). Test no longer needs MODEL_KEY. 14/14 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(mega-D): wire test_agent_adapters.py into agent-adapter-test (was a dead test) The agent-adapter-test job ran test_agent_sdk_adapters.py + test_agent_trajectory.py but NOT test_agent_adapters.py — so the 14 adapter cases (incl. the 3 sglang→vLLM schema ports) never ran in CI. slime wires test_agent_adapters.py in its agent-adapter-test matrix; add it here (yml + j2). Deps (openai/anthropic/aiohttp) already installed by this job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [Sync][D] revert rollout_id->group_id in agent files (port slime #2013, D-side) Rebased D's own commits onto the updated A #145 (which now carries slime #2013). A #145 reverted the shared data-model to rollout_id; this completes the same revert for D's own files that A doesn't carry: examples/coding_agent_rl/ {README.md,generate.py} and vime/agent/trajectory.py. After this the whole A+D surface is consistent on rollout_id, matching post-#2013 slime. * fix(D): translate engine_url -> vllm_url at AnthropicAdapter call site (coding_agent_rl) The adapter modules (agent/adapters/{anthropic,common,openai}.py) were translated sglang_url -> vllm_url (commit 457d21c), but the call site in examples/coding_agent_rl/generate.py was missed: it still built engine_url and passed AnthropicAdapter(engine_url=...). Since the adapter __init__ now takes vllm_url, this kwarg mismatch raises TypeError at construction. Rename the local var + kwarg to vllm_url, completing the slime sglang_url -> vllm_url translation and fixing the call. --------- Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
73263b6 to
3ec7c48
Compare
slime #2013 reverts #1984 (the rollout_id->group_id rename) because it conflicts with internal tooling. A #145 ported #1984, so mirror the revert to stay byte-faithful and realign with main + post-#2013 slime: group_id -> rollout_id, group_ids -> rollout_ids, group_mask_sums -> rollout_mask_sums, num_groups_in_rollout -> num_rollouts_in_rollout, and drop the Sample.rollout_id deprecation guard (__getattribute__/__setattr__ + import warnings) #1984 had added. Per-file churn matches slime #2013 exactly (actor/data/loss/model/rollout/ _fanout_test_helpers/forge_load/dp_schedule/types + 3 tests). The unrelated compute_pass_rate(num_groups=...) kwarg is left as-is (slime keeps it too). NOTE: #2013 also reverts D-side files not present on A (examples/coding_agent_rl/*, vime/agent/trajectory.py, docs .../agent.md, the group_id sections of docs customization.md + multi_agent stamping). Those must get the same revert when D #148 is rebased onto this A.
…no image rebuild Port THUDM/slime delta weight sync to vime's vLLM rollout. Trainer bytewise-diffs weights vs a pinned-CPU snapshot and ships only changed positions+values (nccl broadcast or disk safetensors); receiver overwrites only the changed bytes (lossless, NaN-masked). Bandwidth optimization for large / cross-DC non-colocate. - delta_io.py: DeltaEncoding/DeltaParam/DeltaSpec (local; slime imported from sglang io_struct). - update_weight_from_distributed_delta.py: trainer encoder (subclasses UpdateWeightFromDistributed). - delta_receiver.py: engine-agnostic pure-torch decode + NaN-masked apply (param_storage_index / delta_apply_context monkey-patches torch.Tensor.copy_/fill_ scoped to model param storage, wrapping a normal model.load_weights). - vLLMColocateWorkerExtension: collective_rpc-callable delta receivers (nccl: recv positions/values on model_update_group; disk: read safetensors). NO image rebuild -- receiver is runtime worker-extension/hijack, like the existing IPC hijack. - args: --update-weight-mode/transport/encoding/delta-dir/keep-files/chunk-bytes. - actor.py: delta-mode dispatch (lazy import, #1946 backward-compat) + zero-delta version bump. - docs/zh/advanced/delta-weight-sync.md (+toctree) + e2e test test_delta_weight_update.py (CI registered). SKIPPED: #1993 (sglang EAGLE draft-worker delta forwarding) = N/A, no vime/vLLM analogue. CAVEAT (documented): vLLM does not refresh EAGLE/MTP draft weights on ANY sync (main-model only) -- vLLM-wide limitation, not delta-specific; upstream-track. Based on PR-A (#145) (stacked). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
PR-A — rollout data-model + train-split (RFC #107)
Heaviest-logic mega-PR. Ports the coupled rollout-data-model feature line from THUDM/slime.
Included
vime/utils/dp_schedule.py, first-fit packing inseqlen_balancing.py, index-onlyDataIterator).cp_utils.reduce_train_step_metrics/get_sum_of_sample_mean(sample_denoms=...); loss denominator →step_global_batch_size).vime/rollout/forge_load.py,--load-forge-rollout-data).group_idsfall back torange()notsample.index. #1969--save-hfraw mode. #1941 multi-sample fanout test. #1984 renamerollout_ids→group_ids(non-agent files; agent half → PR-D). #1962 lint.Validation (CPU)
py_compileclean.test_metric_report_dist+test_loss_cp_invariance+test_cp_utils+test_metric_report= 57/57 incl. real multi-process gloo distributed across CP/DP ∈ {1,2,4} — these assert CP-invariance and rollout-side per-rollout-mean == train-sidetrain_one_stepfor the #1930/#1933 numerics.test_dp_schedule8/8,test_sample16/16.Cross-PR note
test_samplereadsargs.vllm_speculative_config; relies on PR-C #1938'sgetattrguard (types.py). The integration stack order F+C+B+A satisfies this.sglang→vLLM
Translated per the arg-map (
--sglang-*→--vllm-*,sglang_rollout→vllm_rollout,vllm_speculative_config).🤖 Generated with Claude Code
Fidelity ledger (audited 2026-06-04 vs slime
8ef1fb47..7a7aba4, viaagent_run/scripts/completeness_oracle.sh)group_idsdata model; CP per-token-loss reduction (cp_utils); the 6 numeric unit tests (dp_schedule/cp_utils/metric_report{,_dist}/loss_cp_invariance/sample)_split_train_data_by_dp(data, dp_size)→(data)reading dp_size fromtrain_parallel_config+ delegating to unit-testabledp_schedule.build_dp_schedule;--load-forge-rollout-datahelp reworded skip_sglang→skip_vllm / "sglang servers"→"vLLM servers, router, weight_update"--disable-rollout-trim-samples+--use-dynamic-global-batch-size(slime #1933 removed them too)8803d18)tests/utils/test_hf_checkpoint_saver.py(slime #1969) + wired the 6 numeric tests + hf into the cpu CI job — they were present-but-unwired before