[Model] Add Cosmos3 mixed W8A8/W8A16 and W4A4/W4A16 denoising (#6560)

Signed-off-by: Rahul Steiger <rsteiger@aws-cmh-slurm-1-vscode-04.cm.cluster>
Signed-off-by: Wojciech Kutak <wkutak@nvidia.com>
Co-authored-by: Rahul Steiger <rsteiger@nvidia.com>
This commit is contained in:
wkutakandRahul Steiger authored and GitHub committed 2026-09-10 23:51:09 +12:00
1 parent d8d4062547
commit 43a476c1e5
10 files changed
+1509 -4

No files matched your search

+85
View File
@@ -204,6 +204,91 @@ omni = Omni(
| `--linear-backend cutlass` | str | auto | Select the validated CUTLASS linear backend for supported ModelOpt NVFP4 or mixed FP8/NVFP4 diffusion stages |
| `--moe-backend cutlass` | str | auto | Select the validated CUTLASS MoE backend for supported ModelOpt mixed MoE checkpoints |
## Cosmos3 Mixed-Precision Schedule
The experimental Cosmos3 schedule can use the checkpoint-native quantized GEMM for middle denoising
steps and dense 16-bit activation execution for selected first and last steps.
The schedule supports serialized ModelOpt FP8 and NVFP4 checkpoints:
| Detected weight format | Native middle steps | A16 boundary steps |
|------------------------|---------------------|--------------------|
| FP8 | W8A8 | W8A16 |
| NVFP4 | W4A4 | W4A16 |
The native and A16 paths share one quantized weight representation. The A16
path dequantizes the live backend weight and calls `F.linear`; it does not keep
a second checkpoint-weight snapshot. Scheduled FP8 currently requires
serialized tensorwise scales and a backend that retains canonical FP8 weights.
Scheduled NVFP4 requires a supported CUTLASS-compatible native or FlashInfer
layout. SmoothQuant, Marlin-repacked FP8, and per-channel/per-token FP8
schedules fail closed.
The reasoner uses dense A16 execution by default when its weights are FP8 or
NVFP4. Set the nested `reasoner` field to `native` to retain the checkpoint-native
W8A8/W4A4 path. A BF16 reasoner remains BF16 in either mode. The schedule
currently requires tensor parallel size 1 and one active request per worker,
does not support HSDP, and does not support block-scaled FP8. Its live-weight
design is compatible with model-level and standard layer-wise offload, but
those paths still require GPU end-to-end validation. Distributed layer-wise
offload is rejected because its direct loader bypasses ModelOpt post-load
transformations.
A checkpoint can opt in by adding a versioned policy to its authoritative
`transformer/config.json`. The same policy schema is used for FP8 and NVFP4:
```json
{
"quantization_config": {
"quant_method": "modelopt",
"quant_algo": "FP8",
"runtime": {
"diffusion_step_policy": {
"schema_version": 1,
"type": "first_last_n",
"index_space": "denoising_loop_iteration",
"scope": ["transformer"],
"default_mode": "native",
"first_steps": {"count": 3, "mode": "a16"},
"last_steps": {"count": 3, "mode": "a16"},
"overlap": "a16",
"reasoner": "a16"
}
}
}
}
```
The example preserves the checkpoint's existing `quant_method` and
`quant_algo`; only `runtime` is added.
When present and valid, the checkpoint policy is the default. An explicit
runtime object overrides it. To retain ordinary checkpoint-native execution
for every step, disable only the schedule:
```bash
vllm serve /path/to/Cosmos3-Nano-modelopt \
--omni \
--additional-config '{"cosmos3_mixed_precision":{"enabled":false}}'
```
This does not disable checkpoint quantization; it prevents installation of the
mixed-step runtime.
```bash
vllm serve /path/to/Cosmos3-Nano-modelopt \
--omni \
--additional-config \
'{"cosmos3_mixed_precision":{"first_steps":3,"last_steps":3,"reasoner":"a16"}}'
```
The presence of `cosmos3_mixed_precision` supplies an explicit runtime
override; an empty object uses the defaults shown above.
The schedule uses vLLM's selected native backend and fails during loading if
its live weight layout cannot support A16 dequantization.
The runtime selects FP8 or NVFP4 from the checkpoint's ModelOpt configuration.
BF16 linears are untouched. Mixed FP8/NVFP4 checkpoints are not supported by
this schedule.
## Validation and Notes
1. Compare the ModelOpt checkpoint against the BF16 baseline with the same
+32
View File
@@ -115,6 +115,38 @@ shift at the same seed). The pipeline
auto-resolves from `model_index.json`; pass
`--model-class-name Cosmos3OmniDiffusersPipeline` to force it explicitly.
For a serialized ModelOpt FP8 or NVFP4 checkpoint, an experimental
mixed-precision schedule can use native W8A8/W4A4 in middle denoising steps
and dense W8A16/W4A16 in the first and last steps:
```bash
vllm serve /path/to/Cosmos3-Nano-modelopt \
--omni \
--additional-config \
'{"cosmos3_mixed_precision":{"first_steps":3,"last_steps":3,"reasoner":"a16"}}'
```
The nested object's presence supplies an explicit runtime override; use an
empty object for these defaults. A compatible checkpoint can instead declare
the versioned `runtime.diffusion_step_policy` in its authoritative
`transformer/config.json`. The checkpoint policy is used only when no runtime
override is present. Use
`--additional-config '{"cosmos3_mixed_precision":{"enabled":false}}'` to
disable the checkpoint schedule without disabling checkpoint quantization.
This path currently requires tensor parallel size 1 and does not support HSDP
or block-scaled FP8. It keeps one live quantized weight representation:
scheduled FP8 requires serialized tensorwise scales and a canonical backend,
while scheduled NVFP4 requires a supported CUTLASS-compatible native or
FlashInfer layout. Its dequantization is a correctness baseline; no speedup is
implied. Quantized reasoner weights use A16 by default; set
`"reasoner":"native"` in the nested object to keep W8A8/W4A4.
The checkpoint's ModelOpt configuration selects FP8 or NVFP4; mixed FP8/NVFP4
checkpoints are not supported by this schedule. BF16 linears are left unchanged.
The schedule currently supports one active request per worker. Model-level and
layer-wise offload are designed to work with this live-weight path but still
require GPU validation. Distributed layer-wise offload and incompatible native
weight layouts fail during loading.
#### Verification
Best quality uses the JSON-upsampled prompts from `assets/` (download with
@@ -0,0 +1,690 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from __future__ import annotations
from types import SimpleNamespace
import pytest
import torch
from vllm_omni.diffusion.models.cosmos3.mixed_precision import (
Cosmos3MixedPrecisionConfig,
Cosmos3MixedPrecisionRuntime,
resolve_mixed_precision_config,
)
from vllm_omni.diffusion.models.cosmos3.mixed_precision import runtime as runtime_impl
from vllm_omni.diffusion.models.cosmos3.mixed_precision.checkpoint import read_checkpoint_policy
from vllm_omni.diffusion.models.cosmos3.mixed_precision.runtime import (
Cosmos3MixedPrecisionLinearMethod,
)
from vllm_omni.diffusion.models.cosmos3.mixed_precision.strategy import (
Fp8W8A8W8A16Strategy,
Nvfp4W4A4W4A16Strategy,
)
pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
def _policy(
*,
first_steps: int = 3,
last_steps: int = 3,
reasoner: str = "a16",
scope: list[str] | None = None,
) -> dict[str, object]:
return {
"schema_version": 1,
"type": "first_last_n",
"index_space": "denoising_loop_iteration",
"scope": scope or ["transformer"],
"default_mode": "native",
"first_steps": {"count": first_steps, "mode": "a16"},
"last_steps": {"count": last_steps, "mode": "a16"},
"overlap": "a16",
"reasoner": reasoner,
}
def _fake_quant_config(name: str, *, serialized: bool = True):
if name == "modelopt":
return SimpleNamespace(
get_name=lambda: name,
is_checkpoint_fp8_serialized=serialized,
)
if name == "modelopt_fp4":
return SimpleNamespace(
get_name=lambda: name,
quant_method="NVFP4",
is_checkpoint_nvfp4_serialized=serialized,
)
return SimpleNamespace(get_name=lambda: name)
def _checkpoint_od_config(
quant_config,
*,
policy: object | None = None,
additional_config: dict[str, object] | None = None,
):
quant_config_name = quant_config.get_name()
quant_algo = {
"modelopt": "FP8",
"modelopt_fp4": "NVFP4",
}.get(quant_config_name, "FP8")
disk_quant_config: dict[str, object] = {
"quant_method": quant_config_name,
"quant_algo": quant_algo,
}
if policy is not None:
disk_quant_config["runtime"] = {"diffusion_step_policy": policy}
return SimpleNamespace(
quantization_config=quant_config,
tf_model_config=SimpleNamespace(
params={"quantization_config": disk_quant_config},
quant_config=quant_config,
),
additional_config=additional_config,
)
def _swizzle_blockscale_cpu(scale: torch.Tensor) -> torch.Tensor:
rows, cols = scale.shape
padded_rows = ((rows + 127) // 128) * 128
padded_cols = ((cols + 3) // 4) * 4
padded = torch.zeros(
(1, padded_rows, padded_cols),
dtype=scale.dtype,
device=scale.device,
)
padded[0, :rows, :cols] = scale
padded = padded.reshape(1, padded_rows // 128, 4, 32, padded_cols // 4, 4)
return (
padded.permute(0, 1, 4, 3, 2, 5)
.contiguous()
.reshape(
padded_rows,
padded_cols,
)
)
def test_config_parses_nested_schedule_and_reasoner_policy() -> None:
config = Cosmos3MixedPrecisionConfig.from_additional_config(
{
"cosmos3_mixed_precision": {
"first_steps": 2,
"last_steps": 4,
"reasoner": "native",
}
}
)
assert config is not None
assert config.reasoner == "native"
assert [index for index in range(10) if config.use_high_precision(index, 10)] == [0, 1, 6, 7, 8, 9]
@pytest.mark.parametrize(
("first_steps", "last_steps", "selected"),
[
(0, 2, [5, 6]),
(2, 0, [0, 1]),
(0, 0, []),
(4, 4, list(range(7))),
],
)
def test_schedule_boundaries_and_overlap(
first_steps: int,
last_steps: int,
selected: list[int],
) -> None:
config = Cosmos3MixedPrecisionConfig(
first_steps=first_steps,
last_steps=last_steps,
)
assert [index for index in range(7) if config.use_high_precision(index, 7)] == selected
def test_one_step_request_honors_boundary_precision() -> None:
config = Cosmos3MixedPrecisionConfig(first_steps=1, last_steps=1)
assert config.use_high_precision(0, 1)
@pytest.mark.parametrize(
("values", "message"),
[
({"cosmos3_mixed_precision": True}, "must be a mapping"),
({"cosmos3_mixed_precision": {"first_steps": -1}}, "non-negative"),
({"cosmos3_mixed_precision": {"reasoner": "fp16"}}, "must be one of"),
({"cosmos3_mixed_precision": {"enabled": 0}}, "must be a boolean"),
(
{"cosmos3_mixed_precision": {"enabled": False, "first_steps": 1}},
"cannot be combined",
),
({"cosmos3_mixed_precision": {"unknown": 1}}, "Unknown"),
],
)
def test_config_rejects_invalid_values(values: dict, message: str) -> None:
with pytest.raises((TypeError, ValueError), match=message):
Cosmos3MixedPrecisionConfig.from_additional_config(values)
def test_config_presence_enables_defaults() -> None:
assert Cosmos3MixedPrecisionConfig.from_additional_config({}) is None
config = Cosmos3MixedPrecisionConfig.from_additional_config({"cosmos3_mixed_precision": {}})
assert config == Cosmos3MixedPrecisionConfig()
def test_noop_config_does_not_install_runtime() -> None:
assert (
Cosmos3MixedPrecisionConfig.from_additional_config(
{
"cosmos3_mixed_precision": {
"first_steps": 0,
"last_steps": 0,
"reasoner": "native",
}
}
)
is None
)
def test_additional_config_distinguishes_absent_and_disabled() -> None:
assert Cosmos3MixedPrecisionConfig.resolve_additional_config({}) == (False, None)
assert Cosmos3MixedPrecisionConfig.resolve_additional_config({"cosmos3_mixed_precision": {"enabled": False}}) == (
True,
None,
)
assert Cosmos3MixedPrecisionConfig.resolve_additional_config(
{
"cosmos3_mixed_precision": {
"first_steps": 0,
"last_steps": 0,
"reasoner": "native",
}
}
) == (True, None)
def test_checkpoint_policy_round_trip_through_transformer_config() -> None:
from vllm_omni.diffusion.data import TransformerConfig
disk = {
"_class_name": "Cosmos3VFMTransformer",
"quantization_config": {
"quant_method": "modelopt",
"quant_algo": "FP8",
"runtime": {"diffusion_step_policy": _policy(first_steps=2, last_steps=4)},
},
}
tf_config = TransformerConfig.from_dict(disk)
assert tf_config.quant_config is not None
assert tf_config.quant_config.get_name() == "modelopt"
assert tf_config.to_dict()["quantization_config"]["runtime"] == disk["quantization_config"]["runtime"]
assert read_checkpoint_policy(SimpleNamespace(tf_model_config=tf_config)) == Cosmos3MixedPrecisionConfig(
first_steps=2,
last_steps=4,
reasoner="a16",
)
@pytest.mark.parametrize("name", ["modelopt", "modelopt_fp4"])
def test_checkpoint_policy_supports_serialized_modelopt_formats(name: str) -> None:
od_config = _checkpoint_od_config(_fake_quant_config(name), policy=_policy())
assert read_checkpoint_policy(od_config) == Cosmos3MixedPrecisionConfig()
@pytest.mark.parametrize("name", ["modelopt", "modelopt_fp4"])
def test_checkpoint_policy_rejects_nonserialized_modelopt_formats(name: str) -> None:
od_config = _checkpoint_od_config(
_fake_quant_config(name, serialized=False),
policy=_policy(),
)
with pytest.raises(ValueError, match="serialized ModelOpt"):
read_checkpoint_policy(od_config)
def test_checkpoint_policy_rejects_mixed_modelopt_format() -> None:
with pytest.raises(ValueError, match="serialized ModelOpt FP8 or NVFP4"):
read_checkpoint_policy(_checkpoint_od_config(_fake_quant_config("modelopt_mixed"), policy=_policy()))
def test_checkpoint_policy_missing_metadata_preserves_ordinary_path() -> None:
assert read_checkpoint_policy(_checkpoint_od_config(_fake_quant_config("modelopt"))) is None
def test_checkpoint_policy_rejects_malformed_runtime_container() -> None:
od_config = _checkpoint_od_config(_fake_quant_config("modelopt"))
od_config.tf_model_config.params["quantization_config"]["runtime"] = True
with pytest.raises(TypeError, match="runtime must be a mapping"):
read_checkpoint_policy(od_config)
@pytest.mark.parametrize(
("field", "value", "message"),
[
("schema_version", 2, "schema_version"),
("type", "sigma_ranges", "type"),
("index_space", "scheduler_timestep", "index_space"),
("default_mode", "a16", "default_mode"),
("overlap", "native", "overlap"),
("reasoner", "fp16", "reasoner"),
],
)
def test_checkpoint_policy_rejects_invalid_schema(field: str, value: object, message: str) -> None:
policy = _policy()
policy[field] = value
with pytest.raises(ValueError, match=message):
read_checkpoint_policy(_checkpoint_od_config(_fake_quant_config("modelopt"), policy=policy))
@pytest.mark.parametrize(
("step_range", "message"),
[
({"count": -1, "mode": "a16"}, "non-negative"),
({"count": True, "mode": "a16"}, "non-negative"),
({"count": 1, "mode": "native"}, "mode"),
({"mode": "a16"}, "Missing"),
({"count": 1, "mode": "a16", "sigma": 1.0}, "Unknown"),
],
)
def test_checkpoint_policy_rejects_invalid_step_range(step_range: object, message: str) -> None:
policy = _policy()
policy["first_steps"] = step_range
with pytest.raises((TypeError, ValueError), match=message):
read_checkpoint_policy(_checkpoint_od_config(_fake_quant_config("modelopt"), policy=policy))
def test_checkpoint_policy_rejects_unsupported_quantization_config() -> None:
with pytest.raises(ValueError, match="serialized ModelOpt FP8 or NVFP4"):
read_checkpoint_policy(_checkpoint_od_config(_fake_quant_config("compressed-tensors"), policy=_policy()))
def test_checkpoint_policy_for_other_scope_is_not_applied() -> None:
od_config = _checkpoint_od_config(
_fake_quant_config("modelopt"),
policy=_policy(scope=["vae"]),
)
assert read_checkpoint_policy(od_config) is None
def test_additional_config_overrides_and_disables_checkpoint_policy() -> None:
checkpoint = _checkpoint_od_config(
_fake_quant_config("modelopt"),
policy=_policy(first_steps=1, last_steps=1),
)
assert resolve_mixed_precision_config(checkpoint) == (
Cosmos3MixedPrecisionConfig(first_steps=1, last_steps=1),
"checkpoint",
)
checkpoint.additional_config = {
"cosmos3_mixed_precision": {
"first_steps": 2,
"last_steps": 0,
"reasoner": "native",
}
}
assert resolve_mixed_precision_config(checkpoint) == (
Cosmos3MixedPrecisionConfig(first_steps=2, last_steps=0, reasoner="native"),
"additional_config",
)
checkpoint.additional_config = {"cosmos3_mixed_precision": {"enabled": False}}
assert resolve_mixed_precision_config(checkpoint) == (None, "additional_config_disabled")
@pytest.mark.parametrize("name", ["modelopt", "modelopt_fp4"])
def test_additional_config_supports_serialized_modelopt_formats_without_checkpoint_policy(name: str) -> None:
od_config = _checkpoint_od_config(
_fake_quant_config(name),
additional_config={"cosmos3_mixed_precision": {}},
)
assert resolve_mixed_precision_config(od_config) == (Cosmos3MixedPrecisionConfig(), "additional_config")
@pytest.mark.parametrize("has_checkpoint_policy", [False, True])
@pytest.mark.parametrize(
("name", "serialized"),
[
("modelopt_mixed", True),
("mxfp8", True),
("compressed-tensors", True),
("modelopt", False),
("modelopt_fp4", False),
],
)
def test_additional_config_rejects_incompatible_quantization(
name: str, serialized: bool, has_checkpoint_policy: bool
) -> None:
od_config = _checkpoint_od_config(
_fake_quant_config(name, serialized=serialized),
policy=_policy() if has_checkpoint_policy else None,
additional_config={"cosmos3_mixed_precision": {}},
)
with pytest.raises(ValueError, match="serialized ModelOpt"):
resolve_mixed_precision_config(od_config)
@pytest.mark.parametrize("additional_config", [None, {"cosmos3_mixed_precision": {}}])
def test_policy_validates_effective_quantization_config(additional_config: dict[str, object] | None) -> None:
od_config = _checkpoint_od_config(
_fake_quant_config("modelopt"),
policy=_policy(),
additional_config=additional_config,
)
od_config.quantization_config = _fake_quant_config("modelopt_mixed")
with pytest.raises(ValueError, match="serialized ModelOpt FP8 or NVFP4"):
resolve_mixed_precision_config(od_config)
def test_additional_config_rejects_missing_quantization_config() -> None:
od_config = SimpleNamespace(additional_config={"cosmos3_mixed_precision": {}})
with pytest.raises(ValueError, match="serialized ModelOpt FP8 or NVFP4"):
resolve_mixed_precision_config(od_config)
@pytest.mark.parametrize("policy", [_policy(), True])
def test_additional_config_disable_bypasses_incompatible_checkpoint(policy: object) -> None:
od_config = _checkpoint_od_config(
_fake_quant_config("modelopt_mixed"),
policy=policy,
additional_config={"cosmos3_mixed_precision": {"enabled": False}},
)
od_config.quantization_config = _fake_quant_config("modelopt_mixed")
assert resolve_mixed_precision_config(od_config) == (None, "additional_config_disabled")
def test_runtime_allows_standard_offload_and_rejects_distributed(monkeypatch) -> None:
from vllm_omni.diffusion.models.cosmos3 import transformer_cosmos3
monkeypatch.setattr(
transformer_cosmos3,
"get_tensor_model_parallel_world_size",
lambda: 1,
)
od_config = SimpleNamespace(
enable_cpu_offload=True,
enable_layerwise_offload=True,
enable_distributed_layerwise_offload=False,
parallel_config=SimpleNamespace(use_hsdp=False),
)
transformer_cosmos3._validate_mixed_precision_runtime(
Cosmos3MixedPrecisionConfig(),
od_config,
)
od_config.enable_distributed_layerwise_offload = True
with pytest.raises(ValueError, match="distributed layer-wise offload"):
transformer_cosmos3._validate_mixed_precision_runtime(
Cosmos3MixedPrecisionConfig(),
od_config,
)
od_config.enable_distributed_layerwise_offload = False
od_config.max_num_seqs = 2
with pytest.raises(ValueError, match="one active request"):
transformer_cosmos3._validate_mixed_precision_runtime(
Cosmos3MixedPrecisionConfig(),
od_config,
)
class _Layer(torch.nn.Module):
def __init__(self, output_size: int, input_size: int) -> None:
super().__init__()
self.output_size_per_partition = output_size
self.input_size_per_partition = input_size
class _BaseMethod:
def __init__(self, *, nvfp4: bool = False) -> None:
self.processed = False
self.apply_calls = 0
self.fp8_linear = object()
if nvfp4:
from vllm.model_executor.kernels.linear.nvfp4.cutlass import (
CutlassNvFp4LinearKernel,
)
self.kernel = object.__new__(CutlassNvFp4LinearKernel)
else:
self.kernel = None
def create_weights(self, *args, **kwargs) -> None:
pass
def process_weights_after_loading(self, layer) -> None:
self.processed = True
if layer.weight.dtype == torch.float8_e4m3fn:
layer.weight = layer.weight.t().contiguous()
layer.weight_scale = layer.weight_scale.max().reshape(1)
elif layer.weight.dtype == torch.uint8:
layer.weight_scale = _swizzle_blockscale_cpu(layer.weight_scale)
layer.weight_global_scale = layer.weight_scale_2.max().float().reshape(1)
del layer.weight_scale_2
def apply(self, layer, x, bias=None):
del bias
self.apply_calls += 1
return torch.full(
(*x.shape[:-1], layer.output_size_per_partition),
17,
dtype=x.dtype,
device=x.device,
)
def _fp8_layer(output_size: int = 2, input_size: int = 4) -> _Layer:
layer = _Layer(output_size, input_size)
layer.weight = torch.ones(output_size, input_size, dtype=torch.float8_e4m3fn)
layer.weight_scale = torch.tensor([0.5], dtype=torch.float32)
return layer
def _nvfp4_layer(output_size: int = 128, input_size: int = 64) -> _Layer:
layer = _Layer(output_size, input_size)
layer.weight = torch.full((output_size, input_size // 2), 0x22, dtype=torch.uint8)
layer.weight_scale = torch.ones(output_size, input_size // 16, dtype=torch.float8_e4m3fn)
layer.weight_scale_2 = torch.ones(1)
return layer
def _runtime_and_method(
strategy,
layer: _Layer,
*,
path: str = "generation",
reasoner: str = "native",
):
config = Cosmos3MixedPrecisionConfig(
first_steps=1,
last_steps=1,
reasoner=reasoner,
)
runtime = Cosmos3MixedPrecisionRuntime(config)
base = _BaseMethod(nvfp4=isinstance(strategy, Nvfp4W4A4W4A16Strategy))
method = Cosmos3MixedPrecisionLinearMethod(
base,
strategy,
runtime,
f"{path}.linear",
path,
)
method.process_weights_after_loading(layer)
return runtime, base, method
@pytest.mark.parametrize(
("strategy", "layer"),
[
(Fp8W8A8W8A16Strategy(), _fp8_layer()),
(Nvfp4W4A4W4A16Strategy(), _nvfp4_layer()),
],
)
def test_generation_dispatches_native_middle_and_a16_edges(strategy, layer) -> None:
runtime, base, method = _runtime_and_method(strategy, layer)
x = torch.ones(1, layer.input_size_per_partition, dtype=torch.bfloat16)
runtime.set_step(1, 3)
assert torch.equal(
method.apply(layer, x),
torch.full((1, layer.output_size_per_partition), 17, dtype=x.dtype),
)
runtime.set_step(0, 3)
assert torch.equal(
method.apply(layer, x),
torch.nn.functional.linear(x, strategy.materialize(layer)),
)
assert base.apply_calls == 1
@pytest.mark.parametrize(
("strategy", "layer"),
[
(Fp8W8A8W8A16Strategy(), _fp8_layer()),
(Nvfp4W4A4W4A16Strategy(), _nvfp4_layer()),
],
)
def test_a16_uses_only_live_native_weights(strategy, layer) -> None:
runtime, base, method = _runtime_and_method(strategy, layer)
assert base.processed
assert not hasattr(layer, "_cosmos3_precision_weight")
assert not hasattr(layer, "_cosmos3_precision_weight_scale")
runtime.set_step(0, 3)
output = method.apply(
layer,
torch.ones(1, layer.input_size_per_partition, dtype=torch.bfloat16),
)
assert output.shape == (1, layer.output_size_per_partition)
def test_a16_follows_live_weight_storage_after_offload_rebinding() -> None:
layer = _fp8_layer()
strategy = Fp8W8A8W8A16Strategy()
runtime, _, method = _runtime_and_method(strategy, layer)
runtime.set_step(0, 3)
x = torch.ones(1, 4, dtype=torch.bfloat16)
before = method.apply(layer, x)
layer.weight = torch.zeros_like(layer.weight)
after = method.apply(layer, x)
assert not torch.equal(before, after)
assert torch.count_nonzero(after) == 0
def test_fp8_rejects_smoothquant() -> None:
layer = _fp8_layer()
layer.pre_quant_scale = torch.ones(1)
with pytest.raises(ValueError, match="SmoothQuant"):
Fp8W8A8W8A16Strategy().validate_before_processing(
_BaseMethod(),
layer,
"gen.linear",
)
def test_fp8_rejects_non_tensorwise_scales() -> None:
layer = _fp8_layer(output_size=3, input_size=2)
layer.weight_scale = torch.tensor([[1.0], [2.0], [3.0]])
with pytest.raises(ValueError, match="tensorwise FP8"):
Fp8W8A8W8A16Strategy().validate_before_processing(
_BaseMethod(),
layer,
"gen.linear",
)
def test_nvfp4_reference_materializes_live_cutlass_weights() -> None:
layer = _nvfp4_layer()
strategy = Nvfp4W4A4W4A16Strategy()
_runtime_and_method(strategy, layer)
output = strategy.materialize(layer)
assert output.shape == (128, 64)
assert torch.equal(output, torch.ones_like(output))
def test_nvfp4_rejects_fused_global_scales() -> None:
layer = _nvfp4_layer()
layer.weight_scale_2 = torch.tensor([1.0, 2.0])
strategy = Nvfp4W4A4W4A16Strategy()
with pytest.raises(ValueError, match="NVFP4 scales"):
strategy.validate_before_processing(
_BaseMethod(nvfp4=True),
layer,
"gen.qkv",
)
@pytest.mark.parametrize(
("policy", "uses_native"),
[("a16", False), ("native", True)],
)
def test_reasoner_policy_is_independent_of_generation_step(
policy: str,
uses_native: bool,
) -> None:
layer = _fp8_layer()
runtime, base, method = _runtime_and_method(
Fp8W8A8W8A16Strategy(),
layer,
path="reasoner",
reasoner=policy,
)
runtime.set_step(1, 3)
method.apply(layer, torch.ones(1, 4, dtype=torch.bfloat16))
assert (base.apply_calls == 1) is uses_native
def test_reset_clears_generation_state() -> None:
runtime = Cosmos3MixedPrecisionRuntime(Cosmos3MixedPrecisionConfig(first_steps=1, last_steps=1))
runtime.set_step(0, 5)
assert runtime.use_high_precision("generation")
runtime.reset()
assert not runtime.use_high_precision("generation")
def test_install_discovers_generation_and_opt_in_reasoner(monkeypatch) -> None:
class _FakeLinear(torch.nn.Module):
def __init__(self, prefix: str) -> None:
super().__init__()
self.prefix = prefix
self.input_size_per_partition = 4
self.output_size_per_partition = 2
self.quant_method = SimpleNamespace(name="fp8")
monkeypatch.setattr(runtime_impl, "LinearBase", _FakeLinear)
strategy = Fp8W8A8W8A16Strategy()
monkeypatch.setattr(strategy, "accepts", lambda method: getattr(method, "name", None) == "fp8")
monkeypatch.setattr(runtime_impl, "_STRATEGIES", (strategy,))
runtime = Cosmos3MixedPrecisionRuntime(Cosmos3MixedPrecisionConfig(reasoner="a16"))
reasoner = _FakeLinear("reasoner.q_proj")
generation = [
_FakeLinear("generation.q_proj"),
_FakeLinear("generation.out_proj"),
]
transformer = SimpleNamespace(
language_model=SimpleNamespace(layers=torch.nn.Sequential(reasoner)),
gen_layers=torch.nn.Sequential(*generation),
)
runtime.install(transformer)
assert isinstance(reasoner.quant_method, Cosmos3MixedPrecisionLinearMethod)
assert all(isinstance(layer.quant_method, Cosmos3MixedPrecisionLinearMethod) for layer in generation)
def test_pipeline_helpers_forward_and_reset_schedule() -> None:
from vllm_omni.diffusion.models.cosmos3.pipeline_cosmos3 import (
Cosmos3OmniDiffusersPipeline,
)
calls = []
pipeline = object.__new__(Cosmos3OmniDiffusersPipeline)
pipeline.transformer = SimpleNamespace(
set_mixed_precision_step=lambda step, count: calls.append((step, count)),
reset_mixed_precision=lambda: calls.append("reset"),
)
pipeline._set_mixed_precision_step(2, 7)
pipeline._reset_mixed_precision()
assert calls == [(2, 7), "reset"]
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Scheduled A16 execution for quantized Cosmos3 checkpoints."""
from .checkpoint import resolve_mixed_precision_config
from .config import Cosmos3MixedPrecisionConfig
from .runtime import Cosmos3MixedPrecisionRuntime
__all__ = [
"Cosmos3MixedPrecisionConfig",
"Cosmos3MixedPrecisionRuntime",
"resolve_mixed_precision_config",
]
@@ -0,0 +1,176 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Checkpoint discovery for the Cosmos3 diffusion-step precision policy."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Literal, cast
from .config import Cosmos3MixedPrecisionConfig, ReasonerPolicy, _non_negative_int
PolicySource = Literal[
"none",
"checkpoint",
"additional_config",
"additional_config_disabled",
]
_COMPONENT = "transformer"
_POLICY_FIELDS = frozenset(
{
"schema_version",
"type",
"index_space",
"scope",
"default_mode",
"first_steps",
"last_steps",
"overlap",
"reasoner",
}
)
_STEP_RANGE_FIELDS = frozenset({"count", "mode"})
_SUPPORTED_MODEL_OPT_CONFIGS = frozenset(
{
"modelopt",
"modelopt_fp4",
}
)
def resolve_mixed_precision_config(
od_config: object,
) -> tuple[Cosmos3MixedPrecisionConfig | None, PolicySource]:
"""Resolve an explicit runtime override before the checkpoint default."""
override_present, override = Cosmos3MixedPrecisionConfig.resolve_additional_config(
getattr(od_config, "additional_config", None)
)
if override_present:
if override is not None:
_validate_checkpoint_quantization(od_config)
source: PolicySource = "additional_config" if override is not None else "additional_config_disabled"
return override, source
checkpoint = read_checkpoint_policy(od_config)
if checkpoint is not None:
return checkpoint, "checkpoint"
return None, "none"
def read_checkpoint_policy(od_config: object) -> Cosmos3MixedPrecisionConfig | None:
"""Read and validate a policy from ``transformer/config.json``.
Missing metadata preserves ordinary checkpoint behavior. Metadata that is
present but malformed or incompatible fails closed.
"""
tf_config = getattr(od_config, "tf_model_config", None)
params = getattr(tf_config, "params", None)
if not isinstance(params, Mapping):
return None
disk_quant_config = params.get("quantization_config")
if not isinstance(disk_quant_config, Mapping):
return None
if "runtime" not in disk_quant_config:
return None
runtime_config = disk_quant_config["runtime"]
if not isinstance(runtime_config, Mapping):
raise TypeError("quantization_config.runtime must be a mapping")
if "diffusion_step_policy" not in runtime_config:
return None
raw_policy = runtime_config["diffusion_step_policy"]
if not isinstance(raw_policy, Mapping):
raise TypeError("quantization_config.runtime.diffusion_step_policy must be a mapping")
policy = _parse_policy(raw_policy)
if policy is None:
return None
_validate_checkpoint_quantization(od_config)
return policy
def _parse_policy(policy: Mapping[str, object]) -> Cosmos3MixedPrecisionConfig | None:
fields = set(policy)
unknown = fields - _POLICY_FIELDS
if unknown:
raise ValueError(f"Unknown diffusion_step_policy fields: {sorted(unknown)}")
missing = _POLICY_FIELDS - fields
if missing:
raise ValueError(f"Missing diffusion_step_policy fields: {sorted(missing)}")
schema_version = policy["schema_version"]
if not isinstance(schema_version, int) or isinstance(schema_version, bool) or schema_version != 1:
raise ValueError("diffusion_step_policy.schema_version must be the integer 1")
if policy["type"] != "first_last_n":
raise ValueError("diffusion_step_policy.type must be 'first_last_n'")
if policy["index_space"] != "denoising_loop_iteration":
raise ValueError("diffusion_step_policy.index_space must be 'denoising_loop_iteration'")
if policy["default_mode"] != "native":
raise ValueError("diffusion_step_policy.default_mode must be 'native'")
if policy["overlap"] != "a16":
raise ValueError("diffusion_step_policy.overlap must be 'a16'")
scope = policy["scope"]
if not isinstance(scope, list) or not scope or not all(isinstance(item, str) for item in scope):
raise TypeError("diffusion_step_policy.scope must be a non-empty list of strings")
first_steps = _parse_step_range(policy["first_steps"], "first_steps")
last_steps = _parse_step_range(policy["last_steps"], "last_steps")
reasoner = policy["reasoner"]
if reasoner not in {"native", "a16"}:
raise ValueError("diffusion_step_policy.reasoner must be 'native' or 'a16'")
if _COMPONENT not in scope:
return None
return Cosmos3MixedPrecisionConfig(
first_steps=first_steps,
last_steps=last_steps,
reasoner=cast(ReasonerPolicy, reasoner),
)
def _parse_step_range(value: object, name: str) -> int:
if not isinstance(value, Mapping):
raise TypeError(f"diffusion_step_policy.{name} must be a mapping")
fields = set(value)
unknown = fields - _STEP_RANGE_FIELDS
if unknown:
raise ValueError(f"Unknown diffusion_step_policy.{name} fields: {sorted(unknown)}")
missing = _STEP_RANGE_FIELDS - fields
if missing:
raise ValueError(f"Missing diffusion_step_policy.{name} fields: {sorted(missing)}")
if value["mode"] != "a16":
raise ValueError(f"diffusion_step_policy.{name}.mode must be 'a16'")
return _non_negative_int(value["count"], f"diffusion_step_policy.{name}.count")
def _validate_checkpoint_quantization(od_config: object) -> None:
# Match the effective quantization used to construct the transformer linears.
quant_config = getattr(od_config, "quantization_config", None)
if quant_config is None:
tf_config = getattr(od_config, "tf_model_config", None)
quant_config = getattr(tf_config, "quant_config", None)
get_name = getattr(quant_config, "get_name", None)
name = get_name() if callable(get_name) else None
if name not in _SUPPORTED_MODEL_OPT_CONFIGS:
raise ValueError(f"diffusion_step_policy requires a serialized ModelOpt FP8 or NVFP4 checkpoint, got {name!r}")
if name == "modelopt":
_require_serialized(quant_config, "is_checkpoint_fp8_serialized", "FP8")
return
if name == "modelopt_fp4":
if getattr(quant_config, "quant_method", "NVFP4") != "NVFP4":
raise ValueError("diffusion_step_policy requires checkpoint-native NVFP4 W4A4 linears")
_require_serialized(quant_config, "is_checkpoint_nvfp4_serialized", "NVFP4")
return
def _require_serialized(quant_config: object | None, flag: str, format_name: str) -> None:
if not bool(getattr(quant_config, flag, False)):
raise ValueError(f"diffusion_step_policy requires serialized ModelOpt {format_name} weights")
@@ -0,0 +1,106 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Configuration parsing and denoising-step policy for mixed precision."""
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import dataclass
from typing import Literal, cast
ReasonerPolicy = Literal["native", "a16"]
_REASONER_POLICIES = frozenset({"native", "a16"})
_CONFIG_FIELDS = frozenset({"enabled", "first_steps", "last_steps", "reasoner"})
@dataclass(frozen=True)
class Cosmos3MixedPrecisionConfig:
"""Validated precision policy shared by every quantization strategy."""
first_steps: int = 3
last_steps: int = 3
reasoner: ReasonerPolicy = "a16"
@classmethod
def from_additional_config(
cls,
additional_config: Mapping[str, object] | None,
) -> Cosmos3MixedPrecisionConfig | None:
"""Parse Cosmos3 fields from vLLM-Omni's additional configuration."""
_, config = cls.resolve_additional_config(additional_config)
return config
@classmethod
def resolve_additional_config(
cls,
additional_config: Mapping[str, object] | None,
) -> tuple[bool, Cosmos3MixedPrecisionConfig | None]:
"""Return whether an override was supplied and its effective policy.
The separate presence bit distinguishes an absent runtime override from
an explicit disable. That distinction matters when a checkpoint owns a
default policy.
"""
if additional_config is not None and not isinstance(additional_config, Mapping):
raise TypeError("additional_config must be a mapping")
values = additional_config or {}
if "cosmos3_mixed_precision" not in values:
return False, None
raw_config = values["cosmos3_mixed_precision"]
if not isinstance(raw_config, Mapping):
raise TypeError("cosmos3_mixed_precision must be a mapping")
unknown = set(raw_config) - _CONFIG_FIELDS
if unknown:
raise ValueError(f"Unknown cosmos3_mixed_precision fields: {sorted(unknown)}")
enabled = raw_config.get("enabled", True)
if not isinstance(enabled, bool):
raise TypeError("cosmos3_mixed_precision.enabled must be a boolean")
if not enabled:
conflicting = set(raw_config) - {"enabled"}
if conflicting:
raise ValueError(
"cosmos3_mixed_precision.enabled=false cannot be combined with "
f"schedule fields: {sorted(conflicting)}"
)
return True, None
first_steps = _non_negative_int(
raw_config.get("first_steps", 3),
"cosmos3_mixed_precision.first_steps",
)
last_steps = _non_negative_int(
raw_config.get("last_steps", 3),
"cosmos3_mixed_precision.last_steps",
)
reasoner = str(raw_config.get("reasoner", "a16")).lower()
if reasoner not in _REASONER_POLICIES:
raise ValueError(
f"cosmos3_mixed_precision.reasoner must be one of {sorted(_REASONER_POLICIES)}, got {reasoner!r}"
)
config = cls(
first_steps=first_steps,
last_steps=last_steps,
reasoner=cast(ReasonerPolicy, reasoner),
)
if first_steps == 0 and last_steps == 0 and reasoner == "native":
return True, None
return True, config
def use_high_precision(self, step_index: int, num_steps: int) -> bool:
"""Select the high path for an actual scheduler-step index."""
if num_steps <= 0:
raise ValueError(f"num_steps must be positive, got {num_steps}")
if step_index < 0 or step_index >= num_steps:
raise IndexError(f"step_index must be in [0, {num_steps}), got {step_index}")
return step_index < self.first_steps or step_index >= num_steps - self.last_steps
def _non_negative_int(value: object, name: str) -> int:
"""Validate an integer configuration field without accepting booleans."""
if not isinstance(value, int) or isinstance(value, bool) or value < 0:
raise TypeError(f"{name} must be a non-negative integer")
return value
@@ -0,0 +1,116 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Format-agnostic schedule state, linear discovery, and dispatch."""
from __future__ import annotations
from typing import Literal
import torch
from vllm.model_executor.layers.linear import LinearBase, LinearMethodBase
from .config import Cosmos3MixedPrecisionConfig
from .strategy import (
Cosmos3PrecisionStrategy,
Fp8W8A8W8A16Strategy,
Nvfp4W4A4W4A16Strategy,
)
PrecisionPath = Literal["reasoner", "generation"]
_STRATEGIES: tuple[Cosmos3PrecisionStrategy, ...] = (
Fp8W8A8W8A16Strategy(),
Nvfp4W4A4W4A16Strategy(),
)
def _strategy_for(method: object | None) -> Cosmos3PrecisionStrategy | None:
return next((strategy for strategy in _STRATEGIES if strategy.accepts(method)), None)
class Cosmos3MixedPrecisionLinearMethod(LinearMethodBase):
"""Dispatch between a checkpoint-native method and dense A16."""
def __init__(
self,
base_method: LinearMethodBase,
strategy: Cosmos3PrecisionStrategy,
runtime: Cosmos3MixedPrecisionRuntime,
module_name: str,
path: PrecisionPath,
) -> None:
self.base_method = base_method
self.strategy = strategy
self.runtime = runtime
self.module_name = module_name
self.path = path
def create_weights(self, *args, **kwargs) -> None:
self.base_method.create_weights(*args, **kwargs)
def process_weights_after_loading(self, layer: torch.nn.Module) -> None:
self.strategy.validate_before_processing(
self.base_method,
layer,
self.module_name,
)
self.base_method.process_weights_after_loading(layer)
self.strategy.validate_after_processing(layer, self.module_name)
def apply(
self,
layer: torch.nn.Module,
x: torch.Tensor,
bias: torch.Tensor | None = None,
) -> torch.Tensor:
if not self.runtime.use_high_precision(self.path):
return self.base_method.apply(layer, x, bias)
return self.strategy.apply_high(layer, x, bias)
class Cosmos3MixedPrecisionRuntime:
"""Own one transformer's schedule state and wrapped linear inventory."""
def __init__(self, config: Cosmos3MixedPrecisionConfig) -> None:
self.config = config
# TODO: Make this request-local before Cosmos3 supports interleaved
# denoising requests on one transformer instance.
self._generation_high_precision = False
def install(self, transformer: torch.nn.Module) -> None:
components: dict[PrecisionPath, torch.nn.Module] = {
"generation": transformer.gen_layers,
}
if self.config.reasoner == "a16":
components["reasoner"] = transformer.language_model.layers
wrapped_count = 0
for path, component in components.items():
for local_name, layer in component.named_modules():
if not isinstance(layer, LinearBase):
continue
base_method = getattr(layer, "quant_method", None)
strategy = _strategy_for(base_method)
if strategy is None:
continue
module_name = getattr(layer, "prefix", None) or f"{path}.{local_name}"
layer.quant_method = Cosmos3MixedPrecisionLinearMethod(
base_method,
strategy,
self,
module_name,
path,
)
wrapped_count += 1
if not wrapped_count:
raise ValueError("Cosmos3 mixed precision found no compatible FP8 or NVFP4 ModelOpt linears")
def use_high_precision(self, path: PrecisionPath) -> bool:
return self.config.reasoner == "a16" if path == "reasoner" else self._generation_high_precision
def set_step(self, step_index: int, num_steps: int) -> None:
self._generation_high_precision = self.config.use_high_precision(step_index, num_steps)
def reset(self) -> None:
self._generation_high_precision = False
@@ -0,0 +1,218 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Format-specific live-weight validation and reference A16 materialization."""
from __future__ import annotations
import torch
import torch.nn.functional as F
from vllm.model_executor.layers.quantization.modelopt import (
ModelOptFp8LinearMethod,
ModelOptNvFp4LinearMethod,
)
from vllm.model_executor.layers.quantization.utils import nvfp4_emulation_utils
_NVFP4_BLOCK_SIZE = 16
class Cosmos3PrecisionStrategy:
"""Quantization-format boundary behind the shared precision schedule."""
def accepts(self, method: object | None) -> bool:
"""Return whether this strategy owns a native linear method."""
raise NotImplementedError
def validate_before_processing(
self,
method: object,
layer: torch.nn.Module,
module_name: str,
) -> None:
"""Reject native transforms that cannot support live dequantization."""
def validate_after_processing(
self,
layer: torch.nn.Module,
module_name: str,
) -> None:
"""Validate the live native weight representation."""
raise NotImplementedError
def materialize(self, layer: torch.nn.Module) -> torch.Tensor:
"""Materialize the live quantized weight as a dense BF16 matrix."""
raise NotImplementedError
def apply_high(
self,
layer: torch.nn.Module,
x: torch.Tensor,
bias: torch.Tensor | None,
) -> torch.Tensor:
"""Apply the reference dense A16 path."""
input_size = int(layer.input_size_per_partition)
output_size = int(layer.output_size_per_partition)
weight = self.materialize(layer)
expected_shape = (output_size, input_size)
if tuple(weight.shape) != expected_shape:
raise RuntimeError(f"Dense weight shape {tuple(weight.shape)} does not match {expected_shape}")
x_2d = x.reshape(-1, x.shape[-1])
if x_2d.shape[1] != input_size:
raise ValueError(f"Expected activation width {input_size}, got {x_2d.shape[1]}")
weight = weight.to(dtype=x.dtype)
if bias is not None and bias.dtype != x.dtype:
bias = bias.to(dtype=x.dtype)
output = F.linear(x_2d, weight, bias)
return output.view(*x.shape[:-1], output_size)
class Fp8W8A8W8A16Strategy(Cosmos3PrecisionStrategy):
"""Use native ModelOpt W8A8 or reference dense W8A16."""
def accepts(self, method: object | None) -> bool:
return isinstance(method, ModelOptFp8LinearMethod)
def validate_before_processing(
self,
method: object,
layer: torch.nn.Module,
module_name: str,
) -> None:
if hasattr(layer, "pre_quant_scale"):
raise ValueError(f"{module_name} uses unsupported SmoothQuant pre_quant_scale")
weight_scale = getattr(layer, "weight_scale", None)
if not isinstance(weight_scale, torch.Tensor) or weight_scale.numel() != 1:
raise ValueError(f"{module_name} requires serialized tensorwise FP8 weights")
fp8_kernel = getattr(method, "fp8_linear", None)
from vllm.model_executor.kernels.linear.scaled_mm.marlin import (
MarlinFP8ScaledMMLinearKernel,
)
if isinstance(fp8_kernel, MarlinFP8ScaledMMLinearKernel):
raise ValueError(
f"{module_name} selected Marlin FP8, which repacks the only weight copy; "
"use a backend that retains canonical FP8 weights"
)
def validate_after_processing(
self,
layer: torch.nn.Module,
module_name: str,
) -> None:
weight = getattr(layer, "weight", None)
scale = getattr(layer, "weight_scale", None)
if not isinstance(weight, torch.Tensor) or weight.dtype != torch.float8_e4m3fn:
dtype = getattr(weight, "dtype", None)
raise TypeError(f"{module_name} requires a canonical FP8 weight, got {dtype}")
if weight.ndim != 2:
raise ValueError(f"{module_name} requires a rank-2 FP8 weight, got {tuple(weight.shape)}")
if not isinstance(scale, torch.Tensor):
raise ValueError(f"{module_name} has an FP8 weight but no weight_scale")
if scale.numel() != 1:
raise ValueError(f"{module_name} requires one live FP8 weight scale")
input_size = int(layer.input_size_per_partition)
output_size = int(layer.output_size_per_partition)
if weight.shape[0] < input_size or weight.shape[1] < output_size:
raise ValueError(
f"{module_name} live FP8 weight shape {tuple(weight.shape)} does not cover "
f"(K, N)=({input_size}, {output_size})"
)
_validate_positive_finite_scale(scale, module_name)
def materialize(self, layer: torch.nn.Module) -> torch.Tensor:
input_size = int(layer.input_size_per_partition)
output_size = int(layer.output_size_per_partition)
weight = layer.weight[:input_size, :output_size]
scale = layer.weight_scale.reshape(1).to(device=weight.device, dtype=torch.float32)
return (weight.to(torch.float32) * scale).t().to(torch.bfloat16)
class Nvfp4W4A4W4A16Strategy(Cosmos3PrecisionStrategy):
"""Use native ModelOpt W4A4 or reference dense W4A16."""
def accepts(self, method: object | None) -> bool:
return isinstance(method, ModelOptNvFp4LinearMethod)
def validate_before_processing(
self,
method: object,
layer: torch.nn.Module,
module_name: str,
) -> None:
kernel = getattr(method, "kernel", None)
from vllm.model_executor.kernels.linear.nvfp4.cutlass import (
CutlassNvFp4LinearKernel,
)
from vllm.model_executor.kernels.linear.nvfp4.flashinfer import (
FlashInferCuteDslNvFp4LinearKernel,
FlashInferCutlassNvFp4LinearKernel,
)
compatible_kernels = (
CutlassNvFp4LinearKernel,
FlashInferCuteDslNvFp4LinearKernel,
FlashInferCutlassNvFp4LinearKernel,
)
if not isinstance(kernel, compatible_kernels):
kernel_name = type(kernel).__name__ if kernel is not None else "none"
raise ValueError(
f"{module_name} selected unsupported NVFP4 backend {kernel_name}; "
"live W4A16 dequantization requires a CUTLASS-compatible layout"
)
global_scale = _nvfp4_global_scale(layer)
if global_scale is None or global_scale.numel() != 1:
raise ValueError(f"{module_name} is missing ModelOpt NVFP4 scales")
def validate_after_processing(
self,
layer: torch.nn.Module,
module_name: str,
) -> None:
packed = getattr(layer, "weight", None)
scale = getattr(layer, "weight_scale", None)
global_scale = getattr(layer, "weight_global_scale", None)
if not isinstance(packed, torch.Tensor) or packed.dtype != torch.uint8:
dtype = getattr(packed, "dtype", None)
raise TypeError(f"{module_name} requires a live packed NVFP4 weight, got {dtype}")
if not isinstance(scale, torch.Tensor) or not isinstance(global_scale, torch.Tensor):
raise ValueError(f"{module_name} is missing live NVFP4 scales")
output_size = int(layer.output_size_per_partition)
input_size = int(layer.input_size_per_partition)
if input_size % _NVFP4_BLOCK_SIZE != 0:
raise ValueError(f"{module_name} input size {input_size} is not divisible by {_NVFP4_BLOCK_SIZE}")
expected_weight = (output_size, input_size // 2)
if packed.shape[0] < expected_weight[0] or packed.shape[1] < expected_weight[1]:
raise ValueError(
f"{module_name} live NVFP4 weight shape {tuple(packed.shape)} does not cover {expected_weight}"
)
_validate_positive_finite_scale(global_scale, module_name)
lut_handle = nvfp4_emulation_utils.kE2M1ToFloat_handle
if lut_handle.val.device != packed.device:
lut_handle.val = lut_handle.val.to(packed.device)
def materialize(self, layer: torch.nn.Module) -> torch.Tensor:
output_size = int(layer.output_size_per_partition)
input_size = int(layer.input_size_per_partition)
packed = layer.weight[:output_size, : input_size // 2]
return nvfp4_emulation_utils.dequantize_to_dtype(
packed,
layer.weight_scale,
layer.weight_global_scale,
torch.bfloat16,
_NVFP4_BLOCK_SIZE,
True,
)
def _validate_positive_finite_scale(scale: torch.Tensor, module_name: str) -> None:
values = scale.detach().float()
if not torch.isfinite(values).all() or not (values > 0).all():
raise ValueError(f"{module_name} has a non-finite or non-positive weight scale")
def _nvfp4_global_scale(layer: torch.nn.Module) -> torch.Tensor | None:
for name in ("weight_scale_2", "weight_global_scale"):
value = getattr(layer, name, None)
if isinstance(value, torch.Tensor):
return value
return None
@@ -1822,6 +1822,16 @@ class Cosmos3OmniDiffusersPipeline(
def num_timesteps(self):
return self._num_timesteps
def _set_mixed_precision_step(self, step_index: int, num_steps: int) -> None:
setter = getattr(self.transformer, "set_mixed_precision_step", None)
if setter is not None:
setter(step_index, num_steps)
def _reset_mixed_precision(self) -> None:
resetter = getattr(self.transformer, "reset_mixed_precision", None)
if resetter is not None:
resetter()
@staticmethod
def _distilled_unsupported_error(detail: str) -> ValueError:
return ValueError(
@@ -2819,7 +2829,8 @@ class Cosmos3OmniDiffusersPipeline(
# Each CFG-parallel rank runs exactly one branch (rank 0 -> cond,
# else uncond), so session keying loads/stores only this rank's branch.
cfg_rank_is_negative = get_classifier_free_guidance_rank() != 0
for t in self.progress_bar(timesteps):
for step_index, t in enumerate(self.progress_bar(timesteps)):
self._set_mixed_precision_step(step_index, len(timesteps))
timestep = t.unsqueeze(0)
# Outside the interval, scale=1 makes the combined output equal
# the cond branch. Every rank remains on the same iteration and
@@ -2858,7 +2869,8 @@ class Cosmos3OmniDiffusersPipeline(
uncond_cache: tuple = (None, None)
keep_uncond_for_cache = self._cache_requires_paired_cfg()
for t in self.progress_bar(timesteps):
for step_index, t in enumerate(self.progress_bar(timesteps)):
self._set_mixed_precision_step(step_index, len(timesteps))
timestep = t.unsqueeze(0)
cfg_active = _cfg_active_at(t)
@@ -2912,7 +2924,8 @@ class Cosmos3OmniDiffusersPipeline(
else:
# No CFG: a single cond branch per step. Bespoke (state None) keeps
# using the transformer-instance cache exactly as before.
for t in self.progress_bar(timesteps):
for step_index, t in enumerate(self.progress_bar(timesteps)):
self._set_mixed_precision_step(step_index, len(timesteps))
timestep = t.unsqueeze(0)
self._kv_load_und(kv_state, is_negative=False)
noise_pred = self.transformer(
@@ -2928,6 +2941,7 @@ class Cosmos3OmniDiffusersPipeline(
self._kv_capture_und(kv_state, is_negative=False)
_assign_step_out(_step(noise_pred, t, latents, action_latents, sound_latents))
finally:
self._reset_mixed_precision()
# Cosmos3 currently receives a unique request_id rather than a
# reusable rollout session id. Retaining its state would only pin
# K/V buffers on device after this generation finishes.
@@ -3112,7 +3126,8 @@ class Cosmos3OmniDiffusersPipeline(
self.transformer.reset_cache()
self._cosmos3_branch_caches = {}
try:
for t in self.progress_bar(timesteps):
for step_index, t in enumerate(self.progress_bar(timesteps)):
self._set_mixed_precision_step(step_index, len(timesteps))
timestep = t.unsqueeze(0)
step_guidance = guidance_scale if _active_at(t, guidance_interval) else 1.0
step_control = control_guidance if _active_at(t, control_guidance_interval) else 1.0
@@ -3224,6 +3239,7 @@ class Cosmos3OmniDiffusersPipeline(
)[0]
latents = velocity_mask * latents + (1.0 - velocity_mask) * condition_latents
finally:
self._reset_mixed_precision()
self._cosmos3_branch_caches = None
self.transformer.reset_cache()
return latents
@@ -40,6 +40,12 @@ from vllm_omni.diffusion.forward_context import get_forward_context, is_forward_
from vllm_omni.diffusion.layers.norm import RMSNorm as _VllmRMSNorm
from vllm_omni.platforms import current_omni_platform
from .mixed_precision import (
Cosmos3MixedPrecisionConfig,
Cosmos3MixedPrecisionRuntime,
resolve_mixed_precision_config,
)
if TYPE_CHECKING:
from vllm_omni.diffusion.offloader.sequential_backend import SequentialOffloadHook
@@ -136,6 +142,26 @@ def _od_config_get(od_config: Any, key: str, default: Any = None) -> Any:
return default if value is None else value
def _validate_mixed_precision_runtime(
config: Cosmos3MixedPrecisionConfig | None,
od_config: OmniDiffusionConfig,
) -> None:
if config is None:
return
if get_tensor_model_parallel_world_size() != 1:
raise ValueError("Cosmos3 mixed precision currently supports tensor parallel size 1 only")
if int(getattr(od_config, "max_num_seqs", 1)) != 1:
raise ValueError("Cosmos3 mixed precision currently supports one active request per worker")
if bool(getattr(od_config, "enable_distributed_layerwise_offload", False)):
raise ValueError(
"Cosmos3 mixed precision does not support distributed layer-wise offload "
"because its direct loader bypasses ModelOpt post-load transformations"
)
parallel_config = getattr(od_config, "parallel_config", None)
if bool(getattr(parallel_config, "use_hsdp", False)):
raise ValueError("Cosmos3 mixed precision has not validated live backend weights under HSDP")
def _as_bool(value: Any) -> bool:
if isinstance(value, str):
return value.strip().lower() in {"1", "true", "yes", "on"}
@@ -1241,6 +1267,19 @@ class Cosmos3VFMTransformer(nn.Module):
dtype = od_config.dtype
quant_config = getattr(od_config, "quantization_config", None) if od_config else None
mixed_precision_config, mixed_precision_source = resolve_mixed_precision_config(od_config)
if mixed_precision_config is None:
if mixed_precision_source == "additional_config_disabled":
logger.info("Cosmos3 checkpoint mixed-precision policy disabled by additional_config")
else:
logger.info(
"Cosmos3 mixed precision active (source=%s): first_steps=%d last_steps=%d reasoner=%s",
mixed_precision_source,
mixed_precision_config.first_steps,
mixed_precision_config.last_steps,
mixed_precision_config.reasoner,
)
_validate_mixed_precision_runtime(mixed_precision_config, od_config)
self.language_model = self._language_model_cls(
hidden_size=self.hidden_size,
@@ -1300,6 +1339,11 @@ class Cosmos3VFMTransformer(nn.Module):
]
)
self.mixed_precision_runtime: Cosmos3MixedPrecisionRuntime | None = None
if mixed_precision_config is not None:
self.mixed_precision_runtime = Cosmos3MixedPrecisionRuntime(mixed_precision_config)
self.mixed_precision_runtime.install(self)
self.norm_moe_gen = RMSNorm(self.hidden_size, eps=self.rms_norm_eps)
self.gen_sp_prepare = Cosmos3GenSPPrepare()
self.gen_sp_gather = nn.Identity()
@@ -1958,3 +2002,11 @@ class Cosmos3VFMTransformer(nn.Module):
def post_load_weights(self) -> None:
"""Post-load processing: ensure correct dtypes."""
self.time_embedder.to(torch.float32)
def set_mixed_precision_step(self, step_index: int, num_steps: int) -> None:
if self.mixed_precision_runtime is not None:
self.mixed_precision_runtime.set_step(step_index, num_steps)
def reset_mixed_precision(self) -> None:
if self.mixed_precision_runtime is not None:
self.mixed_precision_runtime.reset()