CoolFace
Modelpublic

younghan-meta/Voxtral-4B-TTS-2603-ExecuTorch-CUDA

sourceHugging Faceapache-2.0updated 5mo agoView on Hugging Face
1likes78downloads
Model Card

Voxtral-4B-TTS-2603-ExecuTorch-CUDA

Pre-exported ExecuTorch artifacts for Voxtral-4B-TTS-2603 with CUDA backend (NVIDIA GPU), bf16 precision, and 4-bit weight-only quantization (tile_packed_to_4d packing for _weight_int4pack_mm) on the LM decoder + flow head linears. The codec decoder is exported in fp32 via the same CUDA backend using a conv-as-matmul reformulation so it lowers onto Triton's batched-matmul kernels.

Overview

The pipeline has two stages: export (Python, once) and inference (C++ runner, repeated). This repo ships the export outputs so you can skip straight to inference.

The model has three components:

  1. 1.Mistral 4B LLM decoder — autoregressive text → hidden states
  2. 2.Flow Matching Head (3-layer transformer) — hidden states → 37 audio codebook tokens per frame via a 7-step Euler ODE
  3. 3.Codec Decoder (Conv1d / ConvTranspose1d stack + 8 transformer layers) — codebook tokens → 24 kHz waveform

Pick the right folder for your GPU

ExecuTorch's CUDA backend uses AOTInductor, which *bakes pre-compiled cubins for the export-time GPU's compute capability into `.ptd**. The cubins are not forward/backward compatible across architectures — running an sm_80 blob on a Blackwell card fails with CUDA driver error: invalid argument` on the first kernel launch.

This repo ships per-arch artifacts in subfolders:

FolderCompute capabilityExample GPUsExported on
`sm80/`sm_80 (Ampere)A100, A30A100 80 GB, CUDA 12.8
`sm120/`sm_120 (Blackwell)RTX 5080, RTX 5090RTX 5080 16 GB, CUDA 12.9

Find your GPU's compute capability with:

bash
nvidia-smi --query-gpu=name,compute_cap --format=csv

If your arch isn't listed, re-export on your GPU.

Performance

End-to-end on seed=42, after the per-process Triton autotune cache is warm (first call is ~30–50 s slower; the runner's warmup() amortizes it).

GPUFolderPromptAudioWallRTF
A100 80 GBsm80/7 tok ("Hello, how are you today?")2.56 s3.7 s0.88x
RTX 5080 16 GBsm120/7 tok ("Hello, how are you today?")2.48 s3.5 s1.29x
RTX 5080 16 GBsm120/ (--streaming)24 tok10.32 s5.6 s0.55x
RTX 5080 16 GBsm120/ (--streaming, warm)24 tok10.32 s3.85 s0.37x

Numerical parity vs the XNNPACK FP32 baseline (measured on the A100 export):

  • —Last-position prefill hidden cosine: 0.999994
  • —First-frame semantic argmax + top-5: identical

Artifacts target Linux NVIDIA GPUs.

Prerequisites

  • —Linux with NVIDIA GPU + CUDA 12.8 or 12.9 toolkit (CUDA 13 not supported — ExecuTorch's backends/cuda/runtime/shims/sort.cu was written against CUB 2.x).
  • —Conda + Python 3.10–3.12.
  • —ExecuTorch built from source with the CUDA backend (see Build).
  • —Tokenizer + at least one voice embedding from the upstream Mistral repo (~33 MB total). They are not included in this repo.

Install + Build

bash
git clone https://github.com/pytorch/executorch/ ~/executorch
cd ~/executorch

unset CPATH                              # avoids CUDA-13 host header pollution
./install_executorch.sh
pip install -e . --no-build-isolation    # editable so source edits take effect

# Build runner with CUDA enabled
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH
make voxtral_tts-cuda

Binary lands at cmake-out/examples/models/voxtral_tts/voxtral_tts_runner.

WSL2 only: the linker also needs libcuda.so from the driver dir:

bash
export LIBRARY_PATH=/usr/lib/wsl/lib:/usr/local/cuda/lib64/stubs:$LIBRARY_PATH
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:/usr/lib/wsl/lib:$LD_LIBRARY_PATH

Download

bash
pip install huggingface_hub

# 1. Pre-exported ExecuTorch artifacts for your GPU arch (~3.7 GB).
#    Replace `sm80` with `sm120` for Blackwell (RTX 5080/5090).
hf download younghan-meta/Voxtral-4B-TTS-2603-ExecuTorch-CUDA \
    --include 'sm80/*' \
    --local-dir voxtral_tts_cuda

# 2. Tokenizer + voice embeddings from the base model (~33 MB)
hf download mistralai/Voxtral-4B-TTS-2603 \
    tekken.json voice_embedding/* \
    --local-dir voxtral_tts_base

Run

bash
unset CPATH
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH

# Pick your arch
ARCH=sm80                                # or sm120

cmake-out/examples/models/voxtral_tts/voxtral_tts_runner \
    --model voxtral_tts_cuda/$ARCH/model.pte \
    --data_path voxtral_tts_cuda/$ARCH/aoti_cuda_blob.ptd \
    --codec voxtral_tts_cuda/$ARCH/codec_decoder.pte \
    --codec_data_path voxtral_tts_cuda/$ARCH/codec_aoti_cuda_blob.ptd \
    --tokenizer voxtral_tts_base/tekken.json \
    --voice voxtral_tts_base/voice_embedding/neutral_female.pt \
    --text "Hello, how are you today?" \
    --output output.wav \
    --seed 42 \
    --max_new_tokens 200

Output is 24 kHz mono 16-bit PCM. Listen with ffplay output.wav or aplay output.wav.

Streaming mode

Add --streaming to emit codec output in chunks instead of one batch at the end. The first chunk is always 9 600 samples (0.4 s) for low time-to-first- audio; subsequent chunks are 48 000 samples (2 s) until END_AUDIO. Pair with --speaker to pipe raw f32le PCM to stdout for live playback:

bash
cmake-out/examples/models/voxtral_tts/voxtral_tts_runner \
    --model voxtral_tts_cuda/$ARCH/model.pte \
    --data_path voxtral_tts_cuda/$ARCH/aoti_cuda_blob.ptd \
    --codec voxtral_tts_cuda/$ARCH/codec_decoder.pte \
    --codec_data_path voxtral_tts_cuda/$ARCH/codec_aoti_cuda_blob.ptd \
    --tokenizer voxtral_tts_base/tekken.json \
    --voice voxtral_tts_base/voice_embedding/neutral_female.pt \
    --text "The quick brown fox jumps over the lazy dog." \
    --seed 42 \
    --streaming \
    --speaker \
  | ffplay -f f32le -ar 24000 -ac 1 -nodisp -autoexit -

For aplay instead: ... | aplay -f FLOAT_LE -r 24000 -c 1.

On RTX 5080, time-to-first-audio is ~2.6 s on a warm cache (most of which is the LM prefill); subsequent chunks arrive every ~0.5 s, comfortably ahead of playback.

Available voices

neutral_female, neutral_male, casual_female, casual_male, cheerful_female, ar_male, de_female, de_male, es_female, es_male, fr_female, fr_male, hi_female, hi_male, it_female, it_male, nl_female, nl_male, pt_female, pt_male — under `voice_embedding/` in the base-model repo.

Runner options

FlagDefaultDescription
--model(required)Path to exported model.pte (LM + flow head)
--data_path(none)Path to LM .ptd (required for CUDA)
--codeccodec_decoder.ptePath to exported codec .pte
--codec_data_path(none)Path to codec .ptd (required for CUDA)
--tokenizertekken.jsonPath to tokenizer JSON
--voice(required)Path to voice embedding .pt
--text(required)Prompt text
--outputoutput.wavOutput WAV path (ignored if --speaker)
--seed42RNG seed (semantic sampling + flow noise)
--temperature0.0Sampling temperature (0 = greedy)
--max_new_tokens2048Max audio frames (~12.5 frames/s)
--streamingoffChunked codec emission
--speakeroffPipe raw f32le PCM to stdout instead of writing WAV

Re-exporting for another GPU

If your GPU's compute capability isn't shipped above, run the export on the target GPU (the AOTI compile step writes cubins for the local arch):

bash
unset CPATH
export LIBRARY_PATH=/usr/lib/wsl/lib:/usr/local/cuda/lib64/stubs:$LIBRARY_PATH  # WSL only
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:/usr/lib/wsl/lib:$LD_LIBRARY_PATH

python examples/models/voxtral_tts/export_voxtral_tts.py \
    --model-path ~/models/Voxtral-4B-TTS-2603 \
    --backend cuda \
    --qlinear 4w \
    --output-dir ./voxtral_tts_exports_cuda_4w

--dtype is auto-promoted to bf16 and --qlinear-packing-format is auto-set to tile_packed_to_4d when --backend cuda --qlinear 4w is selected.

Export needs ~10 GB GPU VRAM and the full base-model checkpoint (consolidated.safetensors, ~8 GB). On RTX 5080 16 GB it takes ~6 minutes. Triton autotuning will reject some configs that exceed Blackwell's 99 KB shared-memory limit — those OutOfResources warnings are expected.

File manifest (per arch folder)

FileSizeWhat
model.pte~3.4 MBLM + flow head, 5 methods (textdecoder, tokenembedding, audiotokenembedding, semantichead, predictvelocity), bf16 + 4w quant
aoti_cuda_blob.ptd~3.4 GBLM AOTI .so + int4-packed weights blob
codec_decoder.pte~5 MBCodec forward method (256-frame static input)
codec_aoti_cuda_blob.ptd~290 MBCodec AOTI .so + fp32 weights blob

tekken.json and voice_embedding/*.pt are not in this repo — download them from `mistralai/Voxtral-4B-TTS-2603` so they always match the upstream release that this export was produced from.

Troubleshooting

  • —`CUDA driver error: invalid argument` on first kernel launch. The AOTI cubins don't match your GPU's compute capability. Pick the right subfolder for your GPU, or re-export.
  • —`__cudaLaunch was not declared` during build. CPATH is polluted with CUDA 13's include path. unset CPATH and rebuild.
  • —`GLIBCXX_3.4.30 not found` at runner startup. AOTI .so files require a newer libstdc++ than /lib64/libstdc++.so.6. Set LD_LIBRARY_PATH=$CONDA_PREFIX/lib before launching.
  • —`cannot find -lcuda` during `pip install -e .` or export (WSL2). The CUDA toolkit doesn't ship libcuda.so; on WSL2 the driver lib lives at /usr/lib/wsl/lib/. Prepend it (or /usr/local/cuda/lib64/stubs) to LIBRARY_PATH.
  • —First call takes ~30–50 s. Triton autotunes the LM matmul kernels on first run, then caches per-process. The runner's warmup() absorbs this so the first user-visible synth pays the cost once.
  • —`pip install -e .` after pulling source changes. The default install_executorch.sh does pip install .. Repo edits won't take effect until you reinstall as editable.

Notes

More Info