dsh-voice
回合制语音通道 for DeepSeek Harness(dsh)——为「面向面试者的 preset」而生的语音插件。
Agent 通过三个工具获得语音能力,浏览器端自动配合录音/播放,形成完整的一问一答闭环:
| 工具 | 方向 | 作用 |
|---|---|---|
voice_speak |
Agent → 人 | 把提问/反馈合成语音,浏览器自动播放 |
voice_listen |
人 → Agent | 弹出录音面板,候选人作答后自动转写回传 |
voice_status |
— | 引擎健康检查(TTS/ASR 可用性、队列、录音状态) |
三引擎 provider 抽象
TTS 与 ASR 各自独立选择引擎,auto 模式按 qwen → mimo → local 顺序探测,取第一个可用者:
| 引擎 | TTS | ASR | 依赖 |
|---|---|---|---|
| qwen(首发) | qwen3-tts-flash(DashScope 原生 multimodal-generation) |
qwen3-asr-flash(OpenAI 兼容 /audio/transcriptions) |
环境变量 DASHSCOPE_API_KEY |
| mimo | MiMo-V2.5-TTS(POST /audio/speech) |
MiMo-V2.5-ASR(POST /audio/transcriptions) |
环境变量 MIMO_API_KEY;baseUrl/model 可配(本地 MiMo 网关同理) |
| local | sherpa-onnx / piper 二进制 / macOS say |
sherpa-onnx(paraformer/zipformerCtc 等离线模型)/ whisper.cpp 二进制 | 本地模型与二进制,零 API 依赖 |
本地 ASR(sherpa-onnx)已验证闭环:macOS
say合成中文 → 16 kHz WAV →sherpa-onnx-paraformer-zh-small-2024-03-09(int8,约 82 MB,hf-mirror 可下载) 转写,552 ms、逐字命中。插件将sherpa-onnx-node声明为 optionalDependency, 本地引擎生效只需:模型目录就位 + 配置asr.local.{kind, modelType, modelDir, model}。
音频落盘在 ~/.dsh/voice(可配),由本机 loopback 路由(支持 Range)服务给浏览器;浏览器端以 16 kHz 单声道 WAV 录音(对所有 ASR 后端通用)。云引擎只收到需要转写的音频本身。
安装
dsh plugin --profile web add @harness-flow/dsh-voice
安装后重启对应 profile 生效。插件行的默认配置是中性值;在你的 profile 的
cordis.patch.yml里按行 iddsh-voice覆盖(不要重复 insert 同一 id)。
配置
- id: dsh-voice
config:
asr:
engine: auto # auto | qwen | mimo | local
language: zh
# qwen: { apiKeyEnv: DASHSCOPE_API_KEY, model: qwen3-asr-flash, baseUrl: https://dashscope.aliyuncs.com/compatible-mode/v1 }
# mimo: { apiKeyEnv: MIMO_API_KEY, model: MiMo-V2.5-ASR, baseUrl: https://api.mimo.mi.com/v1 }
# local: { kind: sherpa-onnx | whisper-bin, modelType: paraformer, modelDir: ~/.dsh/voice-models/paraformer-zh-small, model: model.int8.onnx, bin: ... }
tts:
engine: auto # auto | qwen | mimo | local
voice: Cherry
# qwen: { apiKeyEnv: DASHSCOPE_API_KEY, model: qwen3-tts-flash, baseUrl: https://dashscope.aliyuncs.com/api/v1 }
# mimo: { apiKeyEnv: MIMO_API_KEY, model: MiMo-V2.5-TTS, baseUrl: https://api.mimo.mi.com/v1 }
# local: { kind: sherpa-onnx | piper-bin | say, modelDir: ..., bin: ..., model: ... }
audioDir: ~/.dsh/voice
listenTimeoutSec: 120
- 云引擎密钥只在调用时从引用的环境变量读取,配置里只写变量名,永不写密钥。
sherpa-onnx需要 profile 里安装sherpa-onnx-node并配置模型目录;whisper-bin/piper-bin指向 whisper.cpp / piper 的可执行文件与模型。- 本地 MiMo(MiMo-Audio-7B 经 vLLM-Omni 等 OpenAI 兼容网关)通过
tts.mimo.baseUrl/asr.mimo.baseUrl指向本机地址即可复用同一实现。
面试官 preset(推荐用法)
preset 与插件各司其职:插件负责语音链路(host 侧服务 + 浏览器 UI),preset 只负责「面试官」这个角色与流程。给面试 preset 的 persona 建议:
- id: persona
name: '@deepseek-ai/dsh-persona'
config:
text: >-
你是一位专业的面试官,正在通过语音进行一场结构化面试。
一次只提一个问题:用 voice_speak 朗读问题,随后立刻调用 voice_listen
等待候选人作答;根据 transcript 追问或进入下一题。
流程:开场寒暄 → 自我介绍 → 技术/项目深挖 → 行为面 → 候选人提问 →
结束语与后续安排。全程专业、中立、鼓励,不做主观臆断;
面试结束后输出评分表(各维度 1–5 分 + 一句话依据)与录用建议。
开发
pnpm install
pnpm check # build + 22 项单元测试
pnpm run verify:dsh-offline # 一次性 DSH_HOME 隔离 profile 启动验证(不碰用户 profile)
- Host:
src/index.ts(TypeScript,tsc 直出 ESM 到lib/) - Client:
src/client/*.tsx(esbuild 打成window.__ModuleLoader__.load懒加载 CJS 包) - 测试:
node --test test/*.test.mjs(fake/mock 引擎,不访问网络) - 浏览器验收:
scripts/browser-accept.mjs(Playwright,需DSH_VOICE_BASE_URL+PLAYWRIGHT_ENTRY环境变量)
发布与市场
- GitHub:
Harzva/dsh-voice(topic:dsh-plugin),Release tarball 即安装包:dsh plugin --profile web add github:Harzva/dsh-voice - awesome-dsh-plugin.com 收录后自动辐射 dsh-market、dsh-find-plugin、
dsh-webui-market-plugin 与内置 dsh-market 的桌面客户端;
带
dsh-plugintopic 的仓库会在话题驱动市场(DSH-Plugins-Marketplace、 DSH-Plugin-Market 等)自动收录。
边界与设计取舍(v0.1)
- 回合制优先:
voice_speak阻塞到合成完成(2–5s),保证「提问 → 收听」顺序;全双工打断(barge-in)留给后续版本。 - 单客户端桥接:listen 会话与播放队列在内存中,假设 DSH web UI 一个浏览器;页面关闭后队列自动丢弃。
- 不做会话事件持久化:v0.1 不写
voice/*会话事件(历史加载兼容风险),聊天记录里保留文本转写。 - 失败局部化:引擎探测失败只影响该引擎;浏览器播放被自动播放策略拦截时,等下一次用户手势重试。
No comments yet. Be the first to write one.