[CI][ROCm] Shorten the blocking CosyVoice test path (#7748)
Signed-off-by: andyluo7 <andy.luo@amd.com>
This commit is contained in:
1 parent
cb31e0774f
commit
1586c41ae4
6 files changed
+111
-12
No files matched your search
@@ -64,3 +64,21 @@ steps:
|
||||
commands:
|
||||
- export VLLM_ROCM_USE_AITER=1
|
||||
- pytest -s -v tests/e2e/online_serving/test_qwen3_omni_expansion.py::test_text_to_text_audio_001 -m "full_model and rocm and MI325 and cards_2" --run-level "full_model"
|
||||
|
||||
- group: ":speaker: CosyVoice3 MI300 Nightly"
|
||||
steps:
|
||||
# Exercise all sync/async and Chinese/English cases with the platform's
|
||||
# default attention backend. On ROCm this retains end-to-end AITER
|
||||
# coverage without putting its cold JIT build on the READY critical path.
|
||||
- label: "CosyVoice3-TTS E2E Test"
|
||||
agent_pool: mi300_1
|
||||
depends_on: amd-build
|
||||
mirror_hardwares: [amdproduction]
|
||||
grade: NonBlocking
|
||||
timeout_in_minutes: 90
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 134
|
||||
limit: 1
|
||||
commands:
|
||||
- pytest -s -v tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py -m "slow" --run-level "core_model"
|
||||
@@ -328,7 +328,10 @@ steps:
|
||||
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
|
||||
- timeout 30m pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py -m "core_model" --run-level "core_model"
|
||||
|
||||
- label: "CosyVoice3-TTS E2E Test"
|
||||
# Keep a fast model/server integration check in the blocking lane. The
|
||||
# full default-backend suite remains in the nightly pipeline because a
|
||||
# cold ROCm AITER MHA build can add more than 25 minutes to this job.
|
||||
- label: "CosyVoice3-TTS E2E Smoke (SDPA)"
|
||||
agent_pool: mi300_1
|
||||
depends_on: amd-build
|
||||
mirror_hardwares: [amdproduction]
|
||||
@@ -340,7 +343,8 @@ steps:
|
||||
- exit_status: 134
|
||||
limit: 1
|
||||
commands:
|
||||
- pytest -s -v tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py -m "slow" --run-level "core_model"
|
||||
- export DIFFUSION_ATTENTION_BACKEND=TORCH_SDPA
|
||||
- pytest -s -v tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py::test_voice_clone_zh_002 -m "slow" --run-level "core_model"
|
||||
|
||||
# TODO: Bagel test on ROCm is very unstable. @tjtanaa
|
||||
# Need to debug before reneable numerical changes across large PRs
|
||||
|
||||
@@ -67,11 +67,31 @@ def test_ready_diffusion_cpu_suite_is_sharded() -> None:
|
||||
assert "--shard-id=$$BUILDKITE_PARALLEL_JOB" in pytest_command
|
||||
|
||||
|
||||
def test_cosyvoice_gpu_abort_gets_one_fresh_job_retry() -> None:
|
||||
step = _find_step("CosyVoice3-TTS E2E Test", AMD_READY_PIPELINE)
|
||||
def test_cosyvoice_ready_smoke_uses_sdpa() -> None:
|
||||
step = _find_step("CosyVoice3-TTS E2E Smoke (SDPA)", AMD_READY_PIPELINE)
|
||||
|
||||
assert step["grade"] == "Blocking"
|
||||
assert step["retry"] == {"automatic": [{"exit_status": 134, "limit": 1}]}
|
||||
assert "export DIFFUSION_ATTENTION_BACKEND=TORCH_SDPA" in step["commands"]
|
||||
|
||||
pytest_command = next(command for command in step["commands"] if "pytest" in command)
|
||||
assert "tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py::test_voice_clone_zh_002" in pytest_command
|
||||
|
||||
|
||||
def test_cosyvoice_full_default_backend_suite_runs_nightly() -> None:
|
||||
step = _find_step("CosyVoice3-TTS E2E Test", AMD_NIGHTLY_PIPELINE)
|
||||
|
||||
assert step["grade"] == "NonBlocking"
|
||||
assert step["timeout_in_minutes"] == 90
|
||||
assert step["retry"] == {"automatic": [{"exit_status": 134, "limit": 1}]}
|
||||
assert all("DIFFUSION_ATTENTION_BACKEND" not in command for command in step["commands"])
|
||||
|
||||
pytest_command = next(command for command in step["commands"] if "pytest" in command)
|
||||
assert "tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py" in pytest_command
|
||||
assert "::" not in pytest_command
|
||||
|
||||
|
||||
def test_amd_template_preserves_step_retry_policy() -> None:
|
||||
template = AMD_TEMPLATE.read_text(encoding="utf-8")
|
||||
# Both grouped and top-level AMD steps must preserve an explicit retry
|
||||
# policy when the source suite is rendered into the uploaded pipeline.
|
||||
|
||||
@@ -260,6 +260,37 @@ class TestDiTAttention:
|
||||
assert attention.to_k.out_features == 512
|
||||
assert attention.to_v.out_features == 512
|
||||
|
||||
def test_embedded_dit_honors_diffusion_attention_backend(self, monkeypatch):
|
||||
"""The LLM-hosted code2wav DiT must consume the diffusion env override."""
|
||||
from vllm_omni.diffusion.config import get_current_diffusion_config_or_none
|
||||
from vllm_omni.model_executor.models.cosyvoice3.cosyvoice3_code2wav import _build_dit_estimator
|
||||
|
||||
monkeypatch.setenv("DIFFUSION_ATTENTION_BACKEND", "TORCH_SDPA")
|
||||
|
||||
estimator = _build_dit_estimator(
|
||||
{
|
||||
"dim": 32,
|
||||
"depth": 1,
|
||||
"heads": 2,
|
||||
"dim_head": 16,
|
||||
"dropout": 0.0,
|
||||
"ff_mult": 2,
|
||||
"mel_dim": 8,
|
||||
"mu_dim": 8,
|
||||
"spk_dim": 4,
|
||||
"out_channels": 8,
|
||||
"static_chunk_size": 4,
|
||||
"num_decoding_left_chunks": 1,
|
||||
}
|
||||
)
|
||||
|
||||
attention = estimator.transformer_blocks[0].attn.attn
|
||||
assert attention.backend_pref == "TORCH_SDPA"
|
||||
assert attention.backend_explicit is True
|
||||
assert attention.attn_backend is not None
|
||||
assert attention.attn_backend.get_name() == "SDPA"
|
||||
assert get_current_diffusion_config_or_none() is None
|
||||
|
||||
@pytest.mark.core_model
|
||||
@pytest.mark.cpu
|
||||
def test_forward_passes_2d_mask_without_casting_qkv(self):
|
||||
|
||||
@@ -39,7 +39,10 @@ CHUNK_LEN = 24
|
||||
TOTAL_MEL = 96
|
||||
SPM = 480 # samples per mel frame for the small test HiFT (8*5*3*4), matching the real model
|
||||
|
||||
LONG_TOTAL_MEL = 400 # long enough that the 64-frame window actually truncates
|
||||
WINDOW_LEN = 64
|
||||
# Six chunks exercise three updates after history exceeds the bounded window,
|
||||
# without spending minutes recomputing an unnecessarily long synthetic signal.
|
||||
LONG_TOTAL_MEL = 144
|
||||
PCM16_LSB = 1.0 / 32767.0 # smallest representable PCM16 difference
|
||||
|
||||
# Worst observed deviation is 1.97e-7 (~2x float32 eps); atol=1e-6 keeps 5x headroom.
|
||||
@@ -189,16 +192,19 @@ def test_incremental_hift_bounded_window_is_close(config):
|
||||
def test_incremental_hift_matches_streaming_reference_within_tolerance(config):
|
||||
"""Windowed output matches the full-cumulative reference within float32 rounding.
|
||||
|
||||
The load-bearing correctness test: 400 mel frames far exceeds the 64-frame
|
||||
window, so truncation genuinely exercises the phase/noise carry. Float64
|
||||
agrees to ~1e-16, confirming the residual here is rounding, not truncation.
|
||||
The load-bearing correctness test crosses the 64-frame window repeatedly,
|
||||
so truncation genuinely exercises the phase/noise carry. Float64 agrees to
|
||||
~1e-16, confirming the residual here is rounding, not truncation.
|
||||
"""
|
||||
hift = _make_hift(config)
|
||||
model = _make_model(hift, window_len=64) # the real _hift_window_len
|
||||
model = _make_model(hift, window_len=WINDOW_LEN) # the real _hift_window_len
|
||||
chunks = _chunks(total_mel=LONG_TOTAL_MEL)
|
||||
|
||||
trim = int(hift.f0_predictor.condnet[0].causal_padding)
|
||||
assert LONG_TOTAL_MEL > 64 + trim + CHUNK_LEN # window must actually truncate
|
||||
truncating_steps = sum(
|
||||
history_len > WINDOW_LEN + trim for history_len in range(CHUNK_LEN, LONG_TOTAL_MEL, CHUNK_LEN)
|
||||
)
|
||||
assert truncating_steps >= 3 # exercise repeated truncation, not only the boundary
|
||||
|
||||
full = _full_reference(model, chunks)
|
||||
incr = _incremental(model, chunks)
|
||||
|
||||
@@ -10,7 +10,8 @@ This module contains the code2wav (token-to-waveform) stage which uses:
|
||||
"""
|
||||
|
||||
from collections import Counter
|
||||
from typing import TypedDict, cast
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, TypedDict, cast
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -18,6 +19,8 @@ import torch.nn as nn
|
||||
from omegaconf import DictConfig
|
||||
from vllm.logger import init_logger
|
||||
|
||||
from vllm_omni.diffusion.config import get_current_diffusion_config_or_none, set_current_diffusion_config
|
||||
from vllm_omni.diffusion.data import OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.models.cosyvoice3_audio.cosyvoice3_dit import DiT
|
||||
from vllm_omni.model_executor.models.cosyvoice3.code2wav_core.cfm import (
|
||||
CausalConditionalCFM,
|
||||
@@ -37,6 +40,23 @@ from vllm_omni.transformers_utils.configs.cosyvoice3 import CosyVoice3Config
|
||||
logger = init_logger(__name__)
|
||||
|
||||
|
||||
def _build_dit_estimator(estimator_config: Mapping[str, Any]) -> DiT:
|
||||
"""Build CosyVoice's embedded DiT with diffusion backend configuration.
|
||||
|
||||
The code2wav model runs inside an LLM-generation worker, so it does not go
|
||||
through the diffusion model loader that normally installs an
|
||||
``OmniDiffusionConfig`` during model construction. Install a local default
|
||||
config when needed so ``DIFFUSION_ATTENTION_BACKEND`` and the platform
|
||||
default are resolved by the same path as standalone diffusion models.
|
||||
"""
|
||||
if get_current_diffusion_config_or_none() is not None:
|
||||
return DiT(**estimator_config)
|
||||
|
||||
diffusion_config = OmniDiffusionConfig()
|
||||
with set_current_diffusion_config(diffusion_config):
|
||||
return DiT(**estimator_config)
|
||||
|
||||
|
||||
class StreamingFlowItem(TypedDict, total=False):
|
||||
"""One entry of the batched-streaming item list passed to forward_streaming_batch."""
|
||||
|
||||
@@ -71,7 +91,7 @@ class CosyVoice3Code2Wav(nn.Module):
|
||||
cfm_params = DictConfig(decoder_cfg["cfm_params"])
|
||||
|
||||
# DiT estimator using diffusion attention (Flash/Sage/SDPA backends)
|
||||
estimator = DiT(**decoder_cfg["estimator"])
|
||||
estimator = _build_dit_estimator(decoder_cfg["estimator"])
|
||||
|
||||
decoder = CausalConditionalCFM(
|
||||
in_channels=decoder_cfg["in_channels"],
|
||||
|
||||
Reference in new issue
Block a user