Instructions to use nvidia/Nemotron-Labs-Audex-2B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use nvidia/Nemotron-Labs-Audex-2B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="nvidia/Nemotron-Labs-Audex-2B")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("nvidia/Nemotron-Labs-Audex-2B", dtype="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use nvidia/Nemotron-Labs-Audex-2B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "nvidia/Nemotron-Labs-Audex-2B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Labs-Audex-2B", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/nvidia/Nemotron-Labs-Audex-2B
- SGLang
How to use nvidia/Nemotron-Labs-Audex-2B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "nvidia/Nemotron-Labs-Audex-2B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Labs-Audex-2B", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "nvidia/Nemotron-Labs-Audex-2B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Labs-Audex-2B", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use nvidia/Nemotron-Labs-Audex-2B with Docker Model Runner:
docker model run hf.co/nvidia/Nemotron-Labs-Audex-2B
Audex-2B audio understanding in vLLM 0.20 (Nemotron Nano Omni-style)
Production-style integration: audio -> text through vLLM's own multimodal
pipeline. A registered model wraps the vLLM-native NemotronDense (2B dense) LLM
and adds the NV-Whisper audio encoder + Audex projector; vLLM owns placeholder
merging and serving (offline LLM.generate and the OpenAI audio_url server).
This is the 2B-dense counterpart to Audex-30B-A3B/.../audioqa_scripts. The only
differences from the 30B package: the backbone is the plain attention
NemotronDenseForCausalLM (no Mamba/hybrid cache) and the LLM hidden size is
2048 (the Audex projector output matches config.hidden_size). Audio
preprocessing, 30s chunking, <so_embedding> expansion, caps, and the vLLM
processor logic are identical.
Architecture name (from checkpoint_folder_full/config.json):
NemotronDenseAudexForConditionalGeneration (model_type=nemotron_dense_audex).
Layout
inference_scripts_vllm/audioqa_scripts/
README.md
pyproject.toml # installs the model as a vLLM plugin
run_audioqa_vllm.py # offline LLM.generate runner
serve_audioqa_vllm.sh # OpenAI-compatible server
client_audioqa.py # OpenAI audio_url client (one request)
audex_2b_vllm/ # import package (distinct from 30B audex_30b_a3b_vllm)
modeling_audex_vllm.py # NemotronDenseAudex model (SupportsMultiModal + SupportsPP)
processing_audex_vllm.py # processor: 30s chunking, <so_embedding> expansion, caps
audio_features.py # waveform -> NV-Whisper features
audio_encoder.py # Audex projector + Qwen2AudioEncoder factory
plugin.py / register.py # registration in every TP worker
The import package is audex_2b_vllm (the 30B package is audex_30b_a3b_vllm), so
both audioqa plugins can be co-installed without one shadowing the other.
Install (once)
The model must be registered in every tensor-parallel worker, which vLLM does via
the vllm.general_plugins entry points. Install the dense backbone plugin and
this folder as editable plugins:
pip install -e ../../nemotron_dense_vllm_plugin --no-deps --no-build-isolation
pip install -e . --no-deps --no-build-isolation
Run offline
python run_audioqa_vllm.py \
--model-path "$(cd ../.. && pwd)/checkpoint_folder_full" \
--input-json ./inputs.json \
--output-jsonl ./audioqa_outputs/results.jsonl \
--tensor-parallel-size 1
inputs.json: [{"id", "sound": "/abs/path.wav", "conversations":[{"from":"human","value":"<sound>\nDescribe this audio."}]}].
Serve + query (OpenAI audio_url)
# Safe defaults: HOST=127.0.0.1, local audio restricted to the Audex-2B release root.
bash serve_audioqa_vllm.sh "$(cd ../.. && pwd)/checkpoint_folder_full" 8000
python client_audioqa.py --audio /path/to/audio.wav --prompt "Describe this audio."
To expose externally or widen file access (advanced):
HOST=0.0.0.0 ALLOWED_MEDIA_PATH=/data bash serve_audioqa_vllm.sh ... 8000
# ALLOWED_MEDIA_PATH= (empty) disables local-file audio entirely.
Benchmark recipes
Both run_audioqa_vllm.py and client_audioqa.py take --recipe, which sets
reproduction-safe sampling. No audio benchmark uses thinking mode; default is
audio-understanding (non-thinking).
| recipe | thinking | temperature | top_p | top_k |
|---|---|---|---|---|
audio-understanding (default) |
off | 0.7 | 0.9 | 0 |
speech-recognition-translation |
off | 0.0 | 1.0 | 0 |
custom |
on | 0.7 | 0.9 | 0 |
top_k=0means "disabled" in vLLM (consider all tokens).- Audio understanding is non-thinking:
audio-understanding(temperature=0.7, top_p=0.9, top_k=0) covers audio understanding/reasoning. - Greedy translation:
speech-recognition-translationis true greedy for ASR/AST —temperature=0.0triggers vLLM's greedy path (it normalizestop_p=1.0, top_k=0). - Precedence: recipe defaults < explicit CLI override (
--reasoning/--no-reasoning,--temperature,--top-p,--top-k).customis the manual escape hatch (thinking on by default; override as needed).
Key facts / gotchas
- Backbone: 2B dense (
NemotronDenseForCausalLM) — plain RMSNorm / relu^2 / GQA, no Mamba; the wrapper isSupportsMultiModal + SupportsPP(not hybrid). - Hidden size: 2048. The Audex projector's
fc2maps the 1280-d encoder features toconfig.hidden_size(2048), not 2688. - Long audio: non-overlapping 30s windows, padded tail,
N = num_clips*750placeholders. Caps (fail loud):MAX_AUDIO_SECONDS=900,MAX_AUDIO_CLIPS=30,MAX_AUDIO_TOKENS=22500(inprocessing_audex_vllm.py). The offline runner and serve script default to--max-model-len 32768so the full 22500-embedding cap fits in the context window. - Placeholder contract:
<so_embedding>-><so_start>+ N*<so_embedding><so_end>; a placeholder/token count mismatch fails loud.
- No audio-token leakage (offline and served): generation is masked to text
ids —
allowed_token_ids = range(131072)minus the sound placeholder ids (<so_embedding>/<so_start>/<so_end>= 29/30/31). The offline runner passes this toSamplingParams; the client passes it viaextra_body. All audio codec/gen tokens are id >= 131072. Both paths also scan the output text for<audiocodec_/<speechcodec_/<audiogen_/<speechgen_/<so_*>leakage. - Self-contained preflight: the offline runner and serve script fail early
with a clear message if
model.safetensors.index.jsonreferences shards that are missing/unresolvable. - Reasoning / prompt format: the
audio-understandingrecipe is non-thinking; the offline runner and client default to it. These scripts use the Audex audio-understanding evaluation prompt format — the non-thinking generation prompt uses the<think></think>assistant prefix, consistently offline (run_audioqa_vllm.py) and served (checkpoint_folder_full/chat_template.jinja,enable_thinking=False). Use--recipe customfor a thinking-capable manual setup.
Integration notes (why the model code looks the way it does)
- Out-of-tree registration must reach TP workers -> done via the plugin entry points (registering only in the main process raises "unsupported arch" in workers).
- vLLM streams all
.safetensorsin the model dir;load_weightssplits the stream:model.*/lm_head.*-> dense language model (its AutoWeightsLoader fuses q/k/v into qkv_proj),audio_encoder.*/audio_projector.*-> audio. - The dense backbone is registered by the separate
nemotron-dense-vllmplugin;register_audexalso registers it defensively so the wrappedlanguage_modelarch always resolves.