Skip to content

Export Parakeet-TDT-CTC to QNN - #3692

Merged
csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:export-parakeet-tdt-ctc-qnn
Jun 22, 2026
Merged

csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:export-parakeet-tdt-ctc-qnn

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Jun 22, 2026 •

Copy link
Copy Markdown
Collaborator

It adds two models

Note that only the CTC branch is exported in this PR. The transducer branch is handled in a separate PR.

https://huggingface.co/nvidia/parakeet-tdt_ctc-1.1b is not included since it throws OOM in GitHub Actions.


See

Summary by CodeRabbit

  • New Features

    • Added support for exporting Parakeet TDT CTC models to QNN format with dynamic build parameters across multiple configurations.
  • Chores

    • Enhanced QNN toolkit download reliability with automatic retry mechanism across multiple export workflows.
    • Updated model export scripts to support configurable feature dimensions and dynamic model parameters.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 22, 2026
@coderabbitai

coderabbitai Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 02ec460c-2b80-46c8-9db6-062d98e7953f

📥 Commits

Reviewing files that changed from the base of the PR and between 6faa814 and 87c3d02.

📒 Files selected for processing (14)
  • .github/scripts/export-qnn/generate_parakeet_tdt_ctc.py
  • .github/workflows/export-paraformer-to-qnn.yaml
  • .github/workflows/export-parakeet-ctc-qnn.yaml
  • .github/workflows/export-parakeet-tdt-ctc-qnn.yaml
  • .github/workflows/export-sense-voice-to-qnn.yaml
  • .github/workflows/export-streaming-zipformer-transducer-to-qnn.yaml
  • .github/workflows/export-x-asr-qnn.yaml
  • .github/workflows/export-zipformer-ctc-to-qnn-20250703.yaml
  • .github/workflows/export-zipformer-transducer-to-qnn.yaml
  • scripts/nemo/qnn/parakeet-ctc/test_onnx.py
  • scripts/nemo/qnn/parakeet-ctc/wrapper.py
  • scripts/nemo/qnn/parakeet-tdt-ctc/run.sh
  • scripts/nemo/qnn/parakeet-tdt-ctc/test_onnx.py
  • scripts/nemo/qnn/parakeet-tdt-ctc/wrapper.py

📝 Walkthrough

Walkthrough

Adds a complete Parakeet TDT CTC ONNX-to-QNN export pipeline: new model scripts (wrapper.py, run.sh, test_onnx.py symlink), a build matrix generator, and a new GitHub Actions workflow covering ONNX export, QNN conversion, binary packaging, and release upload. Also fixes dynamic feature dimension handling in the existing parakeet-ctc scripts and adds a 10-attempt retry loop to the QNN toolkit download step in seven existing workflows.

Changes

Parakeet TDT CTC QNN Export Pipeline

Layer / File(s) Summary
Parakeet TDT CTC model wrapper, run script, and test symlink
scripts/nemo/qnn/parakeet-tdt-ctc/wrapper.py, scripts/nemo/qnn/parakeet-tdt-ctc/run.sh, scripts/nemo/qnn/parakeet-tdt-ctc/test_onnx.py
Adds wrapper.py with ModelWrapper (CTC encoder + decoder) and ONNX export logic, run.sh for dependency install and invocation, and a symlink for test_onnx.py pointing to the shared parakeet-ctc implementation.
Dynamic feat_dim in parakeet-ctc test and wrapper
scripts/nemo/qnn/parakeet-ctc/test_onnx.py, scripts/nemo/qnn/parakeet-ctc/wrapper.py
Updates create_fbank to accept feat_dim instead of hardcoding 80, derives feat_dim from the ONNX model input shape in main(), and uses it when constructing the export input tensor.
Build matrix generator script
.github/scripts/export-qnn/generate_parakeet_tdt_ctc.py
Produces a JSON build matrix by computing the cartesian product of model names, num_seconds values, and soc_info_dict entries via a Config dataclass.
New workflow: triggers, onnx export, artifact collection
.github/workflows/export-parakeet-tdt-ctc-qnn.yaml (lines 1–115)
Defines workflow triggers, concurrency, onnx job matrix, WAV download, run.sh/test_onnx.py execution, model.txt generation, and the collect step that tars and uploads the packaged model artifact.
New workflow: matrix generation job and qnn job setup
.github/workflows/export-parakeet-tdt-ctc-qnn.yaml (lines 116–377)
Adds the generate_build_matrix job that runs the Python matrix script and the qnn job setup: artifact download, Python/venv setup, QNN toolkit download with retry, and dependency installation.
New workflow: QNN conversion, binary packaging, and release upload
.github/workflows/export-parakeet-tdt-ctc-qnn.yaml (lines 378–567)
Implements the qnn Run step (qnn-onnx-converter, config generation, qnn-model-lib-generator, qnn-context-binary-generator, tarball packaging), config artifact upload, and conditional release upload for so/ and binary/ tarballs.

QNN Toolkit Download Retry

Layer / File(s) Summary
Retry loop for QNN toolkit download in existing workflows
.github/workflows/export-paraformer-to-qnn.yaml, .github/workflows/export-parakeet-ctc-qnn.yaml, .github/workflows/export-sense-voice-to-qnn.yaml, .github/workflows/export-streaming-zipformer-transducer-to-qnn.yaml, .github/workflows/export-x-asr-qnn.yaml, .github/workflows/export-zipformer-ctc-to-qnn-20250703.yaml, .github/workflows/export-zipformer-transducer-to-qnn.yaml
Replaces the single curl download with a 10-attempt retry loop that validates the ZIP file size via stat, deletes partial downloads, and sleeps 30 seconds between attempts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • k2-fsa/sherpa-onnx#2815: Introduces the export-zipformer-ctc-to-qnn-20250703 workflow, which this PR modifies to add the same retry download logic.
  • k2-fsa/sherpa-onnx#3666: Introduces the export-x-asr-qnn workflow whose Download toolkit step is updated with the retry loop in this PR.

Suggested labels

size:XL

Poem

🐇 Hop, hop, retrying the curl,
Ten attempts before I unfurl!
TDT CTC takes the stage,
Model wrapper fills the page.
feat_dim no longer fixed at eighty—
The rabbit's pipeline is looking weighty! 🎉

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@csukuangfj csukuangfj changed the title Export parakeet tdt ctc qnn Export Parakeet-TDT-CTC to QNN Jun 22, 2026
@csukuangfj
csukuangfj merged commit 41a3fb5 into k2-fsa:master Jun 22, 2026
1 check was pending
@csukuangfj
csukuangfj deleted the export-parakeet-tdt-ctc-qnn branch June 22, 2026 06:44

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces configuration generation and export scripts for the Parakeet TDT CTC models, alongside updates to the existing Parakeet CTC scripts to dynamically handle feature dimensions. Feedback on the changes highlights a critical NameError in scripts/nemo/qnn/parakeet-ctc/wrapper.py where feat_dim is used without being defined, redundant model loading in scripts/nemo/qnn/parakeet-tdt-ctc/wrapper.py, and a potential shell globbing issue with unquoted brackets in run.sh.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +69 to +70
print("feat_dim", feat_dim)
x = torch.rand(1, feat_dim, args.max_len, dtype=torch.float32)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

The variable feat_dim is used here but it is not defined anywhere in this file, which will cause a NameError at runtime. You should retrieve feat_dim from the model configuration before using it, similar to how it is done in the TDT wrapper.

Suggested change
print("feat_dim", feat_dim)
x = torch.rand(1, feat_dim, args.max_len, dtype=torch.float32)
feat_dim = asr_model.cfg["preprocessor"]["features"]
print("feat_dim", feat_dim)
x = torch.rand(1, feat_dim, args.max_len, dtype=torch.float32)

Comment on lines +53 to +56
asr_model = nemo_asr.models.EncDecCTCModelBPE.from_pretrained(
model_name=args.model_id
)
asr_model = nemo_asr.models.ASRModel.from_pretrained(model_name=args.model_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The model is loaded twice consecutively: first using EncDecCTCModelBPE.from_pretrained and then immediately overwritten using ASRModel.from_pretrained. This is redundant and wastes significant time and memory. You should remove the first redundant load.

    asr_model = nemo_asr.models.ASRModel.from_pretrained(model_name=args.model_id)

set -ex

pip install \
nemo_toolkit['asr'] \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In bash, unquoted square brackets like nemo_toolkit['asr'] can be interpreted as globbing patterns by the shell, which might lead to unexpected behavior or installation failures depending on the files in the current directory. It is safer to quote the package name.

Suggested change
nemo_toolkit['asr'] \
"nemo_toolkit[asr]" \

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

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant