Repository navigation
[Model] Add NVIDIA Nemotron-3-Diarization (offline speaker diarization) - #65002
Closed
Alex-Wengg wants to merge 2 commits into
Closed
Alex-Wengg wants to merge 2 commits into
Alex-Wengg wants to merge 2 commits into
Conversation
Add Nemotron3DiarizationForAudioFrameClassification, a tokenizer-free, raw-input-only pooling model that diarizes one whole recording per request through the "plugin" task, following the Terratorch pattern and wrapping the Transformers module. Each output is the [num_frames, 8] speaker logits at the 10 ms spectrogram frame rate. - Pad the step's logits to one tensor and trim them back per recording in the pooler, since the V1 runner pools a tensor. - Recompute the RoPE frequencies on the CPU, matching Transformers. - Declare a one-token vocabulary so the placeholder prompt [0] passes prompt validation without a tokenizer. - Force eager mode: the forward syncs with the host at every chunk. - Fall back to the V1 model runner for raw-input-only models, which Model Runner V2 does not support. Signed-off-by: Alex-Wengg <hanweng9@gmail.com>
Contributor
|
Documentation preview: https://vllm--65002.org.readthedocs.build/en/65002/ |
- Reject prompts without multi_modal_data for raw-input-only models in the input processor. Such a prompt skips the multimodal processor, so alone it returned empty logits and batched with real audio it crashed the engine. - Add is_multimodal_raw_input_only_model to the fake model config in test_routed_experts_capture.py, which the Model Runner V2 check reads. - Recompute the RoPE frequencies only for the default rope type, and reset the pooler's frame counts when a step has no audio. - Document the GPU memory taken by queued recordings. Signed-off-by: Alex-Wengg <hanweng9@gmail.com>
Alex-Wengg
marked this pull request as ready for review
November 1, 2026 16:40
Alex-Wengg
requested review from
AndreasKaratzas,
DarkLight1337,
ProExpertProg,
WoosukKwon,
houseroad,
mgoin,
njhill,
noooop,
robertgshaw2-redhat,
tlrmchlsmth,
tomeras91,
yewentao256,
youkaichao and
ywang96
as code owners
November 1, 2026 16:40
Member
|
This is quite a small model. I wonder how much performance improvement does vLLM actually provide here over other baselines? |
Contributor
Author
|
@DarkLight1337 good point, honestly not much. should I move it to an out-of-tree plugin, like vllm-parakeet-plugin (#65005) or just close this PR . support nemotron 3 on vllm in a form for devs that want easier time customizing different models easily |
Member
|
If you are ok with maintaining it and feel that it's valuable then you could do plugin. Either way let's close this PR. |
6 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Adds
Nemotron3DiarizationForAudioFrameClassificationfornvidia/Nemotron-3-Diarization, a 99M-parameter streaming Sortformer speaker diarizer. For every 10 ms frame of a recording it returns the logits of up to 8 speakers. vLLM serves it offline: one whole recording per request, through thepluginpooling task. The model is tokenizer-free and raw-input-only, like Terratorch, and wraps the Transformers module as is (Transformers ≥ 5.18).No existing issue or PR:
gh pr list/gh issue listsearches forNemotron-3-Diarization,Nemotron3Diarization,diarizationandsortformerreturn only unrelated ASR/realtime items.Claims
LLM.encode(..., pooling_task="plugin")returns[num_frames, 8]logits per recording. With fp32 these are bit-identical to TransformersNemotron3DiarizationForAudioFrameClassificationgiven the same features, including recordings long enough to run the speaker cache over 6 chunks.encodecall give the same output as single requests.VLLMValidationErrorinstead of returning empty logits or crashing the engine.Validation
NVIDIA RTX A6000, Transformers 5.22.0 (the CI pin), torch 2.14.0, fp32. Clips: the pyannote 2-speaker
sample.wav(30 s), its first 17.3 s, and five copies back to back (150 s, 6 offline chunks).extract_speaker_dictsegments[150 s, 17.3 s, 30 s, 17.3 s]in one call: every output equals its single-request result exactly (the batch runs in ~0.9 s).dtype="auto"resolves to float16 for this fp32 checkpoint. fp16 and bf16 keep 99.98–100% frame agreement and the same onsets, but move a few segment boundaries, so the docs recommenddtype="float32".examples/pooling/plugin/nemotron3_diarization_offline.py --audio sample.wavprints 11 segments against the RTTM's 10. Boundaries are within 0.05 s of the RTTM except for speaker 1 at two points: at 14.10 s an extra 0.06 s segment plus an onset 0.20 s early (14.29 s vs 14.49 s), and at 18.07 s an onset 0.08 s early.Exact parity holds when both sides use identical features. vLLM's frontend computes features with one torch thread, and this feature extractor's CPU output varies by ~1e-6 between 1 and 6 threads. Against a default-threads Transformers run the max |Δlogit| is 2.5e-3, with identical segments. The reference above therefore uses
torch.set_num_threads(1).Reproduce
Tests
*
test_rope_customization,test_is_encoder_decoder[meta-llama/Llama-3.2-1B-Instruct-False]andtest_eagle_draft_model_configfail with "You are trying to access a gated repo": they need gatedmeta-llamacheckpoints, and the box has no HF token. The newtest_v2_model_runner_raw_input_only_model_falls_back_to_v1passes. No model-specific correctness test is added; the registry entry covers loading.Details
terratorch.py. The processor overridesapply()to run the checkpoint'sNemotronAsrStreamingFeatureExtractor, asNemotron3DiarizationProcessordoes offline. It returns the placeholder prompt[0]with a zero-length audio placeholder. The model loops over the step's recordings and runs the Transformers offline forward on each, undergpu_sync_allowed(). That forward chunks the recording and updates the speaker cache, which reads back to the host._poolneeds a tensor (it readshidden_states.device), so the step's logits are padded to[num_reqs, max_frames, 8]. A smallIdentityPoolersubclass trims each one back to its own frame count.inv_freqcomes out ~4e-9 different. That alone shifts the logits by up to 2.4e-3 on the 150 s clip, as the speaker cache carries small differences from one chunk to the next.skip_tokenizer_init, and this config has novocab_size.verify_and_update_model_confighook setsenforce_eager=True. The per-chunk host syncs break CUDA graph capture (device-side assert).pluginpooling task. So_get_v2_model_runner_unsupported_features()now lists raw-input-only models, and they fall back to V1 with the usual warning instead of failing at load. Terratorch, the other raw-input-only model, no longer needsVLLM_USE_V2_MODEL_RUNNER=0either, though it is separately affected by [Bugfix][Core] Validate prompt token ids when skip_tokenizer_init is set #62911. Supporting these models on MRV2 is a separate change.multi_modal_dataskips the multimodal processor, soInputProcessornow rejects it for raw-input-only models. Before, such a prompt returned empty logits on its own, and batched with real audio it crashed the engine (pooler output length mismatch). The new test intest_prompt_validation.pycovers it.max_num_seqsrecordings with all their features on the GPU (about 200 MB per hour of audio in fp32). The docs suggest loweringmax_num_seqsfor long recordings.plugin-task model. The test entry usesrequire_embed_inputs=Trueto skip tokenizer init, as Terratorch does./poolingcannot carry audio for a tokenizer-free model without an IO processor plugin); streaming sessions that keep the speaker cache across requests; MRV2 support.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
🤖 Generated with Claude Code