Skip to content

Commit 76a3e71

Browse files
authored
feat: add postprocess hotword correction for AutoModel.generate() (#2959)
Adds text-level postprocess hotword correction for large domain vocabularies. Fixes #2959.
1 parent 57e2f48 commit 76a3e71

5 files changed

Lines changed: 621 additions & 2 deletions

File tree

docs/tutorial/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,31 @@ wav_file = f"{model.model_path}/example/asr_example.wav"
8686
res = model.generate(input=wav_file, batch_size_s=300, batch_size_threshold_s=60, hotword='魔搭')
8787
print(res)
8888
```
89+
90+
#### Postprocess hotword correction
91+
92+
Model-level `hotword` / `hotwords` boosts a small set of terms during decoding. For large vocabularies (for example thousands of stock names), apply text-level correction after recognition:
93+
94+
```python
95+
from funasr import AutoModel
96+
97+
model = AutoModel(model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc")
98+
99+
res = model.generate(
100+
input="asr_example.wav",
101+
postprocess_hotwords={
102+
"科大迅飞": "科大讯飞",
103+
"东方财富": "东方财富",
104+
},
105+
postprocess_hotword_threshold=0.85,
106+
return_postprocess_hotword_matches=True,
107+
)
108+
print(res[0]["text"])
109+
print(res[0].get("postprocess_hotword_matches"))
110+
```
111+
112+
You can also pass `postprocess_hotword_file` with one target word per line, or an explicit mapping such as `wrong=>right`. Fuzzy matching requires optional `pypinyin` and `rapidfuzz`; explicit mappings work without them.
113+
89114
Notes:
90115
- Typically, the input duration for models is limited to under 30 seconds. However, when combined with `vad_model`, support for audio input of any length is enabled, not limited to the paraformer model—any audio input model can be used.
91116
- Parameters related to model can be directly specified in the definition of AutoModel; parameters related to `vad_model` can be set through `vad_kwargs`, which is a dict; similar parameters include `punc_kwargs` and `spk_kwargs`.

docs/tutorial/README_zh.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@ wav_file = f"{model.model_path}/example/asr_example.wav"
8787
res = model.generate(input=wav_file, batch_size_s=300, batch_size_threshold_s=60, hotword='魔搭')
8888
print(res)
8989
```
90+
91+
#### ASR 后处理热词替换
92+
93+
模型层 `hotword` / `hotwords` 用于在解码阶段提升少量高优先级词的识别率;如果词表很大(例如几千个股票名),更适合在识别完成后做文本级纠错:
94+
95+
```python
96+
from funasr import AutoModel
97+
98+
model = AutoModel(model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc")
99+
100+
res = model.generate(
101+
input="asr_example.wav",
102+
postprocess_hotwords={
103+
"科大迅飞": "科大讯飞",
104+
"东方财富": "东方财富",
105+
},
106+
postprocess_hotword_threshold=0.85,
107+
return_postprocess_hotword_matches=True,
108+
)
109+
print(res[0]["text"])
110+
print(res[0].get("postprocess_hotword_matches"))
111+
```
112+
113+
也支持热词文件 `postprocess_hotword_file`,每行一个目标词,或一行一个显式映射(`错误词=>目标词`)。模糊匹配需要额外安装 `pypinyin``rapidfuzz`;未安装时仍可使用显式映射。
114+
90115
注意:
91116
- 通常模型输入限制时长30s以下,组合`vad_model`后,支持任意时长音频输入,不局限于paraformer模型,所有音频输入模型均可以。
92117
- `model`相关的参数可以直接在`AutoModel`定义中直接指定;与`vad_model`相关参数可以通过`vad_kwargs`来指定,类型为dict;类似的有`punc_kwargs``spk_kwargs`

funasr/auto/auto_model.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from funasr.train_utils.set_all_random_seed import set_all_random_seed
2929
from funasr.train_utils.load_pretrained_model import load_pretrained_model
3030
from funasr.utils import export_utils
31+
from funasr.utils.postprocess_hotwords import apply_postprocess_hotwords_to_results
3132
from funasr.utils import misc
3233

3334

@@ -458,6 +459,12 @@ def generate(self, input, input_len=None, progress_callback=None, **cfg):
458459
**cfg: Runtime parameters:
459460
- cache (dict): State cache for streaming mode. Pass {} for first call.
460461
- hotword (str/list): Keywords to boost recognition accuracy.
462+
- postprocess_hotwords (str/list/dict): Text-level hotword correction after
463+
decoding. Unlike model-level ``hotword``, this runs on the final text.
464+
- postprocess_hotword_file (str): Hotword file path. Each line is a target
465+
word or an explicit mapping like ``错误词=>目标词``.
466+
- postprocess_hotword_threshold (float): Fuzzy match threshold in [0, 1].
467+
- return_postprocess_hotword_matches (bool): Include replacement details.
461468
- language (str): Language hint ("auto", "zh", "en", "Chinese", etc.)
462469
- batch_size_s (int): Dynamic batch total duration in seconds.
463470
- is_final (bool): Last chunk flag for streaming mode.
@@ -486,12 +493,13 @@ def generate(self, input, input_len=None, progress_callback=None, **cfg):
486493
if cfg.get("return_raw_text", self.kwargs.get("return_raw_text", False)):
487494
result["raw_text"] = copy.copy(result["text"])
488495
result["text"] = punc_res[0]["text"]
489-
return results
496+
return apply_postprocess_hotwords_to_results(results, cfg)
490497

491498
else:
492-
return self.inference_with_vad(
499+
results = self.inference_with_vad(
493500
input, input_len=input_len, progress_callback=progress_callback, **cfg
494501
)
502+
return apply_postprocess_hotwords_to_results(results, cfg)
495503

496504
def inference(
497505
self,

0 commit comments

Comments
 (0)