44
55from ...models .transformers .transformer_cosmos3 import Cosmos3OmniTransformer
66from ...pipelines .cosmos .pipeline_cosmos3_omni import _EMBODIMENT_TO_DOMAIN_ID , CosmosActionCondition
7- from ...schedulers import SchedulerMixin
7+ from ...schedulers import FlowMatchEulerDiscreteScheduler , UniPCMultistepScheduler
88from ...utils .torch_utils import randn_tensor
99from ..modular_pipeline import ModularPipelineBlocks , PipelineState
10- from ..modular_pipeline_utils import ComponentSpec , InputParam , OutputParam
10+ from ..modular_pipeline_utils import ComponentSpec , ConfigSpec , InputParam , OutputParam
1111from .modular_pipeline import Cosmos3OmniModularPipeline
1212
1313
@@ -187,7 +187,7 @@ def description(self) -> str:
187187 def expected_components (self ) -> list [ComponentSpec ]:
188188 return [
189189 ComponentSpec ("transformer" , Cosmos3OmniTransformer ),
190- ComponentSpec ("scheduler" , SchedulerMixin ),
190+ ComponentSpec ("scheduler" , UniPCMultistepScheduler ),
191191 ]
192192
193193 @property
@@ -263,7 +263,7 @@ def description(self) -> str:
263263 def expected_components (self ) -> list [ComponentSpec ]:
264264 return [
265265 ComponentSpec ("transformer" , Cosmos3OmniTransformer ),
266- ComponentSpec ("scheduler" , SchedulerMixin ),
266+ ComponentSpec ("scheduler" , UniPCMultistepScheduler ),
267267 ]
268268
269269 @property
@@ -940,7 +940,48 @@ def description(self) -> str:
940940
941941 @property
942942 def expected_components (self ) -> list [ComponentSpec ]:
943- return [ComponentSpec ("scheduler" , SchedulerMixin )]
943+ return [ComponentSpec ("scheduler" , UniPCMultistepScheduler )]
944+
945+ @property
946+ def inputs (self ) -> list [InputParam ]:
947+ return [
948+ InputParam .template ("num_inference_steps" , required = True ),
949+ ]
950+
951+ @property
952+ def intermediate_outputs (self ) -> list [OutputParam ]:
953+ return [
954+ OutputParam ("timesteps" , type_hint = torch .Tensor , description = "Scheduler timesteps for denoising." ),
955+ OutputParam ("num_warmup_steps" , type_hint = int , description = "Number of scheduler warmup steps." ),
956+ ]
957+
958+ @torch .no_grad ()
959+ def __call__ (self , components : Cosmos3OmniModularPipeline , state : PipelineState ) -> PipelineState :
960+ block_state = self .get_block_state (state )
961+ device = components ._execution_device
962+ components .scheduler .set_timesteps (block_state .num_inference_steps , device = device )
963+ block_state .timesteps = components .scheduler .timesteps
964+ block_state .num_warmup_steps = (
965+ len (block_state .timesteps ) - block_state .num_inference_steps * components .scheduler .order
966+ )
967+ self .set_block_state (state , block_state )
968+ return components , state
969+
970+
971+ class Cosmos3DistilledSetTimestepsStep (ModularPipelineBlocks ):
972+ model_name = "cosmos3-omni"
973+
974+ @property
975+ def description (self ) -> str :
976+ return "Initializes the fixed distilled sampling schedule from the scheduler's `fixed_step_sampler_config`."
977+
978+ @property
979+ def expected_components (self ) -> list [ComponentSpec ]:
980+ return [ComponentSpec ("scheduler" , FlowMatchEulerDiscreteScheduler )]
981+
982+ @property
983+ def expected_configs (self ) -> list [ConfigSpec ]:
984+ return [ConfigSpec (name = "is_distilled" , default = True )]
944985
945986 @property
946987 def inputs (self ) -> list [InputParam ]:
@@ -950,7 +991,10 @@ def inputs(self) -> list[InputParam]:
950991 name = "guidance_scale" ,
951992 type_hint = float ,
952993 default = None ,
953- description = "Classifier-free guidance scale. Forced to 1.0 for distilled checkpoints." ,
994+ description = (
995+ "Unused for distilled checkpoints; classifier-free guidance is baked into the weights and the "
996+ "scale is forced to 1.0. Passing a value other than 1.0 raises an error."
997+ ),
954998 ),
955999 ]
9561000
@@ -962,32 +1006,46 @@ def intermediate_outputs(self) -> list[OutputParam]:
9621006 OutputParam (
9631007 "num_inference_steps" ,
9641008 type_hint = int ,
965- description = "Resolved number of denoising steps." ,
1009+ description = "Resolved number of denoising steps (fixed by the distilled schedule) ." ,
9661010 ),
9671011 OutputParam (
9681012 name = "guidance_scale" ,
9691013 type_hint = float ,
970- description = "Resolved classifier-free guidance scale for the denoising loop ." ,
1014+ description = "Resolved classifier-free guidance scale (always 1.0 for distilled checkpoints) ." ,
9711015 ),
9721016 ]
9731017
9741018 @torch .no_grad ()
9751019 def __call__ (self , components : Cosmos3OmniModularPipeline , state : PipelineState ) -> PipelineState :
9761020 block_state = self .get_block_state (state )
9771021 device = components ._execution_device
978- num_inference_steps , guidance_scale = components .resolve_inference_schedule (
979- block_state .num_inference_steps ,
980- block_state .guidance_scale ,
981- )
982- block_state .num_inference_steps = num_inference_steps
983- block_state .guidance_scale = guidance_scale
9841022
985- if components .is_distilled_checkpoint :
986- components .scheduler .set_timesteps (sigmas = components .distilled_sigmas , device = device )
987- else :
988- components .scheduler .set_timesteps (num_inference_steps , device = device )
1023+ fixed_step_cfg = components .scheduler .config .get ("fixed_step_sampler_config" , None )
1024+ if not fixed_step_cfg or not fixed_step_cfg .get ("t_list" ):
1025+ raise ValueError (
1026+ "Cosmos3DistilledSetTimestepsStep requires a scheduler that ships a distilled "
1027+ "`fixed_step_sampler_config.t_list`. Load a distilled Cosmos3 checkpoint or use "
1028+ "`Cosmos3OmniModularPipeline` for base checkpoints."
1029+ )
1030+ sigmas = [float (s ) for s in fixed_step_cfg ["t_list" ]]
1031+ distilled_steps = len (sigmas )
1032+
1033+ if block_state .num_inference_steps is not None and block_state .num_inference_steps != distilled_steps :
1034+ raise ValueError (
1035+ "This is a distilled checkpoint; the step count is fixed by the scheduler's "
1036+ f"`fixed_step_sampler_config.t_list` ({ distilled_steps } steps). "
1037+ f"`num_inference_steps` must be { distilled_steps } or left unset (got { block_state .num_inference_steps } )."
1038+ )
1039+ if block_state .guidance_scale is not None and block_state .guidance_scale != 1.0 :
1040+ raise ValueError (
1041+ "This is a distilled checkpoint; classifier-free guidance is baked into the weights. "
1042+ f"`guidance_scale` must be 1.0 or left unset (got { block_state .guidance_scale } )."
1043+ )
9891044
1045+ components .scheduler .set_timesteps (sigmas = sigmas , device = device )
1046+ block_state .num_inference_steps = distilled_steps
1047+ block_state .guidance_scale = 1.0
9901048 block_state .timesteps = components .scheduler .timesteps
991- block_state .num_warmup_steps = len (block_state .timesteps ) - num_inference_steps * components .scheduler .order
1049+ block_state .num_warmup_steps = len (block_state .timesteps ) - distilled_steps * components .scheduler .order
9921050 self .set_block_state (state , block_state )
9931051 return components , state
0 commit comments