From f66ed428910738cd49b8e7d575df1a735af42440 Mon Sep 17 00:00:00 2001 From: anubissbe <116725818+anubissbe@users.noreply.github.com> Date: Tue, 21 Jul 2026 22:30:26 +0200 Subject: [PATCH 1/2] fix: don't cast Silero VAD to fp16 SileroVAD::to_half() casts the VAD weights but leaves its context buffer, LSTM state and audio input in fp32. With an fp16 transcriber, enable_vad() therefore builds a mixed-dtype graph and MPSGraph aborts the process: 'mps.add' op requires the same element type for all operands and results %3 = "mps.add"(%arg0, %arg1) : (tensor<1x512xf32>, tensor<512xf16>) failed assertion `Error: MLIR pass manager failed' use_fp16_ in SileroVAD is written but never read, so the cast has nothing backing it. Drop the cast at the three enable_vad() call sites; the VAD still moves to GPU. It is a ~1.2 MB preprocessor emitting segment boundaries rather than tensors entering the ASR graph, so fp32 is numerically irrelevant here. Fixes #31 Co-Authored-By: Claude Opus 4.8 --- include/parakeet/api/transcribe.hpp | 16 ++++++++++++---- src/api/diarize.cpp | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/parakeet/api/transcribe.hpp b/include/parakeet/api/transcribe.hpp index b317451..9fbf4ba 100644 --- a/include/parakeet/api/transcribe.hpp +++ b/include/parakeet/api/transcribe.hpp @@ -492,8 +492,12 @@ class Transcriber { /// Enable VAD preprocessing. Call after to_half()/to_gpu(). void enable_vad(const std::string &vad_weights_path) { vad_ = std::make_unique(vad_weights_path); - if (use_fp16_) - vad_->to_half(); + // The VAD deliberately stays fp32 even when the ASR model is fp16. + // SileroVAD::to_half() casts the weights but leaves the context + // buffer, LSTM state and audio input fp32, which aborts the process + // under MPSGraph ('mps.add' requires the same element type). The VAD + // is a ~1.2 MB preprocessor that only emits segment boundaries, so + // running it in fp32 costs almost nothing. if (use_gpu_) vad_->to_gpu(); } @@ -841,8 +845,12 @@ class TDTTranscriber { /// Enable VAD preprocessing. Call after to_half()/to_gpu(). void enable_vad(const std::string &vad_weights_path) { vad_ = std::make_unique(vad_weights_path); - if (use_fp16_) - vad_->to_half(); + // The VAD deliberately stays fp32 even when the ASR model is fp16. + // SileroVAD::to_half() casts the weights but leaves the context + // buffer, LSTM state and audio input fp32, which aborts the process + // under MPSGraph ('mps.add' requires the same element type). The VAD + // is a ~1.2 MB preprocessor that only emits segment boundaries, so + // running it in fp32 costs almost nothing. if (use_gpu_) vad_->to_gpu(); } diff --git a/src/api/diarize.cpp b/src/api/diarize.cpp index 7d46f9d..eff4cca 100644 --- a/src/api/diarize.cpp +++ b/src/api/diarize.cpp @@ -75,8 +75,8 @@ void DiarizedTranscriber::to_half() { void DiarizedTranscriber::enable_vad(const std::string &vad_weights_path) { vad_ = std::make_unique(vad_weights_path); - if (use_fp16_) - vad_->to_half(); + // See ParakeetTranscriber::enable_vad — casting the VAD to fp16 mixes an + // fp32 context buffer with fp16 weights and aborts under MPSGraph. if (use_gpu_) vad_->to_gpu(); } From bb82249bca373500981dcda4afbca7000353a8fe Mon Sep 17 00:00:00 2001 From: anubissbe <116725818+anubissbe@users.noreply.github.com> Date: Tue, 21 Jul 2026 22:34:35 +0200 Subject: [PATCH 2/2] fix: correct stale class reference in VAD comment The comment pointed at ParakeetTranscriber::enable_vad, which does not exist. The declaring class is Transcriber (include/parakeet/api/transcribe.hpp). Co-Authored-By: Claude Opus 4.8 --- src/api/diarize.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/diarize.cpp b/src/api/diarize.cpp index eff4cca..e3e1b42 100644 --- a/src/api/diarize.cpp +++ b/src/api/diarize.cpp @@ -75,8 +75,8 @@ void DiarizedTranscriber::to_half() { void DiarizedTranscriber::enable_vad(const std::string &vad_weights_path) { vad_ = std::make_unique(vad_weights_path); - // See ParakeetTranscriber::enable_vad — casting the VAD to fp16 mixes an - // fp32 context buffer with fp16 weights and aborts under MPSGraph. + // See Transcriber::enable_vad — casting the VAD to fp16 mixes an fp32 + // context buffer with fp16 weights and aborts under MPSGraph. if (use_gpu_) vad_->to_gpu(); }