Repository navigation
Fix padded-frame leakage and feature normalization in Parakeet encoder - #808
Merged
Merged
Conversation
The bucketed Parakeet encoder zero-padded normalized log-mel features up to the bucket length but the exported graph had no length mask, so padded frames leaked into real frames through attention and the depthwise conv, and the decoder also walked the padded tail. Short clips lost their last word and gained hallucinated words (MOB-12663). Separately, the engine built the mel filterbank with the HTK scale and no normalization while NeMo uses Slaney/Slaney, and the full encoder was traced to the transpiler's 20 s example asset rather than the configured audio limit. - The encoder takes a required second input, input_features_mask [batch, frames], like the Gemma4 audio encoder. The graph subsamples it by the subsampling factor and applies it the way NeMo does: an additive -10000 key mask on attention and a multiply after the GLU in the conv module. The conv-module fusion accepts that multiply so the fused lowering is kept. - The engine fills the mask up to the copied frame count, decodes only the valid encoder frames in both the one-shot and streaming paths, and rejects bundles without the input. - Parakeet features use the Slaney mel scale and norm; the 4-bit engine now scores the same WER as the official fp32 checkpoint on the CoreApp eval clips. - The Parakeet example is padded to CACTUS_TRANSPILER_MAX_AUDIO_SECONDS (30 s by default) and the default bucket ladder becomes 1, 2, 3, 5, 8, 13, 21 s plus the full window. - io.cpp: define MappedFileRegistry outside the nested GraphFile namespace so the tree compiles again. Claude-Session: https://claude.ai/code/session_01EZYnugf8VMdNDtnK8stdpU
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The masking/padding fixes are consistently implemented across Python and C++ call paths and are backed by targeted new/updated tests for bucket selection, padding, and hidden-state trimming.
Pull request overview
This PR fixes masked/padded-frame leakage in the Parakeet TDT encoder path and aligns feature preprocessing + component-graph execution so validation and runtime use consistent bucket capacities and masking behavior across the Python transpiler and C++ engine.
Changes:
- Extends the default audio bucket ladder (adds 21s) and updates tests/spec generation to build encoder components up to the full 30s capture window.
- Updates Parakeet TDT runtime/graphs to require explicit feature masks, applies masks in attention and convolution paths, and trims encoder hidden states to valid (unpadded) frames during validation/component decode.
- Enhances conv-module fusion/lowering to propagate an optional mask input through IR fusion and apply it at the correct stage in the fused op.
File summaries
| File | Description |
|---|---|
| python/cactus/transpile/tdt_runtime.py | Requires/threads masks through Parakeet encoder attention+conv and updates component spec inputs. |
| python/cactus/transpile/hf_model.py | Selects smallest fitting encoder bucket, pads features/mask for validation, trims hidden states to valid frames. |
| python/cactus/transpile/fusion/conv.py | Detects optional mask multiply in conv-module pattern matching and records mask input. |
| python/cactus/transpile/optimize_graph.py | Adds optional mask value to fused conv_module inputs/attrs. |
| python/cactus/transpile/ops.py | Extends conv_module op schema attrs with has_mask. |
| python/cactus/transpile/lower.py | Lowers conv_module with optional mask multiply between GLU and depthwise conv. |
| python/cactus/transpile/audio_preprocess.py | Expands default bucket ladder to include 21s. |
| python/cactus/convert/tests/test_audio_buckets.py | Updates/extends bucket ladder expectations. |
| python/cactus/convert/tests/test_parakeet_capture.py | Adds tests covering capture-window independence and validation padding/mask trimming behavior. |
| cactus-graph/src/io.cpp | Removes redundant namespace scoping around MappedFileRegistry implementation. |
| cactus-engine/src/transcribe.cpp | Updates Parakeet spectrogram graph computation parameters to match intended normalization/scale behavior. |
| cactus-engine/src/stream.cpp | Applies the same spectrogram parameter update for streaming feature computation. |
| cactus-engine/src/model.cpp | Adds input_features_mask input population and uses valid (subsampled) frame count for commit bounds. |
Review details
- Files reviewed: 13/13 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
This pull request introduces several improvements and bug fixes related to audio preprocessing, Parakeet TDT model handling, and graph optimization for the Cactus engine and transpiler. The most significant changes include expanding the default audio bucket ladder, improving mask handling and padding for Parakeet TDT validation, and enhancing the fusion and lowering of convolution modules with optional mask support.
Audio bucket and preprocessing improvements:
(1, 2, 3, 5, 8, 13)to(1, 2, 3, 5, 8, 13, 21)seconds, updated corresponding tests, and adjusted spectrogram computation parameters to better match Parakeet's requirements. [1] [2] [3] [4] [5] [6] [7]Parakeet TDT validation and masking:
input_features_maskinput for the audio encoder in the C++ backend, ensuring correct masking of valid frames. [1] [2]Convolution module fusion and lowering:
PyTorch Parakeet runtime changes:
forwardmethods, ensuring correct masking during attention and convolution operations. [1] [2] [3]Minor refactoring:
MappedFileRegistryin the C++ graph IO implementation. [1] [2]