Skip to content

Fix padded-frame leakage and feature normalization in Parakeet encoder - #808

Merged
jakmro merged 1 commit into
mainfrom
parakeet-pad-mask
Sep 8, 2026
Merged

jakmro merged 1 commit into
mainfrom
parakeet-pad-mask

Conversation

@jakmro

@jakmro jakmro commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

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:

  • Expanded the default audio bucket ladder from (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:

  • Improved Parakeet TDT validation to select the smallest encoder that fits the input, pad features and masks accordingly, and ensure that the encoder hidden states are trimmed to the valid number of frames. Added comprehensive tests for these behaviors. [1] [2]
  • Added explicit creation and handling of the input_features_mask input for the audio encoder in the C++ backend, ensuring correct masking of valid frames. [1] [2]

Convolution module fusion and lowering:

  • Enhanced the convolution module fusion logic to detect and handle an optional mask input, propagate this through the IR, and apply it at the correct stage in the fused module. This includes changes to the matching, schema, optimization, and lowering steps. [1] [2] [3] [4] [5] [6] [7] [8] [9]

PyTorch Parakeet runtime changes:

  • Updated the Parakeet TDT runtime modules to require and use attention and padding masks explicitly in their forward methods, ensuring correct masking during attention and convolution operations. [1] [2] [3]

Minor refactoring:

  • Removed unnecessary namespace scoping from MappedFileRegistry in the C++ graph IO implementation. [1] [2]

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
Copilot AI lite review requested due to automatic review settings September 8, 2026 13:38
@jakmro
jakmro merged commit d6b0edd into main Sep 8, 2026
6 of 8 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants