fix: mask all stop_token_ids in sampling_ids + multi-GPU device support - #1916
fix: mask all stop_token_ids in sampling_ids + multi-GPU device support#1916lonrencn wants to merge 1 commit into
Conversation
sampling_ids: mask ALL stop_token_ids (sos+eos+task_id+fill_token) during ignore_eos window, not just speech_token_size (sos only). Prevents premature EOS prediction with transformers >= 5.0. model.py/frontend.py: use torch.cuda.current_device() instead of hardcoded 'cuda' (defaults to cuda:0), enabling correct multi-GPU operation.
|
FunAudioLLM-side triage/validation on current head What I checked locally: The I also sanity-checked the CPU branch of the new device expression in this environment; |
|
Independent confirmation of the Confirming the mechanism as you describe it: One additional symptom worth recording: an extremely early stop doesn't only produce garbage or near-silence. It can also leave HiFi-GAN's f0 predictor with too few mel frames, surfacing as Being straight about our evidence, since it argues for merging but not for urgency: under correct conditioning we measured 0/64 failures both with and without the fix on an English verified-transcript reference voice. We did see failures (15/64) under a mis-conditioned setup, but that turned out to be a bug in our own harness — a wrong-language reference voice paired with a mismatched transcript — not in CosyVoice, so we don't offer those numbers as evidence about this defect. So our data supports your analysis that this is normally latent and only fires when numerical differences flip EOS to the top — it does not independently demonstrate visible breakage at the default operating point. It's still worth merging: the guard is provably a no-op as written, the fix is one line, and the (We have no data on the multi-GPU half of this PR — we ran single-GPU throughout.) |
Summary
Two bug fixes for CosyVoice3 inference:
sampling_ids()only masksspeech_token_size(sos) duringignore_eos=True, noteosor other stop tokens — on certain transformers versions, the LLM can predict EOS with high confidence as the first token, and the unmasked EOS leaks through theignore_eoswindow, producing garbage output.Hardcoded
torch.device('cuda')defaults tocuda:0— on multi-GPU systems,torch.cuda.set_device()has no effect and models load on the wrong GPU.Changes
cosyvoice/llm/llm.py— sampling_ids fixCosyVoice3LM.stop_token_ids = [speech_token_size + i for i in range(200)]covers sos(6561), eos(6562), task_id(6563), fill_token(6564), etc. The original code only masked indexspeech_token_size(sos=6561), leaving eos(6562) unmasked during the minimum-length window.This is usually harmless because a well-functioning LLM doesn't predict EOS early. But with slight numerical differences across transformers versions (e.g., SDPA mask handling changed between 4.x and 5.x), the logits can shift enough (~0.012) to flip EOS from #2 to #1, causing the model to output garbage.
The fix uses
hasattrto maintain backward compatibility with CosyVoice1/2.cosyvoice/cli/model.py+cosyvoice/cli/frontend.py— multi-GPU fixtorch.device('cuda')always defaults tocuda:0, ignoringtorch.cuda.set_device(). Changed totorch.device(f'cuda:{torch.cuda.current_device()}')in all model classes.Testing
Verified with
Fun-CosyVoice3-0.5B-2512: