-
Notifications
You must be signed in to change notification settings - Fork 7.2k
Cosmos3 Distilled support #14177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Cosmos3 Distilled support #14177
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,10 +4,10 @@ | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from ...models.transformers.transformer_cosmos3 import Cosmos3OmniTransformer | ||||||||||||||||||||||||
| from ...pipelines.cosmos.pipeline_cosmos3_omni import _EMBODIMENT_TO_DOMAIN_ID, CosmosActionCondition | ||||||||||||||||||||||||
| from ...schedulers import UniPCMultistepScheduler | ||||||||||||||||||||||||
| from ...schedulers import FlowMatchEulerDiscreteScheduler, UniPCMultistepScheduler | ||||||||||||||||||||||||
| from ...utils.torch_utils import randn_tensor | ||||||||||||||||||||||||
| from ..modular_pipeline import ModularPipelineBlocks, PipelineState | ||||||||||||||||||||||||
| from ..modular_pipeline_utils import ComponentSpec, InputParam, OutputParam | ||||||||||||||||||||||||
| from ..modular_pipeline_utils import ComponentSpec, ConfigSpec, InputParam, OutputParam | ||||||||||||||||||||||||
| from .modular_pipeline import Cosmos3OmniModularPipeline | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -115,6 +115,11 @@ def intermediate_outputs(self) -> list[OutputParam]: | |||||||||||||||||||||||
| type_hint=list[int], | ||||||||||||||||||||||||
| description="Indexes of conditioned vision latent frames.", | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| OutputParam( | ||||||||||||||||||||||||
| "vision_conditioning_latents", | ||||||||||||||||||||||||
| type_hint=torch.Tensor, | ||||||||||||||||||||||||
| description="Clean encoded vision latents used to re-anchor image conditioning each step.", | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @torch.no_grad() | ||||||||||||||||||||||||
|
|
@@ -165,6 +170,7 @@ def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) | |||||||||||||||||||||||
| block_state.vision_condition_mask[:, 0, 0] > 0, as_tuple=False | ||||||||||||||||||||||||
| ).flatten() | ||||||||||||||||||||||||
| block_state.vision_condition_indexes_for_pack = [int(idx.item()) for idx in vision_condition_indexes] | ||||||||||||||||||||||||
| block_state.vision_conditioning_latents = x0_tokens_vision | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| self.set_block_state(state, block_state) | ||||||||||||||||||||||||
| return components, state | ||||||||||||||||||||||||
|
|
@@ -1224,3 +1230,86 @@ def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) | |||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| self.set_block_state(state, block_state) | ||||||||||||||||||||||||
| return components, state | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class Cosmos3DistilledSetTimestepsStep(ModularPipelineBlocks): | ||||||||||||||||||||||||
| model_name = "cosmos3-omni" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def description(self) -> str: | ||||||||||||||||||||||||
| return "Initializes the fixed distilled sampling schedule from the scheduler's `fixed_step_sampler_config`." | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def expected_components(self) -> list[ComponentSpec]: | ||||||||||||||||||||||||
| return [ComponentSpec("scheduler", FlowMatchEulerDiscreteScheduler)] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def expected_configs(self) -> list[ConfigSpec]: | ||||||||||||||||||||||||
| return [ConfigSpec(name="is_distilled", default=True)] | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def inputs(self) -> list[InputParam]: | ||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||
| InputParam.template("num_inference_steps", required=False, default=None), | ||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you write a new block (Cosmos3DistilledSetTimestepsStep) for distilled checkpoint?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should add a new and assemble a see flux2 as a reference on how to structure this https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines/flux2 |
||||||||||||||||||||||||
| InputParam( | ||||||||||||||||||||||||
| name="guidance_scale", | ||||||||||||||||||||||||
| type_hint=float, | ||||||||||||||||||||||||
| default=None, | ||||||||||||||||||||||||
| description=( | ||||||||||||||||||||||||
| "Unused for distilled checkpoints; classifier-free guidance is baked into the weights and the " | ||||||||||||||||||||||||
| "scale is forced to 1.0. Passing a value other than 1.0 raises an error." | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||
| def intermediate_outputs(self) -> list[OutputParam]: | ||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||
| OutputParam("timesteps", type_hint=torch.Tensor, description="Scheduler timesteps for denoising."), | ||||||||||||||||||||||||
| OutputParam("num_warmup_steps", type_hint=int, description="Number of scheduler warmup steps."), | ||||||||||||||||||||||||
| OutputParam( | ||||||||||||||||||||||||
| "num_inference_steps", | ||||||||||||||||||||||||
| type_hint=int, | ||||||||||||||||||||||||
| description="Resolved number of denoising steps (fixed by the distilled schedule).", | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| OutputParam( | ||||||||||||||||||||||||
| name="guidance_scale", | ||||||||||||||||||||||||
| type_hint=float, | ||||||||||||||||||||||||
| description="Resolved classifier-free guidance scale (always 1.0 for distilled checkpoints).", | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| @torch.no_grad() | ||||||||||||||||||||||||
| def __call__(self, components: Cosmos3OmniModularPipeline, state: PipelineState) -> PipelineState: | ||||||||||||||||||||||||
| block_state = self.get_block_state(state) | ||||||||||||||||||||||||
| device = components._execution_device | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| fixed_step_cfg = components.scheduler.config.get("fixed_step_sampler_config", None) | ||||||||||||||||||||||||
| if not fixed_step_cfg or not fixed_step_cfg.get("t_list"): | ||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||
| "Cosmos3DistilledSetTimestepsStep requires a scheduler that ships a distilled " | ||||||||||||||||||||||||
| "`fixed_step_sampler_config.t_list`. Load a distilled Cosmos3 checkpoint or use " | ||||||||||||||||||||||||
| "`Cosmos3OmniModularPipeline` for base checkpoints." | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| sigmas = [float(s) for s in fixed_step_cfg["t_list"]] | ||||||||||||||||||||||||
| distilled_steps = len(sigmas) | ||||||||||||||||||||||||
|
Comment on lines
+1287
to
+1295
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
our scheduler does not actually have this config -> it is better to add the fixed steps as a pipeline config, you can set the value from |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if block_state.num_inference_steps is not None and block_state.num_inference_steps != distilled_steps: | ||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||
| "This is a distilled checkpoint; the step count is fixed by the scheduler's " | ||||||||||||||||||||||||
| f"`fixed_step_sampler_config.t_list` ({distilled_steps} steps). " | ||||||||||||||||||||||||
| f"`num_inference_steps` must be {distilled_steps} or left unset (got {block_state.num_inference_steps})." | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| if block_state.guidance_scale is not None and block_state.guidance_scale != 1.0: | ||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||
| "This is a distilled checkpoint; classifier-free guidance is baked into the weights. " | ||||||||||||||||||||||||
| f"`guidance_scale` must be 1.0 or left unset (got {block_state.guidance_scale})." | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| components.scheduler.set_timesteps(sigmas=sigmas, device=device) | ||||||||||||||||||||||||
| block_state.num_inference_steps = distilled_steps | ||||||||||||||||||||||||
| block_state.guidance_scale = 1.0 | ||||||||||||||||||||||||
| block_state.timesteps = components.scheduler.timesteps | ||||||||||||||||||||||||
| block_state.num_warmup_steps = len(block_state.timesteps) - distilled_steps * components.scheduler.order | ||||||||||||||||||||||||
| self.set_block_state(state, block_state) | ||||||||||||||||||||||||
| return components, state | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -271,6 +271,23 @@ def _tokenize(text: str) -> list[int]: | |
| return components, state | ||
|
|
||
|
|
||
| class Cosmos3DistilledTextEncoderStep(Cosmos3TextEncoderStep): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might be cleaner to write its own block (not subclass from Cosmos3TextEncoderStep) and not list the |
||
| model_name = "cosmos3-omni" | ||
|
|
||
| @property | ||
| def description(self) -> str: | ||
| return "Prepares distilled prompt token IDs; rejects `negative_prompt` since guidance is baked in." | ||
|
|
||
| @staticmethod | ||
| def _check_inputs(block_state) -> None: | ||
| if block_state.negative_prompt is not None: | ||
| raise ValueError( | ||
| "This is a distilled Cosmos3 checkpoint; classifier-free guidance is baked into the weights, so " | ||
| "`negative_prompt` is not supported. Leave it unset." | ||
| ) | ||
| Cosmos3TextEncoderStep._check_inputs(block_state) | ||
|
|
||
|
|
||
| class Cosmos3ActionTextStep(ModularPipelineBlocks): | ||
| model_name = "cosmos3-omni" | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This link does not exist