Voice Chat · 和 WatcheRobot 对话

对着机器人说话,它用本地模型理解并开口回答。

对话期间机器人保持彩虹灯效,屏幕表情随状态切换:微笑 → 聆听 → 思考 → 说话。

工作原理

机器人麦克风 → 本地 ASR(SenseVoice) → 本地 LLM(qwen3/Ollama) → edge-tts → 响度归一化 → 机器人喇叭

识别和大模型全部运行在本机,不需要 API Key;语音合成使用微软在线语音服务。

技术栈

环节 方案 运行位置 需要联网
语音识别 ASR SenseVoice Small(int8,sherpa-onnx 推理) 本机 CPU 否
大模型 LLM Qwen3 0.6B(Ollama 运行) 本机 CPU 否
语音合成 TTS edge-tts,音色 zh-CN-XiaoxiaoNeural 微软在线服务 是
音频处理 ffmpeg(loudnorm 响度归一化 + alimiter 限幅) 本机 否
对话记忆 最近 4 轮(8 条消息)上下文 本机内存 否

识别单句约 0.05–0.09 秒,大模型生成约 0.07–0.10 秒,语音合成 2–4 秒,单轮总计约 5–8 秒。

快速开始

# ============ 准备(只需执行一次) ============
conda activate watcherobot-source
python -m pip install sherpa-onnx soundfile soxr edge-tts
brew install ffmpeg
ollama pull qwen3:0.6b

# ============ 启动 ============
cd "/Users/zongzheli/Downloads/self_study/workshop"
watcherobot daemon start
watcherobot robot status            # 需要显示 Robot connected
watcherobot app run ./voice_chat

# ============ 停止(任选一种) ============
# 方式 A:在运行窗口按 Ctrl+C
# 方式 B:另开一个终端
watcherobot app stop
# 方式 C:对机器人说「退出」「再见」「拜拜」「停止」「结束」

启动后机器人亮起彩虹灯、露出微笑,说一句开场白,然后进入聆听状态。直接说话即可。

停止后自动恢复:关灯、播放待机表情。

目录结构

voice_chat/
├─ app.py            主程序(Application 入口)
├─ app.json          Application 清单
├─ settings.json     全部可调参数
├─ icon.svg          图标
├─ models/asr/       识别模型存放位置(发布包中不含,首次使用需下载,见下)
├─ artifacts/        运行产物,可随时删除
└─ README.md

识别权重以相对路径 models/asr/ 引用。

获取识别权重

发布包里不包含识别权重(已在 .watcherignore 中排除)。首次使用前下载到 models/asr/:

cd voice_chat
python - <<'PY'
from huggingface_hub import hf_hub_download
import shutil, pathlib
pathlib.Path("models/asr").mkdir(parents=True, exist_ok=True)
for f in ["model.int8.onnx", "tokens.txt"]:
    p = hf_hub_download(
        "csukuangfj/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17", f
    )
    shutil.copy(p, "models/asr/" + pathlib.Path(f).name)
    print("已下载", f)
PY

下载约 228 MB。国内网络可先设置 export HF_ENDPOINT=https://hf-mirror.com 走镜像。

大模型权重由 Ollama 管理,位置在 ~/.ollama/models/,用 ollama list 可确认 qwen3:0.6b 已就绪。

参数配置

全部参数都在 settings.json:

参数 作用 默认值
asr_model / asr_tokens 识别模型路径,相对于本目录 models/asr/...
asr_input_gain 送识别前对麦克风音频的放大倍数 4.0
ollama_model 使用的大模型 qwen3:0.6b
tts_voice 语音音色 zh-CN-XiaoxiaoNeural
loudness_filter 响度归一化滤镜 loudnorm + alimiter
noise_floor_min 判定「开始说话」的最低能量 900
speech_ratio 超过本底噪声多少倍算说话 2.5
silence_seconds 停顿多久算说完 0.8
max_utterance_seconds 单次录音最长时长 12.0
light_color / light_zone 灯光颜色与区域 #FF1E8A / all
light_effect 灯效名称,留空则常亮 rainbow
system_prompt 机器人的说话风格 简短口语化
knowledge_file 常见问题参考文件 knowledge.md
greeting 启动开场白 「你好,我在听,请说吧。」

调音建议:识别不准时先调 asr_input_gain(调到 6.0);环境嘈杂时调高 noise_floor_min(如 1200)。

知识库

knowledge.md 存放常见问题的参考回答。启动时它会被注入给模型,同时附带当前时间,所以「现在几点」这类问题也能回答。

文件按 问:… 答:… 的格式编写,想加内容直接追加即可:

问:你几岁了?
答:我是刚出厂的,还很年轻,请多关照。

能回答哪些问题

以下问题有预设答案,回答稳定:

类别 问题
身份 你是谁 / 你叫什么名字;你是什么做的 / 用什么模型;你几岁了 / 多大了
能力 你会做什么;你能看到我吗;你能听到我说话吗;你会唱歌吗;你能走路吗 / 能动能
隐私 我说的话会被上传到网上吗;你会记录我吗
时间 现在几点 / 今天几号
闲聊 你好 / 嗨;你喜欢什么;讲个笑话;夸夸我;我有点累 / 心情不好;你怎么看这个工作坊 / 今天的活动;再见 / 拜拜

以下问题会明确说"答不了",不会编造:

类别 问题 回答方式
实时信息 今天天气怎么样 说明查不了实时信息,建议用手机
检索 你能帮我查东西吗 说明查不了资料,可以陪聊

知识库没覆盖的问题走自然闲聊,由 qwen3:0.6b 自由回答。因为是 0.6B 小模型,自由发挥时回答偏短,偶尔会绕。

提问超出知识库时,模型会正常闲聊;不确定的内容会直说不知道,不会编造。不需要知识库就把 knowledge_file 设为空字符串,或删除该文件。

灯光

颜色

SDK 接受 #RRGGBB,任意颜色可用。几个高饱和推荐:

颜色 色值
品红 #FF1E8A
青蓝 #00E5FF
紫罗兰 #B000FF
荧光绿 #39FF14
亮橙 #FF7A00
宝石红 #FF0033

区域

light_zone 可选 all(全部)、side(两侧)、head(头部)、bottom(底部)。

灯效

由 light_effect 与 light_effect_period_ms 控制:

灯效 说明
rainbow 彩虹流转,当前默认
breathing 呼吸明暗
blink 闪烁
status-pulse 状态脉冲

把 light_effect 设为空字符串 "" 即可切回纯色常亮,此时 light_color 生效。

已知限制