参考资料
- https://github.com/QwenLM/Qwen-Agent
由于可能使用到音频生成功能,了解下TTS模型的部署过程。测试环境如下
g5.4xlarge
EBS: 200GB
AMI:ami-0a83c884ad208dfbc ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-20250419
从官网下载模型到/home/ubuntu/.cache/modelscope/hub/models/iic/CosyVoice2-0.5B
环境要求上使用vllm版本0.9.0
If you want to use vllm for inference, please install vllmv0.9.0. Older vllm version do not support CosyVoice2 inference.
Notice that vllmv0.9.0 has a lot of specific requirements, for example torch==2.7.0
为了环境隔离考虑使用镜像
public.ecr.aws/deep-learning-containers/vllm:0.9.0-gpu-py312-ec2
public.ecr.aws/deep-learning-containers/vllm:0.9.2-gpu-py312-cu128-ubuntu22.04-ec2
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai:v0.9.0.1
docker.io/vllm/vllm-openai:v0.9.0.1
将https://github.com/QwenLM/Qwen-Image克隆到/home/ubuntu/vlmodel/cosyvoice下
构建镜像修改入口命令
FROM docker.io/vllm/vllm-openai:v0.9.0.1
# COPY ./entrypoint.sh /usr/local/bin/dockerd_entrypoint.sh
ENTRYPOINT ["/usr/bin/bash"]
启动容器
docker build -t zhaojiew-vllm:0.9.0.1 .
docker run -it --rm \--name cosyvoice \--network=host \-v /home/ubuntu/.cache/modelscope/hub/models/:/models \-v /home/ubuntu/vlmodel/cosyvoice/:/workspace \--gpus all \zhaojiew-vllm:0.9.0.1
参考官方示例安装依赖命令如下
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com
测试了0.9.2和0.9.0版本的vllm镜像环境,默认python为3.12,无法成功编译安装依赖
之所以要编译是因为python版本太新了,官方网站示例为py310,因此考虑使用conda创建对应版本的虚拟环境
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
exec bash
conda create -n cosyvoice -y python=3.10
conda activate cosyvoice
直接使用官方的如下示例测试,cosyvoice似乎要依赖third_party/Matcha-TTS中的一些功能
导入依赖和加载模型
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 torchaudiocosyvoice = CosyVoice2('/models/iic/CosyVoice2-0___5B', load_jit=False, load_trt=False, load_vllm=False, fp16=False)
模型加载和启动时会下载 wetext 文本前端模型(因 ttsfrd 未安装)。wetext 是阿里开源的中文文本前端处理工具,用于分词、韵律预测等。ttsfrd 可能在速度、韵律准确性上更优
Downloading Model to directory: /root/.cache/modelscope/hub/pengzhendong/wetext
...
DEBUG https://www.modelscope.cn:443 "GET /api/v1/models/... 200 OK
下面的零样本语音克隆(Zero-shot Voice Cloning) 。无需对该说话人进行任何模型微调或训练,仅凭一段几秒的语音即可复刻其音色。使用 load_wav 函数加载一个 .wav 音频文件作为 语音风格参考(prompt)。采样率为 16kHz( CosyVoice 模型要求的标准输入采样率)。
- 调用
cosyvoice.inference_zero_shot(...)方法进行零样本语音合成,提示文本(prompt text),应与prompt_speech_16k中的语音内容一致 stream=False:表示不使用流式生成(一次性返回完整结果);若为True,则会逐步返回音频片段(适用于实时场景)- 输出可能包含多个音频段(例如按句子分段),所以用循环遍历每个结果。
# 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_shot1_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
使用上个步骤中的音频,保存并复用零样本说话人(zero-shot speaker)特征,模型内部会提取该语音的声学特征(如音色、语调等),并将其与该 ID 关联起来。
- 不再传入
prompt_text和prompt_speech,而是通过zero_shot_spk_id='my_zero_shot_spk'直接指定已注册的特征。 - 默认保存到了
/models/iic/CosyVoice2-0___5B路径下,名称为spk2info.pt add_zero_shot_spk需要文本的原因?因为 CosyVoice 是基于流式语音单元(如 flow, VAE, 或 discrete units)建模的,必须对齐语音和文本才能准确提取与语言无关的说话人特征。
# 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_shot2_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
cosyvoice.save_spkinfo()
所有支持的控制标记(control tokens)定义在源码 tokenizer.py 第 248 行附近
- 文本中的
[laughter]是什么?预定义的控制标记(special token)。
# 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)
指令驱动语音合成(Instruction-based TTS) 功能,具体调用的是 inference_instruct2 接口。
- 在保持说话人音色不变的前提下,根据自然语言指令动态调整语音的风格、语调、方言、情感等属性**。
# 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)
如何理解vllm的部署脚本?从 cosyvoice.vllm.cosyvoice2 导入一个 适配 vLLM 的 CosyVoice 2 包装类,封装成 类似语言模型的因果生成结构,使其能被 vLLM 调度。目的是将 TTS 模型接入 vLLM 生态,享受 LLM 级推理优化
- 采用全优化配置同时尝试 JIT、TRT、vLLM 三种加速手段,优先级由内部实现决定
cosyvoice = CosyVoice2('/models/iic/CosyVoice2-0___5B',load_jit=True,load_trt=True,load_vllm=True,fp16=True
)
此外官方还提供了gradio的webui示例如下,我合成了一段夸语言的音频(双城记开头)
