From e3c2400abb1ad51b7c60e6fb7adbbcccc8f08965 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 19 Aug 2025 16:23:59 +0800 Subject: [PATCH 01/61] update --- cosyvoice/cli/cosyvoice.py | 42 ++- cosyvoice/cli/model.py | 67 ++++ cosyvoice/hifigan/f0_predictor.py | 45 +++ cosyvoice/hifigan/generator.py | 305 ++++++++++++++---- cosyvoice/transformer/convolution.py | 113 +++++++ .../libritts/cosyvoice3/conf/cosyvoice2.yaml | 234 ++++++++++++++ .../libritts/cosyvoice3/conf/ds_stage2.json | 42 +++ examples/libritts/cosyvoice3/cosyvoice | 1 + examples/libritts/cosyvoice3/local | 1 + examples/libritts/cosyvoice3/path.sh | 1 + examples/libritts/cosyvoice3/run.sh | 111 +++++++ examples/libritts/cosyvoice3/tools | 1 + 12 files changed, 891 insertions(+), 72 deletions(-) create mode 100644 examples/libritts/cosyvoice3/conf/cosyvoice2.yaml create mode 100644 examples/libritts/cosyvoice3/conf/ds_stage2.json create mode 120000 examples/libritts/cosyvoice3/cosyvoice create mode 120000 examples/libritts/cosyvoice3/local create mode 120000 examples/libritts/cosyvoice3/path.sh create mode 100644 examples/libritts/cosyvoice3/run.sh create mode 120000 examples/libritts/cosyvoice3/tools diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index cc443be..f4acba1 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -19,7 +19,7 @@ from hyperpyyaml import load_hyperpyyaml from modelscope import snapshot_download import torch from cosyvoice.cli.frontend import CosyVoiceFrontEnd -from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model +from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model, CosyVoice3Model from cosyvoice.utils.file_utils import logging from cosyvoice.utils.class_utils import get_model_type @@ -192,3 +192,43 @@ class CosyVoice2(CosyVoice): logging.info('yield speech len {}, rtf {}'.format(speech_len, (time.time() - start_time) / speech_len)) yield model_output start_time = time.time() + + +class CosyVoice3(CosyVoice): + + def __init__(self, model_dir, load_jit=False, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): + self.instruct = True if '-Instruct' in model_dir else False + self.model_dir = model_dir + self.fp16 = fp16 + if not os.path.exists(model_dir): + model_dir = snapshot_download(model_dir) + hyper_yaml_path = '{}/cosyvoice3.yaml'.format(model_dir) + if not os.path.exists(hyper_yaml_path): + raise ValueError('{} not found!'.format(hyper_yaml_path)) + with open(hyper_yaml_path, 'r') as f: + configs = load_hyperpyyaml(f, overrides={'qwen_pretrain_path': os.path.join(model_dir, 'CosyVoice-BlankEN')}) + assert get_model_type(configs) == CosyVoice2Model, 'do not use {} for CosyVoice2 initialization!'.format(model_dir) + self.frontend = CosyVoiceFrontEnd(configs['get_tokenizer'], + configs['feat_extractor'], + '{}/campplus.onnx'.format(model_dir), + '{}/speech_tokenizer_v3.onnx'.format(model_dir), + '{}/spk2info.pt'.format(model_dir), + configs['allowed_special']) + self.sample_rate = configs['sample_rate'] + if torch.cuda.is_available() is False and (load_jit is True or load_trt is True or fp16 is True): + load_jit, load_trt, fp16 = False, False, False + logging.warning('no cuda device, set load_jit/load_trt/fp16 to False') + self.model = CosyVoice3Model(configs['llm'], configs['flow'], configs['hift'], fp16) + self.model.load('{}/llm.pt'.format(model_dir), + '{}/flow.pt'.format(model_dir), + '{}/bigvgan.pt'.format(model_dir)) + if load_vllm: + self.model.load_vllm('{}/vllm'.format(model_dir)) + if load_jit: + self.model.load_jit('{}/flow.encoder.{}.zip'.format(model_dir, 'fp16' if self.fp16 is True else 'fp32')) + if load_trt: + self.model.load_trt('{}/flow.decoder.estimator.{}.mygpu.plan'.format(model_dir, 'fp16' if self.fp16 is True else 'fp32'), + '{}/flow.decoder.estimator.fp32.onnx'.format(model_dir), + trt_concurrent, + self.fp16) + del configs diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 9c8ac7e..2b6a918 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -384,3 +384,70 @@ class CosyVoice2Model(CosyVoiceModel): if torch.cuda.is_available(): torch.cuda.empty_cache() torch.cuda.current_stream().synchronize() + + +class CosyVoice3Model(CosyVoice2Model): + + def __init__(self, + llm: torch.nn.Module, + flow: torch.nn.Module, + hift: torch.nn.Module, + fp16: bool = False): + self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + self.llm = llm + self.flow = flow + self.hift = hift + self.fp16 = fp16 + if self.fp16 is True: + self.llm.half() + self.flow.half() + # NOTE must matching training static_chunk_size + self.token_hop_len = 25 + # hift cache + self.mel_cache_len = 8 + self.source_cache_len = int(self.mel_cache_len * 480) + # speech fade in out + self.speech_window = np.hamming(2 * self.source_cache_len) + # rtf and decoding related + self.llm_context = torch.cuda.stream(torch.cuda.Stream(self.device)) if torch.cuda.is_available() else nullcontext() + self.lock = threading.Lock() + # dict used to store session related variable + self.tts_speech_token_dict = {} + self.llm_end_dict = {} + self.hift_cache_dict = {} + + def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): + with torch.cuda.amp.autocast(self.fp16): + tts_mel, _ = self.flow.inference(token=token.to(self.device), + token_len=torch.tensor([token.shape[1]], dtype=torch.int32).to(self.device), + prompt_token=prompt_token.to(self.device), + prompt_token_len=torch.tensor([prompt_token.shape[1]], dtype=torch.int32).to(self.device), + prompt_feat=prompt_feat.to(self.device), + prompt_feat_len=torch.tensor([prompt_feat.shape[1]], dtype=torch.int32).to(self.device), + embedding=embedding.to(self.device), + streaming=stream, + finalize=finalize) + tts_mel = tts_mel[:, :, token_offset * self.flow.token_mel_ratio:] + # append hift cache + if self.hift_cache_dict[uuid] is not None: + hift_cache_mel, hift_cache_source = self.hift_cache_dict[uuid]['mel'], self.hift_cache_dict[uuid]['source'] + tts_mel = torch.concat([hift_cache_mel, tts_mel], dim=2) + else: + hift_cache_source = torch.zeros(1, 1, 0) + # keep overlap mel and hift cache + if finalize is False: + tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel, cache_source=hift_cache_source) + if self.hift_cache_dict[uuid] is not None: + tts_speech = fade_in_out(tts_speech, self.hift_cache_dict[uuid]['speech'], self.speech_window) + self.hift_cache_dict[uuid] = {'mel': tts_mel[:, :, -self.mel_cache_len:], + 'source': tts_source[:, :, -self.source_cache_len:], + 'speech': tts_speech[:, -self.source_cache_len:]} + tts_speech = tts_speech[:, :-self.source_cache_len] + else: + if speed != 1.0: + assert self.hift_cache_dict[uuid] is None, 'speed change only support non-stream inference mode' + tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') + tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel, cache_source=hift_cache_source) + if self.hift_cache_dict[uuid] is not None: + tts_speech = fade_in_out(tts_speech, self.hift_cache_dict[uuid]['speech'], self.speech_window) + return tts_speech \ No newline at end of file diff --git a/cosyvoice/hifigan/f0_predictor.py b/cosyvoice/hifigan/f0_predictor.py index 5797c31..8e55254 100644 --- a/cosyvoice/hifigan/f0_predictor.py +++ b/cosyvoice/hifigan/f0_predictor.py @@ -17,6 +17,7 @@ try: from torch.nn.utils.parametrizations import weight_norm except ImportError: from torch.nn.utils import weight_norm +from cosyvoice.transformer.convolution import CausalConv1d class ConvRNNF0Predictor(nn.Module): @@ -56,3 +57,47 @@ class ConvRNNF0Predictor(nn.Module): x = self.condnet(x) x = x.transpose(1, 2) return torch.abs(self.classifier(x).squeeze(-1)) + + +class CausalConvRNNF0Predictor(nn.Module): + def __init__(self, + num_class: int = 1, + in_channels: int = 80, + cond_channels: int = 512 + ): + super().__init__() + + self.num_class = num_class + self.condnet = nn.Sequential( + weight_norm( + CausalConv1d(in_channels, cond_channels, kernel_size=4, causal_type='right') + ), + nn.ELU(), + weight_norm( + CausalConv1d(cond_channels, cond_channels, kernel_size=3, causal_type='left') + ), + nn.ELU(), + weight_norm( + CausalConv1d(cond_channels, cond_channels, kernel_size=3, causal_type='left') + ), + nn.ELU(), + weight_norm( + CausalConv1d(cond_channels, cond_channels, kernel_size=3, causal_type='left') + ), + nn.ELU(), + weight_norm( + CausalConv1d(cond_channels, cond_channels, kernel_size=3, causal_type='left') + ), + nn.ELU(), + ) + self.classifier = nn.Linear(in_features=cond_channels, out_features=self.num_class) + + def forward(self, x: torch.Tensor, finalize: bool = True) -> torch.Tensor: + if finalize is True: + x = self.condnet[0](x) + else: + x = self.condnet[0](x[:, :, :-self.condnet[0].causal_padding], x[:, :, -self.condnet[0].causal_padding:]) + for i in range(1, len(self.condnet)): + x = self.condnet[i](x) + x = x.transpose(1, 2) + return torch.abs(self.classifier(x).squeeze(-1)) \ No newline at end of file diff --git a/cosyvoice/hifigan/generator.py b/cosyvoice/hifigan/generator.py index 326a1a7..c3f8b1f 100644 --- a/cosyvoice/hifigan/generator.py +++ b/cosyvoice/hifigan/generator.py @@ -28,7 +28,7 @@ try: except ImportError: from torch.nn.utils import weight_norm from torch.distributions.uniform import Uniform - +from cosyvoice.transformer.convolution import CausalConv1d, CausalConv1dDownSample, CausalConv1dUpsample from cosyvoice.transformer.activation import Snake from cosyvoice.utils.common import get_padding from cosyvoice.utils.common import init_weights @@ -50,8 +50,10 @@ class ResBlock(torch.nn.Module): channels: int = 512, kernel_size: int = 3, dilations: List[int] = [1, 3, 5], + causal: bool = False, ): super(ResBlock, self).__init__() + self.causal = causal self.convs1 = nn.ModuleList() self.convs2 = nn.ModuleList() @@ -64,7 +66,14 @@ class ResBlock(torch.nn.Module): kernel_size, 1, dilation=dilation, - padding=get_padding(kernel_size, dilation) + padding=get_padding(kernel_size, dilation)) if causal is False else + CausalConv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation, + causal_type='left' ) ) ) @@ -76,7 +85,14 @@ class ResBlock(torch.nn.Module): kernel_size, 1, dilation=1, - padding=get_padding(kernel_size, 1) + padding=get_padding(kernel_size, 1)) if causal is False else + CausalConv1d( + channels, + channels, + kernel_size, + 1, + dilation=1, + causal_type='left' ) ) ) @@ -171,58 +187,6 @@ class SineGen(torch.nn.Module): return sine_waves, uv, noise -class SourceModuleHnNSF(torch.nn.Module): - """ SourceModule for hn-nsf - SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1, - add_noise_std=0.003, voiced_threshod=0) - sampling_rate: sampling_rate in Hz - harmonic_num: number of harmonic above F0 (default: 0) - sine_amp: amplitude of sine source signal (default: 0.1) - add_noise_std: std of additive Gaussian noise (default: 0.003) - note that amplitude of noise in unvoiced is decided - by sine_amp - voiced_threshold: threhold to set U/V given F0 (default: 0) - Sine_source, noise_source = SourceModuleHnNSF(F0_sampled) - F0_sampled (batchsize, length, 1) - Sine_source (batchsize, length, 1) - noise_source (batchsize, length 1) - uv (batchsize, length, 1) - """ - - def __init__(self, sampling_rate, upsample_scale, harmonic_num=0, sine_amp=0.1, - add_noise_std=0.003, voiced_threshod=0): - super(SourceModuleHnNSF, self).__init__() - - self.sine_amp = sine_amp - self.noise_std = add_noise_std - - # to produce sine waveforms - self.l_sin_gen = SineGen(sampling_rate, harmonic_num, - sine_amp, add_noise_std, voiced_threshod) - - # to merge source harmonics into a single excitation - self.l_linear = torch.nn.Linear(harmonic_num + 1, 1) - self.l_tanh = torch.nn.Tanh() - - def forward(self, x): - """ - Sine_source, noise_source = SourceModuleHnNSF(F0_sampled) - F0_sampled (batchsize, length, 1) - Sine_source (batchsize, length, 1) - noise_source (batchsize, length 1) - """ - # source for harmonic branch - with torch.no_grad(): - sine_wavs, uv, _ = self.l_sin_gen(x.transpose(1, 2)) - sine_wavs = sine_wavs.transpose(1, 2) - uv = uv.transpose(1, 2) - sine_merge = self.l_tanh(self.l_linear(sine_wavs)) - - # source for noise branch, in the same shape as uv - noise = torch.randn_like(uv) * self.sine_amp / 3 - return sine_merge, noise, uv - - class SineGen2(torch.nn.Module): """ Definition of sine generator SineGen(samp_rate, harmonic_num = 0, @@ -242,7 +206,8 @@ class SineGen2(torch.nn.Module): def __init__(self, samp_rate, upsample_scale, harmonic_num=0, sine_amp=0.1, noise_std=0.003, voiced_threshold=0, - flag_for_pulse=False): + flag_for_pulse=False, + causal=False): super(SineGen2, self).__init__() self.sine_amp = sine_amp self.noise_std = noise_std @@ -252,6 +217,11 @@ class SineGen2(torch.nn.Module): self.voiced_threshold = voiced_threshold self.flag_for_pulse = flag_for_pulse self.upsample_scale = upsample_scale + self.causal = causal + if causal is True: + self.rand_ini = torch.rand(1, 9) + self.rand_ini[:, 0] = 0 + self.sine_waves = torch.rand(1, 60 * 16000, 9) def _f02uv(self, f0): # generate uv signal @@ -267,9 +237,12 @@ class SineGen2(torch.nn.Module): rad_values = (f0_values / self.sampling_rate) % 1 # initial phase noise (no noise for fundamental component) - rand_ini = torch.rand(f0_values.shape[0], f0_values.shape[2], device=f0_values.device) - rand_ini[:, 0] = 0 - rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini + if self.training is False and self.causal is True: + rad_values[:, 0, :] = rad_values[:, 0, :] + self.rand_ini.to(rad_values.device) + else: + rand_ini = torch.rand(f0_values.shape[0], f0_values.shape[2], device=f0_values.device) + rand_ini[:, 0] = 0 + rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini # instantanouse phase sine[t] = sin(2*pi \sum_i=1 ^{t} rad) if not self.flag_for_pulse: @@ -279,7 +252,7 @@ class SineGen2(torch.nn.Module): phase = torch.cumsum(rad_values, dim=1) * 2 * np.pi phase = torch.nn.functional.interpolate(phase.transpose(1, 2) * self.upsample_scale, - scale_factor=self.upsample_scale, mode="linear").transpose(1, 2) + scale_factor=self.upsample_scale, mode="nearest" if self.causal is True else 'linear').transpose(1, 2) sines = torch.sin(phase) else: # If necessary, make sure that the first time step of every @@ -331,7 +304,10 @@ class SineGen2(torch.nn.Module): # std = self.sine_amp/3 -> max value ~ self.sine_amp # . for voiced regions is self.noise_std noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3 - noise = noise_amp * torch.randn_like(sine_waves) + if self.training is False and self.causal is True: + noise = noise_amp * self.sine_waves[:, :sine_waves.shape[1]].to(sine_waves.device) + else: + noise = noise_amp * torch.randn_like(sine_waves) # first: set the unvoiced part to 0 by uv # then: additive noise @@ -339,7 +315,7 @@ class SineGen2(torch.nn.Module): return sine_waves, uv, noise -class SourceModuleHnNSF2(torch.nn.Module): +class SourceModuleHnNSF(torch.nn.Module): """ SourceModule for hn-nsf SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1, add_noise_std=0.003, voiced_threshod=0) @@ -358,19 +334,26 @@ class SourceModuleHnNSF2(torch.nn.Module): """ def __init__(self, sampling_rate, upsample_scale, harmonic_num=0, sine_amp=0.1, - add_noise_std=0.003, voiced_threshod=0): - super(SourceModuleHnNSF2, self).__init__() + add_noise_std=0.003, voiced_threshod=0, sinegen_type='1', causal=False): + super(SourceModuleHnNSF, self).__init__() self.sine_amp = sine_amp self.noise_std = add_noise_std # to produce sine waveforms - self.l_sin_gen = SineGen2(sampling_rate, upsample_scale, harmonic_num, - sine_amp, add_noise_std, voiced_threshod) + if sinegen_type == '1': + self.l_sin_gen = SineGen(sampling_rate, harmonic_num, + sine_amp, add_noise_std, voiced_threshod) + else: + self.l_sin_gen = SineGen2(sampling_rate, upsample_scale, harmonic_num, + sine_amp, add_noise_std, voiced_threshod, causal=causal) # to merge source harmonics into a single excitation self.l_linear = torch.nn.Linear(harmonic_num + 1, 1) self.l_tanh = torch.nn.Tanh() + self.causal = causal + if causal is True: + self.uv = torch.rand(1, 60 * 24000, 1) def forward(self, x): """ @@ -385,7 +368,10 @@ class SourceModuleHnNSF2(torch.nn.Module): sine_merge = self.l_tanh(self.l_linear(sine_wavs)) # source for noise branch, in the same shape as uv - noise = torch.randn_like(uv) * self.sine_amp / 3 + if self.training is False and self.causal is True: + noise = self.uv[:, :uv.shape[1]] * self.sine_amp / 3 + else: + noise = torch.randn_like(uv) * self.sine_amp / 3 return sine_merge, noise, uv @@ -425,15 +411,16 @@ class HiFTGenerator(nn.Module): self.num_kernels = len(resblock_kernel_sizes) self.num_upsamples = len(upsample_rates) - # NOTE in CosyVoice2, we use the original SourceModuleHnNSF implementation - this_SourceModuleHnNSF = SourceModuleHnNSF if self.sampling_rate == 22050 else SourceModuleHnNSF2 - self.m_source = this_SourceModuleHnNSF( + # NOTE in CosyVoice2, we use the original SineGen implementation + self.m_source = SourceModuleHnNSF( sampling_rate=sampling_rate, upsample_scale=np.prod(upsample_rates) * istft_params["hop_len"], harmonic_num=nb_harmonics, sine_amp=nsf_alpha, add_noise_std=nsf_sigma, - voiced_threshod=nsf_voiced_threshold) + voiced_threshod=nsf_voiced_threshold, + sinegen_type='1' if self.sampling_rate == 22050 else '2', + causal=False) self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates) * istft_params["hop_len"]) self.conv_pre = weight_norm( @@ -580,3 +567,179 @@ class HiFTGenerator(nn.Module): s[:, :, :cache_source.shape[2]] = cache_source generated_speech = self.decode(x=speech_feat, s=s) return generated_speech, s + + +class CausalHiFTGenerator(HiFTGenerator): + """ + HiFTNet Generator: Neural Source Filter + ISTFTNet + https://arxiv.org/abs/2309.09493 + """ + def __init__( + self, + in_channels: int = 80, + base_channels: int = 512, + nb_harmonics: int = 8, + sampling_rate: int = 22050, + nsf_alpha: float = 0.1, + nsf_sigma: float = 0.003, + nsf_voiced_threshold: float = 10, + upsample_rates: List[int] = [8, 8], + upsample_kernel_sizes: List[int] = [16, 16], + istft_params: Dict[str, int] = {"n_fft": 16, "hop_len": 4}, + resblock_kernel_sizes: List[int] = [3, 7, 11], + resblock_dilation_sizes: List[List[int]] = [[1, 3, 5], [1, 3, 5], [1, 3, 5]], + source_resblock_kernel_sizes: List[int] = [7, 11], + source_resblock_dilation_sizes: List[List[int]] = [[1, 3, 5], [1, 3, 5]], + lrelu_slope: float = 0.1, + audio_limit: float = 0.99, + conv_pre_look_right: int = 4, + f0_predictor: torch.nn.Module = None, + ): + torch.nn.Module.__init__(self) + + self.out_channels = 1 + self.nb_harmonics = nb_harmonics + self.sampling_rate = sampling_rate + self.istft_params = istft_params + self.lrelu_slope = lrelu_slope + self.audio_limit = audio_limit + + self.num_kernels = len(resblock_kernel_sizes) + self.num_upsamples = len(upsample_rates) + self.m_source = SourceModuleHnNSF( + sampling_rate=sampling_rate, + upsample_scale=np.prod(upsample_rates) * istft_params["hop_len"], + harmonic_num=nb_harmonics, + sine_amp=nsf_alpha, + add_noise_std=nsf_sigma, + voiced_threshod=nsf_voiced_threshold, + sinegen_type='1' if self.sampling_rate == 22050 else '2', + causal=True) + self.upsample_rates = upsample_rates + self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates) * istft_params["hop_len"]) + + self.conv_pre = weight_norm( + CausalConv1d(in_channels, base_channels, conv_pre_look_right + 1, 1, causal_type='right') + ) + + # Up + self.ups = nn.ModuleList() + for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)): + self.ups.append( + weight_norm( + CausalConv1dUpsample( + base_channels // (2**i), + base_channels // (2**(i + 1)), + k, + u, + ) + ) + ) + + # Down + self.source_downs = nn.ModuleList() + self.source_resblocks = nn.ModuleList() + downsample_rates = [1] + upsample_rates[::-1][:-1] + downsample_cum_rates = np.cumprod(downsample_rates) + for i, (u, k, d) in enumerate(zip(downsample_cum_rates[::-1], source_resblock_kernel_sizes, source_resblock_dilation_sizes)): + if u == 1: + self.source_downs.append( + CausalConv1d(istft_params["n_fft"] + 2, base_channels // (2 ** (i + 1)), 1, 1, causal_type='left') + ) + else: + self.source_downs.append( + CausalConv1dDownSample(istft_params["n_fft"] + 2, base_channels // (2 ** (i + 1)), u * 2, u) + ) + + self.source_resblocks.append( + ResBlock(base_channels // (2 ** (i + 1)), k, d, causal=True) + ) + + self.resblocks = nn.ModuleList() + for i in range(len(self.ups)): + ch = base_channels // (2**(i + 1)) + for _, (k, d) in enumerate(zip(resblock_kernel_sizes, resblock_dilation_sizes)): + self.resblocks.append(ResBlock(ch, k, d, causal=True)) + + self.conv_post = weight_norm(CausalConv1d(ch, istft_params["n_fft"] + 2, 7, 1, causal_type='left')) + self.ups.apply(init_weights) + self.conv_post.apply(init_weights) + self.reflection_pad = nn.ReflectionPad1d((1, 0)) + self.stft_window = torch.from_numpy(get_window("hann", istft_params["n_fft"], fftbins=True).astype(np.float32)) + self.conv_pre_look_right = conv_pre_look_right + self.f0_predictor = f0_predictor + + def decode(self, x: torch.Tensor, s: torch.Tensor = torch.zeros(1, 1, 0), finalize: bool = True) -> torch.Tensor: + s_stft_real, s_stft_imag = self._stft(s.squeeze(1)) + if finalize is True: + x = self.conv_pre(x) + else: + x = self.conv_pre(x[:, :, :-self.conv_pre_look_right], x[:, :, -self.conv_pre_look_right:]) + s_stft_real, s_stft_imag = s_stft_real[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)], s_stft_imag[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)] + s_stft = torch.cat([s_stft_real, s_stft_imag], dim=1) + + for i in range(self.num_upsamples): + x = F.leaky_relu(x, self.lrelu_slope) + x = self.ups[i](x) + + if i == self.num_upsamples - 1: + x = self.reflection_pad(x) + + # fusion + si = self.source_downs[i](s_stft) + si = self.source_resblocks[i](si) + x = x + si + + xs = None + for j in range(self.num_kernels): + if xs is None: + xs = self.resblocks[i * self.num_kernels + j](x) + else: + xs += self.resblocks[i * self.num_kernels + j](x) + x = xs / self.num_kernels + + x = F.leaky_relu(x) + x = self.conv_post(x) + magnitude = torch.exp(x[:, :self.istft_params["n_fft"] // 2 + 1, :]) + phase = torch.sin(x[:, self.istft_params["n_fft"] // 2 + 1:, :]) # actually, sin is redundancy + + x = self._istft(magnitude, phase) + if finalize is False: + x = x[:, :-int(np.prod(self.upsample_rates) * self.istft_params['hop_len'])] + x = torch.clamp(x, -self.audio_limit, self.audio_limit) + return x + + @torch.inference_mode() + def inference(self, speech_feat: torch.Tensor, finalize: bool = True) -> torch.Tensor: + # mel->f0 + self.f0_predictor.to('cpu') + f0 = self.f0_predictor(speech_feat.cpu(), finalize=finalize).to(speech_feat) + # f0->source + s = self.f0_upsamp(f0[:, None]).transpose(1, 2) # bs,n,t + s, _, _ = self.m_source(s) + s = s.transpose(1, 2) + if finalize is True: + generated_speech = self.decode(x=speech_feat, s=s, finalize=finalize) + else: + generated_speech = self.decode(x=speech_feat[:, :, :-self.f0_predictor.condnet[0].causal_padding], s=s, finalize=finalize) + return generated_speech, s + + +if __name__ == '__main__': + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + from hyperpyyaml import load_hyperpyyaml + with open('./pretrained_models/CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: + configs = load_hyperpyyaml(f, overrides={'llm': None, 'flow': None}) + model = configs['hift'] + device = 'cuda' if torch.cuda.is_available() else 'cpu' + model.to(device) + model.eval() + max_len, chunk_size, context_size = 300, 30, 8 + mel = torch.rand(1, 80, max_len) + pred_gt, _ = model.inference(mel) + for i in range(0, max_len, chunk_size): + finalize = True if i + chunk_size + context_size >= max_len else False + pred_chunk, _ = model.inference(mel[:, :, : i + chunk_size + context_size], finalize=finalize) + pred_chunk = pred_chunk[:, i * 480:] + print((pred_gt[:, i * 480:i * 480 + pred_chunk.shape[1]] - pred_chunk).abs().max().item()) \ No newline at end of file diff --git a/cosyvoice/transformer/convolution.py b/cosyvoice/transformer/convolution.py index 4d5d961..2dc9116 100644 --- a/cosyvoice/transformer/convolution.py +++ b/cosyvoice/transformer/convolution.py @@ -19,6 +19,7 @@ from typing import Tuple import torch from torch import nn +import torch.nn.functional as F class ConvolutionModule(nn.Module): @@ -143,3 +144,115 @@ class ConvolutionModule(nn.Module): x.masked_fill_(~mask_pad, 0.0) return x.transpose(1, 2), new_cache + + +# NOTE(Xiang Lyu) causal conv module used in convolution-based vocoder +class CausalConv1d(torch.nn.Conv1d): + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + padding_mode: str = 'zeros', + causal_type: str = 'left', + device=None, + dtype=None + ) -> None: + super(CausalConv1d, self).__init__(in_channels, out_channels, + kernel_size, stride=1, + padding=0, dilation=dilation, + groups=groups, bias=bias, + padding_mode=padding_mode, + device=device, dtype=dtype) + assert stride == 1 + self.causal_padding = int((kernel_size * dilation - dilation) / 2) * 2 + (kernel_size + 1) % 2 + assert causal_type in ['left', 'right'] + self.causal_type = causal_type + + def forward(self, x: torch.Tensor, cache: torch.Tensor = torch.zeros(0, 0, 0)) -> Tuple[torch.Tensor]: + input_timestep = x.shape[2] + if cache.size(2) == 0: + cache = torch.zeros(x.shape[0], x.shape[1], self.causal_padding).to(x) + assert cache.size(2) == self.causal_padding + if self.causal_type == 'left': + x = torch.concat([cache, x], dim=2) + else: + x = torch.concat([x, cache], dim=2) + x = super(CausalConv1d, self).forward(x) + assert x.shape[2] == input_timestep + return x + + +class CausalConv1dDownSample(torch.nn.Conv1d): + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + padding_mode: str = 'zeros', + device=None, + dtype=None + ) -> None: + super(CausalConv1dDownSample, self).__init__(in_channels, out_channels, + kernel_size, stride, + padding=0, dilation=dilation, + groups=groups, bias=bias, + padding_mode=padding_mode, + device=device, dtype=dtype) + assert stride != 1 and dilation == 1 + assert kernel_size % stride == 0 + self.causal_padding = stride - 1 + + def forward(self, x: torch.Tensor, cache: torch.Tensor = torch.zeros(0, 0, 0)) -> Tuple[torch.Tensor, torch.Tensor]: + if cache.size(2) == 0: + x = F.pad(x, (self.causal_padding, 0), value=0.0) + else: + assert cache.size(2) == self.causal_padding + x = torch.concat([cache, x], dim=2) + x = super(CausalConv1dDownSample, self).forward(x) + return x + + +class CausalConv1dUpsample(torch.nn.Conv1d): + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + padding_mode: str = 'zeros', + device=None, + dtype=None + ) -> None: + super(CausalConv1dUpsample, self).__init__(in_channels, out_channels, + kernel_size, 1, + padding=0, dilation=dilation, + groups=groups, bias=bias, + padding_mode=padding_mode, + device=device, dtype=dtype) + assert dilation == 1 + self.causal_padding = kernel_size - 1 + self.upsample = torch.nn.Upsample(scale_factor=stride, mode='nearest') + + def forward(self, x: torch.Tensor, cache: torch.Tensor = torch.zeros(0, 0, 0)) -> Tuple[torch.Tensor, torch.Tensor]: + x = self.upsample(x) + input_timestep = x.shape[2] + if cache.size(2) == 0: + x = F.pad(x, (self.causal_padding, 0), value=0.0) + else: + assert cache.size(2) == self.causal_padding + x = torch.concat([cache, x], dim=2) + x = super(CausalConv1dUpsample, self).forward(x) + assert input_timestep == x.shape[2] + return x \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice2.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice2.yaml new file mode 100644 index 0000000..df36109 --- /dev/null +++ b/examples/libritts/cosyvoice3/conf/cosyvoice2.yaml @@ -0,0 +1,234 @@ +# set random seed, so that you may reproduce your result. +__set_seed1: !apply:random.seed [1986] +__set_seed2: !apply:numpy.random.seed [1986] +__set_seed3: !apply:torch.manual_seed [1986] +__set_seed4: !apply:torch.cuda.manual_seed_all [1986] + +# fixed params +sample_rate: 24000 +llm_input_size: 896 +llm_output_size: 896 +spk_embed_dim: 192 +qwen_pretrain_path: '' +token_frame_rate: 25 +token_mel_ratio: 2 + +# stream related params +chunk_size: 25 # streaming inference chunk size, in token +num_decoding_left_chunks: -1 # streaming inference flow decoder left chunk size, <0 means use all left chunks + +# model params +# for all class/function included in this repo, we use ! or ! for intialization, so that user may find all corresponding class/function according to one single yaml. +# for system/third_party class/function, we do not require this. +llm: !new:cosyvoice.llm.llm.Qwen2LM + llm_input_size: !ref + llm_output_size: !ref + speech_token_size: 6561 + length_normalized_loss: True + lsm_weight: 0 + mix_ratio: [5, 15] + llm: !new:cosyvoice.llm.llm.Qwen2Encoder + pretrain_path: !ref + sampling: !name:cosyvoice.utils.common.ras_sampling + top_p: 0.8 + top_k: 25 + win_size: 10 + tau_r: 0.1 + +flow: !new:cosyvoice.flow.flow.CausalMaskedDiffWithXvec + input_size: 512 + output_size: 80 + spk_embed_dim: !ref + output_type: 'mel' + vocab_size: 6561 + input_frame_rate: !ref + only_mask_loss: True + token_mel_ratio: !ref + pre_lookahead_len: 3 + encoder: !new:cosyvoice.transformer.upsample_encoder.UpsampleConformerEncoder + output_size: 512 + attention_heads: 8 + linear_units: 2048 + num_blocks: 6 + dropout_rate: 0.1 + positional_dropout_rate: 0.1 + attention_dropout_rate: 0.1 + normalize_before: True + input_layer: 'linear' + pos_enc_layer_type: 'rel_pos_espnet' + selfattention_layer_type: 'rel_selfattn' + input_size: 512 + use_cnn_module: False + macaron_style: False + static_chunk_size: !ref + decoder: !new:cosyvoice.flow.flow_matching.CausalConditionalCFM + in_channels: 240 + n_spks: 1 + spk_emb_dim: 80 + cfm_params: !new:omegaconf.DictConfig + content: + sigma_min: 1e-06 + solver: 'euler' + t_scheduler: 'cosine' + training_cfg_rate: 0.2 + inference_cfg_rate: 0.7 + reg_loss_type: 'l1' + estimator: !new:cosyvoice.flow.decoder.CausalConditionalDecoder + in_channels: 320 + out_channels: 80 + channels: [256] + dropout: 0.0 + attention_head_dim: 64 + n_blocks: 4 + num_mid_blocks: 12 + num_heads: 8 + act_fn: 'gelu' + static_chunk_size: !ref * + num_decoding_left_chunks: !ref + +hift: !new:cosyvoice.hifigan.generator.HiFTGenerator + in_channels: 80 + base_channels: 512 + nb_harmonics: 8 + sampling_rate: !ref + nsf_alpha: 0.1 + nsf_sigma: 0.003 + nsf_voiced_threshold: 10 + upsample_rates: [8, 5, 3] + upsample_kernel_sizes: [16, 11, 7] + istft_params: + n_fft: 16 + hop_len: 4 + resblock_kernel_sizes: [3, 7, 11] + resblock_dilation_sizes: [[1, 3, 5], [1, 3, 5], [1, 3, 5]] + source_resblock_kernel_sizes: [7, 7, 11] + source_resblock_dilation_sizes: [[1, 3, 5], [1, 3, 5], [1, 3, 5]] + lrelu_slope: 0.1 + audio_limit: 0.99 + f0_predictor: !new:cosyvoice.hifigan.f0_predictor.ConvRNNF0Predictor + num_class: 1 + in_channels: 80 + cond_channels: 512 + +# gan related module +mel_spec_transform1: !name:matcha.utils.audio.mel_spectrogram + n_fft: 1920 + num_mels: 80 + sampling_rate: !ref + hop_size: 480 + win_size: 1920 + fmin: 0 + fmax: null + center: False +hifigan: !new:cosyvoice.hifigan.hifigan.HiFiGan + generator: !ref + discriminator: !new:cosyvoice.hifigan.discriminator.MultipleDiscriminator + mpd: !new:matcha.hifigan.models.MultiPeriodDiscriminator + mrd: !new:cosyvoice.hifigan.discriminator.MultiResSpecDiscriminator + mel_spec_transform: [ + !ref + ] + +# processor functions +parquet_opener: !name:cosyvoice.dataset.processor.parquet_opener +get_tokenizer: !name:cosyvoice.tokenizer.tokenizer.get_qwen_tokenizer + token_path: !ref + skip_special_tokens: True +allowed_special: 'all' +tokenize: !name:cosyvoice.dataset.processor.tokenize + get_tokenizer: !ref + allowed_special: !ref +filter: !name:cosyvoice.dataset.processor.filter + max_length: 40960 + min_length: 100 + token_max_length: 200 + token_min_length: 1 +resample: !name:cosyvoice.dataset.processor.resample + resample_rate: !ref +truncate: !name:cosyvoice.dataset.processor.truncate + truncate_length: 24480 # must be a multiplier of hop_size +feat_extractor: !name:matcha.utils.audio.mel_spectrogram + n_fft: 1920 + num_mels: 80 + sampling_rate: !ref + hop_size: 480 + win_size: 1920 + fmin: 0 + fmax: 8000 + center: False +compute_fbank: !name:cosyvoice.dataset.processor.compute_fbank + feat_extractor: !ref + token_mel_ratio: 2 +compute_f0: !name:cosyvoice.dataset.processor.compute_f0 + sample_rate: !ref + hop_size: 480 +parse_embedding: !name:cosyvoice.dataset.processor.parse_embedding + normalize: True +shuffle: !name:cosyvoice.dataset.processor.shuffle + shuffle_size: 1000 +sort: !name:cosyvoice.dataset.processor.sort + sort_size: 500 # sort_size should be less than shuffle_size +batch: !name:cosyvoice.dataset.processor.batch + batch_type: 'dynamic' + max_frames_in_batch: 2000 +padding: !name:cosyvoice.dataset.processor.padding + use_spk_embedding: False # change to True during sft + + +# dataset processor pipeline +data_pipeline: [ + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , +] +data_pipeline_gan: [ + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , + !ref , +] + +# llm flow train conf +train_conf: + optim: adam + optim_conf: + lr: 1e-5 # change to 1e-5 during sft + scheduler: constantlr # change to constantlr during sft + scheduler_conf: + warmup_steps: 2500 + max_epoch: 200 + grad_clip: 5 + accum_grad: 2 + log_interval: 100 + save_per_step: -1 + +# gan train conf +train_conf_gan: + optim: adam + optim_conf: + lr: 0.0002 # use small lr for gan training + scheduler: constantlr + optim_d: adam + optim_conf_d: + lr: 0.0002 # use small lr for gan training + scheduler_d: constantlr + max_epoch: 200 + grad_clip: 5 + accum_grad: 1 # in gan training, accum_grad must be 1 + log_interval: 100 + save_per_step: -1 \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/conf/ds_stage2.json b/examples/libritts/cosyvoice3/conf/ds_stage2.json new file mode 100644 index 0000000..2b2de3d --- /dev/null +++ b/examples/libritts/cosyvoice3/conf/ds_stage2.json @@ -0,0 +1,42 @@ +{ + "train_micro_batch_size_per_gpu": 1, + "gradient_accumulation_steps": 1, + "steps_per_print": 100, + "gradient_clipping": 5, + "fp16": { + "enabled": false, + "auto_cast": false, + "loss_scale": 0, + "initial_scale_power": 16, + "loss_scale_window": 256, + "hysteresis": 2, + "consecutive_hysteresis": false, + "min_loss_scale": 1 + }, + "bf16": { + "enabled": false + }, + "zero_force_ds_cpu_optimizer": false, + "zero_optimization": { + "stage": 2, + "offload_optimizer": { + "device": "none", + "pin_memory": true + }, + "allgather_partitions": true, + "allgather_bucket_size": 5e8, + "overlap_comm": false, + "reduce_scatter": true, + "reduce_bucket_size": 5e8, + "contiguous_gradients" : true + }, + "optimizer": { + "type": "AdamW", + "params": { + "lr": 0.001, + "weight_decay": 0.0001, + "torch_adam": true, + "adam_w_mode": true + } + } +} \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/cosyvoice b/examples/libritts/cosyvoice3/cosyvoice new file mode 120000 index 0000000..3903806 --- /dev/null +++ b/examples/libritts/cosyvoice3/cosyvoice @@ -0,0 +1 @@ +../../../cosyvoice \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/local b/examples/libritts/cosyvoice3/local new file mode 120000 index 0000000..5e847a1 --- /dev/null +++ b/examples/libritts/cosyvoice3/local @@ -0,0 +1 @@ +../cosyvoice/local \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/path.sh b/examples/libritts/cosyvoice3/path.sh new file mode 120000 index 0000000..59f7179 --- /dev/null +++ b/examples/libritts/cosyvoice3/path.sh @@ -0,0 +1 @@ +../cosyvoice/path.sh \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/run.sh b/examples/libritts/cosyvoice3/run.sh new file mode 100644 index 0000000..ad59c0a --- /dev/null +++ b/examples/libritts/cosyvoice3/run.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# Copyright 2024 Alibaba Inc. All Rights Reserved. +. ./path.sh || exit 1; + +stage=-1 +stop_stage=3 + +data_url=www.openslr.org/resources/60 +data_dir=/mnt/lyuxiang.lx/data/tts/openslr/libritts +pretrained_model_dir=../../../pretrained_models/CosyVoice2-0.5B + +if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then + echo "Data Download" + for part in dev-clean test-clean dev-other test-other train-clean-100 train-clean-360 train-other-500; do + local/download_and_untar.sh ${data_dir} ${data_url} ${part} + done +fi + +if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then + echo "Data preparation, prepare wav.scp/text/utt2spk/spk2utt" + for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do + mkdir -p data/$x + python local/prepare_data.py --src_dir $data_dir/LibriTTS/$x --des_dir data/$x + done +fi + +if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then + echo "Extract campplus speaker embedding, you will get spk2embedding.pt and utt2embedding.pt in data/$x dir" + for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do + tools/extract_embedding.py --dir data/$x \ + --onnx_path $pretrained_model_dir/campplus.onnx + done +fi + +if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then + echo "Extract discrete speech token, you will get utt2speech_token.pt in data/$x dir" + for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do + tools/extract_speech_token.py --dir data/$x \ + --onnx_path $pretrained_model_dir/speech_tokenizer_v2.onnx + done +fi + +if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then + echo "Prepare required parquet format data, you should have prepared wav.scp/text/utt2spk/spk2utt/utt2embedding.pt/spk2embedding.pt/utt2speech_token.pt" + for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do + mkdir -p data/$x/parquet + tools/make_parquet_list.py --num_utts_per_parquet 1000 \ + --num_processes 10 \ + --src_dir data/$x \ + --des_dir data/$x/parquet + done +fi + +# train llm +export CUDA_VISIBLE_DEVICES="0,1,2,3" +num_gpus=$(echo $CUDA_VISIBLE_DEVICES | awk -F "," '{print NF}') +job_id=1986 +dist_backend="nccl" +num_workers=2 +prefetch=100 +train_engine=torch_ddp +if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then + echo "Run train. We only support llm traning for now" + if [ $train_engine == 'deepspeed' ]; then + echo "Notice deepspeed has its own optimizer config. Modify conf/ds_stage2.json if necessary" + fi + cat data/{train-clean-100,train-clean-360,train-other-500}/parquet/data.list > data/train.data.list + cat data/{dev-clean,dev-other}/parquet/data.list > data/dev.data.list + # NOTE will update llm/hift training later + for model in llm flow hifigan; do + torchrun --nnodes=1 --nproc_per_node=$num_gpus \ + --rdzv_id=$job_id --rdzv_backend="c10d" --rdzv_endpoint="localhost:1234" \ + cosyvoice/bin/train.py \ + --train_engine $train_engine \ + --config conf/cosyvoice2.yaml \ + --train_data data/train.data.list \ + --cv_data data/dev.data.list \ + --qwen_pretrain_path $pretrained_model_dir/CosyVoice-BlankEN \ + --model $model \ + --checkpoint $pretrained_model_dir/$model.pt \ + --model_dir `pwd`/exp/cosyvoice2/$model/$train_engine \ + --tensorboard_dir `pwd`/tensorboard/cosyvoice2/$model/$train_engine \ + --ddp.dist_backend $dist_backend \ + --num_workers ${num_workers} \ + --prefetch ${prefetch} \ + --pin_memory \ + --use_amp \ + --deepspeed_config ./conf/ds_stage2.json \ + --deepspeed.save_states model+optimizer + done +fi + +# average model +average_num=5 +if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then + for model in llm flow hifigan; do + decode_checkpoint=`pwd`/exp/cosyvoice/$model/$train_engine/${model}.pt + echo "do model average and final checkpoint is $decode_checkpoint" + python cosyvoice/bin/average_model.py \ + --dst_model $decode_checkpoint \ + --src_path `pwd`/exp/cosyvoice/$model/$train_engine \ + --num ${average_num} \ + --val_best + done +fi + +if [ ${stage} -le 7 ] && [ ${stop_stage} -ge 7 ]; then + echo "Export your model for inference speedup. Remember copy your llm or flow model to model_dir" + python cosyvoice/bin/export_jit.py --model_dir $pretrained_model_dir + python cosyvoice/bin/export_onnx.py --model_dir $pretrained_model_dir +fi \ No newline at end of file diff --git a/examples/libritts/cosyvoice3/tools b/examples/libritts/cosyvoice3/tools new file mode 120000 index 0000000..c92f417 --- /dev/null +++ b/examples/libritts/cosyvoice3/tools @@ -0,0 +1 @@ +../../../tools \ No newline at end of file From da41f6175bc1d3c245630e915e8512a03ffbdd6c Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 19 Aug 2025 18:53:18 +0800 Subject: [PATCH 02/61] update --- cosyvoice/flow/DiT/dit_model.py | 208 ++++++++ cosyvoice/flow/DiT/dit_modules.py | 615 ++++++++++++++++++++++ cosyvoice/flow/flow.py | 165 +++++- cosyvoice/hifigan/generator.py | 2 +- cosyvoice/transformer/upsample_encoder.py | 9 +- 5 files changed, 986 insertions(+), 13 deletions(-) create mode 100644 cosyvoice/flow/DiT/dit_model.py create mode 100644 cosyvoice/flow/DiT/dit_modules.py diff --git a/cosyvoice/flow/DiT/dit_model.py b/cosyvoice/flow/DiT/dit_model.py new file mode 100644 index 0000000..ada9392 --- /dev/null +++ b/cosyvoice/flow/DiT/dit_model.py @@ -0,0 +1,208 @@ +""" +ein notation: +b - batch +n - sequence +nt - text sequence +nw - raw wave length +d - dimension +""" + +from __future__ import annotations + +import torch +from torch import nn +import torch.nn.functional as F +from einops import repeat +from x_transformers.x_transformers import RotaryEmbedding +from funasr.models.transformer.utils.mask import causal_block_mask + +from cosyvoice.flow.DiT.dit_modules import ( + TimestepEmbedding, + ConvNeXtV2Block, + CausalConvPositionEmbedding, + DiTBlock, + AdaLayerNormZero_Final, + precompute_freqs_cis, + get_pos_embed_indices, +) + + +# Text embedding + + +class TextEmbedding(nn.Module): + def __init__(self, text_num_embeds, text_dim, conv_layers=0, conv_mult=2): + super().__init__() + self.text_embed = nn.Embedding(text_num_embeds + 1, text_dim) # use 0 as filler token + + if conv_layers > 0: + self.extra_modeling = True + self.precompute_max_pos = 4096 # ~44s of 24khz audio + self.register_buffer("freqs_cis", precompute_freqs_cis(text_dim, self.precompute_max_pos), persistent=False) + self.text_blocks = nn.Sequential( + *[ConvNeXtV2Block(text_dim, text_dim * conv_mult) for _ in range(conv_layers)] + ) + else: + self.extra_modeling = False + + def forward(self, text: int["b nt"], seq_len, drop_text=False): # noqa: F722 + batch, text_len = text.shape[0], text.shape[1] + text = text + 1 # use 0 as filler token. preprocess of batch pad -1, see list_str_to_idx() + text = text[:, :seq_len] # curtail if character tokens are more than the mel spec tokens + text = F.pad(text, (0, seq_len - text_len), value=0) + + if drop_text: # cfg for text + text = torch.zeros_like(text) + + text = self.text_embed(text) # b n -> b n d + + # possible extra modeling + if self.extra_modeling: + # sinus pos emb + batch_start = torch.zeros((batch,), dtype=torch.long) + pos_idx = get_pos_embed_indices(batch_start, seq_len, max_pos=self.precompute_max_pos) + text_pos_embed = self.freqs_cis[pos_idx] + text = text + text_pos_embed + + # convnextv2 blocks + text = self.text_blocks(text) + + return text + + +# noised input audio and context mixing embedding + + +class InputEmbedding(nn.Module): + def __init__(self, mel_dim, text_dim, out_dim, spk_dim=None): + super().__init__() + spk_dim = 0 if spk_dim is None else spk_dim + self.spk_dim = spk_dim + self.proj = nn.Linear(mel_dim * 2 + text_dim + spk_dim, out_dim) + self.conv_pos_embed = CausalConvPositionEmbedding(dim=out_dim) + + def forward( + self, + x: float["b n d"], + cond: float["b n d"], + text_embed: float["b n d"], + spks: float["b d"], + ): + to_cat = [x, cond, text_embed] + if self.spk_dim > 0: + spks = repeat(spks, "b c -> b t c", t=x.shape[1]) + to_cat.append(spks) + + x = self.proj(torch.cat(to_cat, dim=-1)) + x = self.conv_pos_embed(x) + x + return x + + +# Transformer backbone using DiT blocks + + +class DiT(nn.Module): + def __init__( + self, + *, + dim, + depth=8, + heads=8, + dim_head=64, + dropout=0.1, + ff_mult=4, + mel_dim=80, + mu_dim=None, + long_skip_connection=False, + spk_dim=None, + **kwargs + ): + super().__init__() + + self.time_embed = TimestepEmbedding(dim) + if mu_dim is None: + mu_dim = mel_dim + self.input_embed = InputEmbedding(mel_dim, mu_dim, dim, spk_dim) + + self.rotary_embed = RotaryEmbedding(dim_head) + + self.dim = dim + self.depth = depth + + self.transformer_blocks = nn.ModuleList( + [DiTBlock(dim=dim, heads=heads, dim_head=dim_head, ff_mult=ff_mult, dropout=dropout) for _ in range(depth)] + ) + self.long_skip_connection = nn.Linear(dim * 2, dim, bias=False) if long_skip_connection else None + + self.norm_out = AdaLayerNormZero_Final(dim) # final modulation + self.proj_out = nn.Linear(dim, mel_dim) + self.causal_mask_type = kwargs.get("causal_mask_type", None) + + def build_mix_causal_mask(self, attn_mask, rand=None, ratio=None): + b, _, _, t = attn_mask.shape + if rand is None: + rand = torch.rand((b, 1, 1, 1), device=attn_mask.device, dtype=torch.float32) + mixed_mask = attn_mask.clone() + for item in self.causal_mask_type: + prob_min, prob_max = item["prob_min"], item["prob_max"] + _ratio = 1 + if "ratio" in item: + _ratio = item["ratio"] + if ratio is not None: + _ratio = ratio + block_size = item["block_size"] * _ratio + if block_size <= 0: + causal_mask = attn_mask + else: + causal_mask = causal_block_mask( + t, block_size, attn_mask.device, torch.float32 + ).unsqueeze(0).unsqueeze(1) # 1,1,T,T + flag = (prob_min <= rand) & (rand < prob_max) + mixed_mask = mixed_mask * (~flag) + (causal_mask * attn_mask) * flag + + return mixed_mask + + def forward( + self, + x: float["b n d"], # nosied input audio + cond: float["b n d"], # masked cond audio + mu: int["b nt d"], # mu + spks: float["b 1 d"], # spk xvec + time: float["b"] | float[""], # time step + return_hidden: bool = False, + mask: bool["b 1 n"] | None = None, + mask_rand: float["b 1 1"] = None, # for mask flag type + **kwargs, + ): + batch, seq_len = x.shape[0], x.shape[1] + if time.ndim == 0: + time = time.repeat(batch) + + # t: conditioning time, c: context (text + masked cond audio), x: noised input audio + t = self.time_embed(time) + x = self.input_embed(x, cond, mu, spks.squeeze(1)) + + rope = self.rotary_embed.forward_from_seq_len(seq_len) + + if self.long_skip_connection is not None: + residual = x + + mask = mask.unsqueeze(1) # B,1,1,T + if self.causal_mask_type is not None: + mask = self.build_mix_causal_mask(mask, rand=mask_rand.unsqueeze(-1)) + + for block in self.transformer_blocks: + # mask-out padded values for amp training + x = x * mask[:, 0, -1, :].unsqueeze(-1) + x = block(x, t, mask=mask.bool(), rope=rope) + + if self.long_skip_connection is not None: + x = self.long_skip_connection(torch.cat((x, residual), dim=-1)) + + x = self.norm_out(x, t) + output = self.proj_out(x) + + if return_hidden: + return output, None + + return output diff --git a/cosyvoice/flow/DiT/dit_modules.py b/cosyvoice/flow/DiT/dit_modules.py new file mode 100644 index 0000000..1c1ee01 --- /dev/null +++ b/cosyvoice/flow/DiT/dit_modules.py @@ -0,0 +1,615 @@ +""" +ein notation: +b - batch +n - sequence +nt - text sequence +nw - raw wave length +d - dimension +""" + +from __future__ import annotations +from typing import Optional +import math + +import torch +from torch import nn +import torch.nn.functional as F +import torchaudio + +from x_transformers.x_transformers import apply_rotary_pos_emb + + +# raw wav to mel spec +class MelSpec(nn.Module): + def __init__( + self, + filter_length=1024, + hop_length=256, + win_length=1024, + n_mel_channels=100, + target_sample_rate=24_000, + normalize=False, + power=1, + norm=None, + center=True, + ): + super().__init__() + self.n_mel_channels = n_mel_channels + + self.mel_stft = torchaudio.transforms.MelSpectrogram( + sample_rate=target_sample_rate, + n_fft=filter_length, + win_length=win_length, + hop_length=hop_length, + n_mels=n_mel_channels, + power=power, + center=center, + normalized=normalize, + norm=norm, + ) + + self.register_buffer("dummy", torch.tensor(0), persistent=False) + + def forward(self, inp): + if len(inp.shape) == 3: + inp = inp.squeeze(1) # 'b 1 nw -> b nw' + + assert len(inp.shape) == 2 + + if self.dummy.device != inp.device: + self.to(inp.device) + + mel = self.mel_stft(inp) + mel = mel.clamp(min=1e-5).log() + return mel + + +# sinusoidal position embedding + + +class SinusPositionEmbedding(nn.Module): + def __init__(self, dim): + super().__init__() + self.dim = dim + + def forward(self, x, scale=1000): + device = x.device + half_dim = self.dim // 2 + emb = math.log(10000) / (half_dim - 1) + emb = torch.exp(torch.arange(half_dim, device=device).float() * -emb) + emb = scale * x.unsqueeze(1) * emb.unsqueeze(0) + emb = torch.cat((emb.sin(), emb.cos()), dim=-1) + return emb + + +# convolutional position embedding + + +class ConvPositionEmbedding(nn.Module): + def __init__(self, dim, kernel_size=31, groups=16): + super().__init__() + assert kernel_size % 2 != 0 + self.conv1d = nn.Sequential( + nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2), + nn.Mish(), + nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2), + nn.Mish(), + ) + + def forward(self, x: float["b n d"], mask: bool["b n"] | None = None): # noqa: F722 + if mask is not None: + mask = mask[..., None] + x = x.masked_fill(~mask, 0.0) + + x = x.permute(0, 2, 1) + x = self.conv1d(x) + out = x.permute(0, 2, 1) + + if mask is not None: + out = out.masked_fill(~mask, 0.0) + + return out + + +class CausalConvPositionEmbedding(nn.Module): + def __init__(self, dim, kernel_size=31, groups=16): + super().__init__() + assert kernel_size % 2 != 0 + self.kernel_size = kernel_size + self.conv1 = nn.Sequential( + nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=0), + nn.Mish(), + ) + self.conv2 = nn.Sequential( + nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=0), + nn.Mish(), + ) + + def forward(self, x: float["b n d"], mask: bool["b n"] | None = None): # noqa: F722 + if mask is not None: + mask = mask[..., None] + x = x.masked_fill(~mask, 0.0) + + x = x.permute(0, 2, 1) + x = F.pad(x, (self.kernel_size - 1, 0, 0, 0)) + x = self.conv1(x) + x = F.pad(x, (self.kernel_size - 1, 0, 0, 0)) + x = self.conv2(x) + out = x.permute(0, 2, 1) + + if mask is not None: + out = out.masked_fill(~mask, 0.0) + + return out + + +# rotary positional embedding related + + +def precompute_freqs_cis(dim: int, end: int, theta: float = 10000.0, theta_rescale_factor=1.0): + # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning + # has some connection to NTK literature + # https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/ + # https://github.com/lucidrains/rotary-embedding-torch/blob/main/rotary_embedding_torch/rotary_embedding_torch.py + theta *= theta_rescale_factor ** (dim / (dim - 2)) + freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim)) + t = torch.arange(end, device=freqs.device) # type: ignore + freqs = torch.outer(t, freqs).float() # type: ignore + freqs_cos = torch.cos(freqs) # real part + freqs_sin = torch.sin(freqs) # imaginary part + return torch.cat([freqs_cos, freqs_sin], dim=-1) + + +def get_pos_embed_indices(start, length, max_pos, scale=1.0): + # length = length if isinstance(length, int) else length.max() + scale = scale * torch.ones_like(start, dtype=torch.float32) # in case scale is a scalar + pos = ( + start.unsqueeze(1) + + (torch.arange(length, device=start.device, dtype=torch.float32).unsqueeze(0) * scale.unsqueeze(1)).long() + ) + # avoid extra long error. + pos = torch.where(pos < max_pos, pos, max_pos - 1) + return pos + + +# Global Response Normalization layer (Instance Normalization ?) + + +class GRN(nn.Module): + def __init__(self, dim): + super().__init__() + self.gamma = nn.Parameter(torch.zeros(1, 1, dim)) + self.beta = nn.Parameter(torch.zeros(1, 1, dim)) + + def forward(self, x): + Gx = torch.norm(x, p=2, dim=1, keepdim=True) + Nx = Gx / (Gx.mean(dim=-1, keepdim=True) + 1e-6) + return self.gamma * (x * Nx) + self.beta + x + + +# ConvNeXt-V2 Block https://github.com/facebookresearch/ConvNeXt-V2/blob/main/models/convnextv2.py +# ref: https://github.com/bfs18/e2_tts/blob/main/rfwave/modules.py#L108 + + +class ConvNeXtV2Block(nn.Module): + def __init__( + self, + dim: int, + intermediate_dim: int, + dilation: int = 1, + ): + super().__init__() + padding = (dilation * (7 - 1)) // 2 + self.dwconv = nn.Conv1d( + dim, dim, kernel_size=7, padding=padding, groups=dim, dilation=dilation + ) # depthwise conv + self.norm = nn.LayerNorm(dim, eps=1e-6) + self.pwconv1 = nn.Linear(dim, intermediate_dim) # pointwise/1x1 convs, implemented with linear layers + self.act = nn.GELU() + self.grn = GRN(intermediate_dim) + self.pwconv2 = nn.Linear(intermediate_dim, dim) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + residual = x + x = x.transpose(1, 2) # b n d -> b d n + x = self.dwconv(x) + x = x.transpose(1, 2) # b d n -> b n d + x = self.norm(x) + x = self.pwconv1(x) + x = self.act(x) + x = self.grn(x) + x = self.pwconv2(x) + return residual + x + + +# AdaLayerNormZero +# return with modulated x for attn input, and params for later mlp modulation + + +class AdaLayerNormZero(nn.Module): + def __init__(self, dim): + super().__init__() + + self.silu = nn.SiLU() + self.linear = nn.Linear(dim, dim * 6) + + self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6) + + def forward(self, x, emb=None): + emb = self.linear(self.silu(emb)) + shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = torch.chunk(emb, 6, dim=1) + + x = self.norm(x) * (1 + scale_msa[:, None]) + shift_msa[:, None] + return x, gate_msa, shift_mlp, scale_mlp, gate_mlp + + +# AdaLayerNormZero for final layer +# return only with modulated x for attn input, cuz no more mlp modulation + + +class AdaLayerNormZero_Final(nn.Module): + def __init__(self, dim): + super().__init__() + + self.silu = nn.SiLU() + self.linear = nn.Linear(dim, dim * 2) + + self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6) + + def forward(self, x, emb): + emb = self.linear(self.silu(emb)) + scale, shift = torch.chunk(emb, 2, dim=1) + + x = self.norm(x) * (1 + scale)[:, None, :] + shift[:, None, :] + return x + + +# FeedForward + + +class FeedForward(nn.Module): + def __init__(self, dim, dim_out=None, mult=4, dropout=0.0, approximate: str = "none"): + super().__init__() + inner_dim = int(dim * mult) + dim_out = dim_out if dim_out is not None else dim + + activation = nn.GELU(approximate=approximate) + project_in = nn.Sequential(nn.Linear(dim, inner_dim), activation) + self.ff = nn.Sequential(project_in, nn.Dropout(dropout), nn.Linear(inner_dim, dim_out)) + + def forward(self, x): + return self.ff(x) + + +# Attention with possible joint part +# modified from diffusers/src/diffusers/models/attention_processor.py + + +class Attention(nn.Module): + def __init__( + self, + processor: JointAttnProcessor | AttnProcessor, + dim: int, + heads: int = 8, + dim_head: int = 64, + dropout: float = 0.0, + context_dim: Optional[int] = None, # if not None -> joint attention + context_pre_only=None, + ): + super().__init__() + + if not hasattr(F, "scaled_dot_product_attention"): + raise ImportError("Attention equires PyTorch 2.0, to use it, please upgrade PyTorch to 2.0.") + + self.processor = processor + + self.dim = dim + self.heads = heads + self.inner_dim = dim_head * heads + self.dropout = dropout + + self.context_dim = context_dim + self.context_pre_only = context_pre_only + + self.to_q = nn.Linear(dim, self.inner_dim) + self.to_k = nn.Linear(dim, self.inner_dim) + self.to_v = nn.Linear(dim, self.inner_dim) + + if self.context_dim is not None: + self.to_k_c = nn.Linear(context_dim, self.inner_dim) + self.to_v_c = nn.Linear(context_dim, self.inner_dim) + if self.context_pre_only is not None: + self.to_q_c = nn.Linear(context_dim, self.inner_dim) + + self.to_out = nn.ModuleList([]) + self.to_out.append(nn.Linear(self.inner_dim, dim)) + self.to_out.append(nn.Dropout(dropout)) + + if self.context_pre_only is not None and not self.context_pre_only: + self.to_out_c = nn.Linear(self.inner_dim, dim) + + def forward( + self, + x: float["b n d"], # noised input x # noqa: F722 + c: float["b n d"] = None, # context c # noqa: F722 + mask: bool["b n"] | None = None, # noqa: F722 + rope=None, # rotary position embedding for x + c_rope=None, # rotary position embedding for c + ) -> torch.Tensor: + if c is not None: + return self.processor(self, x, c=c, mask=mask, rope=rope, c_rope=c_rope) + else: + return self.processor(self, x, mask=mask, rope=rope) + + +# Attention processor + + +class AttnProcessor: + def __init__(self): + pass + + def __call__( + self, + attn: Attention, + x: float["b n d"], # noised input x # noqa: F722 + mask: bool["b n"] | None = None, # noqa: F722 + rope=None, # rotary position embedding + ) -> torch.FloatTensor: + batch_size = x.shape[0] + + # `sample` projections. + query = attn.to_q(x) + key = attn.to_k(x) + value = attn.to_v(x) + + # apply rotary position embedding + if rope is not None: + freqs, xpos_scale = rope + q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0) + + query = apply_rotary_pos_emb(query, freqs, q_xpos_scale) + key = apply_rotary_pos_emb(key, freqs, k_xpos_scale) + + # attention + inner_dim = key.shape[-1] + head_dim = inner_dim // attn.heads + query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + + # mask. e.g. inference got a batch with different target durations, mask out the padding + if mask is not None: + attn_mask = mask + if attn_mask.dim() == 2: + attn_mask = attn_mask.unsqueeze(1).unsqueeze(1) # 'b n -> b 1 1 n' + attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2]) + else: + attn_mask = None + + x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False) + x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim) + x = x.to(query.dtype) + + # linear proj + x = attn.to_out[0](x) + # dropout + x = attn.to_out[1](x) + + if mask is not None: + if mask.dim() == 2: + mask = mask.unsqueeze(-1) + else: + mask = mask[:, 0, -1].unsqueeze(-1) + x = x.masked_fill(~mask, 0.0) + + return x + + +# Joint Attention processor for MM-DiT +# modified from diffusers/src/diffusers/models/attention_processor.py + + +class JointAttnProcessor: + def __init__(self): + pass + + def __call__( + self, + attn: Attention, + x: float["b n d"], # noised input x # noqa: F722 + c: float["b nt d"] = None, # context c, here text # noqa: F722 + mask: bool["b n"] | None = None, # noqa: F722 + rope=None, # rotary position embedding for x + c_rope=None, # rotary position embedding for c + ) -> torch.FloatTensor: + residual = x + + batch_size = c.shape[0] + + # `sample` projections. + query = attn.to_q(x) + key = attn.to_k(x) + value = attn.to_v(x) + + # `context` projections. + c_query = attn.to_q_c(c) + c_key = attn.to_k_c(c) + c_value = attn.to_v_c(c) + + # apply rope for context and noised input independently + if rope is not None: + freqs, xpos_scale = rope + q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0) + query = apply_rotary_pos_emb(query, freqs, q_xpos_scale) + key = apply_rotary_pos_emb(key, freqs, k_xpos_scale) + if c_rope is not None: + freqs, xpos_scale = c_rope + q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0) + c_query = apply_rotary_pos_emb(c_query, freqs, q_xpos_scale) + c_key = apply_rotary_pos_emb(c_key, freqs, k_xpos_scale) + + # attention + query = torch.cat([query, c_query], dim=1) + key = torch.cat([key, c_key], dim=1) + value = torch.cat([value, c_value], dim=1) + + inner_dim = key.shape[-1] + head_dim = inner_dim // attn.heads + query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2) + + # mask. e.g. inference got a batch with different target durations, mask out the padding + if mask is not None: + attn_mask = F.pad(mask, (0, c.shape[1]), value=True) # no mask for c (text) + attn_mask = attn_mask.unsqueeze(1).unsqueeze(1) # 'b n -> b 1 1 n' + attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2]) + else: + attn_mask = None + + x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False) + x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim) + x = x.to(query.dtype) + + # Split the attention outputs. + x, c = ( + x[:, : residual.shape[1]], + x[:, residual.shape[1] :], + ) + + # linear proj + x = attn.to_out[0](x) + # dropout + x = attn.to_out[1](x) + if not attn.context_pre_only: + c = attn.to_out_c(c) + + if mask is not None: + mask = mask.unsqueeze(-1) + x = x.masked_fill(~mask, 0.0) + # c = c.masked_fill(~mask, 0.) # no mask for c (text) + + return x, c + + +# DiT Block + + +class DiTBlock(nn.Module): + def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1): + super().__init__() + + self.attn_norm = AdaLayerNormZero(dim) + self.attn = Attention( + processor=AttnProcessor(), + dim=dim, + heads=heads, + dim_head=dim_head, + dropout=dropout, + ) + + self.ff_norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6) + self.ff = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh") + + def forward(self, x, t, mask=None, rope=None): # x: noised input, t: time embedding + # pre-norm & modulation for attention input + norm, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.attn_norm(x, emb=t) + + # attention + attn_output = self.attn(x=norm, mask=mask, rope=rope) + + # process attention output for input x + x = x + gate_msa.unsqueeze(1) * attn_output + + ff_norm = self.ff_norm(x) * (1 + scale_mlp[:, None]) + shift_mlp[:, None] + ff_output = self.ff(ff_norm) + x = x + gate_mlp.unsqueeze(1) * ff_output + + return x + + +# MMDiT Block https://arxiv.org/abs/2403.03206 + + +class MMDiTBlock(nn.Module): + r""" + modified from diffusers/src/diffusers/models/attention.py + + notes. + _c: context related. text, cond, etc. (left part in sd3 fig2.b) + _x: noised input related. (right part) + context_pre_only: last layer only do prenorm + modulation cuz no more ffn + """ + + def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1, context_pre_only=False): + super().__init__() + + self.context_pre_only = context_pre_only + + self.attn_norm_c = AdaLayerNormZero_Final(dim) if context_pre_only else AdaLayerNormZero(dim) + self.attn_norm_x = AdaLayerNormZero(dim) + self.attn = Attention( + processor=JointAttnProcessor(), + dim=dim, + heads=heads, + dim_head=dim_head, + dropout=dropout, + context_dim=dim, + context_pre_only=context_pre_only, + ) + + if not context_pre_only: + self.ff_norm_c = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6) + self.ff_c = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh") + else: + self.ff_norm_c = None + self.ff_c = None + self.ff_norm_x = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6) + self.ff_x = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh") + + def forward(self, x, c, t, mask=None, rope=None, c_rope=None): # x: noised input, c: context, t: time embedding + # pre-norm & modulation for attention input + if self.context_pre_only: + norm_c = self.attn_norm_c(c, t) + else: + norm_c, c_gate_msa, c_shift_mlp, c_scale_mlp, c_gate_mlp = self.attn_norm_c(c, emb=t) + norm_x, x_gate_msa, x_shift_mlp, x_scale_mlp, x_gate_mlp = self.attn_norm_x(x, emb=t) + + # attention + x_attn_output, c_attn_output = self.attn(x=norm_x, c=norm_c, mask=mask, rope=rope, c_rope=c_rope) + + # process attention output for context c + if self.context_pre_only: + c = None + else: # if not last layer + c = c + c_gate_msa.unsqueeze(1) * c_attn_output + + norm_c = self.ff_norm_c(c) * (1 + c_scale_mlp[:, None]) + c_shift_mlp[:, None] + c_ff_output = self.ff_c(norm_c) + c = c + c_gate_mlp.unsqueeze(1) * c_ff_output + + # process attention output for input x + x = x + x_gate_msa.unsqueeze(1) * x_attn_output + + norm_x = self.ff_norm_x(x) * (1 + x_scale_mlp[:, None]) + x_shift_mlp[:, None] + x_ff_output = self.ff_x(norm_x) + x = x + x_gate_mlp.unsqueeze(1) * x_ff_output + + return c, x + + +# time step conditioning embedding + + +class TimestepEmbedding(nn.Module): + def __init__(self, dim, freq_embed_dim=256): + super().__init__() + self.time_embed = SinusPositionEmbedding(freq_embed_dim) + self.time_mlp = nn.Sequential(nn.Linear(freq_embed_dim, dim), nn.SiLU(), nn.Linear(dim, dim)) + + def forward(self, timestep: float["b"]): # noqa: F821 + time_hidden = self.time_embed(timestep) + time_hidden = time_hidden.to(timestep.dtype) + time = self.time_mlp(time_hidden) # b d + return time diff --git a/cosyvoice/flow/flow.py b/cosyvoice/flow/flow.py index a068288..415d44e 100644 --- a/cosyvoice/flow/flow.py +++ b/cosyvoice/flow/flow.py @@ -37,14 +37,11 @@ class MaskedDiffWithXvec(torch.nn.Module): 'cfm_params': DictConfig({'sigma_min': 1e-06, 'solver': 'euler', 't_scheduler': 'cosine', 'training_cfg_rate': 0.2, 'inference_cfg_rate': 0.7, 'reg_loss_type': 'l1'}), 'decoder_params': {'channels': [256, 256], 'dropout': 0.0, 'attention_head_dim': 64, - 'n_blocks': 4, 'num_mid_blocks': 12, 'num_heads': 8, 'act_fn': 'gelu'}}, - mel_feat_conf: Dict = {'n_fft': 1024, 'num_mels': 80, 'sampling_rate': 22050, - 'hop_size': 256, 'win_size': 1024, 'fmin': 0, 'fmax': 8000}): + 'n_blocks': 4, 'num_mid_blocks': 12, 'num_heads': 8, 'act_fn': 'gelu'}}): super().__init__() self.input_size = input_size self.output_size = output_size self.decoder_conf = decoder_conf - self.mel_feat_conf = mel_feat_conf self.vocab_size = vocab_size self.output_type = output_type self.input_frame_rate = input_frame_rate @@ -165,14 +162,11 @@ class CausalMaskedDiffWithXvec(torch.nn.Module): 'cfm_params': DictConfig({'sigma_min': 1e-06, 'solver': 'euler', 't_scheduler': 'cosine', 'training_cfg_rate': 0.2, 'inference_cfg_rate': 0.7, 'reg_loss_type': 'l1'}), 'decoder_params': {'channels': [256, 256], 'dropout': 0.0, 'attention_head_dim': 64, - 'n_blocks': 4, 'num_mid_blocks': 12, 'num_heads': 8, 'act_fn': 'gelu'}}, - mel_feat_conf: Dict = {'n_fft': 1024, 'num_mels': 80, 'sampling_rate': 22050, - 'hop_size': 256, 'win_size': 1024, 'fmin': 0, 'fmax': 8000}): + 'n_blocks': 4, 'num_mid_blocks': 12, 'num_heads': 8, 'act_fn': 'gelu'}}): super().__init__() self.input_size = input_size self.output_size = output_size self.decoder_conf = decoder_conf - self.mel_feat_conf = mel_feat_conf self.vocab_size = vocab_size self.output_type = output_type self.input_frame_rate = input_frame_rate @@ -279,3 +273,158 @@ class CausalMaskedDiffWithXvec(torch.nn.Module): feat = feat[:, :, mel_len1:] assert feat.shape[2] == mel_len2 return feat.float(), None + + +class CausalMaskedDiffWithDiT(torch.nn.Module): + def __init__(self, + input_size: int = 512, + output_size: int = 80, + spk_embed_dim: int = 192, + output_type: str = "mel", + vocab_size: int = 4096, + input_frame_rate: int = 50, + only_mask_loss: bool = True, + token_mel_ratio: int = 2, + pre_lookahead_len: int = 3, + pre_lookahead_layer: torch.nn.Module = None, + decoder: torch.nn.Module = None, + decoder_conf: Dict = {'in_channels': 240, 'out_channel': 80, 'spk_emb_dim': 80, 'n_spks': 1, + 'cfm_params': DictConfig({'sigma_min': 1e-06, 'solver': 'euler', 't_scheduler': 'cosine', + 'training_cfg_rate': 0.2, 'inference_cfg_rate': 0.7, 'reg_loss_type': 'l1'}), + 'decoder_params': {'channels': [256, 256], 'dropout': 0.0, 'attention_head_dim': 64, + 'n_blocks': 4, 'num_mid_blocks': 12, 'num_heads': 8, 'act_fn': 'gelu'}}): + super().__init__() + self.input_size = input_size + self.output_size = output_size + self.decoder_conf = decoder_conf + self.vocab_size = vocab_size + self.output_type = output_type + self.input_frame_rate = input_frame_rate + logging.info(f"input frame rate={self.input_frame_rate}") + self.input_embedding = nn.Embedding(vocab_size, input_size) + self.spk_embed_affine_layer = torch.nn.Linear(spk_embed_dim, output_size) + self.pre_lookahead_len = pre_lookahead_len + self.pre_lookahead_layer = pre_lookahead_layer + self.decoder = decoder + self.only_mask_loss = only_mask_loss + self.token_mel_ratio = token_mel_ratio + + def forward( + self, + batch: dict, + device: torch.device, + ) -> Dict[str, Optional[torch.Tensor]]: + token = batch['speech_token'].to(device) + token_len = batch['speech_token_len'].to(device) + feat = batch['speech_feat'].to(device) + feat_len = batch['speech_feat_len'].to(device) + embedding = batch['embedding'].to(device) + + # NOTE unified training, static_chunk_size > 0 or = 0 + streaming = True if random.random() < 0.5 else False + + # xvec projection + embedding = F.normalize(embedding, dim=1) + embedding = self.spk_embed_affine_layer(embedding) + + # concat text and prompt_text + mask = (~make_pad_mask(token_len)).float().unsqueeze(-1).to(device) + token = self.input_embedding(torch.clamp(token, min=0)) * mask + + # text encode + h, h_lengths = self.encoder(token, token_len, streaming=streaming) + h = self.encoder_proj(h) + + # get conditions + conds = torch.zeros(feat.shape, device=token.device) + for i, j in enumerate(feat_len): + if random.random() < 0.5: + continue + index = random.randint(0, int(0.3 * j)) + conds[i, :index] = feat[i, :index] + conds = conds.transpose(1, 2) + + mask = (~make_pad_mask(h_lengths.sum(dim=-1).squeeze(dim=1))).to(h) + loss, _ = self.decoder.compute_loss( + feat.transpose(1, 2).contiguous(), + mask.unsqueeze(1), + h.transpose(1, 2).contiguous(), + embedding, + cond=conds, + streaming=streaming, + ) + return {'loss': loss} + + @torch.inference_mode() + def inference(self, + token, + token_len, + prompt_token, + prompt_token_len, + prompt_feat, + prompt_feat_len, + embedding, + streaming, + finalize): + assert token.shape[0] == 1 + # xvec projection + embedding = F.normalize(embedding, dim=1) + embedding = self.spk_embed_affine_layer(embedding) + + # concat text and prompt_text + token, token_len = torch.concat([prompt_token, token], dim=1), prompt_token_len + token_len + mask = (~make_pad_mask(token_len)).unsqueeze(-1).to(embedding) + token = self.input_embedding(torch.clamp(token, min=0)) * mask + + # text encode + if finalize is True: + h = self.pre_lookahead_layer(token) + else: + h = self.pre_lookahead_layer(token[:, :-self.pre_lookahead_len], context=token[:, -self.pre_lookahead_len:]) + h = h.repeat_interleave(self.token_mel_ratio, dim=1) + mel_len1, mel_len2 = prompt_feat.shape[1], h.shape[1] - prompt_feat.shape[1] + + # get conditions + conds = torch.zeros([1, mel_len1 + mel_len2, self.output_size], device=token.device).to(h.dtype) + conds[:, :mel_len1] = prompt_feat + conds = conds.transpose(1, 2) + + mask = (~make_pad_mask(torch.tensor([mel_len1 + mel_len2]))).to(h) + feat, _ = self.decoder( + mu=h.transpose(1, 2).contiguous(), + mask=mask.unsqueeze(1), + spks=embedding, + cond=conds, + n_timesteps=10, + streaming=streaming + ) + feat = feat[:, :, mel_len1:] + assert feat.shape[2] == mel_len2 + return feat.float(), None + +if __name__ == '__main__': + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + from hyperpyyaml import load_hyperpyyaml + with open('./pretrained_models/CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: + configs = load_hyperpyyaml(f, overrides={'llm': None, 'hift': None}) + model = configs['flow'] + device = 'cuda' if torch.cuda.is_available() else 'cpu' + model.to(device) + model.eval() + max_len = 10 * model.decoder.estimator.static_chunk_size + chunk_size = model.decoder.estimator.static_chunk_size + context_size = model.pre_lookahead_layer.pre_lookahead_len + token = torch.randint(0, 6561, size=(1, max_len)).to(device) + token_len = torch.tensor([max_len]).to(device) + prompt_token = torch.randint(0, 6561, size=(1, chunk_size)).to(device) + prompt_token_len = torch.tensor([chunk_size]).to(device) + prompt_feat = torch.rand(1, chunk_size * 2, 80).to(device) + prompt_feat_len = torch.tensor([chunk_size * 2]).to(device) + prompt_embedding = torch.rand(1, 192).to(device) + pred_gt, _ = model.inference(token, token_len, prompt_token, prompt_token_len, prompt_feat, prompt_feat_len, prompt_embedding, streaming=True, finalize=True) + for i in range(0, max_len, chunk_size): + finalize = True if i + chunk_size + context_size >= max_len else False + pred_chunk, _ = model.inference(token[:, :i + chunk_size + context_size], torch.tensor([token[:, :i + chunk_size + context_size].shape[1]]).to(device), prompt_token, prompt_token_len, prompt_feat, prompt_feat_len, prompt_embedding, streaming=True, finalize=finalize) + pred_chunk = pred_chunk[:, :, i * model.token_mel_ratio:] + print((pred_gt[:, :, i * model.token_mel_ratio: i * model.token_mel_ratio + pred_chunk.shape[2]] - pred_chunk).abs().max().item()) \ No newline at end of file diff --git a/cosyvoice/hifigan/generator.py b/cosyvoice/hifigan/generator.py index c3f8b1f..9647ef3 100644 --- a/cosyvoice/hifigan/generator.py +++ b/cosyvoice/hifigan/generator.py @@ -736,7 +736,7 @@ if __name__ == '__main__': model.to(device) model.eval() max_len, chunk_size, context_size = 300, 30, 8 - mel = torch.rand(1, 80, max_len) + mel = torch.rand(1, 80, max_len).to(device) pred_gt, _ = model.inference(mel) for i in range(0, max_len, chunk_size): finalize = True if i + chunk_size + context_size >= max_len else False diff --git a/cosyvoice/transformer/upsample_encoder.py b/cosyvoice/transformer/upsample_encoder.py index 6ffda6a..baf7481 100644 --- a/cosyvoice/transformer/upsample_encoder.py +++ b/cosyvoice/transformer/upsample_encoder.py @@ -64,17 +64,18 @@ class Upsample1D(nn.Module): class PreLookaheadLayer(nn.Module): - def __init__(self, channels: int, pre_lookahead_len: int = 1): + def __init__(self, in_channels: int, channels: int, pre_lookahead_len: int = 1): super().__init__() + self.in_channels = in_channels self.channels = channels self.pre_lookahead_len = pre_lookahead_len self.conv1 = nn.Conv1d( - channels, channels, + in_channels, channels, kernel_size=pre_lookahead_len + 1, stride=1, padding=0, ) self.conv2 = nn.Conv1d( - channels, channels, + channels, in_channels, kernel_size=3, stride=1, padding=0, ) @@ -199,7 +200,7 @@ class UpsampleConformerEncoder(torch.nn.Module): # convolution module definition convolution_layer_args = (output_size, cnn_module_kernel, activation, cnn_module_norm, causal) - self.pre_lookahead_layer = PreLookaheadLayer(channels=512, pre_lookahead_len=3) + self.pre_lookahead_layer = PreLookaheadLayer(in_channels=512, channels=512, pre_lookahead_len=3) self.encoders = torch.nn.ModuleList([ ConformerEncoderLayer( output_size, From dd2d9261478b97b197090c9bf69f108b382da5ef Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 20 Aug 2025 16:55:03 +0800 Subject: [PATCH 03/61] update --- cosyvoice/flow/DiT/{dit_model.py => dit.py} | 76 +++++-------------- .../flow/DiT/{dit_modules.py => modules.py} | 1 + 2 files changed, 22 insertions(+), 55 deletions(-) rename cosyvoice/flow/DiT/{dit_model.py => dit.py} (68%) rename cosyvoice/flow/DiT/{dit_modules.py => modules.py} (99%) diff --git a/cosyvoice/flow/DiT/dit_model.py b/cosyvoice/flow/DiT/dit.py similarity index 68% rename from cosyvoice/flow/DiT/dit_model.py rename to cosyvoice/flow/DiT/dit.py index ada9392..73a5423 100644 --- a/cosyvoice/flow/DiT/dit_model.py +++ b/cosyvoice/flow/DiT/dit.py @@ -1,3 +1,4 @@ + """ ein notation: b - batch @@ -14,9 +15,8 @@ from torch import nn import torch.nn.functional as F from einops import repeat from x_transformers.x_transformers import RotaryEmbedding -from funasr.models.transformer.utils.mask import causal_block_mask - -from cosyvoice.flow.DiT.dit_modules import ( +from cosyvoice.utils.mask import add_optional_chunk_mask +from cosyvoice.flow.DiT.modules import ( TimestepEmbedding, ConvNeXtV2Block, CausalConvPositionEmbedding, @@ -115,7 +115,8 @@ class DiT(nn.Module): mu_dim=None, long_skip_connection=False, spk_dim=None, - **kwargs + static_chunk_size=50, + num_decoding_left_chunks=2 ): super().__init__() @@ -136,50 +137,20 @@ class DiT(nn.Module): self.norm_out = AdaLayerNormZero_Final(dim) # final modulation self.proj_out = nn.Linear(dim, mel_dim) - self.causal_mask_type = kwargs.get("causal_mask_type", None) + self.static_chunk_size = static_chunk_size + self.num_decoding_left_chunks = num_decoding_left_chunks - def build_mix_causal_mask(self, attn_mask, rand=None, ratio=None): - b, _, _, t = attn_mask.shape - if rand is None: - rand = torch.rand((b, 1, 1, 1), device=attn_mask.device, dtype=torch.float32) - mixed_mask = attn_mask.clone() - for item in self.causal_mask_type: - prob_min, prob_max = item["prob_min"], item["prob_max"] - _ratio = 1 - if "ratio" in item: - _ratio = item["ratio"] - if ratio is not None: - _ratio = ratio - block_size = item["block_size"] * _ratio - if block_size <= 0: - causal_mask = attn_mask - else: - causal_mask = causal_block_mask( - t, block_size, attn_mask.device, torch.float32 - ).unsqueeze(0).unsqueeze(1) # 1,1,T,T - flag = (prob_min <= rand) & (rand < prob_max) - mixed_mask = mixed_mask * (~flag) + (causal_mask * attn_mask) * flag - - return mixed_mask - - def forward( - self, - x: float["b n d"], # nosied input audio - cond: float["b n d"], # masked cond audio - mu: int["b nt d"], # mu - spks: float["b 1 d"], # spk xvec - time: float["b"] | float[""], # time step - return_hidden: bool = False, - mask: bool["b 1 n"] | None = None, - mask_rand: float["b 1 1"] = None, # for mask flag type - **kwargs, - ): + def forward(self, x, mask, mu, t, spks=None, cond=None, streaming=False): + x = x.transpose(1, 2) + mu = mu.transpose(1, 2) + cond = cond.transpose(1, 2) + spks = spks.unsqueeze(dim=1) batch, seq_len = x.shape[0], x.shape[1] - if time.ndim == 0: - time = time.repeat(batch) + if t.ndim == 0: + t = t.repeat(batch) # t: conditioning time, c: context (text + masked cond audio), x: noised input audio - t = self.time_embed(time) + t = self.time_embed(t) x = self.input_embed(x, cond, mu, spks.squeeze(1)) rope = self.rotary_embed.forward_from_seq_len(seq_len) @@ -187,22 +158,17 @@ class DiT(nn.Module): if self.long_skip_connection is not None: residual = x - mask = mask.unsqueeze(1) # B,1,1,T - if self.causal_mask_type is not None: - mask = self.build_mix_causal_mask(mask, rand=mask_rand.unsqueeze(-1)) + if streaming is True: + attn_mask = add_optional_chunk_mask(x, mask.bool(), False, False, 0, self.static_chunk_size, -1).unsqueeze(dim=1) + else: + attn_mask = add_optional_chunk_mask(x, mask.bool(), False, False, 0, 0, -1).repeat(1, x.size(1), 1).unsqueeze(dim=1) for block in self.transformer_blocks: - # mask-out padded values for amp training - x = x * mask[:, 0, -1, :].unsqueeze(-1) - x = block(x, t, mask=mask.bool(), rope=rope) + x = block(x, t, mask=attn_mask.bool(), rope=rope) if self.long_skip_connection is not None: x = self.long_skip_connection(torch.cat((x, residual), dim=-1)) x = self.norm_out(x, t) - output = self.proj_out(x) - - if return_hidden: - return output, None - + output = self.proj_out(x).transpose(1, 2) return output diff --git a/cosyvoice/flow/DiT/dit_modules.py b/cosyvoice/flow/DiT/modules.py similarity index 99% rename from cosyvoice/flow/DiT/dit_modules.py rename to cosyvoice/flow/DiT/modules.py index 1c1ee01..542ba36 100644 --- a/cosyvoice/flow/DiT/dit_modules.py +++ b/cosyvoice/flow/DiT/modules.py @@ -1,3 +1,4 @@ + """ ein notation: b - batch From 8c96081f94aa18de10f55f18e0a1d43b414e1845 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Thu, 21 Aug 2025 11:45:36 +0800 Subject: [PATCH 04/61] update --- cosyvoice/bin/export_onnx.py | 7 +++++-- cosyvoice/cli/cosyvoice.py | 2 +- cosyvoice/cli/model.py | 2 +- cosyvoice/flow/DiT/dit.py | 2 ++ cosyvoice/utils/class_utils.py | 6 ++++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cosyvoice/bin/export_onnx.py b/cosyvoice/bin/export_onnx.py index dd9f009..e4857da 100644 --- a/cosyvoice/bin/export_onnx.py +++ b/cosyvoice/bin/export_onnx.py @@ -27,7 +27,7 @@ from tqdm import tqdm ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../..'.format(ROOT_DIR)) sys.path.append('{}/../../third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 +from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2, CosyVoice3 from cosyvoice.utils.file_utils import logging @@ -64,7 +64,10 @@ def main(): try: model = CosyVoice2(args.model_dir) except Exception: - raise TypeError('no valid model_type!') + try: + model = CosyVoice3(args.model_dir) + except Exception: + raise TypeError('no valid model_type!') # 1. export flow decoder estimator estimator = model.model.flow.decoder.estimator diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index f4acba1..7731863 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -221,7 +221,7 @@ class CosyVoice3(CosyVoice): self.model = CosyVoice3Model(configs['llm'], configs['flow'], configs['hift'], fp16) self.model.load('{}/llm.pt'.format(model_dir), '{}/flow.pt'.format(model_dir), - '{}/bigvgan.pt'.format(model_dir)) + '{}/hift.pt'.format(model_dir)) if load_vllm: self.model.load_vllm('{}/vllm'.format(model_dir)) if load_jit: diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 2b6a918..c658996 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -447,7 +447,7 @@ class CosyVoice3Model(CosyVoice2Model): if speed != 1.0: assert self.hift_cache_dict[uuid] is None, 'speed change only support non-stream inference mode' tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') - tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel, cache_source=hift_cache_source) + tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel) if self.hift_cache_dict[uuid] is not None: tts_speech = fade_in_out(tts_speech, self.hift_cache_dict[uuid]['speech'], self.speech_window) return tts_speech \ No newline at end of file diff --git a/cosyvoice/flow/DiT/dit.py b/cosyvoice/flow/DiT/dit.py index 73a5423..0d637e4 100644 --- a/cosyvoice/flow/DiT/dit.py +++ b/cosyvoice/flow/DiT/dit.py @@ -115,6 +115,7 @@ class DiT(nn.Module): mu_dim=None, long_skip_connection=False, spk_dim=None, + out_channels=None, static_chunk_size=50, num_decoding_left_chunks=2 ): @@ -137,6 +138,7 @@ class DiT(nn.Module): self.norm_out = AdaLayerNormZero_Final(dim) # final modulation self.proj_out = nn.Linear(dim, mel_dim) + self.out_channels = out_channels self.static_chunk_size = static_chunk_size self.num_decoding_left_chunks = num_decoding_left_chunks diff --git a/cosyvoice/utils/class_utils.py b/cosyvoice/utils/class_utils.py index c49de00..c52fec4 100644 --- a/cosyvoice/utils/class_utils.py +++ b/cosyvoice/utils/class_utils.py @@ -33,8 +33,8 @@ from cosyvoice.transformer.attention import (MultiHeadedAttention, from cosyvoice.transformer.embedding import EspnetRelPositionalEncoding from cosyvoice.transformer.subsampling import LegacyLinearNoSubsampling from cosyvoice.llm.llm import TransformerLM, Qwen2LM -from cosyvoice.flow.flow import MaskedDiffWithXvec, CausalMaskedDiffWithXvec -from cosyvoice.hifigan.generator import HiFTGenerator +from cosyvoice.flow.flow import MaskedDiffWithXvec, CausalMaskedDiffWithXvec, CausalMaskedDiffWithDiT +from cosyvoice.hifigan.generator import HiFTGenerator, CausalHiFTGenerator from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model @@ -80,4 +80,6 @@ def get_model_type(configs): return CosyVoiceModel if isinstance(configs['llm'], Qwen2LM) and isinstance(configs['flow'], CausalMaskedDiffWithXvec) and isinstance(configs['hift'], HiFTGenerator): return CosyVoice2Model + if isinstance(configs['llm'], Qwen2LM) and isinstance(configs['flow'], CausalMaskedDiffWithDiT) and isinstance(configs['hift'], CausalHiFTGenerator): + return CosyVoice2Model raise TypeError('No valid model type found!') From 70991d73270cda916085f3dac7a25488aa6627d8 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Thu, 21 Aug 2025 20:08:08 +0800 Subject: [PATCH 05/61] update --- cosyvoice/llm/llm.py | 76 ++++++++++++++++++++++++++++++++ cosyvoice/tokenizer/tokenizer.py | 56 +++++++++++++++++++++-- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index 6891b33..cc2f2da 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -609,3 +609,79 @@ class Qwen2LM(TransformerLM): # in stream mode, yield token one by one yield top_ids lm_input = self.speech_embedding.weight[top_ids].reshape(1, 1, -1) + + +class CosyVoice3LM(Qwen2LM): + def __init__( + self, + llm_input_size: int, + llm_output_size: int, + speech_token_size: int, + llm: torch.nn.Module, + sampling: Callable, + length_normalized_loss: bool = True, + lsm_weight: float = 0.0, + mix_ratio: List[int] = [5, 15], + ): + torch.nn.Module.__init__(self) + self.llm_input_size = llm_input_size + self.llm_output_size = llm_output_size + self.speech_token_size = speech_token_size + # 2. build speech token language model related modules + self.sos = 0 + self.eos = 1 + self.task_id = 2 + self.fill_token = 3 + + self.llm = llm + self.llm_decoder = nn.Linear(llm_output_size, speech_token_size + 200, bias=False) + self.criterion_ce = LabelSmoothingLoss( + size=speech_token_size + 200, + padding_idx=IGNORE_ID, + smoothing=lsm_weight, + normalize_length=length_normalized_loss, + ) + + # 3. [Optional] build speech token related modules + self.speech_embedding = torch.nn.Embedding(speech_token_size + 200, llm_input_size) + + # 4. sampling method + self.sampling = sampling + self.mix_ratio = mix_ratio + + @torch.inference_mode() + def inference( + self, + text: torch.Tensor, + text_len: torch.Tensor, + prompt_text: torch.Tensor, + prompt_text_len: torch.Tensor, + prompt_speech_token: torch.Tensor, + prompt_speech_token_len: torch.Tensor, + embedding: torch.Tensor, + sampling: int = 25, + max_token_text_ratio: float = 20, + min_token_text_ratio: float = 2, + uuid: str = '', + ) -> Generator[torch.Tensor, None, None]: + device = text.device + text = torch.concat([prompt_text, text], dim=1) + text_len += prompt_text_len + text = self.llm.model.model.embed_tokens(text) + + # 3. concat llm_input + sos_eos_emb = self.speech_embedding.weight[self.speech_token_size + self.sos].reshape(1, 1, -1) + task_id_emb = self.speech_embedding.weight[self.speech_token_size + self.task_id].reshape(1, 1, -1) + if prompt_speech_token_len != 0: + prompt_speech_token_emb = self.speech_embedding(prompt_speech_token) + else: + prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device) + lm_input = torch.concat([sos_eos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1) + + # 4. cal min/max_length + min_len = int((text_len - prompt_text_len) * min_token_text_ratio) + max_len = int((text_len - prompt_text_len) * max_token_text_ratio) + + # 5. step by step decode + for token in self.inference_wrapper(lm_input, sampling, min_len, max_len, uuid): + yield token diff --git a/cosyvoice/tokenizer/tokenizer.py b/cosyvoice/tokenizer/tokenizer.py index 43fb39a..6ecf4ae 100644 --- a/cosyvoice/tokenizer/tokenizer.py +++ b/cosyvoice/tokenizer/tokenizer.py @@ -238,7 +238,7 @@ def get_tokenizer( ) -class QwenTokenizer(): +class CosyVoice2Tokenizer(): def __init__(self, token_path, skip_special_tokens=True): super().__init__() # NOTE: non-chat model, all these special tokens keep randomly initialized. @@ -271,9 +271,57 @@ class QwenTokenizer(): return text +class CosyVoice3Tokenizer(CosyVoice2Tokenizer): + def __init__(self, token_path, skip_special_tokens=True): + # NOTE: non-chat model, all these special tokens keep randomly initialized. + special_tokens = { + 'eos_token': '<|endoftext|>', + 'pad_token': '<|endoftext|>', + 'additional_special_tokens': [ + '<|im_start|>', '<|im_end|>', '<|endofprompt|>', + '[breath]', '', '', '[noise]', + '[laughter]', '[cough]', '[clucking]', '[accent]', + '[quick_breath]', + "", "", + "[hissing]", "[sigh]", "[vocalized-noise]", + "[lipsmack]", "[mn]", "<|endofsystem|>", + "[AA]", "[AA0]", "[AA1]", "[AA2]", "[AE]", "[AE0]", "[AE1]", "[AE2]", "[AH]", "[AH0]", "[AH1]", "[AH2]", + "[AO]", "[AO0]", "[AO1]", "[AO2]", "[AW]", "[AW0]", "[AW1]", "[AW2]", "[AY]", "[AY0]", "[AY1]", "[AY2]", + "[B]", "[CH]", "[D]", "[DH]", "[EH]", "[EH0]", "[EH1]", "[EH2]", "[ER]", "[ER0]", "[ER1]", "[ER2]", "[EY]", + "[EY0]", "[EY1]", "[EY2]", "[F]", "[G]", "[HH]", "[IH]", "[IH0]", "[IH1]", "[IH2]", "[IY]", "[IY0]", "[IY1]", + "[IY2]", "[JH]", "[K]", "[L]", "[M]", "[N]", "[NG]", "[OW]", "[OW0]", "[OW1]", "[OW2]", "[OY]", "[OY0]", + "[OY1]", "[OY2]", "[P]", "[R]", "[S]", "[SH]", "[T]", "[TH]", "[UH]", "[UH0]", "[UH1]", "[UH2]", "[UW]", + "[UW0]", "[UW1]", "[UW2]", "[V]", "[W]", "[Y]", "[Z]", "[ZH]", + "[a]", "[ai]", "[an]", "[ang]", "[ao]", "[b]", "[c]", "[ch]", "[d]", "[e]", "[ei]", "[en]", "[eng]", "[f]", + "[g]", "[h]", "[i]", "[ian]", "[in]", "[ing]", "[iu]", "[ià]", "[iàn]", "[iàng]", "[iào]", "[iá]", "[ián]", + "[iáng]", "[iáo]", "[iè]", "[ié]", "[iòng]", "[ióng]", "[iù]", "[iú]", "[iā]", "[iān]", "[iāng]", "[iāo]", + "[iē]", "[iě]", "[iōng]", "[iū]", "[iǎ]", "[iǎn]", "[iǎng]", "[iǎo]", "[iǒng]", "[iǔ]", "[j]", "[k]", "[l]", + "[m]", "[n]", "[o]", "[ong]", "[ou]", "[p]", "[q]", "[r]", "[s]", "[sh]", "[t]", "[u]", "[uang]", "[ue]", + "[un]", "[uo]", "[uà]", "[uài]", "[uàn]", "[uàng]", "[uá]", "[uái]", "[uán]", "[uáng]", "[uè]", "[ué]", "[uì]", + "[uí]", "[uò]", "[uó]", "[uā]", "[uāi]", "[uān]", "[uāng]", "[uē]", "[uě]", "[uī]", "[uō]", "[uǎ]", "[uǎi]", + "[uǎn]", "[uǎng]", "[uǐ]", "[uǒ]", "[vè]", "[w]", "[x]", "[y]", "[z]", "[zh]", "[à]", "[ài]", "[àn]", "[àng]", + "[ào]", "[á]", "[ái]", "[án]", "[áng]", "[áo]", "[è]", "[èi]", "[èn]", "[èng]", "[èr]", "[é]", "[éi]", "[én]", + "[éng]", "[ér]", "[ì]", "[ìn]", "[ìng]", "[í]", "[ín]", "[íng]", "[ò]", "[òng]", "[òu]", "[ó]", "[óng]", "[óu]", + "[ù]", "[ùn]", "[ú]", "[ún]", "[ā]", "[āi]", "[ān]", "[āng]", "[āo]", "[ē]", "[ēi]", "[ēn]", "[ēng]", "[ě]", + "[ěi]", "[ěn]", "[ěng]", "[ěr]", "[ī]", "[īn]", "[īng]", "[ō]", "[ōng]", "[ōu]", "[ū]", "[ūn]", "[ǎ]", "[ǎi]", + "[ǎn]", "[ǎng]", "[ǎo]", "[ǐ]", "[ǐn]", "[ǐng]", "[ǒ]", "[ǒng]", "[ǒu]", "[ǔ]", "[ǔn]", "[ǘ]", "[ǚ]", "[ǜ]" + ] + } + self.special_tokens = special_tokens + self.tokenizer = AutoTokenizer.from_pretrained(token_path) + self.tokenizer.add_special_tokens(special_tokens) + self.skip_special_tokens = skip_special_tokens + + @lru_cache(maxsize=None) def get_qwen_tokenizer( token_path: str, - skip_special_tokens: bool -) -> QwenTokenizer: - return QwenTokenizer(token_path=token_path, skip_special_tokens=skip_special_tokens) + skip_special_tokens: bool, + version: str = 'cosyvoice2' +): + if version == 'cosyvoice2': + return CosyVoice2Tokenizer(token_path=token_path, skip_special_tokens=skip_special_tokens) + elif version == 'cosyvoice3': + return CosyVoice3Tokenizer(token_path=token_path, skip_special_tokens=skip_special_tokens) + else: + raise ValueError From dc96e4c98430ce7ac4068df8e54d0f115dcdbfd2 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Thu, 21 Aug 2025 21:03:58 +0800 Subject: [PATCH 06/61] update --- cosyvoice/cli/cosyvoice.py | 2 +- cosyvoice/llm/llm.py | 78 +++++++++++++++++----------------- cosyvoice/utils/class_utils.py | 8 ++-- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 7731863..910fa74 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -207,7 +207,7 @@ class CosyVoice3(CosyVoice): raise ValueError('{} not found!'.format(hyper_yaml_path)) with open(hyper_yaml_path, 'r') as f: configs = load_hyperpyyaml(f, overrides={'qwen_pretrain_path': os.path.join(model_dir, 'CosyVoice-BlankEN')}) - assert get_model_type(configs) == CosyVoice2Model, 'do not use {} for CosyVoice2 initialization!'.format(model_dir) + assert get_model_type(configs) == CosyVoice3Model, 'do not use {} for CosyVoice3 initialization!'.format(model_dir) self.frontend = CosyVoiceFrontEnd(configs['get_tokenizer'], configs['feat_extractor'], '{}/campplus.onnx'.format(model_dir), diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index cc2f2da..85ad6fb 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -56,8 +56,9 @@ class TransformerLM(torch.nn.Module): ) # 2. build speech token language model related modules - self.sos_eos = 0 + self.sos = 0 self.task_id = 1 + self.eos_token = self.speech_token_size self.llm_embedding = torch.nn.Embedding(2, llm_input_size) self.llm = llm self.llm_decoder = nn.Linear(llm_output_size, speech_token_size + 1) @@ -85,10 +86,10 @@ class TransformerLM(torch.nn.Module): encoder_out = self.text_encoder_affine_layer(encoder_out) return encoder_out, encoder_out_lens - def pad_unpad_sequence(self, sos_eos_emb, embedding, text_token, text_token_len, task_id_emb, speech_token, speech_token_len): + def pad_unpad_sequence(self, sos_emb, embedding, text_token, text_token_len, task_id_emb, speech_token, speech_token_len): text_token = unpad_sequence(text_token, text_token_len.cpu(), batch_first=True) speech_token = unpad_sequence(speech_token, speech_token_len.cpu(), batch_first=True) - lm_input = [torch.concat([sos_eos_emb.squeeze(dim=0), embedding[i], text_token[i], task_id_emb.squeeze(dim=0), speech_token[i]], dim=0) + lm_input = [torch.concat([sos_emb.squeeze(dim=0), embedding[i], text_token[i], task_id_emb.squeeze(dim=0), speech_token[i]], dim=0) for i in range(len(text_token))] lm_input_len = torch.tensor([i.size(0) for i in lm_input], dtype=torch.int32) lm_input = pad_sequence(lm_input, batch_first=True, padding_value=IGNORE_ID) @@ -127,14 +128,14 @@ class TransformerLM(torch.nn.Module): embedding = embedding.unsqueeze(1) # 3. eos and task_id - sos_eos_emb = self.llm_embedding.weight[self.sos_eos].reshape(1, 1, -1) + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) # 4. encode speech_token speech_token = self.speech_embedding(speech_token) # 5. unpad and pad - lm_input, lm_input_len = self.pad_unpad_sequence(sos_eos_emb, embedding, text_token, text_token_len, + lm_input, lm_input_len = self.pad_unpad_sequence(sos_emb, embedding, text_token, text_token_len, task_id_emb, speech_token, speech_token_len) # 6. run lm forward @@ -193,13 +194,13 @@ class TransformerLM(torch.nn.Module): embedding = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device).to(text.dtype) # 3. concat llm_input - sos_eos_emb = self.llm_embedding.weight[self.sos_eos].reshape(1, 1, -1) + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) if prompt_speech_token_len != 0: prompt_speech_token_emb = self.speech_embedding(prompt_speech_token) else: prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device) - lm_input = torch.concat([sos_eos_emb, embedding, text, task_id_emb, prompt_speech_token_emb], dim=1) + lm_input = torch.concat([sos_emb, embedding, text, task_id_emb, prompt_speech_token_emb], dim=1) # 4. cal min/max_length min_len = int((text_len - prompt_text_len) * min_token_text_ratio) @@ -215,11 +216,8 @@ class TransformerLM(torch.nn.Module): att_mask=torch.tril(torch.ones((1, lm_input.shape[1], lm_input.shape[1]), device=lm_input.device)).to(torch.bool)) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) - # force continue decode first token - if i == 0: - logp[:, self.speech_token_size] = -float('inf') top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False).item() - if top_ids == self.speech_token_size: + if top_ids == self.eos_token: break # in stream mode, yield token one by one yield top_ids @@ -276,9 +274,10 @@ class Qwen2LM(TransformerLM): self.llm_output_size = llm_output_size self.speech_token_size = speech_token_size # 2. build speech token language model related modules - self.sos_eos = 0 + self.sos = 0 self.task_id = 1 - self.fill_token = 2 + self.eos_token = speech_token_size + self.fill_token = speech_token_size + 2 self.llm_embedding = torch.nn.Embedding(2, llm_input_size) self.llm = llm @@ -312,7 +311,7 @@ class Qwen2LM(TransformerLM): if random.random() < 0.5 and speech_token_len[i] / text_token_len[i] > self.mix_ratio[1] / self.mix_ratio[0]: this_lm_target, this_lm_input = [], [] this_lm_target.append(IGNORE_ID) - this_lm_input.append(self.llm_embedding.weight[self.sos_eos].reshape(1, -1)) + this_lm_input.append(self.llm_embedding.weight[self.sos].reshape(1, -1)) for j in range(((text_token_len[i] + 1) / self.mix_ratio[0]).ceil().int().item()): this_text_token = text_token[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]].tolist() this_speech_token = speech_token[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]].tolist() @@ -320,21 +319,21 @@ class Qwen2LM(TransformerLM): assert len(this_speech_token) == self.mix_ratio[1] this_lm_target += [IGNORE_ID] * (self.mix_ratio[0] - 1) this_lm_target += this_speech_token - this_lm_target.append(self.speech_token_size + 2) + this_lm_target.append(self.fill_token) this_lm_input.append(text_token_emb[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]]) this_lm_input.append(speech_token_emb[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]]) else: this_lm_target += [-1] * len(this_text_token) this_lm_target += speech_token[i][j * self.mix_ratio[1]:].tolist() - this_lm_target.append(self.speech_token_size) + this_lm_target.append(self.eos_token) this_lm_input.append(text_token_emb[i][j * self.mix_ratio[0]:]) this_lm_input.append(self.llm_embedding.weight[self.task_id].reshape(1, -1)) this_lm_input.append(speech_token_emb[i][j * self.mix_ratio[1]:]) this_lm_target, this_lm_input = torch.tensor(this_lm_target), torch.concat(this_lm_input, dim=0) # unistream sequence else: - this_lm_target = torch.tensor([IGNORE_ID] * (1 + text_token_len[i]) + speech_token[i].tolist() + [self.speech_token_size]) - this_lm_input = torch.concat([self.llm_embedding.weight[self.sos_eos].reshape(1, -1), text_token_emb[i], + this_lm_target = torch.tensor([IGNORE_ID] * (1 + text_token_len[i]) + speech_token[i].tolist() + [self.eos_token]) + this_lm_input = torch.concat([self.llm_embedding.weight[self.sos].reshape(1, -1), text_token_emb[i], self.llm_embedding.weight[self.task_id].reshape(1, -1), speech_token_emb[i]], dim=0) lm_target.append(this_lm_target) lm_input.append(this_lm_input) @@ -445,13 +444,13 @@ class Qwen2LM(TransformerLM): text = self.llm.model.model.embed_tokens(text) # 3. concat llm_input - sos_eos_emb = self.llm_embedding.weight[self.sos_eos].reshape(1, 1, -1) + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) if prompt_speech_token_len != 0: prompt_speech_token_emb = self.speech_embedding(prompt_speech_token) else: prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device) - lm_input = torch.concat([sos_eos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1) + lm_input = torch.concat([sos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1) # 4. cal min/max_length min_len = int((text_len - prompt_text_len) * min_token_text_ratio) @@ -501,10 +500,8 @@ class Qwen2LM(TransformerLM): cache=cache) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False).item() - if top_ids == self.speech_token_size: + if top_ids in self.stop_token_ids: break - if top_ids > self.speech_token_size: - continue # in stream mode, yield token one by one yield top_ids out_tokens.append(top_ids) @@ -526,13 +523,13 @@ class Qwen2LM(TransformerLM): device = prompt_text.device # 1. prepare input - sos_eos_emb = self.llm_embedding.weight[self.sos_eos].reshape(1, 1, -1) + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) if prompt_speech_token_len != 0: prompt_speech_token_emb = self.speech_embedding(prompt_speech_token) else: prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=prompt_text.dtype).to(device) - lm_input = torch.concat([sos_eos_emb], dim=1) + lm_input = torch.concat([sos_emb], dim=1) # 2. iterate text out_tokens = [] @@ -554,12 +551,12 @@ class Qwen2LM(TransformerLM): break # no prompt_speech_token_emb remain, can decode some speech token if prompt_speech_token_emb.size(1) == 0: - if (len(out_tokens) != 0 and out_tokens[-1] == self.speech_token_size + 2) or (len(out_tokens) == 0 and lm_input.size(1) == 1): + if (len(out_tokens) != 0 and out_tokens[-1] == self.fill_token) or (len(out_tokens) == 0 and lm_input.size(1) == 1): logging.info('get fill token, need to append more text token') if text_cache.size(1) >= self.mix_ratio[0]: lm_input_text = text_cache[:, :self.mix_ratio[0]] logging.info('append {} text token'.format(lm_input_text.size(1))) - if len(out_tokens) != 0 and out_tokens[-1] == self.speech_token_size + 2: + if len(out_tokens) != 0 and out_tokens[-1] == self.fill_token: lm_input = lm_input_text else: lm_input = torch.concat([lm_input, lm_input_text], dim=1) @@ -574,16 +571,16 @@ class Qwen2LM(TransformerLM): cache=cache) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) if next_fill_index != -1 and len(out_tokens) == next_fill_index: - top_ids = self.speech_token_size + 2 + top_ids = self.fill_token next_fill_index += (self.mix_ratio[1] + 1) else: top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True).item() - if top_ids == self.speech_token_size + 2: + if top_ids == self.fill_token: next_fill_index = len(out_tokens) + self.mix_ratio[1] + 1 logging.info('fill_token index {} next fill_token index {}'.format(len(out_tokens), next_fill_index)) out_tokens.append(top_ids) if top_ids >= self.speech_token_size: - if top_ids == self.speech_token_size + 2: + if top_ids == self.fill_token: break else: raise ValueError('should not get token {}'.format(top_ids)) @@ -602,7 +599,7 @@ class Qwen2LM(TransformerLM): top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=False).item() out_tokens.append(top_ids) if top_ids >= self.speech_token_size: - if top_ids == self.speech_token_size: + if top_ids == self.eos_token: break else: raise ValueError('should not get token {}'.format(top_ids)) @@ -628,10 +625,10 @@ class CosyVoice3LM(Qwen2LM): self.llm_output_size = llm_output_size self.speech_token_size = speech_token_size # 2. build speech token language model related modules - self.sos = 0 - self.eos = 1 - self.task_id = 2 - self.fill_token = 3 + self.sos = speech_token_size + 0 + self.eos_token = speech_token_size + 1 + self.task_id = speech_token_size + 2 + self.fill_token = speech_token_size + 3 self.llm = llm self.llm_decoder = nn.Linear(llm_output_size, speech_token_size + 200, bias=False) @@ -649,6 +646,11 @@ class CosyVoice3LM(Qwen2LM): self.sampling = sampling self.mix_ratio = mix_ratio + # 5. vllm related + self.stop_token_ids = [speech_token_size + i for i in range(4)] + self.vllm_output_queue = {} + + @torch.inference_mode() def inference( self, @@ -670,13 +672,13 @@ class CosyVoice3LM(Qwen2LM): text = self.llm.model.model.embed_tokens(text) # 3. concat llm_input - sos_eos_emb = self.speech_embedding.weight[self.speech_token_size + self.sos].reshape(1, 1, -1) - task_id_emb = self.speech_embedding.weight[self.speech_token_size + self.task_id].reshape(1, 1, -1) + sos_emb = self.speech_embedding.weight[self.sos].reshape(1, 1, -1) + task_id_emb = self.speech_embedding.weight[self.task_id].reshape(1, 1, -1) if prompt_speech_token_len != 0: prompt_speech_token_emb = self.speech_embedding(prompt_speech_token) else: prompt_speech_token_emb = torch.zeros(1, 0, self.llm_input_size, dtype=text.dtype).to(device) - lm_input = torch.concat([sos_eos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1) + lm_input = torch.concat([sos_emb, text, task_id_emb, prompt_speech_token_emb], dim=1) # 4. cal min/max_length min_len = int((text_len - prompt_text_len) * min_token_text_ratio) diff --git a/cosyvoice/utils/class_utils.py b/cosyvoice/utils/class_utils.py index c52fec4..aab8326 100644 --- a/cosyvoice/utils/class_utils.py +++ b/cosyvoice/utils/class_utils.py @@ -32,10 +32,10 @@ from cosyvoice.transformer.attention import (MultiHeadedAttention, RelPositionMultiHeadedAttention) from cosyvoice.transformer.embedding import EspnetRelPositionalEncoding from cosyvoice.transformer.subsampling import LegacyLinearNoSubsampling -from cosyvoice.llm.llm import TransformerLM, Qwen2LM +from cosyvoice.llm.llm import TransformerLM, Qwen2LM, CosyVoice3LM from cosyvoice.flow.flow import MaskedDiffWithXvec, CausalMaskedDiffWithXvec, CausalMaskedDiffWithDiT from cosyvoice.hifigan.generator import HiFTGenerator, CausalHiFTGenerator -from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model +from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model, CosyVoice3Model COSYVOICE_ACTIVATION_CLASSES = { @@ -80,6 +80,6 @@ def get_model_type(configs): return CosyVoiceModel if isinstance(configs['llm'], Qwen2LM) and isinstance(configs['flow'], CausalMaskedDiffWithXvec) and isinstance(configs['hift'], HiFTGenerator): return CosyVoice2Model - if isinstance(configs['llm'], Qwen2LM) and isinstance(configs['flow'], CausalMaskedDiffWithDiT) and isinstance(configs['hift'], CausalHiFTGenerator): - return CosyVoice2Model + if isinstance(configs['llm'], CosyVoice3LM) and isinstance(configs['flow'], CausalMaskedDiffWithDiT) and isinstance(configs['hift'], CausalHiFTGenerator): + return CosyVoice3Model raise TypeError('No valid model type found!') From 6b5eef62ccb6240eee7aabb3018ecec0269ade66 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Fri, 22 Aug 2025 14:24:27 +0800 Subject: [PATCH 07/61] update --- cosyvoice/cli/model.py | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index c658996..b0fc120 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -403,11 +403,6 @@ class CosyVoice3Model(CosyVoice2Model): self.flow.half() # NOTE must matching training static_chunk_size self.token_hop_len = 25 - # hift cache - self.mel_cache_len = 8 - self.source_cache_len = int(self.mel_cache_len * 480) - # speech fade in out - self.speech_window = np.hamming(2 * self.source_cache_len) # rtf and decoding related self.llm_context = torch.cuda.stream(torch.cuda.Stream(self.device)) if torch.cuda.is_available() else nullcontext() self.lock = threading.Lock() @@ -428,26 +423,17 @@ class CosyVoice3Model(CosyVoice2Model): streaming=stream, finalize=finalize) tts_mel = tts_mel[:, :, token_offset * self.flow.token_mel_ratio:] - # append hift cache + # append mel cache if self.hift_cache_dict[uuid] is not None: - hift_cache_mel, hift_cache_source = self.hift_cache_dict[uuid]['mel'], self.hift_cache_dict[uuid]['source'] + hift_cache_mel = self.hift_cache_dict[uuid]['mel'] tts_mel = torch.concat([hift_cache_mel, tts_mel], dim=2) + self.hift_cache_dict[uuid]['mel'] = tts_mel else: - hift_cache_source = torch.zeros(1, 1, 0) - # keep overlap mel and hift cache - if finalize is False: - tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel, cache_source=hift_cache_source) - if self.hift_cache_dict[uuid] is not None: - tts_speech = fade_in_out(tts_speech, self.hift_cache_dict[uuid]['speech'], self.speech_window) - self.hift_cache_dict[uuid] = {'mel': tts_mel[:, :, -self.mel_cache_len:], - 'source': tts_source[:, :, -self.source_cache_len:], - 'speech': tts_speech[:, -self.source_cache_len:]} - tts_speech = tts_speech[:, :-self.source_cache_len] - else: - if speed != 1.0: - assert self.hift_cache_dict[uuid] is None, 'speed change only support non-stream inference mode' - tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') - tts_speech, tts_source = self.hift.inference(speech_feat=tts_mel) - if self.hift_cache_dict[uuid] is not None: - tts_speech = fade_in_out(tts_speech, self.hift_cache_dict[uuid]['speech'], self.speech_window) + self.hift_cache_dict[uuid] = {'mel': tts_mel, 'speech_offset': 0} + if speed != 1.0: + assert token_offset == 0 and finalize is True, 'speed change only support non-stream inference mode' + tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') + tts_speech, _ = self.hift.inference(speech_feat=tts_mel, finalize=finalize) + tts_speech = tts_speech[:, self.hift_cache_dict[uuid]['speech_offset']:] + self.hift_cache_dict[uuid]['speech_offset'] += tts_speech.shape[1] return tts_speech \ No newline at end of file From f76f5abcc1b3cfc6e372ba6bfb469e2f3467f86a Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Fri, 22 Aug 2025 14:42:34 +0800 Subject: [PATCH 08/61] update --- cosyvoice/llm/llm.py | 62 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index 85ad6fb..cba0c57 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -127,7 +127,7 @@ class TransformerLM(torch.nn.Module): embedding = self.spk_embed_affine_layer(embedding) embedding = embedding.unsqueeze(1) - # 3. eos and task_id + # 3. sos and task_id sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) @@ -300,7 +300,7 @@ class Qwen2LM(TransformerLM): self.stop_token_ids = [speech_token_size + i for i in range(3)] self.vllm_output_queue = {} - def prepare_lm_input_target(self, text_token, text_token_emb, text_token_len, speech_token, speech_token_emb, speech_token_len): + def prepare_lm_input_target(self, sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len): lm_target, lm_input = [], [] text_token = unpad_sequence(text_token, text_token_len.cpu(), batch_first=True) speech_token = unpad_sequence(speech_token, speech_token_len.cpu(), batch_first=True) @@ -311,7 +311,7 @@ class Qwen2LM(TransformerLM): if random.random() < 0.5 and speech_token_len[i] / text_token_len[i] > self.mix_ratio[1] / self.mix_ratio[0]: this_lm_target, this_lm_input = [], [] this_lm_target.append(IGNORE_ID) - this_lm_input.append(self.llm_embedding.weight[self.sos].reshape(1, -1)) + this_lm_input.append(sos_emb.squeeze(dim=0)) for j in range(((text_token_len[i] + 1) / self.mix_ratio[0]).ceil().int().item()): this_text_token = text_token[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]].tolist() this_speech_token = speech_token[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]].tolist() @@ -327,14 +327,13 @@ class Qwen2LM(TransformerLM): this_lm_target += speech_token[i][j * self.mix_ratio[1]:].tolist() this_lm_target.append(self.eos_token) this_lm_input.append(text_token_emb[i][j * self.mix_ratio[0]:]) - this_lm_input.append(self.llm_embedding.weight[self.task_id].reshape(1, -1)) + this_lm_input.append(task_id_emb.squeeze(dim=0)) this_lm_input.append(speech_token_emb[i][j * self.mix_ratio[1]:]) this_lm_target, this_lm_input = torch.tensor(this_lm_target), torch.concat(this_lm_input, dim=0) # unistream sequence else: this_lm_target = torch.tensor([IGNORE_ID] * (1 + text_token_len[i]) + speech_token[i].tolist() + [self.eos_token]) - this_lm_input = torch.concat([self.llm_embedding.weight[self.sos].reshape(1, -1), text_token_emb[i], - self.llm_embedding.weight[self.task_id].reshape(1, -1), speech_token_emb[i]], dim=0) + this_lm_input = torch.concat([sos_emb.squeeze(dim=0), text_token_emb[i], task_id_emb.squeeze(dim=0), speech_token_emb[i]], dim=0) lm_target.append(this_lm_target) lm_input.append(this_lm_input) lm_input_len = torch.tensor([i.size(0) for i in lm_input], dtype=torch.int32) @@ -362,11 +361,15 @@ class Qwen2LM(TransformerLM): # 1. encode text_token text_token_emb = self.llm.model.model.embed_tokens(text_token) + # 3. sos and task_id + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) + task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) + # 2. encode speech_token speech_token_emb = self.speech_embedding(speech_token) # 3. prepare llm_input/target - lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(text_token, text_token_emb, text_token_len, speech_token, speech_token_emb, speech_token_len) + lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len) lm_target = lm_target.to(device) # 4. run lm forward @@ -391,6 +394,10 @@ class Qwen2LM(TransformerLM): # 1. encode text_token text_token_emb = self.llm.model.model.embed_tokens(text_token) + # 3. sos and task_id + sos_emb = self.llm_embedding.weight[self.sos].reshape(1, 1, -1) + task_id_emb = self.llm_embedding.weight[self.task_id].reshape(1, 1, -1) + # 2. encode speech_token speech_token = unpad_sequence(speech_token, speech_token_len.cpu(), batch_first=True) reject_speech_token = unpad_sequence(reject_speech_token, reject_speech_token_len.cpu(), batch_first=True) @@ -400,8 +407,8 @@ class Qwen2LM(TransformerLM): speech_token_combined_emb = self.speech_embedding(speech_token_combined) # 3. prepare llm_input/target - lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(text_token.repeat(2, 1), text_token_emb.repeat(2, 1, 1), text_token_len.repeat(2), - speech_token_combined, speech_token_combined_emb, speech_token_combined_len) + lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token.repeat(2, 1), text_token_emb.repeat(2, 1, 1), text_token_len.repeat(2), + task_id_emb, speech_token_combined, speech_token_combined_emb, speech_token_combined_len) lm_target = lm_target.to(device) # 4. run lm forward @@ -650,6 +657,43 @@ class CosyVoice3LM(Qwen2LM): self.stop_token_ids = [speech_token_size + i for i in range(4)] self.vllm_output_queue = {} + def forward( + self, + batch: dict, + device: torch.device, + ) -> Dict[str, Optional[torch.Tensor]]: + """ + Args: + text: (B, L, D) + text_lengths: (B,) + audio: (B, T, N) or (B, T) + audio_lengths: (B,) + """ + text_token = batch['text_token'].to(device) + text_token_len = batch['text_token_len'].to(device) + speech_token = batch['speech_token'].to(device) + speech_token_len = batch['speech_token_len'].to(device) + + # 1. encode text_token + text_token_emb = self.llm.model.model.embed_tokens(text_token) + + # 3. sos and task_id + sos_emb = self.speech_embedding.weight[self.sos].reshape(1, 1, -1) + task_id_emb = self.speech_embedding.weight[self.task_id].reshape(1, 1, -1) + + # 2. encode speech_token + speech_token_emb = self.speech_embedding(speech_token) + + # 3. prepare llm_input/target + lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len) + lm_target = lm_target.to(device) + + # 4. run lm forward + lm_output, lm_output_mask = self.llm(lm_input, lm_input_len.to(device)) + logits = self.llm_decoder(lm_output) + loss = self.criterion_ce(logits, lm_target.to(device)) + acc = th_accuracy(logits.view(-1, self.speech_token_size + 3), lm_target, ignore_label=IGNORE_ID) + return {'loss': loss, 'acc': acc} @torch.inference_mode() def inference( From cd26dd19329a2e3f56ce530d4a062a438c20ea06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=98=EC=A7=84?= Date: Mon, 27 Oct 2025 17:20:14 +0900 Subject: [PATCH 09/61] fix triton token2wav model cache thread unsafety --- runtime/triton_trtllm/model_repo/token2wav/1/model.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/triton_trtllm/model_repo/token2wav/1/model.py b/runtime/triton_trtllm/model_repo/token2wav/1/model.py index 1e38052..53d5a54 100644 --- a/runtime/triton_trtllm/model_repo/token2wav/1/model.py +++ b/runtime/triton_trtllm/model_repo/token2wav/1/model.py @@ -28,6 +28,7 @@ import json import os import logging +from uuid import uuid4 import torch from torch.utils.dlpack import to_dlpack @@ -235,17 +236,17 @@ class TritonPythonModel: stream = True else: stream = False - request_id = request.request_id() + uuid = uuid4().hex audio_hat = self.token2wav_model.model.token2wav(token=target_speech_tokens, prompt_token=prompt_speech_tokens, prompt_feat=prompt_speech_feat, embedding=prompt_spk_embedding, token_offset=token_offset, - uuid=request_id, + uuid=uuid, stream=stream, finalize=finalize) if finalize: - self.token2wav_model.model.hift_cache_dict.pop(request_id) + self.token2wav_model.model.hift_cache_dict.pop(uuid) else: tts_mel, _ = self.token2wav_model.model.flow.inference( From fa2781405f8df3cc0bc02593400559c24f26e0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=98=EC=A7=84?= Date: Mon, 27 Oct 2025 18:07:30 +0900 Subject: [PATCH 10/61] Revert "fix triton token2wav model cache thread unsafety" This reverts commit cd26dd19329a2e3f56ce530d4a062a438c20ea06. --- runtime/triton_trtllm/model_repo/token2wav/1/model.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/runtime/triton_trtllm/model_repo/token2wav/1/model.py b/runtime/triton_trtllm/model_repo/token2wav/1/model.py index 53d5a54..1e38052 100644 --- a/runtime/triton_trtllm/model_repo/token2wav/1/model.py +++ b/runtime/triton_trtllm/model_repo/token2wav/1/model.py @@ -28,7 +28,6 @@ import json import os import logging -from uuid import uuid4 import torch from torch.utils.dlpack import to_dlpack @@ -236,17 +235,17 @@ class TritonPythonModel: stream = True else: stream = False - uuid = uuid4().hex + request_id = request.request_id() audio_hat = self.token2wav_model.model.token2wav(token=target_speech_tokens, prompt_token=prompt_speech_tokens, prompt_feat=prompt_speech_feat, embedding=prompt_spk_embedding, token_offset=token_offset, - uuid=uuid, + uuid=request_id, stream=stream, finalize=finalize) if finalize: - self.token2wav_model.model.hift_cache_dict.pop(uuid) + self.token2wav_model.model.hift_cache_dict.pop(request_id) else: tts_mel, _ = self.token2wav_model.model.flow.inference( From e8bf717333d0418c4421c456a14df92cda5a46bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=98=EC=A7=84?= Date: Mon, 27 Oct 2025 18:12:17 +0900 Subject: [PATCH 11/61] Fix: generate token2wav_request_id from cosyvoice2 - Since all token2wav requests within a single cosyvoice2 request must share the same request_id, modify the logic so that a new request_id is generated only if it does not already exist, and ensure that the same request_id is sent consistently. --- runtime/triton_trtllm/model_repo/cosyvoice2/1/model.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/runtime/triton_trtllm/model_repo/cosyvoice2/1/model.py b/runtime/triton_trtllm/model_repo/cosyvoice2/1/model.py index a2bfb30..94c82c6 100644 --- a/runtime/triton_trtllm/model_repo/cosyvoice2/1/model.py +++ b/runtime/triton_trtllm/model_repo/cosyvoice2/1/model.py @@ -28,6 +28,7 @@ import json import os import threading import time +from uuid import uuid4 import numpy as np import torch @@ -364,6 +365,7 @@ class TritonPythonModel: # Generate semantic tokens with LLM generated_ids_iter = self.forward_llm(input_ids) + token2wav_request_id = request_id or str(uuid4()) if self.decoupled: response_sender = request.get_response_sender() @@ -392,7 +394,7 @@ class TritonPythonModel: this_tts_speech_token = torch.tensor(this_tts_speech_token).unsqueeze(dim=0).to(torch.int32).to(self.device) sub_tts_speech = self.forward_token2wav( - this_tts_speech_token, request_id, prompt_speech_tokens, + this_tts_speech_token, token2wav_request_id, prompt_speech_tokens, prompt_speech_feat, prompt_spk_embedding, token_offset, False ) @@ -427,7 +429,7 @@ class TritonPythonModel: time.sleep(0.02) this_tts_speech_token = torch.tensor(semantic_token_ids_arr).unsqueeze(dim=0).to(torch.int32).to(self.device) - sub_tts_speech = self.forward_token2wav(this_tts_speech_token, request_id, prompt_speech_tokens, prompt_speech_feat, prompt_spk_embedding, token_offset, True) + sub_tts_speech = self.forward_token2wav(this_tts_speech_token, token2wav_request_id, prompt_speech_tokens, prompt_speech_feat, prompt_spk_embedding, token_offset, True) audio_tensor = pb_utils.Tensor.from_dlpack("waveform", to_dlpack(sub_tts_speech)) inference_response = pb_utils.InferenceResponse(output_tensors=[audio_tensor]) response_sender.send(inference_response) @@ -441,7 +443,7 @@ class TritonPythonModel: if generated_ids is None or len(generated_ids) == 0: raise pb_utils.TritonModelException("Generated IDs is None or empty") - audio = self.forward_token2wav(generated_ids, request_id, prompt_speech_tokens, prompt_speech_feat, prompt_spk_embedding) + audio = self.forward_token2wav(generated_ids, token2wav_request_id, prompt_speech_tokens, prompt_speech_feat, prompt_spk_embedding) # Prepare response audio_tensor = pb_utils.Tensor.from_dlpack("waveform", to_dlpack(audio)) From 622a3a19b03a1c752fdadb7304901b36f6381ee7 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 8 Dec 2025 08:43:09 +0000 Subject: [PATCH 12/61] use wav file rather than tensor --- cosyvoice/cli/cosyvoice.py | 20 +++++++++---------- cosyvoice/cli/frontend.py | 37 ++++++++++++++++++----------------- cosyvoice/utils/file_utils.py | 4 ++-- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 910fa74..47f8336 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -67,9 +67,9 @@ class CosyVoice: spks = list(self.frontend.spk2info.keys()) return spks - def add_zero_shot_spk(self, prompt_text, prompt_speech_16k, zero_shot_spk_id): + def add_zero_shot_spk(self, prompt_text, prompt_wav, zero_shot_spk_id): assert zero_shot_spk_id != '', 'do not use empty zero_shot_spk_id' - model_input = self.frontend.frontend_zero_shot('', prompt_text, prompt_speech_16k, self.sample_rate, '') + model_input = self.frontend.frontend_zero_shot('', prompt_text, prompt_wav, self.sample_rate, '') del model_input['text'] del model_input['text_len'] self.frontend.spk2info[zero_shot_spk_id] = model_input @@ -89,12 +89,12 @@ class CosyVoice: yield model_output start_time = time.time() - def inference_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): + def inference_zero_shot(self, tts_text, prompt_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): prompt_text = self.frontend.text_normalize(prompt_text, split=False, text_frontend=text_frontend) for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): if (not isinstance(i, Generator)) and len(i) < 0.5 * len(prompt_text): logging.warning('synthesis text {} too short than prompt text {}, this may lead to bad performance'.format(i, prompt_text)) - model_input = self.frontend.frontend_zero_shot(i, prompt_text, prompt_speech_16k, self.sample_rate, zero_shot_spk_id) + model_input = self.frontend.frontend_zero_shot(i, prompt_text, prompt_wav, self.sample_rate, zero_shot_spk_id) start_time = time.time() logging.info('synthesis text {}'.format(i)) for model_output in self.model.tts(**model_input, stream=stream, speed=speed): @@ -103,9 +103,9 @@ class CosyVoice: yield model_output start_time = time.time() - def inference_cross_lingual(self, tts_text, prompt_speech_16k, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): + def inference_cross_lingual(self, tts_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): - model_input = self.frontend.frontend_cross_lingual(i, prompt_speech_16k, self.sample_rate, zero_shot_spk_id) + model_input = self.frontend.frontend_cross_lingual(i, prompt_wav, self.sample_rate, zero_shot_spk_id) start_time = time.time() logging.info('synthesis text {}'.format(i)) for model_output in self.model.tts(**model_input, stream=stream, speed=speed): @@ -129,8 +129,8 @@ class CosyVoice: yield model_output start_time = time.time() - def inference_vc(self, source_speech_16k, prompt_speech_16k, stream=False, speed=1.0): - model_input = self.frontend.frontend_vc(source_speech_16k, prompt_speech_16k, self.sample_rate) + def inference_vc(self, source_wav, prompt_wav, stream=False, speed=1.0): + model_input = self.frontend.frontend_vc(source_wav, prompt_wav, self.sample_rate) start_time = time.time() for model_output in self.model.tts(**model_input, stream=stream, speed=speed): speech_len = model_output['tts_speech'].shape[1] / self.sample_rate @@ -181,10 +181,10 @@ class CosyVoice2(CosyVoice): def inference_instruct(self, *args, **kwargs): raise NotImplementedError('inference_instruct is not implemented for CosyVoice2!') - def inference_instruct2(self, tts_text, instruct_text, prompt_speech_16k, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): + def inference_instruct2(self, tts_text, instruct_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): assert isinstance(self.model, CosyVoice2Model), 'inference_instruct2 is only implemented for CosyVoice2!' for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): - model_input = self.frontend.frontend_instruct2(i, instruct_text, prompt_speech_16k, self.sample_rate, zero_shot_spk_id) + model_input = self.frontend.frontend_instruct2(i, instruct_text, prompt_wav, self.sample_rate, zero_shot_spk_id) start_time = time.time() logging.info('synthesis text {}'.format(i)) for model_output in self.model.tts(**model_input, stream=stream, speed=speed): diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index f98b0d6..d614883 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -32,7 +32,7 @@ except ImportError: from wetext import Normalizer as ZhNormalizer from wetext import Normalizer as EnNormalizer use_ttsfrd = False -from cosyvoice.utils.file_utils import logging +from cosyvoice.utils.file_utils import logging, load_wav from cosyvoice.utils.frontend_utils import contains_chinese, replace_blank, replace_corner_mark, remove_bracket, spell_out_number, split_paragraph, is_only_punctuation @@ -89,7 +89,8 @@ class CosyVoiceFrontEnd: for i in range(text_token.shape[1]): yield text_token[:, i: i + 1] - def _extract_speech_token(self, speech): + def _extract_speech_token(self, prompt_wav): + speech = load_wav(prompt_wav, 16000) assert speech.shape[1] / 16000 <= 30, 'do not support extract speech token for audio longer than 30s' feat = whisper.log_mel_spectrogram(speech, n_mels=128) speech_token = self.speech_tokenizer_session.run(None, @@ -101,7 +102,8 @@ class CosyVoiceFrontEnd: speech_token_len = torch.tensor([speech_token.shape[1]], dtype=torch.int32).to(self.device) return speech_token, speech_token_len - def _extract_spk_embedding(self, speech): + def _extract_spk_embedding(self, prompt_wav): + speech = load_wav(prompt_wav, 16000) feat = kaldi.fbank(speech, num_mel_bins=80, dither=0, @@ -112,7 +114,8 @@ class CosyVoiceFrontEnd: embedding = torch.tensor([embedding]).to(self.device) return embedding - def _extract_speech_feat(self, speech): + def _extract_speech_feat(self, prompt_wav): + speech = load_wav(prompt_wav, 24000) speech_feat = self.feat_extractor(speech).squeeze(dim=0).transpose(0, 1).to(self.device) speech_feat = speech_feat.unsqueeze(dim=0) speech_feat_len = torch.tensor([speech_feat.shape[1]], dtype=torch.int32).to(self.device) @@ -154,19 +157,18 @@ class CosyVoiceFrontEnd: model_input = {'text': tts_text_token, 'text_len': tts_text_token_len, 'llm_embedding': embedding, 'flow_embedding': embedding} return model_input - def frontend_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, resample_rate, zero_shot_spk_id): + def frontend_zero_shot(self, tts_text, prompt_text, prompt_wav, resample_rate, zero_shot_spk_id): tts_text_token, tts_text_token_len = self._extract_text_token(tts_text) if zero_shot_spk_id == '': prompt_text_token, prompt_text_token_len = self._extract_text_token(prompt_text) - prompt_speech_resample = torchaudio.transforms.Resample(orig_freq=16000, new_freq=resample_rate)(prompt_speech_16k) - speech_feat, speech_feat_len = self._extract_speech_feat(prompt_speech_resample) - speech_token, speech_token_len = self._extract_speech_token(prompt_speech_16k) + speech_feat, speech_feat_len = self._extract_speech_feat(prompt_wav) + speech_token, speech_token_len = self._extract_speech_token(prompt_wav) if resample_rate == 24000: # cosyvoice2, force speech_feat % speech_token = 2 token_len = min(int(speech_feat.shape[1] / 2), speech_token.shape[1]) speech_feat, speech_feat_len[:] = speech_feat[:, :2 * token_len], 2 * token_len speech_token, speech_token_len[:] = speech_token[:, :token_len], token_len - embedding = self._extract_spk_embedding(prompt_speech_16k) + embedding = self._extract_spk_embedding(prompt_wav) model_input = {'prompt_text': prompt_text_token, 'prompt_text_len': prompt_text_token_len, 'llm_prompt_speech_token': speech_token, 'llm_prompt_speech_token_len': speech_token_len, 'flow_prompt_speech_token': speech_token, 'flow_prompt_speech_token_len': speech_token_len, @@ -178,8 +180,8 @@ class CosyVoiceFrontEnd: model_input['text_len'] = tts_text_token_len return model_input - def frontend_cross_lingual(self, tts_text, prompt_speech_16k, resample_rate, zero_shot_spk_id): - model_input = self.frontend_zero_shot(tts_text, '', prompt_speech_16k, resample_rate, zero_shot_spk_id) + def frontend_cross_lingual(self, tts_text, prompt_wav, resample_rate, zero_shot_spk_id): + model_input = self.frontend_zero_shot(tts_text, '', prompt_wav, resample_rate, zero_shot_spk_id) # in cross lingual mode, we remove prompt in llm del model_input['prompt_text'] del model_input['prompt_text_len'] @@ -196,17 +198,16 @@ class CosyVoiceFrontEnd: model_input['prompt_text_len'] = instruct_text_token_len return model_input - def frontend_instruct2(self, tts_text, instruct_text, prompt_speech_16k, resample_rate, zero_shot_spk_id): - model_input = self.frontend_zero_shot(tts_text, instruct_text + '<|endofprompt|>', prompt_speech_16k, resample_rate, zero_shot_spk_id) + def frontend_instruct2(self, tts_text, instruct_text, prompt_wav, resample_rate, zero_shot_spk_id): + model_input = self.frontend_zero_shot(tts_text, instruct_text + '<|endofprompt|>', prompt_wav, resample_rate, zero_shot_spk_id) del model_input['llm_prompt_speech_token'] del model_input['llm_prompt_speech_token_len'] return model_input - def frontend_vc(self, source_speech_16k, prompt_speech_16k, resample_rate): - prompt_speech_token, prompt_speech_token_len = self._extract_speech_token(prompt_speech_16k) - prompt_speech_resample = torchaudio.transforms.Resample(orig_freq=16000, new_freq=resample_rate)(prompt_speech_16k) - prompt_speech_feat, prompt_speech_feat_len = self._extract_speech_feat(prompt_speech_resample) - embedding = self._extract_spk_embedding(prompt_speech_16k) + def frontend_vc(self, source_speech_16k, prompt_wav, resample_rate): + prompt_speech_token, prompt_speech_token_len = self._extract_speech_token(prompt_wav) + prompt_speech_feat, prompt_speech_feat_len = self._extract_speech_feat(prompt_wav) + embedding = self._extract_spk_embedding(prompt_wav) source_speech_token, source_speech_token_len = self._extract_speech_token(source_speech_16k) model_input = {'source_speech_token': source_speech_token, 'source_speech_token_len': source_speech_token_len, 'flow_prompt_speech_token': prompt_speech_token, 'flow_prompt_speech_token_len': prompt_speech_token_len, diff --git a/cosyvoice/utils/file_utils.py b/cosyvoice/utils/file_utils.py index a92f8e7..374a90e 100644 --- a/cosyvoice/utils/file_utils.py +++ b/cosyvoice/utils/file_utils.py @@ -41,11 +41,11 @@ def read_json_lists(list_file): return results -def load_wav(wav, target_sr): +def load_wav(wav, target_sr, min_sr=16000): speech, sample_rate = torchaudio.load(wav, backend='soundfile') speech = speech.mean(dim=0, keepdim=True) if sample_rate != target_sr: - assert sample_rate > target_sr, 'wav sample rate {} must be greater than {}'.format(sample_rate, target_sr) + assert sample_rate >= min_sr, 'wav sample rate {} must be greater than {}'.format(sample_rate, target_sr) speech = torchaudio.transforms.Resample(orig_freq=sample_rate, new_freq=target_sr)(speech) return speech From bfa835a74b9f5085658b180c2a9ffbf69ac9676c Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 8 Dec 2025 10:04:11 +0000 Subject: [PATCH 13/61] add cosyvoice3 inference code --- README.md | 94 ++++-------------------------------- cosyvoice/cli/cosyvoice.py | 4 +- cosyvoice/utils/common.py | 26 ++++++++++ example.py | 97 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 86 deletions(-) create mode 100644 example.py diff --git a/README.md b/README.md index 1d32e44..495934a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## 👉🏻 CosyVoice 👈🏻 -**CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) +**CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) **CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/spaces/FunAudioLLM/CosyVoice2-0.5B) @@ -29,6 +29,11 @@ ## Roadmap +- [x] 2025/12 + + - [x] release cosyvoice3-0.5B base model and its training/inference script + - [x] release cosyvoice3-0.5B modelscope gradio space + - [x] 2025/08 - [x] Thanks to the contribution from NVIDIA Yuekai Zhang, add triton trtllm runtime support and cosyvoice2 grpo training support @@ -96,6 +101,7 @@ We strongly recommend that you download our pretrained `CosyVoice2-0.5B` `CosyVo ``` python # SDK模型下载 from modelscope import snapshot_download +snapshot_download('iic/CosyVoice3-0.5B', local_dir='pretrained_models/CosyVoice3-0.5B') snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B') snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M') snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT') @@ -103,16 +109,6 @@ snapshot_download('iic/CosyVoice-300M-Instruct', local_dir='pretrained_models/Co snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd') ``` -``` sh -# git模型下载,请确保已安装git lfs -mkdir -p pretrained_models -git clone https://www.modelscope.cn/iic/CosyVoice2-0.5B.git pretrained_models/CosyVoice2-0.5B -git clone https://www.modelscope.cn/iic/CosyVoice-300M.git pretrained_models/CosyVoice-300M -git clone https://www.modelscope.cn/iic/CosyVoice-300M-SFT.git pretrained_models/CosyVoice-300M-SFT -git clone https://www.modelscope.cn/iic/CosyVoice-300M-Instruct.git pretrained_models/CosyVoice-300M-Instruct -git clone https://www.modelscope.cn/iic/CosyVoice-ttsfrd.git pretrained_models/CosyVoice-ttsfrd -``` - Optionally, you can unzip `ttsfrd` resource and install `ttsfrd` package for better text normalization performance. Notice that this step is not necessary. If you do not install `ttsfrd` package, we will use wetext by default. @@ -127,49 +123,9 @@ pip install ttsfrd-0.4.2-cp310-cp310-linux_x86_64.whl ### Basic Usage We strongly recommend using `CosyVoice2-0.5B` for better performance. -Follow the code below for detailed usage of each model. - -``` python -import sys -sys.path.append('third_party/Matcha-TTS') -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 -from cosyvoice.utils.file_utils import load_wav -import torchaudio -``` - -#### CosyVoice2 Usage -```python -cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B', load_jit=False, load_trt=False, load_vllm=False, fp16=False) - -# NOTE if you want to reproduce the results on https://funaudiollm.github.io/cosyvoice2, please add text_frontend=False during inference -# zero_shot usage -prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000) -for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)): - torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - -# save zero_shot spk for future usage -assert cosyvoice.add_zero_shot_spk('希望你以后能够做的比我还好呦。', prompt_speech_16k, 'my_zero_shot_spk') is True -for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '', '', zero_shot_spk_id='my_zero_shot_spk', stream=False)): - torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) -cosyvoice.save_spkinfo() - -# fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L248 -for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', prompt_speech_16k, stream=False)): - torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - -# instruct usage -for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话', prompt_speech_16k, stream=False)): - torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - -# bistream usage, you can use generator as input, this is useful when using text llm model as input -# NOTE you should still have some basic sentence split logic because llm can not handle arbitrary sentence length -def text_generator(): - yield '收到好友从远方寄来的生日礼物,' - yield '那份意外的惊喜与深深的祝福' - yield '让我心中充满了甜蜜的快乐,' - yield '笑容如花儿般绽放。' -for i, j in enumerate(cosyvoice.inference_zero_shot(text_generator(), '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)): - torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) +Follow the code in `example.py` for detailed usage of each model. +```sh +python example.py ``` #### CosyVoice2 vllm Usage @@ -184,36 +140,6 @@ pip install vllm==v0.9.0 transformers==4.51.3 -i https://mirrors.aliyun.com/pypi python vllm_example.py ``` -#### CosyVoice Usage -```python -cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-SFT', load_jit=False, load_trt=False, fp16=False) -# sft usage -print(cosyvoice.list_available_spks()) -# change stream=True for chunk stream inference -for i, j in enumerate(cosyvoice.inference_sft('你好,我是通义生成式语音大模型,请问有什么可以帮您的吗?', '中文女', stream=False)): - torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - -cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M') -# zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean -prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000) -for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)): - torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) -# cross_lingual usage -prompt_speech_16k = load_wav('./asset/cross_lingual_prompt.wav', 16000) -for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', prompt_speech_16k, stream=False)): - torchaudio.save('cross_lingual_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) -# vc usage -prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000) -source_speech_16k = load_wav('./asset/cross_lingual_prompt.wav', 16000) -for i, j in enumerate(cosyvoice.inference_vc(source_speech_16k, prompt_speech_16k, stream=False)): - torchaudio.save('vc_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - -cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-Instruct') -# instruct usage, support [laughter][breath] -for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.', stream=False)): - torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) -``` - #### Start web demo You can use our web demo page to get familiar with CosyVoice quickly. diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 47f8336..1f2f60a 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -182,7 +182,7 @@ class CosyVoice2(CosyVoice): raise NotImplementedError('inference_instruct is not implemented for CosyVoice2!') def inference_instruct2(self, tts_text, instruct_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): - assert isinstance(self.model, CosyVoice2Model), 'inference_instruct2 is only implemented for CosyVoice2!' + assert isinstance(self.model, CosyVoice2Model) or isinstance(self.model, CosyVoice3Model), 'inference_instruct2 is only implemented for CosyVoice2 and CosyVoice3!' for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): model_input = self.frontend.frontend_instruct2(i, instruct_text, prompt_wav, self.sample_rate, zero_shot_spk_id) start_time = time.time() @@ -194,7 +194,7 @@ class CosyVoice2(CosyVoice): start_time = time.time() -class CosyVoice3(CosyVoice): +class CosyVoice3(CosyVoice2): def __init__(self, model_dir, load_jit=False, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): self.instruct = True if '-Instruct' in model_dir else False diff --git a/cosyvoice/utils/common.py b/cosyvoice/utils/common.py index 6f5a3dd..2b602fa 100644 --- a/cosyvoice/utils/common.py +++ b/cosyvoice/utils/common.py @@ -25,6 +25,32 @@ import torch IGNORE_ID = -1 +instruct_list = ["You are a helpful assistant. 请用广东话表达。", + "You are a helpful assistant. 请用东北话表达。", + "You are a helpful assistant. 请用甘肃话表达。", + "You are a helpful assistant. 请用贵州话表达。", + "You are a helpful assistant. 请用河南话表达。", + "You are a helpful assistant. 请用湖北话表达。", + "You are a helpful assistant. 请用湖南话表达。", + "You are a helpful assistant. 请用江西话表达。", + "You are a helpful assistant. 请用闽南话表达。", + "You are a helpful assistant. 请用宁夏话表达。", + "You are a helpful assistant. 请用山西话表达。", + "You are a helpful assistant. 请用陕西话表达。", + "You are a helpful assistant. 请用山东话表达。", + "You are a helpful assistant. 请用上海话表达。", + "You are a helpful assistant. 请用四川话表达。", + "You are a helpful assistant. 请用天津话表达。", + "You are a helpful assistant. 请用云南话表达。", + "You are a helpful assistant. Please say a sentence as loudly as possible.", + "You are a helpful assistant. Please say a sentence in a very soft voice.", + "You are a helpful assistant. 请用尽可能慢地语速说一句话。", + "You are a helpful assistant. 请用尽可能快地语速说一句话。", + "You are a helpful assistant. 请非常开心地说一句话。", + "You are a helpful assistant. 请非常伤心地说一句话。", + "You are a helpful assistant. 请非常生气地说一句话。", + "You are a helpful assistant. 我想体验一下小猪佩奇风格,可以吗?", + "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?"] def pad_list(xs: List[torch.Tensor], pad_value: int): """Perform padding for the list of tensors. diff --git a/example.py b/example.py new file mode 100644 index 0000000..70d0d8c --- /dev/null +++ b/example.py @@ -0,0 +1,97 @@ +import sys +sys.path.append('third_party/Matcha-TTS') +from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2, CosyVoice3 +from cosyvoice.utils.file_utils import load_wav +import torchaudio + + +def cosyvoice_example(): + """ CosyVoice Usage, check https://fun-audio-llm.github.io/ for more details + """ + cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-SFT', load_jit=False, load_trt=False, fp16=False) + # sft usage + print(cosyvoice.list_available_spks()) + # change stream=True for chunk stream inference + for i, j in enumerate(cosyvoice.inference_sft('你好,我是通义生成式语音大模型,请问有什么可以帮您的吗?', '中文女', stream=False)): + torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M') + # zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + # cross_lingual usage + for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', './asset/cross_lingual_prompt.wav', stream=False)): + torchaudio.save('cross_lingual_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + # vc usage + for i, j in enumerate(cosyvoice.inference_vc('./asset/zero_shot_prompt.wav', './asset/cross_lingual_prompt.wav', stream=False)): + torchaudio.save('vc_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-Instruct') + # instruct usage, support [laughter][breath] + for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.', stream=False)): + torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + +def cosyvoice2_example(): + """ CosyVoice2 Usage, check https://funaudiollm.github.io/cosyvoice2/ for more details + """ + cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B', load_jit=False, load_trt=False, load_vllm=False, fp16=False) + + # NOTE if you want to reproduce the results on https://funaudiollm.github.io/cosyvoice2, please add text_frontend=False during inference + # zero_shot usage + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # save zero_shot spk for future usage + assert cosyvoice.add_zero_shot_spk('希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', 'my_zero_shot_spk') is True + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '', '', zero_shot_spk_id='my_zero_shot_spk', stream=False)): + torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + cosyvoice.save_spkinfo() + + # fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L248 + for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # instruct usage + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # bistream usage, you can use generator as input, this is useful when using text llm model as input + # NOTE you should still have some basic sentence split logic because llm can not handle arbitrary sentence length + def text_generator(): + yield '收到好友从远方寄来的生日礼物,' + yield '那份意外的惊喜与深深的祝福' + yield '让我心中充满了甜蜜的快乐,' + yield '笑容如花儿般绽放。' + for i, j in enumerate(cosyvoice.inference_zero_shot(text_generator(), '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + +def cosyvoice3_example(): + """ CosyVoice3 Usage, check https://funaudiollm.github.io/cosyvoice3/ for more details + """ + cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_jit=False, load_trt=False, fp16=False) + # zero_shot usage + for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L280 + for i, j in enumerate(cosyvoice.inference_cross_lingual('[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # instruct usage + for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + + # hotfix usage + for i, j in enumerate(cosyvoice.inference_zero_shot('高管也通过电话、短信、微信等方式对报道[j][ǐ]予好评。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + torchaudio.save('hotfix_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + +def main(): + # cosyvoice_example() + cosyvoice2_example() + cosyvoice3_example() + + +if __name__ == '__main__': + main() From b4dd67a8afcf71d49a07ad1ec22d0abf2628eb00 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 8 Dec 2025 10:55:53 +0000 Subject: [PATCH 14/61] add cosyvoice3 vllm example --- cosyvoice/utils/file_utils.py | 16 +++++++++++----- example.py | 2 +- vllm_example.py | 21 +++++++++++++++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/cosyvoice/utils/file_utils.py b/cosyvoice/utils/file_utils.py index 374a90e..358a9f6 100644 --- a/cosyvoice/utils/file_utils.py +++ b/cosyvoice/utils/file_utils.py @@ -88,6 +88,7 @@ def convert_onnx_to_trt(trt_model, trt_kwargs, onnx_model, fp16): logging.info("Succesfully convert onnx to trt...") +# NOTE do not support bistream inference as only speech token embedding/head is kept def export_cosyvoice2_vllm(model, model_path, device): if os.path.exists(model_path): return @@ -98,12 +99,14 @@ def export_cosyvoice2_vllm(model, model_path, device): dtype = torch.bfloat16 # lm_head - new_lm_head = torch.nn.Linear(in_features=feature_size, out_features=pad_vocab_size, bias=True) + use_bias = True if model.llm_decoder.bias is not None else False + new_lm_head = torch.nn.Linear(in_features=feature_size, out_features=pad_vocab_size, bias=use_bias) with torch.no_grad(): new_lm_head.weight[:vocab_size] = model.llm_decoder.weight - new_lm_head.bias[:vocab_size] = model.llm_decoder.bias new_lm_head.weight[vocab_size:] = 0 - new_lm_head.bias[vocab_size:] = 0 + if use_bias is True: + new_lm_head.bias[:vocab_size] = model.llm_decoder.bias + new_lm_head.bias[vocab_size:] = 0 model.llm.model.lm_head = new_lm_head new_codec_embed = torch.nn.Linear(in_features=feature_size, out_features=pad_vocab_size) # embed_tokens @@ -121,9 +124,12 @@ def export_cosyvoice2_vllm(model, model_path, device): del model.llm.model.config.eos_token_id model.llm.model.config.vocab_size = pad_vocab_size model.llm.model.config.tie_word_embeddings = False - model.llm.model.config.use_bias = True + model.llm.model.config.use_bias = use_bias model.llm.model.save_pretrained(model_path) - os.system('sed -i s@Qwen2ForCausalLM@CosyVoice2ForCausalLM@g {}/config.json'.format(os.path.abspath(model_path))) + if use_bias is True: + os.system('sed -i s@Qwen2ForCausalLM@CosyVoice2ForCausalLM@g {}/config.json'.format(os.path.abspath(model_path))) + else: + os.system('sed -i s@Qwen2ForCausalLM@Qwen2ForCausalLM@g {}/config.json'.format(os.path.abspath(model_path))) model.llm.model.config.vocab_size = tmp_vocab_size model.llm.model.config.tie_word_embeddings = tmp_tie_embedding model.llm.model.set_input_embeddings(embed_tokens) diff --git a/example.py b/example.py index 70d0d8c..ba7c5a2 100644 --- a/example.py +++ b/example.py @@ -88,7 +88,7 @@ def cosyvoice3_example(): torchaudio.save('hotfix_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) def main(): - # cosyvoice_example() + cosyvoice_example() cosyvoice2_example() cosyvoice3_example() diff --git a/vllm_example.py b/vllm_example.py index e613033..8b177a3 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -4,20 +4,33 @@ from vllm import ModelRegistry from cosyvoice.vllm.cosyvoice2 import CosyVoice2ForCausalLM ModelRegistry.register_model("CosyVoice2ForCausalLM", CosyVoice2ForCausalLM) -from cosyvoice.cli.cosyvoice import CosyVoice2 -from cosyvoice.utils.file_utils import load_wav +from cosyvoice.cli.cosyvoice import CosyVoice2, CosyVoice3 from cosyvoice.utils.common import set_all_random_seed from tqdm import tqdm -def main(): +def cosyvoice2_example(): + """ CosyVoice2 vllm usage + """ cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B', load_jit=True, load_trt=True, load_vllm=True, fp16=True) + for i in tqdm(range(100)): + set_all_random_seed(i) + for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + continue + +def cosyvoice3_example(): + """ CosyVoice3 vllm usage + """ + cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_jit=True, load_trt=True, load_vllm=True, fp16=True) prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000) for i in tqdm(range(100)): set_all_random_seed(i) - for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)): + for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): continue +def main(): + cosyvoice2_example() + cosyvoice3_example() if __name__ == '__main__': main() From 59f02cb85d2f2ebec458680e144a2c1553002330 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 8 Dec 2025 11:14:12 +0000 Subject: [PATCH 15/61] add vllm example --- cosyvoice/cli/cosyvoice.py | 2 -- vllm_example.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 1f2f60a..ea63fc0 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -224,8 +224,6 @@ class CosyVoice3(CosyVoice2): '{}/hift.pt'.format(model_dir)) if load_vllm: self.model.load_vllm('{}/vllm'.format(model_dir)) - if load_jit: - self.model.load_jit('{}/flow.encoder.{}.zip'.format(model_dir, 'fp16' if self.fp16 is True else 'fp32')) if load_trt: self.model.load_trt('{}/flow.decoder.estimator.{}.mygpu.plan'.format(model_dir, 'fp16' if self.fp16 is True else 'fp32'), '{}/flow.decoder.estimator.fp32.onnx'.format(model_dir), diff --git a/vllm_example.py b/vllm_example.py index 8b177a3..f8bc01b 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -21,8 +21,7 @@ def cosyvoice2_example(): def cosyvoice3_example(): """ CosyVoice3 vllm usage """ - cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_jit=True, load_trt=True, load_vllm=True, fp16=True) - prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000) + cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=True) for i in tqdm(range(100)): set_all_random_seed(i) for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): From b35ece675bfdad7d50b990225394074f817056a0 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 8 Dec 2025 11:28:45 +0000 Subject: [PATCH 16/61] dit need higher trt version --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index cd3b5ef..f776cbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,9 +29,9 @@ pyworld==0.3.4 rich==13.7.1 soundfile==0.12.1 tensorboard==2.14.0 -tensorrt-cu12==10.0.1; sys_platform == 'linux' -tensorrt-cu12-bindings==10.0.1; sys_platform == 'linux' -tensorrt-cu12-libs==10.0.1; sys_platform == 'linux' +tensorrt-cu12==10.13.3.9; sys_platform == 'linux' +tensorrt-cu12-bindings==10.13.3.9; sys_platform == 'linux' +tensorrt-cu12-libs==10.13.3.9; sys_platform == 'linux' torch==2.3.1 torchaudio==2.3.1 transformers==4.51.3 From 56d9876037078da118b48d268d6cf5340de129af Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 9 Dec 2025 07:57:10 +0000 Subject: [PATCH 17/61] fix bug --- cosyvoice/cli/frontend.py | 4 +- cosyvoice/cli/model.py | 6 +- cosyvoice/llm/llm.py | 6 +- cosyvoice/utils/common.py | 56 +++++++++---------- example.py | 14 ++--- .../conf/{cosyvoice2.yaml => cosyvoice3.yaml} | 0 examples/libritts/cosyvoice3/run.sh | 10 ++-- vllm_example.py | 2 +- 8 files changed, 49 insertions(+), 49 deletions(-) rename examples/libritts/cosyvoice3/conf/{cosyvoice2.yaml => cosyvoice3.yaml} (100%) diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index d614883..ae2b485 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -193,13 +193,13 @@ class CosyVoiceFrontEnd: model_input = self.frontend_sft(tts_text, spk_id) # in instruct mode, we remove spk_embedding in llm due to information leakage del model_input['llm_embedding'] - instruct_text_token, instruct_text_token_len = self._extract_text_token(instruct_text + '') + instruct_text_token, instruct_text_token_len = self._extract_text_token(instruct_text) model_input['prompt_text'] = instruct_text_token model_input['prompt_text_len'] = instruct_text_token_len return model_input def frontend_instruct2(self, tts_text, instruct_text, prompt_wav, resample_rate, zero_shot_spk_id): - model_input = self.frontend_zero_shot(tts_text, instruct_text + '<|endofprompt|>', prompt_wav, resample_rate, zero_shot_spk_id) + model_input = self.frontend_zero_shot(tts_text, instruct_text, prompt_wav, resample_rate, zero_shot_spk_id) del model_input['llm_prompt_speech_token'] del model_input['llm_prompt_speech_token_len'] return model_input diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index b0fc120..85e63d4 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -129,7 +129,7 @@ class CosyVoiceModel: def token2wav(self, token, prompt_token, prompt_feat, embedding, uuid, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): - tts_mel, self.flow_cache_dict[uuid] = self.flow.inference(token=token.to(self.device), + tts_mel, self.flow_cache_dict[uuid] = self.flow.inference(token=token.to(self.device, dtype=torch.int32), token_len=torch.tensor([token.shape[1]], dtype=torch.int32).to(self.device), prompt_token=prompt_token.to(self.device), prompt_token_len=torch.tensor([prompt_token.shape[1]], dtype=torch.int32).to(self.device), @@ -284,7 +284,7 @@ class CosyVoice2Model(CosyVoiceModel): def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): - tts_mel, _ = self.flow.inference(token=token.to(self.device), + tts_mel, _ = self.flow.inference(token=token.to(self.device, dtype=torch.int32), token_len=torch.tensor([token.shape[1]], dtype=torch.int32).to(self.device), prompt_token=prompt_token.to(self.device), prompt_token_len=torch.tensor([prompt_token.shape[1]], dtype=torch.int32).to(self.device), @@ -413,7 +413,7 @@ class CosyVoice3Model(CosyVoice2Model): def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): - tts_mel, _ = self.flow.inference(token=token.to(self.device), + tts_mel, _ = self.flow.inference(token=token.to(self.device, dtype=torch.int32), token_len=torch.tensor([token.shape[1]], dtype=torch.int32).to(self.device), prompt_token=prompt_token.to(self.device), prompt_token_len=torch.tensor([prompt_token.shape[1]], dtype=torch.int32).to(self.device), diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index cba0c57..559d49f 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -155,7 +155,7 @@ class TransformerLM(torch.nn.Module): num_trials, max_trials = 0, 100 while True: top_ids = self.sampling(weighted_scores, decoded_tokens, sampling) - if (not ignore_eos) or (self.speech_token_size not in top_ids): + if (not ignore_eos) or (top_ids < self.speech_token_size): break num_trials += 1 if num_trials > max_trials: @@ -506,7 +506,7 @@ class Qwen2LM(TransformerLM): masks=torch.tril(torch.ones((1, lm_input.shape[1], lm_input.shape[1]), device=lm_input.device)).to(torch.bool), cache=cache) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) - top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False).item() + top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False) if top_ids in self.stop_token_ids: break # in stream mode, yield token one by one @@ -654,7 +654,7 @@ class CosyVoice3LM(Qwen2LM): self.mix_ratio = mix_ratio # 5. vllm related - self.stop_token_ids = [speech_token_size + i for i in range(4)] + self.stop_token_ids = [speech_token_size + i for i in range(200)] self.vllm_output_queue = {} def forward( diff --git a/cosyvoice/utils/common.py b/cosyvoice/utils/common.py index 2b602fa..3c4cb44 100644 --- a/cosyvoice/utils/common.py +++ b/cosyvoice/utils/common.py @@ -25,32 +25,32 @@ import torch IGNORE_ID = -1 -instruct_list = ["You are a helpful assistant. 请用广东话表达。", - "You are a helpful assistant. 请用东北话表达。", - "You are a helpful assistant. 请用甘肃话表达。", - "You are a helpful assistant. 请用贵州话表达。", - "You are a helpful assistant. 请用河南话表达。", - "You are a helpful assistant. 请用湖北话表达。", - "You are a helpful assistant. 请用湖南话表达。", - "You are a helpful assistant. 请用江西话表达。", - "You are a helpful assistant. 请用闽南话表达。", - "You are a helpful assistant. 请用宁夏话表达。", - "You are a helpful assistant. 请用山西话表达。", - "You are a helpful assistant. 请用陕西话表达。", - "You are a helpful assistant. 请用山东话表达。", - "You are a helpful assistant. 请用上海话表达。", - "You are a helpful assistant. 请用四川话表达。", - "You are a helpful assistant. 请用天津话表达。", - "You are a helpful assistant. 请用云南话表达。", - "You are a helpful assistant. Please say a sentence as loudly as possible.", - "You are a helpful assistant. Please say a sentence in a very soft voice.", - "You are a helpful assistant. 请用尽可能慢地语速说一句话。", - "You are a helpful assistant. 请用尽可能快地语速说一句话。", - "You are a helpful assistant. 请非常开心地说一句话。", - "You are a helpful assistant. 请非常伤心地说一句话。", - "You are a helpful assistant. 请非常生气地说一句话。", - "You are a helpful assistant. 我想体验一下小猪佩奇风格,可以吗?", - "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?"] +instruct_list = ["You are a helpful assistant. 请用广东话表达。", + "You are a helpful assistant. 请用东北话表达。", + "You are a helpful assistant. 请用甘肃话表达。", + "You are a helpful assistant. 请用贵州话表达。", + "You are a helpful assistant. 请用河南话表达。", + "You are a helpful assistant. 请用湖北话表达。", + "You are a helpful assistant. 请用湖南话表达。", + "You are a helpful assistant. 请用江西话表达。", + "You are a helpful assistant. 请用闽南话表达。", + "You are a helpful assistant. 请用宁夏话表达。", + "You are a helpful assistant. 请用山西话表达。", + "You are a helpful assistant. 请用陕西话表达。", + "You are a helpful assistant. 请用山东话表达。", + "You are a helpful assistant. 请用上海话表达。", + "You are a helpful assistant. 请用四川话表达。", + "You are a helpful assistant. 请用天津话表达。", + "You are a helpful assistant. 请用云南话表达。", + "You are a helpful assistant. Please say a sentence as loudly as possible.", + "You are a helpful assistant. Please say a sentence in a very soft voice.", + "You are a helpful assistant. 请用尽可能慢地语速说一句话。", + "You are a helpful assistant. 请用尽可能快地语速说一句话。", + "You are a helpful assistant. 请非常开心地说一句话。", + "You are a helpful assistant. 请非常伤心地说一句话。", + "You are a helpful assistant. 请非常生气地说一句话。", + "You are a helpful assistant. 我想体验一下小猪佩奇风格,可以吗?", + "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?"] def pad_list(xs: List[torch.Tensor], pad_value: int): """Perform padding for the list of tensors. @@ -156,12 +156,12 @@ def nucleus_sampling(weighted_scores, top_p=0.8, top_k=25): break prob = torch.tensor(prob).to(weighted_scores) indices = torch.tensor(indices, dtype=torch.long).to(weighted_scores.device) - top_ids = indices[prob.multinomial(1, replacement=True)] + top_ids = indices[prob.multinomial(1, replacement=True)].item() return top_ids def random_sampling(weighted_scores, decoded_tokens, sampling): - top_ids = weighted_scores.softmax(dim=0).multinomial(1, replacement=True) + top_ids = weighted_scores.softmax(dim=0).multinomial(1, replacement=True).item() return top_ids diff --git a/example.py b/example.py index ba7c5a2..6216cf5 100644 --- a/example.py +++ b/example.py @@ -28,7 +28,7 @@ def cosyvoice_example(): cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-Instruct') # instruct usage, support [laughter][breath] - for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.<|endofprompt|>', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) def cosyvoice2_example(): @@ -52,7 +52,7 @@ def cosyvoice2_example(): torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # instruct usage - for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # bistream usage, you can use generator as input, this is useful when using text llm model as input @@ -70,21 +70,21 @@ def cosyvoice3_example(): """ cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_jit=False, load_trt=False, fp16=False) # zero_shot usage - for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L280 - for i, j in enumerate(cosyvoice.inference_cross_lingual('[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_cross_lingual('You are a helpful assistant.<|endofprompt|>[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # instruct usage - for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # hotfix usage - for i, j in enumerate(cosyvoice.inference_zero_shot('高管也通过电话、短信、微信等方式对报道[j][ǐ]予好评。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('高管也通过电话、短信、微信等方式对报道[j][ǐ]予好评。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('hotfix_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) def main(): diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice2.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml similarity index 100% rename from examples/libritts/cosyvoice3/conf/cosyvoice2.yaml rename to examples/libritts/cosyvoice3/conf/cosyvoice3.yaml diff --git a/examples/libritts/cosyvoice3/run.sh b/examples/libritts/cosyvoice3/run.sh index ad59c0a..ce20043 100644 --- a/examples/libritts/cosyvoice3/run.sh +++ b/examples/libritts/cosyvoice3/run.sh @@ -7,7 +7,7 @@ stop_stage=3 data_url=www.openslr.org/resources/60 data_dir=/mnt/lyuxiang.lx/data/tts/openslr/libritts -pretrained_model_dir=../../../pretrained_models/CosyVoice2-0.5B +pretrained_model_dir=../../../pretrained_models/CosyVoice3-0.5B if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then echo "Data Download" @@ -36,7 +36,7 @@ if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then echo "Extract discrete speech token, you will get utt2speech_token.pt in data/$x dir" for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do tools/extract_speech_token.py --dir data/$x \ - --onnx_path $pretrained_model_dir/speech_tokenizer_v2.onnx + --onnx_path $pretrained_model_dir/speech_tokenizer_v3.onnx done fi @@ -72,14 +72,14 @@ if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then --rdzv_id=$job_id --rdzv_backend="c10d" --rdzv_endpoint="localhost:1234" \ cosyvoice/bin/train.py \ --train_engine $train_engine \ - --config conf/cosyvoice2.yaml \ + --config conf/cosyvoice3.yaml \ --train_data data/train.data.list \ --cv_data data/dev.data.list \ --qwen_pretrain_path $pretrained_model_dir/CosyVoice-BlankEN \ --model $model \ --checkpoint $pretrained_model_dir/$model.pt \ - --model_dir `pwd`/exp/cosyvoice2/$model/$train_engine \ - --tensorboard_dir `pwd`/tensorboard/cosyvoice2/$model/$train_engine \ + --model_dir `pwd`/exp/cosyvoice3/$model/$train_engine \ + --tensorboard_dir `pwd`/tensorboard/cosyvoice3/$model/$train_engine \ --ddp.dist_backend $dist_backend \ --num_workers ${num_workers} \ --prefetch ${prefetch} \ diff --git a/vllm_example.py b/vllm_example.py index f8bc01b..e4222af 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -24,7 +24,7 @@ def cosyvoice3_example(): cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=True) for i in tqdm(range(100)): set_all_random_seed(i) - for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): continue def main(): From 0c65d3c7ab2e85cccad00dc3a9e94e3d5ff5961e Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 9 Dec 2025 15:15:05 +0000 Subject: [PATCH 18/61] use automodel --- cosyvoice/bin/export_jit.py | 30 ++++++++++++++---------------- cosyvoice/bin/export_onnx.py | 13 ++----------- cosyvoice/cli/cosyvoice.py | 23 +++++++++++++++++++---- cosyvoice/cli/frontend.py | 3 +++ cosyvoice/utils/file_utils.py | 23 +++-------------------- example.py | 12 ++++++------ vllm_example.py | 6 +++--- webui.py | 34 ++++++---------------------------- 8 files changed, 56 insertions(+), 88 deletions(-) diff --git a/cosyvoice/bin/export_jit.py b/cosyvoice/bin/export_jit.py index 4eedc1a..0013d64 100644 --- a/cosyvoice/bin/export_jit.py +++ b/cosyvoice/bin/export_jit.py @@ -23,8 +23,10 @@ import torch ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../..'.format(ROOT_DIR)) sys.path.append('{}/../../third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 +from cosyvoice.cli.cosyvoice import AutoModel +from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model, CosyVoice3Model from cosyvoice.utils.file_utils import logging +from cosyvoice.utils.class_utils import get_model_type def get_args(): @@ -57,15 +59,17 @@ def main(): torch._C._jit_set_profiling_mode(False) torch._C._jit_set_profiling_executor(False) - try: - model = CosyVoice(args.model_dir) - except Exception: - try: - model = CosyVoice2(args.model_dir) - except Exception: - raise TypeError('no valid model_type!') + model = AutoModel(model_dir=args.model_dir) - if not isinstance(model, CosyVoice2): + if get_model_type(model.model) == CosyVoiceModel: + # 1. export flow encoder + flow_encoder = model.model.flow.encoder + script = get_optimized_script(flow_encoder) + script.save('{}/flow.encoder.fp32.zip'.format(args.model_dir)) + script = get_optimized_script(flow_encoder.half()) + script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) + logging.info('successfully export flow_encoder') + elif get_model_type(model.model) == CosyVoice2Model: # 1. export llm text_encoder llm_text_encoder = model.model.llm.text_encoder script = get_optimized_script(llm_text_encoder) @@ -90,13 +94,7 @@ def main(): script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) logging.info('successfully export flow_encoder') else: - # 3. export flow encoder - flow_encoder = model.model.flow.encoder - script = get_optimized_script(flow_encoder) - script.save('{}/flow.encoder.fp32.zip'.format(args.model_dir)) - script = get_optimized_script(flow_encoder.half()) - script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) - logging.info('successfully export flow_encoder') + raise ValueError('unsupported model type') if __name__ == '__main__': diff --git a/cosyvoice/bin/export_onnx.py b/cosyvoice/bin/export_onnx.py index e4857da..58e7708 100644 --- a/cosyvoice/bin/export_onnx.py +++ b/cosyvoice/bin/export_onnx.py @@ -27,7 +27,7 @@ from tqdm import tqdm ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../..'.format(ROOT_DIR)) sys.path.append('{}/../../third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2, CosyVoice3 +from cosyvoice.cli.cosyvoice import AutoModel from cosyvoice.utils.file_utils import logging @@ -58,16 +58,7 @@ def main(): logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s') - try: - model = CosyVoice(args.model_dir) - except Exception: - try: - model = CosyVoice2(args.model_dir) - except Exception: - try: - model = CosyVoice3(args.model_dir) - except Exception: - raise TypeError('no valid model_type!') + model = AutoModel(model_dir=args.model_dir) # 1. export flow decoder estimator estimator = model.model.flow.decoder.estimator diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index ea63fc0..6395d60 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -196,7 +196,7 @@ class CosyVoice2(CosyVoice): class CosyVoice3(CosyVoice2): - def __init__(self, model_dir, load_jit=False, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): + def __init__(self, model_dir, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): self.instruct = True if '-Instruct' in model_dir else False self.model_dir = model_dir self.fp16 = fp16 @@ -215,9 +215,9 @@ class CosyVoice3(CosyVoice2): '{}/spk2info.pt'.format(model_dir), configs['allowed_special']) self.sample_rate = configs['sample_rate'] - if torch.cuda.is_available() is False and (load_jit is True or load_trt is True or fp16 is True): - load_jit, load_trt, fp16 = False, False, False - logging.warning('no cuda device, set load_jit/load_trt/fp16 to False') + if torch.cuda.is_available() is False and (load_trt is True or fp16 is True): + load_trt, fp16 = False, False + logging.warning('no cuda device, set load_trt/fp16 to False') self.model = CosyVoice3Model(configs['llm'], configs['flow'], configs['hift'], fp16) self.model.load('{}/llm.pt'.format(model_dir), '{}/flow.pt'.format(model_dir), @@ -225,8 +225,23 @@ class CosyVoice3(CosyVoice2): if load_vllm: self.model.load_vllm('{}/vllm'.format(model_dir)) if load_trt: + if self.fp16 is True: + logging.warning('DiT tensorRT fp16 engine have some performance issue, use at caution!') self.model.load_trt('{}/flow.decoder.estimator.{}.mygpu.plan'.format(model_dir, 'fp16' if self.fp16 is True else 'fp32'), '{}/flow.decoder.estimator.fp32.onnx'.format(model_dir), trt_concurrent, self.fp16) del configs + + +def AutoModel(**kwargs): + if not os.path.exists(kwargs['model_dir']): + kwargs['model_dir'] = snapshot_download(kwargs['model_dir']) + if os.path.exists('{}/cosyvoice.yaml'.format(kwargs['model_dir'])): + return CosyVoice(**kwargs) + elif os.path.exists('{}/cosyvoice2.yaml'.format(kwargs['model_dir'])): + return CosyVoice2(**kwargs) + elif os.path.exists('{}/cosyvoice3.yaml'.format(kwargs['model_dir'])): + return CosyVoice3(**kwargs) + else: + raise TypeError('No valid model type found!') diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index ae2b485..4292931 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -122,6 +122,9 @@ class CosyVoiceFrontEnd: return speech_feat, speech_feat_len def text_normalize(self, text, split=True, text_frontend=True): + # NOTE skip text_frontend when ssml symbol in text + if '<|' in text and '|>' in text: + text_frontend = False if isinstance(text, Generator): logging.info('get tts_text generator, will skip text_normalize!') return [text] diff --git a/cosyvoice/utils/file_utils.py b/cosyvoice/utils/file_utils.py index 358a9f6..b173ef2 100644 --- a/cosyvoice/utils/file_utils.py +++ b/cosyvoice/utils/file_utils.py @@ -92,29 +92,14 @@ def convert_onnx_to_trt(trt_model, trt_kwargs, onnx_model, fp16): def export_cosyvoice2_vllm(model, model_path, device): if os.path.exists(model_path): return - pad_to = DEFAULT_VOCAB_PADDING_SIZE = 64 - vocab_size = model.speech_embedding.num_embeddings - feature_size = model.speech_embedding.embedding_dim - pad_vocab_size = ((vocab_size + pad_to - 1) // pad_to) * pad_to dtype = torch.bfloat16 # lm_head use_bias = True if model.llm_decoder.bias is not None else False - new_lm_head = torch.nn.Linear(in_features=feature_size, out_features=pad_vocab_size, bias=use_bias) - with torch.no_grad(): - new_lm_head.weight[:vocab_size] = model.llm_decoder.weight - new_lm_head.weight[vocab_size:] = 0 - if use_bias is True: - new_lm_head.bias[:vocab_size] = model.llm_decoder.bias - new_lm_head.bias[vocab_size:] = 0 - model.llm.model.lm_head = new_lm_head - new_codec_embed = torch.nn.Linear(in_features=feature_size, out_features=pad_vocab_size) + model.llm.model.lm_head = model.llm_decoder # embed_tokens embed_tokens = model.llm.model.model.embed_tokens - with torch.no_grad(): - new_codec_embed.weight[:vocab_size] = model.speech_embedding.weight - new_codec_embed.weight[vocab_size:] = 0 - model.llm.model.set_input_embeddings(new_codec_embed) + model.llm.model.set_input_embeddings(model.speech_embedding) model.llm.model.to(device) model.llm.model.to(dtype) tmp_vocab_size = model.llm.model.config.vocab_size @@ -122,14 +107,12 @@ def export_cosyvoice2_vllm(model, model_path, device): del model.llm.model.generation_config.eos_token_id del model.llm.model.config.bos_token_id del model.llm.model.config.eos_token_id - model.llm.model.config.vocab_size = pad_vocab_size + model.llm.model.config.vocab_size = model.speech_embedding.num_embeddings model.llm.model.config.tie_word_embeddings = False model.llm.model.config.use_bias = use_bias model.llm.model.save_pretrained(model_path) if use_bias is True: os.system('sed -i s@Qwen2ForCausalLM@CosyVoice2ForCausalLM@g {}/config.json'.format(os.path.abspath(model_path))) - else: - os.system('sed -i s@Qwen2ForCausalLM@Qwen2ForCausalLM@g {}/config.json'.format(os.path.abspath(model_path))) model.llm.model.config.vocab_size = tmp_vocab_size model.llm.model.config.tie_word_embeddings = tmp_tie_embedding model.llm.model.set_input_embeddings(embed_tokens) diff --git a/example.py b/example.py index 6216cf5..164acf6 100644 --- a/example.py +++ b/example.py @@ -1,6 +1,6 @@ import sys sys.path.append('third_party/Matcha-TTS') -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2, CosyVoice3 +from cosyvoice.cli.cosyvoice import AutoModel from cosyvoice.utils.file_utils import load_wav import torchaudio @@ -8,14 +8,14 @@ import torchaudio def cosyvoice_example(): """ CosyVoice Usage, check https://fun-audio-llm.github.io/ for more details """ - cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-SFT', load_jit=False, load_trt=False, fp16=False) + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M-SFT') # sft usage print(cosyvoice.list_available_spks()) # change stream=True for chunk stream inference for i, j in enumerate(cosyvoice.inference_sft('你好,我是通义生成式语音大模型,请问有什么可以帮您的吗?', '中文女', stream=False)): torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M') + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M') # zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) @@ -26,7 +26,7 @@ def cosyvoice_example(): for i, j in enumerate(cosyvoice.inference_vc('./asset/zero_shot_prompt.wav', './asset/cross_lingual_prompt.wav', stream=False)): torchaudio.save('vc_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M-Instruct') + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M-Instruct') # instruct usage, support [laughter][breath] for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.<|endofprompt|>', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) @@ -34,7 +34,7 @@ def cosyvoice_example(): def cosyvoice2_example(): """ CosyVoice2 Usage, check https://funaudiollm.github.io/cosyvoice2/ for more details """ - cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B', load_jit=False, load_trt=False, load_vllm=False, fp16=False) + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice2-0.5B') # NOTE if you want to reproduce the results on https://funaudiollm.github.io/cosyvoice2, please add text_frontend=False during inference # zero_shot usage @@ -68,7 +68,7 @@ def cosyvoice2_example(): def cosyvoice3_example(): """ CosyVoice3 Usage, check https://funaudiollm.github.io/cosyvoice3/ for more details """ - cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_jit=False, load_trt=False, fp16=False) + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice3-0.5B') # zero_shot usage for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) diff --git a/vllm_example.py b/vllm_example.py index e4222af..5fbfe7d 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -4,7 +4,7 @@ from vllm import ModelRegistry from cosyvoice.vllm.cosyvoice2 import CosyVoice2ForCausalLM ModelRegistry.register_model("CosyVoice2ForCausalLM", CosyVoice2ForCausalLM) -from cosyvoice.cli.cosyvoice import CosyVoice2, CosyVoice3 +from cosyvoice.cli.cosyvoice import AutoModel from cosyvoice.utils.common import set_all_random_seed from tqdm import tqdm @@ -12,7 +12,7 @@ from tqdm import tqdm def cosyvoice2_example(): """ CosyVoice2 vllm usage """ - cosyvoice = CosyVoice2('pretrained_models/CosyVoice2-0.5B', load_jit=True, load_trt=True, load_vllm=True, fp16=True) + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice2-0.5B', load_jit=True, load_trt=True, load_vllm=True, fp16=True) for i in tqdm(range(100)): set_all_random_seed(i) for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): @@ -21,7 +21,7 @@ def cosyvoice2_example(): def cosyvoice3_example(): """ CosyVoice3 vllm usage """ - cosyvoice = CosyVoice3('pretrained_models/CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=True) + cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=False) for i in tqdm(range(100)): set_all_random_seed(i) for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): diff --git a/webui.py b/webui.py index 3552cd9..ee5a962 100644 --- a/webui.py +++ b/webui.py @@ -22,8 +22,8 @@ import random import librosa ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 -from cosyvoice.utils.file_utils import load_wav, logging +from cosyvoice.cli.cosyvoice import AutoModel +from cosyvoice.utils.file_utils import logging from cosyvoice.utils.common import set_all_random_seed inference_mode_list = ['预训练音色', '3s极速复刻', '跨语种复刻', '自然语言控制'] @@ -42,23 +42,9 @@ def generate_seed(): "value": seed } - -def postprocess(speech, top_db=60, hop_length=220, win_length=440): - speech, _ = librosa.effects.trim( - speech, top_db=top_db, - frame_length=win_length, - hop_length=hop_length - ) - if speech.abs().max() > max_val: - speech = speech / speech.abs().max() * max_val - speech = torch.concat([speech, torch.zeros(1, int(cosyvoice.sample_rate * 0.2))], dim=1) - return speech - - def change_instruction(mode_checkbox_group): return instruct_dict[mode_checkbox_group] - def generate_audio(tts_text, mode_checkbox_group, sft_dropdown, prompt_text, prompt_wav_upload, prompt_wav_record, instruct_text, seed, stream, speed): if prompt_wav_upload is not None: @@ -118,15 +104,13 @@ def generate_audio(tts_text, mode_checkbox_group, sft_dropdown, prompt_text, pro yield (cosyvoice.sample_rate, i['tts_speech'].numpy().flatten()) elif mode_checkbox_group == '3s极速复刻': logging.info('get zero_shot inference request') - prompt_speech_16k = postprocess(load_wav(prompt_wav, prompt_sr)) set_all_random_seed(seed) - for i in cosyvoice.inference_zero_shot(tts_text, prompt_text, prompt_speech_16k, stream=stream, speed=speed): + for i in cosyvoice.inference_zero_shot(tts_text, prompt_text, prompt_wav, stream=stream, speed=speed): yield (cosyvoice.sample_rate, i['tts_speech'].numpy().flatten()) elif mode_checkbox_group == '跨语种复刻': logging.info('get cross_lingual inference request') - prompt_speech_16k = postprocess(load_wav(prompt_wav, prompt_sr)) set_all_random_seed(seed) - for i in cosyvoice.inference_cross_lingual(tts_text, prompt_speech_16k, stream=stream, speed=speed): + for i in cosyvoice.inference_cross_lingual(tts_text, prompt_wav, stream=stream, speed=speed): yield (cosyvoice.sample_rate, i['tts_speech'].numpy().flatten()) else: logging.info('get instruct inference request') @@ -181,16 +165,10 @@ if __name__ == '__main__': default=8000) parser.add_argument('--model_dir', type=str, - default='pretrained_models/CosyVoice2-0.5B', + default='pretrained_models/CosyVoice3-0.5B', help='local path or modelscope repo id') args = parser.parse_args() - try: - cosyvoice = CosyVoice(args.model_dir) - except Exception: - try: - cosyvoice = CosyVoice2(args.model_dir) - except Exception: - raise TypeError('no valid model_type!') + model = AutoModel(model_dir=args.model_dir) sft_spk = cosyvoice.list_available_spks() if len(sft_spk) == 0: From a051a09ba4efc042533c0d2f4240c6acf9c42739 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 9 Dec 2025 15:41:02 +0000 Subject: [PATCH 19/61] remove unncessary code --- README.md | 2 +- cosyvoice/cli/cosyvoice.py | 7 +------ example.py | 5 ++--- vllm_example.py | 2 +- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 495934a..6b3297f 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ We strongly recommend that you download our pretrained `CosyVoice2-0.5B` `CosyVo ``` python # SDK模型下载 from modelscope import snapshot_download -snapshot_download('iic/CosyVoice3-0.5B', local_dir='pretrained_models/CosyVoice3-0.5B') +snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B', local_dir='pretrained_models/Fun-CosyVoice3-0.5B') snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B') snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M') snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT') diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 6395d60..ce411c2 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -27,7 +27,6 @@ from cosyvoice.utils.class_utils import get_model_type class CosyVoice: def __init__(self, model_dir, load_jit=False, load_trt=False, fp16=False, trt_concurrent=1): - self.instruct = True if '-Instruct' in model_dir else False self.model_dir = model_dir self.fp16 = fp16 if not os.path.exists(model_dir): @@ -37,7 +36,7 @@ class CosyVoice: raise ValueError('{} not found!'.format(hyper_yaml_path)) with open(hyper_yaml_path, 'r') as f: configs = load_hyperpyyaml(f) - assert get_model_type(configs) != CosyVoice2Model, 'do not use {} for CosyVoice initialization!'.format(model_dir) + assert get_model_type(configs) == CosyVoiceModel, 'do not use {} for CosyVoice initialization!'.format(model_dir) self.frontend = CosyVoiceFrontEnd(configs['get_tokenizer'], configs['feat_extractor'], '{}/campplus.onnx'.format(model_dir), @@ -116,8 +115,6 @@ class CosyVoice: def inference_instruct(self, tts_text, spk_id, instruct_text, stream=False, speed=1.0, text_frontend=True): assert isinstance(self.model, CosyVoiceModel), 'inference_instruct is only implemented for CosyVoice!' - if self.instruct is False: - raise ValueError('{} do not support instruct inference'.format(self.model_dir)) instruct_text = self.frontend.text_normalize(instruct_text, split=False, text_frontend=text_frontend) for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): model_input = self.frontend.frontend_instruct(i, spk_id, instruct_text) @@ -142,7 +139,6 @@ class CosyVoice: class CosyVoice2(CosyVoice): def __init__(self, model_dir, load_jit=False, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): - self.instruct = True if '-Instruct' in model_dir else False self.model_dir = model_dir self.fp16 = fp16 if not os.path.exists(model_dir): @@ -197,7 +193,6 @@ class CosyVoice2(CosyVoice): class CosyVoice3(CosyVoice2): def __init__(self, model_dir, load_trt=False, load_vllm=False, fp16=False, trt_concurrent=1): - self.instruct = True if '-Instruct' in model_dir else False self.model_dir = model_dir self.fp16 = fp16 if not os.path.exists(model_dir): diff --git a/example.py b/example.py index 164acf6..1307ed4 100644 --- a/example.py +++ b/example.py @@ -1,7 +1,6 @@ import sys sys.path.append('third_party/Matcha-TTS') from cosyvoice.cli.cosyvoice import AutoModel -from cosyvoice.utils.file_utils import load_wav import torchaudio @@ -68,7 +67,7 @@ def cosyvoice2_example(): def cosyvoice3_example(): """ CosyVoice3 Usage, check https://funaudiollm.github.io/cosyvoice3/ for more details """ - cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice3-0.5B') + cosyvoice = AutoModel(model_dir='pretrained_models/Fun-CosyVoice3-0.5B') # zero_shot usage for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) @@ -77,7 +76,7 @@ def cosyvoice3_example(): for i, j in enumerate(cosyvoice.inference_cross_lingual('You are a helpful assistant.<|endofprompt|>[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - # instruct usage + # instruct usage, for supported control, check cosyvoice/utils/common.py#L28 for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): diff --git a/vllm_example.py b/vllm_example.py index 5fbfe7d..3e4dd20 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -21,7 +21,7 @@ def cosyvoice2_example(): def cosyvoice3_example(): """ CosyVoice3 vllm usage """ - cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=False) + cosyvoice = AutoModel(model_dir='pretrained_models/Fun-CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=False) for i in tqdm(range(100)): set_all_random_seed(i) for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): From 927addadd8618ca81f542f651c7d64f6c319161d Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 10 Dec 2025 02:17:00 +0000 Subject: [PATCH 20/61] fix lint --- .github/workflows/lint.yml | 2 +- README.md | 18 +++++++------- cosyvoice/cli/cosyvoice.py | 10 +++----- cosyvoice/cli/model.py | 2 +- cosyvoice/flow/DiT/modules.py | 2 +- cosyvoice/flow/flow.py | 8 ++++--- cosyvoice/hifigan/f0_predictor.py | 2 +- cosyvoice/hifigan/generator.py | 15 ++++++------ cosyvoice/llm/llm.py | 6 +++-- cosyvoice/transformer/convolution.py | 22 ++++++++--------- cosyvoice/utils/common.py | 1 + example.py | 36 ++++++++++++++++++---------- vllm_example.py | 6 ++++- webui.py | 4 +++- 14 files changed, 75 insertions(+), 59 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ef28761..4002222 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -52,5 +52,5 @@ jobs: set -eux pip install flake8==3.8.2 flake8-bugbear flake8-comprehensions flake8-executable flake8-pyi==20.5.0 mccabe pycodestyle==2.6.0 pyflakes==2.2.0 flake8 --version - flake8 --max-line-length 180 --ignore B006,B008,B905,C408,E402,E731,E741,W503,W504,F401,F403,F405,F841 --exclude ./third_party/,./runtime/python/grpc/cosyvoice_pb2*py + flake8 --max-line-length 180 --ignore B006,B008,B905,C408,E402,E731,E741,W503,W504,F401,F403,F405,F722,F841 --exclude ./third_party/,./runtime/python/grpc/cosyvoice_pb2*py if [ $? != 0 ]; then exit 1; fi \ No newline at end of file diff --git a/README.md b/README.md index 6b3297f..ae11eb9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## 👉🏻 CosyVoice 👈🏻 -**CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) +**CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) **CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/spaces/FunAudioLLM/CosyVoice2-0.5B) @@ -31,8 +31,8 @@ - [x] 2025/12 - - [x] release cosyvoice3-0.5B base model and its training/inference script - - [x] release cosyvoice3-0.5B modelscope gradio space + - [x] release CosyVoice3-0.5B base model and its training/inference script + - [x] release CosyVoice3-0.5B modelscope gradio space - [x] 2025/08 @@ -40,20 +40,20 @@ - [x] 2025/07 - - [x] release cosyvoice 3.0 eval set + - [x] release CosyVoice 3.0 eval set - [x] 2025/05 - - [x] add cosyvoice 2.0 vllm support + - [x] add CosyVoice2-0.5B vllm support - [x] 2024/12 - - [x] 25hz cosyvoice 2.0 released + - [x] 25hz CosyVoice2-0.5B released - [x] 2024/09 - - [x] 25hz cosyvoice base model - - [x] 25hz cosyvoice voice conversion model + - [x] 25hz CosyVoice-300M base model + - [x] 25hz CosyVoice-300M voice conversion function - [x] 2024/08 @@ -122,7 +122,7 @@ pip install ttsfrd-0.4.2-cp310-cp310-linux_x86_64.whl ### Basic Usage -We strongly recommend using `CosyVoice2-0.5B` for better performance. +We strongly recommend using `CosyVoice3-0.5B` for better performance. Follow the code in `example.py` for detailed usage of each model. ```sh python example.py diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index ce411c2..316b5f1 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -156,9 +156,9 @@ class CosyVoice2(CosyVoice): '{}/spk2info.pt'.format(model_dir), configs['allowed_special']) self.sample_rate = configs['sample_rate'] - if torch.cuda.is_available() is False and (load_jit is True or load_trt is True or fp16 is True): - load_jit, load_trt, fp16 = False, False, False - logging.warning('no cuda device, set load_jit/load_trt/fp16 to False') + if torch.cuda.is_available() is False and (load_jit is True or load_trt is True or load_vllm is True or fp16 is True): + load_jit, load_trt, load_vllm, fp16 = False, False, False, False + logging.warning('no cuda device, set load_jit/load_trt/load_vllm/fp16 to False') self.model = CosyVoice2Model(configs['llm'], configs['flow'], configs['hift'], fp16) self.model.load('{}/llm.pt'.format(model_dir), '{}/flow.pt'.format(model_dir), @@ -174,11 +174,7 @@ class CosyVoice2(CosyVoice): self.fp16) del configs - def inference_instruct(self, *args, **kwargs): - raise NotImplementedError('inference_instruct is not implemented for CosyVoice2!') - def inference_instruct2(self, tts_text, instruct_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): - assert isinstance(self.model, CosyVoice2Model) or isinstance(self.model, CosyVoice3Model), 'inference_instruct2 is only implemented for CosyVoice2 and CosyVoice3!' for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): model_input = self.frontend.frontend_instruct2(i, instruct_text, prompt_wav, self.sample_rate, zero_shot_spk_id) start_time = time.time() diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 85e63d4..0f9416a 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -436,4 +436,4 @@ class CosyVoice3Model(CosyVoice2Model): tts_speech, _ = self.hift.inference(speech_feat=tts_mel, finalize=finalize) tts_speech = tts_speech[:, self.hift_cache_dict[uuid]['speech_offset']:] self.hift_cache_dict[uuid]['speech_offset'] += tts_speech.shape[1] - return tts_speech \ No newline at end of file + return tts_speech diff --git a/cosyvoice/flow/DiT/modules.py b/cosyvoice/flow/DiT/modules.py index 542ba36..be8caec 100644 --- a/cosyvoice/flow/DiT/modules.py +++ b/cosyvoice/flow/DiT/modules.py @@ -476,7 +476,7 @@ class JointAttnProcessor: # Split the attention outputs. x, c = ( x[:, : residual.shape[1]], - x[:, residual.shape[1] :], + x[:, residual.shape[1]:], ) # linear proj diff --git a/cosyvoice/flow/flow.py b/cosyvoice/flow/flow.py index 415d44e..d07c181 100644 --- a/cosyvoice/flow/flow.py +++ b/cosyvoice/flow/flow.py @@ -402,11 +402,12 @@ class CausalMaskedDiffWithDiT(torch.nn.Module): assert feat.shape[2] == mel_len2 return feat.float(), None + if __name__ == '__main__': torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False from hyperpyyaml import load_hyperpyyaml - with open('./pretrained_models/CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: + with open('./pretrained_models/Fun-CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: configs = load_hyperpyyaml(f, overrides={'llm': None, 'hift': None}) model = configs['flow'] device = 'cuda' if torch.cuda.is_available() else 'cpu' @@ -425,6 +426,7 @@ if __name__ == '__main__': pred_gt, _ = model.inference(token, token_len, prompt_token, prompt_token_len, prompt_feat, prompt_feat_len, prompt_embedding, streaming=True, finalize=True) for i in range(0, max_len, chunk_size): finalize = True if i + chunk_size + context_size >= max_len else False - pred_chunk, _ = model.inference(token[:, :i + chunk_size + context_size], torch.tensor([token[:, :i + chunk_size + context_size].shape[1]]).to(device), prompt_token, prompt_token_len, prompt_feat, prompt_feat_len, prompt_embedding, streaming=True, finalize=finalize) + pred_chunk, _ = model.inference(token[:, :i + chunk_size + context_size], torch.tensor([token[:, :i + chunk_size + context_size].shape[1]]).to(device), + prompt_token, prompt_token_len, prompt_feat, prompt_feat_len, prompt_embedding, streaming=True, finalize=finalize) pred_chunk = pred_chunk[:, :, i * model.token_mel_ratio:] - print((pred_gt[:, :, i * model.token_mel_ratio: i * model.token_mel_ratio + pred_chunk.shape[2]] - pred_chunk).abs().max().item()) \ No newline at end of file + print((pred_gt[:, :, i * model.token_mel_ratio: i * model.token_mel_ratio + pred_chunk.shape[2]] - pred_chunk).abs().max().item()) diff --git a/cosyvoice/hifigan/f0_predictor.py b/cosyvoice/hifigan/f0_predictor.py index 8e55254..c896890 100644 --- a/cosyvoice/hifigan/f0_predictor.py +++ b/cosyvoice/hifigan/f0_predictor.py @@ -100,4 +100,4 @@ class CausalConvRNNF0Predictor(nn.Module): for i in range(1, len(self.condnet)): x = self.condnet[i](x) x = x.transpose(1, 2) - return torch.abs(self.classifier(x).squeeze(-1)) \ No newline at end of file + return torch.abs(self.classifier(x).squeeze(-1)) diff --git a/cosyvoice/hifigan/generator.py b/cosyvoice/hifigan/generator.py index 9647ef3..c893b11 100644 --- a/cosyvoice/hifigan/generator.py +++ b/cosyvoice/hifigan/generator.py @@ -342,11 +342,9 @@ class SourceModuleHnNSF(torch.nn.Module): # to produce sine waveforms if sinegen_type == '1': - self.l_sin_gen = SineGen(sampling_rate, harmonic_num, - sine_amp, add_noise_std, voiced_threshod) + self.l_sin_gen = SineGen(sampling_rate, harmonic_num, sine_amp, add_noise_std, voiced_threshod) else: - self.l_sin_gen = SineGen2(sampling_rate, upsample_scale, harmonic_num, - sine_amp, add_noise_std, voiced_threshod, causal=causal) + self.l_sin_gen = SineGen2(sampling_rate, upsample_scale, harmonic_num, sine_amp, add_noise_std, voiced_threshod, causal=causal) # to merge source harmonics into a single excitation self.l_linear = torch.nn.Linear(harmonic_num + 1, 1) @@ -675,7 +673,8 @@ class CausalHiFTGenerator(HiFTGenerator): x = self.conv_pre(x) else: x = self.conv_pre(x[:, :, :-self.conv_pre_look_right], x[:, :, -self.conv_pre_look_right:]) - s_stft_real, s_stft_imag = s_stft_real[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)], s_stft_imag[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)] + s_stft_real = s_stft_real[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)] + s_stft_imag = s_stft_imag[:, :, :-int(np.prod(self.upsample_rates) * self.conv_pre_look_right)] s_stft = torch.cat([s_stft_real, s_stft_imag], dim=1) for i in range(self.num_upsamples): @@ -711,7 +710,7 @@ class CausalHiFTGenerator(HiFTGenerator): @torch.inference_mode() def inference(self, speech_feat: torch.Tensor, finalize: bool = True) -> torch.Tensor: - # mel->f0 + # mel->f0 NOTE f0_predictor precision is crucial for causal inference, move self.f0_predictor to cpu if necessary self.f0_predictor.to('cpu') f0 = self.f0_predictor(speech_feat.cpu(), finalize=finalize).to(speech_feat) # f0->source @@ -729,7 +728,7 @@ if __name__ == '__main__': torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False from hyperpyyaml import load_hyperpyyaml - with open('./pretrained_models/CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: + with open('./pretrained_models/Fun-CosyVoice3-0.5B/cosyvoice3.yaml', 'r') as f: configs = load_hyperpyyaml(f, overrides={'llm': None, 'flow': None}) model = configs['hift'] device = 'cuda' if torch.cuda.is_available() else 'cpu' @@ -742,4 +741,4 @@ if __name__ == '__main__': finalize = True if i + chunk_size + context_size >= max_len else False pred_chunk, _ = model.inference(mel[:, :, : i + chunk_size + context_size], finalize=finalize) pred_chunk = pred_chunk[:, i * 480:] - print((pred_gt[:, i * 480:i * 480 + pred_chunk.shape[1]] - pred_chunk).abs().max().item()) \ No newline at end of file + print((pred_gt[:, i * 480:i * 480 + pred_chunk.shape[1]] - pred_chunk).abs().max().item()) diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index 559d49f..a343ce4 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -369,7 +369,8 @@ class Qwen2LM(TransformerLM): speech_token_emb = self.speech_embedding(speech_token) # 3. prepare llm_input/target - lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len) + lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, + speech_token, speech_token_emb, speech_token_len) lm_target = lm_target.to(device) # 4. run lm forward @@ -685,7 +686,8 @@ class CosyVoice3LM(Qwen2LM): speech_token_emb = self.speech_embedding(speech_token) # 3. prepare llm_input/target - lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len) + lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, + speech_token, speech_token_emb, speech_token_len) lm_target = lm_target.to(device) # 4. run lm forward diff --git a/cosyvoice/transformer/convolution.py b/cosyvoice/transformer/convolution.py index 2dc9116..edb32b2 100644 --- a/cosyvoice/transformer/convolution.py +++ b/cosyvoice/transformer/convolution.py @@ -202,11 +202,11 @@ class CausalConv1dDownSample(torch.nn.Conv1d): dtype=None ) -> None: super(CausalConv1dDownSample, self).__init__(in_channels, out_channels, - kernel_size, stride, - padding=0, dilation=dilation, - groups=groups, bias=bias, - padding_mode=padding_mode, - device=device, dtype=dtype) + kernel_size, stride, + padding=0, dilation=dilation, + groups=groups, bias=bias, + padding_mode=padding_mode, + device=device, dtype=dtype) assert stride != 1 and dilation == 1 assert kernel_size % stride == 0 self.causal_padding = stride - 1 @@ -236,11 +236,11 @@ class CausalConv1dUpsample(torch.nn.Conv1d): dtype=None ) -> None: super(CausalConv1dUpsample, self).__init__(in_channels, out_channels, - kernel_size, 1, - padding=0, dilation=dilation, - groups=groups, bias=bias, - padding_mode=padding_mode, - device=device, dtype=dtype) + kernel_size, 1, + padding=0, dilation=dilation, + groups=groups, bias=bias, + padding_mode=padding_mode, + device=device, dtype=dtype) assert dilation == 1 self.causal_padding = kernel_size - 1 self.upsample = torch.nn.Upsample(scale_factor=stride, mode='nearest') @@ -255,4 +255,4 @@ class CausalConv1dUpsample(torch.nn.Conv1d): x = torch.concat([cache, x], dim=2) x = super(CausalConv1dUpsample, self).forward(x) assert input_timestep == x.shape[2] - return x \ No newline at end of file + return x diff --git a/cosyvoice/utils/common.py b/cosyvoice/utils/common.py index 3c4cb44..8afe308 100644 --- a/cosyvoice/utils/common.py +++ b/cosyvoice/utils/common.py @@ -52,6 +52,7 @@ instruct_list = ["You are a helpful assistant. 请用广东话表达。", "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?"] + def pad_list(xs: List[torch.Tensor], pad_value: int): """Perform padding for the list of tensors. diff --git a/example.py b/example.py index 1307ed4..1e507c0 100644 --- a/example.py +++ b/example.py @@ -16,20 +16,23 @@ def cosyvoice_example(): cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M') # zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean - for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav')): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # cross_lingual usage - for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', './asset/cross_lingual_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', + './asset/cross_lingual_prompt.wav')): torchaudio.save('cross_lingual_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # vc usage - for i, j in enumerate(cosyvoice.inference_vc('./asset/zero_shot_prompt.wav', './asset/cross_lingual_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_vc('./asset/zero_shot_prompt.wav', './asset/cross_lingual_prompt.wav')): torchaudio.save('vc_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M-Instruct') # instruct usage, support [laughter][breath] - for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.<|endofprompt|>', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct('在面对挑战时,他展现了非凡的勇气智慧。', '中文男', + 'Theo \'Crimson\', is a fiery, passionate rebel leader. Fights with fervor for justice, but struggles with impulsiveness.<|endofprompt|>')): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + def cosyvoice2_example(): """ CosyVoice2 Usage, check https://funaudiollm.github.io/cosyvoice2/ for more details """ @@ -37,21 +40,21 @@ def cosyvoice2_example(): # NOTE if you want to reproduce the results on https://funaudiollm.github.io/cosyvoice2, please add text_frontend=False during inference # zero_shot usage - for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav')): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # save zero_shot spk for future usage assert cosyvoice.add_zero_shot_spk('希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', 'my_zero_shot_spk') is True - for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '', '', zero_shot_spk_id='my_zero_shot_spk', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '', '', zero_shot_spk_id='my_zero_shot_spk')): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) cosyvoice.save_spkinfo() # fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L248 - for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', './asset/zero_shot_prompt.wav')): torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # instruct usage - for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '用四川话说这句话<|endofprompt|>', './asset/zero_shot_prompt.wav')): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # bistream usage, you can use generator as input, this is useful when using text llm model as input @@ -64,28 +67,35 @@ def cosyvoice2_example(): for i, j in enumerate(cosyvoice.inference_zero_shot(text_generator(), '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + def cosyvoice3_example(): """ CosyVoice3 Usage, check https://funaudiollm.github.io/cosyvoice3/ for more details """ cosyvoice = AutoModel(model_dir='pretrained_models/Fun-CosyVoice3-0.5B') # zero_shot usage - for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', + './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L280 - for i, j in enumerate(cosyvoice.inference_cross_lingual('You are a helpful assistant.<|endofprompt|>[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_cross_lingual('You are a helpful assistant.<|endofprompt|>[breath]因为他们那一辈人[breath]在乡里面住的要习惯一点,[breath]邻居都很活络,[breath]嗯,都很熟悉。[breath]', + './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # instruct usage, for supported control, check cosyvoice/utils/common.py#L28 - for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('好少咯,一般系放嗰啲国庆啊,中秋嗰啲可能会咯。', 'You are a helpful assistant. 请用广东话表达。<|endofprompt|>', + './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。<|endofprompt|>', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_instruct2('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant. 请用尽可能快地语速说一句话。<|endofprompt|>', + './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('instruct_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # hotfix usage - for i, j in enumerate(cosyvoice.inference_zero_shot('高管也通过电话、短信、微信等方式对报道[j][ǐ]予好评。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for i, j in enumerate(cosyvoice.inference_zero_shot('高管也通过电话、短信、微信等方式对报道[j][ǐ]予好评。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', + './asset/zero_shot_prompt.wav', stream=False)): torchaudio.save('hotfix_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + def main(): cosyvoice_example() cosyvoice2_example() diff --git a/vllm_example.py b/vllm_example.py index 3e4dd20..f82cfe7 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -18,18 +18,22 @@ def cosyvoice2_example(): for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): continue + def cosyvoice3_example(): """ CosyVoice3 vllm usage """ cosyvoice = AutoModel(model_dir='pretrained_models/Fun-CosyVoice3-0.5B', load_trt=True, load_vllm=True, fp16=False) for i in tqdm(range(100)): set_all_random_seed(i) - for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): + for _, _ in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', 'You are a helpful assistant.<|endofprompt|>希望你以后能够做的比我还好呦。', + './asset/zero_shot_prompt.wav', stream=False)): continue + def main(): cosyvoice2_example() cosyvoice3_example() + if __name__ == '__main__': main() diff --git a/webui.py b/webui.py index ee5a962..debf5d3 100644 --- a/webui.py +++ b/webui.py @@ -42,9 +42,11 @@ def generate_seed(): "value": seed } + def change_instruction(mode_checkbox_group): return instruct_dict[mode_checkbox_group] + def generate_audio(tts_text, mode_checkbox_group, sft_dropdown, prompt_text, prompt_wav_upload, prompt_wav_record, instruct_text, seed, stream, speed): if prompt_wav_upload is not None: @@ -168,7 +170,7 @@ if __name__ == '__main__': default='pretrained_models/CosyVoice3-0.5B', help='local path or modelscope repo id') args = parser.parse_args() - model = AutoModel(model_dir=args.model_dir) + cosyvoice = AutoModel(model_dir=args.model_dir) sft_spk = cosyvoice.list_available_spks() if len(sft_spk) == 0: From f21c4764ecb04cd5108252802c568f452fe2d576 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Thu, 11 Dec 2025 06:04:36 +0000 Subject: [PATCH 21/61] fix bug --- cosyvoice/llm/llm.py | 2 +- cosyvoice/utils/common.py | 52 +++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index a343ce4..6b3a7b0 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -604,7 +604,7 @@ class Qwen2LM(TransformerLM): masks=torch.tril(torch.ones((1, seq_len, seq_len), device=lm_input.device)).to(torch.bool), cache=cache) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) - top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=False).item() + top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=False) out_tokens.append(top_ids) if top_ids >= self.speech_token_size: if top_ids == self.eos_token: diff --git a/cosyvoice/utils/common.py b/cosyvoice/utils/common.py index 8afe308..5d307ae 100644 --- a/cosyvoice/utils/common.py +++ b/cosyvoice/utils/common.py @@ -25,32 +25,32 @@ import torch IGNORE_ID = -1 -instruct_list = ["You are a helpful assistant. 请用广东话表达。", - "You are a helpful assistant. 请用东北话表达。", - "You are a helpful assistant. 请用甘肃话表达。", - "You are a helpful assistant. 请用贵州话表达。", - "You are a helpful assistant. 请用河南话表达。", - "You are a helpful assistant. 请用湖北话表达。", - "You are a helpful assistant. 请用湖南话表达。", - "You are a helpful assistant. 请用江西话表达。", - "You are a helpful assistant. 请用闽南话表达。", - "You are a helpful assistant. 请用宁夏话表达。", - "You are a helpful assistant. 请用山西话表达。", - "You are a helpful assistant. 请用陕西话表达。", - "You are a helpful assistant. 请用山东话表达。", - "You are a helpful assistant. 请用上海话表达。", - "You are a helpful assistant. 请用四川话表达。", - "You are a helpful assistant. 请用天津话表达。", - "You are a helpful assistant. 请用云南话表达。", - "You are a helpful assistant. Please say a sentence as loudly as possible.", - "You are a helpful assistant. Please say a sentence in a very soft voice.", - "You are a helpful assistant. 请用尽可能慢地语速说一句话。", - "You are a helpful assistant. 请用尽可能快地语速说一句话。", - "You are a helpful assistant. 请非常开心地说一句话。", - "You are a helpful assistant. 请非常伤心地说一句话。", - "You are a helpful assistant. 请非常生气地说一句话。", - "You are a helpful assistant. 我想体验一下小猪佩奇风格,可以吗?", - "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?"] +instruct_list = ["You are a helpful assistant. 请用广东话表达。<|endofprompt|>", + "You are a helpful assistant. 请用东北话表达。<|endofprompt|>", + "You are a helpful assistant. 请用甘肃话表达。<|endofprompt|>", + "You are a helpful assistant. 请用贵州话表达。<|endofprompt|>", + "You are a helpful assistant. 请用河南话表达。<|endofprompt|>", + "You are a helpful assistant. 请用湖北话表达。<|endofprompt|>", + "You are a helpful assistant. 请用湖南话表达。<|endofprompt|>", + "You are a helpful assistant. 请用江西话表达。<|endofprompt|>", + "You are a helpful assistant. 请用闽南话表达。<|endofprompt|>", + "You are a helpful assistant. 请用宁夏话表达。<|endofprompt|>", + "You are a helpful assistant. 请用山西话表达。<|endofprompt|>", + "You are a helpful assistant. 请用陕西话表达。<|endofprompt|>", + "You are a helpful assistant. 请用山东话表达。<|endofprompt|>", + "You are a helpful assistant. 请用上海话表达。<|endofprompt|>", + "You are a helpful assistant. 请用四川话表达。<|endofprompt|>", + "You are a helpful assistant. 请用天津话表达。<|endofprompt|>", + "You are a helpful assistant. 请用云南话表达。<|endofprompt|>", + "You are a helpful assistant. Please say a sentence as loudly as possible.<|endofprompt|>", + "You are a helpful assistant. Please say a sentence in a very soft voice.<|endofprompt|>", + "You are a helpful assistant. 请用尽可能慢地语速说一句话。<|endofprompt|>", + "You are a helpful assistant. 请用尽可能快地语速说一句话。<|endofprompt|>", + "You are a helpful assistant. 请非常开心地说一句话。<|endofprompt|>", + "You are a helpful assistant. 请非常伤心地说一句话。<|endofprompt|>", + "You are a helpful assistant. 请非常生气地说一句话。<|endofprompt|>", + "You are a helpful assistant. 我想体验一下小猪佩奇风格,可以吗?<|endofprompt|>", + "You are a helpful assistant. 你可以尝试用机器人的方式解答吗?<|endofprompt|>"] def pad_list(xs: List[torch.Tensor], pad_value: int): From 3298d6f3e381a5f447f389c8c5da1fab727dcfba Mon Sep 17 00:00:00 2001 From: quantu Date: Thu, 11 Dec 2025 15:55:26 +0800 Subject: [PATCH 22/61] readme --- README.md | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ae11eb9..9ab26e5 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,27 @@ ## Highlight🔥 -**CosyVoice 2.0** has been released! Compared to version 1.0, the new version offers more accurate, more stable, faster, and better speech generation capabilities. -### Multilingual -- **Supported Language**: Chinese, English, Japanese, Korean, Chinese dialects (Cantonese, Sichuanese, Shanghainese, Tianjinese, Wuhanese, etc.) -- **Crosslingual & Mixlingual**:Support zero-shot voice cloning for cross-lingual and code-switching scenarios. -### Ultra-Low Latency -- **Bidirectional Streaming Support**: CosyVoice 2.0 integrates offline and streaming modeling technologies. -- **Rapid First Packet Synthesis**: Achieves latency as low as 150ms while maintaining high-quality audio output. -### High Accuracy -- **Improved Pronunciation**: Reduces pronunciation errors by 30% to 50% compared to CosyVoice 1.0. -- **Benchmark Achievements**: Attains the lowest character error rate on the hard test set of the Seed-TTS evaluation set. -### Strong Stability -- **Consistency in Timbre**: Ensures reliable voice consistency for zero-shot and cross-language speech synthesis. -- **Cross-language Synthesis**: Marked improvements compared to version 1.0. -### Natural Experience -- **Enhanced Prosody and Sound Quality**: Improved alignment of synthesized audio, raising MOS evaluation scores from 5.4 to 5.53. -- **Emotional and Dialectal Flexibility**: Now supports more granular emotional controls and accent adjustments. +**CosyVoice 3.0** is here! Building on the strengths of version 2.0, it achieves a leap in "in-the-wild speech generation" with larger scale, more powerful technology, and broader coverage—delivering more natural, accurate, and versatile speech synthesis capabilities. +### Multilingual & Wide Coverage +- **Expanded Language** Support: Covers 9 universal languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian) and 18+ Chinese dialects/accents, supporting zero-shot multilingual/cross-lingual voice cloning. +- **Massive Data Upgrade**: Training data scaled from ten thousand hours to 1 million hours,enhancing cross-lingual generalization and synthesis stability. +- **Polyglot Transformation**: Enables monolingual speakers to generate speech in multiple languages, with WER/CER below 4% for most languages. +### High Precision & Robustness +- **Superior Content Consistency**: Compared to 2.0, Chinese test set CER relative improves 44%, English test set 51%, and complex scenario (test-hard) CER drops from 6.83% to 5.09%. +- **Pronunciation Perfection**: Features pronunciation inpainting technology with high correction rate for polyphonic characters and rare words, solving long-standing pronunciation challenges. +- **Strong Scene Adaptability**: Excels in noisy backgrounds, tongue twisters, and domain-specific terms; self-training text normalization supports raw text direct synthesis, compatible with special symbols. +### Natural & Expressive Experience +- **Rich Style Control**: Supports 100+ speaking styles (emotions, speeds, roles, accents) and fine-grained instructions ([laughter], [breath], emphasis). +- **Advanced Emotion CloningControl**:: Optimized with DiffRO-EMO, leading in emotion accuracy for both text-related and text-unrelated scenarios. +### Innovative Core Technology +- **DiffRO Optimization**: Innovative reinforcement learning method, directly optimizing speech tokens, improving WER by 20%-50% in low-resource/cross-lingual scenarios, applicable to other LLM-based TTS models. +- **Supervised Multi-task Tokenizer**: Trained on ASR, SER, LID, etc., better capturing paralinguistic information like emotion and pronunciation style. +- **Pronunciation & Text Normalization**: Supports word-phoneme mixed sequence modeling; LLM-based self-training TN eliminates manual rules. +### Real-time & Flexible Deployment +- **Multi-mode Support**: Single model compatible with offline mode, one-way streaming, and bidirectional streaming, meeting diverse deployment needs. +- **Ultra-low Latency**: Achieves latency as low as 150ms while maintaining high-quality audio output. +- **Hot Fix Capability**: Supports SSML hot fix and built-in TN capability, enhancing usability and adaptability to complex text formats. + ## Roadmap From ebef63066f9cb50d3685ecbba6ea146b21aaf0ea Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Thu, 11 Dec 2025 09:43:25 +0000 Subject: [PATCH 23/61] add instruct --- cosyvoice/dataset/processor.py | 9 +++++++++ cosyvoice/llm/llm.py | 3 +++ examples/libritts/cosyvoice/local/prepare_data.py | 11 +++++++++-- examples/libritts/cosyvoice3/run.sh | 3 ++- tools/make_parquet_list.py | 13 +++++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/cosyvoice/dataset/processor.py b/cosyvoice/dataset/processor.py index 1eec976..f186ed2 100644 --- a/cosyvoice/dataset/processor.py +++ b/cosyvoice/dataset/processor.py @@ -242,6 +242,10 @@ def tokenize(data, get_tokenizer, allowed_special, mode='train'): for sample in data: assert 'text' in sample sample['text_token'] = tokenizer.encode(sample['text'], allowed_special=allowed_special) + if 'instruct' in sample: + sample['instruct_token'] = tokenizer.encode(sample['instruct'], allowed_special=allowed_special) + else: + sample['instruct_token'] = tokenizer.encode('', allowed_special=allowed_special) yield sample @@ -390,6 +394,9 @@ def padding(data, use_spk_embedding, mode='train', gan=False, dpo=False): text_token = [torch.tensor(sample[i]['text_token']) for i in order] text_token_len = torch.tensor([i.size(0) for i in text_token], dtype=torch.int32) text_token = pad_sequence(text_token, batch_first=True, padding_value=0) + instruct_token = [torch.tensor(sample[i]['instruct_token']) for i in order] + instruct_token_len = torch.tensor([i.size(0) for i in instruct_token], dtype=torch.int32) + instruct_token = pad_sequence(instruct_token, batch_first=True, padding_value=0) utt_embedding = torch.stack([sample[i]['utt_embedding'] for i in order], dim=0) spk_embedding = torch.stack([sample[i]['spk_embedding'] for i in order], dim=0) batch = { @@ -403,6 +410,8 @@ def padding(data, use_spk_embedding, mode='train', gan=False, dpo=False): "text": text, "text_token": text_token, "text_token_len": text_token_len, + "instruct_token": instruct_token, + "instruct_token_len": instruct_token_len, "utt_embedding": utt_embedding, "spk_embedding": spk_embedding, } diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index 6b3a7b0..c0b3400 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -674,6 +674,9 @@ class CosyVoice3LM(Qwen2LM): text_token_len = batch['text_token_len'].to(device) speech_token = batch['speech_token'].to(device) speech_token_len = batch['speech_token_len'].to(device) + # NOTE should append instruct_token to sequence, not implemented yet + instruct_token = batch['instruct_token'].to(device) + instruct_token_len = batch['instruct_token_len'].to(device) # 1. encode text_token text_token_emb = self.llm.model.model.embed_tokens(text_token) diff --git a/examples/libritts/cosyvoice/local/prepare_data.py b/examples/libritts/cosyvoice/local/prepare_data.py index 918aef3..fffa9fb 100644 --- a/examples/libritts/cosyvoice/local/prepare_data.py +++ b/examples/libritts/cosyvoice/local/prepare_data.py @@ -40,6 +40,11 @@ def main(): with open('{}/spk2utt'.format(args.des_dir), 'w') as f: for k, v in spk2utt.items(): f.write('{} {}\n'.format(k, ' '.join(v))) + if args.instruct is True: + with open('{}/instruct'.format(args.des_dir), 'w') as f: + for k, v in utt2text.items(): + # NOTE in CosyVoice3, we add instruct in sequence + f.write('{} You are a helpful assistant.<|endofprompt|>\n'.format(k, v)) return @@ -49,7 +54,9 @@ if __name__ == "__main__": type=str) parser.add_argument('--des_dir', type=str) - parser.add_argument('--ref_model', - type=str) + parser.add_argument('--instruct', + action='store_true', + default=False, + help='create instruct file or not') args = parser.parse_args() main() diff --git a/examples/libritts/cosyvoice3/run.sh b/examples/libritts/cosyvoice3/run.sh index ce20043..4e6ce11 100644 --- a/examples/libritts/cosyvoice3/run.sh +++ b/examples/libritts/cosyvoice3/run.sh @@ -20,7 +20,7 @@ if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then echo "Data preparation, prepare wav.scp/text/utt2spk/spk2utt" for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do mkdir -p data/$x - python local/prepare_data.py --src_dir $data_dir/LibriTTS/$x --des_dir data/$x + python local/prepare_data.py --src_dir $data_dir/LibriTTS/$x --des_dir data/$x --instruct done fi @@ -46,6 +46,7 @@ if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then mkdir -p data/$x/parquet tools/make_parquet_list.py --num_utts_per_parquet 1000 \ --num_processes 10 \ + --instruct \ --src_dir data/$x \ --des_dir data/$x/parquet done diff --git a/tools/make_parquet_list.py b/tools/make_parquet_list.py index 8920841..29f42cc 100755 --- a/tools/make_parquet_list.py +++ b/tools/make_parquet_list.py @@ -37,6 +37,8 @@ def job(utt_list, parquet_file, utt2parquet_file, spk2parquet_file): speech_token_list = [utt2speech_token.get(utt, []) for utt in utt_list] if args.dpo: reject_speech_token_list = [utt2reject_speech_token[utt] for utt in utt_list] + if args.instruct: + instruct_list = [utt2instruct[utt] for utt in utt_list] # 保存到parquet,utt2parquet_file,spk2parquet_file df = pd.DataFrame() @@ -50,6 +52,8 @@ def job(utt_list, parquet_file, utt2parquet_file, spk2parquet_file): df['speech_token'] = speech_token_list if args.dpo: df['reject_speech_token'] = reject_speech_token_list + if args.instruct: + df['instruct'] = instruct_list df.to_parquet(parquet_file) with open(utt2parquet_file, 'w') as f: json.dump({k: parquet_file for k in utt_list}, f, ensure_ascii=False, indent=2) @@ -68,6 +72,10 @@ if __name__ == "__main__": type=int, default=1, help='num processes for make parquets') + parser.add_argument('--instruct', + action='store_true', + default=False, + help='has instruct file or not') parser.add_argument('--src_dir', type=str) parser.add_argument('--des_dir', @@ -91,6 +99,11 @@ if __name__ == "__main__": for l in f: l = l.replace('\n', '').split() utt2spk[l[0]] = l[1] + if args.instruct is True: + with open('{}/instruct'.format(args.src_dir)) as f: + for l in f: + l = l.replace('\n', '').split() + utt2instruct[l[0]] = ' '.join(l[1:]) utt2embedding = torch.load('{}/utt2embedding.pt'.format(args.src_dir)) spk2embedding = torch.load('{}/spk2embedding.pt'.format(args.src_dir)) utt2speech_token = torch.load('{}/utt2speech_token.pt'.format(args.src_dir)) From 5bc4b23f02278151c3d2aade403e07a4bdaf1871 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Fri, 12 Dec 2025 06:53:28 +0000 Subject: [PATCH 24/61] use amp in flow --- cosyvoice/bin/inference_deprecated.py | 126 -------------------------- cosyvoice/cli/model.py | 9 -- cosyvoice/flow/flow_matching.py | 13 +-- 3 files changed, 7 insertions(+), 141 deletions(-) delete mode 100644 cosyvoice/bin/inference_deprecated.py diff --git a/cosyvoice/bin/inference_deprecated.py b/cosyvoice/bin/inference_deprecated.py deleted file mode 100644 index 0d45cc7..0000000 --- a/cosyvoice/bin/inference_deprecated.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (c) 2024 Alibaba Inc (authors: Xiang Lyu) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function - -import argparse -import logging -logging.getLogger('matplotlib').setLevel(logging.WARNING) -import os -import torch -from torch.utils.data import DataLoader -import torchaudio -from hyperpyyaml import load_hyperpyyaml -from tqdm import tqdm -from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model -from cosyvoice.dataset.dataset import Dataset - - -def get_args(): - parser = argparse.ArgumentParser(description='inference with your model') - parser.add_argument('--config', required=True, help='config file') - parser.add_argument('--prompt_data', required=True, help='prompt data file') - parser.add_argument('--prompt_utt2data', required=True, help='prompt data file') - parser.add_argument('--tts_text', required=True, help='tts input file') - parser.add_argument('--qwen_pretrain_path', required=False, help='qwen pretrain path') - parser.add_argument('--llm_model', required=True, help='llm model file') - parser.add_argument('--flow_model', required=True, help='flow model file') - parser.add_argument('--hifigan_model', required=True, help='hifigan model file') - parser.add_argument('--gpu', - type=int, - default=-1, - help='gpu id for this rank, -1 for cpu') - parser.add_argument('--mode', - default='sft', - choices=['sft', 'zero_shot'], - help='inference mode') - parser.add_argument('--result_dir', required=True, help='asr result file') - args = parser.parse_args() - print(args) - return args - - -def main(): - args = get_args() - logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)s %(message)s') - os.environ['CUDA_VISIBLE_DEVICES'] = str(args.gpu) - - # Init cosyvoice models from configs - use_cuda = args.gpu >= 0 and torch.cuda.is_available() - device = torch.device('cuda' if use_cuda else 'cpu') - try: - with open(args.config, 'r') as f: - configs = load_hyperpyyaml(f, overrides={'qwen_pretrain_path': args.qwen_pretrain_path}) - model = CosyVoice2Model(configs['llm'], configs['flow'], configs['hift']) - except Exception: - try: - with open(args.config, 'r') as f: - configs = load_hyperpyyaml(f) - model = CosyVoiceModel(configs['llm'], configs['flow'], configs['hift']) - except Exception: - raise TypeError('no valid model_type!') - - model.load(args.llm_model, args.flow_model, args.hifigan_model) - - test_dataset = Dataset(args.prompt_data, data_pipeline=configs['data_pipeline'], mode='inference', shuffle=False, partition=False, - tts_file=args.tts_text, prompt_utt2data=args.prompt_utt2data) - test_data_loader = DataLoader(test_dataset, batch_size=None, num_workers=0) - - sample_rate = configs['sample_rate'] - del configs - os.makedirs(args.result_dir, exist_ok=True) - fn = os.path.join(args.result_dir, 'wav.scp') - f = open(fn, 'w') - with torch.no_grad(): - for _, batch in tqdm(enumerate(test_data_loader)): - utts = batch["utts"] - assert len(utts) == 1, "inference mode only support batchsize 1" - text_token = batch["text_token"].to(device) - text_token_len = batch["text_token_len"].to(device) - tts_index = batch["tts_index"] - tts_text_token = batch["tts_text_token"].to(device) - tts_text_token_len = batch["tts_text_token_len"].to(device) - speech_token = batch["speech_token"].to(device) - speech_token_len = batch["speech_token_len"].to(device) - speech_feat = batch["speech_feat"].to(device) - speech_feat_len = batch["speech_feat_len"].to(device) - utt_embedding = batch["utt_embedding"].to(device) - spk_embedding = batch["spk_embedding"].to(device) - if args.mode == 'sft': - model_input = {'text': tts_text_token, 'text_len': tts_text_token_len, - 'llm_embedding': spk_embedding, 'flow_embedding': spk_embedding} - else: - model_input = {'text': tts_text_token, 'text_len': tts_text_token_len, - 'prompt_text': text_token, 'prompt_text_len': text_token_len, - 'llm_prompt_speech_token': speech_token, 'llm_prompt_speech_token_len': speech_token_len, - 'flow_prompt_speech_token': speech_token, 'flow_prompt_speech_token_len': speech_token_len, - 'prompt_speech_feat': speech_feat, 'prompt_speech_feat_len': speech_feat_len, - 'llm_embedding': utt_embedding, 'flow_embedding': utt_embedding} - tts_speeches = [] - for model_output in model.tts(**model_input): - tts_speeches.append(model_output['tts_speech']) - tts_speeches = torch.concat(tts_speeches, dim=1) - tts_key = '{}_{}'.format(utts[0], tts_index[0]) - tts_fn = os.path.join(args.result_dir, '{}.wav'.format(tts_key)) - torchaudio.save(tts_fn, tts_speeches, sample_rate=sample_rate, backend='soundfile') - f.write('{} {}\n'.format(tts_key, tts_fn)) - f.flush() - f.close() - logging.info('Result wav.scp saved in {}'.format(fn)) - - -if __name__ == '__main__': - logging.warning('this code has been deprecated, please refer to README for CosyVoice inference usage!') - main() diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 0f9416a..01e76c6 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -38,9 +38,6 @@ class CosyVoiceModel: self.flow = flow self.hift = hift self.fp16 = fp16 - if self.fp16 is True: - self.llm.half() - self.flow.half() self.token_min_hop_len = 2 * self.flow.input_frame_rate self.token_max_hop_len = 4 * self.flow.input_frame_rate self.token_overlap_len = 20 @@ -249,9 +246,6 @@ class CosyVoice2Model(CosyVoiceModel): self.flow = flow self.hift = hift self.fp16 = fp16 - if self.fp16 is True: - self.llm.half() - self.flow.half() # NOTE must matching training static_chunk_size self.token_hop_len = 25 # hift cache @@ -398,9 +392,6 @@ class CosyVoice3Model(CosyVoice2Model): self.flow = flow self.hift = hift self.fp16 = fp16 - if self.fp16 is True: - self.llm.half() - self.flow.half() # NOTE must matching training static_chunk_size self.token_hop_len = 25 # rtf and decoding related diff --git a/cosyvoice/flow/flow_matching.py b/cosyvoice/flow/flow_matching.py index 7f92df5..a45337a 100644 --- a/cosyvoice/flow/flow_matching.py +++ b/cosyvoice/flow/flow_matching.py @@ -91,12 +91,13 @@ class ConditionalCFM(BASECFM): sol = [] # Do not use concat, it may cause memory format changed and trt infer with wrong results! - x_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=x.dtype) - mask_in = torch.zeros([2, 1, x.size(2)], device=x.device, dtype=x.dtype) - mu_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=x.dtype) - t_in = torch.zeros([2], device=x.device, dtype=x.dtype) - spks_in = torch.zeros([2, 80], device=x.device, dtype=x.dtype) - cond_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=x.dtype) + # NOTE when flow run in amp mode, x.dtype is float32, which cause nan in trt fp16 inference, so set dtype=spks.dtype + x_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=spks.dtype) + mask_in = torch.zeros([2, 1, x.size(2)], device=x.device, dtype=spks.dtype) + mu_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=spks.dtype) + t_in = torch.zeros([2], device=x.device, dtype=spks.dtype) + spks_in = torch.zeros([2, 80], device=x.device, dtype=spks.dtype) + cond_in = torch.zeros([2, 80, x.size(2)], device=x.device, dtype=spks.dtype) for step in range(1, len(t_span)): # Classifier-Free Guidance inference introduced in VoiceBox x_in[:] = x From 564054540651812e08741e5d134f384d1a4edf83 Mon Sep 17 00:00:00 2001 From: "hengwu.zty" Date: Fri, 12 Dec 2025 18:38:30 +0800 Subject: [PATCH 25/61] update readme --- README.md | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9ab26e5..05aec42 100644 --- a/README.md +++ b/README.md @@ -10,26 +10,14 @@ ## Highlight🔥 -**CosyVoice 3.0** is here! Building on the strengths of version 2.0, it achieves a leap in "in-the-wild speech generation" with larger scale, more powerful technology, and broader coverage—delivering more natural, accurate, and versatile speech synthesis capabilities. -### Multilingual & Wide Coverage -- **Expanded Language** Support: Covers 9 universal languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian) and 18+ Chinese dialects/accents, supporting zero-shot multilingual/cross-lingual voice cloning. -- **Massive Data Upgrade**: Training data scaled from ten thousand hours to 1 million hours,enhancing cross-lingual generalization and synthesis stability. -- **Polyglot Transformation**: Enables monolingual speakers to generate speech in multiple languages, with WER/CER below 4% for most languages. -### High Precision & Robustness -- **Superior Content Consistency**: Compared to 2.0, Chinese test set CER relative improves 44%, English test set 51%, and complex scenario (test-hard) CER drops from 6.83% to 5.09%. -- **Pronunciation Perfection**: Features pronunciation inpainting technology with high correction rate for polyphonic characters and rare words, solving long-standing pronunciation challenges. -- **Strong Scene Adaptability**: Excels in noisy backgrounds, tongue twisters, and domain-specific terms; self-training text normalization supports raw text direct synthesis, compatible with special symbols. -### Natural & Expressive Experience -- **Rich Style Control**: Supports 100+ speaking styles (emotions, speeds, roles, accents) and fine-grained instructions ([laughter], [breath], emphasis). -- **Advanced Emotion CloningControl**:: Optimized with DiffRO-EMO, leading in emotion accuracy for both text-related and text-unrelated scenarios. -### Innovative Core Technology -- **DiffRO Optimization**: Innovative reinforcement learning method, directly optimizing speech tokens, improving WER by 20%-50% in low-resource/cross-lingual scenarios, applicable to other LLM-based TTS models. -- **Supervised Multi-task Tokenizer**: Trained on ASR, SER, LID, etc., better capturing paralinguistic information like emotion and pronunciation style. -- **Pronunciation & Text Normalization**: Supports word-phoneme mixed sequence modeling; LLM-based self-training TN eliminates manual rules. -### Real-time & Flexible Deployment -- **Multi-mode Support**: Single model compatible with offline mode, one-way streaming, and bidirectional streaming, meeting diverse deployment needs. -- **Ultra-low Latency**: Achieves latency as low as 150ms while maintaining high-quality audio output. -- **Hot Fix Capability**: Supports SSML hot fix and built-in TN capability, enhancing usability and adaptability to complex text formats. +**CosyVoice 3.0** is an advanced text-to-speech (TTS) system based on large language models (LLM), surpassing its predecessor (CosyVoice 2.0) in content consistency, speaker similarity, and prosody naturalness. It is designed for zero-shot multilingual speech synthesis in the wild. +### Key Features +- **Language Coverage**: Covers 9 common languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian), 18+ Chinese dialects/accents and meanwhile supports both multi-lingual/cross-lingual zero-shot voice cloning. +- **Content Consistency & Naturalness**: Achieves state-of-the-art performance in content consistency, speaker similarity, and prosody naturalness. +- **Pronunciation Inpainting**: Supports pronunciation inpainting of Chinese Pinyin and English CMU phonemes, providing more controllability and thus suitable for production use. +- **Text Normalization**: Supports reading of numbers, special symbols and various text formats without a traditional frontend module. +- **Bi-Streaming**: Support both text-in streaming and audio-out streaming, and achieves latency as low as 150ms while maintaining high-quality audio output. +- **Instruct Support**: Supports various instructions such as languages, dialects, emotions, speed, volume, etc. ## Roadmap @@ -71,6 +59,25 @@ - [x] WeTextProcessing support when ttsfrd is not available - [x] Fastapi server and client +## Evaluation +| Model | CER (%) ↓ (test-zh) | WER (%) ↓ (test-en) | CER (%) ↓ (test-hard) | +|-----|------------------|------------------|------------------| +| Human | 1.26 | 2.14 | - | +| F5-TTS | 1.53 | 2.00 | 8.67 | +| SparkTTS | 1.20 | 1.98 | - | +| Seed-TTS | 1.12 | 2.25 | 7.59 | +| CosyVoice2 | 1.45 | 2.57 | 6.83 | +| FireRedTTS-2 | 1.14 | 1.95 | - | +| IndexTTS2 | 1.01 | 1.52 | 7.12 | +| VibeVoice | 1.16 | 3.04 | - | +| HiggsAudio | 1.79 | 2.44 | - | +| MiniMax-Speech | 0.83 | 1.65 | - | +| VoxPCM | 0.93 | 1.85 | 8.87 | +| GLM-TTS | 1.03 | - | - | +| GLM-TTS_RL | 0.89 | - | - | +| CosyVoice3 | 1.21 | 2.24 | 6.71 | +| CosyVoice3_RL | 0.81 | 1.68 | 5.44 | + ## Install From b02d7e61f743839a93d4058d9c11e79f82fad041 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Fri, 12 Dec 2025 08:42:35 +0000 Subject: [PATCH 26/61] update prompt wav --- asset/zero_shot_prompt.wav | Bin 111496 -> 334138 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/asset/zero_shot_prompt.wav b/asset/zero_shot_prompt.wav index 25fbf592f2a5efa3d966ff64084c75a43be4cc1e..a7b9d954289ddf5c90a4dc4f0a912edaea10945a 100644 GIT binary patch literal 334138 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 z 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 z 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%0DDXdRUZ1Vi!5d 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 za(∈PeIHMbuoVB{M`Y96ia=Wd==_W(Cap5meRuXAbU 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 I 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 bnMsLf7;u{A-B211Vn&g&`Za27pY5LB58&hA{Y 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 literal 111496 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�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 Date: Fri, 12 Dec 2025 10:41:25 +0000 Subject: [PATCH 27/61] fix bistream bug --- cosyvoice/cli/frontend.py | 6 +++--- cosyvoice/cli/model.py | 28 ++++++++++++++-------------- cosyvoice/hifigan/generator.py | 16 +++++++++------- cosyvoice/llm/llm.py | 7 ++++--- example.py | 12 ++++++------ vllm_example.py | 2 +- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index 4292931..0942da6 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -122,12 +122,12 @@ class CosyVoiceFrontEnd: return speech_feat, speech_feat_len def text_normalize(self, text, split=True, text_frontend=True): - # NOTE skip text_frontend when ssml symbol in text - if '<|' in text and '|>' in text: - text_frontend = False if isinstance(text, Generator): logging.info('get tts_text generator, will skip text_normalize!') return [text] + # NOTE skip text_frontend when ssml symbol in text + if '<|' in text and '|>' in text: + text_frontend = False if text_frontend is False or text == '': return [text] if split is True else text text = text.strip() diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 01e76c6..8e67b0c 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -413,18 +413,18 @@ class CosyVoice3Model(CosyVoice2Model): embedding=embedding.to(self.device), streaming=stream, finalize=finalize) - tts_mel = tts_mel[:, :, token_offset * self.flow.token_mel_ratio:] - # append mel cache - if self.hift_cache_dict[uuid] is not None: - hift_cache_mel = self.hift_cache_dict[uuid]['mel'] - tts_mel = torch.concat([hift_cache_mel, tts_mel], dim=2) - self.hift_cache_dict[uuid]['mel'] = tts_mel - else: - self.hift_cache_dict[uuid] = {'mel': tts_mel, 'speech_offset': 0} - if speed != 1.0: - assert token_offset == 0 and finalize is True, 'speed change only support non-stream inference mode' - tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') - tts_speech, _ = self.hift.inference(speech_feat=tts_mel, finalize=finalize) - tts_speech = tts_speech[:, self.hift_cache_dict[uuid]['speech_offset']:] - self.hift_cache_dict[uuid]['speech_offset'] += tts_speech.shape[1] + tts_mel = tts_mel[:, :, token_offset * self.flow.token_mel_ratio:] + # append mel cache + if self.hift_cache_dict[uuid] is not None: + hift_cache_mel = self.hift_cache_dict[uuid]['mel'] + tts_mel = torch.concat([hift_cache_mel, tts_mel], dim=2) + self.hift_cache_dict[uuid]['mel'] = tts_mel + else: + self.hift_cache_dict[uuid] = {'mel': tts_mel, 'speech_offset': 0} + if speed != 1.0: + assert token_offset == 0 and finalize is True, 'speed change only support non-stream inference mode' + tts_mel = F.interpolate(tts_mel, size=int(tts_mel.shape[2] / speed), mode='linear') + tts_speech, _ = self.hift.inference(speech_feat=tts_mel, finalize=finalize) + tts_speech = tts_speech[:, self.hift_cache_dict[uuid]['speech_offset']:] + self.hift_cache_dict[uuid]['speech_offset'] += tts_speech.shape[1] return tts_speech diff --git a/cosyvoice/hifigan/generator.py b/cosyvoice/hifigan/generator.py index c893b11..045cb4e 100644 --- a/cosyvoice/hifigan/generator.py +++ b/cosyvoice/hifigan/generator.py @@ -155,11 +155,13 @@ class SineGen(torch.nn.Module): @torch.no_grad() def forward(self, f0): + """ sine_tensor, uv = forward(f0) + input F0: tensor(batchsize=1, dim=1, length) + f0 for unvoiced steps should be 0 + output sine_tensor: tensor(batchsize=1, length, dim) + output uv: tensor(batchsize=1, length, 1) """ - :param f0: [B, 1, sample_len], Hz - :return: [B, 1, sample_len] - """ - + f0 = f0.transpose(1, 2) F_mat = torch.zeros((f0.size(0), self.harmonic_num + 1, f0.size(-1))).to(f0.device) for i in range(self.harmonic_num + 1): F_mat[:, i: i + 1, :] = f0 * (i + 1) / self.sampling_rate @@ -184,7 +186,7 @@ class SineGen(torch.nn.Module): # first: set the unvoiced part to 0 by uv # then: additive noise sine_waves = sine_waves * uv + noise - return sine_waves, uv, noise + return sine_waves.transpose(1, 2), uv.transpose(1, 2), noise class SineGen2(torch.nn.Module): @@ -221,7 +223,7 @@ class SineGen2(torch.nn.Module): if causal is True: self.rand_ini = torch.rand(1, 9) self.rand_ini[:, 0] = 0 - self.sine_waves = torch.rand(1, 60 * 16000, 9) + self.sine_waves = torch.rand(1, 300 * 24000, 9) def _f02uv(self, f0): # generate uv signal @@ -351,7 +353,7 @@ class SourceModuleHnNSF(torch.nn.Module): self.l_tanh = torch.nn.Tanh() self.causal = causal if causal is True: - self.uv = torch.rand(1, 60 * 24000, 1) + self.uv = torch.rand(1, 300 * 24000, 1) def forward(self, x): """ diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index c0b3400..eacde5b 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -17,6 +17,7 @@ import random import time import threading from typing import Dict, Optional, Callable, List, Generator +import numpy as np import torch from torch import nn import torch.nn.functional as F @@ -216,7 +217,7 @@ class TransformerLM(torch.nn.Module): att_mask=torch.tril(torch.ones((1, lm_input.shape[1], lm_input.shape[1]), device=lm_input.device)).to(torch.bool)) logp = self.llm_decoder(y_pred[:, -1]).log_softmax(dim=-1) - top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False).item() + top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True if i < min_len else False) if top_ids == self.eos_token: break # in stream mode, yield token one by one @@ -544,7 +545,7 @@ class Qwen2LM(TransformerLM): cache = None # NOTE init prompt_text as text_cache as it is basically impossible prompt_speech_token/prompt_text < 15/5 text_cache = self.llm.model.model.embed_tokens(prompt_text) - next_fill_index = -1 + next_fill_index = (int(prompt_speech_token.shape[1] / self.mix_ratio[1]) + 1) * self.mix_ratio[1] - prompt_speech_token.shape[1] for this_text in text: text_cache = torch.concat([text_cache, self.llm.model.model.embed_tokens(this_text)], dim=1) # prompt_speech_token_emb not empty, try append to lm_input @@ -582,7 +583,7 @@ class Qwen2LM(TransformerLM): top_ids = self.fill_token next_fill_index += (self.mix_ratio[1] + 1) else: - top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True).item() + top_ids = self.sampling_ids(logp.squeeze(dim=0), out_tokens, sampling, ignore_eos=True) if top_ids == self.fill_token: next_fill_index = len(out_tokens) + self.mix_ratio[1] + 1 logging.info('fill_token index {} next fill_token index {}'.format(len(out_tokens), next_fill_index)) diff --git a/example.py b/example.py index 1e507c0..85952ae 100644 --- a/example.py +++ b/example.py @@ -15,15 +15,15 @@ def cosyvoice_example(): torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M') - # zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean + # zero_shot usage for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav')): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - # cross_lingual usage + # cross_lingual usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', './asset/cross_lingual_prompt.wav')): torchaudio.save('cross_lingual_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) # vc usage - for i, j in enumerate(cosyvoice.inference_vc('./asset/zero_shot_prompt.wav', './asset/cross_lingual_prompt.wav')): + for i, j in enumerate(cosyvoice.inference_vc('./asset/cross_lingual_prompt.wav', './asset/zero_shot_prompt.wav')): torchaudio.save('vc_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) cosyvoice = AutoModel(model_dir='pretrained_models/CosyVoice-300M-Instruct') @@ -65,7 +65,7 @@ def cosyvoice2_example(): yield '让我心中充满了甜蜜的快乐,' yield '笑容如花儿般绽放。' for i, j in enumerate(cosyvoice.inference_zero_shot(text_generator(), '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav', stream=False)): - torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) + torchaudio.save('zero_shot_bistream_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) def cosyvoice3_example(): @@ -97,8 +97,8 @@ def cosyvoice3_example(): def main(): - cosyvoice_example() - cosyvoice2_example() + # cosyvoice_example() + # cosyvoice2_example() cosyvoice3_example() diff --git a/vllm_example.py b/vllm_example.py index f82cfe7..697d7a9 100644 --- a/vllm_example.py +++ b/vllm_example.py @@ -31,7 +31,7 @@ def cosyvoice3_example(): def main(): - cosyvoice2_example() + # cosyvoice2_example() cosyvoice3_example() From a6eb2c56da75472addfb68a369665edaf79aeba0 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Sun, 14 Dec 2025 14:00:40 +0000 Subject: [PATCH 28/61] update dingding --- asset/dingding.png | Bin 96417 -> 122824 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/asset/dingding.png b/asset/dingding.png index 8467cd964ca2aaf2cd3f018eb183fc5631de1234..b7a955e32779a8693ac313963c4779544da2ca5d 100644 GIT binary patch literal 122824 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 literal 96417 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ÊVmVY^qWc| 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ì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%0AF2pisU4a}N(i1T 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 Date: Mon, 15 Dec 2025 03:53:10 +0000 Subject: [PATCH 29/61] update readme --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 05aec42..29f4cd0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## 👉🏻 CosyVoice 👈🏻 -**CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) +**Fun-CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) **CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/spaces/FunAudioLLM/CosyVoice2-0.5B) @@ -10,9 +10,9 @@ ## Highlight🔥 -**CosyVoice 3.0** is an advanced text-to-speech (TTS) system based on large language models (LLM), surpassing its predecessor (CosyVoice 2.0) in content consistency, speaker similarity, and prosody naturalness. It is designed for zero-shot multilingual speech synthesis in the wild. +**Fun-CosyVoice 3.0** is an advanced text-to-speech (TTS) system based on large language models (LLM), surpassing its predecessor (CosyVoice 2.0) in content consistency, speaker similarity, and prosody naturalness. It is designed for zero-shot multilingual speech synthesis in the wild. ### Key Features -- **Language Coverage**: Covers 9 common languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian), 18+ Chinese dialects/accents and meanwhile supports both multi-lingual/cross-lingual zero-shot voice cloning. +- **Language Coverage**: Covers 9 common languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian), 18+ Chinese dialects/accents (Guangdong, Minnan, Sichuan, Dongbei, Shan3xi, Shan1xi, Shanghai, Tianjin, Shan1dong, Ningxia, Gansu, etc.) and meanwhile supports both multi-lingual/cross-lingual zero-shot voice cloning. - **Content Consistency & Naturalness**: Achieves state-of-the-art performance in content consistency, speaker similarity, and prosody naturalness. - **Pronunciation Inpainting**: Supports pronunciation inpainting of Chinese Pinyin and English CMU phonemes, providing more controllability and thus suitable for production use. - **Text Normalization**: Supports reading of numbers, special symbols and various text formats without a traditional frontend module. @@ -24,8 +24,8 @@ - [x] 2025/12 - - [x] release CosyVoice3-0.5B base model and its training/inference script - - [x] release CosyVoice3-0.5B modelscope gradio space + - [x] release Fun-CosyVoice3-0.5B-2512 base model, rl model and its training/inference script + - [x] release Fun-CosyVoice3-0.5B modelscope gradio space - [x] 2025/08 @@ -33,7 +33,7 @@ - [x] 2025/07 - - [x] release CosyVoice 3.0 eval set + - [x] release Fun-CosyVoice 3.0 eval set - [x] 2025/05 @@ -108,12 +108,12 @@ ### Model download -We strongly recommend that you download our pretrained `CosyVoice2-0.5B` `CosyVoice-300M` `CosyVoice-300M-SFT` `CosyVoice-300M-Instruct` model and `CosyVoice-ttsfrd` resource. +We strongly recommend that you download our pretrained `Fun-CosyVoice3-0.5B` `CosyVoice2-0.5B` `CosyVoice-300M` `CosyVoice-300M-SFT` `CosyVoice-300M-Instruct` model and `CosyVoice-ttsfrd` resource. ``` python # SDK模型下载 from modelscope import snapshot_download -snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B', local_dir='pretrained_models/Fun-CosyVoice3-0.5B') +snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B-2512', local_dir='pretrained_models/Fun-CosyVoice3-0.5B') snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B') snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M') snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT') @@ -134,7 +134,7 @@ pip install ttsfrd-0.4.2-cp310-cp310-linux_x86_64.whl ### Basic Usage -We strongly recommend using `CosyVoice3-0.5B` for better performance. +We strongly recommend using `Fun-CosyVoice3-0.5B` for better performance. Follow the code in `example.py` for detailed usage of each model. ```sh python example.py From 95d56cba64d112246954c7c299d6974bac3689e0 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 03:56:42 +0000 Subject: [PATCH 30/61] update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29f4cd0..5a9185d 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,8 @@ | VoxPCM | 0.93 | 1.85 | 8.87 | | GLM-TTS | 1.03 | - | - | | GLM-TTS_RL | 0.89 | - | - | -| CosyVoice3 | 1.21 | 2.24 | 6.71 | -| CosyVoice3_RL | 0.81 | 1.68 | 5.44 | +| Fun-CosyVoice3-0.5B-2512 | 1.21 | 2.24 | 6.71 | +| Fun-CosyVoice3-0.5B-2512_RL | 0.81 | 1.68 | 5.44 | ## Install From 089343ab0a6b84987ff4864cfda52f2843275bc9 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 12:44:06 +0800 Subject: [PATCH 31/61] update --- tools/make_parquet_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/make_parquet_list.py b/tools/make_parquet_list.py index 29f42cc..2f35ae6 100755 --- a/tools/make_parquet_list.py +++ b/tools/make_parquet_list.py @@ -86,7 +86,7 @@ if __name__ == "__main__": help='Use Direct Preference Optimization') args = parser.parse_args() - utt2wav, utt2text, utt2spk = {}, {}, {} + utt2wav, utt2text, utt2spk, utt2instruct = {}, {}, {}, {} with open('{}/wav.scp'.format(args.src_dir)) as f: for l in f: l = l.replace('\n', '').split() From f11ba4024c6fa1da3f44fb8ae7c5bf37ded72aff Mon Sep 17 00:00:00 2001 From: "hengwu.zty" Date: Mon, 15 Dec 2025 13:24:44 +0800 Subject: [PATCH 32/61] [mod]readme --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 5a9185d..612b70b 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ **Fun-CosyVoice 3.0** is an advanced text-to-speech (TTS) system based on large language models (LLM), surpassing its predecessor (CosyVoice 2.0) in content consistency, speaker similarity, and prosody naturalness. It is designed for zero-shot multilingual speech synthesis in the wild. ### Key Features -- **Language Coverage**: Covers 9 common languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian), 18+ Chinese dialects/accents (Guangdong, Minnan, Sichuan, Dongbei, Shan3xi, Shan1xi, Shanghai, Tianjin, Shan1dong, Ningxia, Gansu, etc.) and meanwhile supports both multi-lingual/cross-lingual zero-shot voice cloning. +- **Language Coverage**: Covers 9 common languages (Chinese, English, Japanese, Korean, German, Spanish, French, Italian, Russian), 18+ Chinese dialects/accents (Guangdong, Minnan, Sichuan, Dongbei, Shan3xi, Shan1xi, Shanghai, Tianjin, Shandong, Ningxia, Gansu, etc.) and meanwhile supports both multi-lingual/cross-lingual zero-shot voice cloning. - **Content Consistency & Naturalness**: Achieves state-of-the-art performance in content consistency, speaker similarity, and prosody naturalness. - **Pronunciation Inpainting**: Supports pronunciation inpainting of Chinese Pinyin and English CMU phonemes, providing more controllability and thus suitable for production use. - **Text Normalization**: Supports reading of numbers, special symbols and various text formats without a traditional frontend module. @@ -60,23 +60,23 @@ - [x] Fastapi server and client ## Evaluation -| Model | CER (%) ↓ (test-zh) | WER (%) ↓ (test-en) | CER (%) ↓ (test-hard) | -|-----|------------------|------------------|------------------| -| Human | 1.26 | 2.14 | - | -| F5-TTS | 1.53 | 2.00 | 8.67 | -| SparkTTS | 1.20 | 1.98 | - | -| Seed-TTS | 1.12 | 2.25 | 7.59 | -| CosyVoice2 | 1.45 | 2.57 | 6.83 | -| FireRedTTS-2 | 1.14 | 1.95 | - | -| IndexTTS2 | 1.01 | 1.52 | 7.12 | -| VibeVoice | 1.16 | 3.04 | - | -| HiggsAudio | 1.79 | 2.44 | - | -| MiniMax-Speech | 0.83 | 1.65 | - | -| VoxPCM | 0.93 | 1.85 | 8.87 | -| GLM-TTS | 1.03 | - | - | -| GLM-TTS_RL | 0.89 | - | - | -| Fun-CosyVoice3-0.5B-2512 | 1.21 | 2.24 | 6.71 | -| Fun-CosyVoice3-0.5B-2512_RL | 0.81 | 1.68 | 5.44 | +| Model | Model Size | CER (%) ↓ (test-zh) | WER (%) ↓ (test-en) | CER (%) ↓ (test-hard) | +|-------|------------|---------------------|---------------------|-----------------------| +| Human | - | 1.26 | 2.14 | - | +| Seed-TTS | - | 1.12 | 2.25 | 7.59 | +| MiniMax-Speech | - | 0.83 | 1.65 | - | +| F5-TTS | 0.3B | 1.52 | 2.00 | 8.67 | +| SparkTTS | 0.5B | 1.20 | 1.98 | - | +| CosyVoice2 | 0.5B | 1.45 | 2.57 | 6.83 | +| FireRedTTS-2 | - | 1.14 | 1.95 | - | +| IndexTTS2 | 1.5B | 1.01 | 1.52 | 7.12 | +| VibeVoice | 1.5B | 1.16 | 3.04 | - | +| HiggsAudio-v2 | 3B | 1.50 | 2.44 | - | +| VoxPCM | 0.5B | 0.93 | 1.85 | 8.87 | +| GLM-TTS | - | 1.03 | - | - | +| GLM-TTS_RL | - | 0.89 | - | - | +| Fun-CosyVoice3-0.5B-2512 | 0.5B | 1.21 | 2.24 | 6.71 | +| Fun-CosyVoice3-0.5B-2512_RL | 0.5B | 0.81 | 1.68 | 5.44 | ## Install From f51f5c5c6a2292fe2f839e9d7beefe941095533b Mon Sep 17 00:00:00 2001 From: "hengwu.zty" Date: Mon, 15 Dec 2025 13:39:56 +0800 Subject: [PATCH 33/61] [mod]readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 612b70b..f881298 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ | F5-TTS | 0.3B | 1.52 | 2.00 | 8.67 | | SparkTTS | 0.5B | 1.20 | 1.98 | - | | CosyVoice2 | 0.5B | 1.45 | 2.57 | 6.83 | -| FireRedTTS-2 | - | 1.14 | 1.95 | - | +| FireRedTTS-2 | 1.5B | 1.14 | 1.95 | - | | IndexTTS2 | 1.5B | 1.01 | 1.52 | 7.12 | | VibeVoice | 1.5B | 1.16 | 3.04 | - | | HiggsAudio-v2 | 3B | 1.50 | 2.44 | - | From a460960adec10b4763e273f00cb12e8586370f60 Mon Sep 17 00:00:00 2001 From: "hengwu.zty" Date: Mon, 15 Dec 2025 13:53:11 +0800 Subject: [PATCH 34/61] [mod]readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f881298..81408ef 100644 --- a/README.md +++ b/README.md @@ -73,8 +73,8 @@ | VibeVoice | 1.5B | 1.16 | 3.04 | - | | HiggsAudio-v2 | 3B | 1.50 | 2.44 | - | | VoxPCM | 0.5B | 0.93 | 1.85 | 8.87 | -| GLM-TTS | - | 1.03 | - | - | -| GLM-TTS_RL | - | 0.89 | - | - | +| GLM-TTS | 1.5B | 1.03 | - | - | +| GLM-TTS_RL | 1.5B | 0.89 | - | - | | Fun-CosyVoice3-0.5B-2512 | 0.5B | 1.21 | 2.24 | 6.71 | | Fun-CosyVoice3-0.5B-2512_RL | 0.5B | 0.81 | 1.68 | 5.44 | From 9476a063b395a49dea67ca7d565757f8fb9c70e8 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 14:48:17 +0800 Subject: [PATCH 35/61] update metric --- README.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 81408ef..6b81b5f 100644 --- a/README.md +++ b/README.md @@ -60,23 +60,25 @@ - [x] Fastapi server and client ## Evaluation -| Model | Model Size | CER (%) ↓ (test-zh) | WER (%) ↓ (test-en) | CER (%) ↓ (test-hard) | -|-------|------------|---------------------|---------------------|-----------------------| -| Human | - | 1.26 | 2.14 | - | -| Seed-TTS | - | 1.12 | 2.25 | 7.59 | -| MiniMax-Speech | - | 0.83 | 1.65 | - | -| F5-TTS | 0.3B | 1.52 | 2.00 | 8.67 | -| SparkTTS | 0.5B | 1.20 | 1.98 | - | -| CosyVoice2 | 0.5B | 1.45 | 2.57 | 6.83 | -| FireRedTTS-2 | 1.5B | 1.14 | 1.95 | - | -| IndexTTS2 | 1.5B | 1.01 | 1.52 | 7.12 | -| VibeVoice | 1.5B | 1.16 | 3.04 | - | -| HiggsAudio-v2 | 3B | 1.50 | 2.44 | - | -| VoxPCM | 0.5B | 0.93 | 1.85 | 8.87 | -| GLM-TTS | 1.5B | 1.03 | - | - | -| GLM-TTS_RL | 1.5B | 0.89 | - | - | -| Fun-CosyVoice3-0.5B-2512 | 0.5B | 1.21 | 2.24 | 6.71 | -| Fun-CosyVoice3-0.5B-2512_RL | 0.5B | 0.81 | 1.68 | 5.44 | + +| Model | Open-Source | Model Size | test-zh
CER (%) ↓ | test-zh
Speaker Similarity (%) ↑ | test-en
WER (%) ↓ | test-en
Speaker Similarity (%) ↑ | test-hard
CER (%) ↓ | test-hard
Speaker Similarity (%) | +| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| Human | - | - | 1.26 | 75.5 | 2.14 | 73.4 | - | - | +| Seed-TTS | ❌ | - | 1.12 | 79.6 | 2.25 | 76.2 | 7.59 | 77.6 | +| MiniMax-Speech | ❌ | - | 0.83 | 78.3 | 1.65 | 69.2 | - | - | +| F5-TTS | ✅ | 0.3B | 1.52 | 74.1 | 2.00 | 64.7 | 8.67 | 71.3 | +| Spark TTS | ✅ | 0.5B | 1.2 | 66.0 | 1.98 | 57.3 | - | - | +| CosyVoice2 | ✅ | 0.5B | 1.45 | 75.7 | 2.57 | 65.9 | 6.83 | 72.4 | +| FireRedTTS 2 | ✅ | 1.5B | 1.14 | 73.2 | 1.95 | 66.5 | - | - | +| Index-TTS2 | ✅ | 1.5B | 1.03 | 76.5 | 2.23 | 70.6 | 7.12 | 75.5 | +| VibeVoice-1.5B | ✅ | 1.5B | 1.16 | 74.4 | 3.04 | 68.9 | - | - | +| VibeVoice-Realtime | ✅ | 0.5B | - | - | 2.05 | 63.3 | - | - | +| HiggsAudio-v2 | ✅ | 3B | 1.50 | 74.0 | 2.44 | 67.7 | - | - | +| VoxCPM | ✅ | 0.5B | 0.93 | 77.2 | 1.85 | 72.9 | 8.87 | 73.0 | +| GLM-TTS | ✅ | 1.5B | 1.03 | 76.1 | - | - | - | - | +| GLM-TTS RL | ✅ | 1.5B | 0.89 | 76.4 | - | - | - | - | +| Fun-CosyVoice3-0.5B | ✅ | 0.5B | 1.21 | 78.0 | 2.24 | 71.8 | 6.71 | 75.8 | +| Fun-CosyVoice3-0.5B-2512 | ✅ | 0.5B | 0.81 | 77.4 | 1.68 | 69.5 | 5.44 | 75.0 | ## Install From 781a49acb4339fcb4f5e3340e3e045e941afd55c Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 14:52:32 +0800 Subject: [PATCH 36/61] update metric --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b81b5f..6ae2055 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,8 @@ | VoxCPM | ✅ | 0.5B | 0.93 | 77.2 | 1.85 | 72.9 | 8.87 | 73.0 | | GLM-TTS | ✅ | 1.5B | 1.03 | 76.1 | - | - | - | - | | GLM-TTS RL | ✅ | 1.5B | 0.89 | 76.4 | - | - | - | - | -| Fun-CosyVoice3-0.5B | ✅ | 0.5B | 1.21 | 78.0 | 2.24 | 71.8 | 6.71 | 75.8 | -| Fun-CosyVoice3-0.5B-2512 | ✅ | 0.5B | 0.81 | 77.4 | 1.68 | 69.5 | 5.44 | 75.0 | +| Fun-CosyVoice3-0.5B-2512 | ✅ | 0.5B | 1.21 | 78.0 | 2.24 | 71.8 | 6.71 | 75.8 | +| Fun-CosyVoice3-0.5B-2512_RL | ✅ | 0.5B | 0.81 | 77.4 | 1.68 | 69.5 | 5.44 | 75.0 | ## Install From 4d4c787be0d2da6b2db063763bf2ac75b78e2b51 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 15:33:52 +0800 Subject: [PATCH 37/61] update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ae2055..d475567 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ ## Evaluation -| Model | Open-Source | Model Size | test-zh
CER (%) ↓ | test-zh
Speaker Similarity (%) ↑ | test-en
WER (%) ↓ | test-en
Speaker Similarity (%) ↑ | test-hard
CER (%) ↓ | test-hard
Speaker Similarity (%) | +| Model | Open-Source | Model Size | test-zh
CER (%) ↓ | test-zh
Speaker Similarity (%) ↑ | test-en
WER (%) ↓ | test-en
Speaker Similarity (%) ↑ | test-hard
CER (%) ↓ | test-hard
Speaker Similarity (%) ↑ | | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | | Human | - | - | 1.26 | 75.5 | 2.14 | 73.4 | - | - | | Seed-TTS | ❌ | - | 1.12 | 79.6 | 2.25 | 76.2 | 7.59 | 77.6 | @@ -69,7 +69,7 @@ | F5-TTS | ✅ | 0.3B | 1.52 | 74.1 | 2.00 | 64.7 | 8.67 | 71.3 | | Spark TTS | ✅ | 0.5B | 1.2 | 66.0 | 1.98 | 57.3 | - | - | | CosyVoice2 | ✅ | 0.5B | 1.45 | 75.7 | 2.57 | 65.9 | 6.83 | 72.4 | -| FireRedTTS 2 | ✅ | 1.5B | 1.14 | 73.2 | 1.95 | 66.5 | - | - | +| FireRedTTS2 | ✅ | 1.5B | 1.14 | 73.2 | 1.95 | 66.5 | - | - | | Index-TTS2 | ✅ | 1.5B | 1.03 | 76.5 | 2.23 | 70.6 | 7.12 | 75.5 | | VibeVoice-1.5B | ✅ | 1.5B | 1.16 | 74.4 | 3.04 | 68.9 | - | - | | VibeVoice-Realtime | ✅ | 0.5B | - | - | 2.05 | 63.3 | - | - | From e98b828f330e457777ba6b009aeca69595a5a1c1 Mon Sep 17 00:00:00 2001 From: Xiangang Li Date: Mon, 15 Dec 2025 15:54:32 +0800 Subject: [PATCH 38/61] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d475567..052e7a0 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ## 👉🏻 CosyVoice 👈🏻 -**Fun-CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) +**Fun-CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval); [Huggingface](https://huggingface.co/FunAudioLLM/Fun-CosyVoice3-0.5B-2512) -**CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/spaces/FunAudioLLM/CosyVoice2-0.5B) +**CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/FunAudioLLM/CosyVoice2-0.5B) **CosyVoice 1.0**: [Demos](https://fun-audio-llm.github.io); [Paper](https://funaudiollm.github.io/pdf/CosyVoice_v1.pdf); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice-300M) From 0b80c0746acef91b5673bac9072980a2e1ab9ba8 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 15 Dec 2025 16:13:53 +0800 Subject: [PATCH 39/61] update --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d475567..a8af859 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ We strongly recommend that you download our pretrained `Fun-CosyVoice3-0.5B` `CosyVoice2-0.5B` `CosyVoice-300M` `CosyVoice-300M-SFT` `CosyVoice-300M-Instruct` model and `CosyVoice-ttsfrd` resource. ``` python -# SDK模型下载 +# modelscope SDK model download from modelscope import snapshot_download snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B-2512', local_dir='pretrained_models/Fun-CosyVoice3-0.5B') snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B') @@ -121,6 +121,15 @@ snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-3 snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT') snapshot_download('iic/CosyVoice-300M-Instruct', local_dir='pretrained_models/CosyVoice-300M-Instruct') snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd') + +# for oversea users, huggingface SDK model download +from huggingface_hub import snapshot_download +snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B-2512', local_dir='pretrained_models/Fun-CosyVoice3-0.5B') +snapshot_download('FunAudioLLM/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B') +snapshot_download('FunAudioLLM/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M') +snapshot_download('FunAudioLLM/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT') +snapshot_download('FunAudioLLM/CosyVoice-300M-Instruct', local_dir='pretrained_models/CosyVoice-300M-Instruct') +snapshot_download('FunAudioLLM/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd') ``` Optionally, you can unzip `ttsfrd` resource and install `ttsfrd` package for better text normalization performance. From 2abd42220edd9a719a532500cb9c5b5a088c4551 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 16 Dec 2025 14:45:02 +0800 Subject: [PATCH 40/61] add x-transformer version --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index f776cbf..d0eb5af 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,6 +35,7 @@ tensorrt-cu12-libs==10.13.3.9; sys_platform == 'linux' torch==2.3.1 torchaudio==2.3.1 transformers==4.51.3 +x-transformers==2.11.24 uvicorn==0.30.0 wetext==0.0.4 wget==3.2 From 8b54619760fcb78abf5e4637a88e19c1b9ab53c9 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 16 Dec 2025 15:00:03 +0800 Subject: [PATCH 41/61] update --- README.md | 2 +- requirements.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ad5ff60..aafaeae 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ Notice that `vllm==v0.9.0` has a lot of specific requirements, for example `torc ``` sh conda create -n cosyvoice_vllm --clone cosyvoice conda activate cosyvoice_vllm -pip install vllm==v0.9.0 transformers==4.51.3 -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com +pip install vllm==v0.9.0 transformers==4.51.3 numpy==1.26.4 -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com python vllm_example.py ``` diff --git a/requirements.txt b/requirements.txt index d0eb5af..149bc43 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,7 @@ lightning==2.2.4 matplotlib==3.7.5 modelscope==1.20.0 networkx==3.1 +numpy==1.26.4 omegaconf==2.3.0 onnx==1.16.0 onnxruntime-gpu==1.18.0; sys_platform == 'linux' From f5816b4e510d9807b3c116c11c60377ae1014081 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 17 Dec 2025 03:16:00 +0000 Subject: [PATCH 42/61] update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aafaeae..a1d3d5e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -[![SVG Banners](https://svg-banners.vercel.app/api?type=origin&text1=CosyVoice🤠&text2=Text-to-Speech%20💖%20Large%20Language%20Model&width=800&height=210)](https://github.com/Akshay090/svg-banners) +![SVG Banners](https://svg-banners.vercel.app/api?type=origin&text1=CosyVoice🤠&text2=Text-to-Speech%20💖%20Large%20Language%20Model&width=800&height=210) ## 👉🏻 CosyVoice 👈🏻 -**Fun-CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/abs/2505.17589); [Modelscope](https://www.modelscope.cn/studios/FunAudioLLM/Fun-CosyVoice3-0.5B); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval); [Huggingface](https://huggingface.co/FunAudioLLM/Fun-CosyVoice3-0.5B-2512) +**Fun-CosyVoice 3.0**: [Demos](https://funaudiollm.github.io/cosyvoice3/); [Paper](https://arxiv.org/pdf/2505.17589); [Modelscope](https://www.modelscope.cn/models/FunAudioLLM/Fun-CosyVoice3-0.5B-2512); [Huggingface](https://huggingface.co/FunAudioLLM/Fun-CosyVoice3-0.5B-2512); [CV3-Eval](https://github.com/FunAudioLLM/CV3-Eval) -**CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/abs/2412.10117); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/FunAudioLLM/CosyVoice2-0.5B) +**CosyVoice 2.0**: [Demos](https://funaudiollm.github.io/cosyvoice2/); [Paper](https://arxiv.org/pdf/2412.10117); [Modelscope](https://www.modelscope.cn/models/iic/CosyVoice2-0.5B); [HuggingFace](https://huggingface.co/FunAudioLLM/CosyVoice2-0.5B) -**CosyVoice 1.0**: [Demos](https://fun-audio-llm.github.io); [Paper](https://funaudiollm.github.io/pdf/CosyVoice_v1.pdf); [Modelscope](https://www.modelscope.cn/studios/iic/CosyVoice-300M) +**CosyVoice 1.0**: [Demos](https://fun-audio-llm.github.io); [Paper](https://funaudiollm.github.io/pdf/CosyVoice_v1.pdf); [Modelscope](https://www.modelscope.cn/models/iic/CosyVoice-300M); [HuggingFace](https://huggingface.co/FunAudioLLM/CosyVoice-300M) ## Highlight🔥 From ff0d05c380102f184998ca16d7b71241ef07ceba Mon Sep 17 00:00:00 2001 From: "di.wu" Date: Wed, 17 Dec 2025 14:56:21 +0800 Subject: [PATCH 43/61] Fix CosyVoice3 config error --- cosyvoice/llm/llm.py | 2 +- examples/libritts/cosyvoice3/conf/cosyvoice3.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index eacde5b..3d9ae01 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -698,7 +698,7 @@ class CosyVoice3LM(Qwen2LM): lm_output, lm_output_mask = self.llm(lm_input, lm_input_len.to(device)) logits = self.llm_decoder(lm_output) loss = self.criterion_ce(logits, lm_target.to(device)) - acc = th_accuracy(logits.view(-1, self.speech_token_size + 3), lm_target, ignore_label=IGNORE_ID) + acc = th_accuracy(logits.view(-1, self.speech_token_size + 200), lm_target, ignore_label=IGNORE_ID) return {'loss': loss, 'acc': acc} @torch.inference_mode() diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml index df36109..2ec5fcb 100644 --- a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml +++ b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml @@ -20,7 +20,7 @@ num_decoding_left_chunks: -1 # streaming inference flow decoder left chunk size, # model params # for all class/function included in this repo, we use ! or ! for intialization, so that user may find all corresponding class/function according to one single yaml. # for system/third_party class/function, we do not require this. -llm: !new:cosyvoice.llm.llm.Qwen2LM +llm: !new:cosyvoice.llm.llm.CosyVoice3LM llm_input_size: !ref llm_output_size: !ref speech_token_size: 6561 @@ -231,4 +231,4 @@ train_conf_gan: grad_clip: 5 accum_grad: 1 # in gan training, accum_grad must be 1 log_interval: 100 - save_per_step: -1 \ No newline at end of file + save_per_step: -1 From 7baefaf0f2444bbaba9cd88595b5596f71523bfc Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 17 Dec 2025 17:14:17 +0800 Subject: [PATCH 44/61] update libritts cosyvoice3.yaml --- .../libritts/cosyvoice3/conf/cosyvoice3.yaml | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml index df36109..43e457f 100644 --- a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml +++ b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml @@ -20,7 +20,7 @@ num_decoding_left_chunks: -1 # streaming inference flow decoder left chunk size, # model params # for all class/function included in this repo, we use ! or ! for intialization, so that user may find all corresponding class/function according to one single yaml. # for system/third_party class/function, we do not require this. -llm: !new:cosyvoice.llm.llm.Qwen2LM +llm: !new:cosyvoice.llm.llm.CosyVoice3LM llm_input_size: !ref llm_output_size: !ref speech_token_size: 6561 @@ -35,8 +35,8 @@ llm: !new:cosyvoice.llm.llm.Qwen2LM win_size: 10 tau_r: 0.1 -flow: !new:cosyvoice.flow.flow.CausalMaskedDiffWithXvec - input_size: 512 +flow: !new:cosyvoice.flow.flow.CausalMaskedDiffWithDiT + input_size: 80 output_size: 80 spk_embed_dim: !ref output_type: 'mel' @@ -45,22 +45,10 @@ flow: !new:cosyvoice.flow.flow.CausalMaskedDiffWithXvec only_mask_loss: True token_mel_ratio: !ref pre_lookahead_len: 3 - encoder: !new:cosyvoice.transformer.upsample_encoder.UpsampleConformerEncoder - output_size: 512 - attention_heads: 8 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.1 - normalize_before: True - input_layer: 'linear' - pos_enc_layer_type: 'rel_pos_espnet' - selfattention_layer_type: 'rel_selfattn' - input_size: 512 - use_cnn_module: False - macaron_style: False - static_chunk_size: !ref + pre_lookahead_layer: !new:cosyvoice.transformer.upsample_encoder.PreLookaheadLayer + in_channels: 80 + channels: 1024 + pre_lookahead_len: 3 decoder: !new:cosyvoice.flow.flow_matching.CausalConditionalCFM in_channels: 240 n_spks: 1 @@ -73,20 +61,20 @@ flow: !new:cosyvoice.flow.flow.CausalMaskedDiffWithXvec training_cfg_rate: 0.2 inference_cfg_rate: 0.7 reg_loss_type: 'l1' - estimator: !new:cosyvoice.flow.decoder.CausalConditionalDecoder - in_channels: 320 + estimator: !new:cosyvoice.flow.DiT.dit.DiT + dim: 1024 + depth: 22 + heads: 16 + dim_head: 64 + ff_mult: 2 + mel_dim: 80 + mu_dim: 80 + spk_dim: 80 out_channels: 80 - channels: [256] - dropout: 0.0 - attention_head_dim: 64 - n_blocks: 4 - num_mid_blocks: 12 - num_heads: 8 - act_fn: 'gelu' static_chunk_size: !ref * num_decoding_left_chunks: !ref -hift: !new:cosyvoice.hifigan.generator.HiFTGenerator +hift: !new:cosyvoice.hifigan.generator.CausalHiFTGenerator in_channels: 80 base_channels: 512 nb_harmonics: 8 @@ -105,7 +93,8 @@ hift: !new:cosyvoice.hifigan.generator.HiFTGenerator source_resblock_dilation_sizes: [[1, 3, 5], [1, 3, 5], [1, 3, 5]] lrelu_slope: 0.1 audio_limit: 0.99 - f0_predictor: !new:cosyvoice.hifigan.f0_predictor.ConvRNNF0Predictor + conv_pre_look_right: 4 + f0_predictor: !new:cosyvoice.hifigan.f0_predictor.CausalConvRNNF0Predictor num_class: 1 in_channels: 80 cond_channels: 512 From a7d6e2251adb64f7cef595c5c71c5763cb1d162b Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 17 Dec 2025 17:15:10 +0800 Subject: [PATCH 45/61] update libritts cosyvoice3.yaml --- examples/libritts/cosyvoice3/conf/cosyvoice3.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml index 43e457f..aaa42c7 100644 --- a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml +++ b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml @@ -123,6 +123,7 @@ parquet_opener: !name:cosyvoice.dataset.processor.parquet_opener get_tokenizer: !name:cosyvoice.tokenizer.tokenizer.get_qwen_tokenizer token_path: !ref skip_special_tokens: True + version: cosyvoice3 allowed_special: 'all' tokenize: !name:cosyvoice.dataset.processor.tokenize get_tokenizer: !ref From 9f27b42cd98ed1e46cd5472f6cd47853ab49de01 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Wed, 17 Dec 2025 18:58:50 +0800 Subject: [PATCH 46/61] update --- examples/libritts/cosyvoice3/conf/cosyvoice3.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml index aaa42c7..69d5c12 100644 --- a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml +++ b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml @@ -144,7 +144,7 @@ feat_extractor: !name:matcha.utils.audio.mel_spectrogram hop_size: 480 win_size: 1920 fmin: 0 - fmax: 8000 + fmax: null center: False compute_fbank: !name:cosyvoice.dataset.processor.compute_fbank feat_extractor: !ref @@ -221,4 +221,4 @@ train_conf_gan: grad_clip: 5 accum_grad: 1 # in gan training, accum_grad must be 1 log_interval: 100 - save_per_step: -1 \ No newline at end of file + save_per_step: -1 From 80bebb19783f2f08e8e71a3c03023759039c90f8 Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Mon, 22 Dec 2025 19:11:47 +0800 Subject: [PATCH 47/61] docs: fix Japanese language tag in example.py comment Changed <|jp|> to <|ja|> to match the actual tokenizer implementation. The LANGUAGES dict in cosyvoice/tokenizer/tokenizer.py defines 'ja' for Japanese, not 'jp'. This fixes the misleading comment that could cause issues like #621. Fixes #1683 --- example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.py b/example.py index 85952ae..48468e6 100644 --- a/example.py +++ b/example.py @@ -18,7 +18,7 @@ def cosyvoice_example(): # zero_shot usage for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', './asset/zero_shot_prompt.wav')): torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) - # cross_lingual usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean + # cross_lingual usage, <|zh|><|en|><|ja|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean for i, j in enumerate(cosyvoice.inference_cross_lingual('<|en|>And then later on, fully acquiring that company. So keeping management in line, interest in line with the asset that\'s coming into the family is a reason why sometimes we don\'t buy the whole thing.', './asset/cross_lingual_prompt.wav')): torchaudio.save('cross_lingual_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate) From 59cb2bf16ca9b14144ad68da645e82eb68539716 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 23 Dec 2025 14:06:40 +0800 Subject: [PATCH 48/61] fix jit_export --- cosyvoice/bin/export_jit.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cosyvoice/bin/export_jit.py b/cosyvoice/bin/export_jit.py index 0013d64..8dd6531 100644 --- a/cosyvoice/bin/export_jit.py +++ b/cosyvoice/bin/export_jit.py @@ -62,14 +62,6 @@ def main(): model = AutoModel(model_dir=args.model_dir) if get_model_type(model.model) == CosyVoiceModel: - # 1. export flow encoder - flow_encoder = model.model.flow.encoder - script = get_optimized_script(flow_encoder) - script.save('{}/flow.encoder.fp32.zip'.format(args.model_dir)) - script = get_optimized_script(flow_encoder.half()) - script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) - logging.info('successfully export flow_encoder') - elif get_model_type(model.model) == CosyVoice2Model: # 1. export llm text_encoder llm_text_encoder = model.model.llm.text_encoder script = get_optimized_script(llm_text_encoder) @@ -93,6 +85,14 @@ def main(): script = get_optimized_script(flow_encoder.half()) script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) logging.info('successfully export flow_encoder') + elif get_model_type(model.model) == CosyVoice2Model: + # 1. export flow encoder + flow_encoder = model.model.flow.encoder + script = get_optimized_script(flow_encoder) + script.save('{}/flow.encoder.fp32.zip'.format(args.model_dir)) + script = get_optimized_script(flow_encoder.half()) + script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) + logging.info('successfully export flow_encoder') else: raise ValueError('unsupported model type') From 823ae2c60d3a0d7e17d8288b0c33a1fc4a430096 Mon Sep 17 00:00:00 2001 From: yigitcatak Date: Tue, 23 Dec 2025 16:22:48 +0900 Subject: [PATCH 49/61] fix a typo in Dockerfile --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8cefdba..7d7b16e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ ARG VENV_NAME="cosyvoice" ENV VENV=$VENV_NAME ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 -ENV DEBIAN_FRONTEN=noninteractive +ENV DEBIAN_FRONTEND=noninteractive ENV PYTHONUNBUFFERED=1 SHELL ["/bin/bash", "--login", "-c"] From 7538c6a73d8f8f80672518112092279bb431a4d7 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 23 Dec 2025 15:23:29 +0800 Subject: [PATCH 50/61] update export_jit --- cosyvoice/bin/export_jit.py | 7 +++---- cosyvoice/cli/frontend.py | 41 +++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/cosyvoice/bin/export_jit.py b/cosyvoice/bin/export_jit.py index 8dd6531..5d6b9a8 100644 --- a/cosyvoice/bin/export_jit.py +++ b/cosyvoice/bin/export_jit.py @@ -24,9 +24,8 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../..'.format(ROOT_DIR)) sys.path.append('{}/../../third_party/Matcha-TTS'.format(ROOT_DIR)) from cosyvoice.cli.cosyvoice import AutoModel -from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model, CosyVoice3Model +from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model from cosyvoice.utils.file_utils import logging -from cosyvoice.utils.class_utils import get_model_type def get_args(): @@ -61,7 +60,7 @@ def main(): model = AutoModel(model_dir=args.model_dir) - if get_model_type(model.model) == CosyVoiceModel: + if isinstance(model.model, CosyVoiceModel): # 1. export llm text_encoder llm_text_encoder = model.model.llm.text_encoder script = get_optimized_script(llm_text_encoder) @@ -85,7 +84,7 @@ def main(): script = get_optimized_script(flow_encoder.half()) script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) logging.info('successfully export flow_encoder') - elif get_model_type(model.model) == CosyVoice2Model: + elif isinstance(model.model, CosyVoice2Model): # 1. export flow encoder flow_encoder = model.model.flow.encoder script = get_optimized_script(flow_encoder) diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index 0942da6..f0c75dd 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -20,18 +20,9 @@ import numpy as np import whisper from typing import Callable import torchaudio.compliance.kaldi as kaldi -import torchaudio import os import re import inflect -try: - import ttsfrd - use_ttsfrd = True -except ImportError: - print("failed to import ttsfrd, use wetext instead") - from wetext import Normalizer as ZhNormalizer - from wetext import Normalizer as EnNormalizer - use_ttsfrd = False from cosyvoice.utils.file_utils import logging, load_wav from cosyvoice.utils.frontend_utils import contains_chinese, replace_blank, replace_corner_mark, remove_bracket, spell_out_number, split_paragraph, is_only_punctuation @@ -60,17 +51,29 @@ class CosyVoiceFrontEnd: else: self.spk2info = {} self.allowed_special = allowed_special - self.use_ttsfrd = use_ttsfrd - if self.use_ttsfrd: + self.inflect_parser = inflect.engine() + # NOTE compatible when no text frontend tool is avaliable + try: + import ttsfrd self.frd = ttsfrd.TtsFrontendEngine() ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) assert self.frd.initialize('{}/../../pretrained_models/CosyVoice-ttsfrd/resource'.format(ROOT_DIR)) is True, \ 'failed to initialize ttsfrd resource' self.frd.set_lang_type('pinyinvg') - else: - self.zh_tn_model = ZhNormalizer(remove_erhua=False) - self.en_tn_model = EnNormalizer() - self.inflect_parser = inflect.engine() + self.text_frontend = 'ttsfrd' + logging.info('use ttsfrd frontend') + except: + try: + from wetext import Normalizer as ZhNormalizer + from wetext import Normalizer as EnNormalizer + self.zh_tn_model = ZhNormalizer(remove_erhua=False) + self.en_tn_model = EnNormalizer() + self.text_frontend = 'wetext' + logging.info('use wetext frontend') + except: + self.text_frontend = '' + logging.info('no frontend is avaliable') + def _extract_text_token(self, text): if isinstance(text, Generator): @@ -131,12 +134,13 @@ class CosyVoiceFrontEnd: if text_frontend is False or text == '': return [text] if split is True else text text = text.strip() - if self.use_ttsfrd: + if self.text_frontend == 'ttsfrd': texts = [i["text"] for i in json.loads(self.frd.do_voicegen_frd(text))["sentences"]] text = ''.join(texts) else: if contains_chinese(text): - text = self.zh_tn_model.normalize(text) + if self.text_frontend == 'wetext': + text = self.zh_tn_model.normalize(text) text = text.replace("\n", "") text = replace_blank(text) text = replace_corner_mark(text) @@ -147,7 +151,8 @@ class CosyVoiceFrontEnd: texts = list(split_paragraph(text, partial(self.tokenizer.encode, allowed_special=self.allowed_special), "zh", token_max_n=80, token_min_n=60, merge_len=20, comma_split=False)) else: - text = self.en_tn_model.normalize(text) + if self.text_frontend == 'wetext': + text = self.en_tn_model.normalize(text) text = spell_out_number(text, self.inflect_parser) texts = list(split_paragraph(text, partial(self.tokenizer.encode, allowed_special=self.allowed_special), "en", token_max_n=80, token_min_n=60, merge_len=20, comma_split=False)) From 2db78e705835e56778f69b80cae51e4314d635b0 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 23 Dec 2025 17:23:23 +0800 Subject: [PATCH 51/61] fix export_jit.py --- cosyvoice/bin/export_jit.py | 5 ++--- cosyvoice/cli/cosyvoice.py | 2 +- cosyvoice/cli/model.py | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cosyvoice/bin/export_jit.py b/cosyvoice/bin/export_jit.py index 5d6b9a8..3ecfd05 100644 --- a/cosyvoice/bin/export_jit.py +++ b/cosyvoice/bin/export_jit.py @@ -24,7 +24,6 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../..'.format(ROOT_DIR)) sys.path.append('{}/../../third_party/Matcha-TTS'.format(ROOT_DIR)) from cosyvoice.cli.cosyvoice import AutoModel -from cosyvoice.cli.model import CosyVoiceModel, CosyVoice2Model from cosyvoice.utils.file_utils import logging @@ -60,7 +59,7 @@ def main(): model = AutoModel(model_dir=args.model_dir) - if isinstance(model.model, CosyVoiceModel): + if model.__class__.__name__ == 'CosyVoice': # 1. export llm text_encoder llm_text_encoder = model.model.llm.text_encoder script = get_optimized_script(llm_text_encoder) @@ -84,7 +83,7 @@ def main(): script = get_optimized_script(flow_encoder.half()) script.save('{}/flow.encoder.fp16.zip'.format(args.model_dir)) logging.info('successfully export flow_encoder') - elif isinstance(model.model, CosyVoice2Model): + elif model.__class__.__name__ == 'CosyVoice2': # 1. export flow encoder flow_encoder = model.model.flow.encoder script = get_optimized_script(flow_encoder) diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 316b5f1..7ab04a7 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -114,7 +114,7 @@ class CosyVoice: start_time = time.time() def inference_instruct(self, tts_text, spk_id, instruct_text, stream=False, speed=1.0, text_frontend=True): - assert isinstance(self.model, CosyVoiceModel), 'inference_instruct is only implemented for CosyVoice!' + assert self.__class__.__name__ == 'CosyVoice', 'inference_instruct is only implemented for CosyVoice!' instruct_text = self.frontend.text_normalize(instruct_text, split=False, text_frontend=text_frontend) for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): model_input = self.frontend.frontend_instruct(i, spk_id, instruct_text) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 8e67b0c..6bc3b31 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -100,7 +100,7 @@ class CosyVoiceModel: def llm_job(self, text, prompt_text, llm_prompt_speech_token, llm_embedding, uuid): with self.llm_context, torch.cuda.amp.autocast(self.fp16 is True and hasattr(self.llm, 'vllm') is False): if isinstance(text, Generator): - assert isinstance(self, CosyVoice2Model) and not hasattr(self.llm, 'vllm'), 'streaming input text is only implemented for CosyVoice2 and do not support vllm!' + assert (self.__class__.__name__ != 'CosyVoiceModel') and not hasattr(self.llm, 'vllm'), 'streaming input text is only implemented for CosyVoice2/3 and do not support vllm!' for i in self.llm.inference_bistream(text=text, prompt_text=prompt_text.to(self.device), prompt_text_len=torch.tensor([prompt_text.shape[1]], dtype=torch.int32).to(self.device), From 8524c81acd9507139d526ed8a859122b005c57cc Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Fri, 26 Dec 2025 10:16:58 +0000 Subject: [PATCH 52/61] fix cv3 train --- examples/libritts/cosyvoice/local/prepare_data.py | 9 +++------ examples/libritts/cosyvoice3/run.sh | 5 +++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/libritts/cosyvoice/local/prepare_data.py b/examples/libritts/cosyvoice/local/prepare_data.py index fffa9fb..ded523d 100644 --- a/examples/libritts/cosyvoice/local/prepare_data.py +++ b/examples/libritts/cosyvoice/local/prepare_data.py @@ -40,11 +40,10 @@ def main(): with open('{}/spk2utt'.format(args.des_dir), 'w') as f: for k, v in spk2utt.items(): f.write('{} {}\n'.format(k, ' '.join(v))) - if args.instruct is True: + if args.instruct != '': with open('{}/instruct'.format(args.des_dir), 'w') as f: for k, v in utt2text.items(): - # NOTE in CosyVoice3, we add instruct in sequence - f.write('{} You are a helpful assistant.<|endofprompt|>\n'.format(k, v)) + f.write('{} {}\n'.format(k, args.instruct)) return @@ -55,8 +54,6 @@ if __name__ == "__main__": parser.add_argument('--des_dir', type=str) parser.add_argument('--instruct', - action='store_true', - default=False, - help='create instruct file or not') + type=str) args = parser.parse_args() main() diff --git a/examples/libritts/cosyvoice3/run.sh b/examples/libritts/cosyvoice3/run.sh index 4e6ce11..6b86227 100644 --- a/examples/libritts/cosyvoice3/run.sh +++ b/examples/libritts/cosyvoice3/run.sh @@ -7,7 +7,7 @@ stop_stage=3 data_url=www.openslr.org/resources/60 data_dir=/mnt/lyuxiang.lx/data/tts/openslr/libritts -pretrained_model_dir=../../../pretrained_models/CosyVoice3-0.5B +pretrained_model_dir=../../../pretrained_models/Fun-CosyVoice3-0.5B if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then echo "Data Download" @@ -20,7 +20,8 @@ if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then echo "Data preparation, prepare wav.scp/text/utt2spk/spk2utt" for x in train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other; do mkdir -p data/$x - python local/prepare_data.py --src_dir $data_dir/LibriTTS/$x --des_dir data/$x --instruct + # NOTE in CosyVoice3, we add instruct in sequence + python local/prepare_data.py --src_dir $data_dir/LibriTTS/$x --des_dir data/$x --instruct "You are a helpful assistant.<|endofprompt|>" done fi From 4d7295a9a7076b7b656f63c35f4dad199f3af33e Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 29 Dec 2025 10:02:59 +0000 Subject: [PATCH 53/61] fix cosyvoice3 training --- cosyvoice/dataset/processor.py | 10 +++------- cosyvoice/flow/flow.py | 6 +++--- cosyvoice/llm/llm.py | 20 ++++++++++++------- cosyvoice/utils/train_utils.py | 10 +++++----- .../libritts/cosyvoice3/conf/cosyvoice3.yaml | 2 +- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/cosyvoice/dataset/processor.py b/cosyvoice/dataset/processor.py index f186ed2..78e84f8 100644 --- a/cosyvoice/dataset/processor.py +++ b/cosyvoice/dataset/processor.py @@ -26,7 +26,7 @@ import pyworld as pw AUDIO_FORMAT_SETS = {'flac', 'mp3', 'm4a', 'ogg', 'opus', 'wav', 'wma'} -def parquet_opener(data, mode='train', tts_data={}): +def parquet_opener(data, mode='train'): """ Give url or local file, return file descriptor Inplace operation. @@ -44,12 +44,8 @@ def parquet_opener(data, mode='train', tts_data={}): df = df.to_pandas() for i in range(len(df)): sample.update(dict(df.loc[i])) - if mode == 'train': - # NOTE do not return sample directly, must initialize a new dict - yield {**sample} - else: - for index, text in enumerate(tts_data[df.loc[i, 'utt']]): - yield {**sample, 'tts_index': index, 'tts_text': text} + # NOTE do not return sample directly, must initialize a new dict + yield {**sample} except Exception as ex: logging.warning('Failed to open {}, ex info {}'.format(url, ex)) diff --git a/cosyvoice/flow/flow.py b/cosyvoice/flow/flow.py index d07c181..63651e0 100644 --- a/cosyvoice/flow/flow.py +++ b/cosyvoice/flow/flow.py @@ -332,8 +332,9 @@ class CausalMaskedDiffWithDiT(torch.nn.Module): token = self.input_embedding(torch.clamp(token, min=0)) * mask # text encode - h, h_lengths = self.encoder(token, token_len, streaming=streaming) - h = self.encoder_proj(h) + h = self.pre_lookahead_layer(token) + h = h.repeat_interleave(self.token_mel_ratio, dim=1) + mask = mask.repeat_interleave(self.token_mel_ratio, dim=1).squeeze(dim=-1) # get conditions conds = torch.zeros(feat.shape, device=token.device) @@ -344,7 +345,6 @@ class CausalMaskedDiffWithDiT(torch.nn.Module): conds[i, :index] = feat[i, :index] conds = conds.transpose(1, 2) - mask = (~make_pad_mask(h_lengths.sum(dim=-1).squeeze(dim=1))).to(h) loss, _ = self.decoder.compute_loss( feat.transpose(1, 2).contiguous(), mask.unsqueeze(1), diff --git a/cosyvoice/llm/llm.py b/cosyvoice/llm/llm.py index 3d9ae01..6ac5e50 100644 --- a/cosyvoice/llm/llm.py +++ b/cosyvoice/llm/llm.py @@ -301,18 +301,23 @@ class Qwen2LM(TransformerLM): self.stop_token_ids = [speech_token_size + i for i in range(3)] self.vllm_output_queue = {} - def prepare_lm_input_target(self, sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len): + def prepare_lm_input_target(self, sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, speech_token, speech_token_emb, speech_token_len, instruct_token=None, instruct_token_emb=None, instruct_token_len=None): lm_target, lm_input = [], [] text_token = unpad_sequence(text_token, text_token_len.cpu(), batch_first=True) speech_token = unpad_sequence(speech_token, speech_token_len.cpu(), batch_first=True) text_token_emb = unpad_sequence(text_token_emb, text_token_len.cpu(), batch_first=True) speech_token_emb = unpad_sequence(speech_token_emb, speech_token_len.cpu(), batch_first=True) + # NOTE add instruct_token in CosyVoice3 + if instruct_token is not None and instruct_token_emb is not None and instruct_token_len is not None: + instruct_token = unpad_sequence(instruct_token, instruct_token_len.cpu(), batch_first=True) + instruct_token_emb = unpad_sequence(instruct_token_emb, instruct_token_len.cpu(), batch_first=True) for i in range(len(text_token)): # bistream sequence if random.random() < 0.5 and speech_token_len[i] / text_token_len[i] > self.mix_ratio[1] / self.mix_ratio[0]: - this_lm_target, this_lm_input = [], [] - this_lm_target.append(IGNORE_ID) - this_lm_input.append(sos_emb.squeeze(dim=0)) + this_lm_target, this_lm_input = [IGNORE_ID], [sos_emb.squeeze(dim=0)] + if instruct_token is not None and instruct_token_emb is not None and instruct_token_len is not None: + this_lm_target += [IGNORE_ID] * instruct_token_len[i] + this_lm_input.append(instruct_token_emb[i]) for j in range(((text_token_len[i] + 1) / self.mix_ratio[0]).ceil().int().item()): this_text_token = text_token[i][j * self.mix_ratio[0]: (j + 1) * self.mix_ratio[0]].tolist() this_speech_token = speech_token[i][j * self.mix_ratio[1]: (j + 1) * self.mix_ratio[1]].tolist() @@ -333,8 +338,8 @@ class Qwen2LM(TransformerLM): this_lm_target, this_lm_input = torch.tensor(this_lm_target), torch.concat(this_lm_input, dim=0) # unistream sequence else: - this_lm_target = torch.tensor([IGNORE_ID] * (1 + text_token_len[i]) + speech_token[i].tolist() + [self.eos_token]) - this_lm_input = torch.concat([sos_emb.squeeze(dim=0), text_token_emb[i], task_id_emb.squeeze(dim=0), speech_token_emb[i]], dim=0) + this_lm_target = torch.tensor([IGNORE_ID] * (1 + instruct_token_len[i] + text_token_len[i]) + speech_token[i].tolist() + [self.eos_token]) + this_lm_input = torch.concat([sos_emb.squeeze(dim=0), instruct_token_emb[i], text_token_emb[i], task_id_emb.squeeze(dim=0), speech_token_emb[i]], dim=0) lm_target.append(this_lm_target) lm_input.append(this_lm_input) lm_input_len = torch.tensor([i.size(0) for i in lm_input], dtype=torch.int32) @@ -681,6 +686,7 @@ class CosyVoice3LM(Qwen2LM): # 1. encode text_token text_token_emb = self.llm.model.model.embed_tokens(text_token) + instruct_token_emb = self.llm.model.model.embed_tokens(instruct_token) # 3. sos and task_id sos_emb = self.speech_embedding.weight[self.sos].reshape(1, 1, -1) @@ -691,7 +697,7 @@ class CosyVoice3LM(Qwen2LM): # 3. prepare llm_input/target lm_target, lm_input, lm_input_len = self.prepare_lm_input_target(sos_emb, text_token, text_token_emb, text_token_len, task_id_emb, - speech_token, speech_token_emb, speech_token_len) + speech_token, speech_token_emb, speech_token_len, instruct_token, instruct_token_emb, instruct_token_len) lm_target = lm_target.to(device) # 4. run lm forward diff --git a/cosyvoice/utils/train_utils.py b/cosyvoice/utils/train_utils.py index e2d2b09..2ab5ebe 100644 --- a/cosyvoice/utils/train_utils.py +++ b/cosyvoice/utils/train_utils.py @@ -53,7 +53,7 @@ def init_distributed(args): def init_dataset_and_dataloader(args, configs, gan, dpo): data_pipeline = configs['data_pipeline_gan'] if gan is True else configs['data_pipeline'] train_dataset = Dataset(args.train_data, data_pipeline=data_pipeline, mode='train', gan=gan, dpo=dpo, shuffle=True, partition=True) - cv_dataset = Dataset(args.cv_data, data_pipeline=data_pipeline, mode='train', gan=gan, dpo=dpo, shuffle=False, partition=False) + cv_dataset = Dataset(args.cv_data, data_pipeline=data_pipeline, mode='dev', gan=gan, dpo=dpo, shuffle=False, partition=False) # do not use persistent_workers=True, as whisper tokenizer opens tiktoken file each time when the for loop starts train_data_loader = DataLoader(train_dataset, @@ -164,18 +164,18 @@ def init_optimizer_and_scheduler(args, configs, model, gan): raise ValueError("unknown scheduler: " + configs['train_conf']) if configs['train_conf']['optim_d'] == 'adam': - optimizer_d = optim.Adam(model.module.discriminator.parameters(), **configs['train_conf']['optim_conf']) + optimizer_d = optim.Adam(model.module.discriminator.parameters(), **configs['train_conf']['optim_conf_d']) elif configs['train_conf']['optim_d'] == 'adamw': - optimizer_d = optim.AdamW(model.module.discriminator.parameters(), **configs['train_conf']['optim_conf']) + optimizer_d = optim.AdamW(model.module.discriminator.parameters(), **configs['train_conf']['optim_conf_d']) else: raise ValueError("unknown optimizer: " + configs['train_conf']) if configs['train_conf']['scheduler_d'] == 'warmuplr': scheduler_type = WarmupLR - scheduler_d = WarmupLR(optimizer_d, **configs['train_conf']['scheduler_conf']) + scheduler_d = WarmupLR(optimizer_d, **configs['train_conf']['scheduler_d']) elif configs['train_conf']['scheduler_d'] == 'NoamHoldAnnealing': scheduler_type = NoamHoldAnnealing - scheduler_d = NoamHoldAnnealing(optimizer_d, **configs['train_conf']['scheduler_conf']) + scheduler_d = NoamHoldAnnealing(optimizer_d, **configs['train_conf']['scheduler_d']) elif configs['train_conf']['scheduler'] == 'constantlr': scheduler_type = ConstantLR scheduler_d = ConstantLR(optimizer_d) diff --git a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml index 69d5c12..16ab187 100644 --- a/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml +++ b/examples/libritts/cosyvoice3/conf/cosyvoice3.yaml @@ -136,7 +136,7 @@ filter: !name:cosyvoice.dataset.processor.filter resample: !name:cosyvoice.dataset.processor.resample resample_rate: !ref truncate: !name:cosyvoice.dataset.processor.truncate - truncate_length: 24480 # must be a multiplier of hop_size + truncate_length: 24960 # must be a multiplier of hop_size and token_mel_ratio feat_extractor: !name:matcha.utils.audio.mel_spectrogram n_fft: 1920 num_mels: 80 From 3b449137823f0ece887db42e583476e35a8dabdd Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 29 Dec 2025 10:30:54 +0000 Subject: [PATCH 54/61] fix bug --- cosyvoice/cli/cosyvoice.py | 2 ++ cosyvoice/cli/frontend.py | 2 +- runtime/python/fastapi/server.py | 12 +++--------- runtime/python/grpc/server.py | 12 +++--------- webui.py | 2 +- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/cosyvoice/cli/cosyvoice.py b/cosyvoice/cli/cosyvoice.py index 7ab04a7..e91bf09 100644 --- a/cosyvoice/cli/cosyvoice.py +++ b/cosyvoice/cli/cosyvoice.py @@ -89,6 +89,8 @@ class CosyVoice: start_time = time.time() def inference_zero_shot(self, tts_text, prompt_text, prompt_wav, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True): + if self.__class__.__name__ == 'CosyVoice3' and '<|endofprompt|>' not in prompt_text + tts_text: + logging.warning('<|endofprompt|> not found in CosyVoice3 inference, check your input text') prompt_text = self.frontend.text_normalize(prompt_text, split=False, text_frontend=text_frontend) for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)): if (not isinstance(i, Generator)) and len(i) < 0.5 * len(prompt_text): diff --git a/cosyvoice/cli/frontend.py b/cosyvoice/cli/frontend.py index f0c75dd..7ad6f7c 100644 --- a/cosyvoice/cli/frontend.py +++ b/cosyvoice/cli/frontend.py @@ -183,7 +183,7 @@ class CosyVoiceFrontEnd: 'prompt_speech_feat': speech_feat, 'prompt_speech_feat_len': speech_feat_len, 'llm_embedding': embedding, 'flow_embedding': embedding} else: - model_input = self.spk2info[zero_shot_spk_id] + model_input = {**self.spk2info[zero_shot_spk_id]} model_input['text'] = tts_text_token model_input['text_len'] = tts_text_token_len return model_input diff --git a/runtime/python/fastapi/server.py b/runtime/python/fastapi/server.py index 74c62d8..1502f9c 100644 --- a/runtime/python/fastapi/server.py +++ b/runtime/python/fastapi/server.py @@ -24,7 +24,7 @@ import numpy as np ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../../..'.format(ROOT_DIR)) sys.path.append('{}/../../../third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 +from cosyvoice.cli.cosyvoice import AutoModel from cosyvoice.utils.file_utils import load_wav app = FastAPI() @@ -88,14 +88,8 @@ if __name__ == '__main__': default=50000) parser.add_argument('--model_dir', type=str, - default='iic/CosyVoice-300M', + default='iic/CosyVoice2-0.5B', help='local path or modelscope repo id') args = parser.parse_args() - try: - cosyvoice = CosyVoice(args.model_dir) - except Exception: - try: - cosyvoice = CosyVoice2(args.model_dir) - except Exception: - raise TypeError('no valid model_type!') + cosyvoice = AutoModel(model_dir=args.model_dir) uvicorn.run(app, host="0.0.0.0", port=args.port) diff --git a/runtime/python/grpc/server.py b/runtime/python/grpc/server.py index 76827e6..28ecc19 100644 --- a/runtime/python/grpc/server.py +++ b/runtime/python/grpc/server.py @@ -25,7 +25,7 @@ import numpy as np ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append('{}/../../..'.format(ROOT_DIR)) sys.path.append('{}/../../../third_party/Matcha-TTS'.format(ROOT_DIR)) -from cosyvoice.cli.cosyvoice import CosyVoice, CosyVoice2 +from cosyvoice.cli.cosyvoice import AutoModel logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s') @@ -33,13 +33,7 @@ logging.basicConfig(level=logging.DEBUG, class CosyVoiceServiceImpl(cosyvoice_pb2_grpc.CosyVoiceServicer): def __init__(self, args): - try: - self.cosyvoice = CosyVoice(args.model_dir, trt_concurrent=args.max_conc) - except Exception: - try: - self.cosyvoice = CosyVoice2(args.model_dir, trt_concurrent=args.max_conc) - except Exception: - raise TypeError('no valid model_type!') + self.cosyvoice = AutoModel(model_dir=args.model_dir) logging.info('grpc service initialized') def Inference(self, request, context): @@ -90,7 +84,7 @@ if __name__ == '__main__': default=4) parser.add_argument('--model_dir', type=str, - default='iic/CosyVoice-300M', + default='iic/CosyVoice2-0.5B', help='local path or modelscope repo id') args = parser.parse_args() main() diff --git a/webui.py b/webui.py index debf5d3..e9b3ec5 100644 --- a/webui.py +++ b/webui.py @@ -167,7 +167,7 @@ if __name__ == '__main__': default=8000) parser.add_argument('--model_dir', type=str, - default='pretrained_models/CosyVoice3-0.5B', + default='pretrained_models/CosyVoice2-0.5B', help='local path or modelscope repo id') args = parser.parse_args() cosyvoice = AutoModel(model_dir=args.model_dir) From 4c19646b9af318968edf1941fc8e047d11b9a6e1 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Mon, 29 Dec 2025 12:46:34 +0000 Subject: [PATCH 55/61] update dataset --- cosyvoice/dataset/dataset.py | 6 +++++- examples/libritts/cosyvoice2/run.sh | 1 - examples/libritts/cosyvoice3/run.sh | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cosyvoice/dataset/dataset.py b/cosyvoice/dataset/dataset.py index 6b54184..6cb400e 100644 --- a/cosyvoice/dataset/dataset.py +++ b/cosyvoice/dataset/dataset.py @@ -145,7 +145,11 @@ def Dataset(data_list_file, shuffle=shuffle, partition=partition) # map partial arg to padding func - data_pipeline[-1] = partial(data_pipeline[-1], gan=gan, dpo=dpo) + for i in range(1, len(data_pipeline)): + if data_pipeline[i].func.__name__ == 'compute_fbank': + data_pipeline[i] = partial(data_pipeline[i], token_mel_ratio=0) + if data_pipeline[i].func.__name__ == 'padding': + data_pipeline[i] = partial(data_pipeline[i], gan=gan, dpo=dpo) for func in data_pipeline: dataset = Processor(dataset, func, mode=mode) return dataset diff --git a/examples/libritts/cosyvoice2/run.sh b/examples/libritts/cosyvoice2/run.sh index ad59c0a..538c71a 100644 --- a/examples/libritts/cosyvoice2/run.sh +++ b/examples/libritts/cosyvoice2/run.sh @@ -66,7 +66,6 @@ if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then fi cat data/{train-clean-100,train-clean-360,train-other-500}/parquet/data.list > data/train.data.list cat data/{dev-clean,dev-other}/parquet/data.list > data/dev.data.list - # NOTE will update llm/hift training later for model in llm flow hifigan; do torchrun --nnodes=1 --nproc_per_node=$num_gpus \ --rdzv_id=$job_id --rdzv_backend="c10d" --rdzv_endpoint="localhost:1234" \ diff --git a/examples/libritts/cosyvoice3/run.sh b/examples/libritts/cosyvoice3/run.sh index 6b86227..3eed628 100644 --- a/examples/libritts/cosyvoice3/run.sh +++ b/examples/libritts/cosyvoice3/run.sh @@ -68,7 +68,6 @@ if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then fi cat data/{train-clean-100,train-clean-360,train-other-500}/parquet/data.list > data/train.data.list cat data/{dev-clean,dev-other}/parquet/data.list > data/dev.data.list - # NOTE will update llm/hift training later for model in llm flow hifigan; do torchrun --nnodes=1 --nproc_per_node=$num_gpus \ --rdzv_id=$job_id --rdzv_backend="c10d" --rdzv_endpoint="localhost:1234" \ From 2d7ef0b71928e5c4e042dfe26731a84c03779c9f Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 12:36:18 +0800 Subject: [PATCH 56/61] remove instruct warning --- webui.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/webui.py b/webui.py index e9b3ec5..24b7951 100644 --- a/webui.py +++ b/webui.py @@ -57,9 +57,6 @@ def generate_audio(tts_text, mode_checkbox_group, sft_dropdown, prompt_text, pro prompt_wav = None # if instruct mode, please make sure that model is iic/CosyVoice-300M-Instruct and not cross_lingual mode if mode_checkbox_group in ['自然语言控制']: - if cosyvoice.instruct is False: - gr.Warning('您正在使用自然语言控制模式, {}模型不支持此模式, 请使用iic/CosyVoice-300M-Instruct模型'.format(args.model_dir)) - yield (cosyvoice.sample_rate, default_data) if instruct_text == '': gr.Warning('您正在使用自然语言控制模式, 请输入instruct文本') yield (cosyvoice.sample_rate, default_data) @@ -67,9 +64,6 @@ def generate_audio(tts_text, mode_checkbox_group, sft_dropdown, prompt_text, pro gr.Info('您正在使用自然语言控制模式, prompt音频/prompt文本会被忽略') # if cross_lingual mode, please make sure that model is iic/CosyVoice-300M and tts_text prompt_text are different language if mode_checkbox_group in ['跨语种复刻']: - if cosyvoice.instruct is True: - gr.Warning('您正在使用跨语种复刻模式, {}模型不支持此模式, 请使用iic/CosyVoice-300M模型'.format(args.model_dir)) - yield (cosyvoice.sample_rate, default_data) if instruct_text != '': gr.Info('您正在使用跨语种复刻模式, instruct文本会被忽略') if prompt_wav is None: From cfa1c115b2aa86ab0c3b8719d092be41e6332e74 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 09:18:17 +0000 Subject: [PATCH 57/61] add silent_token --- cosyvoice/cli/model.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 6bc3b31..694104b 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -60,6 +60,7 @@ class CosyVoiceModel: self.mel_overlap_dict = {} self.flow_cache_dict = {} self.hift_cache_dict = {} + self.silent_tokens = [] def load(self, llm_model, flow_model, hift_model): self.llm.load_state_dict(torch.load(llm_model, map_location=self.device), strict=True) @@ -98,6 +99,7 @@ class CosyVoiceModel: return {'min_shape': min_shape, 'opt_shape': opt_shape, 'max_shape': max_shape, 'input_names': input_names} def llm_job(self, text, prompt_text, llm_prompt_speech_token, llm_embedding, uuid): + cur_silent_token_num, max_silent_token_num = 0, 5 with self.llm_context, torch.cuda.amp.autocast(self.fp16 is True and hasattr(self.llm, 'vllm') is False): if isinstance(text, Generator): assert (self.__class__.__name__ != 'CosyVoiceModel') and not hasattr(self.llm, 'vllm'), 'streaming input text is only implemented for CosyVoice2/3 and do not support vllm!' @@ -107,6 +109,12 @@ class CosyVoiceModel: prompt_speech_token=llm_prompt_speech_token.to(self.device), prompt_speech_token_len=torch.tensor([llm_prompt_speech_token.shape[1]], dtype=torch.int32).to(self.device), embedding=llm_embedding.to(self.device)): + if i in self.silent_tokens: + cur_silent_token_num += 1 + if cur_silent_token_num > max_silent_token_num: + continue + else: + cur_silent_token_num = 0 self.tts_speech_token_dict[uuid].append(i) else: for i in self.llm.inference(text=text.to(self.device), @@ -117,6 +125,12 @@ class CosyVoiceModel: prompt_speech_token_len=torch.tensor([llm_prompt_speech_token.shape[1]], dtype=torch.int32).to(self.device), embedding=llm_embedding.to(self.device), uuid=uuid): + if i in self.silent_tokens: + cur_silent_token_num += 1 + if cur_silent_token_num > max_silent_token_num: + continue + else: + cur_silent_token_num = 0 self.tts_speech_token_dict[uuid].append(i) self.llm_end_dict[uuid] = True @@ -260,6 +274,7 @@ class CosyVoice2Model(CosyVoiceModel): self.tts_speech_token_dict = {} self.llm_end_dict = {} self.hift_cache_dict = {} + self.silent_tokens = [] def load_jit(self, flow_encoder_model): flow_encoder = torch.jit.load(flow_encoder_model, map_location=self.device) @@ -401,6 +416,8 @@ class CosyVoice3Model(CosyVoice2Model): self.tts_speech_token_dict = {} self.llm_end_dict = {} self.hift_cache_dict = {} + # FSQ silent token + self.silent_tokens = [28, 29] def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): From e15222b17cb0c48c810a0b014405c1a42f3a080c Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 09:24:52 +0000 Subject: [PATCH 58/61] refine code --- cosyvoice/cli/model.py | 44 ++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 694104b..b589bcd 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -103,35 +103,29 @@ class CosyVoiceModel: with self.llm_context, torch.cuda.amp.autocast(self.fp16 is True and hasattr(self.llm, 'vllm') is False): if isinstance(text, Generator): assert (self.__class__.__name__ != 'CosyVoiceModel') and not hasattr(self.llm, 'vllm'), 'streaming input text is only implemented for CosyVoice2/3 and do not support vllm!' - for i in self.llm.inference_bistream(text=text, + token_generator = self.llm.inference_bistream(text=text, + prompt_text=prompt_text.to(self.device), + prompt_text_len=torch.tensor([prompt_text.shape[1]], dtype=torch.int32).to(self.device), + prompt_speech_token=llm_prompt_speech_token.to(self.device), + prompt_speech_token_len=torch.tensor([llm_prompt_speech_token.shape[1]], dtype=torch.int32).to(self.device), + embedding=llm_embedding.to(self.device)) + else: + token_generator = self.llm.inference(text=text.to(self.device), + text_len=torch.tensor([text.shape[1]], dtype=torch.int32).to(self.device), prompt_text=prompt_text.to(self.device), prompt_text_len=torch.tensor([prompt_text.shape[1]], dtype=torch.int32).to(self.device), prompt_speech_token=llm_prompt_speech_token.to(self.device), prompt_speech_token_len=torch.tensor([llm_prompt_speech_token.shape[1]], dtype=torch.int32).to(self.device), - embedding=llm_embedding.to(self.device)): - if i in self.silent_tokens: - cur_silent_token_num += 1 - if cur_silent_token_num > max_silent_token_num: - continue - else: - cur_silent_token_num = 0 - self.tts_speech_token_dict[uuid].append(i) - else: - for i in self.llm.inference(text=text.to(self.device), - text_len=torch.tensor([text.shape[1]], dtype=torch.int32).to(self.device), - prompt_text=prompt_text.to(self.device), - prompt_text_len=torch.tensor([prompt_text.shape[1]], dtype=torch.int32).to(self.device), - prompt_speech_token=llm_prompt_speech_token.to(self.device), - prompt_speech_token_len=torch.tensor([llm_prompt_speech_token.shape[1]], dtype=torch.int32).to(self.device), - embedding=llm_embedding.to(self.device), - uuid=uuid): - if i in self.silent_tokens: - cur_silent_token_num += 1 - if cur_silent_token_num > max_silent_token_num: - continue - else: - cur_silent_token_num = 0 - self.tts_speech_token_dict[uuid].append(i) + embedding=llm_embedding.to(self.device), + uuid=uuid) + for i in token_generator: + if i in self.silent_tokens: + cur_silent_token_num += 1 + if cur_silent_token_num > max_silent_token_num: + continue + else: + cur_silent_token_num = 0 + self.tts_speech_token_dict[uuid].append(i) self.llm_end_dict[uuid] = True def vc_job(self, source_speech_token, uuid): From ab7f1f4a863a366f8333f9de611875d30e24d84e Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 15:12:18 +0000 Subject: [PATCH 59/61] update silent token --- cosyvoice/cli/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index b589bcd..9903acb 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -411,7 +411,7 @@ class CosyVoice3Model(CosyVoice2Model): self.llm_end_dict = {} self.hift_cache_dict = {} # FSQ silent token - self.silent_tokens = [28, 29] + self.silent_tokens = [2, 28, 29] def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): From cc91e40db8da7796e02bd963f54950e8f9e2cc19 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 15:53:33 +0000 Subject: [PATCH 60/61] more silent_token --- cosyvoice/cli/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index 9903acb..b0097fe 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -411,7 +411,7 @@ class CosyVoice3Model(CosyVoice2Model): self.llm_end_dict = {} self.hift_cache_dict = {} # FSQ silent token - self.silent_tokens = [2, 28, 29] + self.silent_tokens = [1, 2, 28, 29, 55, 2241, 2242, 2322, 2323] def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16): From dac6566fc38907164d2a6aaec9b6970879ba7d90 Mon Sep 17 00:00:00 2001 From: "lyuxiang.lx" Date: Tue, 30 Dec 2025 16:14:36 +0000 Subject: [PATCH 61/61] update tokens --- cosyvoice/cli/model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cosyvoice/cli/model.py b/cosyvoice/cli/model.py index b0097fe..0dc2561 100644 --- a/cosyvoice/cli/model.py +++ b/cosyvoice/cli/model.py @@ -410,8 +410,8 @@ class CosyVoice3Model(CosyVoice2Model): self.tts_speech_token_dict = {} self.llm_end_dict = {} self.hift_cache_dict = {} - # FSQ silent token - self.silent_tokens = [1, 2, 28, 29, 55, 2241, 2242, 2322, 2323] + # FSQ silent and breath token + self.silent_tokens = [1, 2, 28, 29, 55, 248, 494, 2241, 2242, 2322, 2323] def token2wav(self, token, prompt_token, prompt_feat, embedding, token_offset, uuid, stream=False, finalize=False, speed=1.0): with torch.cuda.amp.autocast(self.fp16):