语音助手:ASR + LLM + TTS 三件套
在聊天框打字已经很熟了——把键盘换成麦克风,开口问、等它把答案说出来,中间发生了什么?这一课拆解语音助手的最小架构,并指出让它"像人"的两个工程细节:流式输出与多轮上下文。
一、一条语音的旅程:五模块流水线
麦克风 → 音频采集 → VAD 断句 → ASR 转文字 → LLM 回答 → TTS 合成 → 扬声器
三个核心模型各管一段:
- ASR(语音识别):把音频信号转成文字。除识别准确率外,还要考虑口音、语速、环境噪声——安静和嘈杂环境里同一句话的识别效果可能不同;
- LLM:拿到问题文本生成回答。单轮直接问直接答;多轮必须把前几轮的问题和回答放进上下文,否则"那第二个呢"这种指代就接不住;
- TTS(语音合成):把回答转成语音。除读对字,还决定最终听感——清晰度、停顿、语速。
除了三个模型,还有两个容易被忽略的配套模块:音频采集(本地用 sounddevice 等库访问麦克风;云端部署时程序跑在服务器上够不到本地麦克风,常见做法是用 Gradio 在浏览器里采集再传给后端)和 VAD(语音活动检测)——判断用户什么时候开始说、什么时候说完,没有它系统不知道该在什么时候把音频切给 ASR。
二、让助手"像人"的关键:流式 TTS
非流式的时序是:用户说完 → ASR → LLM 生成完整回答 → TTS 合成完整音频 → 播放。用户要盯着屏幕干等十几秒。
流式的时序是:LLM 每生成几个字,TTS 立即合成对应音频片段推给播放模块——"边说边放"。首响应时间从"整段生成完"缩短到"第一句生成完",体感差距是质变。做现场演示时,这一项就是"像产品"和"像实验"的分界线。
三、工程化拆法:先封装,再串联
原著的实现顺序值得照抄——每个模块先封装、单独测试,确认能跑再组合:
- ASR / LLM / TTS 各封装成类(构造时加载模型,暴露
transcribe / chat / synthesize接口); - 采集与播放封装成函数;
- 组合成完整循环:录音 → VAD 切段 → ASR → 拼上下文调 LLM → 流式 TTS 播放 → 保留历史支持多轮。
每步单独测试的好处:组合后出问题时,能立刻定位是哪个模块的锅——这套纪律放到客户现场同样成立。
四、FDE 视角:语音项目的评估维度
- 链路延迟分账:端到端延迟 = VAD 判停 + ASR + LLM 首 Token + TTS 首包。给客户讲"为什么有等待"时逐段拆,比一句"网络原因"专业十倍;流式化能砍掉的是后两段的串行等待;
- 准确率分开测:ASR 用字符错误率(CER),LLM 用业务测试集,TTS 做人工听感评分——三段各有指标,混在一起没法定位问题(呼应《微调效果验收》的分任务指标);
- 场景衔接:客服电话质检(上一课)与语音助手共享 ASR 底座——一个客户里做完质检项目,语音助手方案的土地已经平整了一半;
- 端侧可行:0.6B~2B 级 ASR 模型 + 量化 LLM + 轻量 TTS 可以在单卡甚至高配笔记本上跑通(呼应《显存账》《Ollama 与量化》),涉密环境全链路离线是真实卖点。
本课自测
- 语音助手五个模块分别是什么?VAD 缺了会出什么问题?
- 流式 TTS 改变了哪两段之间的串行等待?对用户体感意味着什么?
- 多轮对话的上下文里应该包含什么?
- 端到端延迟应该拆成哪几段分别优化?
随堂测
逐题作答,即时反馈
1. 语音助手里 VAD(语音活动检测)模块的作用是什么?
2. 流式 TTS 改变了哪两段之间的串行等待?
3. 多轮语音对话中,LLM 的上下文应该包含什么?