Repository navigation
fix(frontend): stop cmvn readers from crashing on blank lines or returning empty statistics - #3760
Conversation
Both package cmvn readers index line_item[0] and lines[i + 1] without checking, so a blank or whitespace-only line anywhere in the file (trailing newline at EOF, a separator between sections) aborts frontend construction with IndexError, and a file whose tags the walker does not recognize returns empty statistics that only fail much later at inference. Skip blank lines, bound the lookahead, and raise a ValueError naming the file when neither <AddShift> nor <Rescale> parsed.
LauraGPT
left a comment
There was a problem hiding this comment.
Reviewed exact head d0b9cc9 against current-main integration. New CMVN cases first fail on old runtime (2 failures / 3 passes), then all 5 selected cases pass. Independent checks cover 30 parser boundaries including empty, partial, truncated, blank/CRLF input and preserved values/dtypes. Replaying the shipped am.mvn with the reporter's blank-line edits and actual WavFrontend construction gives 6 failures / 3 passes before the fix, then 9 passes with exactly unchanged statistics. The current NumPy matrix runs pass 181 tests + 10 subtests in each lane; all 433 exported package Python files match the tested Git tree after restoring omitted setup.py in the test snapshot. Both approved head workflows now succeed; both NumPy artifacts show 123 entries, zero failures/errors/skips, exact head source and all three added regressions. The only main advance since runtime validation is #3764's independently validated SDK image links. No blocking findings. Compact single-line CMVN is rejected early, not newly supported; five standalone runtime/export helper copies remain unchanged. Evidence is Linux/Python3.12/CPU, not Windows hardware or checkpoint inference.
Summary
Both cmvn readers in the installed package walk the file line by line and index the result without checking it:
line_item[0]on a blank line raisesIndexError: list index out of range, and the unbounded one-line lookaheadlines[i + 1]raises the same error when a<AddShift>/<Rescale>tag is the last line. Because the parse is a pure line-matching loop, a file whose tags do not start a line on its own (which Kaldi does emit — the whole<Nnet>on one line) matched nothing andload_cmvnreturned empty statistics with no error at all; the failure then only surfaced on the first inference asRuntimeError: The size of tensor a (N) must match the size of tensor b (0).Fixes #3759
Three-line change per reader (
funasr/frontends/wav_frontend.py:15,funasr/frontends/default.py:390):Skipping blank lines first (rather than guarding inside the loop) also makes
<AddShift>+ blank line +<LearnRateCoef>parse, which a per-line guard would silently drop. TheValueErrorfollows the convention the sibling runtime loader already uses (runtime/python/onnxruntime/funasr_onnx/utils/frontend.py:148names the offending cmvn file), and blank-line skipping matches how this repository reads other plain-text input (funasr/bin/realtime_ws.py:1363,funasr/utils/compute_det_ctc.py:59).Type of change
Validation
Measured on
main@66d7a4c2, Python 3.13.7 / numpy 2.5.3 / torch 2.14.1+cpu, Windows, withPYTHONPATHpointed at the worktree (verified by printingfunasr.__file__):RED with only the two source files restored from
origin/mainand the new tests present:python -m pytest -q tests/test_numpy_compatibility.py -k cmvn→ 2 failed, 3 passed.GREEN with the fix: same command → 5 passed; whole file
python -m pytest -q tests/test_numpy_compatibility.py→ 9 passed, including the two pre-existing cmvn tests andtest_frontend_applies_cmvn_and_preserves_padding.Regression guard as a test of its own:
test_cmvn_reader_loads_the_am_mvn_shipped_by_the_runtimeasserts theam.mvnthis repository ships underruntime/triton_gpu/model_repo_sense_voice_small/feature_extractor/still loads as(2, 560)finite values — it passes onmaintoo, so a file that parses correctly today provably does not change.python -m compileall -q funasr/frontends tests/test_numpy_compatibility.py→ exit 0.Formatting: the repository is not black-clean at
main(e.g.funasr/frontends/default.pydocstring block at 392-395 is already reformatted byblack --line-length=100), soblack --checkfails on both the pristine and the patched file. Checked instead thatblack --line-length=100leaves every added line untouched — the only hunks it proposes in these files are pre-existing ones outside my diff.python -m compileall funasr examples testsDocs or links checked
Runtime/deployment command tested
User impact
Paraformer/SenseVoiceusers who pointcmvn_fileat a hand-edited or concatenated.mvnfile — or at a Kaldi artifact written on a single line — currently get either a bareIndexErrorduring frontend construction, or a frontend that builds fine and fails at the firstmodel.generate()call. Both cases now either parse or raise an error that names the file.Notes for reviewers
runtime/(runtime/python/libtorch/,runtime/python/onnxruntime/,runtime/triton_gpu/,export_lfr_cmvn_pe_onnx.py). Those are standalone export/deployment helpers rather than the installed package, so this PR deliberately leaves them alone; the issue lists them.ValueErroris a behaviour change in one narrow case: a cmvn file that yielded empty statistics used to return them. Such a frontend could never produce features (it hit theRuntimeErrorabove on the first call), so this only converts a downstream failure into an actionable one.