Voxtral Mini 4B Realtime

repository·main·Indexed 21 days ago

https://github.com/trevors/voxtral-mini-realtime-rs

A pure Rust implementation of Mistral's Voxtral Mini 4B Realtime (ASR) and Voxtral 4B TTS models using the Burn ML framework. It supports high-performance inference via WebGPU/WGPU natively and in the browser via WASM. The project includes a CLI for streaming speech recognition and text-to-speech synthesis, supporting both BF16 and Q4 GGUF quantized models.

Tokens
42.3K
Snippets
142
Records
193
Agent score
72%

What's inside voxtral-mini-realtime

  1. Project structure overview

    main

    The repository is organized as follows:

    • src/lib.rs: The public API entry point providing VoxtralRealtime<B>.
    • src/models/: Contains the core model components (encoder.rs, decoder.rs, adapter.rs, voxtral.rs) and the VoxtralModelLoader.
    • src/audio/: Handles audio processing, including MelSpectrogram extraction, resampling, and chunking.
    • src/tokenizer/: A wrapper around the Tekken tokenizer.
    • scripts/: Python utilities for weight inspection, reference generation, and validation.
    • web/: Contains the browser demo, including worker.js for off-main-thread inference and voxtral-client.js for the high-level API.
  2. Module declaration convention for TTS

    main

    To prevent merge conflicts during concurrent development, the src/tts/mod.rs file acts as the central module root. It declares all submodules upfront. When adding new functionality, ensure the corresponding module is declared in this file:

    pub mod config;
    pub mod backbone;
    pub mod voice;
    pub mod embeddings;      // flow-matching
    pub mod sequence;        // flow-matching
    pub mod flow_matching;   // flow-matching
    pub mod codec;           // integration
    pub mod pipeline;        // integration
  3. Implement streaming inference with the correct prefix length

    main

    When performing autoregressive streaming inference, you must use a prefix length of 38 instead of the standard 39. Using 39 tokens causes an anomaly at position 38 that results in the model outputting only padding tokens.

    Correct Prefix Pattern:

    • Use [1] (BOS) followed by 37 [STREAMING_PAD] (token 32) tokens.
    • Total prefix length = 38.

    Token Reference:

    • [STREAMING_PAD] (token 32): Marks pauses.
    • [STREAMING_WORD] (token 33): Starts words.
    • Important: Text token IDs are offset by 1000 from vocab indices (e.g., Token ID 1000+ maps to vocab index token_id - 1000).
    # Correct prefix for autoregressive generation
    prefix_tokens = [1] + [32] * 37  # BOS + 37 STREAMING_PAD = 38 tokens
  4. Inference with the Flow-Matching Transformer

    main

    The Flow-Matching Transformer predicts acoustic tokens using an Euler ODE solver. During inference, the model performs 8 steps (dt = 1/8) to transition from noise to the target state.

    Inference Steps:

    1. Sample x_1 ~ N(0, 1) in $\mathbb{R}^{36}$.
    2. For each step t in [1.0, 0.875, 0.75, ..., 0.125]:
      • Calculate conditional velocity: v_cond = FM(x_t, t, h)
      • Calculate unconditional velocity: v_uncond = FM(x_t, t, zeros)
      • Apply Classifier-Free Guidance (CFG) with $\alpha=1.2$: v = 1.2 * v_cond + (1 - 1.2) * v_uncond
      • Update state: x_{t-dt} = x_t - v * dt
    3. Quantize the final x_0 to 21 FSQ levels per dimension.

    Transformer Inputs per frame:

    • Position 0: Backbone hidden state h (projected via llm_projection [3072, 3072])
    • Position 1: Sinusoidal time step t (projected via time_projection [3072, 3072])
    • Position 2: Current acoustic state x_t (36-dim, projected via input_projection [3072, 36])
  5. Implement Causal and Sliding Window Attention for Streaming

    main

    To enable streaming in the audio encoder, you must use causal attention instead of bidirectional attention. For optimized streaming, combine causal attention with a sliding window constraint to limit the attention span.

    Causal Mask: Ensures position i can only attend to positions 0..=i. Sliding Causal Mask: Ensures position i can only attend to positions within a specific window size behind it.

    fn create_causal_mask(seq_len: usize, device: &Device) -> Tensor {
        let mut mask = vec![f32::NEG_INFINITY; seq_len * seq_len];
        for i in 0..seq_len {
            for j in 0..=i {
                mask[i * seq_len + j] = 0.0;
            }
        }
        Tensor::from_vec(mask, (seq_len, seq_len), device)
    }
    
    fn create_sliding_causal_mask(seq_len: usize, window: usize, device: &Device) -> Tensor {
        let mut mask = vec![f32::NEG_INFINITY; seq_len * seq_len];
        for i in 0..seq_len {
            let start = i.saturating_sub(window);
            for j in start..=i {
                mask[i * seq_len + j] = 0.0;
            }
        }
        Tensor::from_vec(mask, (seq_len, seq_len), device)
    }
  6. Language Model Architecture and GQA

    main

    The language model is a decoder-only transformer based on Ministral-3B that processes audio embeddings.

    Technical Specifications

    • Hidden Dimension: 3,072
    • Layers: 26
    • Vocabulary Size: 131,072 (Tekken tokenizer)
    • Sliding Window: 8,192 tokens
    • Embeddings: Tied (embed_tokens = lm_head.T)

    Grouped Query Attention (GQA)

    To reduce KV cache memory, the model uses a 4:1 GQA ratio:

    • 32 Query heads (4096 dimension)
    • 8 KV heads (1024 dimension)
    • Each KV head is shared by 4 query heads, resulting in a 4x reduction in KV cache memory compared to standard Multi-Head Attention (MHA).
  7. Understand the Voxtral Mini 4B Realtime Model Architecture

    main

    Voxtral Mini 4B Realtime is a pure Rust implementation of a streaming ASR (Automatic Speech Recognition) model built using the Burn ML framework. The model consists of three primary components:

    1. Audio Encoder: A 32-layer stack using causal self-attention, RMSNorm, and SwiGLU MLPs. It processes audio with a window of 750 and uses a 4x downsampler.
    2. Language Model: A 26-layer stack using Grouped Query Attention (GQA) with a 4:1 ratio (32Q/8KV heads), ADA RMSNorm, and a sliding window of 8192 tokens.
    3. Adapter: A 2-layer component that bridges the Audio Encoder and Language Model using GELU activation.

    Key Timing Metric: 1 text token corresponds to approximately 80ms of audio (1280 samples @ 16kHz).

  8. Use Finite Scalar Quantization (FSQ) for acoustic tokens

    main

    Finite Scalar Quantization (FSQ) is used to map continuous 36-dimensional vectors to discrete levels. This is applied after the Euler ODE solver to prepare data for the codec decoder.

    Quantization Logic:

    • Maps each of the 36 dimensions to the nearest of 21 uniformly-spaced levels in the range [-1, 1].
    • Quantize: idx = argmin(|x - levels|) per dimension, producing 36 integer indices in the range [0..20].
    • Dequantize: x = levels[idx] (used for codec decoder input).

    This process is purely arithmetic and uses no learned parameters.

  9. Audio Encoder Architecture and Input Processing

    main

    The audio encoder is a causal transformer designed for streaming mel spectrograms.

    Input Specifications

    • Sample Rate: 16,000 Hz
    • Mel Bins: 128
    • Hop Length: 160 samples (10ms)
    • Window Size: 400 samples (25ms, Hann window)
    • Raw Frame Rate: 100 Hz

    Processing Pipeline

    1. Log Mel Normalization: Mel spectrograms are normalized using clamp(log(max(mel, 1e-10)) / 1.5, -1.0, 1.0).
    2. Convolutional Downsampling: Two 1D convolutional layers with stride 2 reduce the raw 100 Hz frame rate to 25 Hz (a 4x total downsample).
    3. Final Reshape: The 25 Hz output is reshaped (grouping 2 frames) to reach a final rate of 12.5 Hz (80ms per frame).

    Encoder Technical Details

    • Hidden Dimension: 1,280
    • Layers: 32
    • Attention: Multi-Head Attention (MHA) with 32 Query heads and 32 KV heads.
    • Sliding Window: 750 tokens (~60 seconds of audio).
    • FFN Type: SwiGLU (gate * silu(up)).
    • Normalization: RMS Norm with ADA (Adaptive) conditioning.
  10. Understand Audio Codebook Embedding Summation

    main

    The audio codebook embedding layer maps semantic and acoustic token indices to a single 3072-dim vector by summing all 37 embeddings (1 semantic + 36 acoustic).

    Index Layout:

    • Semantic Specials: Indices 0..1 (EMPTY_AUDIO=0, END_AUDIO=1).
    • Semantic VQ: Indices 2..8193 (8192 entries, offset by +2).
    • Acoustic Codebooks: 36 codebooks, each with 23 entries (2 specials + 21 FSQ levels). Indices 8194..9021.
    • Padding: Indices 9022..9087 (unused).

    Index Arithmetic:

    • semantic_global = raw_semantic_idx + 2
    • acoustic_global = 8194 + cb * 23 + (level + 2)