一文搞懂WeTextProcessing:让语音与文本处理项目告别数字乱码的归一化利器
一文搞懂WeTextProcessing让语音与文本处理项目告别数字乱码的归一化利器【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing一个让人头疼的场景想象一下你的语音识别系统刚上线用户说了一句下午三点二十分开会花费二百九十九块九结果系统输出的文字既不是标准数字也不是规整的时间格式反过来TTS语音合成前你丢给它一段会议定于2023-12-25 14:30召开它却把2023-12-25读得磕磕绊绊。数字、日期、货币、单位这些非标准文本在语音与文本系统之间来回转换时总是容易翻车。WeTextProcessing就是来解决这个问题的——一个专注文本归一化Text NormalizationTN与逆文本归一化Inverse Text NormalizationITN的开源工具包让你在不同格式之间一键切换彻底告别乱码和误读。它到底是什么适合谁用简单来说WeTextProcessing做两件事归一化是把123变成一百二十三逆归一化是把一百二十三变回123。它底层基于OpenFST和Pynini构建的有限状态转换器FST规则引擎天然具备确定性高、处理速度快、规则可组合三大优点。如果你在搞语音识别ASR后处理、语音合成TTS前处理、文本数据清洗或者需要中英日多语言文本标准化这个项目就是为你准备的。它最大的特点是生产就绪——不是实验室玩具而是经历过真实业务打磨的成熟方案。核心能力速览能力说明 多语言覆盖内置中文、英文、日文三套独立规则引擎互不干扰 双向转换TN文本→可读语音文本与 ITN语音文本→标准格式两条流水线 规则全覆盖数字、分数、百分比、日期、时间、货币、度量衡、数学符号、电话号码、儿化音、白名单替换等⚡ FST 高性能规则编译成有限状态转换器匹配速度接近 O(n) 智能缓存图缓存按内容寻址规则或配置变化时自动重建无需手工清理 映射溯源支持获取输入输出之间精确的字符跨度映射知道每一处改动来自哪条规则 双形态部署既提供 Python 接口也提供 C 运行时适合高性能场景从零到跑通10分钟上手第一步安装最简单的途径是直接通过 pip 安装pip install WeTextProcessing如果你打算自定义规则、修复 badcase建议克隆源码仓库git clone https://gitcode.com/gh_mirrors/we/WeTextProcessing cd WeTextProcessing pip install -r requirements.txt第二步命令行快速体验装好后两个命令即可上手# 文本归一化把数字转成中文读法 wetn --text 2.5平方电线 # 输出二点五平方电线 # 逆文本归一化把中文读法还原成数字 weitn --text 二点五平方电线 # 输出2.5平方电线第三步Python 调用在代码里使用同样简单以中文为例from tn.chinese.normalizer import Normalizer from itn.chinese.inverse_normalizer import InverseNormalizer # 归一化数字、符号 → 可朗读文本 zh_tn_model Normalizer(remove_erhuaTrue) text 2023年12月25日花费299.99购买了5kg苹果 print(zh_tn_model.normalize(text)) # 二零二三年十二月二十五日花费二百九十九点九九元购买了五千克苹果 # 逆归一化朗读文本 → 标准书写格式 zh_itn_model InverseNormalizer(enable_0_to_9False) text 下午三点二十分开会 print(zh_itn_model.normalize(text)) # 15:20开会✅ 到这里你已经能处理日常 90% 的转换需求了。进阶玩法与技巧技巧一按需配置参数让行为更贴合业务中文归一化器提供了丰富的开关normalizer Normalizer( remove_erhuaTrue, # 是否去除儿化音这地儿→这地 traditional_to_simpleTrue, # 繁体转简体 remove_punctsFalse, # 是否移除标点 full_to_halfTrue, # 全角转半角→IPHONE tag_oovFalse, # 是否标记未登录词 )逆归一化器侧同样灵活比如控制个位数是否单独转换# 小于10的单独数字不转换幸运一百保持中文而不是变成幸运100 inv InverseNormalizer(enable_0_to_9False) # 默认情况下一百这类独立数字会转成100 inv2 InverseNormalizer(enable_0_to_9True)这里有个小技巧enable_standalone_number控制是否把句中独立出现的数字读法转成阿拉伯数字exclue_one则决定一年后要不要变成1年后。业务上不确定时先在测试数据上跑一遍再决定。技巧二用映射功能追查每一处改动当你想知道12为什么被转成了十二以及改动发生在哪个位置时用normalize_with_mappingresult zh_tn_model.normalize_with_mapping(今天中午12点) print(result.output_text) # 今天中午十二点 for mapping in result.mappings: print(mapping.token_type, mapping.input_text, , mapping.output_text) # math 12 十二返回结果里不仅包含替换前后的文本还带上了 Unicode 字符偏移量半开区间以及产出这次改动的规则类型。对排查 badcase 来说这比肉眼比对原文和结果高效得多。注意偏移量是 Python Unicode 字符偏移不是 UTF-8 字节偏移。技巧三利用 n-best 输出兜底两条 API 都支持联合 tagger/verbalizer 的 n-best 输出outputs zh_tn_model.normalize(输入文本, nbest3) # nbest1 时返回字符串nbest1 时返回字符串列表当主路径结果不满意时可以从候选中挑选更合适的表达。技巧四缓存机制的正确打开方式图编译是比较重的一次性操作WeTextProcessing 内置了内容寻址缓存缓存键包含全部图配置、Python 语法源码、TSV/FAR 资源与构建格式信息规则一改缓存自动失效重建日常使用完全不用管只有想强制重建时才传overwrite_cacheTrue缓存默认写在系统用户缓存目录如 Linux 下的~/.cache/wetextprocessing不会污染源码树也可以用cache_dir/path/to/cache-root指定缓存根目录或传cache_dirFalse完全走内存构建。生产环境建议预编译好规则图关闭overwrite_cache把编译结果分发到各服务节点复用。技巧五自定义规则修复 badcase规则文件全部是 Python 源码放在tn/chinese/rules/归一化和itn/chinese/rules/逆归一化目录下数据词表则在对应语言的data/目录中TSV 格式。改规则前务必先读一遍 Python 规则架构文档。它的核心约定是tagger 只负责分类并原样保留输入字段真正的语义转换交给 verbalizer 完成。这条约定保证了输入输出跨度映射的精确性。改完规则后用--overwrite_cache强制重建图即可验证效果python -m tn --text 2.5平方电线 --overwrite_cache python -m itn --text 二点五平方电线 --overwrite_cache命令行还支持--file PATH读取文件或直接从标准输入读文本每行输入会输出标注结果 最终结果两行。技巧六需要极致性能时上 C 运行时runtime/目录下是一套完整的 C 实现适合对延迟敏感的线上服务cmake -B build -DCMAKE_BUILD_TYPERelease cmake --build build ./build/processor_main --tagger zh_tn_tagger.fst --verbalizer zh_tn_verbalizer.fst --text 2.5平方电线需要注意Python 的缓存包是内部格式不要直接把里面的路径传给processor_mainC 运行时需要的是单独导出的、配套的 tagger/verbalizer 文件对。常见问题与避坑Q1全角半角、繁简、儿化音这些为什么没生效这类字符级转换不在 tagger 里做而是由 verbalizer/postprocessor 负责。这是有意设计——让 tagger 尽量保持输入原样才能保证normalize_with_mapping()的映射真实可信。想改这类行为看data/char/fullwidth_to_halfwidth.tsv、data/char/traditional_to_simple.tsv、data/erhua/whitelist.tsv这些词表即可。Q2为什么某些独立出现的数字没有被转换多半是参数问题。中文 ITN 里enable_0_to_9、enable_standalone_number、enable_million三个开关共同决定数字的转换范围度量衡场景还有exclue_one控制一是否参与转换。按业务需求组合即可。Q3改了规则但结果没变化先确认是否真的重建了图。缓存键包含规则源码指纹正常会自动失效但如果你手动复制过缓存目录或修改了系统时间可以显式传overwrite_cacheTrue强制重建。Q4映射结果和预期对不上映射是沿着 tagger 和 verbalizer 的 WFST 路径追踪出来的没有表层文本 diff 兜底。未被任何规则捕获的文本不会产生映射条目想看到保持原样的 token可以传include_identityTrue。Q5Windows 下缓存目录里出现残留文件Windows 上中断构建的残留物不会自动清理因为没有等价的无跟随目录操作但它们是无害的等没有进程占用缓存时手动删除即可。Q6安装依赖失败核心依赖是pynini2.1.6和importlib_resources其中 pynini 需要本地 FST 工具链支持。装不上时优先确认编译环境是否完整。总结与延伸文本归一化看似是个小问题却是语音产品体验的分水岭。WeTextProcessing 用 FST 规则引擎把这件事做得既快又稳多语言覆盖、双向转换、精确映射、智能缓存再加上 Python/C 双形态从开发调试到生产部署一路畅通。想继续深入可以按这个路径走快速阅读tn/README.md和itn/README.md里面有完整的 TN/ITN 流水线说明和大量输入输出对照表想动手改规则的重点研读 docs/python-rule-architecture.md并参考各语言rules/目录下的既有实现想贡献新语言的可以对照tn/japanese/这类已有模板把数据词表和规则类补齐即可关注底层原理的可以研究 OpenFST 与 Pynini 的图组合、权重分配add_weight与最短路径搜索这些知识在排查复杂 badcase 时会非常有用。项目本身还在持续演进规则词表、语言覆盖和运行时能力都在不断更新。无论你是要做 ASR 后处理、TTS 前处理还是通用文本标准化都可以先从wetn --text 2.5平方电线这行命令开始体验一把文本瞬间变得会说话的感觉。【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考