Skip to content

Refactor sense voice impl - #2873

Merged
csukuangfj merged 6 commits into
k2-fsa:masterfrom
csukuangfj:refactor-sense-voice-impl
Dec 8, 2025
Merged

csukuangfj merged 6 commits into
k2-fsa:masterfrom
csukuangfj:refactor-sense-voice-impl

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Dec 8, 2025 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Chores
    • Reduced parallel build jobs during compilation for improved stability and resource management.
    • Consolidated sense-voice implementation across multiple hardware backends into a unified template-based architecture for improved maintainability.

✏️ Tip: You can customize this high-level summary in your review settings.

@csukuangfj
csukuangfj requested a review from Copilot December 8, 2025 04:40
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Dec 8, 2025
@coderabbitai

coderabbitai Bot commented Dec 8, 2025 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@csukuangfj has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 28 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c59ac65 and 2b9a638.

📒 Files selected for processing (1)
  • build-axcl-linux-aarch64.sh (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The PR consolidates provider-specific offline Sense Voice recognizer implementations (ASCEND, AXCL, AXERA, RKNN, QNN) into a unified templated implementation. Provider-specific header files are removed and replaced with a generic template wrapper, with the factory updated to instantiate the template with provider-specific model types.

Changes

Cohort / File(s) Summary
Removed provider-specific Sense Voice implementations
sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h, sherpa-onnx/csrc/axcl/offline-recognizer-sense-voice-axcl-impl.h, sherpa-onnx/csrc/axera/offline-recognizer-sense-voice-axera-impl.h, sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h
Deleted provider-specific implementations of OfflineRecognizerSenseVoice*Impl classes and ConvertSenseVoiceResult declarations for Ascend, AXCL, AXERA, and RKNN backends.
Templated Sense Voice implementation
sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h
Converted from QNN-specific OfflineRecognizerSenseVoiceQnnImpl to generic template OfflineRecognizerSenseVoiceTplImpl<SenseVoiceModel>; added template parameter and Manager-based constructor; updated model instantiation to use template type; added early return guard for empty logits.
Factory integration
sherpa-onnx/csrc/offline-recognizer-impl.cc
Updated Create factory method to instantiate OfflineRecognizerSenseVoiceTplImpl with provider-specific model types (OfflineSenseVoiceModelRknn, OfflineSenseVoiceModelAxera, etc.) across all providers; updated corresponding includes to reference new template and model headers.
Build script optimization
build-axcl-linux-aarch64.sh
Updated environment variable reference in comment (SHERPA_ONNX_AXERA_PATH → SHERPA_ONNX_AXCL_SDK_ROOT); reduced parallel build jobs from -j22 to -j2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify template implementation correctly handles all provider-specific models and their initialization patterns
  • Cross-reference factory changes to ensure each provider is instantiated with the correct model type
  • Check that the template parameter satisfies all interface requirements used by DecodeOneStream, InitFeatConfig, and model-dependent logic
  • Validate the rationale for build parallelism reduction from -j22 to -j2

Possibly related PRs

Poem

🐰 Five homes became one, so neat and so bright,
A template to rule them with logic so tight,
RKNN, AXERA, ASCEND in a row,
Now unified gently in one graceful flow,
Less code to maintain—what a wonderful sight! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor sense voice impl' accurately describes the main change—consolidating multiple provider-specific sense voice implementations into a templated approach.

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.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @csukuangfj, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant refactoring of the Sense Voice offline recognizer. By consolidating platform-specific implementations into a generic templated class, the change aims to streamline the integration of Sense Voice models across different hardware backends like RKNN, Axera, AXCL, Ascend, and QNN. This approach enhances code reusability and simplifies future development and maintenance efforts for these components. Additionally, a minor adjustment was made to a build script to ensure correct environment variable usage and optimize build performance.

Highlights

  • Code Refactoring: The Sense Voice offline recognizer implementations for various hardware platforms (Ascend, AXCL, Axera, RKNN, QNN) have been refactored into a single templated class, OfflineRecognizerSenseVoiceTplImpl.
  • Reduced Duplication: This refactoring eliminates significant code duplication by centralizing the common logic for Sense Voice recognition, making the codebase more maintainable and extensible.
  • Build Script Update: The build-axcl-linux-aarch64.sh script was updated to correct an environment variable name from SHERPA_ONNX_AXERA_PATH to SHERPA_ONNX_ASCL_SDK_ROOT and adjusted the make parallelism.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@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 refactors the sense-voice implementations for different providers (rknn, axera, axcl, ascend, qnn) into a single templated class. This is an excellent change that significantly reduces code duplication and improves maintainability. I've found one minor issue in a build script comment, which I've pointed out. Otherwise, the refactoring looks solid.

Comment thread build-axcl-linux-aarch64.sh Outdated
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

Copilot AI 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.

Pull request overview

This PR refactors the SenseVoice offline recognizer implementations to eliminate code duplication across multiple hardware backends. Previously, each hardware provider (RKNN, Axera, AXCL, Ascend, QNN) had its own nearly identical implementation file. The refactoring consolidates all these implementations into a single template class OfflineRecognizerSenseVoiceTplImpl parameterized by the model type.

Key Changes:

  • Introduced a template-based implementation that accepts different SenseVoice model types as template parameters
  • Removed 5 duplicate implementation files (one for each hardware backend)
  • Updated factory methods to instantiate the template class with appropriate model types
  • Fixed inconsistent empty logits checking (now all backends handle empty results)
  • Fixed minor issues in build script comments and parameters

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h New template-based implementation that replaces all hardware-specific implementations
sherpa-onnx/csrc/offline-recognizer-impl.cc Updated factory methods to use template instantiations; changed includes from hardware-specific impl headers to model headers
sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h Removed duplicate RKNN-specific implementation
sherpa-onnx/csrc/axera/offline-recognizer-sense-voice-axera-impl.h Removed duplicate Axera-specific implementation
sherpa-onnx/csrc/axcl/offline-recognizer-sense-voice-axcl-impl.h Removed duplicate AXCL-specific implementation
sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h Removed duplicate Ascend-specific implementation
build-axcl-linux-aarch64.sh Fixed typo in environment variable comment and corrected make parallel jobs parameter

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# Before you run this file, make sure you have first cloned
# https://github.com/Abandon-ht/axcl_bsp_sdk
# and set the environment variable SHERPA_ONNX_AXERA_PATH
# and set the environment variable SHERPA_ONNX_AXCL_SDK_ROOT

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

Typo in comment: should be SHERPA_ONNX_AXCL_SDK_ROOT instead of SHERPA_ONNX_ASCL_SDK_ROOT (missing 'X'). This matches the actual environment variable name used in the script.

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai 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.

Actionable comments posted: 0

♻️ Duplicate comments (1)
build-axcl-linux-aarch64.sh (1)

24-31: Comment mentions different env var name than the script actually uses

The comment says to set SHERPA_ONNX_AXCL_SDK_ROOT, but the script checks and uses AXCL_SDK_ROOT everywhere (lines 26–31, 33–39, 43–45). That mismatch is likely to confuse users.

I’d recommend aligning them one way or the other; e.g. either:

  • Keep AXCL_SDK_ROOT as the canonical variable and update the comment:
-# and set the environment variable SHERPA_ONNX_AXCL_SDK_ROOT
+# and set the environment variable AXCL_SDK_ROOT

or

  • Rename the script’s variable to SHERPA_ONNX_AXCL_SDK_ROOT consistently.
🧹 Nitpick comments (3)
build-axcl-linux-aarch64.sh (1)

117-118: Consider making the parallel job count configurable instead of hard‑coded -j2

Using -j2 is safe but can be unnecessarily slow on larger machines. If you want slightly more flexibility without losing control, consider something like:

-make VERBOSE=1 -j2
+MAKE_JOBS="${MAKE_JOBS:-2}"
+make VERBOSE=1 -j"${MAKE_JOBS}"

So users can override MAKE_JOBS when they know their hardware limits.

sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h (2)

90-115: Early‑return on empty logits: confirm intended stream result semantics

DecodeOneStream now returns immediately if logits is empty:

std::vector<float> logits = model_->Run(std::move(f), language, text_norm);
if (logits.empty()) {
  return;
}

This avoids computing num_out_frames and calling the decoder with zero frames, which is sensible. However, it also means the OfflineStream’s result is left as-is (likely default/previous) and SetResult is never called.

If DecodeStreams is only ever invoked once per stream and an empty logits output semantically means “no speech / no hypothesis”, this is fine. If you expect an explicit empty result to be set in that case, you might instead construct a default OfflineRecognitionResult and call s->SetResult(...).


81-88: Use of a local config_ copy is consistent with prior pattern but can diverge from base config

InitFeatConfig() updates config_.feat_config, and CreateStream() uses this local config_ rather than the base class’s config. This mirrors the prior SenseVoice impl pattern, but note that calls to OfflineRecognizerImpl::SetConfig() only update the base class’s config, not this local copy.

If dynamic reconfiguration via SetConfig() is not used for SenseVoice, this is fine. Otherwise, consider delegating feature access entirely to the base class config to avoid divergence.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5af7603 and c59ac65.

📒 Files selected for processing (7)
  • build-axcl-linux-aarch64.sh (2 hunks)
  • sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h (0 hunks)
  • sherpa-onnx/csrc/axcl/offline-recognizer-sense-voice-axcl-impl.h (0 hunks)
  • sherpa-onnx/csrc/axera/offline-recognizer-sense-voice-axera-impl.h (0 hunks)
  • sherpa-onnx/csrc/offline-recognizer-impl.cc (12 hunks)
  • sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h (5 hunks)
  • sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h (0 hunks)
💤 Files with no reviewable changes (4)
  • sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h
  • sherpa-onnx/csrc/axcl/offline-recognizer-sense-voice-axcl-impl.h
  • sherpa-onnx/csrc/axera/offline-recognizer-sense-voice-axera-impl.h
  • sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-06T04:23:50.237Z
Learnt from: litongjava
Repo: k2-fsa/sherpa-onnx PR: 2440
File: sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/core/Core.java:4-6
Timestamp: 2025-08-06T04:23:50.237Z
Learning: The sherpa-onnx JNI library files are stored in Hugging Face repository at https://huggingface.co/csukuangfj/sherpa-onnx-libs under versioned directories like jni/1.12.7/, and the actual Windows JNI library filename is "sherpa-onnx-jni.dll" as defined in Core.java constants.

Applied to files:

  • sherpa-onnx/csrc/offline-recognizer-impl.cc
  • sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h
📚 Learning: 2025-08-06T04:18:47.981Z
Learnt from: litongjava
Repo: k2-fsa/sherpa-onnx PR: 2440
File: sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/core/Core.java:4-6
Timestamp: 2025-08-06T04:18:47.981Z
Learning: In sherpa-onnx Java API, the native library names in Core.java (WIN_NATIVE_LIBRARY_NAME = "sherpa-onnx-jni.dll", UNIX_NATIVE_LIBRARY_NAME = "libsherpa-onnx-jni.so", MACOS_NATIVE_LIBRARY_NAME = "libsherpa-onnx-jni.dylib") are copied directly from the compiled binary filenames and should not be changed to match other libraries' naming conventions.

Applied to files:

  • build-axcl-linux-aarch64.sh
🧬 Code graph analysis (1)
sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h (3)
sherpa-onnx/csrc/offline-recognizer-impl.cc (4)
  • OfflineRecognizerImpl (696-747)
  • OfflineRecognizerImpl (750-800)
  • OfflineRecognizerImpl (829-830)
  • OfflineRecognizerImpl (837-838)
sherpa-onnx/csrc/offline-recognizer-impl.h (1)
  • std (36-40)
sherpa-onnx/csrc/rknn/offline-ctc-greedy-search-decoder-rknn.h (1)
  • OfflineCtcGreedySearchDecoderRknn (14-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: Release static tts-OFF
  • GitHub Check: ubuntu-24.04 3.12
  • GitHub Check: ubuntu-24.04 3.9
  • GitHub Check: ubuntu-24.04 3.11
  • GitHub Check: ubuntu-24.04 3.13
  • GitHub Check: ubuntu-24.04 3.8
  • GitHub Check: ubuntu-24.04 3.10
  • GitHub Check: rknn shared OFF
  • GitHub Check: rknn shared ON
  • GitHub Check: Debug shared-ON tts-ON
  • GitHub Check: Debug shared-ON tts-OFF
  • GitHub Check: Debug shared-OFF tts-OFF
  • GitHub Check: Release shared-ON tts-ON
  • GitHub Check: Debug shared-OFF tts-ON
  • GitHub Check: Release shared-OFF tts-OFF
  • GitHub Check: Release shared-OFF tts-ON
  • GitHub Check: Release shared-ON tts-OFF
  • GitHub Check: swift (macos-13)
  • GitHub Check: swift (macos-latest)
🔇 Additional comments (3)
sherpa-onnx/csrc/offline-recognizer-impl.cc (2)

34-62: SenseVoice templated wiring across providers looks consistent

The refactor to route SenseVoice through OfflineRecognizerSenseVoiceTplImpl<OfflineSenseVoiceModelX> for all providers (rknn, axera, axcl, ascend, qnn) appears mechanically consistent:

  • Each provider block includes its corresponding offline-sense-voice-model-*.h.
  • Both Create(const OfflineRecognizerConfig &) and Create(Manager *mgr, ...) use the matching OfflineSenseVoiceModelX template parameter.
  • Existing non-SenseVoice branches (Paraformer, Zipformer CTC, etc.) are preserved as before.

Assuming each OfflineSenseVoiceModel* exposes the same metadata and Run API as the original QNN model, this change should be behavior-preserving and removes the duplication nicely.

Please double-check that all OfflineSenseVoiceModel* classes share the same constructor signatures used here ((const OfflineModelConfig&) and (Manager*, const OfflineModelConfig&)) and compatible GetModelMetadata()/Run() APIs so the template truly remains backend-agnostic.

Also applies to: 71-74, 96-99, 119-121, 143-145, 170-172, 386-389, 411-413, 434-436, 458-460, 487-489


792-793: Minor formatting tweak to closing comments is fine

The updated closing comments on the rule_fars loop and if block keep style consistent with the rest of the file; no behavioral impact.

sherpa-onnx/csrc/offline-recognizer-sense-voice-tpl-impl.h (1)

26-35: Template generalization of SenseVoice impl looks clean

The new OfflineRecognizerSenseVoiceTplImpl<SenseVoiceModel> nicely factors out backend differences:

  • SenseVoiceModel is constructed uniformly from config.model_config (and mgr variant), stored as std::unique_ptr<SenseVoiceModel>.
  • Symbol table handling mirrors the non-manager and manager paths.
  • Decoder setup still uses OfflineCtcGreedySearchDecoderRknn based only on blank_id, which is backend-agnostic in practice.
  • InitFeatConfig() derives feature settings from the model metadata, similar to the previous QNN-specific flow.

This should make it straightforward to plug in additional SenseVoice backends without duplicating recognizer glue code.

Also applies to: 48-55, 131-136

@csukuangfj
csukuangfj merged commit f201a29 into k2-fsa:master Dec 8, 2025
26 of 27 checks passed
@csukuangfj
csukuangfj deleted the refactor-sense-voice-impl branch December 8, 2025 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants