指南:多語言文本歸一化(ITN/TN)與數(shù)字轉(zhuǎn)讀的完整方案)
FunASR FunTextProcessing 實戰(zhàn)指南多語言文本歸一化ITN/TN與數(shù)字轉(zhuǎn)讀的完整方案【免費下載鏈接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.項目地址: https://gitcode.com/GitHub_Trending/fun/FunASRFunTextProcessingFundamental Text Processing是 FunASR 倉庫內(nèi)隨附的一套基礎(chǔ)文本處理 Python 工具包圍繞 ASR語音識別與 TTS語音合成場景提供逆向文本歸一化ITN, Inverse Text Normalization、**正向文本歸一化TN, Text Normalization與數(shù)字轉(zhuǎn)讀num2words**三類核心能力。本文以 fun_text_processing/README.md 為骨架結(jié)合倉庫源碼深入講解其工作原理、CLI 與 Python API 用法、多語言支持矩陣、語法圖WFST緩存機制、評估與導出工具幫助你在 ASR 結(jié)果后處理與 TTS 前端文本預處理兩條鏈路上直接落地這套方案。1. FunTextProcessing 是什么定位與能力全景在完整語音鏈路中文本形態(tài)存在兩個方向的轉(zhuǎn)換需求ASR 側(cè)識別模型輸出的是口語化文本例如twelve kilograms、dua ribu dua puluh dua需要還原成便于展示、檢索和二次消費的書面形式12 kg、2022這一過程稱為逆向文本歸一化ITNTTS 側(cè)合成系統(tǒng)通常要求輸入朗讀形態(tài)的文本例如把12 kg展開成twelve kilograms這一過程稱為正向文本歸一化TN數(shù)字轉(zhuǎn)讀num2words在部分語言中直接把數(shù)字轉(zhuǎn)換為單詞形式是 TN 內(nèi)部能力的重要組成。依據(jù) fun_text_processing/README.md 的官方聲明FunTextProcessing 同時支持上述三種能力且具備多語言覆蓋能力官方聲明支持規(guī)模倉庫內(nèi)實際語言實現(xiàn)按源碼核實逆向文本歸一化ITN10 種語言en、id、ja、es、pt、ru、de、fr、vi、ko、zh、tl共12 種正向文本歸一化TN5 種語言en、de、es、ru、zh共5 種ru僅支持非確定性模式數(shù)字轉(zhuǎn)讀num2words50 種語言借由第三方num2words庫提供語言清單來自 inverse_normalize.pyITN 的--language可選值與 normalize.pyTN 的--language可選值中的參數(shù)定義其中 ITN 額外支持tl菲律賓語與vi越南語其規(guī)則目錄分別位于 inverse_text_normalization/tl 與 inverse_text_normalization/vi。從源碼結(jié)構(gòu)看每種語言都遵循統(tǒng)一的taggers/分類器與verbalizers/言語化器兩段式目錄組織。2. 核心原理基于 WFST 的 Tagger Verbalizer 兩段式管線FunTextProcessing 的歸一化實現(xiàn)并非簡單的規(guī)則表查替換而是基于**加權(quán)有限狀態(tài)轉(zhuǎn)換器WFST**構(gòu)建的語法圖grammar底層依賴 OpenFst 的 Python 綁定Pynini。整條管線可以拆成四個環(huán)節(jié)Tagging打標將輸入文本送入ClassifyFst分類語法圖識別出數(shù)字、日期、貨幣、度量衡、電話等半符號類semiotic classes并打上標簽Parsing解析用 TokenParser 把帶標簽的文本解析成嵌套字典例如tokens { money { integer: 20 currency: $ } }Permutation排列對嵌套標簽生成可能的重排序列見 normalize.py 中的_permute與generate_permutations以覆蓋復合標簽內(nèi)部成分的多種語序Verbalization言語化將標簽序列送入VerbalizeFinalFst言語化語法圖輸出最終目標形態(tài)文本。以 ITN 為例InverseNormalizer 在初始化時按語言動態(tài)導入對應的ClassifyFst與VerbalizeFinalFst并組合出self.tagger、self.verbalizer、self.parser三個組件其轉(zhuǎn)換方向為口語 → 書面例如twelve kilograms - 12 kg。而正向的 Normalizer 方向相反例如12 kg - twelve kilograms。值得一提的實現(xiàn)細節(jié)在正向歸一化的normalize()方法中normalize.py輸入文本會先經(jīng)pynini.escape轉(zhuǎn)義再與self.tagger.fst做組合text self.tagger.fst得到標簽格lattice隨后用pynini.shortestpath取最短路徑作為標簽結(jié)果言語化階段同樣取最短路徑。為了控制組合爆炸_split_tokens_to_reduce_number_of_permutationsnormalize.py會把令牌序列切分為若干段使每段產(chǎn)生的排列數(shù)不超過max_number_of_permutations_per_split默認 729這是大規(guī)模語料歸一化時保持性能的關(guān)鍵機制。3. 環(huán)境準備Pynini 安裝與語法圖緩存FunTextProcessing 的核心運行時依賴是pynini以及regex、joblib、tqdm。倉庫提供了開箱即用的安裝腳本 install_pynini.sh#!/bin/bash if [[ $OSTYPE darwin* ]]; then conda install -c conda-forge -y pynini2.1.5 else pip install pynini2.1.5 fi即macOS 下通過 conda-forge 安裝pynini2.1.5其他平臺通過 pip 安裝同一版本。安裝完成并確認import pynini成功后即可使用。關(guān)于.far語法圖緩存每次構(gòu)造ClassifyFst/VerbalizeFinalFst時程序會嘗試在cache_dir目錄中查找或生成.farfinite-state archive語法文件。cache_dir設(shè)為None時每次都會重新構(gòu)建語法圖首次構(gòu)建耗時較長設(shè)置有效目錄后語法圖只編譯一次后續(xù)推理直接復用顯著加快加載速度。overwrite_cacheTrue則強制重新生成緩存。這一行為在 inverse_normalize.py 與 normalize.py 的構(gòu)造函數(shù)文檔中均有明確說明。4. 逆向文本歸一化ITN把 ASR 口語結(jié)果還原為書面文本ITN 是 FunTextProcessing 中與 ASR 結(jié)合最緊密的能力README 給出的示例腳本即針對此功能。4.1 命令行用法test_filefun_text_processing/inverse_text_normalization/id/id_itn_test_input.txt python fun_text_processing/inverse_text_normalization/inverse_normalize.py --input_file $test_file --cache_dir ./itn_model/ --output_file output.txt --languageid其中fun_text_processing/inverse_text_normalization/id/id_itn_test_input.txt是倉庫自帶的印尼語 ITN 測試輸入內(nèi)容為一行一句的口語化數(shù)字文本例如dua ribu dua puluh dua sembilan ribu sembilan ratus sembilan puluh sembilan dua puluh empat maret seribu tujuh puluh enam rupiah經(jīng)過 ITN 后會輸出2022、9999、24 maret、1076 rupiah這類書面形式。倉庫同樣提供了日語測試輸入 ja_itn_test_input.txt其內(nèi)容涵蓋漢字數(shù)字、序數(shù)詞第一、第二…、分數(shù)五分の一、日期零六年四月、金額十億円等復雜日語書面/口語混合場景。4.2 CLI 參數(shù)完整說明依據(jù) inverse_normalize.py 的參數(shù)定義inverse_normalize.py支持以下參數(shù)參數(shù)類型默認值說明--textstr無直接輸入單條待轉(zhuǎn)換文本與--input_file互斥--input_filestr無輸入文件路徑每行一條文本--output_filestr無輸出文件路徑不指定時結(jié)果打印到控制臺--languagestren語言可選en/id/ja/de/es/pt/ru/fr/vi/ko/zh/tl--verbose布爾False打印中間標簽信息用于調(diào)試--overwrite_cache布爾False置為 True 時重新生成.far語法文件--cache_dirstrNone.far語法文件目錄None時不使用緩存--enable_standalone_numberstrTrue是否啟用獨立數(shù)字轉(zhuǎn)換僅日語生效通過str2bool解析--enable_0_to_9strTrue是否啟用 0~9 單獨數(shù)字轉(zhuǎn)換僅日語生效其中--enable_standalone_number與--enable_0_to_9兩個開關(guān)僅對ja日語生效從 inverse_normalize.py 的入口邏輯可見只有l(wèi)anguage ja時這兩個參數(shù)才會被傳入InverseNormalizer其他語言一律使用默認行為。這兩個開關(guān)主要控制日語中獨立數(shù)字如三→3與個位數(shù)0~9是否進行書面化轉(zhuǎn)換日語場景中大量存在的人名、專有名詞如安倍晉三、山本五十六依賴其關(guān)閉來避免誤轉(zhuǎn)。4.3 Python API 用法除命令行外InverseNormalizer可直接在 Python 代碼中調(diào)用例如嵌入 ASR 后處理服務(wù)from fun_text_processing.inverse_text_normalization.inverse_normalize import InverseNormalizer normalizer InverseNormalizer( langid, cache_dir./itn_model/, # 語法圖緩存目錄 overwrite_cacheFalse, ) # 單條轉(zhuǎn)換口語 - 書面 text normalizer.inverse_normalize(dua ribu dua puluh dua, verboseFalse) # 批量轉(zhuǎn)換 texts normalizer.inverse_normalize_list([tiga ribu, empat belas], verboseFalse)inverse_normalize()接受單條字符串并返回書面形式inverse_normalize_list()接受字符串列表并返回列表inverse_normalize.py。注意ITN 的輸入默認期望是小寫且除撇號與連字符-外無標點的口語文本見類文檔字符串這正是 ASR 解碼結(jié)果的典型形態(tài)。5. 正向文本歸一化TN為 TTS 準備朗讀文本5.1 命令行用法與參數(shù)正向歸一化入口為 normalize.pyCLI 參數(shù)定義在 normalize.py參數(shù)類型默認值說明--text/--input_filestr無單條文本或文件輸入互斥必須二選一--output_filestr無輸出文件路徑--languagestren語言可選en/de/es/zhru需使用normalize_with_audio.py--input_casestrcased輸入大小寫可選lower_cased/cased--verbose布爾False打印中間標簽信息--punct_post_process布爾False歸一化后對標點做后處理以匹配輸入--punct_pre_process布爾False歸一化前對標點做預處理例如[25]→[ 25 ]--overwrite_cache布爾False重新生成.far語法文件--whiteliststrNone白名單替換文件路徑--cache_dirstrNone語法圖緩存目錄典型用法python fun_text_processing/text_normalization/normalize.py --language en --text I bought 12 kg of apples --input_case cased輸出應為I bought twelve kilograms of apples一類的朗讀形態(tài)。Normalizer構(gòu)造時要求input_case必須為lower_cased或cased之一normalize.py。5.2 白名單whitelist機制--whitelist允許用戶提供自定義的精確字符串映射文件用于處理語法圖覆蓋不到的領(lǐng)域詞或?qū)S锌s寫。該文件路徑會被os.path.abspath規(guī)范化后傳入ClassifyFstnormalize.py在分類階段做硬性替換。英文 TN 的白名單數(shù)據(jù)文件位于 text_normalization/en/data/whitelist 對應目錄下可參照其格式自定義。5.3 中文 TN 管線三段式處理詳解對于中文text_normalization/zh/README.md 明確將 TN 管線拆為三部分可作為理解所有語言 TN 實現(xiàn)的參照① 預處理Pre-Processing全角轉(zhuǎn)半角蘋果宣布發(fā)布新→蘋果CEO宣布發(fā)布新IPHONE完整映射表見 text_normalization/zh/data/char/fullwidth_to_halfwidth.tsv去除列表Denylist可自定義刪除啊、呃等語氣填充詞列表見data/denylist/denylist.tsv。② 非標準詞NSW歸一化覆蓋以下類別并給出真實樣例摘自該 README數(shù)字共465篇約315萬字→共四百六十五篇約三百一十五萬字分數(shù)總量的1/5以上→總量的五分之一以上百分比同比增長6.3%→同比增長百分之六點三日期2002/01/28→二零零二年一月二十八日時間8月16號12:00之前→八月十六號十二點之前數(shù)學比分定格在78:96→比分定格在七十八比九十六貨幣價格是13.5→價格是十三點五元度量衡重達25kg→二十五千克、最高氣溫38°C→三十八攝氏度號碼串可以打我手機13501234567→可以打我手機一三五零一二三四五六七兒化音去除這兒有只鳥兒→這有只鳥白名單見data/erhua/whitelist.tsv白名單替換C E O→CEO、O2O→O to O文件見data/whitelist/default.tsv。③ 后處理Post-Processing可選啟用標點去除英文大小寫轉(zhuǎn)換OOV 標記將字符集外的字用oov標簽包裹例如我們??→我們oov?/oovoov?/oov字符集可經(jīng)data/char/charset_extension.tsv擴展。這套預處理 NSW 分類 后處理的架構(gòu)在 data_loader_utils.py 中也有對應實現(xiàn)pre_process()data_loader_utils.py負責給[]等符號兩側(cè)加空格post_process_punct()data_loader_utils.py則根據(jù)原始輸入把歸一化結(jié)果中的標點空格還原到與輸入一致的位置——這對 TTS 前端至關(guān)重要避免引號、逗號位置漂移導致朗讀斷句錯誤。5.4 非確定性歸一化normalize_with_audio.py當一條文本存在多種合理歸一化方式例如金額既可讀作ten dollars也可讀作$10時normalize_with_audio.py 提供先生成多種候選再用 ASR 轉(zhuǎn)錄結(jié)果按 CER 擇優(yōu)的高級方案它繼承Normalizer并以deterministicFalse構(gòu)造normalize_with_audio.py從而輸出多個歸一化候選輸入可以是單條--text、音頻 文本、或包含audio_data/text/pred_text字段的 JSON manifestselect_best_match()normalize_with_audio.py對每個候選計算與 ASR 預測文本的CER選擇最低者作為最終歸一化結(jié)果若 CER 超過--cer_threshold默認 100則放棄歸一化語言支持en/ru/de/es其中英文還支持--lm模式WFSTLM 融合僅英文可用俄語注釋明確僅支持非確定性模式請使用本腳本normalize.py。6. 效果評估run_evaluate.py 與 15 類半符號類別兩個run_evaluate.pyITN 版 與 TN 版提供了標準的離線評測入口。評測數(shù)據(jù)采用 Kaggle Google 文本歸一化數(shù)據(jù)格式每行三列semiotic class\tunnormalized text\tnormalized text。評測支持兩個粒度句子級Sentence level對整句做歸一化/逆歸一化后計算準確率Token 級Token level按類別分別統(tǒng)計準確率并輸出按 token 數(shù)加權(quán)的總準確率及匯總表。腳本默認輸出包含所有類別的對照表類別即known_typesdata_loader_utils.pyPLAIN DATE CARDINAL LETTERS VERBATIM MEASURE DECIMAL ORDINAL DIGIT MONEY TELEPHONE ELECTRONIC FRACTION TIME ADDRESS共 15 個半符號類別。ITN 評測還支持--cat參數(shù)只評測單個類別如--cat CARDINAL--filter參數(shù)則調(diào)用對應語言的clean_eval_data.py清洗數(shù)據(jù)僅英文實現(xiàn)。評測的準確率計算邏輯見 data_loader_utils.py 的evaluate()對預測與標簽統(tǒng)一做clean_generic去空白、轉(zhuǎn)小寫后逐條比較。7. 部署加速把語法圖導出為 .far 文件在生產(chǎn)環(huán)境中重復構(gòu)建 WFST 語法圖的開銷不可忽略。兩個export_models.py用于把語法圖一次性編譯并導出為.far歸檔文件供運行時通過cache_dir直接加載# ITN導出 en_itn_tagger.far 與 en_itn_verbalizer.far python fun_text_processing/inverse_text_normalization/export_models.py --language en --export_dir ./itn_grammars/ # TN導出 en_tn_tagger.far 與 en_tn_verbalizer.far含 input_case 參數(shù) python fun_text_processing/text_normalization/export_models.py --language en --input_case cased --export_dir ./tn_grammars/ITN 版支持de/en/es/fr/id/ja/ko/pt/ru/vi/zh共 11 種語言inverse_text_normalization/export_models.pyTN 版支持de/en/es/ru/zhtext_normalization/export_models.py。導出文件名遵循lang_itn_tagger.far、lang_itn_verbalizer.far、lang_tn_tagger.far、lang_tn_verbalizer.far的命名規(guī)范。之后在InverseNormalizer/Normalizer中傳入cache_dir./itn_grammars/即可跳過首次編譯直接復用離線導出的語法圖。8. 在 FunASR 語音鏈路中的典型集成場景作為隨 FunASR 倉庫分發(fā)的文本處理工具FunTextProcessing 主要服務(wù)于兩類下游場景ASR 結(jié)果后處理FunASR 的 SenseVoice 系列模型在解碼時通過|withitn|/|woitn|特殊 token 控制是否輸出 ITN 后的文本相關(guān) token 映射見 funasr/utils/postprocess_utils.py。對于未內(nèi)置 ITN 的識別結(jié)果可直接調(diào)用InverseNormalizer完成口語到書面的還原再進入標點、熱詞等下游模塊TTS 前端文本預處理合成前用Normalizer含 whitelist、punct 前后處理把含數(shù)字、符號、單位的書面文本展開為朗讀形態(tài)保障合成讀音正確。從實現(xiàn)上看InverseNormalizer直接復用了Normalizer的normalize_list()/normalize()骨架inverse_normalize.py兩者共享同一套 tagger→parser→permutation→verbalizer 執(zhí)行鏈因此無論集成到 FunASR 的 Python 推理腳本還是獨立微服務(wù)調(diào)用范式保持一致。9. 致謝與許可說明依據(jù) fun_text_processing/README.md 的聲明大量代碼借鑒自 NVIDIANeMoITN/TN 的 WFST 架構(gòu)中文逆向文本歸一化參考了WeTextProcessingwenet-e2e的實現(xiàn)數(shù)字轉(zhuǎn)單詞num2words功能在部分語言中借用了第三方num2words庫的代碼。許可證方面本項目以MIT License發(fā)布同時包含部分來自其他倉庫、遵循其他開源許可證的第三方組件與修改代碼。FunTextProcessing 目錄下的核心實現(xiàn)、測試輸入如 id_itn_test_input.txt與中文 TN 的完整管線文檔text_normalization/zh/README.md均可直接在倉庫中查閱作為擴展自定義語言規(guī)則與業(yè)務(wù)集成的起點。10. 快速上手速查表需求命令/代碼安裝依賴bash fun_text_processing/install_pynini.sh命令行 ITNpython fun_text_processing/inverse_text_normalization/inverse_normalize.py --input_file file --cache_dir ./itn_model/ --output_file out.txt --languageidPython ITNInverseNormalizer(langid, cache_dir./itn_model/).inverse_normalize(text)命令行 TNpython fun_text_processing/text_normalization/normalize.py --language zh --text 共465篇約315萬字非確定性 TNpython fun_text_processing/text_normalization/normalize_with_audio.py --text RAW TEXT --language en評估 ITN/TNpython fun_text_processing/inverse_text_normalization/run_evaluate.py --input data --lang en導出語法圖python fun_text_processing/inverse_text_normalization/export_models.py --language en --export_dir ./itn_grammars/使用提示大批量處理時務(wù)必指定--cache_dir以復用.far語法文件輸入超過約 500 詞時Normalizer會輸出告警normalize.py建議先經(jīng)split_text_into_sentences()切句后再批量歸一化以規(guī)避排列組合導致的耗時增長?!久赓M下載鏈接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.項目地址: https://gitcode.com/GitHub_Trending/fun/FunASR創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考