SparkTTS 音色克隆 + vLLM INT8量化加速推理

大模型向量数据库机器学习

picture.image

猴哥的第 170 期分享,欢迎追看

前段时间,分享了低延迟小智AI服务端搭建的 ASR、LLM 和 TTS 部分:

低延迟小智AI服务端搭建-ASR篇

低延迟小智AI服务端搭建-ASR篇(续)

低延迟小智AI服务端搭建-LLM篇

低延迟小智AI服务端搭建-TTS篇

这三个环节中,成本最高的当属 TTS

本地TTS系列,模型选择的要求如下:

  • RTF<1
  • 支持流式推理
  • 支持音色克隆

目前,已更新两篇:

低延迟小智AI服务端搭建-本地TTS篇:fishspeech流式推理

低延迟小智AI服务端搭建-本地TTS篇:CosyVoice流式推理

本篇,继续实测 SparkTTS,一款只需 3 秒音频即可音色克隆的 TTS。

聊聊如何优化推理延时。

  1. 关于 SparkTTS

本地部署 SparkTTS 并搭建音色克隆服务,笔者之前有分享过:最新开源TTS语音克隆,本地部署实测!跨语言、高保真。。。

有朋友问:SparkTTS 的 RTF 远大于 1,怎么会出现在本地TTS系列?

来看下面这张架构图,你就明白了:

picture.image

你看,SparkTTS 也是基于 LLM 的 TTS 模型,而大模型这部分,显然可以用 vLLM / SGlang / TensorRT-LLM 等推理引擎,实现推理加速。

为什么选 vLLM?

加速性能不输其它框架,配置相对简单。

不多说,来测测看。

  1. 推理加速

以下测试,均以单张 RTX 4080 显卡为推理设备,供参考。

2.1 原始推理

SparkTTS 支持两种形式的语音合成:

  • 使用预训练的音色进行语音合成:
  
get prompt time: 0.000s  
tokenize time: 0.012s  
llm generate time: 6.537s  
audio detokenize time: 1.694s  
yield speech len 2.94, rtf 2.804  

  • 使用参考音频实现音色克隆:
  
get prompt time: 1.268s  
tokenize time: 0.010s  
llm generate time: 4.450s  
audio detokenize time: 1.245s  
yield speech len 2.82, rtf 2.473  

你看,无论哪种方式,延时主要在 LLM 生成 token 部分,其中音色克隆因为不需要生成<|bicodec\_global\_id|,故延时相对小一些。

但 RTF 远远达不到实时应用要求。

2.2 vLLM 推理加速

SparkTTS 中采用的 LLM 是标准的 Qwen-2.5-0.5B。

在预训练权重的 config.json 可以看到该模型的描述:

picture.image

vLLM 天然支持 "Qwen2ForCausalLM"。

因此,更换推理方式,只需如下两步:

Step 1 : 首先,替换模型加载方式。

vLLM 加载模型有两种方式:分别支持同步推理和异步推理,其中后者是 LLM 流式输出的关键。

同步推理相对简单:

  
from vllm import LLM  
self.model = LLM(f"{self.model\_dir}/LLM", device=self.device, gpu\_memory\_utilization=0.8)  

异步推理需要引入 AsyncLLMEngine:

  
from vllm import AsyncEngineArgs, AsyncLLMEngine  
engine\_kwargs = dict(  
    model=f"{self.model\_dir}/LLM",  
    max\_model\_len=32768,  
    gpu\_memory\_utilization=0.9,  
    device=self.device,  
    dtype='bfloat16',  
)  
async\_args = AsyncEngineArgs(**engine\_kwargs)  
self.model = AsyncLLMEngine.from\_engine\_args(async\_args)  

Step 2 : 修改模型生成部分代码。

同步推理相对简单:

  
output\_generator = self.model.generate(  
    prompts={"prompt\_token\_ids": model\_inputs.input\_ids[0]},  
    sampling\_params=self.sampling\_params  
)  
predicts = output\_generator[0].outputs[0].text  

异步推理,取最后一步结果:

  
output\_generator = self.model.generate(  
    prompt={"prompt\_token\_ids": model\_inputs.input\_ids[0]},  
    sampling\_params=self.sampling\_params,  
    request\_id=uuid.uuid4()  
)  
async for output in output\_generator:  
    pass  
predicts = output.outputs[0].text  

最后,看下 vLLM 加速后的推理耗时:

  
Processed prompts: [00:00<00:00,  1.32it/s, est. speed input: 21.07 toks/s, output: 263.36 toks/s]  
  
llm generate time: 0.763s  
  
yield speech len 3.2, rtf 0.6169003774994053  

模型输出吞吐量达到 263.36 toks/s,推理耗时从 6.537s -> 0.763s ,实在恐怖!

RTF 直接干到 1 以下,完美解决实时应用需求!

2.2 vLLM INT8 量化

此外,为了进一步降低推理延时,笔者还尝试了模型的 INT8 量化。

vLLM 框架目前已支持多种主流的量化方法,以笔者使用的 0.7.3 版本为例:

https://docs.vllm.ai/en/v0.7.3/features/quantization/index.html

picture.image

本次量化采用 SmoothQuant 方法 - ”激活+权重“的8比特量化,vLLM 官方提供了示例代码:https://github.com/vllm-project/llm-compressor/tree/main/examples/quantization\_w8a8\_int8

通常,模型量化需要以下三步:

  • 加载模型
  • 准备校准数据
  • 应用量化

其中,最关键的是准备校准数据,须模型推理所使用的数据,否则量化后的进度无法保证。

然而,原始的 Qwen-2.5 专为文本生成任务,SparkTTS 中采用的 LLM,词表已经为语音合成任务,进行了针对性设计。

所以,我们需手动生成一批校准数据:

  
def prepare\_data():  
    from cli.SparkTTS import SparkTTS  
    model = SparkTTS('./pretrained\_models/Spark-TTS-0.5B')  
    results = []  
    for i in range(512):  
        gender = random.choice(['male', 'female'])  
        pitch = random.choice(['very\_low', 'low', 'moderate', 'high', 'very\_high'])  
        speed = random.choice(['very\_low', 'low', 'moderate', 'high', 'very\_high'])  
        text = random.choice(['Hello, my name is Spark-TTS. How can I help you?', 'I want to book a flight to New York. Can you help me?'])   
        prompt = model.process\_prompt\_control(gender=gender, pitch=pitch, speed=speed, text=text)  
        model\_inputs = model.tokenizer(prompt, return\_tensors=None)  
        result = {"input\_ids": model\_inputs.input\_ids, "attention\_mask": model\_inputs.attention\_mask}  
        results.append(result)  
    with open('data/data.json', 'w') as f:  
        json.dump(results, f, indent=4, ensure\_ascii=False)  

确保你的每条数据格式如下,即可作为模型输入:

  
{'input\_ids': [151644, 8948], 'attention\_mask': [1, 1]}  

然后,在示例代码中,替换数据集为刚刚生成的数据:

  
from datasets import load\_dataset  
ds = load\_dataset("data/", split="train")  

最后,开始量化并保存模型权重:

  
recipe = [  
    SmoothQuantModifier(smoothing\_strength=0.5),  
    GPTQModifier(targets="Linear", scheme="W8A8", ignore=["lm\_head"]),  
]  
# Apply quantization  
oneshot(  
    model=model,  
    dataset=ds,  
    recipe=recipe,  
    max\_seq\_length=32768,  
    num\_calibration\_samples=512,  
)  
save\_dir = './pretrained\_models/Spark-TTS-0.5B/LLM\_sq'  
model.save\_pretrained(save\_dir, save\_compressed=True)  
tokenizer.save\_pretrained(save\_dir)  
  

量化日志如下:逐层 per_channel 量化,完成大概需要 8 mins。

picture.image

量化成功,问题来了:延时能降多少

你看:

  
Using CutlassScaledMMLinearKernel for CompressedTensorsW8A8Int8  
Processed prompts:[00:00<00:00,  1.25it/s, est. speed input: 20.04 toks/s, output: 231.75 toks/s]  
  
llm generate time: 0.801s  
  
yield speech len 3.2, rtf 0.6169003774994053  

非常遗憾,一顿操作,量化了个寂寞。

量化后,支持的并发数量有所上升,但推理延时并没有降低啊

难道是模型太小,量化带来的增益不明显?

懂的朋友,评论区求教啊!

  1. 首包响应延时实测

和前两篇一样,我们还是把模型封装成服务,供客户端测试。

同样,我也实现了参考音频编码缓存,思路和前两篇一样,不再赘述。

采用 vLLM 加速后的模型,gpu_memory_utilization 调到最大,显存全部占满。

首包延时 约 0.5s

picture.image

转成 wav 音频时,注意 SparkTTS 的音频采样率为 16K:

  
ffmpeg -f s16le -ar 16000 -ac 1 -i tts.pcm tts.wav  

写在最后

本文分享了小智AI服务端 本地TTS的实现,对 SparkTTS 采用 vLLM 进行推理加速,并实践了 INT8 量化,最后对首包延时进行了实测。

如果对你有帮助,欢迎点赞收藏 备用。

截止目前,SparkTTS 的首包延时是最低的,约 0.5s

后续,我们将继续实测更多低延迟、支持流式推理的 TTS 模型!


为方便大家交流,新建了一个 AI 交流群,公众号后台「联系我」,拉你进群。

👇 关注猴哥,快速入门AI工具

picture.image

# AI 工具:

本地部署大模型?看这篇就够了,Ollama 部署和实战

盘点9家免费且靠谱的AI大模型 API,统一封装,任性调用!

免费GPU算力本地跑DeepSeek R1,无惧官方服务繁忙!

# AI应用** :**

弃坑 Coze,我把 Dify 接入了个人微信,AI小助理太强了

我把「FLUX」接入了「小爱」,微信直接出图,告别一切绘画软件!

202K 下载!最强开源OCR:本地部署,邀你围观体验

阿里开源TTS CosyVoice 再升级!语音克隆玩出新花样,支持流式输出

借 WeChatFerry 东风,我把微信机器人复活了!

成本不到50的AI对话机器人,如何自建服务端?自定义角色+语音克隆

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动 XR 技术的探索与实践
火山引擎开发者社区技术大讲堂第二期邀请到了火山引擎 XR 技术负责人和火山引擎创作 CV 技术负责人,为大家分享字节跳动积累的前沿视觉技术及内外部的应用实践,揭秘现代炫酷的视觉效果背后的技术实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论