Add Pascal API for Cohere Transcribe - #3463
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📝 WalkthroughWalkthroughThis 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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
📒 Files selected for processing (5)
.github/workflows/pascal.yamlpascal-api-examples/non-streaming-asr/cohere_transcribe.paspascal-api-examples/non-streaming-asr/run-cohere-transcribe.shsherpa-onnx/csrc/session.ccsherpa-onnx/pascal-api/sherpa_onnx.pas
| 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; |
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "run-cohere-transcribe.sh" 2>/dev/nullRepository: k2-fsa/sherpa-onnx
Length of output: 126
🏁 Script executed:
cat -n ./pascal-api-examples/non-streaming-asr/run-cohere-transcribe.shRepository: 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 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate and examine the file
fd -t f "run-cohere-transcribe.sh" | head -5Repository: 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"
fiRepository: 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 -10Repository: 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 -5Repository: 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 -5Repository: 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 -30Repository: 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 shRepository: k2-fsa/sherpa-onnx
Length of output: 44
🏁 Script executed:
# Check if any scripts set PATH for libraries
rg "export PATH.*lib" --type shRepository: 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.shRepository: 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 -50Repository: 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.
Summary by CodeRabbit
Release Notes
New Features
Tests