|
4 | 4 |
|
5 | 5 | from ...models.transformers.transformer_cosmos3 import Cosmos3OmniTransformer |
6 | 6 | from ...pipelines.cosmos.pipeline_cosmos3_omni import _EMBODIMENT_TO_DOMAIN_ID, CosmosActionCondition |
7 | | -from ...schedulers import UniPCMultistepScheduler |
| 7 | +from ...schedulers import FlowMatchEulerDiscreteScheduler, UniPCMultistepScheduler |
8 | 8 | from ...utils.torch_utils import randn_tensor |
9 | 9 | from ..modular_pipeline import ModularPipelineBlocks, PipelineState |
10 | | -from ..modular_pipeline_utils import ComponentSpec, InputParam, OutputParam |
| 10 | +from ..modular_pipeline_utils import ComponentSpec, ConfigSpec, InputParam, OutputParam |
11 | 11 | from .modular_pipeline import Cosmos3OmniModularPipeline |
12 | 12 |
|
13 | 13 |
|
@@ -115,6 +115,11 @@ def intermediate_outputs(self) -> list[OutputParam]: |
115 | 115 | type_hint=list[int], |
116 | 116 | description="Indexes of conditioned vision latent frames.", |
117 | 117 | ), |
| 118 | + OutputParam( |
| 119 | + "vision_conditioning_latents", |
| 120 | + type_hint=torch.Tensor, |
| 121 | + description="Clean encoded vision latents used to re-anchor image conditioning each step.", |
| 122 | + ), |
118 | 123 | ] |
119 | 124 |
|
120 | 125 | @torch.no_grad() |
@@ -165,6 +170,7 @@ def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) |
165 | 170 | block_state.vision_condition_mask[:, 0, 0] > 0, as_tuple=False |
166 | 171 | ).flatten() |
167 | 172 | block_state.vision_condition_indexes_for_pack = [int(idx.item()) for idx in vision_condition_indexes] |
| 173 | + block_state.vision_conditioning_latents = x0_tokens_vision |
168 | 174 |
|
169 | 175 | self.set_block_state(state, block_state) |
170 | 176 | return components, state |
@@ -1224,3 +1230,86 @@ def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) |
1224 | 1230 | ) |
1225 | 1231 | self.set_block_state(state, block_state) |
1226 | 1232 | return components, state |
| 1233 | + |
| 1234 | + |
| 1235 | +class Cosmos3DistilledSetTimestepsStep(ModularPipelineBlocks): |
| 1236 | + model_name = "cosmos3-omni" |
| 1237 | + |
| 1238 | + @property |
| 1239 | + def description(self) -> str: |
| 1240 | + return "Initializes the fixed distilled sampling schedule from the scheduler's `fixed_step_sampler_config`." |
| 1241 | + |
| 1242 | + @property |
| 1243 | + def expected_components(self) -> list[ComponentSpec]: |
| 1244 | + return [ComponentSpec("scheduler", FlowMatchEulerDiscreteScheduler)] |
| 1245 | + |
| 1246 | + @property |
| 1247 | + def expected_configs(self) -> list[ConfigSpec]: |
| 1248 | + return [ConfigSpec(name="is_distilled", default=True)] |
| 1249 | + |
| 1250 | + @property |
| 1251 | + def inputs(self) -> list[InputParam]: |
| 1252 | + return [ |
| 1253 | + InputParam.template("num_inference_steps", required=False, default=None), |
| 1254 | + InputParam( |
| 1255 | + name="guidance_scale", |
| 1256 | + type_hint=float, |
| 1257 | + default=None, |
| 1258 | + description=( |
| 1259 | + "Unused for distilled checkpoints; classifier-free guidance is baked into the weights and the " |
| 1260 | + "scale is forced to 1.0. Passing a value other than 1.0 raises an error." |
| 1261 | + ), |
| 1262 | + ), |
| 1263 | + ] |
| 1264 | + |
| 1265 | + @property |
| 1266 | + def intermediate_outputs(self) -> list[OutputParam]: |
| 1267 | + return [ |
| 1268 | + OutputParam("timesteps", type_hint=torch.Tensor, description="Scheduler timesteps for denoising."), |
| 1269 | + OutputParam("num_warmup_steps", type_hint=int, description="Number of scheduler warmup steps."), |
| 1270 | + OutputParam( |
| 1271 | + "num_inference_steps", |
| 1272 | + type_hint=int, |
| 1273 | + description="Resolved number of denoising steps (fixed by the distilled schedule).", |
| 1274 | + ), |
| 1275 | + OutputParam( |
| 1276 | + name="guidance_scale", |
| 1277 | + type_hint=float, |
| 1278 | + description="Resolved classifier-free guidance scale (always 1.0 for distilled checkpoints).", |
| 1279 | + ), |
| 1280 | + ] |
| 1281 | + |
| 1282 | + @torch.no_grad() |
| 1283 | + def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) -> PipelineState: |
| 1284 | + block_state = self.get_block_state(state) |
| 1285 | + device = components._execution_device |
| 1286 | + |
| 1287 | + fixed_step_cfg = components.scheduler.config.get("fixed_step_sampler_config", None) |
| 1288 | + if not fixed_step_cfg or not fixed_step_cfg.get("t_list"): |
| 1289 | + raise ValueError( |
| 1290 | + "Cosmos3DistilledSetTimestepsStep requires a scheduler that ships a distilled " |
| 1291 | + "`fixed_step_sampler_config.t_list`. Load a distilled Cosmos3 checkpoint or use " |
| 1292 | + "`Cosmos3OmniModularPipeline` for base checkpoints." |
| 1293 | + ) |
| 1294 | + sigmas = [float(s) for s in fixed_step_cfg["t_list"]] |
| 1295 | + distilled_steps = len(sigmas) |
| 1296 | + |
| 1297 | + if block_state.num_inference_steps is not None and block_state.num_inference_steps != distilled_steps: |
| 1298 | + raise ValueError( |
| 1299 | + "This is a distilled checkpoint; the step count is fixed by the scheduler's " |
| 1300 | + f"`fixed_step_sampler_config.t_list` ({distilled_steps} steps). " |
| 1301 | + f"`num_inference_steps` must be {distilled_steps} or left unset (got {block_state.num_inference_steps})." |
| 1302 | + ) |
| 1303 | + if block_state.guidance_scale is not None and block_state.guidance_scale != 1.0: |
| 1304 | + raise ValueError( |
| 1305 | + "This is a distilled checkpoint; classifier-free guidance is baked into the weights. " |
| 1306 | + f"`guidance_scale` must be 1.0 or left unset (got {block_state.guidance_scale})." |
| 1307 | + ) |
| 1308 | + |
| 1309 | + components.scheduler.set_timesteps(sigmas=sigmas, device=device) |
| 1310 | + block_state.num_inference_steps = distilled_steps |
| 1311 | + block_state.guidance_scale = 1.0 |
| 1312 | + block_state.timesteps = components.scheduler.timesteps |
| 1313 | + block_state.num_warmup_steps = len(block_state.timesteps) - distilled_steps * components.scheduler.order |
| 1314 | + self.set_block_state(state, block_state) |
| 1315 | + return components, state |
0 commit comments