在當(dāng)今人工智能技術(shù)迅猛發(fā)展的浪潮里,大模型如雨后春筍般不斷涌現(xiàn),似乎已成為各個項目中不可或缺的關(guān)鍵要素。
從智能家居領(lǐng)域到智能辦公場景,從教育行業(yè)到娛樂產(chǎn)業(yè),AI的應(yīng)用場景持續(xù)拓展延伸。而人工智能對話機(jī)器人,更是一躍成為當(dāng)下最為熱門的項目類型之一。眾多開發(fā)者競相涌入這一賽道,全力嘗試打造出令人稱奇的智能語音助手,期望能讓AI真正無縫融入人們的日常生活。
就最新情況而言,小智(Xiaozhi - ESP32)無疑是當(dāng)前極為成功的項目典范,在剛剛過去的農(nóng)歷新年期間成為大眾熱議的焦點,網(wǎng)友們口口相傳,熱度居高不下。
將小智移植到樹莓派5上,不僅能夠充分挖掘并發(fā)揮樹莓派5的硬件優(yōu)勢,還可流暢且高效地完成對話交互內(nèi)容,為**智能體的開發(fā)工作夯實基礎(chǔ),鋪平前行道路。
本項目內(nèi)容將詳細(xì)地從環(huán)境搭建開始,一步步深入到運行py - xiaozhi項目,進(jìn)行全方位、手把手式的細(xì)致講解,尤其適合剛剛接觸樹莓派pi5的新手朋友。同時,在講解過程中還會分享這段時間探索項目時積累總結(jié)的寶貴經(jīng)驗,助力大家更好地理解與實踐。
一、系統(tǒng)安裝
1、在 Raspberry Pi 配置工具中,導(dǎo)航到“Advanced Options”(高級選項)。
2、在“Advanced Options”下,選擇“Boot Order”(啟動順序)。
3、在“Boot Order”中,選擇“NVMe/USB boot”(NVMe/USB啟動)。
4、確認(rèn)選擇并保存更改。
5、使用“Finish”或“Esc”鍵退出 Raspberry Pi 配置工具。
6、重啟樹莓派在終端中輸入 sudo reboot 命令來重新啟動你的樹莓派。(保險起見可以關(guān)機(jī),把TF卡抽掉,重新開機(jī))
開機(jī)時間大約10s,心情還是蠻好的。

二、更換軟件源
1. 備份原有的 sources.list 文件
在開始之前,最好備份原有的 sources.list 文件,以防萬一需要恢復(fù)。
打開終端,執(zhí)行以下命令來備份原有的 sources.list 文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
2. 編輯 sources.list 文件
接下來,我們需要編輯 /etc/apt/sources.list 文件,將其替換為清華大學(xué)的鏡像源地址。
使用文本編輯器打開 sources.list 文件,例如使用 nano:
sudo nano /etc/apt/sources.list
# 默認(rèn)注釋了源碼鏡像以提高 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
內(nèi)容修改為
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/`
三、遠(yuǎn)程編程工具


四、py-xiaozhi項目移植
(1)獨立python環(huán)境

# 確保你安裝了虛擬環(huán)境工具
sudo apt update
sudo apt install python3-venv python3-pip
# 創(chuàng)建一個新的虛擬環(huán)境
python3 -m venv myenv
# 激活虛擬環(huán)境
source myenv/bin/activate
# 在虛擬環(huán)境中安裝 requirements.txt 中的包
pip install -r requirements.txt
(2)音頻測試
(myenv) genvex@raspberrypi:~/py-xiaozhi $ aplay -l # 查看可用設(shè)備
**** 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?開發(fā)包:
sudo apt update
sudo apt install portaudio19-dev
pip install pyaudio
(4)按鍵驅(qū)動

(5)py-xiaozhi移植精講




# 典型通信流程示例
def send_audio():
while running:
錄音 -> Opus編碼 -> AES加密 -> UDP發(fā)送
def on_mqtt_message():
接收J(rèn)SON指令 -> 更新會話狀態(tài) -> 控制音頻線程
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"
# 判斷是否需要發(fā)送hello消息
if conn_state is False or aes_opus_info['session_id'] is None:
conn_state = True
# 發(fā)送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":
# 在播放狀態(tài)下發(fā)送abort消息
push_mqtt_msg({"type": "abort"})
print(f"send abort message")
if aes_opus_info['session_id'] is not None:
# 發(fā)送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"
# 發(fā)送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()
# 監(jiān)聽鍵盤按鍵,當(dāng)按下空格鍵時,發(fā)送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
# 創(chuàng)建客戶端實例
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()
總結(jié):
