[Bugfix]Include Reference Audio Cache Salt for HiggsAudio v2 (#7826)

Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
This commit is contained in:
boatman authored and GitHub committed 2026-09-20 00:19:14 +08:00
1 parent 415005be22
commit f9f53f2bd8
2 files changed
+51 -1

No files matched your search

@@ -1859,6 +1859,53 @@ class TestTTSMethods:
assert prompt_a["additional_information"]["ref_audio_cache_key"] == "key_aaa"
assert prompt_b["additional_information"]["ref_audio_cache_key"] == "key_bbb"
@pytest.mark.asyncio
async def test_higgs_v2_cache_salt_changes_for_same_shaped_reference_audio(self, speech_server, mocker):
"""Higgs v2 must salt identical placeholder prompts by resolved audio content."""
build_voice_clone_prompt = mocker.patch(
"vllm_omni.model_executor.models.higgs_audio_v2.higgs_audio_v2_tokenizer.build_voice_clone_prompt"
)
build_voice_clone_prompt.side_effect = lambda _processor, _input, wav, _sr, _ref_text: {
"prompt_token_ids": [1, 151700, 151700, 2],
"audio_input_ids": torch.tensor([[100 if wav[0] < 0.5 else 900, 2], [3, 4]], dtype=torch.long),
"audio_input_ids_mask": torch.ones(2, dtype=torch.bool),
}
speech_server._tts_model_type = "higgs_audio_v2"
speech_server._adapter = speech_server._get_tts_adapter()
speech_server._adapter._resolve_higgs_audio_v2_processor = mocker.AsyncMock(return_value=object())
req_a = OpenAICreateSpeechRequest(
input="hello",
ref_audio="file:///data/spk.wav",
ref_text="transcript",
)
req_b = OpenAICreateSpeechRequest(
input="hello",
ref_audio="file:///data/spk.wav",
ref_text="transcript",
)
speech_server._adapter._resolve_ref_audio = mocker.AsyncMock(
side_effect=[([0.1] * 48000, 24000, "key_aaa"), ([0.9] * 48000, 24000, "key_bbb")]
)
prompt_a = await speech_server._adapter._build_higgs_audio_v2_params(req_a)
prompt_b = await speech_server._adapter._build_higgs_audio_v2_params(req_b)
assert prompt_a["prompt_token_ids"] == [1, 151700, 151700, 2]
assert prompt_a["prompt_token_ids"] == prompt_b["prompt_token_ids"]
assert (
prompt_a["additional_information"]["audio_input_ids"].shape
== prompt_b["additional_information"]["audio_input_ids"].shape
)
assert not torch.equal(
prompt_a["additional_information"]["audio_input_ids"],
prompt_b["additional_information"]["audio_input_ids"],
)
assert prompt_a["cache_salt"] != prompt_b["cache_salt"]
assert prompt_a["additional_information"]["ref_audio_cache_key"] == "key_aaa"
assert prompt_b["additional_information"]["ref_audio_cache_key"] == "key_bbb"
# ── MossReferenceEncoder: speaker cache invalidation ──
@pytest.mark.asyncio
@@ -13,6 +13,7 @@ from vllm_omni.entrypoints.openai.tts_adapters.base import (
ARTTSAdapter,
PreparedRequest,
apply_max_new_tokens,
conditioning_cache_salt,
resolve_stage_model_path,
)
@@ -55,7 +56,7 @@ class HiggsAudioV2Adapter(ARTTSAdapter):
prompt_token_ids = input_ids_to_python_list(inputs)
return tokens_input(prompt_token_ids=prompt_token_ids)
wav_list, sr, _ = await self._resolve_ref_audio(request.ref_audio)
wav_list, sr, cache_key = await self._resolve_ref_audio(request.ref_audio)
wav = np.asarray(wav_list, dtype=np.float32)
out = await asyncio.to_thread(
build_voice_clone_prompt,
@@ -75,7 +76,9 @@ class HiggsAudioV2Adapter(ARTTSAdapter):
prompt["additional_information"] = {
"audio_input_ids": out["audio_input_ids"],
"audio_input_ids_mask": out["audio_input_ids_mask"],
"ref_audio_cache_key": cache_key,
}
prompt["cache_salt"] = conditioning_cache_salt(request, prompt["additional_information"])
return prompt
async def _resolve_higgs_audio_v2_processor(self):