Files
Owner/README.md
T

132 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Owner 语音桌宠
这是一个 Python 语音桌宠运行程序。当前第一版先提供无 GUI 的真实实时语音循环:
`小杰小杰` 唤醒 -> 本地应答“我在” -> 主说话人端点采集问题 -> ASR 转文字 -> 携带本次进程内临时历史调用 LLM -> TTS 生成语音 -> 本机扬声器播放 -> 回到待机继续监听。
## 当前能力
- `owner_voice_pet run-live`:真实常驻语音循环。
- `owner_voice_pet run-live --once`:只跑一轮,便于验收。
- `.env` 直接读取配置,不要求导出 shell 环境变量。
- 唤醒词检测使用本地 `sherpa-onnx` KWS 模型,不走云端 ASR。
- `OWNER_SPEECH_PROVIDER=cloud|local`:选择云端语音模型或本地语音模型。
- 默认云端语音模型:`mimo-v2.5-asr``mimo-v2.5-tts`
- 本地设备:`sounddevice` 读取麦克风,扬声器或 `afplay` 播放。
- 本地模型:`models/` 存放 `sherpa-onnx` wake/VAD/STT 模型,目录不提交 Git。
- Pipeline`run-live` 使用 stage 化 `VoiceAssistantPipeline`,通过事件总线输出终端状态。
- 主说话人端点:默认 `OWNER_ENDPOINT_MODE=primary_speaker`,本轮音色消失后结束录音,避免背景噪声拖慢 STT。
- 临时上下文:同一次 `run-live` 进程内携带最近 user/assistant 历史,退出即清空。
## 首次准备
```bash
python3.11 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e '.[speech]'
cp .env.example .env
```
然后编辑 `.env`,填写本地密钥和模型配置。当前默认示例:
```dotenv
OWNER_LLM_BASE_URL=https://token-plan-cn.xiaomimimo.com/v1
OWNER_LLM_API_KEY=
OWNER_LLM_MODEL=mimo-v2.5
OWNER_LLM_API_STYLE=chat_completions
OWNER_WAKE_PROVIDER=local_kws
OWNER_WAKE_KEYWORDS_FILE=
OWNER_WAKE_KWS_THRESHOLD=0.15
OWNER_WAKE_KWS_SCORE=1.0
OWNER_WAKE_ACK_TEXT=我在
OWNER_POST_PLAYBACK_DRAIN_MS=0
OWNER_PIPELINE_MODE=live_turn_based
OWNER_ENDPOINT_MODE=primary_speaker
OWNER_SPEAKER_PROFILE_MS=600
OWNER_SPEAKER_PROFILE_MIN_MS=120
OWNER_SPEAKER_ABSENT_MS=300
OWNER_SPEAKER_SIMILARITY_THRESHOLD=0.70
OWNER_SPEAKER_MIN_RMS=0.012
OWNER_VAD_PROVIDER=hybrid
OWNER_VAD_THRESHOLD=0.5
OWNER_VAD_MIN_DURATION_MS=250
OWNER_VAD_END_SILENCE_MS=350
OWNER_VAD_NO_SPEECH_TIMEOUT_MS=5000
OWNER_VAD_MAX_RECORDING_MS=12000
OWNER_SPEECH_PROVIDER=cloud
OWNER_ASR_MODEL=mimo-v2.5-asr
OWNER_TTS_MODEL=mimo-v2.5-tts
OWNER_TTS_VOICE=mimo_default
OWNER_CONTEXT_MODE=session_memory
```
`OWNER_WAKE_PROVIDER=local_kws` 表示唤醒词“小杰小杰”由本地模型检测。唤醒命中后会先本地播报 `OWNER_WAKE_ACK_TEXT=我在`,再开始听取问题。`OWNER_SPEECH_PROVIDER=cloud` 只影响唤醒后的正式问题 ASR/TTS:它会把 VAD 切出来的用户问题片段发送到云端 ASR,不会上传连续麦克风流,也不会用云端判断唤醒。改成 `local` 时使用项目 `models/` 下的本地语音模型路径。
## 本地模型
即使默认走云端 ASR/TTS,也必须准备本地唤醒模型;同一脚本会下载 wake、VAD、STT 模型,便于切换到 `OWNER_SPEECH_PROVIDER=local`
```bash
python3.11 scripts/download_speech_models.py --dir models
.venv/bin/python -m owner_voice_pet model-check --models-dir models
```
`models/` 已在 `.gitignore` 中,不会提交大模型文件。
本地唤醒关键词文件位于 `models/wake/keywords.txt`。默认 `OWNER_WAKE_KWS_THRESHOLD=0.15` 已偏向灵敏;如果真人唤醒仍不灵敏,可以继续降到 `0.10`,若误唤醒变多再回调到 `0.20`
默认 `OWNER_ENDPOINT_MODE=primary_speaker` 会在本轮问题开头建立临时音色画像;`OWNER_SPEAKER_PROFILE_MIN_MS=120` 表示最少 120 毫秒有效语音即可让画像参与端点判断。当这个主说话人音色连续消失 `OWNER_SPEAKER_ABSENT_MS=300` 毫秒后,直接结束录音进入转写。它不保存长期声纹、不做主人注册、不跨进程记忆。
默认 `OWNER_POST_PLAYBACK_DRAIN_MS=0` 表示“我在”播放结束后只清理已经积压的输入队列,不再额外读取并丢弃后续音频,避免切掉正式问题开头。默认 `OWNER_VAD_PROVIDER=hybrid` 会同时使用本地 `sherpa-onnx` VAD 和能量阈值兜底,帮助开始录音;结束录音优先由主说话人端点控制。如果你想临时回退旧行为,可以设置 `OWNER_ENDPOINT_MODE=vad`。如果唤醒后你已经停说但还长时间显示“录音中”,优先调小 `OWNER_SPEAKER_ABSENT_MS`,例如 `250`;如果句尾容易被切掉,再调高到 `400`
## 设备检查
```bash
.venv/bin/python -m owner_voice_pet device-check
```
输出里 `ok=true` 表示已检测到可用麦克风和扬声器。
## 运行
单轮验收:
```bash
.venv/bin/python -m owner_voice_pet run-live --once
```
常驻重复对话:
```bash
.venv/bin/python -m owner_voice_pet run-live
```
运行后终端状态来自 pipeline event bus,会显示待机、唤醒命中、应答中、请说出问题、录音中、检测到用户语音、用户语音结束、转写中、转写结果、思考中、播放中、恢复待机等状态。说“小杰小杰”,听到“我在”且看到“请说出问题”后再提问;听到回复后可以再次说“小杰小杰”继续下一轮。本次进程内会携带临时历史,程序退出后不保存。
## 验证
```bash
.venv/bin/python -m compileall src tests scripts
.venv/bin/python -m unittest discover -s tests
.venv/bin/python -m owner_voice_pet acceptance
.venv/bin/python -m owner_voice_pet validate-assets
.venv/bin/python -m owner_voice_pet security-check
.venv/bin/python -m owner_voice_pet model-check --models-dir models
.venv/bin/python -m owner_voice_pet device-check
openspec validate --all --strict
```
LLM smoke
```bash
.venv/bin/python -m owner_voice_pet llm-smoke --no-stream --message '用一句中文回复:小杰在线。'
```
## 安全约束
- API key 只写入本地 `.env``.env` 不提交 Git。
- `models/``.venv/` 和临时音频文件不提交 Git。
- 默认不持久化麦克风原始音频。
- 云端 ASR 只接收 VAD 切分后的语音片段。
- `security-check` 会扫描已跟踪文本文件中的 `sk-...``tp-...` 形式密钥。