Skip to content

Add Pascal API for Cohere Transcribe - #3463

Merged
csukuangfj merged 3 commits into
k2-fsa:masterfrom
csukuangfj:pascal-api
Apr 3, 2026
Merged

csukuangfj merged 3 commits into
k2-fsa:masterfrom
csukuangfj:pascal-api

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Apr 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for Cohere Transcribe model in Pascal API with encoder/decoder configuration options
    • Added new example demonstrating non-streaming speech-to-text transcription with Cohere Transcribe
  • Tests

    • Added CI workflow test for Cohere Transcribe ASR functionality

csukuangfj and others added 3 commits April 2, 2026 18:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 3, 2026
@coderabbitai

coderabbitai Bot commented Apr 3, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds Cohere Transcribe model support to the Pascal API for offline speech-to-text transcription. It introduces a new Pascal example program with configuration types, updates the workflow to use an improved Lazarus setup action, adds a build script, and modifies C interop handling for profiling paths.

Changes

Cohort / File(s) Summary
Workflow Improvements
.github/workflows/pascal.yaml
Replaced Windows-specific Lazarus installation with gcarreno/setup-lazarus@v3.3.1 action; removed hardcoded FPC PATH exports; expanded triggers to include pascal-api branch pushes; added new Cohere Transcribe test step.
Pascal API Extensions
sherpa-onnx/pascal-api/sherpa_onnx.pas
Added TSherpaOnnxOfflineCohereTranscribeModelConfig record with ToString and Initialize methods; extended TSherpaOnnxOfflineModelConfig with CohereTranscribe field; added TSherpaOnnxOfflineStream.SetOption method; updated configuration conversion to populate Cohere Transcribe C struct fields.
Cohere Transcribe Example
pascal-api-examples/non-streaming-asr/cohere_transcribe.pas, pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh
New Pascal example program demonstrating Cohere Transcribe non-streaming ASR with configuration, model loading, audio processing, and result retrieval; accompanying build script handles CMake compilation of Sherpa-ONNX libraries, model download, Pascal program compilation, and runtime execution with library path exports.
C API Update
sherpa-onnx/csrc/session.cc
Changed EnableProfiling argument from raw ProfilingFilePrefix.c_str() to SHERPA_ONNX_TO_ORT_PATH(config["ProfilingFilePrefix"]) for consistent path handling.

Sequence Diagram(s)

sequenceDiagram
    participant App as Pascal Example App
    participant API as Sherpa ONNX<br/>Pascal API
    participant CLib as Sherpa ONNX<br/>C Library
    participant ONNX as ONNX Runtime

    App->>API: Initialize offline recognizer config
    App->>API: Set CohereTranscribe model paths & options
    App->>API: Create offline recognizer instance
    App->>API: Create offline stream
    App->>API: SetOption(language, "English")
    App->>CLib: Load model & initialize recognizer
    CLib->>ONNX: Create ONNX session (encoder/decoder)
    ONNX-->>CLib: Session ready
    CLib-->>API: Recognizer instance
    App->>API: Load WAV audio file
    App->>API: Feed audio samples to stream
    API->>CLib: Submit audio buffer
    App->>API: Decode(stream)
    CLib->>ONNX: Run inference on audio frames
    ONNX-->>CLib: Prediction results
    CLib-->>API: Decoded recognition result
    API-->>App: Return transcript & timing stats
    App->>App: Display result, cleanup
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through code with glee,
Cohere Transcribe now speaks to thee!
Pascal plays the melody sweet,
Audio streams in perfect beat,
From wav to text, the journey's light! 🎵

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Add Pascal API for Cohere Transcribe' accurately and concisely describes the main change: introducing Pascal API support for Cohere Transcribe functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

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

❤️ Share

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for the Cohere Transcribe non-streaming ASR model to the Pascal API. Key changes include the addition of a new example application and shell script, the implementation of the TSherpaOnnxOfflineCohereTranscribeModelConfig record, and the inclusion of a SetOption method for offline streams in the Pascal bindings. Additionally, a minor fix was applied to the C++ core to ensure profiling file paths are correctly handled using the SHERPA_ONNX_TO_ORT_PATH macro. I have no feedback to provide as there are no review comments to address.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pascal-api-examples/non-streaming-asr/cohere_transcribe.pas`:
- Around line 49-65: SherpaOnnxReadWave can return Wave.SampleRate = 0 on
failure, but the example proceeds to call Stream.AcceptWaveform and compute
RealTimeFactor (using Length(Wave.Samples) / Wave.SampleRate) which leads to
divide-by-zero; add an immediate check after SherpaOnnxReadWave: if
Wave.SampleRate = 0 then report a clear error (e.g., write to stderr or use the
program logger) and exit/raise before calling Stream.AcceptWaveform,
Recognizer.Decode, or computing Elapsed/RealTimeFactor so the example fails fast
on missing/corrupt/empty WAV input.

In `@pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh`:
- Line 6: The unquoted variable expansions for SHERPA_ONNX_DIR and other uses of
SCRIPT_DIR (lines showing SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd) and the
expansions at lines 36-37) will break on paths with spaces; update these to use
quoted expansions (e.g., "$SCRIPT_DIR") wherever SCRIPT_DIR or SHERPA_ONNX_DIR
is expanded, and ensure the subshell cd uses the quoted path so the computed
SHERPA_ONNX_DIR is correct even when the repo is checked out under a path with
spaces.
- Line 10: The script checks for sherpa-onnx-c-api.dll but never updates PATH
for Windows DLL resolution; update run-cohere-transcribe.sh to export PATH to
include the native lib dir (../../build/install/lib) when setting
LD_LIBRARY_PATH and DYLD_LIBRARY_PATH so Windows processes can find
sherpa-onnx-c-api.dll at runtime—modify the section that sets LD_LIBRARY_PATH
and DYLD_LIBRARY_PATH to also prepend or append the same directory to PATH when
the DLL file (sherpa-onnx-c-api.dll) is present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c7200c29-bed6-4e3c-a1b8-248964ef3317

📥 Commits

Reviewing files that changed from the base of the PR and between 99206ad and becda4f.

📒 Files selected for processing (5)
  • .github/workflows/pascal.yaml
  • pascal-api-examples/non-streaming-asr/cohere_transcribe.pas
  • pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh
  • sherpa-onnx/csrc/session.cc
  • sherpa-onnx/pascal-api/sherpa_onnx.pas

Comment on lines +49 to +65
Wave := SherpaOnnxReadWave(WaveFilename);

Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;

Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);

RecognitionResult := Recognizer.GetResult(Stream);

Stop := Now;

Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;

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

Fail fast when the input WAV cannot be read.

SherpaOnnxReadWave() returns SampleRate := 0 on failure in sherpa-onnx/pascal-api/sherpa_onnx.pas, Lines 1637-1643. Lines 56 and 64-65 then use that value immediately, so a missing/corrupt or empty en.wav turns this example into an AcceptWaveform call plus a divide-by-zero in the RTF math instead of a clear error.

💡 Proposed fix
   Wave := SherpaOnnxReadWave(WaveFilename);
+
+  if Wave.SampleRate <= 0 then
+  begin
+    WriteLn(Format('Failed to read wave: %s', [WaveFilename]));
+    Halt(1);
+  end;
+
+  if Length(Wave.Samples) = 0 then
+  begin
+    WriteLn(Format('Wave has no samples: %s', [WaveFilename]));
+    Halt(1);
+  end;
 
   Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
   Stream := Recognizer.CreateStream();
📝 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
Wave := SherpaOnnxReadWave(WaveFilename);
Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;
Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);
RecognitionResult := Recognizer.GetResult(Stream);
Stop := Now;
Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;
Wave := SherpaOnnxReadWave(WaveFilename);
if Wave.SampleRate <= 0 then
begin
WriteLn(Format('Failed to read wave: %s', [WaveFilename]));
Halt(1);
end;
if Length(Wave.Samples) = 0 then
begin
WriteLn(Format('Wave has no samples: %s', [WaveFilename]));
Halt(1);
end;
Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;
Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);
RecognitionResult := Recognizer.GetResult(Stream);
Stop := Now;
Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/cohere_transcribe.pas` around lines 49
- 65, SherpaOnnxReadWave can return Wave.SampleRate = 0 on failure, but the
example proceeds to call Stream.AcceptWaveform and compute RealTimeFactor (using
Length(Wave.Samples) / Wave.SampleRate) which leads to divide-by-zero; add an
immediate check after SherpaOnnxReadWave: if Wave.SampleRate = 0 then report a
clear error (e.g., write to stderr or use the program logger) and exit/raise
before calling Stream.AcceptWaveform, Recognizer.Decode, or computing
Elapsed/RealTimeFactor so the example fails fast on missing/corrupt/empty WAV
input.

set -ex

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)

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

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "run-cohere-transcribe.sh" 2>/dev/null

Repository: k2-fsa/sherpa-onnx

Length of output: 126


🏁 Script executed:

cat -n ./pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh

Repository: k2-fsa/sherpa-onnx

Length of output: 1874


Quote variable expansions to handle checkout paths with spaces.

Line 6 and lines 36-37 use unquoted variable expansions that will break if the repository is checked out under a path containing spaces. Line 5 in the same script already demonstrates proper quoting practices for this scenario.

💡 Proposed fix
-SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)
+SHERPA_ONNX_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
@@
 fpc \
   -dSHERPA_ONNX_USE_SHARED_LIBS \
-  -Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api \
-  -Fl$SHERPA_ONNX_DIR/build/install/lib \
+  "-Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api" \
+  "-Fl$SHERPA_ONNX_DIR/build/install/lib" \
   ./cohere_transcribe.pas
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 6-6: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh` at line 6,
The unquoted variable expansions for SHERPA_ONNX_DIR and other uses of
SCRIPT_DIR (lines showing SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd) and the
expansions at lines 36-37) will break on paths with spaces; update these to use
quoted expansions (e.g., "$SCRIPT_DIR") wherever SCRIPT_DIR or SHERPA_ONNX_DIR
is expanded, and ensure the subshell cd uses the quoted path so the computed
SHERPA_ONNX_DIR is correct even when the repo is checked out under a path with
spaces.


echo "SHERPA_ONNX_DIR: $SHERPA_ONNX_DIR"

if [[ ! -f ../../build/install/lib/libsherpa-onnx-c-api.dylib && ! -f ../../build/install/lib/libsherpa-onnx-c-api.so && ! -f ../../build/install/lib/sherpa-onnx-c-api.dll ]]; then

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

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the file
fd -t f "run-cohere-transcribe.sh" | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 124


🏁 Script executed:

# Read the specific file to see the actual content
if [ -f "pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh" ]; then
  cat -n "pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh"
fi

Repository: k2-fsa/sherpa-onnx

Length of output: 1874


🏁 Script executed:

# Also check if there are similar scripts to understand the pattern
fd -t f "run-.*\.sh$" | grep -E "(non-streaming|streaming)" | head -10

Repository: k2-fsa/sherpa-onnx

Length of output: 616


🏁 Script executed:

# Look for C API examples in other languages
fd -t f "run-.*\.sh$" | xargs grep -l "sherpa-onnx-c-api" | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 358


🏁 Script executed:

# Check C examples specifically
fd -t f "run-.*\.sh$" c-api-examples/ 2>/dev/null | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Look at another example of how library paths are handled
fd -t f "run-.*\.sh$" c-api-examples/ 2>/dev/null -exec grep -A 5 "export.*LIBRARY_PATH" {} + | head -30

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Search for any case statements or Windows-specific handling in scripts
rg "MINGW|MSYS|CYGWIN|uname" --type sh

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Check if any scripts set PATH for libraries
rg "export PATH.*lib" --type sh

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Look at all pascal examples to see if they have similar issues
fd -t f "run-.*\.sh$" pascal-api-examples/ -exec cat -n {} + | grep -A 10 -B 2 "LIBRARY_PATH"

Repository: k2-fsa/sherpa-onnx

Length of output: 292


🏁 Script executed:

# Look for PowerShell scripts or Windows batch files
fd -t f "\.(ps1|bat|cmd)$"

Repository: k2-fsa/sherpa-onnx

Length of output: 780


🏁 Script executed:

# Read the pascal examples to see the pattern
cat pascal-api-examples/non-streaming-asr/run-dolphin-ctc.sh

Repository: k2-fsa/sherpa-onnx

Length of output: 1504


🏁 Script executed:

# Check if there's documentation about Windows support
fd -t f "README|WINDOWS|readme" | head -3 | xargs cat 2>/dev/null | head -50

Repository: k2-fsa/sherpa-onnx

Length of output: 2276


Add PATH export for Windows DLL discovery.

Line 10 checks for sherpa-onnx-c-api.dll, but lines 40-41 only set LD_LIBRARY_PATH and DYLD_LIBRARY_PATH. On Windows, the executable won't find the DLL at runtime without PATH being set. This is a recurring pattern across all pascal example scripts.

Proposed fix
-export LD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$DYLD_LIBRARY_PATH
+case "$(uname -s)" in
+  Darwin*)
+    export DYLD_LIBRARY_PATH="$SHERPA_ONNX_DIR/build/install/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
+    ;;
+  MINGW*|MSYS*|CYGWIN*)
+    export PATH="$SHERPA_ONNX_DIR/build/install/lib:$PATH"
+    ;;
+  *)
+    export LD_LIBRARY_PATH="$SHERPA_ONNX_DIR/build/install/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+    ;;
+esac
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh` at line 10,
The script checks for sherpa-onnx-c-api.dll but never updates PATH for Windows
DLL resolution; update run-cohere-transcribe.sh to export PATH to include the
native lib dir (../../build/install/lib) when setting LD_LIBRARY_PATH and
DYLD_LIBRARY_PATH so Windows processes can find sherpa-onnx-c-api.dll at
runtime—modify the section that sets LD_LIBRARY_PATH and DYLD_LIBRARY_PATH to
also prepend or append the same directory to PATH when the DLL file
(sherpa-onnx-c-api.dll) is present.

@csukuangfj
csukuangfj merged commit f1098aa into k2-fsa:master Apr 3, 2026
1 of 27 checks passed
@csukuangfj
csukuangfj deleted the pascal-api branch April 3, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant