如何让机器正确读懂数字与日期WeTextProcessing 文本归一化实战指南【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing语音合成要把 2.5平方电线 读成 二点五平方电线语音识别要把 下午三点二十分开会 还原为 15:20开会这就是文本归一化Text NormalizationTN与逆文本归一化Inverse Text NormalizationITN。WeTextProcessing 正是解决这类问题的多语言开源工具包基于 FST、支持中英日三语、生产环境验证过。一句话说清它的价值把文本与读法互转这件事从无穷无尽的正则修补变成一套可组合、可维护、可追踪的规则工程。先把场景摆出来语音系统里绕不开的最后一公里你写过这样的代码吗为了让一段文本读得顺口写了一串又一串正则。今天补一个日期格式(\d{4})年(\d{1,2})月明天又冒出新写法 299.99、5kg、1.5倍每种格式都加一条规则表越来越厚彼此还互相打架——2023 到底是年份、数量还是编号同一个字符串在不同上下文里意思完全不同正则根本管不过来。ASR 和 TTS 都有这个最后一公里模型吐出的文本和人实际想看的文本不是一回事。ASR 输出口语化的 下午三点二十分开会你存日程时想要 15:20TTS 收到 5kg得读成 五千克 才像人话。WeTextProcessing 把这两类需求分别做成了 ITN 和 TN 两条流水线。它凭什么能解决三个关键设计决策决策一规则构建在 FST 之上而不是 if-else 之上。FST有限状态转换器可以理解成一张带输出的状态机。它有三个对工程极友好的特性确定——同一输入永远得到同一输出可组合——数字规则和单位规则能拼出 5kg → 五千克快——编译后处理一条文本接近线性时间。项目用 OpenFST 和 Pynini 实现规则在 Python 里声明编译成一张张 FST 图之后每次处理都只是在这张图上走一遍。决策二tagger 与 verbalizer 分离这是最值得借鉴的一点。流水线分两段tagger 负责扫描输入把非标准写法分类打标签并原样保留字段verbalizer 负责把标签翻译成目标文本。以中文 TN 的输入12为例tagger 只标注value: 12转成十二是 verbalizer 的事。这样设计的好处是你随时能拿到输入的第几个字符变成了输出的第几个字符这种精确对齐信息——normalize_with_mapping就依赖这一点做哪里被改写了的高亮展示特别方便。决策三规则与数据分离缓存按内容寻址。想改某个转换大部分时候不用动代码改data目录下的 TSV 文件就行比如tn/chinese/data/number/digit.tsv里躺着每个数字的映射表。而编译好的 FST 图按配置 规则源码 数据文件的指纹做缓存改了规则下次构建自动失效重编没改直接复用秒级加载。两条命令跑通双向转换装包、运行十秒钟就能体验pip install WeTextProcessing wetn --text 2.5平方电线 # 输出二点五平方电线 weitn --text 二点五平方电线 # 输出2.5平方电线用 Python 也一样而且能见识到它最实用的一个开关enable_0_to_9from tn.chinese.normalizer import Normalizer from itn.chinese.inverse_normalizer import InverseNormalizer zh_tn Normalizer(remove_erhuaTrue) # 去除儿化音 zh_itn InverseNormalizer(enable_0_to_9False) # 独立个位数字不转换 print(zh_tn.normalize(2023年12月25日花费299.99买了5kg苹果)) # 二零二三年十二月二十五日花费二百九十九点九九元买了五千克苹果 print(zh_itn.normalize(下午三点二十分开会)) # 15:20开会注意enable_0_to_9False的含义单独出现的个位数字保持中文不转避免把九和六这类自然语言误写成 9 和 6。这类细粒度开关正是规则系统在真实数据上打磨出来的痕迹。底层原理一条可追踪的翻译流水线把整个处理过程想象成工厂里的传送带预处理全角转半角、繁体转简体、黑白名单过滤对应full_to_half、traditional_to_simple等开关核心转换传送带依次经过多个工位每个工位负责一类非标准写法——数字、日期、时间、金额、度量单位、数学符号。每个工位就是一张 FST 子图用add_weight调节彼此的优先级后处理去儿化音remove_erhua、清理标点、可选地给未登录词打标记tag_oov。FST 的权重机制还顺带带来了一个福利n-best 输出。normalize(输入文本, nbest3)能返回多个按概率排序的结果ASR 场景里可以让下游再选一次比一刀切多了一条退路。实战避坑这些坑提前知道能省半天缓存什么时候要重建日常使用保持默认即可只有改了规则源码或数据文件后想强制重编才传overwrite_cacheTrue。缓存默认落在系统用户缓存目录不会污染项目目录。改规则前先读架构文档。仓库里docs/python-rule-architecture.md明确定义了 tagger 与 verbalizer 的职责边界。在 tagger 里做不可逆的语义改写比如直接把12改成十二是违反契约的会让输入输出 span 对齐失效。C 运行时有个容易踩的坑。性能敏感场景可以用runtime/下的 C 版本processor_main --tagger xx.fst --verbalizer xx.fst。但注意Python 缓存里的 bundle 是内部格式不能直接喂给 C需要单独导出一对兼容的 tagger/verbalizer 图文件。想拿对齐信息做可视化用normalize_with_mapping返回的每个 mapping 都带token_type比如 math、date标明是哪条规则改写了哪段文本。它适合谁用和同类方案怎么比如果你在做这几件事它大概率对你有用ASR 后处理把识别出的口语文本转回标准书写格式ITNTTS 前处理把数字、日期、金额转成发音友好的文本TN语料清洗把不同来源的文本统一成同一套数字格式。和同类方案对比它最鲜明的特点是轻和透明。NVIDIA NeMo 也提供 TN/ITN但依赖较重、和自家工具链绑定更深WeTextProcessing 的核心只有规则加几张图规则全部是可见可改的 Python 和 TSV出了 badcase 能直接定位到某条规则去修还提供 C 运行时方便嵌入自己的服务。代价也很诚实它是规则系统覆盖质量取决于规则是否完善遇到完全没见过的写法它不会自己学会。下一步从第一个例子开始pip install WeTextProcessing把上面的示例跑一遍感受双向转换想改规则读docs/python-rule-architecture.md往某个 TSV 里加一两个映射用overwrite_cacheTrue看效果遇到 badcase按项目规范补一条规则、配一个测试提交回来这类项目最欢迎的就是真实数据里的反例。需要动手开发时可以 clone 仓库git clone https://gitcode.com/gh_mirrors/we/WeTextProcessing。文本归一化是个脏活但把脏活做成干净的规则工程正是这个项目最有价值的地方。【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考