Skip to main content

Overview

Cosmos3’s generation path turns a sentence into a video. Switch on the sound stream and the same denoising run also writes an audio track that follows the frames. T2V produces video only; T2AV advances the video latent and the sound latent on one timeline, so the picture surfaces out of the noise while the waveform takes shape beside it. One plugin, cosmos3, covers both paths and both machine sizes. With the default cfg_size=tp_size=1 the engine runs inline in your process. Ask for --cfg 2 or --tp N and it spawns one worker per rank on the first visible GPUs instead; the request and the outputs stay the same.
This path is built for correctness and reference alignment, not speed. The denoising loop is a Python-level UniPC loop with CUDA graphs off, and there are no dedicated kernels or batching yet. Read any timing you collect as a baseline.

Architecture

The path follows PhyAI’s usual . Inside the plugin the work splits into a handful of pieces:
phyai/src/phyai/models/cosmos3
main_cosmos3.py
scheduler_cosmos3.py
model_runner_cosmos3.py
model_runner_vae_cosmos3.py
modeling_cosmos3.py
vae_wan.py
avae_sound.py
sampler_unipc.py
configuration_cosmos3.py

Run path

1

Prepare weights

Download Cosmos3-Nano. The examples expect this layout:
2

Construct the engine

T2V needs the transformer and the VAE. T2AV also loads the AVAE from sound_tokenizer, which is what load_sound=True asks for.
flow_shift=10.0 with use_karras_sigmas=False is the native linear-flow UniPC schedule; the example script uses the same values.
3

Tokenize the prompt

The scheduler never sees raw text. Cosmos3Processor applies the chat template, appends the eos and <|vision_start|> tokens, and returns token ids for the positive and negative prompts.
negative_prompt=None selects Cosmos3’s built-in structured negative prompt. Pass "" for an empty one.
4

Build the request

Cosmos3T2VRequest carries the tokenized conditions, the latent grid, and the sampler settings.
pixel_to_latent_shape divides the pixel dimensions by the VAE compression: 4 along time, 16 along each spatial axis.
5

Run generation

T2V returns a pixel tensor shaped (B, 3, T, H, W) in [0, 1]. T2AV returns a dict:
6

Save media

The postprocessor moves everything to the CPU, converts the frames to uint8 RGB, and muxes the waveform into the same mp4 when there is one.

End-to-end examples

examples/cosmos3/run_cosmos3.py strings these steps together. A plain T2V run:
The same script spreads the run over eight GPUs once you add CFG and tensor parallelism. Eight ranks need eight visible devices, so pick them on the launching process:
Add --sound for T2AV. The sound stream loads the AVAE and advances a second latent every step, so expect more memory and a longer run:
The defaults are 720x1280, 189 frames, and 35 steps, which takes a while. Shrink the run for a first smoke test:
The script prints timings for model_load, preprocess, inference, to_cpu, and encode. inference covers the denoising loop and the VAE decode; encode is PyAV writing the file.

Multi-GPU execution

Two fields in ParallelConfig do the work. cfg_size=2 runs the conditional and unconditional branches side by side on two rank groups instead of back to back on one GPU. tp_size=N shards the transformer inside each branch across N ranks. Every rank is one worker process, so a run needs cfg_size * tp_size GPUs, taken from the visible devices in order. Compared with the inline snippet, little changes. EngineConfig gains a parallel block. Request tensors are built on the CPU, because the workers own the GPUs and the request has to cross a process boundary. And the engine moves behind an if __name__ == "__main__": guard: workers start with spawn, which re-imports the main module, and without the guard every worker would try to build an engine of its own. The deployment argument stays optional; here it only gives the workers longer to load the checkpoint.
engine.step() hands back a CUDA-IPC view of the tensor on the output rank’s GPU; the postprocessor copies it to the CPU, so saving works as before. Cosmos3 accepts cfg_size 1 or 2 and any tp_size that divides both the attention heads and the KV heads (1, 2, 4, or 8 for Cosmos3-Nano), with dense and attention TP kept equal. Other parallel axes are rejected before a worker starts. Serving replicas and torchrun launches are covered in Parallel serving.

Full example