Skip to content

Add C++ API with ACL C API for SenseVoice ASR on Ascend NPU - #2728

Merged
csukuangfj merged 17 commits into
k2-fsa:masterfrom
csukuangfj:ascend-npu-acl-api
Oct 28, 2025
Merged

csukuangfj merged 17 commits into
k2-fsa:masterfrom
csukuangfj:ascend-npu-acl-api

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Oct 27, 2025 •

Copy link
Copy Markdown
Collaborator

Usage

Install CANN

Build sherpa-onnx

git clone https://github.com/k2-fsa/sherpa-onnx
cd sherpa-onnx
mkdir build
cmake -DSHERPA_ONNX_ENABLE_ASCEND_NPU=ON ..
make sherpa-onnx-offline

Test with Ascend 910B NPU

cd /path/to/sherpa-onnx

wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-ascend-910B-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2

tar xvf sherpa-onnx-ascend-910B-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2

./build/bin/sherpa-onnx-offline \
  --debug=1 \
  --provider=ascend \
  --sense-voice-model=./sherpa-onnx-ascend-910B-sense-voice-zh-en-ja-ko-yue-2024-07-17/model.om \
  --tokens=./sherpa-onnx-ascend-910B-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt \
  ./sherpa-onnx-ascend-910B-sense-voice-zh-en-ja-ko-yue-2024-07-17/test_wavs/zh.wav

Summary by CodeRabbit

  • New Features

    • Optional Ascend NPU support for hardware‑accelerated offline inference and a new Ascend backend for Sense Voice models.
  • Chores

    • CI workflows migrated to Windows Server 2022 runners across many pipelines.
    • Release artifact tagging and publishing updated to v1.12.15 for Windows builds.
  • Bug Fixes / Improvements

    • Model metadata defaults initialized and improved runtime diagnostics for Ascend builds.

@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Oct 27, 2025
@coderabbitai

coderabbitai Bot commented Oct 27, 2025 •

Copy link
Copy Markdown

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

This PR migrates many GitHub Actions Windows runners to windows-2022, bumps several release tags and artifact upload steps, and adds Ascend NPU support: new CMake option, Ascend ACL RAII wrappers, Ascend SenseVoice model and recognizer implementations, and runtime integration for provider="ascend".

Changes

Cohort / File(s) Summary
Windows Runner Migration
\.github/workflows/*
\.github/workflows/build-wheels-win64.yaml, \.github/workflows/flutter-windows-x64.yaml, \.github/workflows/jar.yaml, \.github/workflows/lazarus.yaml, \.github/workflows/mfc.yaml, \.github/workflows/pascal.yaml, \.github/workflows/test-build-wheel.yaml, \.github/workflows/test-dart.yaml, \.github/workflows/test-dart-package.yaml, \.github/workflows/test-dot-net-nuget.yaml, \.github/workflows/test-go.yaml, \.github/workflows/test-go-package.yaml, \.github/workflows/test-nodejs-addon-api.yaml, \.github/workflows/test-nodejs-addon-npm.yaml, \.github/workflows/test-nodejs-addon-npm-win-x86.yaml, \.github/workflows/test-piper-phonemize.yaml, \.github/workflows/test-python-offline-websocket-server.yaml, \.github/workflows/test-python-online-websocket-server.yaml, \.github/workflows/windows-arm64.yaml, \.github/workflows/windows-x64-debug.yaml, \.github/workflows/windows-x64.yaml, \.github/workflows/windows-x64-cuda.yaml, \.github/workflows/windows-x86-debug.yaml, \.github/workflows/windows-x86.yaml
Replaced windows-latest with windows-2022 across matrices and conditionals; adjusted related artifact/conditional paths and some comments.
Release Tag & Artifact Publishing
\.github/workflows/jar.yaml, \.github/workflows/mfc.yaml, \.github/workflows/windows-x64.yaml, \.github/workflows/windows-x64-cuda.yaml, \.github/workflows/windows-x86.yaml
Updated Sherpa ONNX release tags (bumped to v1.12.15 in several places); restored/enabled repo upload fields and added/adjusted Windows artifact upload steps and descriptions.
Export Workflow Trigger
\.github/workflows/export-paraformer-to-ascend-npu.yaml
Changed push branch trigger from ascend-npu-310 to ascend-npu-acl-api- and used soc_version variable in result directory naming.
CMake Option for Ascend
CMakeLists.txt
Added SHERPA_ONNX_ENABLE_ASCEND_NPU option (OFF by default); when ON, requires/configures ASCEND_TOOLKIT_HOME, checks headers/libs, defines macro, and emits status/fatal messages.
Build Integration for Ascend
sherpa-onnx/csrc/CMakeLists.txt
Included Ascend-specific sources when enabled, moved RKNN decoder source to a shared block, and wired include/link flags (${ASCEND_TOOLKIT_HOME}/include, -L${ASCEND_TOOLKIT_HOME}/lib64 -lascendcl) for sherpa-onnx-core.
Ascend ACL Utilities
sherpa-onnx/csrc/ascend/utils.h, sherpa-onnx/csrc/ascend/utils.cc
Added RAII wrappers and helpers for Ascend ACL: Acl, AclContext, AclDevicePtr, AclHostPtr, AclModelDesc, AclModel, AclMdlDataset, AclDataBuffer, AclTensorDesc; metadata extraction and GetInfo().
Ascend Error Macro
sherpa-onnx/csrc/ascend/macros.h
New macro SHERPA_ONNX_ASCEND_CHECK(ret, msg, ...) to check ACL calls, log recent ACL error messages, and exit on failure.
Ascend SenseVoice Model
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h, sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc
Added OfflineSenseVoiceModelAscend public header and implementation: device/context init, model load (file/memory), buffer preallocation, ApplyLFR, dynamic tensor shapes, aclmdlExecute usage, and logits retrieval. Public constructors, destructor, Run, and GetModelMetadata added.
Ascend Recognizer Impl
sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h
New recognizer implementation OfflineRecognizerSenseVoiceAscendImpl with constructors, CreateStream, DecodeStreams/DecodeOneStream, ConvertSenseVoiceResult, feature config, and greedy-search decoder wiring.
Recognizer Routing
sherpa-onnx/csrc/offline-recognizer-impl.cc
Added runtime branch for provider "ascend" (guarded by SHERPA_ONNX_ENABLE_ASCEND_NPU) to return the Ascend recognizer for SenseVoice models; emits errors/suggests rebuild if Ascend not enabled.
Model Metadata Defaults
sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h
Added inline default initializers for fields (with_itn_id=14, without_itn_id=15, window_size=7, window_shift=6, vocab_size=25055) and initialized lang2id with common language→id entries; added comments on NPU-specific fields.
RKNN Path & Minor Fixes
sherpa-onnx/csrc/rknn/macros.h, sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h, sherpa-onnx/csrc/keyword-spotter-impl.cc
Adjusted header comment paths for rknn subdir; moved RKNN decoder source to shared inclusion; added include for sherpa-onnx/csrc/macros.h in keyword-spotter-impl.cc.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Factory as OfflineRecognizerImpl
    participant AscendRec as OfflineRecognizerSenseVoiceAscendImpl
    participant Model as OfflineSenseVoiceModelAscend
    participant ACL as Ascend ACL

    App->>Factory: Create(config provider="ascend")
    alt SHERPA_ONNX_ENABLE_ASCEND_NPU
        Factory->>AscendRec: instantiate with config
        AscendRec->>Model: Load / Init model
        Model->>ACL: aclInit / create context / load model
        Model-->>AscendRec: model ready (metadata)
        App->>AscendRec: DecodeStreams(streams)
        AscendRec->>AscendRec: DecodeOneStream(stream)
        AscendRec->>Model: Run(features, language, text_norm)
        Model->>ACL: allocate device buffers / aclmdlExecute
        Model-->>AscendRec: logits
        AscendRec->>AscendRec: decode logits -> text
        AscendRec-->>App: recognition result
    else not enabled
        Factory-->>App: error + rebuild guidance
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Files/areas needing extra attention:
    • sherpa-onnx/csrc/ascend/utils.h and utils.cc — RAII correctness, allocation/free symmetry, error handling.
    • sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc/.h — ApplyLFR, dynamic-shape handling, device↔host transfers, buffer sizing.
    • sherpa-onnx/csrc/offline-recognizer-impl.cc — provider branching and error messages consistency with RKNN flow.
    • CMakeLists.txt and sherpa-onnx/csrc/CMakeLists.txt — detection of ASCEND_TOOLKIT_HOME, include/link flags and conditional source inclusion.
    • sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h — correctness of default values and lang2id map.

Possibly related PRs

Poem

🐰 I hopped through CI to windows‑2022,
tucked Ascend into CMake's burrow anew,
ACL wrappers hold buffers snug and tight,
SenseVoice sings from device-lit night,
Hop, build, and test — a rosy rabbit's view!

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 pull request title "Add C++ API with ACL C API for SenseVoice ASR on Ascend NPU" accurately captures the primary feature being added. The changeset includes new Ascend NPU backend implementation files (utils, macros, model implementations, recognizer implementation), CMake configuration for Ascend NPU support, and integration into the main offline-recognizer, which aligns directly with the title's focus. While the PR also contains updates to 25+ GitHub Actions workflows to use windows-2022 instead of windows-latest (along with some release tag updates), these represent secondary infrastructure maintenance changes rather than the primary feature addition. The title is clear, specific, and sufficient for a teammate to understand the core change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

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 adds C++ API support for SenseVoice ASR on Ascend NPU using the ACL (Ascend Computing Language) C API. The implementation follows a similar pattern to the existing RKNN NPU support.

Key changes:

  • Introduces new Ascend NPU backend with ACL C API wrappers for model loading, inference, and memory management
  • Shares the CTC greedy search decoder implementation between RKNN and Ascend NPU backends
  • Provides default values for SenseVoice model metadata to support both NPU backends
  • Updates CI workflows to use windows-2022 runner instead of windows-latest

Reviewed Changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
sherpa-onnx/csrc/ascend/*.{h,cc} New Ascend NPU implementation with ACL API wrappers and SenseVoice model support
sherpa-onnx/csrc/offline-recognizer-impl.cc Integration of Ascend provider into recognizer factory
sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h Default values for model metadata supporting NPU backends
CMakeLists.txt Build configuration for Ascend NPU support
sherpa-onnx/csrc/CMakeLists.txt Source file organization for shared decoder and Ascend-specific files
.github/workflows/*.yaml CI workflow updates to windows-2022 and version tag updates

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

SHERPA_ONNX_LOGE(
"Only SenseVoice models are currently supported "
"by Ascend NPU for non-streaming ASR. Fallback to CPU");
} else if (!config.model_config.sense_voice.model.empty()) {

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

The second condition is redundant. If line 70 checks that model is empty, line 74 checking that model is not empty is unnecessary since it's already guaranteed by the else branch. Remove the explicit condition in the else if and use a simple else.

Suggested change
} else if (!config.model_config.sense_voice.model.empty()) {
} else {

Copilot uses AI. Check for mistakes.
Comment on lines +297 to +301
if (config.model_config.sense_voice.model.empty()) {
SHERPA_ONNX_LOGE(
"Only SenseVoice models are currently supported "
"by Ascend NPU for non-streaming ASR. Fallback to CPU");
} else if (!config.model_config.sense_voice.model.empty()) {

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

The second condition is redundant. If line 297 checks that model is empty, line 301 checking that model is not empty is unnecessary since it's already guaranteed by the else branch. Remove the explicit condition in the else if and use a simple else.

Copilot uses AI. Check for mistakes.
Comment thread sherpa-onnx/csrc/ascend/utils.cc Outdated
aclFormat format = aclmdlGetOutputFormat(desc_->Get(), i);

os << " format: " << AclFormatToString(format) << "\n";
aclDataType type = aclmdlGetInputDataType(desc_->Get(), i);

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

Using aclmdlGetInputDataType for output information. Should use aclmdlGetOutputDataType when retrieving data type for outputs.

Suggested change
aclDataType type = aclmdlGetInputDataType(desc_->Get(), i);
aclDataType type = aclmdlGetOutputDataType(desc_->Get(), i);

Copilot uses AI. Check for mistakes.
@csukuangfj
csukuangfj requested a review from Copilot October 27, 2025 14:47

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

Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.


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

Comment thread sherpa-onnx/csrc/ascend/utils.h Outdated
Comment on lines +71 to +72
AclHostPtr(const AclDevicePtr &) = delete;
const AclHostPtr &operator=(const AclDevicePtr &) = delete;

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

The deleted copy constructor and assignment operator parameters should be AclHostPtr instead of AclDevicePtr. This appears to be a copy-paste error from the AclDevicePtr class.

Suggested change
AclHostPtr(const AclDevicePtr &) = delete;
const AclHostPtr &operator=(const AclDevicePtr &) = delete;
AclHostPtr(const AclHostPtr &) = delete;
const AclHostPtr &operator=(const AclHostPtr &) = delete;

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +150
repo_name: k2-fsa/sherpa-onnx
repo_token: ${{ secrets.UPLOAD_GH_SHERPA_ONNX_TOKEN }}
tag: v1.12.15

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

Previously commented-out configuration lines have been uncommented. Ensure that the UPLOAD_GH_SHERPA_ONNX_TOKEN secret is properly configured in the repository settings.

Copilot uses AI. Check for mistakes.
Comment on lines +128 to +130
repo_name: k2-fsa/sherpa-onnx
repo_token: ${{ secrets.UPLOAD_GH_SHERPA_ONNX_TOKEN }}
tag: v1.12.15

Copilot AI Oct 27, 2025

Copy link

Choose a reason for hiding this comment

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

New release configuration added. Ensure that the UPLOAD_GH_SHERPA_ONNX_TOKEN secret is properly configured in the repository settings.

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: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/build-wheels-win64.yaml (1)

268-268: Update build_wheels_win64 job to use windows-2022 for consistency.

The build_wheels_win64 job at line 268 uses windows-latest while the core and test jobs in the same workflow use windows-2022. This inconsistency can lead to build issues when different OS versions run related jobs in the same workflow.

-        os: [windows-latest]
+        os: [windows-2022]
🧹 Nitpick comments (10)
sherpa-onnx/csrc/keyword-spotter-impl.cc (1)

8-8: Use SHERPA_ONNX_EXIT consistently and add an unreachable return.

You already include macros.h. Prefer the project macro over raw exit for consistency and to satisfy static analyzers.

Apply outside this hunk near Line 71:

-  SHERPA_ONNX_LOGE("Please specify a model");
-  SHERPA_ONNX_EXIT(-1);
+  SHERPA_ONNX_LOGE("Please specify a model");
+  SHERPA_ONNX_EXIT(-1);
+  return nullptr;  // unreachable, silences compilers
sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h (1)

1-1: Guard logits shape and verify metadata assumptions.

Add a check before dividing to avoid silent truncation; also confirm frame_shift and subsampling source.

Apply outside this hunk near Lines 113-121:

-    std::vector<float> logits = model_->Run(std::move(f), language, text_norm);
-    int32_t num_out_frames = logits.size() / meta_data.vocab_size;
+    std::vector<float> logits = model_->Run(std::move(f), language, text_norm);
+    SHERPA_ONNX_CHECK(logits.size() % static_cast<size_t>(meta_data.vocab_size) == 0,
+                      "logits.size() (%zu) is not a multiple of vocab_size (%d)",
+                      logits.size(), meta_data.vocab_size);
+    int32_t num_out_frames = static_cast<int32_t>(logits.size() / meta_data.vocab_size);

Please verify:

  • frame_shift_ms hard-coded to 10 (Line 119): is this guaranteed by SenseVoice metadata?
  • subsampling_factor from meta_data.window_shift (Line 120): confirm this indeed encodes subsampling factor for RKNN SenseVoice.
sherpa-onnx/csrc/ascend/macros.h (1)

10-19: Include ACL header and null-check error message to avoid UB.

The macro references ACL_ERROR_NONE and aclGetRecentErrMsg. Without including acl/acl.h here, include-order matters. Also, aclGetRecentErrMsg may return nullptr.

-#include "sherpa-onnx/csrc/macros.h"
+#include "sherpa-onnx/csrc/macros.h"
+#include <acl/acl.h>

-#define SHERPA_ONNX_ASCEND_CHECK(ret, msg, ...)    \
+#define SHERPA_ONNX_ASCEND_CHECK(ret, msg, ...)    \
   do {                                             \
     if (ret != ACL_ERROR_NONE) {                   \
-      const char *_msg = aclGetRecentErrMsg();     \
+      const char *_msg = aclGetRecentErrMsg();     \
+      const char *_safe = _msg ? _msg : "unknown"; \
       SHERPA_ONNX_LOGE("Return code is: %d", ret); \
-      SHERPA_ONNX_LOGE("Error message: %s", _msg); \
+      SHERPA_ONNX_LOGE("Error message: %s", _safe);\
       SHERPA_ONNX_LOGE(msg, ##__VA_ARGS__);        \
       SHERPA_ONNX_EXIT(-1);                        \
     }                                              \
   } while (0)
sherpa-onnx/csrc/ascend/utils.h (3)

21-23: Minor: assignment operator delete signature.

Prefer returning non-const reference for deleted operator= to match convention.

-  const Acl &operator=(const Acl &) = delete;
+  Acl &operator=(const Acl &) = delete;

38-40: Make conversion operator const.

Safe and conventional; mirrors Get() const.

-  operator aclrtContext() { return context_; }
+  operator aclrtContext() const { return context_; }

91-99: AclModelDesc::Size() returns unused, never-initialized size_.

As written, Size() always returns 0. Either populate size_ (e.g., sum of input sizes or model size if available) or remove the method to avoid misleading APIs.

Is Size() needed by callers? If not, drop it; otherwise, implement using ACL query APIs.

sherpa-onnx/csrc/CMakeLists.txt (1)

307-313: Optional: prefer imported targets/find_library and add rpath for ascend libs.

Using raw -L/-l works but is brittle. Consider find_library(ASCENDCL ...) and target_link_libraries(sherpa-onnx-core PRIVATE ${ASCENDCL}). Also add an rpath entry for ${ASCEND_TOOLKIT_HOME}/lib64 for installed binaries when needed.

sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (1)

19-20: Ensure ACL is initialized in Impl before any aclrt calls.*

Please confirm Impl holds an RAII Acl member (e.g., sherpa_onnx::Acl acl_;) constructed before PreInit(). Without aclInit/aclFinalize, aclrtSetDevice/LoadModel may fail.

I can draft the minimal RAII wiring in Impl if helpful.

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

119-123: Optional: clarify time-scaling parameter.

You’re using window_shift as subsampling_factor for timestamps; add a brief comment or use meta_data.subsampling_factor if that’s the intended knob.


37-44: Optional: decoder naming mismatch.

The greedy decoder lives under rknn/ but is backend-agnostic. Consider moving/renaming to a neutral path to avoid confusion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4450c83 and fc078ca.

📒 Files selected for processing (38)
  • .github/workflows/build-wheels-win64.yaml (1 hunks)
  • .github/workflows/export-paraformer-to-ascend-npu.yaml (2 hunks)
  • .github/workflows/flutter-windows-x64.yaml (2 hunks)
  • .github/workflows/jar.yaml (6 hunks)
  • .github/workflows/lazarus.yaml (4 hunks)
  • .github/workflows/mfc.yaml (4 hunks)
  • .github/workflows/pascal.yaml (4 hunks)
  • .github/workflows/test-build-wheel.yaml (1 hunks)
  • .github/workflows/test-dart-package.yaml (1 hunks)
  • .github/workflows/test-dart.yaml (2 hunks)
  • .github/workflows/test-dot-net-nuget.yaml (1 hunks)
  • .github/workflows/test-go-package.yaml (15 hunks)
  • .github/workflows/test-go.yaml (3 hunks)
  • .github/workflows/test-nodejs-addon-api.yaml (2 hunks)
  • .github/workflows/test-nodejs-addon-npm-win-x86.yaml (1 hunks)
  • .github/workflows/test-nodejs-addon-npm.yaml (1 hunks)
  • .github/workflows/test-piper-phonemize.yaml (3 hunks)
  • .github/workflows/test-python-offline-websocket-server.yaml (3 hunks)
  • .github/workflows/test-python-online-websocket-server.yaml (1 hunks)
  • .github/workflows/windows-arm64.yaml (1 hunks)
  • .github/workflows/windows-x64-cuda.yaml (3 hunks)
  • .github/workflows/windows-x64-debug.yaml (1 hunks)
  • .github/workflows/windows-x64.yaml (2 hunks)
  • .github/workflows/windows-x86-debug.yaml (1 hunks)
  • .github/workflows/windows-x86.yaml (2 hunks)
  • CMakeLists.txt (3 hunks)
  • sherpa-onnx/csrc/CMakeLists.txt (2 hunks)
  • sherpa-onnx/csrc/ascend/macros.h (1 hunks)
  • sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h (1 hunks)
  • sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1 hunks)
  • sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (1 hunks)
  • sherpa-onnx/csrc/ascend/utils.cc (1 hunks)
  • sherpa-onnx/csrc/ascend/utils.h (1 hunks)
  • sherpa-onnx/csrc/keyword-spotter-impl.cc (1 hunks)
  • sherpa-onnx/csrc/offline-recognizer-impl.cc (4 hunks)
  • sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h (2 hunks)
  • sherpa-onnx/csrc/rknn/macros.h (1 hunks)
  • sherpa-onnx/csrc/rknn/offline-recognizer-sense-voice-rknn-impl.h (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-06T04:18:47.981Z
Learnt from: litongjava
PR: k2-fsa/sherpa-onnx#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:

  • .github/workflows/jar.yaml
📚 Learning: 2025-08-06T04:23:50.237Z
Learnt from: litongjava
PR: k2-fsa/sherpa-onnx#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:

  • .github/workflows/jar.yaml
🧬 Code graph analysis (6)
sherpa-onnx/csrc/offline-recognizer-impl.cc (2)
nodejs-addon-examples/test_asr_streaming_transducer_itn.js (1)
  • config (6-28)
nodejs-addon-examples/test_asr_streaming_transducer_microphone_itn.js (1)
  • config (9-37)
sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h (4)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (2)
  • sherpa_onnx (13-41)
  • OfflineSenseVoiceModelAscend (15-39)
sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h (1)
  • sherpa_onnx (11-48)
sherpa-onnx/csrc/offline-recognizer-sense-voice-impl.h (1)
  • ConvertSenseVoiceResult (25-59)
sherpa-onnx/csrc/rknn/offline-ctc-greedy-search-decoder-rknn.h (1)
  • OfflineCtcGreedySearchDecoderRknn (14-24)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (3)
sherpa-onnx/csrc/ascend/offline-recognizer-sense-voice-ascend-impl.h (1)
  • sherpa_onnx (20-134)
sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h (1)
  • sherpa_onnx (11-48)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (13)
  • OfflineSenseVoiceModelAscend (199-201)
  • OfflineSenseVoiceModelAscend (203-203)
  • OfflineSenseVoiceModelAscend (216-217)
  • OfflineSenseVoiceModelAscend (221-222)
  • Run (205-208)
  • Run (205-206)
  • features (43-95)
  • features (43-44)
  • GetModelMetadata (210-213)
  • GetModelMetadata (211-211)
  • Impl (23-27)
  • Impl (23-23)
  • Impl (30-37)
sherpa-onnx/csrc/ascend/utils.cc (2)
sherpa-onnx/csrc/ascend/utils.h (16)
  • Acl (16-26)
  • AclContext (28-43)
  • AclContext (31-31)
  • Get (55-55)
  • Get (74-74)
  • Get (91-91)
  • Get (159-159)
  • Get (174-174)
  • Get (190-190)
  • AclDevicePtr (45-63)
  • AclHostPtr (65-80)
  • AclModelDesc (82-99)
  • AclModel (101-146)
  • AclMdlDataset (148-164)
  • AclDataBuffer (166-179)
  • AclTensorDesc (181-195)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (3)
  • device_id (114-124)
  • data (106-112)
  • data (106-106)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (1)
  • OfflineSenseVoiceModelAscend (15-39)
sherpa-onnx/csrc/ascend/utils.h (2)
sherpa-onnx/csrc/ascend/utils.cc (37)
  • Acl (97-101)
  • Acl (103-108)
  • AclContext (110-113)
  • AclContext (115-120)
  • Get (122-122)
  • Get (122-122)
  • AclDevicePtr (124-133)
  • AclDevicePtr (135-140)
  • AclHostPtr (142-150)
  • AclHostPtr (152-157)
  • AclModelDesc (159-168)
  • AclModelDesc (170-175)
  • AclModel (177-184)
  • AclModel (186-191)
  • AclModel (193-198)
  • GetInfo (265-325)
  • GetInfo (265-265)
  • Init (200-208)
  • Init (200-200)
  • InitInputNames (210-218)
  • InitInputNames (210-210)
  • InitInputShapes (220-236)
  • InitInputShapes (220-220)
  • InitOutputNames (238-245)
  • InitOutputNames (238-238)
  • InitOutputShapes (247-263)
  • InitOutputShapes (247-247)
  • AclMdlDataset (327-333)
  • AclMdlDataset (335-340)
  • AddBuffer (342-345)
  • AddBuffer (342-342)
  • SetTensorDesc (347-353)
  • SetTensorDesc (347-348)
  • AclDataBuffer (355-362)
  • AclDataBuffer (364-369)
  • AclTensorDesc (371-378)
  • AclTensorDesc (380-384)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (3)
  • device_id (114-124)
  • data (106-112)
  • data (106-106)
⏰ 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). (18)
  • GitHub Check: ubuntu-latest Debug static tts-OFF
  • GitHub Check: Debug shared-ON tts-ON
  • GitHub Check: Release shared-OFF tts-ON
  • GitHub Check: ubuntu-latest Debug shared tts-ON
  • GitHub Check: Release shared tts-OFF
  • GitHub Check: Debug shared-ON tts-OFF
  • GitHub Check: Release shared-ON tts-OFF
  • GitHub Check: Debug shared-OFF tts-OFF
  • GitHub Check: Release shared-OFF tts-OFF
  • GitHub Check: Debug shared-OFF tts-ON
  • GitHub Check: Debug shared tts-OFF
  • GitHub Check: ubuntu-24.04 3.9
  • GitHub Check: ubuntu-24.04 3.11
  • GitHub Check: ubuntu-24.04 3.10
  • GitHub Check: ubuntu-24.04 3.12
  • GitHub Check: ubuntu-24.04 3.13
  • GitHub Check: rknn shared OFF
  • GitHub Check: rknn shared ON
🔇 Additional comments (46)
.github/workflows/test-piper-phonemize.yaml (1)

24-24: LGTM! CI infrastructure upgrade with consistent pinning.

The update to explicitly use windows-2022 across all references (matrix definition, exclude rules, and conditional checks) improves CI stability by pinning to a known Windows runner version rather than relying on the latest. All references are consistent and the test logic is preserved correctly—non-Windows tests run conditionally on non-Windows runners, and Windows tests run on windows-2022.

Also applies to: 28-28, 70-70, 82-82

.github/workflows/flutter-windows-x64.yaml (1)

23-23: LGTM: Windows runner standardization.

Both jobs consistently updated from windows-latest to windows-2022. No conditional logic changes needed in this workflow.

Also applies to: 128-128

.github/workflows/test-python-online-websocket-server.yaml (1)

29-29: LGTM: Windows runner update.

Matrix OS correctly updated to windows-2022. Maintains multi-platform test coverage.

.github/workflows/windows-x86.yaml (2)

39-39: LGTM: Windows runner update.

Matrix OS correctly updated to windows-2022.


153-153: LGTM: Release tag update.

Tag updated to v1.12.15 for GitHub release uploads, consistent with PR objectives to bump release tags to v1.12.15.

.github/workflows/test-build-wheel.yaml (1)

83-84: LGTM: Python 3.13 test matrix for Windows.

Added windows-2022 + Python 3.13 to the test matrix, consistent with existing Windows entries and the broader Windows runner standardization.

.github/workflows/windows-x86-debug.yaml (1)

33-33: LGTM: Windows runner update for debug builds.

Matrix OS correctly updated to windows-2022. Maintains debug build type variants.

.github/workflows/test-nodejs-addon-npm.yaml (1)

32-32: LGTM: Windows runner standardized in Node.js addon tests.

Matrix OS updated to include windows-2022. Maintains comprehensive multi-platform coverage.

.github/workflows/test-go.yaml (1)

27-27: LGTM: Consistent windows-2022 standardization across matrix and conditionals.

All three OS references updated consistently: matrix definition (line 27) and conditional checks (lines 81, 95). Platform-specific build logic is properly preserved.

Also applies to: 81-81, 95-95

.github/workflows/windows-x64-debug.yaml (1)

33-33: LGTM: Windows runner update for x64 debug builds.

Matrix OS correctly updated to windows-2022. Mirrors the x86 debug workflow changes.

.github/workflows/test-nodejs-addon-npm-win-x86.yaml (1)

33-33: LGTM: Align Windows runner to windows-2022.

This infrastructure update aligns with the broader CI migration across the repository and carries no impact on test logic or behavior.

.github/workflows/windows-x64.yaml (2)

39-39: LGTM: Align Windows runner to windows-2022.

Infrastructure update consistent with broader CI migration.


148-150: Verify that hardcoded release tag v1.12.15 is intentional.

This section hardcodes the release tag as v1.12.15 instead of computing it from CMakeLists.txt like other sections in the same file (e.g., lines 84, 118). Confirm this reflects the intended release version and is not stale.

.github/workflows/windows-arm64.yaml (1)

27-27: LGTM: Align Windows runner to windows-2022.

Routine infrastructure update.

.github/workflows/test-dot-net-nuget.yaml (1)

28-28: LGTM: Include windows-2022 in multi-OS test matrix.

Aligns with cross-repository CI standardization.

.github/workflows/export-paraformer-to-ascend-npu.yaml (1)

170-170: LGTM: Parameterize directory naming for multi-SOC support.

Good improvement—the parameterized ${soc_version} variable allows the script to handle both 910B and 310P3 SOC versions dynamically, eliminating the hardcoded 910B reference and aligning with the matrix configuration.

.github/workflows/test-dart-package.yaml (1)

26-26: LGTM: Update commented OS suggestion to windows-2022.

Documentation update that keeps the commented example consistent with current CI practices. No functional impact since the line remains disabled.

.github/workflows/lazarus.yaml (4)

33-33: LGTM: Update Windows runner to windows-2022.

Infrastructure update aligned with other workflows.


100-100: LGTM: Update conditional to match new OS label.

Correctly updates the conditional check to reference the new windows-2022 matrix OS value.


176-176: LGTM: Update artifact upload conditional for Windows x64 collection.

Properly aligns the conditional to match the updated Windows matrix OS label.


237-237: LGTM: Update artifact upload conditional for Windows x64 artifacts.

Correctly updates the upload gate to use the new windows-2022 label.

.github/workflows/build-wheels-win64.yaml (1)

29-29: LGTM: Update core job Windows runner to windows-2022.

Aligns with cross-repository CI standardization.

.github/workflows/test-nodejs-addon-api.yaml (1)

81-113: Consistent Windows runner update applied correctly.

The conditionals on lines 81 and 113 properly branch on windows-2022 vs. other OSes, splitting the build to use Visual Studio's MSBuild (Windows-specific) vs. Ninja (cross-platform). No functional changes to the workflow logic.

.github/workflows/test-dart.yaml (1)

27-27: Windows Dart testing intentionally disabled.

Line 27 comments out windows-2022 from the test matrix, which makes the Windows-specific logic on line 92 a harmless dead code path. This is likely intentional due to Dart/Flutter environment constraints on Windows CI runners.

Also applies to: 92-92

.github/workflows/test-python-offline-websocket-server.yaml (1)

29-29: Windows runner added; paraformer tests appropriately skipped on Windows.

Line 29 adds windows-2022 to the test matrix; lines 101 and 116 then skip paraformer model tests specifically on Windows (likely due to library/model availability constraints). The conditional logic is consistent and intentional.

Also applies to: 101-101, 116-116

.github/workflows/windows-x64-cuda.yaml (1)

100-109: Release artifact upload logic correctly differentiates between repository owners.

Lines 100–109 upload artifacts for csukuangfj owner to k2-fsa/sherpa-onnx with explicit tag v1.12.15; lines 111–117 handle k2-fsa owner releases to the current repository. This dual-upload pattern allows personal mirror releases while maintaining org releases. No issues detected.

Also applies to: 111-117

.github/workflows/jar.yaml (1)

38-38: Windows runner and release tag updates applied consistently across JAR build workflow.

All references to windows-latest replaced with windows-2022 (lines 38, 129, 184, 239, 248). Release tag updated to v1.12.15 on line 221. Path separator logic on line 248 correctly uses Windows semicolon. No issues detected.

Also applies to: 129-129, 184-184, 221-221, 239-239, 248-248

.github/workflows/pascal.yaml (1)

30-30: Windows runner update applied consistently with appropriate test exclusions.

Lines 30, 63, 109 correctly reference windows-2022 for compiler install, DLL copy, and streaming tests. Line 150 appropriately excludes Windows from paraformer/CTC HLG tests using !=. Pattern is consistent across the workflow.

Also applies to: 63-63, 109-109, 150-150

.github/workflows/mfc.yaml (1)

29-29: MFC release uploads configured for all three binary types with consistent versioning.

Matrix set to Windows-only (line 29). Three release upload steps (lines 128–152) handle streaming, non-streaming, and TTS binaries, each with matching repo_name: k2-fsa/sherpa-onnx, token, and tag: v1.12.15. Gating condition on line 122 ensures uploads only occur for authorized owners on tag pushes. Configuration is correct.

Also applies to: 128-152

.github/workflows/test-go-package.yaml (1)

35-38: Go test workflow comprehensively updated for Windows 2022 with architecture-specific handling.

Matrix lines 35–38 include both windows-2022 x64 and x86 entries. MinGW setup (lines 62, 68, 75) gates on architecture. Linux/macOS-only tests (lines 80, 88, 95, 102, 109, 153, 160, 374, 487, 500) use != 'windows-2022' to exclude Windows. Windows-specific tests (lines 116, 167, 188, 224, 274, 320, 405, 442, 519, 544) properly check both OS and architecture. Pattern is comprehensive and consistent.

Also applies to: 62-62, 68-68, 75-75, 80-80, 88-88, 95-95, 102-102, 109-109, 153-153, 160-160, 167-167, 188-188, 224-224, 274-274, 320-320, 374-374, 405-405, 442-442, 487-487, 500-500, 519-519, 544-544

CMakeLists.txt (1)

63-64: ****

The Ascend toolkit wiring is already properly configured in sherpa-onnx/csrc/CMakeLists.txt (lines 307–313). The implementation includes:

  • Include directories: target_include_directories(sherpa-onnx-core PRIVATE ${ASCEND_TOOLKIT_HOME}/include) (line 308)
  • Link directories and libraries: -L${ASCEND_TOOLKIT_HOME}/lib64 and -lascendcl (lines 310–311)

The code already uses target-scoped configuration via target_include_directories and target_link_libraries as recommended. No additional wiring or refactoring is needed.

Likely an incorrect or invalid review comment.

sherpa-onnx/csrc/offline-recognizer-impl.cc (1)

42-44: Ascend provider integration verified—all plumbing correct.

  • Class OfflineRecognizerSenseVoiceAscendImpl present and properly included.
  • Provider string checks uniform across both Create() overloads (lines 68 and 295).
  • CMake build system correctly wires Ascend libraries: target_link_libraries includes -L${ASCEND_TOOLKIT_HOME}/lib64 -lascendcl.
  • Mirror of RKNN path is consistent and well-structured.
  • Minor: the "Fallback to CPU" message only logs; consider clarifying it if no CPU SenseVoice model is provided.
sherpa-onnx/csrc/rknn/macros.h (1)

10-17: Consider defensive include-guard but current code is safe due to transitive includes.

Your concern about include-order fragility is valid in principle—macros.h relies on RKNN_SUCC (from external rknn_api.h) without explicitly including it. However, all current uses work because model header files (e.g., offline-sense-voice-model-rknn.h, utils.h) include rknn_api.h before macros.h is included, satisfying the dependency transitively.

The risk emerges only if:

  • A new file includes macros.h directly without first including a header that has rknn_api.h
  • Include order changes

Recommendation: Adding the guard is good defensive practice with no cost:

#ifndef RKNN_SUCC
#error "Include <rknn_api.h> before sherpa-onnx/csrc/rknn/macros.h"
#endif

This is preferable to including the vendor header in macros.h because it avoids coupling and still ensures safety. Verify with your team whether this defensive pattern aligns with your project standards.

sherpa-onnx/csrc/CMakeLists.txt (1)

195-201: Validation for ASCEND_TOOLKIT_HOME already exists in parent CMakeLists.txt.

The root CMakeLists.txt (lines 305-334) already implements all the validations suggested in this review:

  • Checks whether ASCEND_TOOLKIT_HOME is set or defaults to /usr/local/Ascend/ascend-toolkit/latest
  • Validates acl.h exists with FATAL_ERROR if missing (line 328-329)
  • Validates libascendcl.so exists with FATAL_ERROR if missing (line 332-333)

Since this validation occurs at the root level before sherpa-onnx/csrc/CMakeLists.txt is processed, the variable is guaranteed to be valid when used in lines 307-310 of that file. No additional validation is needed in the csrc subdirectory.

Likely an incorrect or invalid review comment.

sherpa-onnx/csrc/ascend/utils.cc (6)

13-95: LGTM!

The enum-to-string conversion functions are comprehensive and provide good diagnostic support for ACL data types and formats.


97-122: LGTM!

The RAII wrappers for ACL initialization and context management follow best practices with proper error checking and cleanup.


124-157: LGTM!

The device and host memory wrappers correctly handle allocation, deallocation, and zero-size edge cases with appropriate RAII semantics.


159-175: LGTM!

The model descriptor wrapper properly checks for allocation failures and manages the lifecycle correctly.


177-263: LGTM!

The model loading and metadata initialization logic is well-structured with proper resource management and efficient use of move semantics.


327-384: LGTM!

The dataset, buffer, and tensor descriptor wrappers correctly implement RAII patterns with appropriate error handling for ACL operations.

sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (6)

21-41: LGTM!

The constructor initialization sequence (PreInit → InitModel → PostInit) provides a clean and maintainable structure for setting up the model on Ascend NPU.


43-95: LGTM!

The inference pipeline correctly handles feature preprocessing, dynamic shape configuration, model execution, and result retrieval with appropriate error checking at each step.


114-124: Device selection is hardcoded.

Line 115 hardcodes device_id = 0, which is reasonable for the initial implementation. The setup and context management logic is correct.


143-179: LGTM!

The low frame rate (LFR) processing implementation correctly handles frame windowing with appropriate truncation warnings for overly long inputs.


182-197: LGTM!

The private member organization is clean with appropriate use of unique_ptr for RAII-managed ACL resources.


199-223: LGTM!

The public interface correctly implements the pimpl pattern with proper delegation, and includes necessary template instantiations for Android and OHOS platforms.

push:
branches:
- ascend-npu-310
- ascend-npu-acl-api-

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Critical: Fix branch trigger typo—trailing dash will prevent workflow from running.

Line 6 specifies ascend-npu-acl-api- (with trailing dash), but the PR source branch is ascend-npu-acl-api (without dash). The workflow will never trigger on the correct branch.

     branches:
-      - ascend-npu-acl-api-
+      - ascend-npu-acl-api

🏁 Script executed:

#!/bin/bash
# Inspect the workflow file to verify branch trigger on line 6
echo "=== Checking workflow file content ==="
cat .github/workflows/export-paraformer-to-ascend-npu.yaml | head -20
echo ""
echo "=== Checking line 6 specifically ==="
sed -n '6p' .github/workflows/export-paraformer-to-ascend-npu.yaml | od -c
echo ""
echo "=== Checking git branch information ==="
git branch -a
git rev-parse --abbrev-ref HEAD

Length of output: 727


🏁 Script executed:

#!/bin/bash
# Check git log and other workflow files for branch name patterns
echo "=== Searching for branch name references in workflows ==="
grep -r "ascend-npu-acl-api" .github/workflows/ --include="*.yaml" --include="*.yml"
echo ""
echo "=== Checking recent commits for context ==="
git log --oneline -10
echo ""
echo "=== Checking if branch ascend-npu-acl-api exists ==="
git branch -a | grep ascend-npu

Length of output: 465


Critical: Fix branch trigger typo—trailing dash will prevent workflow from running.

Line 6 specifies ascend-npu-acl-api- (with trailing dash), but this branch does not exist in the repository. The workflow will never trigger. Remove the trailing dash to match the intended branch name ascend-npu-acl-api.

     branches:
-      - ascend-npu-acl-api-
+      - ascend-npu-acl-api
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- ascend-npu-acl-api-
branches:
- ascend-npu-acl-api
🤖 Prompt for AI Agents
In .github/workflows/export-paraformer-to-ascend-npu.yaml around line 6, the
branch name in the workflow trigger includes an extraneous trailing dash
("ascend-npu-acl-api-") which doesn't match any branch and prevents the workflow
from running; remove the trailing dash so the branch reads "ascend-npu-acl-api"
(ensure there are no surrounding whitespace or YAML syntax changes).

Comment on lines +98 to +112
void InitModel(const std::string &filename) {
model_ = std::make_unique<AclModel>(filename);
if (config_.debug) {
auto s = model_->GetInfo();
SHERPA_ONNX_LOGE("%s", s.c_str());
}
}

void InitModel(void *data, size_t size) {
model_ = std::make_unique<AclModel>(data, size);
if (config_.debug) {
auto s = model_->GetInfo();
SHERPA_ONNX_LOGE("%s", s.c_str());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider using appropriate log level for debug output.

Lines 102 and 110 use SHERPA_ONNX_LOGE (error level) to output model information when config_.debug is enabled. Debug or informational content should use a more appropriate log level (e.g., SHERPA_ONNX_LOGD or SHERPA_ONNX_LOGI if available) to avoid polluting error logs.

🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc around lines 98
to 112, the model info print uses the error-level macro SHERPA_ONNX_LOGE when
config_.debug is true; change these debug prints to the appropriate debug/info
log macro (e.g., SHERPA_ONNX_LOGD or SHERPA_ONNX_LOGI if LOGD is unavailable) so
model information is not logged as an error, keeping the message text and
variable usage unchanged.

Comment on lines +139 to +140
logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
vocab_size_ * sizeof(float));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Clarify the +4 buffer allocation for logits.

Line 139 allocates (max_num_frames_ + 4) * vocab_size_ for the logits buffer. The reason for the additional 4 frames is not immediately clear from the code. Please add a comment explaining whether this is a safety buffer, related to prompt processing, or required by the model architecture.


🏁 Script executed:

#!/bin/bash
# Search for documentation or comments explaining the logits buffer sizing
rg -n -C3 'max_num_frames_.*\+.*4|logits.*allocation|output.*buffer.*size' --type=cc --type=h

Length of output: 26


🏁 Script executed:

#!/bin/bash
# Search for documentation about the +4 buffer allocation, using correct ripgrep types
rg -n -C3 'max_num_frames_.*\+.*4|logits.*allocation|output.*buffer' --type=cpp --type=h

Length of output: 15683


🏁 Script executed:

#!/bin/bash
# Look for the specific file and examine the Preallocate function
fd 'offline-sense-voice-model-ascend' --type f

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Search for comments or documentation about buffer sizing in the offline sense voice model
rg -n 'buffer|allocation|max_num_frames' sherpa-onnx/csrc/ascend/ -C2 | head -50

Length of output: 3575


🏁 Script executed:

#!/bin/bash
# Examine the header file for class definition and any documentation
cat sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h

Length of output: 1276


🏁 Script executed:

#!/bin/bash
# Search for sense-voice references to understand the model architecture
rg -n 'sense.voice|SenseVoice' --type=cpp --type=h -C2 | head -80

Length of output: 6864


🏁 Script executed:

#!/bin/bash
# Look for similar +4 or buffer offset patterns in other model implementations
rg -n 'make_unique.*\+.*4|make_unique.*\+.*sizeof' sherpa-onnx/csrc/ascend/ --type=cpp --type=h -C1

Length of output: 344


🏁 Script executed:

#!/bin/bash
# Look for non-Ascend SenseVoice implementations
fd 'offline.*sense.*voice' --type f | grep -v ascend

Length of output: 1018


🏁 Script executed:

#!/bin/bash
# Search for documentation files that might explain model architecture
find . -name '*.md' -o -name '*.txt' -o -name 'README*' | xargs grep -l 'sense.voice\|SenseVoice' 2>/dev/null | head -10

Length of output: 339


🏁 Script executed:

#!/bin/bash
# Search the Ascend implementation file more thoroughly for any comments near buffer allocations
cat sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc | sed -n '125,165p'

Length of output: 1329


🏁 Script executed:

#!/bin/bash
# Check the standard CPU SenseVoice implementation
cat sherpa-onnx/csrc/offline-sense-voice-model.cc | grep -n -A20 -B5 'logits\|buffer\|Preallocate' | head -60

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look for RKNN version as another reference implementation
cat sherpa-onnx/csrc/rknn/offline-sense-voice-model-rknn.cc | grep -n -A20 -B5 'logits\|buffer\|Preallocate' | head -60

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for any comments about the +4 or buffer sizing near the logits allocation
rg -n 'logits|output.*buffer' sherpa-onnx/csrc/offline-sense-voice-model.cc sherpa-onnx/csrc/rknn/offline-sense-voice-model-rknn.cc -C3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Examine the full Ascend implementation file to understand logits usage
cat sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc | sed -n '140,220p'

Length of output: 2336


🏁 Script executed:

#!/bin/bash
# Search for how logits_ptr_ is used after allocation
rg -n 'logits_ptr_' sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc -C2

Length of output: 961


🏁 Script executed:

#!/bin/bash
# Check if there are any git history clues or annotations about this allocation
cd sherpa-onnx/csrc/ascend && git log -p --all -S 'max_num_frames_ + 4' -- offline-sense-voice-model-ascend.cc 2>/dev/null | head -50

Length of output: 59


Add clarifying comment for the +4 buffer allocation on line 139.

The logits buffer is intentionally allocated with 4 extra frames beyond max_num_frames_ as an overflow safety margin. While the buffer is used with only num_frames * vocab_size_ bytes (lines 81–82 and 90), the allocation reserves extra capacity. Add an inline comment explaining this is a safety buffer to prevent accidental overflow.

logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
                                             vocab_size_ * sizeof(float));

Consider: // +4 frames as overflow safety margin

🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc around lines
139-140, the allocation for logits_ptr_ adds +4 to max_num_frames_ but has no
explanation; add an inline comment after the allocation expression clarifying
that the extra 4 frames are an intentional overflow safety margin to prevent
accidental buffer overruns when indexing (e.g., "// +4 frames as overflow safety
margin"), so future readers understand why capacity exceeds used num_frames *
vocab_size_.

Comment on lines +21 to +23
template <typename Manager>
OfflineSenseVoiceModelAscend(Manager *mgr, const OfflineModelConfig &config);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Templated constructor is declared but not defined; cc provides non-template overloads.

This will instantiate with no definition at call sites, causing link/instantiation errors.

Apply:

+#if defined(__ANDROID__)
+struct AAssetManager;
+#endif
+class NativeResourceManager;
@@
-  template <typename Manager>
-  OfflineSenseVoiceModelAscend(Manager *mgr, const OfflineModelConfig &config);
+  // Explicit overloads; keep in header to match .cc definitions.
+#if defined(__ANDROID__)
+  explicit OfflineSenseVoiceModelAscend(AAssetManager *mgr,
+                                        const OfflineModelConfig &config);
+#endif
+  explicit OfflineSenseVoiceModelAscend(NativeResourceManager *mgr,
+                                        const OfflineModelConfig &config);
+  // Prevent accidental template instantiation.
+  template <typename Manager>
+  OfflineSenseVoiceModelAscend(Manager *, const OfflineModelConfig &) = delete;

If you prefer the template, move its definition into this header or add explicit template instantiations in a TU.



---

🏁 Script executed:

```shell
#!/bin/bash
# Locate the header and corresponding .cc file
fd -t f "offline-sense-voice-model-ascend" --maxdepth 3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Examine the header file around lines 21-23
cat sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h | head -40

Length of output: 1176


🏁 Script executed:

#!/bin/bash
# Find the corresponding .cc file
find . -name "*offline-sense-voice-model-ascend.cc" -type f

Length of output: 61


🏁 Script executed:

#!/bin/bash
# Check for any template definitions in header or implementation
rg -n "template.*OfflineSenseVoiceModelAscend" --type=h --type=cc -A 10

Length of output: 26



---

🏁 Script executed:

```shell
#!/bin/bash
# Examine the .cc file to see constructor implementations
cat ./sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc

Length of output: 7126


🏁 Script executed:

#!/bin/bash
# Search for template definitions using correct syntax
rg -n "template" ./sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc -A 5

Length of output: 607


🏁 Script executed:

#!/bin/bash
# Search for Manager-related types (AAssetManager, NativeResourceManager)
rg -n "AAssetManager|NativeResourceManager" ./sherpa-onnx/csrc/ascend/ -A 2 -B 2

Length of output: 977


🏁 Script executed:

#!/bin/bash
# Search for forward declarations in header
rg -n "class.*Manager|struct.*Manager" ./sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h

Length of output: 0


Templated constructor is declared but not defined; explicit template instantiations in .cc have no corresponding definition.

The header declares the template constructor (lines 21-23) but provides no definition. The .cc file contains only explicit template instantiations (lines 216-222) without the template definition itself, causing linker/instantiation errors.

Replace with explicit overloads:

+#if defined(__ANDROID__)
+struct AAssetManager;
+#endif
+class NativeResourceManager;
+
  explicit OfflineSenseVoiceModelAscend(const OfflineModelConfig &config);
  
-  template <typename Manager>
-  OfflineSenseVoiceModelAscend(Manager *mgr, const OfflineModelConfig &config);
+#if defined(__ANDROID__)
+  explicit OfflineSenseVoiceModelAscend(AAssetManager *mgr,
+                                        const OfflineModelConfig &config);
+#endif
+#if defined(__OHOS__)
+  explicit OfflineSenseVoiceModelAscend(NativeResourceManager *mgr,
+                                        const OfflineModelConfig &config);
+#endif

Remove the explicit template instantiations from the .cc file (lines 215–223) and define these overloads there instead.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h around lines
21-23, the templated constructor OfflineSenseVoiceModelAscend(Manager *mgr,
const OfflineModelConfig &config) is declared but not defined; the .cc contains
explicit template instantiations at lines ~215-223 with no template body.
Replace the template by declaring explicit non-template overloads for each
concrete Manager type used (e.g., OfflineSenseVoiceModelAscend(SpecificManagerA*
mgr, const OfflineModelConfig& config) and
OfflineSenseVoiceModelAscend(SpecificManagerB* mgr, const OfflineModelConfig&
config)) in the header, then remove the explicit template instantiation lines
from the .cc (lines ~215-223) and add corresponding definitions for those
overloads in the .cc file.

Comment thread sherpa-onnx/csrc/ascend/utils.cc Outdated
Comment thread sherpa-onnx/csrc/ascend/utils.h
Comment thread sherpa-onnx/csrc/ascend/utils.h Outdated
Comment on lines +71 to +73
AclHostPtr(const AclDevicePtr &) = delete;
const AclHostPtr &operator=(const AclDevicePtr &) = delete;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Wrong deleted copy signatures leave AclHostPtr copyable (double-free risk).

You’re deleting ctors/assignments taking AclDevicePtr, not AclHostPtr. The real copy ctor/assignment remain, risking double free.

Apply:

-  AclHostPtr(const AclDevicePtr &) = delete;
-  const AclHostPtr &operator=(const AclDevicePtr &) = delete;
+  AclHostPtr(const AclHostPtr &) = delete;
+  AclHostPtr &operator=(const AclHostPtr &) = delete;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
AclHostPtr(const AclDevicePtr &) = delete;
const AclHostPtr &operator=(const AclDevicePtr &) = delete;
AclHostPtr(const AclHostPtr &) = delete;
AclHostPtr &operator=(const AclHostPtr &) = delete;
🤖 Prompt for AI Agents
sherpa-onnx/csrc/ascend/utils.h around lines 71 to 73: the deleted copy ctor and
assignment currently take AclDevicePtr, leaving the real AclHostPtr copy
ctor/assignment intact and risking double-free; replace those deletions with the
correct signatures that take AclHostPtr (i.e., declare AclHostPtr(const
AclHostPtr&) = delete; and const AclHostPtr& operator=(const AclHostPtr&) =
delete;) so copies of AclHostPtr are disabled.

Comment on lines +113 to +114
std::string GetInfo() const;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

GetInfo() implementation bugs (utils.cc): wrong APIs and fields, missing checks.

  • For outputs, use aclmdlGetOutputDataType(), not GetInputDataType().
  • After aclmdlGet(Input|Output)Dims, check return and don’t read uninitialized dims.
  • aclmdlIODims has dims/dimCount; printing dims.name is invalid.

Fix in utils.cc:

@@ void AclModel::GetInfo() const {
-    aclmdlIODims dims;
-    aclError ret = aclmdlGetInputDims(desc_->Get(), i, &dims);
-    os << " dim: " << dims.dimCount << "\n";
-    for (size_t d = 0; d < dims.dimCount; ++d) {
-      os << "  " << d << " -> " << dims.name << ", " << dims.dims[d] << "\n";
-    }
+    aclmdlIODims dims;
+    aclError ret = aclmdlGetInputDims(desc_->Get(), i, &dims);
+    SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclmdlGetInputDims");
+    os << " dim: " << dims.dimCount << "\n";
+    for (size_t d = 0; d < dims.dimCount; ++d) {
+      os << "  dim[" << d << "] = " << dims.dims[d] << "\n";
+    }
@@
-    aclDataType type = aclmdlGetInputDataType(desc_->Get(), i);
+    aclDataType type = aclmdlGetOutputDataType(desc_->Get(), i);
@@
-    aclmdlIODims dims;
-    aclError ret = aclmdlGetOutputDims(desc_->Get(), i, &dims);
-    os << " dim: " << dims.dimCount << "\n";
-    for (size_t d = 0; d < dims.dimCount; ++d) {
-      os << "  " << d << " -> " << dims.name << ", " << dims.dims[d] << "\n";
-    }
+    aclmdlIODims dims;
+    aclError ret = aclmdlGetOutputDims(desc_->Get(), i, &dims);
+    SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclmdlGetOutputDims");
+    os << " dim: " << dims.dimCount << "\n";
+    for (size_t d = 0; d < dims.dimCount; ++d) {
+      os << "  dim[" << d << "] = " << dims.dims[d] << "\n";
+    }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/utils.h around lines 113-114, the GetInfo()
implementation in utils.cc uses wrong APIs and reads invalid fields; update it
to call aclmdlGetOutputDataType() for outputs (keep aclmdlGetInputDataType() for
inputs), check the return value of aclmdlGetInputDims/aclmdlGetOutputDims before
using dims, and never access dims.name (use dims.dims array with dims.dimCount).
Add guards to avoid reading uninitialized dims on error, log or handle acl call
failures, and iterate only up to dimCount when printing dimensions.

Comment thread sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h

@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: 1

♻️ Duplicate comments (3)
sherpa-onnx/csrc/ascend/utils.cc (1)

313-313: Use correct function for output data type.

Line 313 incorrectly calls aclmdlGetInputDataType while iterating over model outputs. This should be aclmdlGetOutputDataType to retrieve the correct data type for output tensors.

Apply this diff:

-    aclDataType type = aclmdlGetInputDataType(desc_->Get(), i);
+    aclDataType type = aclmdlGetOutputDataType(desc_->Get(), i);
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (2)

99-113: Use appropriate log level for debug output.

Lines 102-103 and 110-111 use SHERPA_ONNX_LOGE (error level) for model information when config_.debug is enabled. Debug output should use a more appropriate log level such as SHERPA_ONNX_LOGD or SHERPA_ONNX_LOGI to avoid polluting error logs.

Apply this diff:

 void InitModel(const std::string &filename) {
   model_ = std::make_unique<AclModel>(filename);
   if (config_.debug) {
     auto s = model_->GetInfo();
-    SHERPA_ONNX_LOGE("%s", s.c_str());
+    SHERPA_ONNX_LOGI("%s", s.c_str());
   }
 }
 
 void InitModel(void *data, size_t size) {
   model_ = std::make_unique<AclModel>(data, size);
   if (config_.debug) {
     auto s = model_->GetInfo();
-    SHERPA_ONNX_LOGE("%s", s.c_str());
+    SHERPA_ONNX_LOGI("%s", s.c_str());
   }
 }

140-141: Add comment explaining +4 buffer safety margin.

The logits buffer allocation adds 4 extra frames beyond max_num_frames_. While the actual usage (lines 82-83, 90) respects the true num_frames * vocab_size_ size, a comment explaining this is an overflow safety margin would clarify the intent.

Apply this diff:

-  logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
-                                               vocab_size_ * sizeof(float));
+  // +4 frames as overflow safety margin
+  logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
+                                               vocab_size_ * sizeof(float));
🧹 Nitpick comments (2)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (2)

46-48: Consider validating frame size divisibility.

Line 48 assumes features.size() is perfectly divisible by 560. While ApplyLFR should guarantee this, an assertion or check would make the assumption explicit and catch potential upstream bugs.

Consider adding a validation:

 features = ApplyLFR(std::move(features));
 
+assert(features.size() % 560 == 0 && "Features must be divisible by 560");
 int32_t num_frames = features.size() / 560;

134-134: Add comment explaining max_num_frames calculation.

Line 134 uses a magic formula (10 * 100 - 7) / 6 + 1 to calculate max_num_frames_. A brief comment explaining this formula (e.g., "10 seconds at 100 frames/sec with LFR params") would improve readability.

Consider adding a comment:

-  max_num_frames_ = (10 * 100 - 7) / 6 + 1;
+  max_num_frames_ = (10 * 100 - 7) / 6 + 1;  // 10s audio: LFR with window=7, shift=6
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc078ca and 8dcf579.

📒 Files selected for processing (2)
  • sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1 hunks)
  • sherpa-onnx/csrc/ascend/utils.cc (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
sherpa-onnx/csrc/ascend/utils.cc (2)
sherpa-onnx/csrc/ascend/utils.h (16)
  • Acl (16-26)
  • AclContext (28-43)
  • AclContext (31-31)
  • Get (55-55)
  • Get (74-74)
  • Get (91-91)
  • Get (159-159)
  • Get (174-174)
  • Get (190-190)
  • AclDevicePtr (45-63)
  • AclHostPtr (65-80)
  • AclModelDesc (82-99)
  • AclModel (101-146)
  • AclMdlDataset (148-164)
  • AclDataBuffer (166-179)
  • AclTensorDesc (181-195)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (3)
  • device_id (115-125)
  • data (107-113)
  • data (107-107)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (1)
  • OfflineSenseVoiceModelAscend (15-39)
⏰ 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). (20)
  • GitHub Check: ubuntu-24.04 3.10
  • GitHub Check: ubuntu-latest Debug shared tts-ON
  • GitHub Check: macos-latest Debug shared tts-ON
  • GitHub Check: macos-latest Debug static tts-OFF
  • GitHub Check: ubuntu-latest Debug static tts-ON
  • GitHub Check: macos-latest Debug static tts-ON
  • GitHub Check: ubuntu-latest Release shared tts-ON
  • GitHub Check: ubuntu-latest Release shared tts-OFF
  • GitHub Check: ubuntu-latest Debug static tts-OFF
  • GitHub Check: Release shared-OFF tts-OFF
  • GitHub Check: Release shared-OFF tts-ON
  • GitHub Check: Debug shared-OFF tts-ON
  • GitHub Check: Debug shared-OFF tts-OFF
  • GitHub Check: Debug shared-ON tts-ON
  • GitHub Check: Release shared-ON tts-ON
  • GitHub Check: Debug shared-ON tts-OFF
  • GitHub Check: rknn shared OFF
  • GitHub Check: rknn shared ON
  • GitHub Check: swift (macos-13)
  • GitHub Check: swift (macos-latest)
🔇 Additional comments (8)
sherpa-onnx/csrc/ascend/utils.cc (4)

13-95: LGTM! Comprehensive enum-to-string converters.

The helper functions provide complete coverage of ACL data types and formats with appropriate fallback handling.


97-157: LGTM! Solid RAII wrappers for ACL resources.

The resource management classes correctly implement initialization, cleanup, and error handling. The conditional checks prevent double-free, and zero-size allocations are handled safely.


200-263: LGTM! Model metadata initialization is correct.

The initialization methods properly extract and store input/output names and shapes with appropriate error handling.


327-384: LGTM! Dataset and buffer wrappers are correctly implemented.

The RAII wrappers for datasets, data buffers, and tensor descriptors follow the same robust pattern with proper error handling and resource cleanup.

sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (4)

19-39: LGTM! Impl initialization follows a clear sequence.

The constructors properly orchestrate the initialization flow: device setup, model loading, and post-initialization. The template constructor correctly handles in-memory model data.


50-96: LGTM! Inference pipeline correctly orchestrates ACL operations.

The memory copies, dataset construction, model execution, and result retrieval all use proper ACL APIs with consistent error handling. Buffer sizes are correctly aligned between allocation and usage.


144-180: LGTM! LFR processing correctly handles frame windowing and truncation.

The ApplyLFR method properly implements low-frame-rate processing with sliding windows. The truncation logic (lines 153-163) appropriately warns users when input exceeds max_num_frames_ and clips the output.


182-227: LGTM! Clean pimpl pattern and platform-specific instantiations.

The private members are appropriately declared, the public interface correctly delegates to the impl, and the template instantiations properly support Android and OHOS platforms.

Comment thread sherpa-onnx/csrc/ascend/utils.cc Outdated
@csukuangfj
csukuangfj requested a review from Copilot October 28, 2025 01:28

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

Copilot reviewed 38 out of 38 changed files in this pull request and generated no new comments.


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

@csukuangfj

Copy link
Copy Markdown
Collaborator Author

@coderabbitai please review

@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: 2

♻️ Duplicate comments (3)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (2)

110-113: Use info/debug log level for model introspection, not error.

Avoid polluting error logs when config_.debug is true.

-      SHERPA_ONNX_LOGE("%s", s.c_str());
+      SHERPA_ONNX_LOGI("%s", s.c_str());

Also applies to: 118-121


142-151: Preallocate from metadata; document +4 extra frames.

Keep parameters consistent with meta and clarify extra capacity.

-    max_num_frames_ = (10 * 100 - 7) / 6 + 1;
+    // 10 s @ 100 fps after LFR; derive with metadata for consistency
+    max_num_frames_ =
+        (10 * 100 - meta_data_.window_size) / meta_data_.window_shift + 1;
@@
-    logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
-                                                 vocab_size_ * sizeof(float));
+    // +4 frames as safety headroom for dynamic shape rounding
+    logits_ptr_ = std::make_unique<AclDevicePtr>((max_num_frames_ + 4) *
+                                                 vocab_size_ * sizeof(float));
sherpa-onnx/csrc/ascend/utils.cc (1)

274-279: Fix GetInfo(): wrong field access and missing error checks for dims.

Must check aclmdlGet(Input|Output)Dims and don’t read dims.name (not valid). Use dims.dims[] with dimCount. Also print error via existing macro.

-    aclmdlIODims dims;
-    aclError ret = aclmdlGetInputDims(desc_->Get(), i, &dims);
-    os << " dim: " << dims.dimCount << "\n";
-    for (size_t d = 0; d < dims.dimCount; ++d) {
-      os << "  " << d << " -> " << dims.name << ", " << dims.dims[d] << "\n";
-    }
+    aclmdlIODims dims;
+    aclError ret = aclmdlGetInputDims(desc_->Get(), i, &dims);
+    SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclmdlGetInputDims");
+    os << " dim: " << dims.dimCount << "\n";
+    for (size_t d = 0; d < dims.dimCount; ++d) {
+      os << "  dim[" << d << "] = " << dims.dims[d] << "\n";
+    }
@@
-    aclmdlIODims dims;
-    aclError ret = aclmdlGetOutputDims(desc_->Get(), i, &dims);
-    os << " dim: " << dims.dimCount << "\n";
-    for (size_t d = 0; d < dims.dimCount; ++d) {
-      os << "  " << d << " -> " << dims.name << ", " << dims.dims[d] << "\n";
-    }
+    aclmdlIODims dims;
+    aclError ret = aclmdlGetOutputDims(desc_->Get(), i, &dims);
+    SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclmdlGetOutputDims");
+    os << " dim: " << dims.dimCount << "\n";
+    for (size_t d = 0; d < dims.dimCount; ++d) {
+      os << "  dim[" << d << "] = " << dims.dims[d] << "\n";
+    }

Also applies to: 299-304

🧹 Nitpick comments (4)
sherpa-onnx/csrc/ascend/utils.h (3)

21-22: Use canonical operator= signatures (drop const return type).

Assignment operators should return T&, not const T&. While deleted, keeping canonical signatures avoids surprises and matches normal lookup rules.

Apply:

-  const Acl &operator=(const Acl &) = delete;
+  Acl &operator=(const Acl &) = delete;
@@
-  const AclContext &operator=(const AclContext &) = delete;
+  AclContext &operator=(const AclContext &) = delete;
@@
-  const AclModelDesc &operator=(const AclModelDesc &) = delete;
+  AclModelDesc &operator=(const AclModelDesc &) = delete;

Also applies to: 34-35, 70-71


37-39: Make conversion operator const.

Allows use from const contexts and matches Get() const.

-  operator aclrtContext() { return context_; }
+  operator aclrtContext() const { return context_; }

76-81: Remove unused size_/Size() or populate it.

Currently always 0; dead API surface.

Options:

  • Drop Size()/size_, or
  • Set size_ to something meaningful (e.g., total IO count) and document it.
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1)

59-67: Minor: pass destination capacity via x_ptr_->Size() for consistency.

Semantically identical but clearer and consistent with prompt/logits paths.

-    aclError ret =
-        aclrtMemcpy(*x_ptr_, features.size() * sizeof(float), features.data(),
-                    features.size() * sizeof(float), ACL_MEMCPY_HOST_TO_DEVICE);
+    aclError ret = aclrtMemcpy(*x_ptr_, x_ptr_->Size(), features.data(),
+                               features.size() * sizeof(float),
+                               ACL_MEMCPY_HOST_TO_DEVICE);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8dcf579 and 60ec50e.

📒 Files selected for processing (4)
  • sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1 hunks)
  • sherpa-onnx/csrc/ascend/utils.cc (1 hunks)
  • sherpa-onnx/csrc/ascend/utils.h (1 hunks)
  • sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
sherpa-onnx/csrc/ascend/utils.cc (2)
sherpa-onnx/csrc/ascend/utils.h (13)
  • Acl (16-26)
  • AclContext (28-42)
  • Get (54-54)
  • Get (73-73)
  • Get (141-141)
  • Get (156-156)
  • Get (172-172)
  • AclDevicePtr (44-62)
  • AclModelDesc (64-81)
  • AclModel (83-128)
  • AclMdlDataset (130-146)
  • AclDataBuffer (148-161)
  • AclTensorDesc (163-177)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (3)
  • device_id (124-134)
  • data (116-122)
  • data (116-116)
sherpa-onnx/csrc/ascend/utils.h (1)
sherpa-onnx/csrc/ascend/utils.cc (35)
  • Acl (97-101)
  • Acl (103-108)
  • AclContext (110-113)
  • AclContext (115-120)
  • Get (122-122)
  • Get (122-122)
  • AclDevicePtr (124-133)
  • AclDevicePtr (135-140)
  • AclModelDesc (142-151)
  • AclModelDesc (153-158)
  • AclModel (160-167)
  • AclModel (169-174)
  • AclModel (176-181)
  • GetInfo (248-308)
  • GetInfo (248-248)
  • Init (183-191)
  • Init (183-183)
  • InitInputNames (193-201)
  • InitInputNames (193-193)
  • InitInputShapes (203-219)
  • InitInputShapes (203-203)
  • InitOutputNames (221-228)
  • InitOutputNames (221-221)
  • InitOutputShapes (230-246)
  • InitOutputShapes (230-230)
  • AclMdlDataset (310-316)
  • AclMdlDataset (318-323)
  • AddBuffer (325-328)
  • AddBuffer (325-325)
  • SetTensorDesc (330-336)
  • SetTensorDesc (330-331)
  • AclDataBuffer (338-345)
  • AclDataBuffer (347-352)
  • AclTensorDesc (354-361)
  • AclTensorDesc (363-367)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc (1)
sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.h (1)
  • OfflineSenseVoiceModelAscend (15-39)
⏰ 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 shared tts-OFF
  • GitHub Check: Release static tts-OFF
  • GitHub Check: Debug static tts-OFF
  • GitHub Check: Debug shared tts-ON
  • GitHub Check: ubuntu-24.04 3.8
  • GitHub Check: ubuntu-latest Release static tts-ON
  • GitHub Check: ubuntu-latest Debug shared tts-ON
  • GitHub Check: ubuntu-latest Debug static tts-ON
  • GitHub Check: ubuntu-latest Release shared tts-OFF
  • GitHub Check: Debug shared-ON tts-ON
  • GitHub Check: Release shared-ON tts-ON
  • GitHub Check: Release shared-ON tts-OFF
  • GitHub Check: Debug shared-ON tts-OFF
  • GitHub Check: rknn shared OFF
  • GitHub Check: Release shared-OFF tts-OFF
  • GitHub Check: Debug shared-OFF tts-OFF
  • GitHub Check: Debug shared-OFF tts-ON
  • GitHub Check: Release shared-OFF tts-ON
  • GitHub Check: rknn shared ON
🔇 Additional comments (1)
sherpa-onnx/csrc/offline-sense-voice-model-meta-data.h (1)

15-23: LGTM: sensible defaults and lang2id fix.

Defaults align with SenseVoice; “ja” key looks correct. No issues spotted.

Also applies to: 42-44, 46-47

Comment on lines +124 to +134
void PreInit() {
int32_t device_id = 0;
aclError ret = aclrtSetDevice(device_id);
SHERPA_ONNX_ASCEND_CHECK(
ret, "Failed to call aclrtSetDevice with device id: %d", device_id);

context_ = std::make_unique<AclContext>(device_id);

ret = aclrtSetCurrentContext(*context_);
SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclrtSetCurrentContext");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reset device on teardown; match aclrtSetDevice in PreInit.

Add device_id_ member, store it in PreInit, and call aclrtResetDevice in Impl dtor after destroying context. Prevents leaks on Ascend.

 class OfflineSenseVoiceModelAscend::Impl {
  public:
+  ~Impl() {
+    // Destroy context before resetting device.
+    context_.reset();
+    aclError ret = aclrtResetDevice(device_id_);
+    SHERPA_ONNX_ASCEND_CHECK(ret, "Failed to call aclrtResetDevice");
+  }
@@
-  void PreInit() {
-    int32_t device_id = 0;
-    aclError ret = aclrtSetDevice(device_id);
+  void PreInit() {
+    device_id_ = 0;
+    aclError ret = aclrtSetDevice(device_id_);
     SHERPA_ONNX_ASCEND_CHECK(
-        ret, "Failed to call aclrtSetDevice with device id: %d", device_id);
+        ret, "Failed to call aclrtSetDevice with device id: %d", device_id_);
 
-    context_ = std::make_unique<AclContext>(device_id);
+    context_ = std::make_unique<AclContext>(device_id_);
@@
  private:
+  int32_t device_id_ = 0;
   std::mutex mutex_;
   Acl acl_;

Also applies to: 191-208

🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc around lines 124
to 134 (and also apply change at ~191-208), PreInit currently calls
aclrtSetDevice(0) but does not store the device id and the Impl destructor does
not call aclrtResetDevice, which can leak device resources; add a member int32_t
device_id_ to the Impl class, set device_id_ = device_id in PreInit after
determining the device, and in the Impl destructor, after destroying/freeing
context_ and before returning, call aclrtResetDevice(device_id_) and check its
return value (use existing SHERPA_ONNX_ASCEND_CHECK macro) to match the
aclrtSetDevice call and ensure the device is reset.

Comment on lines +158 to +161
int32_t in_num_frames = in.size() / in_feat_dim;
int32_t out_num_frames =
(in_num_frames - lfr_window_size) / lfr_window_shift + 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix LFR underflow: out_num_frames becomes 1 when input < window.

Current formula yields 1 for small inputs, causing OOB reads when copying LFR windows. Guard explicitly.

-    int32_t out_num_frames =
-        (in_num_frames - lfr_window_size) / lfr_window_shift + 1;
+    int32_t out_num_frames = 0;
+    if (in_num_frames >= lfr_window_size) {
+      out_num_frames =
+          (in_num_frames - lfr_window_size) / lfr_window_shift + 1;
+    }
🤖 Prompt for AI Agents
In sherpa-onnx/csrc/ascend/offline-sense-voice-model-ascend.cc around lines 158
to 161, the LFR output frame calculation underflows: when in_num_frames <
lfr_window_size the current formula yields 1 and later causes out-of-bounds
reads when building windows; fix by guarding the computation — if in_num_frames
< lfr_window_size set out_num_frames to 0 (or otherwise handle the empty-output
case) else compute out_num_frames = (in_num_frames - lfr_window_size) /
lfr_window_shift + 1; ensure this branch is taken before any LFR window indexing
so no OOB accesses occur.

@coderabbitai

coderabbitai Bot commented Oct 28, 2025

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@csukuangfj I'll provide a comprehensive review of this PR.

Overview

This PR successfully adds Ascend NPU support for SenseVoice ASR using the ACL C API. The implementation follows the existing RKNN pattern and introduces clean RAII wrappers. However, I notice this PR also includes many Windows CI workflow changes that seem unrelated to the main objective.

✅ Strengths

  1. Clean Architecture: The Ascend implementation follows the established pattern with good separation of concerns
  2. RAII Wrappers: The ACL resource management in utils.h/cc uses proper RAII with deleted copy constructors
  3. Error Handling: The SHERPA_ONNX_ASCEND_CHECK macro provides consistent error checking
  4. Conditional Compilation: Proper use of #if guards to keep code modular
  5. Metadata Defaults: Adding default initializers to OfflineSenseVoiceModelMetaData improves usability

🔍 Key Review Points

1. CMake Configuration (CMakeLists.txt)

The Ascend NPU detection logic looks good, but consider:

  • The fallback path /usr/local/Ascend/ascend-toolkit/latest might not work on all systems
  • Consider adding version checking for CANN compatibility

2. Memory Management (sherpa-onnx/csrc/ascend/utils.cc)

The RAII wrappers are well-designed. A few observations:

// In AclDevicePtr constructor
void *ptr_;
auto ret = aclrtMalloc(&ptr_, size_, policy_);

✅ Good: Proper cleanup in destructor
⚠️ Consider: Add size tracking and provide Size() accessor for debugging

3. Error Handling (sherpa-onnx/csrc/ascend/macros.h)

#define SHERPA_ONNX_ASCEND_CHECK(ret, msg, ...)               \
  do {                                                         \
    if ((ret) != ACL_ERROR_NONE) {                            \
      ...
      SHERPA_ONNX_EXIT(-1);                                   \
    }                                                          \
  } while (0)

✅ Good: Retrieves detailed error message via aclGetRecentErrMsg()
⚠️ Consider: In library code, exiting the process may be too aggressive. Consider throwing exceptions or returning error codes for better error recovery.

4. Model Implementation (offline-sense-voice-model-ascend.cc)

The ApplyLFR function and model execution flow look correct. However:

int32_t num_frames = (feature_len - window_size) / window_shift + 1;
if (num_frames * window_shift + window_size - 1 != feature_len) {
  feature_len = num_frames * window_shift + window_size - 1;
  features.resize(feature_len * 80);  // Truncates if needed
}

⚠️ Potential Issue: Silent truncation could lead to unexpected behavior. Consider logging when features are truncated.

5. Integration (offline-recognizer-impl.cc)

The provider selection logic is clean:

if (config.provider == "ascend") {
#if defined(SHERPA_ONNX_ENABLE_ASCEND_NPU)
  if (!config.model_config.sense_voice.model.empty()) {
    return std::make_unique<OfflineRecognizerSenseVoiceAscendImpl>(config);
  }
  ...
#else
  SHERPA_ONNX_LOGE(
      "Please use -DSHERPA_ONNX_ENABLE_ASCEND_NPU=ON to build for Ascend "
      "NPU");
  SHERPA_ONNX_EXIT(-1);
#endif
}

✅ Clear guidance when feature is not enabled

6. Default Values (offline-sense-voice-model-meta-data.h)

int32_t with_itn_id = 14;
int32_t without_itn_id = 15;
int32_t window_size = 7;
int32_t window_shift = 6;
int32_t vocab_size = 25055;

✅ Good: Sensible defaults reduce configuration burden
📝 Consider: Document these magic numbers in comments (e.g., why 14/15 for ITN IDs?)

🤔 Questions & Suggestions

  1. Windows CI Changes: The PR includes many windows-latest → windows-2022 changes across ~20 workflow files. Are these intentional for this PR, or should they be in a separate PR?

  2. Device Selection: The code hardcodes device 0:

    AclContext(int32_t device_id = 0)

    Consider exposing device selection through configuration.

  3. Resource Cleanup: In AclModel::Init(), if initialization fails midway, are all resources properly cleaned up? RAII helps, but verify exception safety.

  4. Testing: The PR description mentions test steps for 910B. Consider adding:

    • Unit tests for the ACL wrapper classes
    • Tests for different input sizes and edge cases
    • CI integration (if Ascend hardware is available)
  5. Documentation: Consider adding:

    • Architecture diagram showing the Ascend integration
    • API documentation for public classes
    • Troubleshooting guide for common CANN/ACL errors

📝 Minor Issues

  1. Consistency: Some files have path comments updated (e.g., rknn/macros.h) while others don't. Ensure consistency.

  2. Unused Variables: Check if neg_mean and inv_stddev marked as "not used on NPU" are dead code that could be removed.

  3. Code Reuse: The offline-ctc-greedy-search-decoder-rknn.cc is now shared between RKNN and Ascend. Consider renaming to reflect this (e.g., offline-ctc-greedy-search-decoder-npu.cc).

🎯 Recommendation

The core Ascend NPU implementation is well-structured and ready for merge with minor improvements. The main concerns are:

  1. Clarify the Windows workflow changes
  2. Consider more graceful error handling instead of process exit
  3. Add device selection configuration
  4. Add documentation and tests

Would you like me to help with any specific aspect, such as:

  • Generating unit tests for the ACL wrappers?
  • Creating documentation for the Ascend integration?
  • Reviewing specific files in more detail?

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