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
开始。
最后,代码在此