From 82aa524c8ef6d671a7857e0370e0b9507bbafdbf Mon Sep 17 00:00:00 2001 From: tzhouam Date: Sun, 4 Oct 2026 03:19:45 +0800 Subject: [PATCH] [Bugfix] Provide Omni lifecycle state for auxiliary v2 stages Signed-off-by: tzhouam --- tests/worker_v2/test_omni_gpu_model_runner.py | 23 +++++++++++++++++++ vllm_omni/worker_v2/model_states/__init__.py | 20 ++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/worker_v2/test_omni_gpu_model_runner.py b/tests/worker_v2/test_omni_gpu_model_runner.py index dd4c760c6..a363523f5 100644 --- a/tests/worker_v2/test_omni_gpu_model_runner.py +++ b/tests/worker_v2/test_omni_gpu_model_runner.py @@ -13,6 +13,7 @@ from vllm import SamplingParams from vllm.config.compilation import CUDAGraphMode from vllm.v1.core.sched.output import SchedulerOutput from vllm.v1.worker.gpu.model_runner import GPUModelRunner +from vllm.v1.worker.gpu.model_states.default import DefaultModelState from vllm.v1.worker.gpu.sample.sampler import Sampler from vllm_omni.config.model import OmniModelConfig @@ -163,6 +164,28 @@ def test_init_model_state_factory_dispatches_omni_only(monkeypatch, flag, expect assert state is upstream.return_value +@pytest.mark.parametrize("omni_stage", [False, True]) +@pytest.mark.parametrize("specialized", [False, True]) +def test_auxiliary_default_state_has_omni_lifecycle_but_preserves_upstream_states(monkeypatch, omni_stage, specialized): + class SpecializedState(DefaultModelState): + pass + + state_cls = SpecializedState if specialized else DefaultModelState + upstream_state = object.__new__(state_cls) + monkeypatch.setattr("vllm_omni.worker_v2.model_states._upstream_init_model_state", lambda *_args: upstream_state) + monkeypatch.setattr(OmniModelState, "__init__", lambda *_args: None) + model_config = object.__new__(OmniModelConfig) if omni_stage else SimpleNamespace() + state = init_omni_model_state( + SimpleNamespace(model_config=model_config), SimpleNamespace(), None, torch.device("cpu") + ) + if omni_stage and not specialized: + assert isinstance(state, OmniModelState) + assert callable(state.run_preprocess) + assert callable(state.postprocess_model_output) + else: + assert state is upstream_state + + def test_finish_requests_notifies_model_and_cleans_only_known_slots(monkeypatch): runner = _make_runner() calls = [] diff --git a/vllm_omni/worker_v2/model_states/__init__.py b/vllm_omni/worker_v2/model_states/__init__.py index 7475d3d7d..50386df02 100644 --- a/vllm_omni/worker_v2/model_states/__init__.py +++ b/vllm_omni/worker_v2/model_states/__init__.py @@ -4,7 +4,8 @@ """Omni-aware ``init_model_state`` factory. Extends the upstream v2 factory with Omni architecture dispatch. -Non-Omni architectures fall through to the upstream ``init_model_state``. +Non-Omni architectures use upstream dispatch; its default state acquires +Omni lifecycle support when owned by an Omni stage. """ from __future__ import annotations @@ -16,8 +17,11 @@ from vllm.v1.worker.gpu.mm.encoder_cache import EncoderCache from vllm.v1.worker.gpu.model_states import ( init_model_state as _upstream_init_model_state, ) +from vllm.v1.worker.gpu.model_states.default import DefaultModelState from vllm.v1.worker.gpu.model_states.interface import ModelState +from vllm_omni.config.model import OmniModelConfig + def init_omni_model_state( vllm_config: VllmConfig, @@ -28,8 +32,8 @@ def init_omni_model_state( """Create the appropriate ``ModelState`` for *model*. Returns an ``OmniModelState`` when the model declares Omni lifecycle - capabilities; otherwise - delegates to the upstream v2 factory. + capabilities. Otherwise delegates to the upstream v2 factory, wrapping + its default state for auxiliary Omni stages. """ factory = getattr(model, "create_omni_model_state", None) if factory is not None: @@ -49,4 +53,12 @@ def init_omni_model_state( ) return OmniModelState(vllm_config, model, encoder_cache, device) - return _upstream_init_model_state(vllm_config, model, encoder_cache, device) + state = _upstream_init_model_state(vllm_config, model, encoder_cache, device) + if type(state) is DefaultModelState and isinstance(getattr(vllm_config, "model_config", None), OmniModelConfig): + # Auxiliary stages such as the forced aligner have no model-owned + # hooks, but Omni's runner still needs its request/output lifecycle. + # Keep specialized upstream states and plain vLLM configs intact. + from vllm_omni.worker_v2.model_states.omni_model_state import OmniModelState + + return OmniModelState(vllm_config, model, encoder_cache, device) + return state