Merge branch 'main' into main

This commit is contained in:
欣南科技
2025-02-14 00:31:20 +08:00
committed by GitHub
8 changed files with 94 additions and 16 deletions
+1
View File
@@ -139,3 +139,4 @@ cython_debug/
*.iml *.iml
model.pt model.pt
tmp tmp
.DS_Store
+1 -1
View File
@@ -21,7 +21,7 @@ RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com
# 第二阶段:生产镜像 # 第二阶段:生产镜像
FROM python:3.10-slim FROM python:3.10-slim
WORKDIR /opt/xiaozhi-es32-server WORKDIR /opt/xiaozhi-esp32-server
# 从构建阶段复制虚拟环境 # 从构建阶段复制虚拟环境
COPY --from=builder /opt/venv /opt/venv COPY --from=builder /opt/venv /opt/venv
+79 -6
View File
@@ -65,7 +65,15 @@
# 部署方式 # 部署方式
本项目支持docker快速部署和本地源码运行。如果您主要是想快速体验,推荐使用docker部署。如果想深入了解本项目,推荐本地源码运行 本项目支持docker快速部署、借助docker环境运行部署和本地源码运行三种方式。三种方式怎么选,每个人的情况不一样,以下是一些推荐
如果您主要是想快速体验,推荐使用`方式一:docker快速部署`
如果您已经安装docker,不想折腾环境,又想对代码进行DIY修改,推荐`方式二:借助docker环境运行部署`
如果您对conda的使用得心应手,或想从零开始学习搭建环境,推荐`方式三:本地源码运行`
如果你对小智的回答速度非常的敏感,不希望有丝丝的性能损失,推荐`方式三:本地源码运行`
## 方式一:docker快速部署 ## 方式一:docker快速部署
@@ -88,7 +96,7 @@ docker镜像已支持x86架构、arm64架构的CPU,支持在国产操作系统
### 4. 修改配置文件 ### 4. 修改配置文件
修改刚才你下载的`config.yaml`文件,配置本项目所需的各种参数。默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,才能启动。 修改刚才你下载的`config.yaml`文件,配置本项目所需的各种参数。默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,因为他们的模型,虽然有免费的,但是仍要去[官网](https://bigmodel.cn/usercenter/proj-mgmt/apikeys)注册密钥,才能启动。
默认的TTS使用的是`EdgeTTS`,这个无需配置,如果你需要更换成`豆包TTS`,则需要配置密钥。 默认的TTS使用的是`EdgeTTS`,这个无需配置,如果你需要更换成`豆包TTS`,则需要配置密钥。
@@ -140,7 +148,7 @@ dir
如果你能看到`config.yaml`文件,确确实实进入到了`项目目录`,接着执行以下命令: 如果你能看到`config.yaml`文件,确确实实进入到了`项目目录`,接着执行以下命令:
``` ```
docker run -d --name xiaozhi-esp32-server --restart always --security-opt seccomp:unconfined -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-es32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest docker run -d --name xiaozhi-esp32-server --restart always --security-opt seccomp:unconfined -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-esp32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
``` ```
如果首次执行,可能需要几分钟时间,你要耐心等待他完成拉取。正常拉取完成后,你可以在命令行执行以下命令查看服务是否启动成功 如果首次执行,可能需要几分钟时间,你要耐心等待他完成拉取。正常拉取完成后,你可以在命令行执行以下命令查看服务是否启动成功
@@ -166,6 +174,9 @@ docker logs -f xiaozhi-esp32-server
正常来说,假设你的ip是`192.168.1.25`,那么你的接口地址就是:`ws://192.168.1.25:8000`。这个信息很有用的,后面`编译esp32固件` 正常来说,假设你的ip是`192.168.1.25`,那么你的接口地址就是:`ws://192.168.1.25:8000`。这个信息很有用的,后面`编译esp32固件`
需要用到。 需要用到。
请注意,你的接口地址是`websocket`协议的地址,你可以使用`apifox`等工具调试。但是不能直接用浏览器打开访问,如果用浏览器打开,日志会显示错误,会让你怀疑是否部署成功了。
后期如果想升级版本,可以这么操作 后期如果想升级版本,可以这么操作
1、备份好`config.yaml`文件,一些关键的配置到时复制到新的`config.yaml`文件里。 1、备份好`config.yaml`文件,一些关键的配置到时复制到新的`config.yaml`文件里。
@@ -180,7 +191,58 @@ docker rmi ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
3.按本教程重新来一遍 3.按本教程重新来一遍
## 方式二:本地源码运行 ## 方式二:借助docker环境运行部署
这个方法的原理,其实是和第一种方式类似。区别在于,第一种方式只要下载一个配置文件,而本方式要下载项目源码。
优点就是源码在你主机躺着,你可以使用本机的代码编辑器加载项目和修改源码。每次修改完项目,想要看效果,那就要重启docker。
缺点就要下载本项目的代码,还要下载模型文件,如果这个项目不常用,确实会占用您电脑的空间。
下载源码后,需要下载模型文件。 默认使用`SenseVoiceSmall`模型,进行语音转文字。因为模型较大,需要独立下载,下载后把`model.pt`文件放在`model/SenseVoiceSmall`
目录下。下面两个下载路线任选一个。
- 线路一:阿里魔塔下载[SenseVoiceSmall](https://modelscope.cn/models/iic/SenseVoiceSmall/resolve/master/model.pt)
- 线路二:百度网盘下载[SenseVoiceSmall](https://pan.baidu.com/share/init?surl=QlgM58FHhYv1tFnUT_A8Sg&pwd=qvna) 提取码:
`qvna`
下载模型后,需要按照`方式一:docker快速部署`修改配置文件`config.yaml`
修改完配置后,打开命令行工具,`cd`进入到你的项目目录下,执行以下命令
```
docker run -d --name xiaozhi-esp32-server --restart always --security-opt seccomp:unconfined \
-p 8000:8000 \
-v $(pwd):/opt/xiaozhi-esp32-server \
ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
```
```
docker logs -f xiaozhi-esp32-server
```
如果你能看到,类似以下日志,则是本项目服务启动成功的标志。
```
2025-xx-xx xx:51:59,492 - core.server - INFO - Server is running at ws://xx.xx.xx.xxx:8000
2025-xx-xx xx:51:59,516 - websockets.server - INFO - server listening on 0.0.0.0:8000
```
接下来,你就可以开始 `编译esp32固件`了,请往下翻,翻到编译`esp32固件`相关章节。那么由于你是用docker部署,你要自己查看自己本机电脑的ip是多少。
正常来说,假设你的ip是`192.168.1.25`,那么你的接口地址就是:`ws://192.168.1.25:8000`。这个信息很有用的,后面`编译esp32固件`
需要用到。
请注意,你的接口地址是`websocket`协议的地址,你可以使用`apifox`等工具调试。但是不能直接用浏览器打开访问,如果用浏览器打开,日志会显示错误,会让你怀疑是否部署成功了。
后期,如果你修改了代码,想让新代码跑起来,可以用以下命令让docker容器重启:
```
docker restart xiaozhi-esp32-server
# 查看日志输出
docker logs -f xiaozhi-esp32-server
```
## 方式三:本地源码运行
### 1.安装基础环境 ### 1.安装基础环境
@@ -226,7 +288,7 @@ pip install -r requirements.txt
### 4.配置项目 ### 4.配置项目
修改`config.yaml`文件,配置本项目所需的各种参数。默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,才能启动。 修改`config.yaml`文件,配置本项目所需的各种参数。默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,因为他们的模型,虽然有免费的,但是仍要去[官网](https://bigmodel.cn/usercenter/proj-mgmt/apikeys)注册密钥,才能启动。
默认的TTS使用的是`EdgeTTS`,这个无需配置,如果你需要更换成`豆包TTS`,则需要配置密钥。 默认的TTS使用的是`EdgeTTS`,这个无需配置,如果你需要更换成`豆包TTS`,则需要配置密钥。
配置说明:这里是各个功能使用的默认组件,例如LLM默认使用`ChatGLMLLM`模型。如果需要切换模型,就是改对应的名称。 配置说明:这里是各个功能使用的默认组件,例如LLM默认使用`ChatGLMLLM`模型。如果需要切换模型,就是改对应的名称。
@@ -278,6 +340,8 @@ python app.py
其中上面的`ws://192.168.1.25:8000`就是本项目提供的接口地址了,当然你自己的机器和我的是不一样的,记得要找到自己的地址。 其中上面的`ws://192.168.1.25:8000`就是本项目提供的接口地址了,当然你自己的机器和我的是不一样的,记得要找到自己的地址。
请注意,你的接口地址是`websocket`协议的地址,你可以使用`apifox`等工具调试。但是不能直接用浏览器打开访问,如果用浏览器打开,日志会显示错误,会让你怀疑是否部署成功了。
# 编译esp32固件 # 编译esp32固件
1. 下载`xiaozhi-esp32` 1. 下载`xiaozhi-esp32`
@@ -308,6 +372,13 @@ config WEBSOCKET_URL
Communication with the server through websocket after wake up. Communication with the server through websocket after wake up.
``` ```
注意:你的地址是`ws://`开头,不是`wss://`开头,一定不要写错了。
注意:你的地址是`ws://`开头,不是`wss://`开头,一定不要写错了。
注意:你的地址是`ws://`开头,不是`wss://`开头,一定不要写错了。
3. 设置编译参数 3. 设置编译参数
``` ```
@@ -343,6 +414,8 @@ python release.py
编译成功后,会在项目根目录下的`build`目录下生成固件文件`merged-binary.bin` 编译成功后,会在项目根目录下的`build`目录下生成固件文件`merged-binary.bin`
这个`merged-binary.bin`就是要烧录到硬件上的固件文件。 这个`merged-binary.bin`就是要烧录到硬件上的固件文件。
注意:如果执行到第二命令后,报了“zip”相关的错误,请忽略这个错误,只要`build`目录下生成固件文件`merged-binary.bin`,对你没有太大影响,请继续。
6. 烧录固件 6. 烧录固件
将esp32设备连接电脑,使用chrome浏览器,打开以下网址 将esp32设备连接电脑,使用chrome浏览器,打开以下网址
@@ -357,7 +430,7 @@ https://espressif.github.io/esp-launchpad/
## 1、TTS 经常失败,经常超时 ## 1、TTS 经常失败,经常超时
建议:如果`EdgeTTS`经常失败,先检查一下是否用了梯子。 建议:如果`EdgeTTS`经常失败,先检查一下是否用了梯子,如果用了梯子,请把梯子关了试试
如果用的是`火山引擎的豆包TTS`经常失败,最好使用付费版本,因为他们的测试版本只有2个并发。 如果用的是`火山引擎的豆包TTS`经常失败,最好使用付费版本,因为他们的测试版本只有2个并发。
## 2、我想通过小智控制电灯、空调、远程开关机等操作。 ## 2、我想通过小智控制电灯、空调、远程开关机等操作。
+1 -1
View File
@@ -156,7 +156,7 @@ If you can see the `config.yaml` file, you have indeed entered the `project dire
command: command:
``` ```
docker run -d --name xiaozhi-esp32-server --restart always --security-opt seccomp:unconfined -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-es32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest docker run -d --name xiaozhi-esp32-server --restart always --security-opt seccomp:unconfined -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-esp32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
``` ```
If executed for the first time, it may take several minutes, and you have to be patient to wait for it to complete the If executed for the first time, it may take several minutes, and you have to be patient to wait for it to complete the
+1
View File
@@ -62,6 +62,7 @@ LLM:
ChatGLMLLM: ChatGLMLLM:
# 定义LLM API类型 # 定义LLM API类型
type: openai type: openai
# glm-4-flash 是免费的,但是还是需要注册填写api_key的
# 可在这里找到你的api key https://bigmodel.cn/usercenter/proj-mgmt/apikeys # 可在这里找到你的api key https://bigmodel.cn/usercenter/proj-mgmt/apikeys
model_name: glm-4-flash model_name: glm-4-flash
url: https://open.bigmodel.cn/api/paas/v4/ url: https://open.bigmodel.cn/api/paas/v4/
+9 -6
View File
@@ -35,11 +35,13 @@ async def handleAudioMessage(conn, audio):
conn.asr_audio.clear() conn.asr_audio.clear()
conn.reset_vad_states() conn.reset_vad_states()
async def startToChat(conn, text): async def startToChat(conn, text):
# 异步发送 stt 信息 # 异步发送 stt 信息
asyncio.create_task( stt_task = asyncio.create_task(
schedule_with_interrupt(0, send_stt_message(conn, text)) schedule_with_interrupt(0, send_stt_message(conn, text))
) )
conn.scheduled_tasks.append(stt_task)
conn.executor.submit(conn.chat, text) conn.executor.submit(conn.chat, text)
@@ -52,7 +54,10 @@ async def sendAudioMessage(conn, audios, duration, text):
conn.tts_start_speak_time = time.time() conn.tts_start_speak_time = time.time()
# 发送 sentence_start(每个音频文件之前发送一次) # 发送 sentence_start(每个音频文件之前发送一次)
await send_tts_message(conn, "sentence_start", text) sentence_task = asyncio.create_task(
schedule_with_interrupt(base_delay, send_tts_message(conn, "sentence_start", text))
)
conn.scheduled_tasks.append(sentence_task)
conn.tts_duration += duration conn.tts_duration += duration
@@ -60,10 +65,6 @@ async def sendAudioMessage(conn, audios, duration, text):
for idx, opus_packet in enumerate(audios): for idx, opus_packet in enumerate(audios):
await conn.websocket.send(opus_packet) await conn.websocket.send(opus_packet)
# 每个音频文件发送结束时,发送 sentence_end
if idx == len(audios) - 1:
await send_tts_message(conn, "sentence_end", text)
if conn.llm_finish_task and text == conn.tts_last_text: if conn.llm_finish_task and text == conn.tts_last_text:
stop_duration = conn.tts_duration - (time.time() - conn.tts_start_speak_time) stop_duration = conn.tts_duration - (time.time() - conn.tts_start_speak_time)
stop_task = asyncio.create_task( stop_task = asyncio.create_task(
@@ -71,6 +72,7 @@ async def sendAudioMessage(conn, audios, duration, text):
) )
conn.scheduled_tasks.append(stop_task) conn.scheduled_tasks.append(stop_task)
async def send_tts_message(conn, state, text=None): async def send_tts_message(conn, state, text=None):
"""发送 TTS 状态消息""" """发送 TTS 状态消息"""
message = { message = {
@@ -85,6 +87,7 @@ async def send_tts_message(conn, state, text=None):
if state == "stop": if state == "stop":
conn.clearSpeakStatus() conn.clearSpeakStatus()
async def send_stt_message(conn, text): async def send_stt_message(conn, text):
"""发送 STT 状态消息""" """发送 STT 状态消息"""
stt_text = get_string_no_punctuation_or_emoji(text) stt_text = get_string_no_punctuation_or_emoji(text)
+2 -2
View File
@@ -15,7 +15,7 @@ docker rm xiaozhi-esp32-server
cd /Users/hrz/myworkspace/docker-java-env/thirddata/ cd /Users/hrz/myworkspace/docker-java-env/thirddata/
cp /Users/hrz/myworkspace/esp32/xiaozhi-esp32-server/config.yaml ./ cp /Users/hrz/myworkspace/esp32/xiaozhi-esp32-server/config.yaml ./
docker run -d --name xiaozhi-esp32-server --restart always -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-es32-server/config.yaml xiaozhi-esp32-server:local docker run -d --name xiaozhi-esp32-server --restart always -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-esp32-server/config.yaml xiaozhi-esp32-server:local
docker logs -f xiaozhi-esp32-server docker logs -f xiaozhi-esp32-server
@@ -40,6 +40,6 @@ docker manifest push ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
6、运行线上镜像 6、运行线上镜像
``` ```
cd /Users/hrz/myworkspace/docker-java-env/thirddata/ cd /Users/hrz/myworkspace/docker-java-env/thirddata/
docker run -d --name xiaozhi-esp32-server --restart always -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-es32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest docker run -d --name xiaozhi-esp32-server --restart always -p 8000:8000 -v $(pwd)/config.yaml:/opt/xiaozhi-esp32-server/config.yaml ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
docker logs -f xiaozhi-esp32-server docker logs -f xiaozhi-esp32-server
``` ```
Binary file not shown.

Before

Width:  |  Height:  |  Size: 841 KiB

After

Width:  |  Height:  |  Size: 481 KiB