唤醒词("Hey Hermes")

唤醒词把 Hermes 变成跨 CLI、TUI 和桌面应用的免手助手:打开一个开关,Hermes 就在后台监听一句口语触发词。说出它,Hermes 就开启一个新会话、打开麦克风,通过常规语音流水线捕获你的命令并作答——完全像 "Hey Siri" 或 "Alexa"。用 surface 选择由哪一个来听。

检测完全在设备端运行。常开监听器只盯唤醒词;在你真正向 agent 说出命令之前,没有任何音频离开你的机器。

工作原理

  1. wake_word.enabled: true(或 /wake on)后,一个轻量热词检测器在你配置的输入设备上监听;未设 wake_word.input_device 时使用进程默认麦克风。
  2. 听到唤醒词时它暂停自身(释放麦克风),开启新会话,并用语音模式的静音检测录制一次语音。
  3. 你的语音被转写并发送给 agent。它回复后,监听器自动恢复,等待下一个唤醒词。

它默认关闭——在你打开之前什么都不听。

在桌面应用中,免手语音对话可直接说 "stop"(或 "never mind"、"goodbye"、"cancel"、"that's all")结束——这句口语命令结束对话,而非发给 agent。只有整句的停止命令才匹配,因此 "stop the docker container" 这样的真实请求仍正常通过。

远程桌面(客户端采集)

当桌面应用连接到远程 Hermes 后端(例如无头 Docker 主机或另一个房间的机器)时,后端往往没有麦克风。服务端 PortAudio 随即失败,报 "Failed to open the wake-word microphone."

为此 Hermes 支持客户端采集:

  1. 桌面以 capture: client 布防唤醒(当后端无本地输入设备时 GUI 自动如此,或在下方显式设置)。
  2. 所选唤醒引擎仍运行在后端(相同引擎、相同模型)。
  3. 桌面打开本地 Mac/PC 麦克风,重采样为 16 kHz 单声道 int16,通过 wake.feed RPC 流式发送短帧。
  4. 检测到时后端照常发出 wake.detected;桌面在客户端麦克风上启动常规语音流水线。
wake_word:
  enabled: true
  capture: auto    # auto | local | client
  # auto   — 本地 PortAudio,除非桌面以 client_capture 布防
  # local  — 始终打开后端麦克风(CLI/TUI 默认)
  # client — 始终期待来自桌面的 wake.feed PCM(远程友好)

桌面 GUI 在 wake.start 时总是传 client_capture: true,因此无麦克风的远程后端自动以客户端模式布防。CLI 和 TUI 保持本地采集,除非你显式设 capture: client。

隐私提示:客户端采集时,唤醒 PCM 经过已鉴权的桌面↔后端 WebSocket(与会话其余部分同一通道)传输。检测仍不向第三方唤醒 API 发送音频;引擎在后端进程本地。

引擎

引擎成本API 密钥说明
openWakeWord免费无经 pyopen-wakeword 的 TFLite。含 "hey hermes" 模型。自定义模型需 .tflite 文件。不支持 Intel macOS 或原生 Windows ARM64。
sherpa免费无对键入短语的开放词表检测。首次使用时下载英文模型。支持原生 Windows ARM64。
Porcupine免费档 / 付费PORCUPINE_ACCESS_KEYPicovoice 引擎;内置关键词 + 自定义 .ppn 文件

默认提供商是 auto。它按此顺序选择第一个平台支持的引擎:openWakeWord → sherpa → Porcupine。平台指 Python 后端的平台,而非远程桌面客户端:

  • 原生 Windows ARM64 和 Intel macOS: sherpa(免费,无密钥)。
  • Windows x64、Apple Silicon 及支持的 Linux 目标: openWakeWord(免费,无密钥)。

显式指定的提供商保持选中,即便该平台不支持它。Hermes 报告需求错误,而非静默切换引擎。既有显式设置不迁移。要选择自动选择,运行 hermes config set wake_word.provider auto。唤醒检测在你启用前保持关闭。

默认短语标签是 "hey hermes"。对 openWakeWord,Hermes 附带其训练好的 TFLite 模型。pyopen-wakeword 包附带共享的特征提取模型,因此该引擎启动时不下载模型。

若所选引擎缺失,Hermes 在你启用唤醒词检测时请求其 PM extra。security.allow_lazy_installs 控制此安装。新依赖环境可能需要重启 Hermes 后引擎才加载。打包构建包含其目标平台支持的引擎依赖。

pyopen-wakeword 的 macOS wheel 虽标 universal2,实则只含 ARM64 库。Hermes 在 Intel Mac 和原生 Windows ARM64 上排除该引擎。Sherpa 在这两个目标上提供无密钥检测。

Porcupine 的默认关键词是 "jarvis",而非 "hey hermes"。其 phrase 设置只是显示标签;选择内置关键词或提供自定义 .ppn 模型才能改变它检测的内容。在 console.picovoice.ai 获取访问密钥,并把 PORCUPINE_ACCESS_KEY 存到你 profile 的 .env,而非 config.yaml。

受支持的 pyopen-wakeword wheel 面向 Apple Silicon(macOS 15 或更高)、glibc Linux 2.35 或更高、Windows x64。这些要求适用于该引擎,而非每个 Hermes 特性。Termux 的 core/ACP 包不含此唤醒栈。

快速开始

# 在交互式 `hermes` 会话中:
/wake on        # 开始监听(首次使用时安装引擎)
/wake status    # 显示短语、提供商和状态
/wake off       # 停止监听

在桌面应用中,把鼠标悬停在输入框的麦克风上,点击从它展开的那只耳朵。唤醒词监听时耳朵为实心。

这个开关本身就是设置:通过 /wake 或桌面耳朵按钮开/关唤醒词,也会把 wake_word.enabled 写入 ~/.hermes/config.yaml,因此你的选择跨会话持久。你也可手动切换:

wake_word:
  enabled: true

配置

wake_word:
  enabled: false
  surface: auto               # 符合条件的界面:"auto" | "cli" | "tui" | "gui"
  input_device: null           # PortAudio 输入索引或设备名子串;null = 进程默认
  capture: auto               # auto | local | client——PCM 在哪里采集(见远程桌面)
  provider: auto              # auto | openwakeword | sherpa | porcupine(需访问密钥)
  phrase: "hey hermes"        # 仅装饰标签——检测由下方模型/关键词决定
  sensitivity: 0.6            # 0.0-1.0——越高越严(误触发越少),三引擎一致
  confirmation_frames: 3      # 仅 openWakeWord——触发所需的连续超阈帧数
  start_new_session: true     # 唤醒时开启新会话 vs. 继续当前会话
  openwakeword:
    model: hey_hermes         # 内置默认,或自定义 .tflite 的绝对路径
  porcupine:
    keyword: jarvis           # 内置关键词或自定义 .ppn 路径

sensitivity 和 start_new_session 适用于全部三个引擎。对 sherpa,phrase 选择检测短语。对 openWakeWord 和 Porcupine,phrase 是显示标签;由其模型或关键词选择检测短语。

input_device 直接传给唤醒监听器的 PortAudio(sounddevice)流。使用数字设备索引或无歧义的设备名子串。此设置只改变唤醒词采集;桌面端按鍵讲话仍使用桌面应用的麦克风路径。

减少环境语音的误触发

openWakeWord 每次给一个短(约 80ms)音频帧打分,因此背景对话中的一个零星音素偶尔会把单帧顶过阈值,无意触发唤醒词。两个旋钮控制它:

  • confirmation_frames(默认 3,仅 openWakeWord)——唤醒触发前需要多少连续超阈帧。真实的 "hey hermes" 在数帧上保持高分;环境杂音只顶起一帧。若嘈杂房间里仍有误触发,调高它(如 4–5);代价是几十毫秒额外延迟。1 恢复旧的首帧即触发行为。
  • sensitivity(默认 0.6)——检测阈值,0.0–1.0。越高越严(误触发越少)。该方向在所有引擎上一致——对 openWakeWord 是原始逐帧分数阈值,对 sherpa 映射到关键词阈值,对 Porcupine 内部反转,使 "越高越严" 同样成立。0.6 默认值位于 openWakeWord 宽松的 0.5 基线上方——后者会放过 "hey hor" 这类近似命中;若仍有误触发,向 0.8 调高;若真实 "hey hermes" 被漏检,则调低。

sherpa 和 porcupine 引擎在内部解码整个短语,因此没有单帧尖峰问题,并忽略 confirmation_frames(但仍遵循 sensitivity)。

openwakeword 提供商名现在选择 pyopen-wakeword。其 wheel 含 TFLite 库和共享特征模型。Hermes 默认使用内置的 hey_hermes.tflite 模型。ONNX 唤醒模型和 inference_framework 设置不再支持。

界面(CLI、TUI、GUI)

唤醒词在所有三个 Hermes 界面中工作,surface 选择哪一个拥有监听器、并在触发时开启新会话:

surface行为
auto(默认)所有本地界面符合条件;第一个布防的拥有监听器。
cli仅经典 hermes CLI。
tui仅 hermes --tui。
gui仅桌面应用。

检测器在设备端、单麦克风,因此同一时刻只有一个界面监听,包括 Hermes 界面运行在不同进程时。所有权是粘性的:第一个符合条件的认领者保持监听器,直到它停止、断开或进程退出。Hermes 不会静默故障转移到另一个已打开的界面。当你想固定所有权而非先到先得时,设置 surface。TUI 和桌面 GUI 共享同一 Python 后端(tui_gateway),它在服务端运行检测器服务器,并在命令录制时把麦克风让给语音采集。

使用不同短语

"Hey Hermes" 是 openWakeWord 和 sherpa 的默认检测短语。Porcupine 使用其配置的关键词(默认 "jarvis")。要唤醒别的东西,在受支持平台上最简单的路径是开放词表引擎:

方案 A——sherpa(任意短语,零训练)

键入你想要的短语;运行时分词——"hey coder"、"computer"、"wake up neo",任何都行:

wake_word:
  enabled: true
  provider: sherpa
  phrase: "hey coder"        # 检测键——直接键入你的短语

小的英文 KWS 模型(约 13 MB)首次使用时下载一次。每个 profile 可设自己的短语——为你运行的每个 profile 设 "hey <profile>"。

唤醒特定 profile(桌面端)

用 sherpa 引擎,一个监听器可唤醒任何 profile。配置中 wake_word.enabled: true 的每个 profile 自动登记;未设置时其短语默认为 hey <profile 名>。说出某 profile 的短语,桌面应用即实时切到该 profile、在那里开启新会话并启动免手语音:

  • "hey hermes" → default profile
  • "hey coder" → coder profile
  • "hey trader" → trader profile

在监听器所在 profile 上设 wake_word.profile_routing: false 可退出路由,只听自己的短语。CLI 和 TUI 是单 profile 进程:属于另一 profile 的唤醒短语会打印切换命令(hermes -p <profile>)而非路由。

名称按英文子词声音声学匹配:由两个词构成、音节 2+ 的独特短语效果最佳。极短名称、浓重的非英语音韵,或两个发音相近的 profile,都会降低准确率——必要时按 profile 调 sensitivity。

方案 B——openWakeWord(免费,训练好的模型)

要换短语,获取或训练一个兼容的 openWakeWord TFLite 模型。在配置中设其绝对路径。Hermes 不会为你解析 hey_jarvis 等内置名或下载其模型。

wake_word:
  enabled: true
  provider: openwakeword
  phrase: "computer"
  openwakeword:
    model: /absolute/path/to/computer.tflite

训练参考:

选一个有辨识度的短语

与日常语音不冲突的唤醒词泛化最好。两个音节加一个不常见的词("hermes" 即符合)胜过 "hello" 或 "stop" 这类常见词。

方案 C——Porcupine(数秒内自定义关键词)

在 Picovoice Console 创建一个 "Hey Hermes" 关键词,下载 .ppn,然后:

wake_word:
  enabled: true
  provider: porcupine
  phrase: "hey hermes"
  porcupine:
    keyword: ~/.hermes/wakewords/hey_hermes.ppn

在 ~/.hermes/.env 设置你的访问密钥:

PORCUPINE_ACCESS_KEY=your-key-here

要求

  • 可用麦克风和 sounddevice + numpy 音频栈(与语音模式共享)。
  • 用于转写口语命令的 STT 提供商——本地 faster-whisper 开箱即用;完整提供商列表见语音模式。
  • 用于朗读回复的 TTS 提供商(默认 edge-tts 无需密钥即可用)。唤醒流程完全免手,因此开关在 STT 和 TTS 都就绪前拒绝布防——hermes tools(Voice 区)会配置它们。
  • 唤醒引擎依赖(自动安装,或 hermes-agent[wake])。

若监听器无法启动,/wake status 会精确报告缺什么。

"Listening" 但从不唤醒(macOS)

macOS 按进程授予麦克风访问权。桌面应用中 STT 正常证明渲染器有麦克风权限——唤醒监听器运行在 Python 后端,它需要自己的授权。没有它,CoreAudio 给后端一条"正常"却只产出静音的流,因此耳朵显示监听但短语从不触发。Hermes 检测到这一点(/wake status 显示 "mic delivers only silence";桌面折叠的语音菜单在其触发器上带同样提示)。修复:系统设置 → 隐私与安全性 → 麦克风 → 启用 Hermes 后端(它可能显示为你的终端、python 或 Hermes),然后把唤醒词关掉再开。

"Listening" 但收到静音(Windows)

桌面端按鍵讲话和唤醒词采集使用不同麦克风路径。按鍵讲话使用桌面应用的浏览器采集,而唤醒词监听器在 Python 后端打开 PortAudio 流。一个工作时,另一个可能选中了静音或不可用的 Windows 输入。

/wake status 报告所选输入设备和 Windows 音频主机 API。当它报告静音时,把 wake_word.input_device 设为工作 PortAudio 输入的数字索引或无歧义名称,然后切换唤醒词:

hermes config set wake_word.input_device "Microphone Array"

用 null 返回进程默认:

hermes config set wake_word.input_device null

注意与限制

  • 仅本地界面。 唤醒词运行在 CLI、TUI 和桌面 GUI——凡有本地麦克风之处。它不在消息网关(Telegram、Discord……)运行,那里没有麦克风。
  • 一次一个麦克风。 检测器在命令录制时释放麦克风,回合结束后重新收回,因此不会与语音采集争抢。
  • 隐私。 热词检测是本地的。误触发多就调高 sensitivity,漏检你就调低。