Skip to content
4 changes: 2 additions & 2 deletions components/src/dynamo/common/configuration/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def add_negatable_bool_argument(
*,
flag_name: str,
env_var: str,
default: bool,
default: Optional[bool],
help: str,
dest: Optional[str] = None,
obsolete_flag: Optional[str] = None,
Expand All @@ -173,7 +173,7 @@ def add_negatable_bool_argument(
parser: ArgumentParser or argument group
flag_name: Primary flag (must start with '--', e.g. "--enable-feature")
env_var: Environment variable name (e.g., "DYN_ENABLE_FEATURE")
default: Default value
default: Default value. Use None when an omitted flag must remain unset.
help: Help text
dest: Optional destination name for the parsed value
obsolete_flag: Optional obsolete/legacy flag (for help msg only, must start with '--')
Expand Down
16 changes: 1 addition & 15 deletions components/src/dynamo/frontend/prepost.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from functools import lru_cache, partial
from typing import TYPE_CHECKING, Any, Protocol, TypeGuard, cast

from packaging.version import Version
from vllm import __version__ as vllm_version
from vllm.entrypoints.chat_utils import make_tool_call_id
from vllm.entrypoints.openai.chat_completion.protocol import (
ChatCompletionNamedFunction,
Expand All @@ -31,24 +29,12 @@
from vllm.utils.async_utils import make_async

from dynamo.common.utils.guided_json import admits_only_empty_object
from dynamo.frontend.vllm_protocol import DeltaFunctionCall, DeltaMessage, DeltaToolCall
Comment thread
GuanLuo marked this conversation as resolved.
from dynamo.llm.exceptions import InvalidArgument

from .thinking import apply_default_thinking_mode_to_template_kwargs
from .utils import legacy_guided_decoding

if Version(vllm_version).release >= (0, 29):
from vllm.entrypoints.generate.base.protocol import (
DeltaFunctionCall,
DeltaMessage,
DeltaToolCall,
)
else:
from vllm.entrypoints.openai.engine.protocol import (
DeltaFunctionCall,
DeltaMessage,
DeltaToolCall,
)

if TYPE_CHECKING:
from vllm.config import ModelConfig

Expand Down
37 changes: 37 additions & 0 deletions components/src/dynamo/frontend/vllm_protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Compatibility imports for vLLM's shared OpenAI protocol types."""

from importlib.util import find_spec

try:
_HAS_GENERATE_PROTOCOL = (
find_spec("vllm.entrypoints.generate.base.protocol") is not None
)
except ModuleNotFoundError:
_HAS_GENERATE_PROTOCOL = False

if _HAS_GENERATE_PROTOCOL:
# vLLM 0.29 moved the shared types out of the OpenAI engine package.
from vllm.entrypoints.generate.base.protocol import (
DeltaFunctionCall,
DeltaMessage,
DeltaToolCall,
FunctionDefinition,
)
else:
# vLLM 0.27 and 0.28 expose the same types at the legacy path.
from vllm.entrypoints.openai.engine.protocol import (
DeltaFunctionCall,
DeltaMessage,
DeltaToolCall,
FunctionDefinition,
)

__all__ = [
"DeltaFunctionCall",
"DeltaMessage",
"DeltaToolCall",
"FunctionDefinition",
]
53 changes: 39 additions & 14 deletions components/src/dynamo/vllm/omni/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
add_argument,
add_negatable_bool_argument,
env_or_default,
parse_bool,
)
from dynamo.common.constants import DisaggregationMode

Expand All @@ -46,19 +47,20 @@ class OmniDiffusionKwargs:
passthrough in base_handler is automatic.
"""

enable_layerwise_offload: bool = False
enable_layerwise_offload: Optional[bool] = None
layerwise_num_gpu_layers: int = 1
vae_use_slicing: bool = False
vae_use_tiling: bool = False
boundary_ratio: float = 0.875
vae_use_slicing: Optional[bool] = None
vae_use_tiling: Optional[bool] = None
boundary_ratio: Optional[float] = None
flow_shift: Optional[float] = None
cache_backend: Optional[str] = None
cache_config: Optional[str] = None
enable_cache_dit_summary: bool = False
enable_cpu_offload: bool = False
enable_cache_dit_summary: Optional[bool] = None
enable_cpu_offload: Optional[bool] = None
task_type: Optional[str] = None
lora_path: Optional[list[str]] = None
diffusion_attention_backend: Optional[str] = None
fastvideo_vsa_topk: Optional[int] = None
enforce_eager: bool = False


Expand Down Expand Up @@ -117,7 +119,8 @@ def add_arguments(self, parser) -> None:
g,
flag_name="--enable-layerwise-offload",
env_var="DYN_OMNI_ENABLE_LAYERWISE_OFFLOAD",
default=False,
default=None,
env_value_type=parse_bool,
help="Enable layerwise (blockwise) offloading on DiT modules to reduce GPU memory.",
)
add_argument(
Expand All @@ -132,25 +135,27 @@ def add_arguments(self, parser) -> None:
g,
flag_name="--vae-use-slicing",
env_var="DYN_OMNI_VAE_USE_SLICING",
default=False,
default=None,
env_value_type=parse_bool,
help="Enable VAE slicing for memory optimization in diffusion models.",
)
add_negatable_bool_argument(
g,
flag_name="--vae-use-tiling",
env_var="DYN_OMNI_VAE_USE_TILING",
default=False,
default=None,
env_value_type=parse_bool,
help="Enable VAE tiling for memory optimization in diffusion models.",
)
add_argument(
g,
flag_name="--boundary-ratio",
env_var="DYN_OMNI_BOUNDARY_RATIO",
default=0.875,
default=None,
arg_type=float,
help=(
"Boundary split ratio for low/high DiT transformers. "
"Default 0.875 uses both transformers for best quality. "
"When omitted, the model pipeline selects its default. "
"Set to 1.0 to load only the low-noise transformer (saves memory)."
),
)
Expand Down Expand Up @@ -185,14 +190,16 @@ def add_arguments(self, parser) -> None:
g,
flag_name="--enable-cache-dit-summary",
env_var="DYN_OMNI_ENABLE_CACHE_DIT_SUMMARY",
default=False,
default=None,
env_value_type=parse_bool,
help="Enable cache-dit summary logging after diffusion forward passes.",
)
add_negatable_bool_argument(
g,
flag_name="--enable-cpu-offload",
env_var="DYN_OMNI_ENABLE_CPU_OFFLOAD",
default=False,
default=None,
env_value_type=parse_bool,
help="Enable CPU offloading for diffusion models to reduce GPU memory usage.",
)
add_argument(
Expand Down Expand Up @@ -221,6 +228,17 @@ def add_arguments(self, parser) -> None:
default=None,
help="vLLM-Omni diffusion attention backend.",
)
add_argument(
g,
flag_name="--fastvideo-vsa-topk",
env_var="DYN_OMNI_FASTVIDEO_VSA_TOPK",
default=None,
arg_type=int,
help=(
"Key/value blocks retained per query block by the "
"FASTVIDEO_VSA diffusion attention backend."
),
)
add_negatable_bool_argument(
g,
flag_name="--enforce-eager",
Expand Down Expand Up @@ -482,8 +500,15 @@ def validate(self) -> None:
raise ValueError("--allgather-degree must be > 0")
if self.parallel.text_encoder_tp_size <= 0:
raise ValueError("--text-encoder-tp-size must be > 0")
if not (0 < self.diffusion.boundary_ratio <= 1):
if self.diffusion.boundary_ratio is not None and not (
0 < self.diffusion.boundary_ratio <= 1
):
raise ValueError("--boundary-ratio must be in (0, 1]")
if (
self.diffusion.fastvideo_vsa_topk is not None
and self.diffusion.fastvideo_vsa_topk <= 0
):
raise ValueError("--fastvideo-vsa-topk must be > 0")
if self.stage_configs_path is None:
if self.stage_id is not None:
raise ValueError("--stage-id requires --stage-configs-path")
Expand Down
58 changes: 58 additions & 0 deletions components/src/dynamo/vllm/tests/omni/test_omni_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,57 @@ def test_ulysses_a2a_permute_parses_as_parallel_option():
assert args.ulysses_a2a_permute is True


def test_fastvideo_vsa_topk_parses_as_diffusion_option():
parser = argparse.ArgumentParser()
OmniArgGroup().add_arguments(parser)

args = parser.parse_args(["--fastvideo-vsa-topk", "64"])

assert args.fastvideo_vsa_topk == 64


def test_diffusion_only_options_remain_unset_when_omitted():
parser = argparse.ArgumentParser()
OmniArgGroup().add_arguments(parser)

args = parser.parse_args([])

assert {
"enable_layerwise_offload": args.enable_layerwise_offload,
"vae_use_slicing": args.vae_use_slicing,
"vae_use_tiling": args.vae_use_tiling,
"boundary_ratio": args.boundary_ratio,
"enable_cache_dit_summary": args.enable_cache_dit_summary,
"enable_cpu_offload": args.enable_cpu_offload,
} == {
"enable_layerwise_offload": None,
"vae_use_slicing": None,
"vae_use_tiling": None,
"boundary_ratio": None,
"enable_cache_dit_summary": None,
"enable_cpu_offload": None,
}


def test_diffusion_bool_option_preserves_explicit_false():
parser = argparse.ArgumentParser()
OmniArgGroup().add_arguments(parser)

args = parser.parse_args(["--no-vae-use-tiling"])

assert args.vae_use_tiling is False


def test_diffusion_bool_environment_option_is_parsed(monkeypatch):
monkeypatch.setenv("DYN_OMNI_VAE_USE_TILING", "false")
parser = argparse.ArgumentParser()
OmniArgGroup().add_arguments(parser)

args = parser.parse_args([])

assert args.vae_use_tiling is False


@pytest.mark.parametrize("fps", [0, -1, -100])
def test_omni_config_invalid_video_fps(fps):
config = _make_omni_config(default_video_fps=fps)
Expand Down Expand Up @@ -165,6 +216,13 @@ def test_omni_config_valid_boundary_ratio(ratio):
config.validate()


@pytest.mark.parametrize("topk", [0, -1])
def test_omni_config_invalid_fastvideo_vsa_topk(topk):
config = _make_omni_config(fastvideo_vsa_topk=topk)
with pytest.raises(ValueError, match="--fastvideo-vsa-topk must be > 0"):
config.validate()


def test_negative_stage_id_rejected():
config = _make_omni_config(stage_id=-1, stage_configs_path="/fake/path.yaml")
with pytest.raises(ValueError, match="--stage-id must be >= 0"):
Expand Down
30 changes: 28 additions & 2 deletions components/src/dynamo/vllm/tests/omni/test_omni_base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
pytest.mark.unit,
pytest.mark.vllm,
pytest.mark.gpu_0,
pytest.mark.xpu_1,
pytest.mark.pre_merge,
]

Expand Down Expand Up @@ -197,14 +198,39 @@ def test_model_defined_diffusion_fields_forwarded_to_async_omni(self):
OmniDiffusionKwargs(),
task_type="fl2va",
lora_path=["/models/fasth3/adapter_model.safetensors"],
diffusion_attention_backend="TRTLLM_ATTN",
diffusion_attention_backend="FASTVIDEO_VSA",
fastvideo_vsa_topk=64,
)

kwargs = _build_kwargs(config)

assert kwargs["task_type"] == "fl2va"
assert kwargs["lora_path"] == ["/models/fasth3/adapter_model.safetensors"]
assert kwargs["diffusion_attention_backend"] == "TRTLLM_ATTN"
assert kwargs["diffusion_attention_backend"] == "FASTVIDEO_VSA"
assert kwargs["fastvideo_vsa_topk"] == 64

def test_diffusion_only_defaults_not_forwarded_to_async_omni(self):
Comment thread
dmitry-tokarev-nv marked this conversation as resolved.
kwargs = _build_kwargs(_make_config())

for field in (
"enable_layerwise_offload",
"vae_use_slicing",
"vae_use_tiling",
"boundary_ratio",
"enable_cache_dit_summary",
"enable_cpu_offload",
):
assert field not in kwargs

def test_explicit_false_diffusion_option_forwarded_to_async_omni(self):
config = _make_config()
config.diffusion = dataclasses.replace(
OmniDiffusionKwargs(), vae_use_tiling=False
)

kwargs = _build_kwargs(config)

assert kwargs["vae_use_tiling"] is False

def test_lora_disabled_resolves_no_capacity(self):
config = _make_config()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@
import inspect

import pytest
from packaging.version import Version

# Import vllm first to ensure it's properly loaded before accessing submodules.
_vllm = importlib.import_module("vllm")
_chat_protocol = importlib.import_module(
"vllm.entrypoints.openai.chat_completion.protocol"
)
_engine_protocol = importlib.import_module(
"vllm.entrypoints.generate.base.protocol"
if Version(_vllm.__version__).release >= (0, 29)
else "vllm.entrypoints.openai.engine.protocol"
)
_engine_protocol = importlib.import_module("dynamo.frontend.vllm_protocol")
_inputs_data = importlib.import_module("vllm.inputs")
_reasoning = importlib.import_module("vllm.reasoning")
_sampling_params = importlib.import_module("vllm.sampling_params")
Expand Down
11 changes: 8 additions & 3 deletions docs/fern/pages/reference/backends/vllm-omni-configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ These are the vLLM-Omni orchestration flags. The omni worker also accepts the sa
<ParamField path="--stage-configs-path" type="path">
Path to stage config YAML (optional; vLLM-Omni uses model defaults if omitted).
</ParamField>
<ParamField path="--boundary-ratio" type="float" default="0.875">
MoE expert switching boundary.
<ParamField path="--boundary-ratio" type="float">
MoE expert switching boundary. If omitted, the vLLM-Omni model pipeline selects its default.
</ParamField>
<ParamField path="--flow-shift" type="float">
Scheduler flow_shift (5.0 for 720p, 12.0 for 480p).
Expand All @@ -39,7 +39,12 @@ These are the vLLM-Omni orchestration flags. The omni worker also accepts the sa
separate from request-time LoRA loading.
</ParamField>
<ParamField path="--diffusion-attention-backend" type="string">
Default diffusion attention backend, such as `TRTLLM_ATTN` or `FLASH_ATTN`.
Default diffusion attention backend, such as `TRTLLM_ATTN`, `FLASH_ATTN`, or
`FASTVIDEO_VSA`.
</ParamField>
<ParamField path="--fastvideo-vsa-topk" type="int">
Key/value blocks retained per query block by `FASTVIDEO_VSA`. The value must
be positive; FastH3 VSA starts with 64.
</ParamField>

## Memory & Performance
Expand Down
Loading
Loading