diff --git a/tests/model_executor/models/minicpmo_4_5/test_cuda_graph_wrapper.py b/tests/model_executor/models/minicpmo_4_5/test_cuda_graph_wrapper.py index f22a2c693..7519b3b5f 100644 --- a/tests/model_executor/models/minicpmo_4_5/test_cuda_graph_wrapper.py +++ b/tests/model_executor/models/minicpmo_4_5/test_cuda_graph_wrapper.py @@ -231,8 +231,12 @@ def _cfm_inputs( time_emb = torch.randn(batch_size, 1, hidden, device=device) cnn_cache = torch.randn(depth, batch_size, hidden, 2, device=device) att_cache = torch.randn(depth, batch_size, 1, old_att_len, hidden, device=device) - cnn_out = torch.empty(depth, batch_size, hidden, 2, device=device) - att_out = torch.empty(depth, batch_size, 1, old_att_len + chunk_size, hidden, device=device) + # The fake estimator only fills ``att_out[:, :, :, :chunk_size]``. The tail + # is the previous cache slot and is not written. ``empty`` leaves it + # uninitialized, so eager and replay compare different garbage and CI + # fails when that garbage is NaN. + cnn_out = torch.zeros(depth, batch_size, hidden, 2, device=device) + att_out = torch.zeros(depth, batch_size, 1, old_att_len + chunk_size, hidden, device=device) return estimator_input, time_emb, cnn_cache, att_cache, cnn_out, att_out diff --git a/tests/platforms/npu/test_voxcpm2_loc_dit_npugraph.py b/tests/platforms/npu/test_voxcpm2_loc_dit_npugraph.py index d34a73209..d066e338b 100644 --- a/tests/platforms/npu/test_voxcpm2_loc_dit_npugraph.py +++ b/tests/platforms/npu/test_voxcpm2_loc_dit_npugraph.py @@ -76,12 +76,13 @@ def test_model_patch_wraps_init_and_is_idempotent(monkeypatch) -> None: assert model.prefix == "talker" -def test_npu_platform_registers_patch_and_keeps_worker_cls(monkeypatch) -> None: +def test_npu_platform_defers_patch_until_device_setup(monkeypatch) -> None: pytest.importorskip( "vllm_ascend", reason="NPU platform registration requires the optional vllm-ascend plugin", ) from vllm_ascend import utils as ascend_utils + from vllm_ascend.platform import NPUPlatform from vllm_omni.platforms.npu import _310p from vllm_omni.platforms.npu.models import ( @@ -115,7 +116,21 @@ def test_npu_platform_registers_patch_and_keeps_worker_cls(monkeypatch) -> None: worker_cls = NPUOmniPlatform.get_omni_ar_worker_cls() assert worker_cls == "vllm_omni.platforms.npu.worker.npu_ar_worker.NPUARWorker" - assert calls == ["voxcpm2"] + assert calls == [] + + device = torch.device("npu:0") + monkeypatch.setattr( + NPUPlatform, + "set_device", + classmethod(lambda cls, device: calls.append(("set_device", device))), + ) + monkeypatch.setattr(ascend_utils, "enable_custom_op", lambda: calls.append("custom_ops")) + monkeypatch.setattr(torch.npu, "config", SimpleNamespace(allow_internal_format=False)) + + NPUOmniPlatform.set_device(device) + + assert calls == [("set_device", device), "voxcpm2", "custom_ops"] + assert torch.npu.config.allow_internal_format def test_loc_dit_npugraph_supports_wrapped_subclass_and_wraps_once(monkeypatch) -> None: diff --git a/vllm_omni/platforms/npu/models/voxcpm2_talker.py b/vllm_omni/platforms/npu/models/voxcpm2_talker.py index 5ef3b2aec..e34734d74 100644 --- a/vllm_omni/platforms/npu/models/voxcpm2_talker.py +++ b/vllm_omni/platforms/npu/models/voxcpm2_talker.py @@ -38,8 +38,8 @@ def apply_voxcpm2_talker_patch() -> None: if _PATCHED: return - # The model defers resolving ``current_omni_platform`` until construction, - # so importing it while NPUOmniPlatform is initialized is cycle-free. + # Call this only after platform initialization: the model's transitive + # imports resolve ``current_omni_platform``. from vllm_omni.model_executor.models.voxcpm2.voxcpm2_talker import ( VoxCPM2TalkerForConditionalGeneration, ) diff --git a/vllm_omni/platforms/npu/platform.py b/vllm_omni/platforms/npu/platform.py index 8165c1a42..82ddaf59c 100644 --- a/vllm_omni/platforms/npu/platform.py +++ b/vllm_omni/platforms/npu/platform.py @@ -68,21 +68,26 @@ class NPUOmniPlatform(OmniPlatform, NPUPlatform): from vllm_omni.platforms.npu.models.qwen3_tts_tokenizer_v2 import ( apply_qwen3_tts_tokenizer_v2_patch, ) - from vllm_omni.platforms.npu.models.voxcpm2_talker import ( - apply_voxcpm2_talker_patch, - ) adapt_patch(is_global_patch=True) apply_minicpmo_4_5_code2wav_patch() apply_qwen3_tts_patches() apply_qwen3_tts_tokenizer_v2_patch() - apply_voxcpm2_talker_patch() apply_310p_patches() @classmethod def set_device(cls, device: torch.device) -> None: super().set_device(device) + # The model's dependencies resolve current_omni_platform, so importing + # it in __init__ would re-enter platform initialization. Install the + # patch in the worker, before it constructs the model instead. + from vllm_omni.platforms.npu.models.voxcpm2_talker import ( + apply_voxcpm2_talker_patch, + ) + + apply_voxcpm2_talker_patch() + # Register vllm_ascend custom ops (torch.ops._C_ascend.*). from vllm_ascend.utils import enable_custom_op