Repository navigation
fix(runtime): merge spelled-out acronyms into one word in funasr_onnx and funasr_torch sentence_postprocess - #3869
Merged
LauraGPT merged 1 commit intoNov 11, 2026
Conversation
…stprocess abbr_dispose in the funasr_onnx and funasr_torch copies of postprocess_utils.py joins a run of single-letter tokens into one acronym with one [begin, end] timestamp, but still appended every letter as its own word. The 2023 change that builds the acronym as one word (2ab8b7f) only went into funasr/utils/postprocess_utils.py. So for tokens ["我", "用", "a", "i", "写", "代", "码"] with a timestamp per token, the runtime copies return "我 用 A I 写 代 码" with 7 words and 6 timestamps, where the in-tree copy returns "我 用 AI 写 代 码" with 6 and 6. The Paraformer wrappers of both runtimes return only that text and the timestamp list, so splitting preds on spaces pairs every word after the acronym with the next word's time and leaves the last word without one. Without timestamps the text was already right, but the word list was split the same way. Port the in-tree code: build abbr_word and append it once. Extend tests/test_sentence_postprocess_timestamps.py, which checks the three copies against one expectation, with acronyms in Chinese and English text, with and without timestamps.
4 of 9 tasks
LauraGPT
added a commit
that referenced
this pull request
Nov 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3868
In the
funasr_onnxandfunasr_torchcopies ofpostprocess_utils.py,abbr_disposegives a run of single-letter tokens one[begin, end]timestamp, but still appends every letter as its own word. In 2023, 2ab8b7f (#270) changed the in-tree copy to build the acronym as one word (abbr_word) and append it once. That change only went intofunasr/utils/postprocess_utils.py.So with a timestamp model, each extra letter adds a word with no timestamp. Tokens
我 用 a i 写 代 码with one timestamp per token ([i*100, (i+1)*100]):funasr/utils我 用 AI 写 代 码funasr_onnx,funasr_torchonmain我 用 A I 写 代 码funasr_onnx,funasr_torchwith this PR我 用 AI 写 代 码i b m is heregivesI B M is here(5 words, 3 timestamps) andc c t vgivesC C T V(4 words, 1 timestamp). The untimed text is already我用AI写代码, but the returned word list is split the same way.The Paraformer wrappers return
preds,timestampand the unmergedraw_tokens, sopreds.split()is the only word list that can be paired withtimestamp. I ran the realfunasr_onnxParaformer.__call__with onlyinferreplaced by BiCif-shaped outputs (am scores for these tokens,token_num,us_alphas,us_peaks) on a 2 s tone. Onmainit returnspreds='我 用 A I 写 代 码'and 6 timestamps:Igets 写's span,写gets 代's,代gets 码's, and码gets none.funasr_torchParaformer(withort_inferreplaced) gives the same result. With this PR both give我 用 AI 写 代 码and every word keeps its own time.The fix is the in-tree code, in both runtime copies: build
abbr_wordand append it once (4 insertions, 3 deletions per file). After it, the runtimeabbr_disposediffers from the in-tree one only by its docstring and the bounds checks from #2122/#2209. Those are not needed here, because these copies raiseValueErrorfor a token they do not recognise, so every word they return has a timestamp.tests/test_sentence_postprocess_timestamps.pyalready checks the three copies against one expectation. I added two tests at the end of the class:我 用 a i 写 代 码andi b m is here, with timestamps;看 c c t v 新 闻, without timestamps (("看CCTV新闻", ["看", "CCTV", "新", "闻"])).Type of change
Validation
test-text-postprocessing.ymlset, with the pins it installs (pytest 8.1.1, pypinyin 0.55.0, rapidfuzz 3.14.5), on Python 3.10.22 and 3.12.15:main(7651777): 30 passed.mainsource: 2 failed, 30 passed. All 6 failing subtests are thefunasr_onnxandfunasr_torchcopies.I also compared the three copies on 20,000 random token sequences (Chinese, single letters, words,
@@pieces,<unk>,<s>,</s>), with and without timestamps. Onmain, a runtime copy gives a different result from the in-tree copy for thousands of them. With this PR, none differ.Also on this branch (Windows 11, Python 3.11.17, numpy 2.4.6, onnxruntime 1.23.2, torch 2.10.0+cpu):
tests/test_runtime_eval_cli.py tests/test_runtime_eval_native.py: 55 passed.tests/test_paraformer_timestamp_contract.py,tests/test_paraformer_timestamp_padding.pyand both rich transcription test files: all pass.The
funasr_onnxpackage test scripts (overlap,empty_final,punctuation_empty_input) pass from source.tests/test_funasr_torch_package.py: 13 passed, 1 failed. The failure istest_wheel_contains_all_runtime_sources, and it fails onmaintoo, because on Windows the test builds its expected file names with backslashes (str(Path.relative_to)).python -m compileall funasr examples testsDocs or links checked
Runtime/deployment command tested (the wrapper runs above, with the model session replaced)
No real model was run, so I have not seen a model emit these tokens.
abbr_disposeexists to merge runs of single-letter tokens, and the C++ runtime'svocab.cppalso joins consecutive single letters without a space. #1030 describes output such as三角形ABCand力FA, the upper-case form this merge produces.User impact
Users of a timestamp export (4 outputs: BiCif Paraformer such as paraformer-large-vad-punc, or SeACo Paraformer) through
funasr_onnxParaformerandSeacoParaformerorfunasr_torchParaformerget one word per timestamp again when the output contains a spelled-out acronym. The untimed word lists of these wrappers and of thefunasr_onnxstreamingParaformeralso keep the acronym as one word. The returned text without timestamps does not change.Notes for reviewers
abbr_disposein the two runtime copies changes.funasr/utils/postprocess_utils.pyis not touched.sentence_postprocessin the same files and adds tests to the same test file. The hunks do not overlap:git merge-tree --write-treeof this branch and fix(postprocess): keep a trailing @@ piece instead of dropping it #3836's head (84c7b76) gives no conflicts.test-text-postprocessing.ymlalready runs this test file for these paths.