Skip to content

Feature request: Support multilingual Nemotron-3.5 streaming ASR (prompt_index input) #3664

Description

@paoloantinori

Summary

Add support for the multilingual variant of Nemotron streaming ASR (nvidia/nemotron-3.5-asr-streaming-0.6b), which supports 40 language-locales with auto-detection. The English-only Nemotron is already supported (PR #3044). The multilingual variant adds a single extra encoder input tensor: prompt_index.

Background

The multilingual Nemotron model is the same architecture as the English one, with one difference: the encoder accepts a 6th input prompt_index (int64, shape [batch]) for language conditioning. When prompt_index=101, the model auto-detects the language. Specific language codes (e.g., Italian) can also be passed for better accuracy.

The ONNX files are already pre-exported and available:

  • Model: pantinor/nemotron-3.5-asr-streaming-0.6b-onnx on HuggingFace
  • Source: altunenes/parakeet-rs (Rust project that already supports this model)

What needs to change

The changes are minimal — auto-detect the multilingual variant from the encoder ONNX and pass prompt_index:

1. sherpa-onnx/csrc/online-transducer-nemo-model.cc

  • Add bool is_multilingual_ flag, auto-detected by checking if encoder has a 6th input named prompt_index
  • Add int64_t prompt_index_ member (default: 101 = auto)
  • In RunEncoder(), when is_multilingual_ is true, add 6th tensor to the inputs array:
    if (is_multilingual_) {
      Ort::Value prompt_index_tensor = Ort::Value::CreateTensor<int64_t>(
          allocator_, &prompt_index_, 1);
      // inputs becomes 6 elements instead of 5
    }

2. sherpa-onnx/csrc/online-transducer-nemo-model.h

  • Add SetPromptIndex(int64_t index) method
  • Expose is_multilingual() getter

3. Java API (OnlineTransducerModelConfig.java or OnlineModelConfig.java)

  • Add optional language field (string like "it-IT", "auto")
  • Map language codes to prompt indices using the model's prompt_dictionary

Key differences from English Nemotron

Property English Multilingual
Encoder inputs 5 6 (extra prompt_index)
cache_last_channel dim2 70 56
Vocab size ~1024 13088
Tokenizer tokens.txt tokenizer.model (SentencePiece)
Languages English only 40 language-locales

Reference implementation

The parakeet-rs Rust project already supports this model: https://github.com/altunenes/parakeet-rs

Their implementation wraps the encoder with a EncoderWithPromptWrapper that:

  1. Detects multilingual from the prompt_index input
  2. Creates a one-hot language vector (128-dim)
  3. Concatenates it to encoder output and runs through prompt_kernel MLP

In sherpa-onnx, the prompt_index fusion is already baked into the exported ONNX encoder, so the runtime only needs to pass the tensor — no MLP logic needed.

Verified ONNX encoder inputs

Inputs:
  processed_signal:           [batch, 128, time]
  processed_signal_length:    [batch]
  cache_last_channel:         [24, 1, 56, 1024]
  cache_last_time:            [24, 1, 1024, 8]
  cache_last_channel_len:     [1]
  prompt_index:               [batch]           ← THIS IS THE ONLY ADDITION
Outputs:
  encoded:                    [batch, 1024, time]
  encoded_len:                [batch]
  cache_last_channel_next:    [24, 1, S, 1024]
  cache_last_time_next:       [24, 1, 1024, C]
  cache_last_channel_len_next: [1]

Use case

We are integrating multilingual streaming ASR into an Android on-device transcription app (Anti-Vocale). The Italian language support is critical for our users. We currently use the offline Parakeet TDT model via sherpa-onnx and would love to add real-time streaming with the multilingual Nemotron model.

We are happy to contribute a PR if this feature request is accepted.

Thank you for the excellent library! 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions