multimodalart's picture
multimodalart HF Staff
Sync the split MiniMax-H3 Spaces
186aa49 verified
Raw
History Blame Contribute Delete
35.8 kB
import inspect
import torch
from ...models.transformers.transformer_cosmos3 import Cosmos3OmniTransformer
from ...schedulers import FlowMatchEulerDiscreteScheduler, UniPCMultistepScheduler
from ..modular_pipeline import (
BlockState,
LoopSequentialPipelineBlocks,
ModularPipelineBlocks,
PipelineState,
)
from ..modular_pipeline_utils import ComponentSpec, InputParam, OutputParam
from .modular_pipeline import Cosmos3OmniModularPipeline
class Cosmos3VisionLoopPrepareStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Prepares vision tokens and timesteps for one denoising iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam.template("latents", required=True, description="Noisy vision latents to denoise."),
InputParam(
name="cond_vision_segment", type_hint=dict, required=True, description="Conditional vision segment."
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [
OutputParam(
"vision_tokens",
type_hint=list[torch.Tensor],
description="Vision tokens for the transformer denoiser.",
),
OutputParam("vision_timesteps", type_hint=torch.Tensor, description="Timesteps for the vision tokens."),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
device = components._execution_device
block_state.vision_tokens = [block_state.latents.to(device=device, dtype=components.transformer.dtype)]
block_state.vision_timesteps = torch.full(
(block_state.cond_vision_segment["num_noisy_vision_tokens"],), t.item(), device=device
)
return components, block_state
class Cosmos3SoundLoopPrepareStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Prepares sound tokens and timesteps for one denoising iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="sound_latents",
type_hint=torch.Tensor,
required=True,
description="Noisy sound latents to denoise.",
),
InputParam(
name="cond_sound_segment", type_hint=dict, required=True, description="Conditional sound segment."
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [
OutputParam(
"sound_tokens", type_hint=list[torch.Tensor], description="Sound tokens for the transformer denoiser."
),
OutputParam("sound_timesteps", type_hint=torch.Tensor, description="Timesteps for the sound tokens."),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
device = components._execution_device
block_state.sound_tokens = [block_state.sound_latents.to(device=device, dtype=components.transformer.dtype)]
block_state.sound_timesteps = torch.full(
(block_state.cond_sound_segment["sound_len"],), t.item(), device=device
)
return components, block_state
class Cosmos3ActionLoopPrepareStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Prepares action tokens and timesteps for one denoising iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="action_latents",
type_hint=torch.Tensor,
required=True,
description="Noisy action latents to denoise.",
),
InputParam(
name="cond_action_segment", type_hint=dict, required=True, description="Conditional action segment."
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [
OutputParam(
"action_tokens",
type_hint=list[torch.Tensor],
description="Action tokens for the transformer denoiser.",
),
OutputParam("action_timesteps", type_hint=torch.Tensor, description="Timesteps for the action tokens."),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
device = components._execution_device
block_state.action_tokens = [block_state.action_latents.to(device=device, dtype=components.transformer.dtype)]
block_state.action_timesteps = torch.full(
(block_state.cond_action_segment["num_noisy_action_tokens"],), t.item(), device=device
)
return components, block_state
class Cosmos3LoopDenoiser(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Predicts available Cosmos3 modality velocities for one denoising iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam.template("denoiser_input_fields"),
InputParam(
name="guidance_scale",
type_hint=float,
default=6.0,
description="Scale for classifier-free guidance.",
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [
OutputParam(
"velocity_vision", type_hint=torch.Tensor, description="Predicted velocity for vision latents."
),
OutputParam("velocity_sound", type_hint=torch.Tensor, description="Predicted velocity for sound latents."),
OutputParam(
"velocity_action", type_hint=torch.Tensor, description="Predicted velocity for action latents."
),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
denoiser_input_fields = block_state.denoiser_input_fields
loop_input_fields = block_state.as_dict()
has_sound = "sound_tokens" in loop_input_fields
has_action = "action_tokens" in loop_input_fields
do_cfg = block_state.guidance_scale != 1.0
transformer_args = set(inspect.signature(components.transformer.forward).parameters)
prediction_passes = ["cond"]
if do_cfg:
prediction_passes.append("uncond")
velocities = {}
for pass_name in prediction_passes:
transformer_kwargs = {}
for field_name, field_value in denoiser_input_fields.items():
if field_name.startswith(f"{pass_name}_"):
transformer_field_name = field_name.removeprefix(f"{pass_name}_")
if transformer_field_name.endswith("_segment"):
transformer_kwargs.update(field_value)
else:
transformer_kwargs[transformer_field_name] = field_value
elif field_name in transformer_args:
transformer_kwargs[field_name] = field_value
transformer_kwargs.update(
{
field_name: field_value
for field_name, field_value in loop_input_fields.items()
if field_name in transformer_args
}
)
transformer_kwargs = {
name: value for name, value in transformer_kwargs.items() if name in transformer_args
}
preds_vision, preds_sound, preds_action = components.transformer(**transformer_kwargs, return_dict=False)
velocities[pass_name] = components._mask_velocity_predictions(
preds_vision,
preds_sound,
vision_condition_mask=[loop_input_fields["vision_condition_mask"]],
sound_condition_mask=[loop_input_fields["sound_condition_mask"]] if has_sound else None,
preds_action=preds_action,
action_condition_mask=[loop_input_fields["action_condition_mask"]] if has_action else None,
raw_action_dim=loop_input_fields.get("raw_action_dim_resolved"),
)
cond_velocity_vision, cond_velocity_sound, cond_velocity_action = velocities["cond"]
if do_cfg:
uncond_velocity_vision, uncond_velocity_sound, uncond_velocity_action = velocities["uncond"]
block_state.velocity_vision = uncond_velocity_vision + block_state.guidance_scale * (
cond_velocity_vision - uncond_velocity_vision
)
block_state.velocity_sound = (
uncond_velocity_sound + block_state.guidance_scale * (cond_velocity_sound - uncond_velocity_sound)
if has_sound
else None
)
block_state.velocity_action = (
uncond_velocity_action + block_state.guidance_scale * (cond_velocity_action - uncond_velocity_action)
if has_action
else None
)
else:
block_state.velocity_vision = cond_velocity_vision
block_state.velocity_sound = cond_velocity_sound if has_sound else None
block_state.velocity_action = cond_velocity_action if has_action else None
return components, block_state
class Cosmos3VisionLoopSchedulerStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Updates vision latents after one denoising iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("scheduler", UniPCMultistepScheduler)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam.template("latents", required=True, description="Noisy vision latents to update."),
InputParam(
name="velocity_vision", type_hint=torch.Tensor, required=True, description="Predicted vision velocity."
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam.template("latents")]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
block_state.latents = components.scheduler.step(
block_state.velocity_vision.unsqueeze(0), t, block_state.latents.unsqueeze(0), return_dict=False
)[0].squeeze(0)
return components, block_state
class Cosmos3DistilledVisionLoopSchedulerStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Updates vision latents after one distilled denoising iteration, re-anchoring conditioned frames."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("scheduler", FlowMatchEulerDiscreteScheduler)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam.template("latents", required=True, description="Noisy vision latents to update."),
InputParam(
name="velocity_vision", type_hint=torch.Tensor, required=True, description="Predicted vision velocity."
),
InputParam(
name="vision_condition_mask",
type_hint=torch.Tensor,
required=True,
description="Mask marking conditioned vision latent frames.",
),
InputParam(
name="vision_conditioning_latents",
type_hint=torch.Tensor,
default=None,
description="Clean encoded vision latents for re-anchoring conditioned frames.",
),
InputParam(
name="vision_condition_indexes_for_pack",
type_hint=list,
default=None,
description="Indexes of conditioned vision latent frames; non-empty for image-to-video.",
),
InputParam.template("generator"),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam.template("latents")]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
# Pass the generator so the scheduler's stochastic (SDE) re-noising is seedable/reproducible.
block_state.latents = components.scheduler.step(
block_state.velocity_vision.unsqueeze(0),
t,
block_state.latents.unsqueeze(0),
generator=block_state.generator,
return_dict=False,
)[0].squeeze(0)
# Distilled checkpoints use stochastic (SDE) scheduler steps that re-noise every position.
# Re-anchor conditioned frames to the clean encoded reference after each step.
has_image_condition = bool(block_state.vision_condition_indexes_for_pack)
if has_image_condition and block_state.vision_conditioning_latents is not None:
mask = block_state.vision_condition_mask
reference = block_state.vision_conditioning_latents.to(block_state.latents.dtype)
block_state.latents = mask * reference + (1.0 - mask) * block_state.latents
return components, block_state
class Cosmos3SoundLoopSchedulerStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Updates sound latents after one denoising iteration."
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="sound_latents",
type_hint=torch.Tensor,
required=True,
description="Noisy sound latents to update.",
),
InputParam(
name="sound_scheduler",
type_hint=UniPCMultistepScheduler,
required=True,
description="Scheduler used to update sound latents.",
),
InputParam(
name="velocity_sound", type_hint=torch.Tensor, required=True, description="Predicted sound velocity."
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam("sound_latents", type_hint=torch.Tensor, description="Updated sound latents.")]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
block_state.sound_latents = block_state.sound_scheduler.step(
block_state.velocity_sound.unsqueeze(0), t, block_state.sound_latents.unsqueeze(0), return_dict=False
)[0].squeeze(0)
return components, block_state
class Cosmos3ActionLoopSchedulerStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Updates action latents after one denoising iteration."
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="action_latents",
type_hint=torch.Tensor,
required=True,
description="Noisy action latents to update.",
),
InputParam(
name="action_scheduler",
type_hint=UniPCMultistepScheduler,
required=True,
description="Scheduler used to update action latents.",
),
InputParam(
name="velocity_action", type_hint=torch.Tensor, required=True, description="Predicted action velocity."
),
InputParam(
name="action_condition_mask",
type_hint=torch.Tensor,
required=True,
description="Mask marking conditioned action latent frames.",
),
InputParam(
name="raw_action_dim_resolved",
type_hint=int,
default=None,
description="Unpadded action-vector dimension.",
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam("action_latents", type_hint=torch.Tensor, description="Updated action latents.")]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
has_noisy_action = block_state.action_condition_mask.sum() < block_state.action_condition_mask.numel()
if has_noisy_action:
block_state.action_latents = block_state.action_scheduler.step(
block_state.velocity_action.unsqueeze(0), t, block_state.action_latents.unsqueeze(0), return_dict=False
)[0].squeeze(0)
if block_state.raw_action_dim_resolved is not None:
block_state.action_latents[:, block_state.raw_action_dim_resolved :] = 0
return components, block_state
class Cosmos3DenoiseLoopWrapper(LoopSequentialPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Iteratively denoises Cosmos3 latents over scheduler timesteps."
@property
def loop_expected_components(self) -> list[ComponentSpec]:
return [
ComponentSpec("scheduler", UniPCMultistepScheduler),
ComponentSpec("transformer", Cosmos3OmniTransformer),
]
@property
def loop_inputs(self) -> list[InputParam]:
return [
InputParam.template("timesteps", required=True),
InputParam.template("num_inference_steps", required=True),
InputParam(
name="num_warmup_steps", type_hint=int, required=True, description="Number of scheduler warmup steps."
),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) -> PipelineState:
block_state = self.get_block_state(state)
with self.progress_bar(total=block_state.num_inference_steps) as progress_bar:
for i, t in enumerate(block_state.timesteps):
components, block_state = self.loop_step(components, block_state, i=i, t=t)
if i == len(block_state.timesteps) - 1 or (
(i + 1) > block_state.num_warmup_steps and (i + 1) % components.scheduler.order == 0
):
progress_bar.update()
self.set_block_state(state, block_state)
return components, state
class Cosmos3VisionDenoiseStep(Cosmos3DenoiseLoopWrapper):
block_classes = [
Cosmos3VisionLoopPrepareStep,
Cosmos3LoopDenoiser,
Cosmos3VisionLoopSchedulerStep,
]
block_names = ["prepare_vision", "denoiser", "update_vision"]
@property
def description(self) -> str:
return "Runs the vision-only Cosmos3 denoising loop."
class Cosmos3DistilledVisionDenoiseStep(Cosmos3DenoiseLoopWrapper):
model_name = "cosmos3-omni"
block_classes = [
Cosmos3VisionLoopPrepareStep,
Cosmos3LoopDenoiser,
Cosmos3DistilledVisionLoopSchedulerStep,
]
block_names = ["prepare_vision", "denoiser", "update_vision"]
@property
def description(self) -> str:
return "Runs the vision-only distilled Cosmos3 denoising loop."
@property
def loop_expected_components(self) -> list[ComponentSpec]:
return [
ComponentSpec("scheduler", FlowMatchEulerDiscreteScheduler),
ComponentSpec("transformer", Cosmos3OmniTransformer),
]
class Cosmos3VisionSoundDenoiseStep(Cosmos3DenoiseLoopWrapper):
block_classes = [
Cosmos3VisionLoopPrepareStep,
Cosmos3SoundLoopPrepareStep,
Cosmos3LoopDenoiser,
Cosmos3VisionLoopSchedulerStep,
Cosmos3SoundLoopSchedulerStep,
]
block_names = ["prepare_vision", "prepare_sound", "denoiser", "update_vision", "update_sound"]
@property
def description(self) -> str:
return "Runs the vision-and-sound Cosmos3 denoising loop."
class Cosmos3VisionActionDenoiseStep(Cosmos3DenoiseLoopWrapper):
block_classes = [
Cosmos3VisionLoopPrepareStep,
Cosmos3ActionLoopPrepareStep,
Cosmos3LoopDenoiser,
Cosmos3VisionLoopSchedulerStep,
Cosmos3ActionLoopSchedulerStep,
]
block_names = ["prepare_vision", "prepare_action", "denoiser", "update_vision", "update_action"]
@property
def description(self) -> str:
return "Runs the vision-and-action Cosmos3 denoising loop."
class Cosmos3VisionSoundActionDenoiseStep(Cosmos3DenoiseLoopWrapper):
block_classes = [
Cosmos3VisionLoopPrepareStep,
Cosmos3SoundLoopPrepareStep,
Cosmos3ActionLoopPrepareStep,
Cosmos3LoopDenoiser,
Cosmos3VisionLoopSchedulerStep,
Cosmos3SoundLoopSchedulerStep,
Cosmos3ActionLoopSchedulerStep,
]
block_names = [
"prepare_vision",
"prepare_sound",
"prepare_action",
"denoiser",
"update_vision",
"update_sound",
"update_action",
]
@property
def description(self) -> str:
return "Runs the vision, sound, and action Cosmos3 denoising loop."
class Cosmos3TransferLoopPrepareStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Prepares the full [control..., target] and target-only vision token lists plus timesteps for one transfer iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="control_latents",
type_hint=list[torch.Tensor],
required=True,
description="Clean control latents for this chunk, one per hint in canonical order.",
),
InputParam(
name="latents", type_hint=torch.Tensor, required=True, description="Noisy target latents to denoise."
),
InputParam(
name="num_noisy_vision_tokens",
type_hint=int,
required=True,
description="Number of noisy target vision tokens denoised each step.",
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [
OutputParam(
"vision_tokens_full",
type_hint=list[torch.Tensor],
description="Token list for the [control..., target] forward passes.",
),
OutputParam(
"vision_tokens_target",
type_hint=list[torch.Tensor],
description="Token list for the target-only (no-control) forward pass.",
),
OutputParam(
"vision_timesteps", type_hint=torch.Tensor, description="Timesteps for the noisy target tokens."
),
]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
device = components._execution_device
dtype = components.transformer.dtype
block_state.vision_tokens_full = [c.to(device=device, dtype=dtype) for c in block_state.control_latents] + [
block_state.latents.to(device=device, dtype=dtype)
]
block_state.vision_tokens_target = [block_state.latents.to(device=device, dtype=dtype)]
block_state.vision_timesteps = torch.full((block_state.num_noisy_vision_tokens,), t.item(), device=device)
return components, block_state
class Cosmos3TransferLoopDenoiser(ModularPipelineBlocks):
# Dedicated (not Cosmos3LoopDenoiser): transfer runs up to 3 passes over different token sequences with nested
# control/text CFG and interval gating, which the generic cond/uncond denoiser cannot express.
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return (
"Predicts the transfer velocity with nested control/text CFG over [control..., target]. Each branch is "
"gated by its guidance interval, and the result is masked so conditioned frames get zero velocity."
)
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("transformer", Cosmos3OmniTransformer)]
@property
def inputs(self) -> list[InputParam]:
return [
# The three pre-packed CFG sequence variants (cond_full / cond_no_control / uncond_full) flow in as
# denoiser_input_fields, gathered generically like the other Cosmos3 denoisers.
InputParam.template("denoiser_input_fields"),
InputParam(
name="vision_tokens_full",
type_hint=list[torch.Tensor],
required=True,
description="Token list for the [control..., target] forward passes.",
),
InputParam(
name="vision_tokens_target",
type_hint=list[torch.Tensor],
required=True,
description="Token list for the target-only (no-control) forward pass.",
),
InputParam(
name="vision_timesteps",
type_hint=torch.Tensor,
required=True,
description="Timesteps for the noisy target tokens.",
),
InputParam(
name="velocity_mask",
type_hint=torch.Tensor,
required=True,
description="Mask that zeroes the velocity on conditioned (clean) latent frames.",
),
InputParam(
name="guidance_scale",
type_hint=float,
default=6.0,
description="Scale for text classifier-free guidance.",
),
InputParam(
name="control_guidance",
type_hint=float,
default=1.0,
description="Scale for the control (structural) guidance axis.",
),
InputParam(
name="guidance_interval",
type_hint=tuple,
default=None,
description="Timestep interval [lo, hi] over which text guidance is active (None = always).",
),
InputParam(
name="control_guidance_interval",
type_hint=tuple,
default=None,
description="Timestep interval [lo, hi] over which control guidance is active (None = always).",
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam("velocity", type_hint=torch.Tensor, description="Predicted (masked) transfer velocity.")]
@staticmethod
def _forward(components, static, vision_tokens, vision_timesteps):
preds_vision, _, _ = components.transformer(
input_ids=static["input_ids"],
text_indexes=static["text_indexes"],
position_ids=static["position_ids"],
und_len=static["und_len"],
sequence_length=static["sequence_length"],
vision_tokens=vision_tokens,
vision_token_shapes=static["vision_token_shapes"],
vision_sequence_indexes=static["vision_sequence_indexes"],
vision_mse_loss_indexes=static["vision_mse_loss_indexes"],
vision_timesteps=vision_timesteps,
vision_noisy_frame_indexes=static["vision_noisy_frame_indexes"],
return_dict=False,
)
return preds_vision[-1]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
# active-at: a None interval is always active; otherwise the timestep must fall within [lo, hi].
guidance_interval = block_state.guidance_interval
guidance_active = guidance_interval is None or (
float(guidance_interval[0]) <= float(t.item()) <= float(guidance_interval[1])
)
control_interval = block_state.control_guidance_interval
control_active = control_interval is None or (
float(control_interval[0]) <= float(t.item()) <= float(control_interval[1])
)
step_guidance = block_state.guidance_scale if guidance_active else 1.0
step_control = block_state.control_guidance if control_active else 1.0
needs_text_cfg = step_guidance > 1.0
needs_control_cfg = step_control != 1.0
denoiser_input_fields = block_state.denoiser_input_fields
cond_full_static = denoiser_input_fields["cond_full_static"]
cond_no_control_static = denoiser_input_fields["cond_no_control_static"]
uncond_full_static = denoiser_input_fields["uncond_full_static"]
cond_full = self._forward(
components, cond_full_static, block_state.vision_tokens_full, block_state.vision_timesteps
)
cond_no_control = None
if needs_control_cfg:
cond_no_control = self._forward(
components,
cond_no_control_static,
block_state.vision_tokens_target,
block_state.vision_timesteps,
)
uncond_full = None
if needs_text_cfg:
uncond_full = self._forward(
components,
uncond_full_static,
block_state.vision_tokens_full,
block_state.vision_timesteps,
)
if needs_control_cfg and needs_text_cfg:
control_cond = cond_no_control + step_control * (cond_full - cond_no_control)
velocity = uncond_full + step_guidance * (control_cond - uncond_full)
elif needs_control_cfg:
velocity = cond_no_control + step_control * (cond_full - cond_no_control)
elif needs_text_cfg:
velocity = uncond_full + step_guidance * (cond_full - uncond_full)
else:
velocity = cond_full
block_state.velocity = velocity * block_state.velocity_mask
return components, block_state
class Cosmos3TransferLoopSchedulerStep(ModularPipelineBlocks):
model_name = "cosmos3-omni"
@property
def description(self) -> str:
return "Steps the scheduler and re-pins the conditioned frames exactly for one transfer iteration."
@property
def expected_components(self) -> list[ComponentSpec]:
return [ComponentSpec("scheduler", UniPCMultistepScheduler)]
@property
def inputs(self) -> list[InputParam]:
return [
InputParam(
name="latents", type_hint=torch.Tensor, required=True, description="Noisy target latents to update."
),
InputParam(
name="velocity",
type_hint=torch.Tensor,
required=True,
description="Predicted (masked) transfer velocity.",
),
InputParam(
name="velocity_mask",
type_hint=torch.Tensor,
required=True,
description="Mask that zeroes the velocity on conditioned (clean) latent frames.",
),
InputParam(
name="condition_latents",
type_hint=torch.Tensor,
required=True,
description="Clean target latents on the conditioned frames (the autoregressive seed).",
),
]
@property
def intermediate_outputs(self) -> list[OutputParam]:
return [OutputParam("latents", type_hint=torch.Tensor, description="Updated target latents for this chunk.")]
@torch.no_grad()
def __call__(self, components: Cosmos3OmniModularPipeline, block_state: BlockState, i: int, t: torch.Tensor):
block_state.latents = components.scheduler.step(
block_state.velocity.unsqueeze(0), t, block_state.latents.unsqueeze(0), return_dict=False
)[0].squeeze(0)
# Re-pin conditioned frames exactly (the autoregressive seed), guarding multistep drift.
block_state.latents = (
block_state.velocity_mask * block_state.latents
+ (1.0 - block_state.velocity_mask) * block_state.condition_latents
)
return components, block_state
# auto_docstring
class Cosmos3TransferDenoiseStep(Cosmos3DenoiseLoopWrapper):
"""
Runs the per-chunk transfer denoising loop over scheduler timesteps.
Components:
transformer (`Cosmos3OmniTransformer`) scheduler (`UniPCMultistepScheduler`)
Inputs:
timesteps (`Tensor`):
Timesteps for the denoising process.
num_inference_steps (`int`):
The number of denoising steps.
num_warmup_steps (`int`):
Number of scheduler warmup steps.
control_latents (`list`):
Clean control latents for this chunk, one per hint in canonical order.
latents (`Tensor`):
Noisy target latents to denoise.
num_noisy_vision_tokens (`int`):
Number of noisy target vision tokens denoised each step.
**denoiser_input_fields (`None`, *optional*):
conditional model inputs for the denoiser: e.g. prompt_embeds, negative_prompt_embeds, etc.
velocity_mask (`Tensor`):
Mask that zeroes the velocity on conditioned (clean) latent frames.
guidance_scale (`float`, *optional*, defaults to 6.0):
Scale for text classifier-free guidance.
control_guidance (`float`, *optional*, defaults to 1.0):
Scale for the control (structural) guidance axis.
guidance_interval (`tuple`, *optional*):
Timestep interval [lo, hi] over which text guidance is active (None = always).
control_guidance_interval (`tuple`, *optional*):
Timestep interval [lo, hi] over which control guidance is active (None = always).
latents (`Tensor`):
Noisy target latents to update.
condition_latents (`Tensor`):
Clean target latents on the conditioned frames (the autoregressive seed).
Outputs:
latents (`Tensor`):
Updated target latents for this chunk.
"""
block_classes = [
Cosmos3TransferLoopPrepareStep,
Cosmos3TransferLoopDenoiser,
Cosmos3TransferLoopSchedulerStep,
]
block_names = ["prepare_transfer", "denoiser", "update_transfer"]
@property
def description(self) -> str:
return "Runs the per-chunk transfer denoising loop over scheduler timesteps."