文本归一化与逆归一化完整指南:如何用 WeTextProcessing 让多语言文本处理一步到位

📅 发布时间:2026/8/17 18:11:24
文本归一化与逆归一化完整指南:如何用 WeTextProcessing 让多语言文本处理一步到位 文本归一化与逆归一化完整指南如何用 WeTextProcessing 让多语言文本处理一步到位【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing在语音识别、语音合成和文本分析的实际项目中你有没有遇到过这样的场景ASR 输出的识别文本里数字、日期、金额全部是阿拉伯数字形式直接展示给用户没问题但一旦要送入 TTS 朗读读出来就变成了二〇二三还是两千零二十三全靠猜反过来TTS 侧需要把十五点三十分读给用户听可下游系统却需要拿到 15:30 这样的标准格式。这类数字与文字之间的往返翻译正是 WeTextProcessing 这个开源文本归一化与逆文本归一化工具包要解决的痛点。本文将带你从真实问题出发理解文本归一化Text NormalizationTN与逆文本归一化Inverse Text NormalizationITN的原理用最小案例 5 分钟跑通流程再深入 FST 规则引擎的运作机制最后给出进阶玩法与避坑建议——全程可落地读完即可上手。一、先对齐概念归一化到底是翻译还是格式化先看两行直观的对比你就能立刻 get 到这个工具在做什么文本归一化TN2023年12月25日花费299.99购买了5kg苹果→二零二三年十二月二十五日花费二百九十九点九九元购买了五千克苹果逆文本归一化ITN下午三点二十分开会→15:20开会通俗地说TN 是把人写的紧凑符号翻译成适合朗读或进一步处理的完整文本ITN 则反过来把口语化的中文/英文表达还原成计算机喜欢的标准符号。两者就像一对往返的翻译官一个负责把简体话翻成字一个负责把字翻回话。为什么这件事这么重要因为几乎所有语音产品的中间环节都缺不了它ASR 输出的原始文本带有一堆非标准写法NSWTTS 输入又需要标准发音形式数据平台更希望所有数字都是统一格式。WeTextProcessing 的价值恰恰在于它把这两条流水线都做成了开箱即用的生产级组件支持中文、英文、日文且每个方向都有独立的规则与数据目录。二、5 分钟跑通安装到首个结果这一步为什么必不可少因为只有先看到真能跑后面讲原理你才有体感。WeTextProcessing 的安装和调用都极其简单。pip install WeTextProcessing安装完成后你会同时获得wetn和weitn两个命令行工具分别对应归一化与逆归一化# 文本归一化数字、符号 → 可读文本 wetn --language zh --text 2.5平方电线 # 输出: 二点五平方电线 # 逆文本归一化可读文本 → 标准格式 weitn --language zh --text 二点五平方电线 # 输出: 2.5平方电线如果你需要把这段流程集成进自己的 Python 项目代码同样只有几行from tn.chinese.normalizer import Normalizer from itn.chinese.inverse_normalizer import InverseNormalizer zh_tn_model Normalizer(remove_erhuaTrue) # 中文归一化 zh_itn_model InverseNormalizer(enable_0_to_9False) # 中文逆归一化 print(zh_tn_model.normalize(共465篇约315万字)) # 共四百六十五篇约三百一十五万字 print(zh_itn_model.normalize(同比增长百分之六点三)) # 同比增长6.3%有没有注意到从安装到产出结果全程没有写一行规则、没有配置任何额外文件这就是生产就绪的含义——默认配置已经覆盖了绝大多数常见场景。三、它能处理哪些疑难杂症核心能力一览WeTextProcessing 的规则覆盖面比你想象的要广得多。以中文归一化为例它内置了十余类规则每一类都对应独立的规则文件位于tn/chinese/rules/目录类别原始输入归一化输出说明基数数字共计6.42万人共计六点四二万人含小数、百分比分数总量的1/5以上总量的五分之一以上分子分母语序自动调整日期2002/01/28二零零二年一月二十八日兼容/、-、.三种分隔符时间8:00 a.m.准时开会上午八点准时开会含 12/24 小时制、noon 语义货币价格是HKD13.5价格是十三点五港元支持多币种符号与代码度量衡最高气温38°C最高气温三十八摄氏度支持 m²、km/h、ms 等复合单位数学符号比分定格在78:96比分定格在七十八比九十六含正负号、百分号、大于等于电话号码可以拨打12306来咨询可以拨打幺二三零六来咨询数字逐个朗读读幺而非一儿化音我儿子喜欢这地儿我儿子喜欢这地通过白名单精准去除白名单替换O2OO to O处理字母数字混合词更贴心的是它还内置了三个收尾能力全角转半角苹果宣布发布新→苹果宣布发布新IPHONE语气词清除呃这个呃啊我不知道→这个我不知道未登录词标记我们안녕→我们oov안/oovoov녕/oov对 OOV 打标签方便你后续决策英文方向同样能力齐整序数词、小数、电子邮箱/网址、电话、时间、货币、罗马数字都在tn/english/rules/下各有归宿。也就是说中英日三种语言你只需学会同一套 API。四、核心机制藏在 FST 规则引擎里的三层流水线理解了能做什么我们再拆一层看看怎么做到的。WeTextProcessing 的底层是有限状态转换器FST——你可以把它想象成一张巨大的状态地图输入文本在图上走一遍每走一步就产出一个输出字符。这种机制的三大好处值得记下来确定性同样的输入永远得到同样的输出方便测试与回归高性能图编译完成后匹配是接近线性的扫描一次走完可组合不同类别的规则像积木一样拼装互不干扰。在具体实现上整条流水线被清晰地拆成三个阶段第一阶段预处理字符级清理。全角转半角、符号映射、黑名单过滤都在这一层完成相当于先洗澡再体检。第二阶段非标准词识别与转写核心。这里采用标注器tagger 转写器verbalizer的双层设计这是本项目最值得学习的架构思想tagger 只负责认出这是什么东西并且原样保留输入片段。比如看到12它只标记为value: 12绝不在这一层把12改成十二verbalizer 才负责真正的语义转换把原始字段12转成十二。为什么非要拆两层因为只有让 tagger 原样保留输入系统才能提供normalize_with_mapping()这个杀手级 API——它能把哪个输入片段被改成了哪个输出片段精确对应起来而不是靠文本 diff 去猜result 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 十二这个能力在做语音识别结果的对齐、标注数据清洗、badcase 定位时价值极大。比如你想知道某条 ASR 结果里到底是哪个词被归一化器改坏了直接读 mappings 就能精准定位不用再整句人工比对。第三阶段后处理输出整理。去除语气词、整理标点、繁体转简体、OOV 打标都在这里完成。你可以在tn/chinese/normalizer.py里看到这个流水线的完整拼装过程每类规则以RuleSpec(规则实例, 权重)的形式注册进统一的规则清单tagger 和 verbalizer 都从同一份清单构建从源头杜绝新增了规则却只加进一半的隐患。五、进阶玩法从能用到好用的四个技巧5.1 用参数控制边界行为而不是改代码中文归一化器提供了多个开关参数建议你根据业务场景精确配置normalizer Normalizer( remove_erhuaTrue, # 是否去除儿化音口语场景建议开 traditional_to_simpleTrue, # 繁体转简体 remove_punctsFalse, # 是否去除标点保留下游可能需要 full_to_halfTrue, # 全角转半角 tag_oovFalse, # 是否标记未登录词 )逆归一化器同样有enable_0_to_9是否把单独出现的一到九也转成数字和enable_standalone_number是否转换独立数字等开关。先调参数再动规则是投入产出比最高的优化顺序。5.2 理解缓存机制别在性能上踩坑FST 图的构建是有成本的所以 WeTextProcessing 默认做了持久化缓存首次调用会构建并缓存编译好的图之后直接复用。缓存目录遵循操作系统惯例Linux 下是~/.cache/wetextprocessing你可以这样控制# 开发期规则改动了强制重建 normalizer Normalizer(overwrite_cacheTrue) # 生产期复用已编译图秒级加载 normalizer Normalizer(overwrite_cacheFalse) # 完全禁用持久化缓存临时环境 normalizer Normalizer(cache_dirFalse)更省心的是缓存键会自动包含配置参数、规则源码与数据文件的指纹——也就是说你改了任何规则或数据下次运行时会自动感知并重新构图不需要手动清理缓存。生产环境建议预先把模型预热一遍避免首次请求触发编译延迟。5.3 改 badcase数据优先规则兜底遇到转换错误的 badcase处理优先级建议是先看是否缺白名单词条多数错词其实是未收录词往data/default/whitelist.tsv里加一行往往就解决了再看是否需要更新 TSV 数据文件比如新增货币符号、度量单位最后才考虑修改tn/chinese/rules/下的规则逻辑。所有数据文件都是纯文本 TSV 格式改起来零门槛。改完规则后用python -m tn --text 你的测试输入 --overwrite_cache即可立即验证效果。5.4 用 n-best 输出兜底歧义当输入存在多种合法解读时例如12块5既可能是钱也可能是数量归一化器还支持 n-best 输出把可能性都给你outputs zh_tn_model.normalize(输入文本, nbest3) # nbest1 返回字符串nbest1 返回候选列表配合normalize_with_mapping(nbest3)还能拿到每个候选的片段级映射非常适合接入下游打分模型做二次消歧。六、典型应用场景这三类系统最适合引入它场景一ASR 结果后处理。语音识别输出往往是用户余额为1234.56元这种混合文本直接展示给用户不够规范。接一层 TN 后输出变成用户余额为一千二百三十四点五六元同时还能顺带清理语气词和全角字符识别结果的可读性立刻上一个台阶。场景二TTS 前端文本标准化。TTS 系统最怕的就是数字读法不统一2023到底读二零二三还是两千零二十三取决于它出现在年份还是数量场景。WeTextProcessing 内置了日期、时间、金额等上下文敏感的读法规则能在送入语音合成前把文本处理成确定性的发音形式。场景三数据平台的格式统一。如果业务里同时流入价格$99.99重量5kg时间14:30等五花八门的字段用归一化器统一成九十九点九九美元五千克十四点三十分后续的存储、检索、分析都会省心很多。值得一提的是项目还提供了 C 运行时runtime/目录支持把编译好的 FST 图导出后在性能敏感的服务端使用Python 负责快速迭代规则C 负责扛生产流量——两条路都给你铺好了。七、动手改造前建议你先读这份文档如果你准备新增语言规则或修 bug请务必先读项目里的 docs/python-rule-architecture.md源码目录docs/。这份规则架构说明只有几百行却把最核心的约定讲透了tagger 只分类并原样保留输入verbalizer 才做语义转换。理解并遵守这条契约你的改动才能保持输入输出可映射的特性一旦破坏它normalize_with_mapping的精确对齐就会失效。改造流程参考源码方式运行git clone https://gitcode.com/gh_mirrors/we/WeTextProcessing cd WeTextProcessing pip install -r requirements.txt python -m tn --text 2.5平方电线 --overwrite_cache python -m itn --text 二点五平方电线 --overwrite_cache一句话总结WeTextProcessing 把文本归一化与逆文本归一化这件又琐碎又关键的工程事做成了可配置、可扩展、可解释的生产级组件——你只需要专注业务把格式问题交给它。结语从今天起把文本格式问题交给专业工具文本归一化看似只是数字转汉字、汉字转数字的小事但它牵动着 ASR 的可读性、TTS 的发音正确率和数据平台的一致性。WeTextProcessing 的价值在于把这条链路做成了双向、多语言、可缓存、可映射的完整方案而且上手成本极低一条 pip 命令、两行 Python、默认配置即用。建议你从今天起做三件事跑通最小案例把wetn/weitn命令在你的真实文本上试一遍翻一翻测试用例tn/chinese/test/data/normalizer.txt里全是输入 期望输出的成对样例比任何文档都直观能帮你快速了解能力边界遇到 badcase 先查白名单和数据文件大概率不用动一行规则代码。文本处理的路上能少写的代码就少写能复用的规则就复用。当你把精力从怎么把数字读对解放出来才能真正聚焦在用户需要什么样的文本这件更有价值的事情上。【免费下载链接】WeTextProcessingText Normalization Inverse Text Normalization项目地址: https://gitcode.com/gh_mirrors/we/WeTextProcessing创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考