fix: preserve CosyVoice full payload and live conditioning (#8343)

Signed-off-by: andyluo7 <andy.luo@amd.com>
This commit is contained in:
andyluo7 authored and GitHub committed 2026-10-04 16:03:27 +13:00
1 parent 09d704907f
commit b171731c81
6 files changed
+149 -14

No files matched your search

@@ -928,4 +928,51 @@ def test_talker_output_contract(monkeypatch, mrv2, packed):
model._sampling_eps = 1e-6
model.mrv2_custom_sampler(SimpleNamespace(penalties_state=None))
output = model.forward(torch.ones(2, dtype=torch.long), torch.arange(2), inputs_embeds=hidden)
assert output is (hidden if mrv2 or packed else sentinel)
assert output is hidden
def test_request_conditioning_normalizes_singletons_without_changing_schema():
from vllm_omni.data_entry_keys import to_struct
from vllm_omni.model_executor.models.cosyvoice3.cosyvoice3 import _normalize_request_conditioning
token = torch.tensor([[7, 8]], dtype=torch.int32)
feat = torch.randn(1, 4, 80)
speaker = torch.randn(1, 192)
length = torch.tensor([[2]], dtype=torch.int32)
raw = {"embed": {"speech_token": token, "speech_feat": feat, "embedding": speaker, "speech_token_len": [length]}}
result = to_struct(_normalize_request_conditioning(raw))
assert result.embed.speech_token is token
assert result.embed.speech_feat is feat
assert result.embed.embedding is speaker
assert result.embed.speech_token_len is length
assert raw["embed"]["speech_token_len"] == [length]
def test_request_conditioning_rejects_unsplit_voices():
from vllm_omni.model_executor.models.cosyvoice3.cosyvoice3 import _normalize_request_conditioning
with pytest.raises(ValueError, match="unsplit batch"):
_normalize_request_conditioning({"embed": {"embedding": [torch.ones(1, 192), torch.zeros(1, 192)]}})
def test_request_conditioning_reaches_code2wav_with_true_prompt_length():
model = _make_code2wav_model()
output = model.forward(
torch.tensor([1, 2]),
torch.arange(2),
model_intermediate_buffer=[
{
"embed": {
"speech_token": torch.tensor([[3, 2, 0, 0]], dtype=torch.int32),
"speech_feat": torch.randn(1, 8, 80),
"embedding": torch.randn(1, 192),
"speech_token_len": [torch.tensor([[2]], dtype=torch.int32)],
},
"meta": {"req_id": ["voice"]},
}
],
)
call = model.code2wav.forward_calls[0]
assert call["prompt_token"].shape == (1, 2)
assert call["prompt_feat"].shape == (1, 4, 80)
assert output.multimodal_outputs
@@ -13,6 +13,7 @@ from vllm_omni.model_executor.stage_input_processors.cosyvoice3 import (
text2flow_full_payload,
text2flow_token_only,
)
from vllm_omni.outputs.mm_outputs import MultimodalPayload
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
@@ -121,6 +122,24 @@ def test_text2flow_full_payload_does_not_send_codec_ids():
assert torch.equal(payload["embed"]["speech_token"], torch.tensor([[1, 2]], dtype=torch.long))
def test_text2flow_full_payload_accepts_structured_multimodal_payload():
speech_token = torch.tensor([[1, 2]], dtype=torch.long)
payload = text2flow_full_payload(
None,
MultimodalPayload(
tensors={
"embed.speech_token": speech_token,
"codes.audio": torch.tensor([7, 8, 9], dtype=torch.long),
}
),
SimpleNamespace(external_req_id="req-structured"),
)
assert payload is not None
assert "codes" not in payload
assert torch.equal(payload["embed"]["speech_token"], speech_token)
def test_talker2code2wav_async_chunk_final_payload_uses_absolute_token_offset():
transfer_manager = _transfer_manager()
request = SimpleNamespace(
@@ -355,3 +374,36 @@ def test_talker2code2wav_async_chunk_emits_terminal_eof_without_duplicate_audio(
assert payload_final is not None
assert payload_final.meta.finished.item() is True
assert payload_final.codes.audio.tolist() == []
def test_full_payload_retains_true_length_for_padded_conditioning():
from vllm_omni.data_entry_keys import to_struct
token = torch.tensor([[7, 8, 0, 0]], dtype=torch.int32)
feat = torch.randn(1, 8, 80)
speaker = torch.randn(1, 192)
length = torch.tensor([[2]], dtype=torch.int32)
result = text2flow_full_payload(
None,
{
"embed.speech_token": token,
"embed.speech_feat": feat,
"embed.embedding": speaker,
"embed.speech_token_len": length,
},
SimpleNamespace(request_id="padded"),
)
payload = to_struct(result)
assert payload.embed.speech_token_len is length
def test_reference_features_are_snapshots_under_output_accumulation():
from vllm_omni.outputs.mm_outputs import MultimodalPayload
from vllm_omni.outputs.output_modality import OutputModality
first = torch.ones(1, 174, 80)
latest = torch.zeros(1, 1500, 80)
payload = MultimodalPayload.from_dict({"embed.speech_feat": first})
payload = payload.merged_with(MultimodalPayload.from_dict({"embed.speech_feat": latest}))
payload.consolidate_tensors(OutputModality.LATENT)
assert payload["embed.speech_feat"] is latest
@@ -971,12 +971,14 @@ def test_cosyvoice3_text2flow_full_payload_nested_fallback() -> None:
def test_cosyvoice3_full_payload_replace_keys_present() -> None:
"""Confirm _FULL_PAYLOAD_REPLACE_KEYS lists the three embed.* keys."""
"""Reference tensors and their length travel as complete snapshots."""
from vllm_omni.model_executor.stage_input_processors.cosyvoice3 import (
_FULL_PAYLOAD_REPLACE_KEYS,
)
assert _FULL_PAYLOAD_REPLACE_KEYS == frozenset({"embed.speech_token", "embed.speech_feat", "embed.embedding"})
assert _FULL_PAYLOAD_REPLACE_KEYS == frozenset(
{"embed.speech_token", "embed.speech_token_len", "embed.speech_feat", "embed.embedding"}
)
def test_ming_flash_omni_thinker2talker_token_only_smoke() -> None: