fix: solve vLLM->BLM misrecognition via glossary postprocessing

The bench and CLI kept emitting BLM for vLLM. Three layers:

1. rules.py: add default rule BLM -> vLLM (word-boundary, case-insensitive) so the default post_mode=rules path restores it everywhere.

2. benchmark/runner.py: the bench never ran postprocessing - it measured raw engine text, so entity retention (66.7%) never reflected rules/glossary. _transcribe_clip now builds Segments and runs run_postprocess(settings, glossary) before metrics; manifest top-level glossary {pattern: replacement} is supported and recorded in run_config (post_mode/glossary).

3. glossary plumbing: CLI transcribe gains --glossary KEY=VALUE (repeatable, parsed + validated); BatchPipeline.run accepts glossary= and passes it to run_postprocess; the in-proc worker forwards job.options.glossary or post_correction.

Notebook: transcribe cells pass --glossary BLM=vLLM, bench manifest carries glossary, postprocess section documents rules/glossary/hotword.

+ 9 unit tests (BLM rule, boundary/case behavior, bench postprocess + glossary entity retention). 147 tests pass, ruff clean.
This commit is contained in:
2026-08-12 21:06:42 +09:00
parent f171ce4992
commit 6bb89eb51f
9 changed files with 237 additions and 22 deletions
+19
View File
@@ -43,6 +43,25 @@ class TestRules:
out = apply_rules(segs)
assert "vLLM" in out["segments"][0].text
def test_vllm_restored_from_blm(self):
# GPU 실전에서 재현된 오인식: vLLM → BLM
segs = _segments(["오늘은 BLM 서버를 배포합니다"])
out = apply_rules(segs)
assert "vLLM" in out["segments"][0].text
assert "BLM" not in out["segments"][0].text
def test_blm_boundary_required(self):
# 단어 경계가 없으면 교정하지 않는다 (부분 문자열 보호)
segs = _segments(["sublm 단어"])
out = apply_rules(segs)
assert "sublm" in out["segments"][0].text
assert "vLLM" not in out["segments"][0].text
def test_blm_case_insensitive(self):
segs = _segments(["blm 서버"])
out = apply_rules(segs)
assert "vLLM" in out["segments"][0].text
def test_whitespace_collapse(self):
segs = _segments(["오늘 API 서버"])
out = apply_rules(segs)