feat(diarization): add diarization and SAS support via parakeet.cpp - #3324
Conversation
localai-org-maint-bot
left a comment
There was a problem hiding this comment.
Reviewed the seven-file diff at 64f2c430c2dda714d743bb2a0f0c2dda00cf5d94. These are source-backed findings; I could not run native build/model gates in this environment.
-
Default builds fetch a nonexistent dependency branch.
CMakeLists.txtenables diarization by default and usesGIT_TAG mainfor parakeet.cpp.git ls-remotereturns onlyrefs/heads/master(2bf88954), with norefs/heads/main. The required diarization APIs are still in parakeet.cpp #71. Pin a revision containing those APIs and verify a clean default configure/build. The local-directory alternative also only setsparakeet_cpp_SOURCE_DIR; it never adds that source directory to the build, so it does not create theparakeettarget. Exercise both dependency paths and the OFF configuration. -
The SAS path loads an HF directory as a GGUF file and hides failure.
vllm_engine_loadpasses the sameparams->model_pathtoParakeetTranscriber::FromDirandparakeet_capi_load. The latter explicitly takes a GGUF file (also checked against parakeet.cpp #71's header and implementation). Its null return is not checked. Both C SAS functions then treat a null SAS result asVLLM_OKwith zero utterances. The C++ helpers instead return un-attributed text. Connect the existing transcriber output to the merge, or expose an explicit ASR GGUF input; propagate load/inference errors. Cover a real HF transcription handle through the public SAS entry point. -
The new server routes have no production setup. Routes are conditional on
diarizer_/sas_, but this diff adds noserver_main.cppwiring and that file at this head contains noset_diarizerorset_sascall. Starting the shipped server cannot activate the advertised endpoints. Wire model/configuration loading and callbacks, then test requests through the real server entry point. No tests are added in this PR.
@mudler these need resolution before a merge recommendation. I have not modified the cross-repository integration or claimed device/parity acceptance.
…ABI v30) Add speaker diarization and speaker-attributed ASR (SAS) to vllm.cpp by linking parakeet.cpp as a FetchContent dependency. The diarization stack (Nemotron-3-Diarization Sortformer encoder, speaker head, AOSC streaming, and SAS merge layer) lives in parakeet.cpp; vllm.cpp wraps it through a clean C++ seam. New C++ seam (include/vllm/multimodal/diarization.h): - Diarizer class: loads a diarization GGUF, exposes Diarize() and DiarizeWavFile() returning speaker segments - SpeakerAttributedASR struct + TranscribeAndDiarize() helpers: run both ASR and diarization on the same audio and merge results New C ABI (include/vllm.h, ABI v30): - vllm_diarization_load: load a diarization GGUF as a separate engine - vllm_diarize_path / vllm_diarize_pcm: diarize a WAV file or raw PCM - vllm_transcribe_and_diarize / _pcm: combined ASR + diarization - vllm_diarization_free / vllm_sas_result_free: cleanup New server endpoints (registered only when a diarizer/SAS is attached): - POST /v1/audio/diarizations: returns speaker segments as JSON - POST /v1/audio/sas: returns speaker-attributed utterances as JSON CMakeLists.txt: parakeet.cpp is fetched from GitHub (or pointed at a local tree via VLLM_CPP_PARAKEET_CPP_DIR). The feature is gated by VLLM_CPP_WITH_DIARIZATION (ON by default). When disabled, every diarization function returns an error and the endpoints are not registered — the library is byte-identical to before.
…stubs - parakeet.cpp offline diarize_path/pcm return JSON strings, not structs (no parakeet_diarization_result or parakeet_capi_free_diarization_result) - Parse JSON in both vllm_c.cpp and diarization.cpp to extract segments - ReadWavPcm16Mono is static in diarization.cpp — inline WAV read in vllm_c.cpp - Fix MakeError forward declaration to match the existing definition signature - Mark sample_rate params as (void) in the !VLLM_WITH_DIARIZATION stubs - handle_audio_diarizations/sas as ApiServer member methods, not free functions - All symbols verified present in libvllm.a (diarization ON) and absent as parakeet_capi references (diarization OFF — stubs only)
…loading num_attention_heads was hardcoded to 12 (mdeberta-v3-base), which is wrong for GLiNER2.5-Decide (deberta-v3-large, 1024/16). Derive it from hidden_size / 64 instead. The GLiNER2.5-Decide checkpoint has no boundary_head tensors. Make boundary head loading conditional on the checkpoint containing boundary_head.boundary_encoder.left_projection.weight.
64f2c43 to
4b252af
Compare
Dismissed: concerns are addressed in follow-up commits. gliner2 fix is committed. parakeet.cpp branch pin is tracked as a follow-up.
Summary
Adds speaker diarization and speaker-attributed ASR (SAS) to vllm.cpp by linking parakeet.cpp as a FetchContent dependency. The diarization stack (Nemotron-3-Diarization Sortformer encoder, speaker head, AOSC streaming, and SAS merge layer) lives in parakeet.cpp; vllm.cpp wraps it through a clean C++ seam.
What's new
C++ seam (
include/vllm/multimodal/diarization.h)Diarizerclass: loads a diarization GGUF, exposesDiarize()andDiarizeWavFile()returning speaker segmentsSpeakerAttributedASRstruct +TranscribeAndDiarize()helpers: run both ASR and diarization on the same audio and merge resultsC ABI (
include/vllm.h, ABI v30)vllm_diarization_load: load a diarization GGUF as a separate engine handlevllm_diarize_path/vllm_diarize_pcm: diarize a WAV file or raw PCMvllm_transcribe_and_diarize/_pcm: combined ASR + diarization (speaker-attributed utterances)vllm_diarization_free/vllm_sas_result_free: cleanupServer endpoints (registered only when a diarizer/SAS is attached)
POST /v1/audio/diarizations: returns speaker segments as JSONPOST /v1/audio/sas: returns speaker-attributed utterances as JSONCMake
parakeet.cppis fetched from GitHub (or pointed at a local tree viaVLLM_CPP_PARAKEET_CPP_DIR)VLLM_CPP_WITH_DIARIZATION(ON by default). When disabled, every diarization function returns an error and the endpoints are not registered — the library is byte-identical to before.Dependencies
Parakeet.cpp PR
The parakeet.cpp diarization implementation is in PR #71 (Phases 1–3.4: offline diarization, streaming diarization, SAS merge, streaming SAS).
Test plan
VLLM_CPP_WITH_DIARIZATION=ON— verify FetchContent populates parakeet.cpp and the library linksVLLM_CPP_WITH_DIARIZATION=OFF— verify the library is byte-identical tomainvllm_diarization_load— verify segments are returnedvllm_transcribe_and_diarizewith a Parakeet ASR checkpoint + diarization GGUF — verify speaker-attributed utterancesPOST /v1/audio/diarizations— verify JSON response with speaker segmentsPOST /v1/audio/sas— verify JSON response with speaker-attributed utterances