- Implémentation en Rust permettant d’exécuter la reconnaissance vocale en streaming à la fois en environnement natif et dans le navigateur, en utilisant le framework ML Burn
- Le modèle est basé sur Voxtral Mini 4B Realtime de Mistral et effectue une inférence entièrement côté client dans un onglet de navigateur via WASM + WebGPU
- Le modèle quantifié Q4 GGUF (2,5 Go) peut être exécuté dans le navigateur, tandis que le modèle F32 basé sur SafeTensors (9 Go) fonctionne en environnement natif
- Pour contourner les contraintes du navigateur (allocation de 2 Go, espace d’adressage de 4 Go, restrictions de lecture GPU, etc.), des techniques comme le sharding, le chargement en deux étapes et le traitement asynchrone des tenseurs ont été appliquées
- Le projet est publié sous licence Apache-2.0 et une démo en temps réel est disponible sur HuggingFace Spaces
Aperçu de Voxtral Mini 4B Realtime (Rust)
- Implémentation complète du modèle Voxtral Mini 4B Realtime de Mistral en Rust avec le framework ML Burn
- La reconnaissance vocale en streaming peut être exécutée en local et dans le navigateur
- La version navigateur fonctionne côté client en s’appuyant sur WASM (WebAssembly) et WebGPU
- Le modèle quantifié Q4 GGUF (environ 2,5 Go) s’exécute dans le navigateur, tandis que le modèle F32 SafeTensors (environ 9 Go) est utilisé en environnement natif
- Une démo en temps réel est proposée sur HuggingFace Spaces
Architecture
- L’audio d’entrée (16 kHz mono) est converti en spectrogramme Mel, puis transformé en texte via un encodeur (32 couches) et un décodeur (26 couches)
- Principales étapes de traitement
- Spectrogramme Mel → encodeur (32 couches, 1280 dimensions) → sous-échantillonnage Conv 4x → adaptateur (3072 dimensions) → décodeur (GQA 32Q/8KV)
- Deux chemins d’inférence sont proposés
- F32 (natif) : basé sur SafeTensors, utilise les opérations sur tenseurs de Burn
- Q4 GGUF (natif + navigateur) : quantification GGUF Q4_0, utilise des shaders WGSL personnalisés
Solutions techniques pour l’exécution dans le navigateur
- Pour exécuter un modèle 4B dans le navigateur, 5 contraintes ont été résolues
- Limite d’allocation de 2 Go → lecture multi-buffer avec
ShardedCursor
- Limite de l’espace d’adressage de 4 Go → chargement en deux étapes (libération du lecteur après parsing, puis finalisation)
- Table d’embedding de 1,5 Gio → embeddings Q4 sur GPU + recherche de lignes sur CPU
- Lecture synchrone GPU interdite → utilisation de
into_data_async().await
- Limite de 256 workgroups → limitation de la taille des kernels via un patch cubecl-wgpu
Correction du padding Q4
- Par défaut, mistral-common padde l’audio avec 32 tokens de silence, mais cela ne couvre que la moitié des 38 préfixes du décodeur
- Le modèle quantifié Q4_0 provoquait donc des erreurs lorsque la parole commence immédiatement dans l’entrée
- Pour corriger cela, le padding a été étendu à 76 tokens (= 38 tokens du décodeur) afin de remplir l’ensemble du préfixe avec du silence
Build et tests
- Options de build
- Par défaut :
cargo build --release (wgpu + native-tokenizer)
- Pour le navigateur :
wasm-pack build --target web --features wasm
- Tests
- Prise en charge des tests unitaires et d’intégration basés sur GPU
- Les tests navigateur E2E sont exécutés avec Playwright + un véritable environnement GPU
- En CI, ces tests sont ignorés faute de GPU
Préparation du modèle et sharding
Licence et ressources
1 commentaires
Commentaires Hacker News
Si ça intéresse du monde, @antirez a publié une implémentation en C de Voxtral Mini 4B
On peut la voir sur antirez/voxtral.c
J’ai créé mon fork et j’y ajoute une implémentation CUDA ainsi que quelques améliorations
Ça fonctionne plutôt bien, mais ce n’est pas encore au niveau de la vitesse de l’endpoint API de Mistral AI
J’ai l’impression qu’il faut d’abord lire et apprendre avant de se mettre à coder directement, donc je serais preneur de guides ou de ressources utiles
Je ne connais pas bien les différences, mais la réaction de la communauté semble meilleure de ce côté-là
J’ai essayé la démo, et il faut appuyer sur le bouton Mic pour enregistrer puis sur “Stop and transcribe” pour obtenir un résultat
Je me demande s’il serait possible d’en faire un vrai mode temps réel, avec des sous-titres qui s’affichent dans les 1 à 2 secondes après que l’utilisateur a parlé
La démo serveur de Hugging Face le fait avec un modèle de 8.5GB basé sur GPU
En revanche, on peut obtenir quelque chose de similaire avec une UI basée sur un ring buffer
C’est comme ça que j’utilise Whisper dans Flutter, et je fais aussi tourner l’inférence GGUF de llama.cpp en Dart
Même sur un M4 Max, ce n’est pas du temps réel, et Whisper est presque en temps réel via ONNX sur les appareils sortis après 2022
Sur du matériel grand public, je pense que la vitesse d’inférence est plus importante que l’amélioration de la précision (WER)
C’est exactement ce type de modèles ouverts on-premise qu’il nous faut vraiment
Les utilisateurs comme les entreprises préfèrent cette forme. Mistral semble avoir bien compris le sujet
L’ère des modèles ouverts va devenir encore plus intéressante
Beau travail. Ce serait bien de l’intégrer à handy.computer, et je me demande aussi s’il est prévu de prendre en charge le streaming
La première version ne prendra probablement pas en charge le streaming
Ça m’a permis de découvrir un bon outil, et maintenant j’ai vraiment l’impression qu’il lui faut une prise en charge de Voxtral
Je ne connais pas très bien ce modèle, mais j’ai essayé Nvidia Parakeet et ça marche très bien
Je me demande si, pour ce genre de modèle de 9GB, il faut le garder chargé en permanence dans la mémoire GPU pour un usage en temps réel, ou si on peut le recharger à chaque fois
Les phrases courtes sont traitées presque instantanément, et les longues en 1 à 3 secondes
Une légère perte de précision n’a pas vraiment d’importance pour discuter avec une IA
J’utilise Parakeet V3 dans une application open source appelée Handy (lien), et l’implémentation en C était bien plus lente
En STT, la vitesse est au cœur de l’UX
La latence apparaît surtout quand on charge un nouveau modèle ou qu’on remplace un gros contexte
La plupart du temps, le modèle est déjà chargé, donc la variable principale, c’est le tokens per second
Dans les architectures complexes avec plusieurs agents, les changements de contexte ralentissent les choses
Le prompt caching d’ik_llama accélère ce type de scénario
En résumé, tant qu’on ne change pas souvent de modèle ou de contexte, la latence de chargement des poids n’est pas un gros problème
Je me demande si c’est vraiment efficace qu’un onglet de navigateur télécharge un modèle de 2.5GB pour ensuite le supprimer peu après
Même si la vitesse d’Internet et le stockage coûtent moins cher, ça reste du gaspillage à mes yeux
Le calcul côté client est intéressant, mais pour un modèle de cette taille, il vaudrait sans doute mieux l’exécuter côté serveur
Mais l’apparition d’un standard d’API web pour les LLM pourrait changer la donne
Si le navigateur communiquait avec le modèle préféré de l’utilisateur et abstraisait l’inférence locale/distante, les sites pourraient partager les modèles au lieu de les dupliquer
Si en 2026 un modèle local de 2.5GB pose encore problème, on peut se demander ce qui sera considéré comme acceptable
On est passé de l’impossible au centralisé, puis au local ; si le prix à payer est 2.5GB, ça reste tout à fait supportable
Le fait que ça tourne dans le navigateur est cool, mais je n’ai pas envie de vivre dans un monde où les sites téléchargent 2.5GB en arrière-plan
Nano est stocké dans le stockage local et partagé entre sites, donc il n’est téléchargé qu’une seule fois
Ça ne semble pas être le cas de Mistral
Les statistiques correspondantes sont résumées dans cet article de blog
je pense que le sandbox du navigateur est plus sûr que l’installation d’un package ou le téléchargement d’un exécutable
On finira bientôt par s’habituer à ce genre de choses :-)
Dans mon environnement (Firefox, Asahi Linux, M1 Pro), ça fonctionne mal
J’ai dit “hello”, et environ une minute plus tard, des mots bizarres ont commencé à s’afficher en boucle
Question simple : je me demande à quel niveau se situent les modèles ouverts comme ceux de Mistral par rapport à OpenAI ou Anthropic
Est-ce qu’ils sont déjà assez bons pour utiliser des fonctions LLM en privé sur une machine personnelle,
ou est-ce qu’ils restent encore très loin derrière les modèles commerciaux ?
Projet intéressant, et ravi de voir le framework burn utilisé
En revanche, quand je l’ai lancé dans la dernière version de Chromium, le système s’est figé et l’OS s’est arrêté de force
Juste après le téléchargement du modèle, la connexion VPN a aussi sauté, alors que je n’avais aucune limite de bande passante, donc je ne comprends pas pourquoi