TL;DR: 本文没有任何技术观点,只是总结了一下最近正在做的事

去年我在"星际蜗牛"上折腾Home Assistant时一直想找个方法把"小爱同学"或"天猫精灵"的语音输入给接管了。

折腾了几天之后,没找到比较好的方案,最后搁置了。

过年时,deepseek爆红之后,这个心思又活络起来,如果我能让智能音响的输入直接转发给deepseek就可以让家里小朋友尽快体验到大模型的便利。

这次我仔细分析了一下需求,输入端到底是不是智能音响其实一点都不重要,我要的只是一个可以语音唤醒的语音终端。

既然这样,我自己直接做个这样的语音终端可能也不会太难,这样至少可以All in control

实现以前我去Github搜了一下(毕竟10多年没画过PCB了,还是不太想碰这块,做起来太麻烦), 发现了一个可以完美实现我需求的方案,xiaozhi-esp32

作者开源了电路板方案、固件还有通信协议,甚至还有适配好有外壳的开发板可以购买。

我直接买了个立创·实战派ESP32-S3开发板的开发板(固件是一点都不想碰:D), 直接去开发对应的服务端程序了。

目前为止,家里24小时开机的设备,只有一台"星际蜗牛的黑群晖", 这上面还同时跑了一个"图书馆", 一个Home Assistant

这也注定了我不可能有太多资源来跑这个服务端, 所以我打算将目标内存限制在100MB以内。

当然这个内存限制直接就让我放弃了Python

最后我选择了我自己的网络框架来开发这个服务端, 这样也可以让我自己更好的了解大模型的调用方式。

100MB的内存太少了,他甚至都跑不起来一个VAD模型,更别提嵌入向量模型BAAI/bge-m3

因此在设计之初,我就已经打算非业务逻辑的功能全部独立出去,先本地部署,然后通过网络调用。

这样当我找到互联网上的免费平替后,可以直接替换。

也只有全部替换成功,这个服务端才有可能真正在"黑群晖"上跑起来。

以前从没来涉及过大模型相关的知识,比如怎么调用openai, 什么是嵌入向量,怎么做内容召回。

再加上,年后开工之后周末空闲时间也比较少, 所以一直到上周才算有了一个可以运行的版本。


整个系统跑下来分为这么几个部分。

语音唤醒和输入 (使用xiaozhi-esp32来实现)

这个没什么说的,直接使用官方的固件即可。

VAD 静音检查

当设备被唤醒之后,它会源源不断的发送声音片段给服务端。

如果服务端一股脑全部发给ASR服务,那这个价格是承受不起的。

所以一般都需要先用VAD模型找出有信息的声音片段, 再将这些片段发给ASR服务。

ASR 语音识别

拿到有信息声音片段之后,我们想知道用户说了什么,就需要使用ASR服务, 来将声音片段转换为文字。

这里真的要感谢腾讯,每月可以有5000次免费调用,对于个人使用场景足够了。

嵌入向量模型

在获取到用户的文本信息之后,在调用大模型之前,我们需要先召回与本次对话相关的聊天记录或知识。

这时就需要用到嵌入向量模型,将用户的问题转换为向量,然后去向量数据库中召回与该向量最相似的聊天记录。

这里要感谢SiliconFlow,他们提供了5种免费的向量模型,其实刚好有我需要的BAAI/bge-m3

向量数据库

为了召回记忆,还需要将聊天记录持久化,这里我选择了redis-stack, 巧的是redis-stack提供了30M的免费空间。

应该没有哪个话痨能聊满30M吧?至少我家小朋友暂时还没这个潜力, 尤其我还增加了记忆遗忘功能。

惟一的缺点是,公网链接redis可能会有延迟,不过等到延迟有明显影响时,再本地部署也来得及。

大模型

这里又要再次感谢SiliconFlow,他们提供了很多免费的小尺寸的大模型,在意图识别和参数提取等方面可以极大的降低延迟和成本。

甚至真正用来思考的全尺寸大模型,也可以用注册赠送的额度来使用。

直接使用官方DeepSeek V3价格也不是不能接受。

回答输出

大模型返回的回答以文字为主,语音大模型目前来看似乎不是主流。

因此我们还需要TTS服务,来将文字转换为语音然后发回给xiaozhi-esp32

其实这里有点纠结,因为国内给的额度都是一次性的,比如3个月多少字符,这种不具有可持续性,我更喜欢使用那种每个月有一定额度的。

所以最终注册了个Azure的账号,然后建了个Azure TTS F0层级的资源,然后使用Azure TTS的API来生成语音。

在试用了一周之后,发现Azure TTS由于节点不在国内,所以延迟非常高,甚至第一句话能延迟3s之多,这在语音交互中特别难受。

最后打算使用Edge TTS来生成语音,不过Edge TTS是逆向出来的API, 不是很稳定,只能先将就用了。


最后,谈谈对目前大模型的感受。

在做这个服务端之前,我其实预设了4个简单的Agent。 也许都不能够称为Agent, 因为它们没有Workflow, 仅仅是系统提示词和调用参数的不同。

  • 普通对话
  • 全科小学老师
  • 英语口语老师
  • 脑筋急转弯伙伴

其中英语口语老师脑筋急转弯伙伴算是彻头彻尾的失败了,因为他们并不是简单的问答模式。

英语口语老师需要先主动说出一句对话,然后小朋友回答一句,老师再点评, 这样循环。

在仅靠系统提示词的情况下,使用全尺寸DeepSeekV3模型,在一轮对话之后,指令的遵从性就变的非常差,有时甚至都不用一轮。

脑筋急转弯伙伴就更复杂,他有可能需要AI出题, 小朋友回答,然后AI再点评。或者小朋友出题,AI回答,小朋友再点评。

在这种情况下,AI甚至都坚持不到一轮对话结束,就开始胡言乱语了。

刚好最近看到一篇文章, 我觉得在目前的情况下,即使在有记忆的情况下,Workflow是不可取代的。

现在的大模型似乎很难尊从超出惟一要求之外的系统指令。

上面的英语口语老师脑筋急转弯伙伴之所以失败,是因为他们希望每次对话执行A,第二次对话执行B, 第三次对话执行C, 然后再从A开始。

最后,代码在此