粗糙转写会在后续放大错误,Whisper.cpp支持自有词典场景关键词拼写纠偏。指令如下:
查看文档:https://www.openhab.org/addons/voice/whisperstt/

1
2
3
4
5
6
7
8
```bash
./main -m ggml-large-v3.bin -f meeting.wav \
--language zh \ # 中文
--prompt "OKR KPI KenLM 飞轮效应" \ # ⬅ Level‑1:短 prompt 注入
--grammar action_item.gbnf \ # ⬅ Level‑2:GBNF 词典
--grammar-rule root \
--grammar-penalty 60 \
--beam-size 5

其中:

  • --prompt:把 5‑10 个高频术语拼到上下文。
  • --grammar + --grammar-penalty:真正的“自有词典”功能

1. 什么是grammar

GBNF(GGML Backus‑Naur Form) 是 GGML 生态(llama.cppwhisper.cpp 等)引入的一种 扩展版 BNF 语法,用来给模型输出“加栅栏”——只有满足语法的 token 序列才允许被采样。它在经典 BNF 的基础上,加入了 Regex‑风格的字符范围、重复、可选等写法,既轻量又易读,可直接写成文本文件并在推理时通过 --grammar 加载。

1.1 语法速览

语法元素 含义 示例
产生式 nonterminal ::= 序列 `move ::= pawn
终结符 用引号圈定的字面量 "OKR" "飞轮效应"
字符范围 [a-z] [0-9] … 可加 ^ 取反 [^\n]
并列 / 选择 `A B
括号分组 () ("1. " move)+
重复 * 0+ + 1+ ? 0/1 {m,n} m~n [0-9]{1,4}
注释 # comment # 专有词列表

root 规则必需:它定义了整个输出必须符合的顶层模式。​GitHub
非终结符命名惯例:建议全小写加短横线,如 kw-listdate-part

1.2 写一个最小词典示例

1
2
3
4
# meeting_keywords.gbnf
root ::= kw-list "." # 整句只有关键词 + 句点
kw-list ::= kw (" " kw)* # 多个关键字用空格分隔
kw ::= "OKR" | "KPI" | "KenLM" | "Conformer" | "飞轮效应"
  • root 要求整句以关键词序列开头,以句点结尾,任何“非词典” token 都会被 --grammar-penalty 强力压制。
  • 词典扩展时,只需在 kw ::= ... 后追加 "新词" 即可。

1.3 更复杂的会议口令示例

1
2
3
4
5
6
7
8
9
# action_item.gbnf
root ::= line+
line ::= speaker ":" todo "\n"
speaker ::= "张三" | "Alice" | "Bob"
todo ::= verb obj [ddl]
verb ::= "完成" | "更新" | "评审"
obj ::= [^@\n]{1,80} # 任意 1‑80 个非换行、非 @ 字符
ddl ::= "@" date
date ::= [0-9]{4} "-" [0-1][0-9] "-" [0-3][0-9]
  • 强制所有输出都是 “人名: 动作 对象 @2025‑05‑01” 的形式。
  • 可用在 大模型生成 Action Item 时确保结构正确,同样适用于 Whisper 转写约束。

1.4 小贴士

  1. 中文 / Unicode 直接写在引号内;必要时用 \u4e2d\u6587 形式。
  2. 大词典 (>1000 词) 建议拆两层:
    • 高频 300 词放 GBNF 并提高 penalty;
    • 低频词放 --prompt,降低 penalty,兼顾速度
  3. 若想把已有 JSON Schema → GBNF(如强制输出合法 JSON),llama.cpp 自带 json_schema_to_grammar.py 可一键转换