在当今人工智能技术迅猛发展的浪潮里,大模型如雨后春笋般不断涌现,似乎已成为各个项目中不可或缺的关键要素。
从智能家居领域到智能办公场景,从教育行业到娱乐产业,AI的应用场景持续拓展延伸。而人工智能对话机器人,更是一跃成为当下最为热门的项目类型之一。众多开发者竞相涌入这一赛道,全力尝试打造出令人称奇的智能语音助手,期望能让AI真正无缝融入人们的日常生活。
就最新情况而言,小智(Xiaozhi - ESP32)无疑是当前极为成功的项目典范,在刚刚过去的农历新年期间成为大众热议的焦点,网友们口口相传,热度居高不下。
将小智移植到树莓派5上,不仅能够充分挖掘并发挥树莓派5的硬件优势,还可流畅且高效地完成对话交互内容,为**智能体的开发工作夯实基础,铺平前行道路。
本项目内容将详细地从环境搭建开始,一步步深入到运行py - xiaozhi项目,进行全方位、手把手式的细致讲解,尤其适合刚刚接触树莓派pi5的新手朋友。同时,在讲解过程中还会分享这段时间探索项目时积累总结的宝贵经验,助力大家更好地理解与实践。

一、系统安装
1、在 Raspberry Pi 配置工具中,导航到“Advanced Options”(高级选项)。
2、在“Advanced Options”下,选择“Boot Order”(启动顺序)。
3、在“Boot Order”中,选择“NVMe/USB boot”(NVMe/USB启动)。
4、确认选择并保存更改。
5、使用“Finish”或“Esc”键退出 Raspberry Pi 配置工具。
6、重启树莓派在终端中输入 sudo reboot 命令来重新启动你的树莓派。(保险起见可以关机,把TF卡抽掉,重新开机)
开机时间大约10s,心情还是蛮好的。


二、更换软件源
1. 备份原有的 sources.list 文件
在开始之前,最好备份原有的 sources.list 文件,以防万一需要恢复。
打开终端,执行以下命令来备份原有的 sources.list 文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
2. 编辑 sources.list 文件
接下来,我们需要编辑 /etc/apt/sources.list 文件,将其替换为清华大学的镜像源地址。
使用文本编辑器打开 sources.list 文件,例如使用 nano:
sudo nano /etc/apt/sources.list
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware
# 以下安全更新软件源包含了官方源与镜像站配置,如有需要可自行修改注释切换
deb https://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
5 修改其他文件
/etc/apt/sources.list.d/raspi.list
sudo nano /etc/apt/sources.list.d/raspi.list
内容修改为
deb https://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ bookworm main
6.更新源
sudo apt update
sudo apt upgrade?
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple
-阿里云:`https://mirrors.aliyun.com/pypi/simple/`
-中科大:`https://pypi.mirrors.ustc.edu.cn/simple/`
三、远程编程工具




四、py-xiaozhi项目移植
(1)独立python环境

# 确保你安装了虚拟环境工具
sudo apt update
sudo apt install python3-venv python3-pip
# 创建一个新的虚拟环境
python3 -m venv myenv
# 激活虚拟环境
source myenv/bin/activate
# 在虚拟环境中安装 requirements.txt 中的包
pip install -r requirements.txt
(2)音频测试
(myenv) genvex@raspberrypi:~/py-xiaozhi $ aplay -l # 查看可用设备
**** List of PLAYBACK Hardware Devices ****
card 0: YueMiUSB [YueMi_USB], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: vc4hdmi0 [vc4-hdmi-0], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: vc4hdmi1 [vc4-hdmi-1], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
<BASH>
# 实时查看音频电平alsamixer -c 0 # 控制USB声卡
Available audio input devices:
Device Index Device Name Default Sample Rate (Hz)
0 YueMi_USB: USB Audio (hw:0,0) 44100.0
1 sysdefault 44100.0
5 spdif 44100.0
6 pulse 44100.0
7 speex 44100.0
8 upmix 44100.0
9 vdownmix 44100.0
11 default 44100.0?
(3)安装?PortAudio?开发包:
sudo apt update
sudo apt install portaudio19-dev
pip install pyaudio
(4)按键驱动


(5)py-xiaozhi移植精讲




# 典型通信流程示例
def send_audio():
while running:
录音 -> Opus编码 -> AES加密 -> UDP发送
def on_mqtt_message():
接收JSON指令 -> 更新会话状态 -> 控制音频线程
def on_space_key_press():
global key_state, udp_socket, aes_opus_info, listen_state, conn_state
if key_state == "press":
return
key_state = "press"
# 判断是否需要发送hello消息
if conn_state is False or aes_opus_info['session_id'] is None:
conn_state = True
# 发送hello消息,建立udp连接
hello_msg = {"type": "hello", "version": 3, "transport": "udp",
"audio_params": {"format": "opus", "sample_rate": 16000, "channels": 1, "frame_duration": 60}}
push_mqtt_msg(hello_msg)
print(f"send hello message: {hello_msg}")
if tts_state == "start" or tts_state == "entence_start":
# 在播放状态下发送abort消息
push_mqtt_msg({"type": "abort"})
print(f"send abort message")
if aes_opus_info['session_id'] is not None:
# 发送start listen消息
msg = {"session_id": aes_opus_info['session_id'], "type": "listen", "state": "start", "mode": "manual"}
print(f"send start listen message: {msg}")
push_mqtt_msg(msg)
def on_space_key_release():
global aes_opus_info, key_state
key_state = "release"
# 发送stop listen消息
if aes_opus_info['session_id'] is not None:
msg = {"session_id": aes_opus_info['session_id'], "type": "listen", "state": "stop"}
print(f"send stop listen message: {msg}")
push_mqtt_msg(msg)
# def on_press(key):
# if key == pynput_keyboard.Key.space:
# on_space_key_press(None)
# def on_release(key):
# if key == pynput_keyboard.Key.space:
# on_space_key_release(None)
# # Stop listener
# if key == pynput_keyboard.Key.esc:
# return False
def run():
global mqtt_info, mqttc
# 获取mqtt与版本信息
get_ota_version()
# 监听键盘按键,当按下空格键时,发送listen消息
# listener = pynput_keyboard.Listener(on_press=on_press, on_release=on_release)
# listener.start()
button = Button(16)
button.when_pressed = on_space_key_press
button.when_released = on_space_key_release
# 创建客户端实例
mqttc = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2, client_id=mqtt_info['client_id'])
mqttc.username_pw_set(username=mqtt_info['username'], password=mqtt_info['password'])
mqttc.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=mqtt.ssl.CERT_REQUIRED,
tls_version=mqtt.ssl.PROTOCOL_TLS, ciphers=None)
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.connect(host=mqtt_info['endpoint'], port=8883)
mqttc.loop_forever()
if __name__ == "__main__":
audio = pyaudio.PyAudio()
run()
总结:

1.2万
