mstar.model.cosmos3.submodules#
NodeSubmodule wrappers for the Cosmos3 generator nodes.
- Nodes:
- Cosmos3DiTSubmodule – dual-pathway DiT (KV_CACHE). Dispatches by
graph_walk between
prefill(the understanding tower runs once over the text prompt and writes its per-layer K/V) andimage_gen(one denoising step of the generation tower per loop iteration, attending to the frozen understanding K/V plus the current generation tokens, then one scheduler step). Classifier-free guidance keeps the conditional and unconditional prompts in two cache labels and combines their velocities.- Cosmos3VAEEncoderSubmodule – Wan VAE conditioning encode (STATELESS): the
request’s conditioning image/video to clean anchor latents, in parallel with the DiT prefill.
- Cosmos3VAEDecoderSubmodule – Wan VAE decode (STATELESS): final latents to
pixels.
- Cosmos3VAEDecoderARSubmodule – streaming Wan VAE decode (STATELESS) for
windowed AR video: one committed window’s latents per stream chunk, decoded behind re-decoded context and emitted per window or assembled.
- Cosmos3VisionEncoderSubmodule – Edge reasoner vision tower (STATELESS):
packed image/video patches to text-space tokens for the reasoner prefill.
- Cosmos3ReasonerSubmodule – the understanding tower as a causal VLM
(shares the DiT’s transformer instance and kv/attn resources, plus its own sampler):
reasoner_prefill/reasoner_prefill_visionwrite the prompt’s K/V and sample the first token,reasoner_decodeone token per loop iteration.
Because the text tokens never receive a timestep embedding, the understanding K/V is denoise-step independent, so writing it once and re-reading it every step matches running the whole transformer each step.
Functions
|
The native flow-matching sigma grid: |
Classes
AVAE sound decode node (STATELESS): final denoised sound latents |
|
|
Dual-pathway DiT node (understanding tower + generation denoiser). |
|
The understanding tower served as a causal VLM. |
|
Streaming Wan VAE decode for windowed AR video (ported from #198). |
|
Wan VAE decode node: final denoised latents -> pixel frames. |
|
Wan VAE conditioning-encode node (STATELESS): the request's conditioning image or video -> clean anchor latents for the denoise loop. |
|
The Edge reasoner's vision tower + projector (STATELESS): the request's packed image/video patches -> one text-space token per merged 2x2 block, in prompt order, for the reasoner prefill to scatter over its |
|
What a denoise step's declaration needs and cannot read off the batch. |
- class mstar.model.cosmos3.submodules.Cosmos3AudioDecoderSubmodule(sound_tokenizer, config)[source]#
Bases:
NodeSubmoduleAVAE sound decode node (STATELESS): final denoised sound latents
[1, C, T]-> stereo waveform[channels, samples]in [-1, 1], trimmed to the request’s target sample count.The target is re-derived from the request metadata (duration x sample rate) rather than read from the DiT node’s per-request state, so this node stays stateless and placeable on any rank.
- forward(graph_walk, engine_inputs, sound_latents, target_samples, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- class mstar.model.cosmos3.submodules.Cosmos3DiTSubmodule(transformer, config, scheduler=None)[source]#
Bases:
ARNodeSubmoduleDual-pathway DiT node (understanding tower + generation denoiser).
- batched_cfg = True#
- cg_key_info(graph_walk, per_request_info, per_request_input_metadata=None, **kwargs)[source]#
Which of this walk’s capture buckets the batch belongs to, or None for “run eager”.
The engine leases the replay slot before the step is declared, so this answers from per-request state rather than from prepared inputs. It is the sole gate on capture — the v1 engine has no
can_use_cuda_graphs— so every condition the old gate checked lives here:only the two-branch guidance regime is captured (both the prefill’s combined cond+uncond pack and the denoise step’s batched CFG);
of the denoise walks only
image_gen, and only at a resolution a graph was captured for (_capture_layout);a batch shares one captured (batch size, token count) bucket, so a mixed-resolution batch falls back to the eager cross-request denoise.
Every fact this reads is fixed for a request’s whole lifetime (its guidance regime and its latent shape, both settled at prefill). That is a requirement, not a coincidence: the speculative pre-plan path leases a slot for step N+1 while step N is still in flight, before N+1 has been through
prepare_inputs, so a key derived from anything that advances per step (the denoise step index, say) would be read one iteration stale and could lease a bucket the declaration then contradicts.Engine.execchecks the two against each other.The guidance interval is the fact this deliberately does not consult: a captured step always runs both branches, so an out-of-interval step gets the guidance combine where the eager path would run the conditional branch alone (
postprocesscombines unconditionally). That predates the v1 migration and matches the fused reference pipeline, which applies guidance on every step; honoring the interval here instead would make the key step-dependent, which is exactly what the pre-plan path cannot support.
- check_stop(request_id, request_info, outputs)[source]#
Stop this request’s denoise loop once it has run its own step count.
The loop is built with a fixed upper-bound iteration count (
config.max_inference_steps); each request runs only as many steps as its scheduler holds (e.g. image 50, video 35, action 30, distilled policy ~4), which can differ between concurrent requests. Runs on the worker’s slow-postprocess path, so reading the per-request step count is fine. The one extra step the loop dispatches before this stop takes effect is vetoed by prepare_inputs (the forwards also guard it for direct callers, e.g. tests).
- cleanup_request(request_id)[source]#
Remove per-request state when a request completes. The engines call this on request removal; overrides with extra internal state should call super().
- Parameters:
request_id (str)
- declare_step(graph_walk, request_ids, inputs, slot_lease=None, piecewise_leases=None, **kwargs)[source]#
This batch’s step: which cache streams it touches, by how much, and which attention backend runs over them.
Two guidance branches are two labels on the one cache. Whether a request has both, and whether this step uses both, is a per-request fact that rides in on
NodeInputs.resource_step_infofromprepare_inputs(seeGenStepInfo) rather than being read off the batch here.The attention key is the other half of the declaration.
attnis paged,attn_gendense; a step that may replay from a captured graph must name the paged one, because the dense backend’s prefix gather is shaped by the step and cannot be captured.- Parameters:
- Return type:
- forward(graph_walk, engine_inputs, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- forward_batched(graph_walk, engine_inputs, latents=None, time_index=None, action_latents=None, sound_latents=None, input_ids=None, text_mrope_ids=None, **kwargs)[source]#
Batched form of
forward: a multi-request batch’s outputs, per request or as aBatchedModelOutput. Override whencan_batchreturns True.- Parameters:
engine_inputs (ModelInputsFromEngine)
- forward_captured(graph_walk, engine_inputs, latents, vision_timesteps, position_ids_cond, position_ids_uncond, noisy_token_mask, **kwargs)[source]#
Velocity-only denoise forward captured into a CUDA graph: both guidance branches in one pass (the combined plan), no scheduler step. The token layout is baked per resolution; the latents, timestep and rotary positions are static-buffer inputs stacked on a leading batch dim. A single request keeps the two-branch path; a concurrent batch runs the per-request denoise (the same compute as the eager cross-request forward), one transformer pass over the whole batch.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- Return type:
- get_cuda_graph_configs(device, tp_world_size=1)[source]#
Declare one fixed-shape capture of the image denoise step per resolution. Requests at other resolutions, or without guidance, fall back to the eager path. The per-resolution token layout is prompt-independent, so bake it once here and key it by latent shape; the per-prompt rotary positions, the latents and the timestep flow in as static-buffer inputs.
Set
COSMOS3_DISABLE_CUDA_GRAPH=1to skip capture and run the denoise loop eagerly (escape hatch for a misbehaving driver, and an A/B switch). SetCOSMOS3_GEN_CAPTURE_RES(e.g."192x320,480x832", height x width) to override which resolutions are captured, andCOSMOS3_GEN_CAPTURE_BS(e.g."1,4,8") to also capture batched denoise steps so concurrent requests replay a padded graph instead of falling back to the eager path.- Parameters:
tp_world_size (int)
- max_gen_batch_size = 8#
- postprocess(request_id, request_info, outputs, inputs=None, **kwargs)[source]#
Captured-path tail: the classifier-free-guidance combine and the (Python, multistep) scheduler step the graph can’t hold, finished from the step’s own
inputs. Mirrors the tail of_forward_image_gen. Eager forwards already emit finishedlatents/time_indexand pass through untouched (nocond_vin their outputs).
- prepare_inputs(graph_walk, fwd_info, inputs, seen_token_mask=None, pos_info={}, **kwargs)[source]#
- Return type:
- preprocess(graph_walk, engine_inputs, inputs)[source]#
- Parameters:
engine_inputs (ModelInputsFromEngine)
inputs (list[ARNodeInputs])
- Return type:
- to(*args, **kwargs)[source]#
Move and/or cast the parameters and buffers.
This can be called as
- to(device=None, dtype=None, non_blocking=False)[source]
- to(dtype, non_blocking=False)[source]
- to(tensor, non_blocking=False)[source]
- to(memory_format=torch.channels_last)[source]
Its signature is similar to
torch.Tensor.to(), but only accepts floating point or complexdtypes. In addition, this method will only cast the floating point or complex parameters and buffers todtype(if given). The integral parameters and buffers will be moveddevice, if that is given, but with dtypes unchanged. Whennon_blockingis set, it tries to convert/move asynchronously with respect to the host if possible, e.g., moving CPU Tensors with pinned memory to CUDA devices.See below for examples.
Note
This method modifies the module in-place.
- Parameters:
device (
torch.device) – the desired device of the parameters and buffers in this moduledtype (
torch.dtype) – the desired floating point or complex dtype of the parameters and buffers in this moduletensor (torch.Tensor) – Tensor whose dtype and device are the desired dtype and device for all parameters and buffers in this module
memory_format (
torch.memory_format) – the desired memory format for 4D parameters and buffers in this module (keyword only argument)
- Returns:
self
- Return type:
Module
Examples:
>>> # xdoctest: +IGNORE_WANT("non-deterministic") >>> linear = nn.Linear(2, 2) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]]) >>> linear.to(torch.double) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]], dtype=torch.float64) >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA1) >>> gpu1 = torch.device("cuda:1") >>> linear.to(gpu1, dtype=torch.half, non_blocking=True) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16, device='cuda:1') >>> cpu = torch.device("cpu") >>> linear.to(cpu) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16) >>> linear = nn.Linear(2, 2, bias=None).to(torch.cdouble) >>> linear.weight Parameter containing: tensor([[ 0.3741+0.j, 0.2382+0.j], [ 0.5593+0.j, -0.4443+0.j]], dtype=torch.complex128) >>> linear(torch.ones(3, 2, dtype=torch.cdouble)) tensor([[0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j]], dtype=torch.complex128)
- class mstar.model.cosmos3.submodules.Cosmos3ReasonerSubmodule(transformer, config)[source]#
Bases:
ARNodeSubmoduleThe understanding tower served as a causal VLM.
Shares the DiT node’s
Cosmos3OmniTransformerinstance (one copy of the text weights) and itskv/attnresources; declares its ownsampler. The prefill walks embed the rendered prompt, scatter the vision encoder’s tokens over the media placeholders, run the text tower (writing the raw K/V under one label), and sample the first token from the last position; the decode loop feeds each sampled token back as the next step’s single-token input. Positions are the prompt’s 3D mRoPE ids (computed inprocess_prompt) and, past the prompt, the scalar cursormax(position) + 1on all three axes, carried in per-request state.- check_stop(request_id, request_info, outputs)[source]#
Return the set of dynamic-loop names that should stop after this step.
Runs on the worker’s slow-postprocess path after
execute_batchreturns — never insideexecute_batch. Allowed to read tensor values (.item()/.cpu()) because by this point the GPU thread is no longer blocked by it.Stops returned here are deferred by one step: they apply to the worker’s next iter’s fast postprocess. The current in-flight step (already submitted under the assumption that the rid continues) will run for that rid and its output discarded — the standard 1-wasted-step cost for any stop signal.
Default: no stops.
- declare_step(graph_walk, request_ids, inputs, slot_lease=None, piecewise_leases=None, **kwargs)[source]#
One causal span per request under the reasoner’s label, committed (the text is context for every later token); the sampler tracks the prompt tokens at prefill for the repetition penalty.
- Parameters:
- Return type:
- forward(graph_walk, engine_inputs, input_ids, position_ids, seq_lens, vision_embeds=None, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- forward_batched(graph_walk, engine_inputs, input_ids, position_ids, seq_lens, vision_embeds=None, **kwargs)[source]#
Batched form of
forward: a multi-request batch’s outputs, per request or as aBatchedModelOutput. Override whencan_batchreturns True.- Parameters:
engine_inputs (ModelInputsFromEngine)
- get_cuda_graph_configs(device, tp_world_size=1)[source]#
Capture the decode step (one token per request) per batch-size bucket; prefills run eager (they are one-shot and shape-varied).
- Parameters:
tp_world_size (int)
- postprocess(request_id, request_info, outputs, inputs=None, **kwargs)[source]#
Per-request postprocessing on the submodule outputs.
Runs on the GPU thread inside
execute_batch, after the forward (eager, batched, or CUDA-graph replay).inputsis the request’sprepare_inputsresult for this step, so a submodule can finish a step the captured graph could not hold (e.g. combine guidance branches and run a Python multistep scheduler against the step’s input latents).Keep it metadata-only where possible. Avoid reading tensor values —
.item()/.cpu()sync here block the GPU thread and forfeit the worker’s async-scheduling overlap; stop-condition decisions that need token values (e.g. EOS) belong incheck_stop. A captured-path tail that must read scheduler state is the sanctioned exception — it costs the same sync wherever it runs.- Typical uses:
rebind output names for graph routing (
outputs["text_inputs"] = outputs["new_token"]);drop keys on a per-request basis for static-capture submodules (e.g. Qwen3-Omni Thinker dropping
thinker_statesfor requests that don’t need audio);finish a captured step from
inputs(Cosmos3 denoise tail).
Modifies
outputsin-place; returns nothing.
- preprocess(graph_walk, engine_inputs, inputs)[source]#
- Parameters:
engine_inputs (ModelInputsFromEngine)
inputs (list[ARNodeInputs])
- Return type:
- class mstar.model.cosmos3.submodules.Cosmos3VAEDecoderARSubmodule(vae, config)[source]#
Bases:
Cosmos3VAEDecoderSubmoduleStreaming Wan VAE decode for windowed AR video (ported from #198).
Consumes one committed window’s latents per stream chunk. Each window is decoded behind a re-decoded left context (the last few latents of the stream so far) so the causal conv stack is warm at the kept frames; the context- and overlap-derived pixels are trimmed, and the video is either emitted per window (
stream_video) or assembled and emitted once the last window lands. The chunk count is the completion signal — it is known per request up front — so the stream’s terminal flush (an empty pass, and the only pass a non-windowed request’s idle stream ever delivers) runs as a no-op forward: the pass must complete normally for the partition to report done, so it is not vetoed.- forward(graph_walk, engine_inputs, latents, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- class mstar.model.cosmos3.submodules.Cosmos3VAEDecoderSubmodule(vae, config)[source]#
Bases:
NodeSubmoduleWan VAE decode node: final denoised latents -> pixel frames.
Applies the pipeline-side latent normalization (the VAE itself returns raw latents) before decoding, matching the fused t2i pipeline’s decode.
- forward(graph_walk, engine_inputs, latents, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- class mstar.model.cosmos3.submodules.Cosmos3VAEEncoderSubmodule(vae, config)[source]#
Bases:
NodeSubmoduleWan VAE conditioning-encode node (STATELESS): the request’s conditioning image or video -> clean anchor latents for the denoise loop.
Runs in parallel with the DiT’s understanding-tower prefill (the conditioned prefill walks put the two nodes in a
Parallelsection) and emitscond_latentsas a persist signal the conductor threads into the generation walk’s first iteration. Everything is re-derived from the request metadata so the node stays stateless and placeable on any rank. Per mode:image-to-video: the single conditioning frame, encoded standalone (the Wan VAE is temporally causal, so frame 0 encodes bit-identically alone);
action policy / forward-dynamics: the frame repeated across the clip, full-clip encoded (mirrors the reference pipelines);
action inverse-dynamics: the whole observed clip;
video-to-video: the
condition_video_keepprefix (short clips padded by repeating the last frame), encoded and scattered into the pinned frames of a full-latent-shape tensor (zeros elsewhere).
- forward(graph_walk, engine_inputs, vision, condition_indexes=None, latent_shape=None, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- class mstar.model.cosmos3.submodules.Cosmos3VisionEncoderSubmodule(vision_model, config)[source]#
Bases:
NodeSubmoduleThe Edge reasoner’s vision tower + projector (STATELESS): the request’s packed image/video patches -> one text-space token per merged 2x2 block, in prompt order, for the reasoner prefill to scatter over its
<|image_pad|>/<|video_pad|>tokens.The pixel patches and their grids are computed CPU-side in
Cosmos3Model.process_prompt(the token count must be known when the prompt is rendered), so this node only runs the encoder.- forward(graph_walk, engine_inputs, pixel_values, vision_grid_thw, **kwargs)[source]#
Pure tensor → NameToTensorList computation. Compilable + CUDA-graphable.
- Parameters:
engine_inputs (ModelInputsFromEngine)
- class mstar.model.cosmos3.submodules.GenStepInfo(cfg, cfg_active, capture_key, commit=False, retention=None)[source]#
Bases:
objectWhat a denoise step’s declaration needs and cannot read off the batch.
All three are per-request facts resolved in
prepare_inputs(which has the request’s state and its step index) and carried todeclare_steponNodeInputs.resource_step_info, since the declaration runs with only the request ids and their prepared inputs.capture_keyis this request’s half ofcg_key_info— the capture bucket its shape belongs to, or None for “no captured graph for this”. Agreeing withcg_key_infomatters: the engine leases the slot from that and then checks the declaration against the lease. What is left over is the batch’s size and token count, which no row knows, so a step every row of which is capturable may still find no bucket and run eager. Declaring the paged backend for such a step only costs the dense path’s speedup; declaring the dense one for a step that does get a slot would try to capture an eager-only backend, so the safe direction over-declares.cfg_activenarrows the eager single-request declaration only. It is deliberately not part ofcapture_key— seecg_key_info.- Parameters:
- retention: Mapping[str, RetentionPolicy] | None = None#
- mstar.model.cosmos3.submodules.native_flow_sigmas(num_inference_steps, num_train_timesteps)[source]#
The native flow-matching sigma grid:
num_inference_stepsvalues linearly spaced from1 - 1/Ttoward 0, the endpoint dropped. A numpy array: UniPC’s explicit-sigma path applies the flow shift arithmetically to it (a Python list raises insideset_timesteps).