大多数语音AI实现停在了流水线层面。真正的对话,从那里才开始。
Android上的语音AI有两个版本:演示版,和真实版。演示版很简单:录音,发给语音API,拿到文字,传给大模型,再用TTS读回来。一个下午就能搭完,视频里看着也还行。直到有人真的试着跟它对话——打断、停顿、追问——整个系统就崩了。
![]()
真实版完全不同。用户说话时,转录已经在进行;用户一停,大模型立刻开始响应;TTS在大模型还没说完时就已经播放;如果用户插话,一切干净利落地中断,200毫秒内恢复监听。没有点击,没有加载态,没有回合制礼仪。
这篇文章讲如何构建真实版——从让它可管理的概念模型,到只在真实对话里才会出现的具体Bug。
核心是一个循环:监听→思考→说话→再监听。三个服务驱动它:STT(边说边出部分转录,静默时出最终结果)、LLM(拿转录+对话历史,逐token流式响应)、TTS(大模型生成一句,它就合成播放一句,而非等全部完成)。难点不在任一环节,而在它们的交互:用户打断TTS怎么办?LLM慢了怎么办?取消的会话里过期的转录,在新会话开始后抵达怎么办?这些在真正来回对话之前,都是看不见的。
技术栈:Deepgram nova-3(STT)、Groq llama-3.3-70b-versatile(LLM)、Cartesia sonic-3(TTS),均有免费额度。完整实现见GitHub上的FluxVoice。
最关键的决策是状态机。最大错误是把三个服务当成独立的——它们共享麦克风、共享对话上下文,需要干净地交接。五状态机解决这个:系统任何时刻只处于一个状态,组件不互相调用,而是观察状态并反应。这消灭了一整类竞态条件——两个阶段同时运行的那种。
状态流转:空闲(IDLE)→开始→监听中出最终结果→思考(THINKING)→首token到达→说话(SPEAKING)→TTS空闲且流结束(或被插话打断)→回到空闲。插话检测靠音量阈值,触发时立即切回监听,同时取消进行中的TTS和LLM请求。上下文管理器负责维护对话历史,但只保留未被取消的会话内容。
200毫秒的目标来自感知研究:超过这个延迟,人类会注意到"卡顿"。Android音频路径本身就要吃掉80-100毫秒,留给应用层的余地很小。预缓冲、预测性TTS启动、本地回声消除,都是压榨延迟的手段。
真实对话里才会暴露的Bug:蓝牙耳机的麦克风切换延迟、网络抖动导致的STT片段乱序、用户用气声说话时VAD(语音活动检测)失效、大模型生成列表时TTS把"第三"读成"第3"然后卡住。每一个都需要针对性的缓解策略,而非框架层面的通用解决。
从Demo到产品,差的不是更多代码,是对"对话"本身的理解。语音AI的工程,最终是人机交互的工程。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.