Merge branch 'main' into codex/fix-diffusion-allrank-rpc

This commit is contained in:
Hongsheng Liu authored and GitHub committed 2026-06-13 12:32:44 +08:00
commit 170f98c847
20 files changed
+1045 -208

No files matched your search

@@ -0,0 +1,101 @@
# SPDX-License-Identifier: Apache-2.0
"""Unit tests for the TTS serving adapter registry (RFC #4327).
Pure-Python registry/resolution logic; no model or GPU resources are loaded.
"""
import pytest
from vllm_omni.entrypoints.openai.tts_adapters import (
TTS_ADAPTER_REGISTRY,
ARTTSAdapter,
DiffusionTTSAdapter,
all_tts_model_types,
resolve_adapter,
)
from vllm_omni.entrypoints.openai.tts_adapters.qwen3_tts import Qwen3TTSAdapter
# Every dedicated TTS model-type must have an adapter so the orchestrator's
# uniform ``self._adapter.build(...)`` dispatch covers it.
EXPECTED_MODEL_TYPES = {
"qwen3_tts",
"voxcpm2",
"voxtral_tts",
"fish_tts",
"cosyvoice3",
"omnivoice",
"covo_audio",
"ming_tts",
"moss_tts_nano",
"moss_tts",
"higgs_audio_v2",
"higgs_audio_v3",
"glm_tts",
"step_audio2",
}
def test_all_model_types_registered():
assert EXPECTED_MODEL_TYPES <= all_tts_model_types()
def test_registry_keyed_by_name():
for name, cls in TTS_ADAPTER_REGISTRY.items():
assert cls.name == name
def test_resolve_each_model_type():
for model_type in EXPECTED_MODEL_TYPES:
cls = resolve_adapter(model_type)
assert cls is not None, model_type
assert cls.name == model_type
def test_resolve_qwen3_tts_class():
assert resolve_adapter("qwen3_tts") is Qwen3TTSAdapter
def test_resolve_unknown_returns_none():
assert resolve_adapter("not_a_real_model") is None
assert resolve_adapter(None) is None
def test_ming_flash_omni_not_migrated():
"""ming_flash_omni is intentionally excluded from the adapter migration in
this PR; it stays on the legacy inline dispatch in serving_speech.py."""
assert resolve_adapter("ming_flash_omni_tts") is None
def test_voxcpm2_resolves():
"""VoxCPM2 (the served ``latent_generator`` model) resolves cleanly.
Detection never returns the legacy ``voxcpm`` type, so there is no shared
stage-key ambiguity to resolve.
"""
assert resolve_adapter("voxcpm2") is not None
assert resolve_adapter("voxcpm") is None
def test_all_adapters_are_ar_or_diffusion():
for cls in TTS_ADAPTER_REGISTRY.values():
assert issubclass(cls, (ARTTSAdapter, DiffusionTTSAdapter))
assert cls.backend in ("ar", "diffusion")
def test_qwen3_tts_metadata():
assert Qwen3TTSAdapter.backend == "ar"
assert issubclass(Qwen3TTSAdapter, ARTTSAdapter)
def test_diffusion_adapter_extra_body_params_fallback():
class _DiffAdapter(DiffusionTTSAdapter):
name = "diff_probe"
async def build(self, request, sampling_params_list): # pragma: no cover
raise NotImplementedError
assert _DiffAdapter.extra_body_params() == frozenset()
if __name__ == "__main__":
pytest.main([__file__, "-v"])
+18 -2
View File
@@ -520,9 +520,25 @@ def assert_omni_response(response: Any, request_config: dict[str, Any], run_leve
def assert_audio_speech_response(response: Any, request_config: dict[str, Any], run_level: str) -> None:
"""Validate speech API results from :class:`~tests.helpers.runtime.OmniResponse`.
Success path only. Use :meth:`OpenAIClientHandler.send_audio_speech_http_request` with ``err_code`` /
``err_message`` for expected HTTP errors.
When ``request_config`` carries ``status_code`` and/or ``err_message``, the
request is expected to be rejected: assert it failed and that the HTTP status
/ error text match. Otherwise the normal success-path checks run.
"""
expected_status = request_config.get("status_code")
expected_err = request_config.get("err_message")
if expected_status is not None or expected_err is not None:
assert not response.success, "Expected an error response, but the request succeeded."
if expected_status is not None:
allowed = expected_status if isinstance(expected_status, (list, tuple)) else (expected_status,)
assert response.status_code in allowed, f"Expected HTTP status in {allowed}, got {response.status_code}"
if expected_err is not None:
alternatives = expected_err if isinstance(expected_err, (list, tuple)) else (expected_err,)
error_text = response.error_message or ""
assert any(alt in error_text for alt in alternatives), (
f"Expected one of {alternatives} in error text, got: {error_text!r}"
)
return
assert response.success, "The request failed."
# Optional floor on decoded audio size (models with very short clips may use a lower value).
+4
View File
@@ -762,6 +762,10 @@ class OmniResponse:
prompt_tokens: int | None = None
cached_tokens: int | None = None
logprobs: list | None = None
#: HTTP status + error text for the error-handling path (e.g. validator
#: rejections); populated when the OpenAI client raises an APIError.
status_code: int | None = None
error_message: str | None = None
@dataclass