Skip to content

feat: support Cosmos3 (Omni) via PatchFunctor#1088

Merged
DefTruth merged 2 commits into
vipshop:mainfrom
johnnynunez:feat/cosmos3-omni-support
Jul 10, 2026
Merged

feat: support Cosmos3 (Omni) via PatchFunctor#1088
DefTruth merged 2 commits into
vipshop:mainfrom
johnnynunez:feat/cosmos3-omni-support

Conversation

@johnnynunez

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds Cosmos3 (Omni) support — nvidia/Cosmos3-Nano / nvidia/Cosmos3-Super via Cosmos3OmniPipeline (diffusers main).

The existing Cosmos adapter only accepts CosmosTransformer3DModel (Cosmos 1/2). Cosmos3OmniPipeline uses Cosmos3OmniTransformer, a MoT dual-stream DiT whose decoder layers take/return (und_seq, gen_seq) instead of the usual (hidden_states, encoder_hidden_states) contract — so enable_cache fails with:

AssertionError: Transformer class Cosmos3OmniTransformer not in allowed classes: ['CosmosTransformer3DModel']

Changes

  • Cosmos3OmniPatchFunctor (new): patches the decoder layers + transformer forward to reorder the block contract to (hidden_states=gen_seq, encoder_hidden_states=und_seq) = ForwardPattern.Pattern_0. This is load-bearing, not cosmetic: the und (text/understanding) stream is quasi-static across denoising steps, so if DBCache computed its residual-diff decision on it, every step would be a false cache hit and generation would break. With the gen stream first, the decision tracks the actually-denoised tokens.
  • cosmos_adapter: detects Cosmos3OmniTransformer (guarded try/except ImportError for older diffusers) and routes through the functor with has_separate_cfg=True (the pipeline runs cond/uncond as separate transformer calls).
  • README: Cosmos3 row.

Measured (real hardware)

nvidia/Cosmos3-Nano T2V, RTX PRO 6000 Blackwell (sm_120, 96 GB), torch 2.12.1+cu132, diffusers 0.39.0.dev0, 189 frames / 35 steps, UniPC flow_shift=10, warmup excluded, median of 3, fixed seed:

Res Config Median Speedup Cached steps
480p baseline (bf16, SDPA) 138.59s 1.00×
480p DBCache rdt=0.20 76.75s 1.81× 18/35
480p DBCache rdt=0.20 + torch.compile 67.86s 2.04× 18/35
256p baseline 11.87s 1.00×
256p DBCache rdt=0.20 7.75s 1.53× 18/35

Residual diffs P50 0.148 (rdt=0.20), stable across CFG/non-CFG contexts. Output latents finite/sane (no NaN).

cache_dit.summary() works and reports per-context stats (cond + CFG separately).

Notes / known limitation

  • Requires diffusers main (Cosmos3OmniPipeline/Cosmos3OmniTransformer are not in the 0.38 release); the functor import is _safe_import-guarded so older diffusers are unaffected.
  • Combining DBCache + torchao NVFP4 quantization + torch.compile currently trips a Dynamo resume-path bug (AttributeError: 'NVFP4Tensor' object has no attribute 'per_tensor_scale', torchao 0.17 + torch 2.12). DBCache+compile (bf16) and DBCache+NVFP4 (eager) both work. I'll file a separate issue with details — relevant to RFC [RFC] NVFP4 (non SVDQuant) Quantization Support #1061.

Cosmos3OmniPipeline (nvidia/Cosmos3-Nano, Cosmos3-Super) uses
Cosmos3OmniTransformer, a MoT dual-stream DiT whose decoder layers
take/return (und_seq, gen_seq) instead of the usual
(hidden_states, encoder_hidden_states) contract, so the existing
'Cosmos' adapter (CosmosTransformer3DModel) rejects it.

- Add Cosmos3OmniPatchFunctor: reorders the block contract to
  (hidden_states=gen_seq, encoder_hidden_states=und_seq) =
  ForwardPattern.Pattern_0, so the DBCache residual-diff decision
  tracks the DENOISED gen stream. The und/text stream is quasi-static
  across denoising steps and would otherwise turn every step into a
  false cache hit.
- Extend the Cosmos adapter to detect Cosmos3OmniTransformer and route
  it through the functor (has_separate_cfg=True: the pipeline runs
  cond/uncond as separate transformer calls).
- README: add Cosmos3 row.

Measured on nvidia/Cosmos3-Nano, RTX PRO 6000 Blackwell (sm_120),
torch 2.12.1+cu132, diffusers main (0.39.0.dev0), 189 frames/35 steps,
warmup excluded, median of 3:

  480p: DBCache(rdt=0.20) 76.75s vs 138.59s baseline (1.81x);
        DBCache + torch.compile 67.86s (2.04x), 18/35 steps cached,
        residual diffs P50 0.148.
  256p: 7.75s vs 11.87s baseline (1.53x).

@DefTruth DefTruth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!

Comment thread README.md Outdated
| Video | EasyAnimate | [`EasyAnimateTransformer3DModel`](src/cache_dit/caching/block_adapters/adapters.py) | 3 | ✔️/✖️/✔️/✔️ |
| Video | ConsisID | [`ConsisIDTransformer3DModel`](src/cache_dit/caching/block_adapters/adapters.py) | 1 | ✔️/✔️/✔️/✔️ |
| Video | Cosmos | [`CosmosTransformer3DModel`](src/cache_dit/caching/block_adapters/adapters.py) | 7+ | ✔️/✖️/✔️/✔️ |
| Video | Cosmos3 (Omni: T2V/T2I/I2V/V2V) | [`Cosmos3OmniTransformer`](src/cache_dit/caching/patch_functors/functor_cosmos3.py) | 2 | ✔️/✖️/✔️/✔️ |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer Cosmos3 (Omni) not Cosmos3 (Omni: T2V/T2I/I2V/V2V) to keep the docs simple.

@DefTruth

Copy link
Copy Markdown
Member

@johnnynunez It would better if you can also add an example into cache_dit.generate CLI (The cache-dit-model-integration skill can help you do this), after that, we can test it via:

# For example:
python3 -m cache_dit.generate cosmos3_omni_t2i --cache --summary

__all__ = [
"flux_example",
"flux_fill_example",
"flux2_example",
"flux2_klein_example",
"flux2_klein_edit_example",
"qwen_image_example",
"qwen_image_controlnet_example",
"qwen_image_edit_example",
"qwen_image_layered_example",
"skyreels_v2_example",
"ltx2_t2v_example",
"ltx2_i2v_example",
"wan_example",
"wan_i2v_example",
"wan_vace_example",
"ovis_image_example",
"zimage_example",
"zimage_controlnet_example",
"longcat_image_example",
"longcat_image_edit_example",
"glm_image_example",
"glm_image_edit_example",
"firered_image_edit_example",
"helios_t2v_example",
"helios_t2v_distill_example",
"flux2_klein_kv_edit_example",
"boogu_image_edit_example",
"ernie_image_example",
"ernie_image_turbo_example",
"krea2_example",
"joy_image_edit_example",
"bria_fibo_example",
"anyflow_far_example",
]
# Please note that the following environment variables is only for debugging and
# development purpose. In practice, users should directly provide the model names
# or paths. The default values are the official model names on HuggingFace Hub.
_env_path_mapping = {
"FLUX_DIR": "black-forest-labs/FLUX.1-dev",
"FLUX_FILL_DIR": "black-forest-labs/FLUX.1-Fill-dev",
"NUNCHAKU_FLUX_DIR": "nunchaku-tech/nunchaku-flux.1-dev",
"FLUX_2_DIR": "black-forest-labs/FLUX.2-dev",
"FLUX_2_KLEIN_4B_DIR": "black-forest-labs/FLUX.2-klein-4B",
"FLUX_2_KLEIN_BASE_4B_DIR": "black-forest-labs/FLUX.2-klein-base-4B",
"FLUX_2_KLEIN_9B_DIR": "black-forest-labs/FLUX.2-klein-9B",
"FLUX_2_KLEIN_BASE_9B_DIR": "black-forest-labs/FLUX.2-klein-base-9B",
"FLUX_2_KLEIN_9B_KV_DIR": "black-forest-labs/FLUX.2-klein-9b-kv",
"OVIS_IMAGE_DIR": "AIDC-AI/Ovis-Image-7B",
"LTX2_DIR": "Lightricks/LTX-2",
"QWEN_IMAGE_DIR": "Qwen/Qwen-Image",
"QWEN_IMAGE_2512_DIR": "Qwen/Qwen-Image-2512",
"QWEN_IMAGE_LIGHT_DIR": "lightx2v/Qwen-Image-Lightning",
"QWEN_IMAGE_EDIT_2509_DIR": "Qwen/Qwen-Image-Edit-2509",
"QWEN_IMAGE_EDIT_2511_DIR": "Qwen/Qwen-Image-Edit-2511",
"QWEN_IMAGE_EDIT_2511_LIGHT_DIR": "lightx2v/Qwen-Image-Edit-2511-Lightning",
"QWEN_IMAGE_CONTROLNET_DIR": "InstantX/Qwen-Image-ControlNet-Inpainting",
"QWEN_IMAGE_LAYERED_DIR": "Qwen/Qwen-Image-Layered",
"SKYREELS_V2_DIR": "Skywork/SkyReels-V2-T2V-14B-720P-Diffusers",
"WAN_DIR": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
"WAN_2_2_DIR": "Wan-AI/Wan2.2-T2V-A14B-Diffusers",
"WAN_I2V_DIR": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers",
"WAN_2_2_I2V_DIR": "Wan-AI/Wan2.2-I2V-A14B-Diffusers",
"WAN_VACE_DIR": "Wan-AI/Wan2.1-VACE-1.3B-diffusers",
"WAN_2_2_VACE_DIR": "linoyts/Wan2.2-VACE-Fun-14B-diffusers",
"ZIMAGE_DIR": "Tongyi-MAI/Z-Image",
"ZIMAGE_TURBO_DIR": "Tongyi-MAI/Z-Image-Turbo",
"NUNCHAKU_ZIMAGE_TURBO_DIR": "nunchaku-tech/nunchaku-z-image-turbo",
"Z_IMAGE_TURBO_CONTROLNET_2_1_DIR": "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.1",
"Z_IMAGE_TURBO_CONTROLNET_2_0_DIR": "alibaba-pai/Z-Image-Turbo-Fun-Controlnet-Union-2.0",
"LONGCAT_IMAGE_DIR": "meituan-longcat/LongCat-Image",
"LONGCAT_IMAGE_EDIT_DIR": "meituan-longcat/LongCat-Image-Edit",
"GLM_IMAGE_DIR": "zai-org/GLM-Image",
"FIRERED_IMAGE_EDIT_1_DIR": "FireRedTeam/FireRed-Image-Edit-1.0",
"FIRERED_IMAGE_EDIT_1_1_DIR": "FireRedTeam/FireRed-Image-Edit-1.1",
"HELIOS_BASE_DIR": "BestWishYsh/Helios-Base",
"HELIOS_DISTILLED_DIR": "BestWishYsh/Helios-Distilled",

@DefTruth

Copy link
Copy Markdown
Member

The pre-commit check failed, it would be better to refer to our docs PRE_COMMIT and make a fix.

@DefTruth DefTruth mentioned this pull request Jul 10, 2026
8 tasks
… examples

- functor_cosmos3.py: docstring re-indented by docformatter (the pre-commit
  failure on the PR run).
- README: 'Cosmos3 (Omni)' per review.
- Add cosmos3_omni_t2i / cosmos3_omni_t2v to cache_dit.generate:
  ExampleRegister entries, COSMOS3_OMNI_DIR env mapping, __all__ +
  _utils/__init__ registration. Output field is 'video' (not 'frames'),
  aliased via post-load call wrapper; guardrail disabled by default in the
  example loader (optional cosmos_guardrail dep) with license note.

Verified on RTX PRO 6000 (sm_120):
  t2i base 2.92s -> cache 2.39s, PSNR 30.25, SSIM 0.764 (rdt=0.12)
                     rdt=0.08: PSNR 31.22, SSIM 0.844
  t2v (93f) base 53.77s -> cache 45.28s
@johnnynunez

Copy link
Copy Markdown
Contributor Author

Thanks for the review @DefTruth! Addressed in f2aff2e:

  1. pre-commit: fixed — docformatter wanted the class docstring in functor_cosmos3.py re-indented (the local hook env I first ran didn't include it; now run against the repo's .pre-commit-config.yaml, all hooks pass on the changed files).
  2. README: simplified to Cosmos3 (Omni) as requested.
  3. generate CLI examples: added cosmos3_omni_t2i and cosmos3_omni_t2v following the model-integration skill (register entries, COSMOS3_OMNI_DIR env mapping, __all__ + _utils/__init__ registration). Two Cosmos3-specific notes:
    • the pipeline output field is video (not frames/images), so the example wraps __call__ post-load to alias it for the generic output handling;
    • the Cosmos guardrail needs the optional cosmos_guardrail package, so the example loads with enable_safety_checker=False (documented in the docstring with the NVIDIA Open Model License note) while keeping the pipeline class a genuine Cosmos3OmniPipeline so adapter matching works.

Verified on RTX PRO 6000 Blackwell:

python3 -m cache_dit.generate cosmos3_omni_t2i --cache --summary
# base 2.92s -> cache 2.39s | PSNR 30.25, SSIM 0.764 (default rdt=0.12)
# --residual-diff-threshold 0.08 -> PSNR 31.22, SSIM 0.844
python3 -m cache_dit.generate cosmos3_omni_t2v --cache --summary
# base 53.77s -> cache 45.28s (480x832, 93 frames)

@DefTruth

Copy link
Copy Markdown
Member

confirm works! thanks for your contribution!

@DefTruth DefTruth changed the title feat: support Cosmos3 (Omni) pipelines via Cosmos3OmniPatchFunctor feat: support Cosmos3 (Omni) via PatchFunctor Jul 10, 2026
@DefTruth DefTruth merged commit 8419cc9 into vipshop:main Jul 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants