SOP-001:小樱桃语音交互体系¶
语音设备日常运维 · VAD 参数 · 音量增益 · PowerMem · 角色设定 · 故障排查
服务器拓扑¶
┌─────────────┐ WebSocket ┌──────────────────┐
│ ESP32 │ ─────────────────→ │ xiaozhi-esp32- │
│ (音箱) │ ws://:18000 │ server (docker) │
└─────────────┘ └────────┬─────────┘
│
┌──────┴──────┐
│ open-xiaoai │
│ -xiaozhi │
│ 桥接器 │
└──────┬──────┘
│
┌──────┴──────┐
│ 智谱 API │
│ glm-4.5-air │
└─────────────┘
关键地址:
- 服务器 IP:192.168.31.27
- WebSocket 端口:18000
- HTTP 端口:18003
- 容器名:xiaozhi-esp32-server
参数表¶
VAD(语音活动检测)¶
| 参数 | server | bridge | 说明 |
|---|---|---|---|
| threshold | 0.30 | 0.10 | 进入说话的门槛 |
| threshold_low | 0.20 | 0.01 | 退出说话的门槛(保持 hysteresis 差距) |
| min_speech_duration | — | 250ms | 最短语音触发时长 |
| min_silence | 1200ms | 1200ms | 静默多久算完(两端统一) |
| boost | — | 10(代码未读取,无效参数) | 配置中 +10,但 bridge 代码无任何引用 |
| frame_window_threshold | 3 | — | 连续几帧达到 threshold 才算开始说话(防误触) |
VAD 双阈值(hysteresis):
threshold > threshold_low,防止在边界处反复触发/关闭。 桥接器 VAD 默认值见/app/.venv/.../silero_vad/__init__.py,配置覆盖见/app/config.py。 服务器 VAD 默认值见silero.py:27(threshold=0.5, threshold_low=0.2, min_silence=1000),.config.yaml 覆盖为当前运行值。 ⚠️ server 修改方式:改.config.yaml→docker restart xiaozhi-esp32-server⚠️ bridge 修改方式:改config.py→docker restart open-xiaoai-xiaozhi
唤醒与超时¶
| 参数 | bridge | server | 说明 |
|---|---|---|---|
| 唤醒前动作 | "嗯!" + 0.5s 缓冲 |
— | bridge before_wakeup,KWS 唤醒时播放缓冲 |
| 小爱拦截 | abort_xiaoai + sleep 2.0s |
— | 小爱正在说话时拦截并等待 |
| 唤醒后动作 | "小小苏,拜拜" |
— | bridge after_wakeup,退出时播报 |
| 唤醒词 | 你好小樱桃/小樱桃你好/呼叫小樱桃/召唤小樱桃 |
— | 支持 4 个变体 |
| 唤醒超时 | 20s | — | 超过此时间未说话自动退出 |
| WS 超时 | — | 120s(close_connection_no_voice_time) |
无语音多久断连 |
| TTS 超时 | — | 15s(tts_timeout) |
TTS 生成超时上限 |
音量¶
| # | 位置 | 增益 | 实现方式 |
|---|---|---|---|
| 1 | 桥接器 codec.py:100 | audioop.mul(pcm_data, 2, 1.5) 约 +3.5dB |
PCM 采样值相乘 |
| 2 | 桥接器 config.py | boost: 10 |
无效参数(代码未读取此字段) |
| 3 | 服务器 util.py(init_and_run 补丁) | audio + 6 = +6dB |
PCM 采样值相加 |
| 4 | 服务器 .config.yaml | gain: 3 |
CosyVoice2 API 增益参数 |
#1、#3、#4 是同一组,一起调小樱桃和小爱的音量一致性。
2(boost)是无效参数,代码未读取,修改无任何效果。¶
模型配置¶
| 参数 | 值 |
|---|---|
| LLM (主) | glm-4.5-air via 智谱 open.bigmodel.cn |
| LLM (备用) | deepseek-chat via api.deepseek.com(max_tokens=500, temperature=0.7) |
| Embedding | embedding-3 via 智谱 open.bigmodel.cn(2048 维) |
| TTS | CosyVoice2-0.5B:anna via 硅基流动 siliconflow(gain=3, response=wav) |
| ASR | FunASR SenseVoiceSmall(容器内本地,模型 data/models/SenseVoiceSmall) |
| PowerMem | selected_module=powermem(启用量化记忆,向量库=sqlite) |
角色设定(小樱桃)¶
- 身份: 苏子桐的 AI 小伙伴(不是助手、不是老师)
- 年龄定位: 永远比苏子桐大 2 岁(她 6 岁我 8 岁,她 10 岁我 12 岁)
- 关系: 朋友/玩伴,不是管教者
- 语气: 童真、好奇、偶尔调皮
- 原则: 引导表达 > 直接给答案。不主动说教
- 知识边界: 通过 PowerMem 知道苏子桐的经历,但不假装全知
prompt 四段结构:模板规则 + few-shot + 动态上下文(时间/记忆) + 聊天历史
用户画像 — 双层注入¶
总体结构¶
每次对话时,系统向 LLM 注入两层用户画像:
<memory>
<stable_profile> ← 你维护的权威事实
[按话题匹配注入]
</stable_profile>
<dynamic_profile> ← PowerMem 自动学习
[AI 从对话中提取的印象]
</dynamic_profile>
优先级:stable 高于 dynamic,冲突时以 stable 为准
</memory>
稳定层(你维护)¶
- 来源:
stable_profile.txt(位于服务器数据目录) - 格式: 6 个
<topic>话题块 +_default兜底块 - 基本信息(年龄、身高、体重)
- 学习(RAZ、英语、游泳)
- 生活作息(睡眠时间)
- 兴趣爱好(动画角色)
- 社交(家人、手表、微信)
_default(简短概要,话题不命中时兜底)- 匹配方式: 用户消息关键词 → 命中对应话题块
- 聊 RAZ → 只注入"学习"块,省 token
- 聊叶罗丽 → 只注入"兴趣爱好"块
- 都不命中 → 仅注入
_default - 更新方式: 直接覆盖文件,下一句话立即生效(无需重启容器)
- 备份: 同目录
stable_profile.txt.bak - 路径:
/opt/xiaozhi-esp32-server/data/stable_profile.txt - 权限: 同目录其他配置文件一致
动态层(AI 自动)¶
- 机制: 对话完成后
save_memory()分成三步: - [PATCH7] 去重(MD5)→ 过滤无意义词(拜拜/再见等)→ 写入
memories表(payload 存原始对话,vector 列存 1536 维嵌入向量) - [中修] 从最近 5 条记忆拼成 profile → 更新
user_profiles表 → 清除last_profile_content缓存,下次对话重新读取 - [深修] 嵌入前清洗文本(去"苏子桐说:"/"小樱桃回答:"前缀 + 去表情符号),只对事实核心调用智谱
embedding-3API 生成向量 - 数据源: 智谱
embedding-3+https://open.bigmodel.cn/api/paas/v4/ - 配置路径: 容器内
/opt/xiaozhi-esp32-server/data/.config.yaml→Memory.powermem.embedder.config - 冲突时:
stable_profile优先
持久化说明¶
修改桥接器参数 → 直接改 /app/config.py + 重启容器
/app/config.py ← 桥接器参数(VAD/唤醒词),bind mount 挂载
/app/xiaozhi/services/audio/codec.py ← 音量增益 audioop.mul,直接改
服务器端:
/opt/xiaozhi-esp32-server/data/.config.yaml ← 服务器参数
/opt/xiaozhi-esp32-server/data/init_and_run.py ← 启动补丁(音量增益 + 模糊匹配 + 记忆保存)
/opt/xiaozhi-esp32-server/core/utils/util.py ← 音量增益(init_and_run 启动时打补丁)
/opt/xiaozhi-esp32-server/core/connection.py ← 模糊匹配 + 记忆保存(init_and_run 启动时打补丁)
故障排查¶
| 症状 | 可能原因 | 检查 |
|---|---|---|
| 没声音 | VAD 门槛太高 / 音量太低 | 检查 threshold 和 gain |
| 破音 | 总增益过高 | 总增益 ≥ +18dB 时有削顶风险 |
| 回答太长被截断 | VAD min_silence 太长 | 检查 server 和 bridge 的 min_silence |
| 反复触发/频繁打断 | threshold == threshold_low | hysteresis 双阈值需保持差距 |
| 沉默不答 | TTS 超时 / ASR 超时 | 检查日志中的 timeout |
| 答非所问/说胡话 | PowerMem 污染 / model 不可用 | 检查 LLM 响应 + API key |
| 名字念错/叫不对 | ASR 听歪 + 模糊匹配没兜住 | 缺的角色名加到 hotwords.txt(122条) |
ASR 热词与模糊匹配¶
Hotwords + 拼音模糊匹配,两层兜底。
第一层:后处理模糊匹配(connection.py _fuzzy_correct_names)¶
ASR 完成后、LLM 处理前,接管文本做角色名修正:
| 策略 | 匹配条件 | 示例 |
|---|---|---|
| 精确匹配 | seg == hw | 海绵宝宝 → ✅ |
| 编辑距离 ≤ 1 | 2字名首字必须相同(防误匹配) | 赛咯 → 赛罗 ✅ / 和迪↛巴迪 ✅ |
| 拼音完全相同 | 编辑距离 ≥ 2 但拼音去声调后一致 | 赛箩 → 赛罗 ✅(同音) / 紫曰 → 紫悦 ✅ |
拼音匹配的额外收益: 多音字、口齿不清、同音别字全部覆盖。 防误匹配:2字名编辑距离=1时首字不同不匹配(防
和迪→巴迪)。
数据源:hotwords.txt¶
- 路径:
/opt/xiaozhi-esp32-server/data/hotwords.txt - 当前:122 个名字(奥特曼/小马宝莉/叶罗丽/迪士尼等角色)
- 特点:文件式动态加载,无需重启容器,改完即生效
- 更新方式:直接编辑文件或告诉我加角色名
文件位置¶
| 文件 | 用途 | 持久化方式 |
|---|---|---|
connection.py |
实时代码(_fuzzy_correct_names) |
init_and_run.py 启动补丁 |
init_and_run.py |
容器重启后补丁代码 | 挂载在容器内 |
hotwords.txt |
角色名列表(122条) | bind mount 挂载 |
变更日志¶
铁律:改参数必更新¶
任何涉及小樱桃代码、配置、参数的变更,必须同步更新本 SOP 对应章节。 不改 SOP-001 视为变更未完成。
检查清单: - [ ] VAD 参数变了? → 更新参数表 - [ ] 音量增益变了? → 更新参数表 - [ ] 模型/API变了? → 更新模型配置 - [ ] 角色设定变了? → 更新角色设定 - [ ] 排查流程新增了? → 更新故障排查 - [ ] 版本日志追加了一笔
| 日期 | 版本 | 变更 |
|---|---|---|
| 2026-07-06 | v1 | 初版,基线参数固化 |
| 2026-07-08 | v2 | 新增 ASR 热词拼音模糊匹配章节 |
| 2026-07-08 | v3 | 修正音量参数(1~4# 分组)、VAD 值对齐实际运行值、更新 TTS/CosyVoice2 模型配置、更新持久化文件路径 |
| 2026-07-08 | v4 | 桥接器 VAD 初调:threshold 0.10→0.20,threshold_low 新增0.15,min_speech 250→300ms |
| 2026-07-08 | v5 | 稳定状态:VAD 全部还原(0.10/0.01/250ms),仅留 min_silence=1000ms;唤醒改用"嗯!"+0.5s缓冲;TTS key 修正(硅基流动);prompt 讲故事不中断;SOP 记录 VAD 参数和唤醒流程 |
| 2026-07-09 | v6 | 用户画像重构:双层注入(stable_profile.txt + PowerMem),年龄定位修正为"永远比苏子桐大2岁",反哺机制从向量切片改为文件直接注入 |
| 2026-07-10 | v8 | PowerMem 三层加固:①PATCH7(去重+过滤无意义词+直写 SQLite)②中修(对话后刷新 user_profiles 表)③深修(修正 embedder 配置字段名 + 清洗嵌入文本去前缀表情 + 真实 1536 维向量写入)。语义搜索从空向量升级为智谱 embedding-3 全链路。 |
相关文档¶
| 方向 | 链接 |
|---|---|
| 🔗 输入 | SOP-004 融合画像更新(反哺来源) · SOP-003 雷达扫描与推送(日志归档) |
| 🔗 输出 | 最新画像(反哺目标) |
| 📝 变更 | 版本日志 |