智能语音送餐机器人交互系统(客户端-服务器版)
面向送餐/服务机器人的全链路语音交互系统:热词唤醒、SeacoParaformer 语音识别、意图槽位联合模型、ERes2Net 声纹鉴权、Matcha-TTS 合成与在线/离线双栈 LLM 对话
智能语音交互机器人系统 — 技术文档(代码梳理版)
系统名称:小七智能语音交互机器人 版本:v3.0(代码梳理版,依据 2026-09 代码实况整理)
目录
- 系统概述
- 总体架构与进程模型
- 客户端-服务器工作模式与部署形态切换
- 所用模型与技术栈清单
- 音频采集与传输链路
- 唤醒词检测
- 语音活动检测与实时语音分段
- 自动语音识别(ASR)与热词匹配
- 意图与槽位解析
- 声纹识别子系统
- 主控状态机
- 送餐模式(AGV)实现逻辑
- 娱乐模式(LLM 对话)实现逻辑
- 语音合成(TTS)
- MQTT 订单发布(可选)
- DeepFilterNet 降噪(可选)
- 关键阈值与参数速查
- 部署与运行
- 核心技术总结与能力矩阵
1. 系统概述
本系统是一套面向送餐/服务机器人的全链路语音交互软件,打通了“远程客户端收音 → 唤醒 → 识别 → 意图理解 → 声纹鉴权 → 指令执行 → 语音回复”的完整闭环。
核心功能点:
- 语音唤醒:离线热词检测,默认唤醒词“小七小七”,可区分“静默监听态”与“对话打断态”两种触发语义;
- 语音活动检测(VAD):基于 Silero VAD + 实时能量/过零率双重机制做流式断句;
- 语音识别(ASR):FunASR 的 SeacoParaformer(ONNX 量化版),支持中文热词注入;
- 意图理解:意图/槽位联合模型(JointBERT 式)+ 规则回退,输出命令意图与槽位(房间、楼层、子意图等);
- 声纹注册与验证:3D-Speaker 系列 ERes2Net 模型,多特征注册、质量评估、余弦相似度匹配,用于命令鉴权(“谁在下指令”);
- 多模式运行:送餐模式(AGV)与娱乐模式(ENT)两种工作模式,可语音切换;
- 大模型对话:本地 Qwen2.5-7B(GGUF)与云端豆包(火山方舟)双后端,按网络情况自动切换;
- 语音合成(TTS):Matcha-TTS(ONNX 声学模型 + Vocos 声码器)离线合成;
- 客户端-服务器架构:工控机侧负责麦克风阵列收音与扬声器播放,主机侧完成全部语音与业务处理,通过 ZeroMQ(TCP)互联,并可在“分布式 / 单机独立 / 一主机多客户端”三种部署形态间按需切换。
1.1 核心技术速览
| 核心技术 | 实现要点 | 带来的能力 |
|---|---|---|
| 边缘—中心解耦的客户端-服务器架构 | 音频 IO 放工控机,全部模型推理集中到服务器,ZeroMQ(TCP)消息总线互联 | 机器人端免 GPU、模型集中维护、一套算力主机可带多台机器人、部署形态可切换 |
| 全链路流式流水线 | 0.1 s 帧级采集→分发→唤醒/识别→合成→下发播放,全程无“录完整段再处理” | 端到端低时延,说话结束即出结果 |
| 热词驱动的唤醒/识别一体化 | SeacoParaformer 热词注入 + 能量证据防幻觉 + 静默/打断双触发语义 | 唤醒率高、误唤醒低,播报中可随时打断重唤 |
| 双保险实时断句 | 自适应噪声地板(RMS/峰值/过零率) + Silero VAD 复核 + 段前补音 | 嘈杂餐厅环境下切点准确、不丢首字 |
| 声纹多特征注册与质量加权融合 | ERes2Net-Large 192 维嵌入 + SNR 质量评估 + 5 种融合策略 + 全特征匹配 | 命令级“谁在下指令”的鉴权,抗口音与响度漂移 |
| 意图槽位联合模型 + 多级确定性约束 | JointBERT 式联合模型 → 规则回退 → 工作模式过滤 → 房间白名单校验 | 听懂命令且不会越权/误执行 |
| 在线/离线双栈与网络自适应热切换 | 核心链路全离线;开放域对话按 TCP 探活在“云端豆包 ↔ 本地 Qwen2.5-7B”间每轮自动切换 | 有网更聪明、断网仍可用,切换无感、无需重启 |
| 集中式 TTS 与全局打断仲裁 | 单一发声点 + 会话号 + 取消集合 + 清空播放队列指令 | 任意时刻可打断,音量全局一致 |
| 异步事件驱动状态机与活动心跳 | asyncio 单线程仲裁,超时自动回待机、语音活动续期 | 不会“话说一半被踢回待机” |
| 订单可靠投递 | 本地订单日志为唯一事实源 + 增量索引发布 + 断线重连 + QoS 1 | 断网不丢单,恢复后增量补发不重复 |
2. 总体架构与进程模型
系统采用 多进程 + ZeroMQ 消息总线 的模块化架构。一个统一的启动脚本按顺序拉起多个独立 Python 进程,进程之间不共享内存,全部通过 ZeroMQ 的 PUB/SUB、PUSH/PULL、REQ/REP 三种模式按既定端口收发消息。
2.1 进程分工
| 进程文件 | 角色 | 职责 |
|---|---|---|
audio_capture.py | 服务端音频入口 | 接收来自客户端(工控机麦克风阵列)的 16 kHz 音频流,按“识别是否激活”扇出给唤醒与识别两条链路,可选开启服务器侧 AGC 与降噪 |
wakeword_detector.py | 唤醒线程 | 常驻监听音频流,流式热词 ASR 判定唤醒词,带能量证据校验防止静音幻觉,唤醒后把事件推给主控 |
recognition.py | 识别主进程 | 唤醒后激活,负责流式断句、ASR 识别、意图解析、声纹验证、命令路由(送餐/娱乐/音量/门控) |
controller.py | 主控/仲裁 | asyncio 事件循环状态机,仲裁各模块,控制唤醒/识别启停、TTS 播放、客户端音频下发、超时管理 |
ent.py | 娱乐进程 | 处理娱乐子意图:自我介绍、闲聊大模型对话、音乐播放等,仅回传文本片段 |
agv.py | 送餐进程 | 处理送餐导航/订单/充电/门控等命令,累积订单、输出订单协议 JSON,请求主控播报 |
tts_utils.py | TTS 库 | 被 controller 等调用的离线语音合成与管理(非独立进程) |
mqtt_publisher.py | MQTT 发布(可选) | 监控订单文件,把订单通过 MQTT 发布到业务服务器 |
client/client.py | 客户端播放端 | 接收主控下发的语音/音乐音频流并播放,支持打断 |
client/client_mic.py | 客户端采集端 | 在工控机上用 arecord/sounddevice 采麦克风阵列,预处理后推送到服务器 |
2.2 消息端口分配
| 端口 | 模式 | 用途 |
|---|---|---|
| 5554 | PUB(audio_capture) | 唤醒进程订阅的实时音频流 |
| 5557 | PUSH(wakeword_detector→controller) | 唤醒事件推送 |
| 5559 | REP(wakeword_detector) | 唤醒进程控制口(start/stop/set_idle/get_status) |
| 5558 | PULL(recognition) | 识别进程接收音频帧(识别激活时) |
| 5562 | REP(recognition) | 识别进程控制口(start/stop_recognition、set_param) |
| 5575 | PUSH(recognition→controller) | 识别语音活动心跳 |
| 5569 | PUSH(recognition→ent) | 娱乐命令转发 |
| 5570 | PUSH(ent→controller) | 娱乐回复/音乐数据回传 |
| 5571 | REP(ent) | 娱乐进程控制口(stop 打断等) |
| 5572 | PUSH(recognition→agv) | 送餐/音量/拒绝等命令转发 |
| 5573 | PUSH(agv→controller) | AGV 完成通知 / TTS 请求 / 音量请求 |
| 5574 | REP(agv) | AGV 进程控制口 |
| 5556 | REP(audio_capture) | 音频采集控制口(start/stop_recognition、clear_queue) |
| 5553 | PUB(controller→客户端) | 客户端播放订阅(语音、音乐、清空队列指令) |
| 5567 | PULL(audio_capture,服务器) | 客户端采集端推流接入(可选降噪直通链) |
2.3 主数据流
客户端采集(麦克风阵列) ──TCP 5567──> audio_capture(扇出)
├─ PUB 5554 ──> wakeword_detector(常开监听)
└─ PUSH 5558 ─> recognition(唤醒后激活)
│ ASR+意图+声纹
┌──────────────────────┼──────────────────┐
娱乐命令(5569) 命令(5572) 唤醒(5557)
│ │ │
ent.py agv.py controller(状态机)
└──文本/音乐─5570───> └──TTS请求/完成─5573─> │
├─ TTS 合成(tts_utils)
└─ PUB 5553 ──> 客户端播放
3. 客户端-服务器工作模式与部署形态切换
系统在架构上把“音频 IO”与“AI 计算”彻底解耦:所有模型(VAD / ASR / 声纹 / 意图 / TTS / LLM)只部署在服务器侧,工控机(机器人本体)只保留“麦克风阵列采集”与“扬声器播放”两个薄客户端,两端通过 TCP 承载的 ZeroMQ 互联。同一套代码可在多种部署形态之间按需切换,切换只改环境变量与主控开关,不改代码。
3.1 三种部署形态
| 形态 | 适用场景 | 切换方式 | 说明 |
|---|---|---|---|
| A. 分布式客户端-服务器(默认) | 正式部署:机器人本体算力弱、需要集中算力与统一维护 | 工控机运行采集端 + 播放端;服务器按常规拉起全部服务端进程 | 麦克风阵列在工控机,全部推理在服务器,中间走 TCP |
| B. 服务器单机闭环 | 无工控机、实验室调试、断网演示 | 不启动客户端;主控关闭“下发客户端”开关,回复改由服务器本机声卡播放;服务器音频入口可打开本地播放回环 | 不依赖任何网络,单台机器跑通完整交互链路 |
| C. 一服务器多客户端 | 多台机器人共用一台算力主机 | 每个客户端以唯一 ID 标识,下发消息可携带目标 ID 定向分发 | 服务器侧模型只加载一份,边际成本随机器数量递减 |
形态切换依赖的配置项:客户端侧改 VOICE_SERVER_IP / VOICE_SERVER_PORT 指向不同服务器;服务器侧改接入绑定地址、是否开启下发、是否开启本地播放、是否开启降噪与 AGC、客户端 ID 等。同一份代码库、同一份模型目录,三种形态通用。
3.2 采用客户端-服务器模式的优点
- 算力与硬件解耦:机器人本体(工控机)无需 GPU,只做采集与播放;加重模型、换显卡、扩容只需动服务器。
- 模型与策略集中维护:模型文件、热词表、声纹库、意图标签、话术文本、阈值参数全部在服务器单点更新,所有机器人即时同步生效,避免逐台烧录/升级。
- 一套算力服务多台机器人:形态 C 下模型只加载一份,新增机器人的边际成本极低;同时便于做统一日志、统一运营统计。
- 故障隔离、模块可独立重启:进程间只通过消息总线通信、不共享内存,任一进程(甚至客户端整机)异常退出,其余模块不受影响;重启后重新连上总线即可继续工作,PUB/SUB 广播本身无状态,客户端断线重连无需服务端配合。
- 实时性可控且可调:音频按 0.1 s 帧传输,收发端均设高水位(HWM)与应用队列上限,队列满丢最旧帧——“宁可丢旧帧,也不让链路卡住”,保证交互永远是“当下”的;HWM、队列长度、AGC 目标、播放恢复提前量等全部可用环境变量热配。
- 远端可控与集中仲裁:主控可远程下发“清空播放队列/打断”“音量增益”“定向播报”等指令,保证多客户端场景下不会出现“各说各话”。
- 安全与资产保护:云端 API 密钥、模型权重、声纹库均只保存在服务器,机器人端不落地任何密钥与模型资产。
- 调试友好:可单独启动任一进程定位问题;服务器侧可开启音频存盘、本地播放回环、状态查询接口,快速判断问题是出在“前端采集/传输”还是“算法/业务”。
3.3 客户端角色
- 采集端(client_mic):运行在带麦克风阵列的工控机上。
- 优先调用系统
arecord子进程读麦克风阵列原始 PCM(支持多档位自动回退:设备、采样率、位深、声道数逐级尝试),也可用 sounddevice 回调方式采集; - 采集后做数字预处理:多声道取单声道、格式换算、按目标采样率重采样到 16 kHz、直流(DC)滤除、自动增益控制(AGC,以目标 RMS 反馈调节增益)、可选的噪声门限/预加重;
- 分帧(0.1 秒/帧)放入本地队列,由独立发送线程通过 ZeroMQ 推送到服务器 5567 端口;队列满时丢旧帧保实时性;
- 客户端带唯一 ID(可用环境变量指定,否则取本机 IP),便于服务器端日志区分。
- 优先调用系统
- 播放端(client):订阅服务器 5553 端口的广播:
- 收到“语音回复/音乐回复”消息时取出音频数据并声卡播放(支持 int16/float32 两种编码);
- 内部维护播放队列与“打断”标志,收到清空队列指令立即停播并丢弃队列;
- 支持定向分发:消息若带指定客户端 ID,仅对应客户端执行,其余忽略。
3.4 服务器侧接入
audio_capture.py 作为服务器音频入口,默认“直通转发”客户端已归一化好的 16 kHz float32 流,不做二次处理(保证 arecord 链路原真度);也可通过环境变量打开服务器侧 AGC 与 DeepFilterNet 降噪。收到一帧音频后:唤醒链路恒常转发(PUB 5554);识别链路仅在“识别激活”时转发(PUSH 5558)。
音频处理链可插拔(按环境一键切换,无需改代码):
| 开关 | 默认 | 作用 |
|---|---|---|
| 直通转发 | 开 | 保真、零额外算力,噪声已由客户端预处理过时的首选 |
| 服务器侧 AGC | 关 | 远端音量过小时在服务器端二次增益(目标 RMS、最大增益、峰值限幅可调) |
| DeepFilterNet 降噪 | 关 | 高噪环境开启,语音段更干净,代价是额外算力与时延 |
| 本地播放回环 / 音频存盘 | 关 | 调试用:服务器本机回放或落盘语音段 |
3.5 链路容错与降级
- 采集端自愈:arecord 参数组合(设备/格式/采样率/声道)逐档自动回退;阵列设备需保活时用静音播放 keepalive 防止休眠;读取超时自动重启采集子进程,网络瞬断后自动重连服务器。
- 传输层保实时:发送/接收高水位 + 应用队列上限,队列满丢弃最旧帧;发送超时不阻塞采集线程,避免“断网时堆积、恢复后爆音”。
- 播放端可打断:收到“清空播放队列”立即置打断标志、停播并丢弃队列;兼容 int16 / float32 两种编码与任意声明采样率。
- 无客户端可降级:形态 B 下关闭下发、改服务器本地播放,即使完全没有网络,唤醒→识别→意图→声纹→TTS 的核心闭环依然完整可用。
4. 所用模型与技术栈清单
| 能力 | 模型/技术 | 运行引擎 | 网络依赖 | 文件/资源 |
|---|---|---|---|---|
| 语音活动检测 | Silero VAD | sherpa-onnx | 离线 | model/silero_vad.onnx |
| 语音识别 | SeacoParaformer(热词增强) | funasr_onnx(ONNX,GPU/量化) | 离线 | model/paraformer-zh |
| 声纹识别 | 3D-Speaker ERes2Net-Large(中文 SV,192 维) | sherpa-onnx SpeakerEmbeddingExtractor(ONNX) | 离线 | model/3dspeaker_..._16k.onnx |
| 意图/槽位 | JointBERT 式意图槽位联合模型 | PyTorch 推理 | 离线 | modeltest/model/model_epoch1499 + tokenizer |
| 本地 LLM(离线兜底) | Qwen2.5-7B-Instruct | llama-cpp-python(GGUF,q2_k 量化) | 离线 | tts_models/qwen2.5-7b-instruct-q2_k.gguf |
| 云端 LLM(在线增强) | 豆包 Doubao(火山方舟,可带联网搜索工具) | OpenAI SDK(HTTP 流式) | 需外网 | doubao_api.py 封装 |
| 语音合成 | Matcha-TTS 中文 + Vocos 声码器 | sherpa-onnx OfflineTts | 离线 | tts_models/matcha-icefall-zh-baker/ |
| 数字规范化 | FST 规则(数字/日期) | sherpa-onnx rule-fsts | 离线 | tts_models/matcha-.../*.fst |
| 降噪(可选) | DeepFilterNet3 | torch | 离线 | DeepFilterNet/ |
| 音乐播放 | 本地音频文件解码/重采样 | pydub + numpy | 离线 | music/ 目录 |
| 进程通信 | ZeroMQ(PUB/SUB、PUSH/PULL、REQ/REP) | pyzmq | 局域网 | — |
| 机器人通信 | MQTT(可选)/ 订单协议文件 | paho-mqtt | 局域网 | — |
4.1 在线/离线双栈与网络自适应切换(核心技术)
系统按“核心链路全离线、增值能力在线增强”的原则设计,把网络依赖收敛到极少数可选环节:
| 层级 | 能力 | 有网 | 无网 | 切换方式 |
|---|---|---|---|---|
| 核心链路 | 唤醒、VAD、ASR、意图槽位、声纹注册与验证、TTS、送餐/音量/模式切换 | 本地模型 | 本地模型(完全一致) | 无需切换,恒离线可用 |
| 固定话术娱乐 | 自我介绍、年龄、籍贯、音乐播放 | 本地文件/本地计算 | 同左 | 无需切换 |
| 开放域对话 | 闲聊、百科、故事、笑话、实时信息 | 云端豆包(支持联网搜索,质量更高) | 本地 Qwen2.5-7B(GGUF 量化,CPU 可跑) | 每轮对话前自动探活切换 |
| 业务上送 | 订单下发布局 | MQTT 发布(QoS 1) | 本地订单日志缓存 | 断线重连后增量补发 |
LLM 后端切换机制:
- 进程启动时同时初始化两个后端:本地 Qwen(llama-cpp 加载 GGUF)与云端豆包(OpenAI 兼容 HTTP 客户端);云端后端初始化失败(模块缺失、Key 无效)只降级为“仅本地”,不影响进程启动;
- 两个后端实现统一的流式生成接口(
stream_generate:输入用户文本与系统提示,输出文本流,支持停止回调),上层业务对“用的是哪个模型”完全无感; - 每轮对话前做一次轻量网络探活(向公网 443 端口发起短超时 TCP 连接,默认 3 秒),成功走云端豆包、失败走本地 Qwen;
- 判定是每轮进行的:断网时下一句自动回落本地,网络恢复后下一句自动回到云端,全程无需重启进程、无需人工干预;
- 云端侧还有一层“本地规则优先”:自我介绍、公司介绍等固定话术直接本地命中返回(零延迟、零流量),需要实时信息时才调用联网搜索工具,其余走关闭思考的“快速模式”,在质量与响应速度之间取平衡;
- 兜底顺序可概括为:本地固定话术 → 云端大模型(有网)→ 本地大模型(无网/云端异常),任何一层失效都有下一层接住,用户侧表现为“永远有回应”。
订单链路断网不丢单:订单先落本地 orders_log.json(唯一事实源),MQTT 发布器以“记录数增量”为索引只发新增项;Broker 断开时进入重连循环、WiFi 由 nmcli 自动回连,恢复后从断点继续发布,不重复推送历史订单。
5. 音频采集与传输链路
- 统一帧格式:16 kHz、单声道、0.1 秒/帧(1600 样本),帧内带时间戳与序号;
- 唤醒线程维护约 1.6 秒的滑动音频缓冲,供流式热词检测;
- 识别线程维护“历史音频环”(前缀窗口),用于在语音段开始时补上说话前约 0.45 秒的音频,避免因端点检测滞后丢失声母/首字;
- 识别进程按序号校验连续性,乱序/丢帧时做状态复位,保证断句正确;
- 全程可开关:存盘调试(保存语音段 WAV)、本地播放回环等。
6. 唤醒词检测
采用“热词驱动的流式 ASR 唤醒”而非独立的关键词检出模型:
- 把唤醒词“小七小七”作为热词注入 SeacoParaformer,模型对滑动窗口音频持续做短句识别,识别文本命中唤醒词即触发;
- 触发语义分为两种:
- 静默监听态(IDLE):识别文本须与唤醒词严格一致才唤醒,避免日常语误唤醒;
- 对话打断态(非 IDLE):允许唤醒词作为识别文本子串出现,便于在对话/播报中随时打断重唤;
- 防幻觉机制:对命中音频做能量证据校验(整段 RMS、峰值、有声帧占比需同时达标),过滤模型在静音下的“幻觉输出”;
- 唤醒成功后仅把“唤醒事件”(含识别文本来源与能量证据)推送主控,由主控统一协调后续动作(停唤醒、清播放队列、进入监听识别态);
- 唤醒进程本身亦暴露控制口,可启停检测、查询状态。
7. 语音活动检测与实时语音分段
识别进程内部用“模型 VAD + 信号特征”双保险做实时断句:
- 信号特征判定语音起止:对每帧计算 RMS 能量、峰值、过零率,并维护自适应“噪声地板”。起点判定要求能量/峰值超过门限或相对噪声比达标(连续若干帧);终点判定要求能量跌回低门限且静音持续到设定时长。此机制比纯 VAD 更抗噪、切点更准;
- Silero VAD 复核:sherpa-onnx 加载 Silero VAD,做段级辅助校验与最小/最大语音时长约束(过短丢弃、过长截断);
- 语音段组装:一段完整话语由“前导缓冲 + 模型/能量判定出的核心语音”组成;说话中间短暂停顿(静音间隙阈值内)自动并入同一句,避免把一句切碎;
- 前缀补音:段落起始时间确定后,从历史音频中取该时刻前一小段(约 0.45 秒)拼接进语音段,再整体送识别;
- 分帧同时记录时间戳,供后续“命令结果与声纹结果按段配对”。
8. 自动语音识别(ASR)与热词匹配
- ASR 用 SeacoParaformer(ONNX 热词版),批量 1、GPU 推理、INT8/量化可选;
- 热词注入:把“当前场景下的高频词汇”(默认是餐厅房间名单:积厚厅、韶华厅、云程厅、行远厅、观潮厅、员工间)作为热词,显著提升专有名词识别率;
- 识别引擎以回调方式上报“命中热词 + 识别文本 + 段落元数据”,识别进程在回调里做命令级过滤与匹配打分:
- 对每个命中,依据文本与词表的匹配度给出置信分,低于设定阈值(默认 0.6)的丢弃;
- 识别链路识别出的唤醒词一律丢弃(唤醒只归唤醒线程管,防重复触发);
- 二次确认:部分场景下还做语音是否真正结束的复核,防止把环境噪声尾音当命令。
9. 意图与槽位解析
ASR 文本出来后送入意图/槽位联合模型(JointBERT 式,tokenizer + 训练好的意图/槽位标签),一次前向得到:
- 顶层意图:送餐导航、提交订单、取消订单、充电、门控(开门/关门)、娱乐、模式切换、音量、唤醒、提示等;
- 槽位:房间名、楼层(一二三四层)、娱乐子意图、音量方向等。
解析结果与规则相结合(例如“有效送餐房间名单”过滤、“有效楼层映射”),再叠加当前工作模式过滤:
- 送餐模式下只放行送餐/订单/充电/门控类意图,娱乐意图被拦截;
- 娱乐模式下反之;
- 模式切换命令立即生效并广播提示语,不进入业务处理队列。
10. 声纹识别子系统
这是“注册声纹 + 声纹验证”的核心,覆盖注册工具、数据库、质量评估、流式匹配四个部分。
10.1 声纹模型与相似度度量
- 特征模型:ERes2Net-Large(中文说话人验证版),ONNX 推理,输入 16 kHz 语音,输出 192 维说话人嵌入向量,提取后立即做 L2 归一化;
- 相似度:因向量已归一化,直接计算内积即等价余弦相似度;
- 阈值:默认匹配阈值 0.4,置信度高于阈值才认定“是某人”,可运行时动态调整;
- 推理引擎为 sherpa-onnx 的 SpeakerEmbeddingExtractor,优先 CUDA,无可回退 CPU。
10.2 声纹数据库
- 持久化两个文件:一个人类可读的元数据 JSON(含每个特征的注册时间、质量分、时长、对应录音文件等)与一个二进制库文件(版本化,兼容旧格式自动迁移);
- 数据模型为“一人多特征”:每个说话人名下可追加多条注册特征(多次录音),每条特征都保留来源录音文件路径,供复核与重算;
- 匹配模式两种:
- 融合特征模式:把名下全部特征合并为单个代表向量再比对;
- 全特征模式:逐条特征比对取最高分(识别主进程采用此模式,抗口音/响度漂移);
- 特征合并提供五种策略,均做 L2 归一化:
- 等权平均;
- 按注册质量加权(低质量特征自动降权);
- 按时间新鲜度加权(约 30 天半衰期衰减,越新越重要);
- 按“与其它特征差异度”加权(鼓励保留环境多样性);
- 混合策略(质量/时间/多样性按比例合成,注册默认采用)。
10.3 音频质量分析(注册把关)
注册前对整段录音做质量评估,核心指标为 SNR 信噪比(FFT 划分语音带与噪声带估算),辅以静音判定:
- 按 SNR 划分等级(优秀≥30dB、良好≥20dB、一般≥10dB、差≥5dB、极差/静音);
- 折算 0–100 质量分,并给出改进建议(如“安静环境”“靠近麦克风”);
- 门槛策略:质量分极低(静音或噪声淹没)直接拒绝注册;中等偏低时告警但放行,避免误杀口音/远场用户;
- 关闭质量检查时给默认偏高的分数。
10.4 说话人注册流程(命令行工具 / GUI 均可触发)
- 用户输入姓名;
- 麦克风录音固定时长(默认 5 秒)16 kHz 单声道音频;
- 质量评估(可关);
- 直接从整段音频提取 192 维声纹向量并归一化(GUI 增强版可选“先 DeepFilterNet 降噪、再 Silero VAD 裁出有效语音段、拼接后提特征”,进一步提升注册音质);
- 录音存档为 WAV;
- 写入数据库:新名字建条目;老名字追加为第 N 条特征并重算融合向量(默认不覆盖,除非显式开启覆盖模式先清后加);
- 注册成功后回显当前库内说话人清单。
10.5 声纹验证(识别链路鉴权)
识别进程中,声纹识别在独立工作线程处理,与 ASR 并行不阻塞:
- 对每个切好的语音段,在说话期间用滑窗(窗口内能量高于下限时)周期性提取嵌入向量并做库内匹配,得到“说话人名 + 置信度”;
- 识别命令与声纹结果按“语音段 ID”配对;任何一方就绪即触发合并尝试;
- 鉴权策略:
- 库里没有任何注册说话人 → 不校验,直接放行(调试/冷启动);
- 库里有注册说话人 → 声纹未匹配到人、或置信度低于阈值 → 命令被拒绝,生成“拒绝”事件通知送餐进程,由机器人语音回应“声纹验证未通过”;
- 匹配通过 → 命令携带说话人 ID 与置信度下发给送餐进程;
- 娱乐/音量类命令不强制声纹(娱乐无需鉴权、音量人皆可调);
- 队列满等异常情况会显式放弃该段声纹任务并丢弃对应命令,避免张冠李戴;
- 识别被唤醒词打断、重新 start 时,会清空所有未配对结果与分段上下文,杜绝旧段串扰。
10.6 流式识别模式与工具
- 声纹类本身亦提供流式接口(喂帧回调识别结果),供其它接入点复用;
- 语音段累积器与“语音起始探测器”(能量 + 过零率双阈值)保证只对真正开口后的音频提特征;
- 命令行工具(麦克风录音 → 注册)、GUI 图形化注册/识别界面均存在,二者共享数据库,可并行使用。
11. 主控状态机
主控是唯一权威仲裁者(asyncio 单线程事件循环),维护三个状态,通过控制口统一下发指令给各进程:
| 状态 | 含义 | 行为 |
|---|---|---|
| IDLE | 待机 | 停止识别、清播放队列、唤醒线程处于“严格匹配”监听态 |
| AWAKE | 已被唤醒、可对话 | 停止唤醒检测、启动识别与播放链路;8 秒无有效活动自动回 IDLE(期间检测到语音活动/有效命令会续期) |
| ENTERTAINMENT | 娱乐对话中 | 关闭 AWAKE 超时,改为“娱乐空闲监视”(默认 10 秒无活动自动退出);TTS 播报期间暂停识别,播完恢复 |
关键机制:
- 唤醒处理:收到唤醒事件先去重(短时间重复唤醒忽略);依据当前状态决定进入 AWAKE、打断娱乐(向娱乐进程发停止、取消其会话)、或在 AWAKE 下重应答并续期;
- TTS 播放时序:回复音频先合成并整体下发客户端播放,播放期间暂停识别防自听;播完按“音频时长 + 可配余量 − 提前量”的时序提前恢复识别,减少用户紧接着说话的丢句;
- 打断:任何新播报/唤醒/命令前先向客户端广播“清空播放队列”,实现即时打断;
- 音量控制:解析音量调大/调小指令,在主控上维护 TTS 增益系数(步进调节、上下限保护),实时改 TTS 音量并播报确认;
- 活动心跳:识别进程持续上报语音活动,主控据此续期超时,避免用户话还没说完就被踢回待机。
12. 送餐模式(AGV)实现逻辑
送餐进程接收识别进程转发的命令(含说话人 ID 与置信度),逐类处理:
- 导航:从槽位解析房间名与楼层;楼层缺省、房间缺失分别回话询问;构造“送某层某房间”的确认话术并请求主控播报;
- 订单累积:多轮送餐指令在会话内累积成“目标房间 + 各楼层点单”的订单列表;
- 提交订单:把订单拼成结构化订单协议(JSON),追加写入订单日志文件,供后续 MQTT 发布或其它业务系统读取;
- 取消/充电/门控:清空累积、回充电确认话术、按槽位中的动作播报“开门/关门”等;
- 拒绝:收到声纹不匹配的拒绝事件时,播报“声纹验证未通过”,不下发任何业务动作;
- 提示广播:模式切换等提示语直接请求主控 TTS 播报;
- 所有处理完成后向主控回“命令完成”通知,主控据此恢复识别并续期超时;音量调整请求则转交主控改增益;
- 说明:本版本中“送餐指令执行”落点为订单协议生成与确认话术,与实体 AGV 底盘的实际运动控制解耦(通过订单文件/后续接口对接),控制口与完成口保留以兼容联动。
13. 娱乐模式(LLM 对话)实现逻辑
娱乐进程只处理“娱乐子意图”,输出文本片段/音乐音频,由主控统一转语音,自身不再发声:
- 子意图路由:介绍、年龄、籍贯、音乐、其它(闲聊/百科/故事等)分别路由到对应处理器;
- 自我介绍:从本地文本文件读取预设介绍语,按句切分逐句回传,实现“边说边播”;
- 多大了:以固定“出生日期”为基准,用当前日期动态计算岁/月并组织成自然语句,纯日期计算不调模型;
- 来自哪里:读取本地预设文本逐句播报;
- 音乐:从音乐目录随机挑选音频文件,解码 → 转单声道 → 重采样到统一采样率 → 归一化,作为音频帧直接回传主控下发给客户端播放;播放时长内可被新指令打断;
- 大模型对话(闲聊/百科类):抽象“LLM 后端”接口,两个实现可在运行期热切换(详见 4.1):
- 本地后端:llama-cpp 加载 Qwen2.5-7B-Instruct 的 GGUF 量化模型(q2_k,CPU 可跑),按 Chat 模板流式生成;
- 云端后端:火山方舟豆包大模型(OpenAI 兼容 HTTP 接口流式生成,可挂联网搜索工具获取实时信息);
- 切换策略:每轮对话前做一次轻量外网探活(TCP 443,3 秒超时)——有网走豆包(质量更高、可联网),断网自动回落本地 Qwen;该判定逐轮执行,网络状态变化后下一句即自动切换,不重启进程、不中断会话;
- 三级兜底:本地固定话术(自我介绍/公司介绍等规则命中)→ 云端豆包(有网)→ 本地 Qwen(无网或云端异常),保证任何网络状态下都有回应;
- 云端后端初始化失败(依赖缺失/密钥无效)时进程仍以“仅本地”模式正常启动,并在日志中提示;
- 流式播报:LLM 输出按中文句末标点切句,逐句回传;先回“收到”确认再进入生成长文本,避免用户等得焦虑;
- 会话与打断:每次对话带会话号;新唤醒/新会话会取消旧会话(主控侧“取消集合”作废旧文本与音乐,播放中可即时切走);支持回复中途被控制口强制停止;
- 结束回传“完成”状态,主控据此恢复识别与超时逻辑。
14. 语音合成(TTS)
- 引擎:sherpa-onnx 离线 TTS,配置为 Matcha-TTS(中文 Baker 语料)+ Vocos 声码器,配套词表、词典与数字/日期规范化 FST 规则;
- 预处理:自动补齐句末标点——按问句词/感叹词特征自动选择问号或叹号,否则默认句号,让合成语气更自然;
- 后处理响度管理:合成后先按目标峰值归一化,再乘增益系数;可选允许轻微削波换响度(默认开启),增益可在主控上被音量指令实时修改并受上下限约束;
- 提供同步播报、异步播报、纯合成三种调用形态,并维护全局单例供各进程复用;
- 娱乐进程等历史版本曾经直接本地播放/自行合成,现行架构统一收敛为“只回文本 → 主控集中合成 → 下发客户端播放”,保证打断与音量控制全局一致。
15. MQTT 订单发布(可选)
- 监听订单日志文件,发现新订单即读取结构化协议并发布;
- MQTT 参数:Broker 地址(局域网服务器)、1883 端口、业务主题、QoS=1 保障送达;
- 附带 WiFi 管理:当处于无线环境时,自动检查并连接指定 SSID,保证发布通路;
- 支持断线自动重连、按索引增量发布(避免重复推送历史订单);
- 该进程默认未纳入统一启动列表,属可选外挂模块。
16. DeepFilterNet 降噪(可选)
- 提供实时降噪器(DeepFilterNet3,torch),支持本地麦克风输入与网络流输入两种模式;
- 处理链路:分块(帧/步进)降噪 → 带软限制的峰值限幅 → 输出;内部做采样率适配(16 kHz/48 kHz)与模型预热;
- 服务器音频入口可选在转发前插入降噪(网络输入模式,绑定同一 5567 端口);默认直通以保持链路原真,噪声大的环境可开启动态切换;
- 同时提供降噪后音频的旁路输出/回调,供注册流程做“先降噪再提声纹”的增强路径。
17. 关键阈值与参数速查
| 参数 | 默认值 | 用途 |
|---|---|---|
| 采样率 / 帧长 | 16 kHz / 0.1 s | 全链路统一 |
| 唤醒词 | 小七小七 | 唤醒触发词 |
| 命令匹配置信阈值 | 0.6 | ASR 热词命中打分下限 |
| 声纹匹配阈值 | 0.4 | 余弦相似度下限,低于则拒 |
| VAD 最小静音 / 最短语音 | 0.15 s / 0.2 s(模型级) | 断句与丢弃过短音 |
| 实时分段静音收尾 / 最长句 | 约 0.5 s / 5 s | 能量断句门限 |
| 前缀补音 | ≈0.45 s | 段前缓冲防丢字 |
| 唤醒防抖窗口 | 1.8 s | 重复唤醒去重 |
| AWAKE 超时 | 8 s | 无活动自动回待机 |
| 娱乐空闲超时 | 10 s | 无活动退出娱乐 |
| 注册录音时长 | 5 s | 命令行注册 |
| 注册质量分门槛 | <30 拒绝 / <40 告警 | 质量控制 |
| TTS 增益范围 | 0.5 ~ 5.0(步进 1) | 音量调节 |
| 有效房间 | 积厚/韶华/云程/行远/观潮厅、员工间 | 送餐白名单 |
| 外网探活超时 | 3 s(TCP 443) | LLM 后端在线/离线判定 |
| ZMQ 收发高水位 / 应用队列 | 30 | 队列满丢旧帧,保实时性 |
18. 部署与运行
- 依赖要点:Python 3(含 numpy/scipy/soundfile)、pyzmq、sherpa-onnx(VAD/声纹/TTS)、funasr-onnx(SeacoParaformer)、onnxruntime(GPU 可选)、torch(降噪)、llama-cpp-python(本地 LLM)、paho-mqtt(可选)、pydub(音乐解码)、sounddevice(本地播放/录音);
- 模型资源按配置文件约定放到
model/、modeltest/、tts_models/、DeepFilterNet/等目录; - 常规启动:运行统一启动脚本一键拉起各进程(Ctrl+C 统一收尾);也可逐进程独立启动便于调试;
- 客户端:分别在工控机上运行采集端与播放端脚本,通过环境变量指定服务器 IP、客户端 ID、声卡设备等;
- 声纹注册:命令行录音注册,或使用图形化注册/识别界面(走服务器或本地声纹库均可),注册后数据即时对识别主进程生效(进程启动时载入,注册后需重启识别进程或重新加载生效,视接入方式而定);
- 形态切换:正式部署用工控机采集端 + 播放端(形态 A);无工控机或断网调试时关闭主控下发、改用服务器本地播放(形态 B);多台机器人共机时给每个客户端配置独立 ID 并定向下发(形态 C)。
19. 核心技术总结与能力矩阵
19.1 核心技术清单
| # | 核心技术 | 关键做法 | 解决的问题 |
|---|---|---|---|
| 1 | 边缘—中心解耦的客户端-服务器架构 | 音频 IO 放工控机,模型推理集中服务器,ZeroMQ 消息总线互联,支持三种部署形态按需切换 | 机器人端免 GPU、模型集中维护升级、一套算力带多台机器人、断网可单机闭环 |
| 2 | 全链路流式流水线 | 0.1 s 帧级采集→分发→唤醒/识别→合成→下发播放,无“录完整段再处理”环节 | 端到端低时延,说完即响应 |
| 3 | 热词驱动的唤醒/识别一体化 | SeacoParaformer 热词注入 + 能量证据防幻觉 + 静默/打断双触发语义 | 唤醒率高、误唤醒低,播报中可随时打断重唤 |
| 4 | 双保险实时断句 | 自适应噪声地板(RMS/峰值/过零率)+ Silero VAD 复核 + 段前补音 | 嘈杂环境切点准确,不吞首字、不碎切 |
| 5 | 声纹多特征注册与质量加权融合 | ERes2Net-Large 192 维嵌入 + SNR 质量评估 + 5 种融合策略 + 全特征匹配 + 命令级鉴权 | 回答“谁在下指令”,抗口音/响度漂移 |
| 6 | 意图槽位联合模型 + 多级确定性约束 | JointBERT 式联合模型 → 规则回退 → 工作模式过滤 → 房间白名单校验 | 听得懂且不会误执行、越权执行 |
| 7 | 在线/离线双栈与网络自适应热切换 | 核心链路全离线;开放域对话按每轮 TCP 探活在“云端豆包 ↔ 本地 Qwen2.5-7B”间自动切换;云端侧本地规则优先 | 有网更聪明、断网仍可用,切换无感、无需重启 |
| 8 | 集中式 TTS 与全局打断仲裁 | 单一发声点 + 会话号 + 取消集合 + 清空队列指令 + 播报时序提前量 | 任意时刻可打断,音量全局一致,播完立刻恢复收音 |
| 9 | 异步事件驱动状态机与活动心跳 | asyncio 单线程仲裁,AWAKE/娱乐超时自动回收,语音活动与命令完成续期 | 不会出现“话说一半被踢回待机” |
| 10 | 全参数环境变量化、处理链可插拔 | 部署形态、降噪、AGC、HWM、阈值、超时、后端选择全部可配置 | 一套代码适配不同硬件、不同噪声环境、不同网络条件 |
| 11 | 订单可靠投递 | 本地订单日志为唯一事实源 + 增量索引发布 + WiFi/ Broker 自动重连 + QoS 1 | 断网不丢单,恢复后增量补发且不重复 |
19.2 在线/离线能力矩阵
| 能力 | 有网时 | 无网时 | 切换方式 |
|---|---|---|---|
| 唤醒词检测 | 本地热词 ASR | 同左(完全一致) | 恒离线,无需切换 |
| VAD / 实时断句 | 本地 Silero + 能量特征 | 同左 | 恒离线 |
| 语音识别 ASR | 本地 SeacoParaformer(ONNX,可选 GPU) | 同左 | 恒离线 |
| 意图与槽位解析 | 本地联合模型 + 规则 | 同左 | 恒离线 |
| 声纹注册与验证 | 本地 ERes2Net | 同左 | 恒离线 |
| 语音合成 TTS | 本地 Matcha-TTS + Vocos | 同左 | 恒离线 |
| 固定话术(介绍/年龄/籍贯/音乐) | 本地文件与日期计算 | 同左 | 恒离线 |
| 开放域对话(闲聊/百科/故事) | 云端豆包(可联网搜索) | 本地 Qwen2.5-7B GGUF | 每轮 TCP 探活自动切换 |
| 订单上送 | MQTT 发布(QoS 1) | 本地 orders_log.json 缓存 | 重连后按索引增量补发 |
| 音频传输 | 客户端-服务器 TCP(形态 A/C) | 服务器本地声卡(形态 B) | 环境变量 + 主控下发开关 |
19.3 部署形态对比
| 维度 | A. 分布式客户端-服务器 | B. 服务器单机闭环 | C. 一服务器多客户端 |
|---|---|---|---|
| 音频采集 | 工控机麦克风阵列(阵列增益/AGC 最佳) | 服务器本机声卡 | 各机器人本地阵列 |
| 算力位置 | 服务器 | 服务器(同一台) | 服务器(一份模型服务多台) |
| 网络依赖 | 局域网(可用离线,仅链路需连通) | 无 | 局域网 |
| 典型用途 | 正式部署 | 调试/演示/断网应急 | 多机规模化部署 |
| 切换成本 | 默认形态 | 关下发 + 开本地播放 | 给客户端配 ID,定向下发 |
19.4 一句话总结
这套系统的技术内核可以概括为:“边缘只做耳朵和嘴巴,中心负责全部大脑;核心链路 100% 离线可用,增值能力在线即增强、断网即回落;所有形态与模型的选择都可配置、可热切换,且任何一层失效都有下一层兜底。”
本文档依据仓库当前代码逻辑整理,指标/参数以 config.py 及各模块内实际实现为准。