- Moshi est un modèle speech-text pour les conversations vocales en temps réel ainsi qu’un framework de dialogue vocal full-duplex ; il propose une démo en direct et des modèles sur Hugging Face
- Le dépôt sépare une pile d’inférence PyTorch pour la recherche et l’expérimentation, MLX pour l’inférence on-device sur iPhone/Mac, et une pile d’inférence Rust pour la production
- Le modèle gère deux flux audio — la parole de Moshi et celle de l’utilisateur — et prédit aussi une inner monologue, c’est-à-dire des tokens texte correspondant à la propre parole de Moshi, afin d’améliorer la qualité de génération
- Le codec Mimi traite en streaming un audio 24 kHz avec une représentation à 12,5 Hz et une bande passante de 1,1 kbps ; il a une latence de trame de 80 ms, la latence théorique de Moshi est de 160 ms, et la latence totale mesurée sur GPU L4 descend à 200 ms
- Les modèles publiés incluent la voix synthétique masculine Moshiko, la voix synthétique féminine Moshika, ainsi que le codec vocal Mimi ; les poids des modèles sont sous CC-BY 4.0, le code client Python et web sous MIT, et le backend Rust sous licence Apache
Objectif et composition de Moshi
- Moshi est à la fois un speech-text foundation model et un framework full-duplex pour les conversations vocales en temps réel
- Une démo en direct est disponible sur moshi.chat, et la collection de modèles est publiée sur Hugging Face
- Le dépôt comprend trois piles d’inférence
- PyTorch : pour la recherche et l’expérimentation, dans le répertoire
moshi/
- MLX : pour l’inférence on-device sur iPhone et Mac, dans le répertoire
moshi_mlx/
- Rust : pour la production, dans le répertoire
rust/
- Inclut une implémentation Rust de Mimi et le binding Python
rustymimi
- Le code du client web UI utilisé dans la démo Moshi se trouve dans le répertoire
client/
- Le fine-tuning de Moshi est traité dans le dépôt séparé kyutai-labs/moshi-finetune
Modèles Kyutai associés
- La codebase de Moshi sert aussi à exécuter des modèles associés de Kyutai utilisant une multi-stream architecture similaire à celle de Moshi
Architecture du modèle
- Moshi modélise deux flux audio
- l’un correspond à la parole produite par Moshi
- l’autre correspond à la parole de l’utilisateur
- En plus de ces deux flux audio, Moshi prédit une inner monologue, c’est-à-dire des tokens texte correspondant à sa propre parole, ce qui améliore fortement la qualité de génération
- Un petit Depth Transformer modélise les dépendances entre codebooks à un pas de temps donné
- Un grand Temporal Transformer de 7B paramètres modélise les dépendances temporelles
- La latence théorique est de 160 ms
- taille de trame Mimi : 80 ms
- latence acoustique : 80 ms
- Sur GPU L4, la latence totale pratique descend à 200 ms
Codec vocal Mimi
- Mimi est un codec audio neuronal qui ramène un audio 24 kHz à une représentation à 12,5 Hz
- Mimi fonctionne en streaming intégral, avec une bande passante de 1,1 kbps et une latence égale à la taille de trame, soit 80 ms
- D’après le README, Mimi offre de meilleures performances que des codecs non streaming existants
- Mimi s’appuie sur des codecs audio neuronaux antérieurs comme SoundStream et EnCodec
- ajout de Transformer à la fois côté encodeur et décodeur
- ajustement des strides pour aligner le framerate global sur 12,5 Hz
- Un framerate de 12,5 Hz est plus proche du framerate moyen des tokens texte, d’environ 3 à 4 Hz, ce qui réduit le nombre d’étapes autorégressives de Moshi
- Comme SpeechTokenizer, Mimi utilise une distillation loss afin d’aligner le token du premier codebook sur les représentations auto-supervisées de WavLM
- Comme EBEN, Mimi n’utilise que l’adversarial training loss avec du feature matching, ce qui améliore fortement la qualité subjective même à bas bitrate
Modèles publiés et formats
- Trois modèles sont publiés
- Moshiko : Moshi fine-tuné avec une voix synthétique masculine
- Moshika : Moshi fine-tuné avec une voix synthétique féminine
- Mimi : le codec vocal
- Les formats de fichiers et les quantifications disponibles varient selon le backend
- Mimi est inclus avec chaque modèle et utilise toujours le même format de checkpoint
- Modèles PyTorch
- Modèles MLX
- Modèles Rust/Candle
- Tous les modèles sont publiés sous licence CC-BY 4.0
Exigences et contraintes d’installation
- Python 3.10 minimum est requis, et 3.12 est recommandé
- Les clients PyTorch et MLX peuvent être installés depuis PyPI
pip install -U moshi
pip install -U moshi_mlx
pip install rustymimi
- Si vous n’utilisez pas Python 3.12, des erreurs peuvent survenir lors de l’installation de
moshi_mlx ou de sa dépendance rustymimi ; dans ce cas, il faut installer la toolchain Rust ou passer à Python 3.12
- Le fonctionnement sur Windows est espéré, mais il n’y a pas de support officiel
- La version MLX a été testée sur MacBook Pro M3
- La version PyTorch actuelle ne prend pas en charge la quantification et nécessite donc une quantité importante de mémoire GPU, de l’ordre de 24GB
- Le backend Rust nécessite une toolchain Rust récente
- Pour compiler avec support GPU, il faut CUDA et
nvcc adaptés au GPU
Modes d’exécution
-
PyTorch
- L’API PyTorch se trouve dans le répertoire
moshi et fournit des versions streaming du tokenizer audio Mimi et du modèle de langage Moshi
- En mode interactif, il faut d’abord lancer le serveur de modèles, puis utiliser le web UI ou le client en ligne de commande
python -m moshi.server [--gradio-tunnel] [--hf-repo kyutai/moshika-pytorch-bf16]
- Le web UI est accessible par défaut sur
localhost:8998
- Si l’on accède au GPU d’une machine distante via HTTP, les politiques de sécurité du navigateur peuvent bloquer l’usage du microphone
- Il est possible de transférer le port distant 8998 vers localhost avec SSH
-L
--gradio-tunnel permet de créer un tunnel accessible de partout
- Ce tunnel passe par les États-Unis et peut ajouter une forte latence supplémentaire, jusqu’à 500 ms depuis l’Europe
--gradio-tunnel-token permet de définir un secret token fixe et de réutiliser la même adresse
--hf-repo permet de choisir un autre modèle préentraîné Hugging Face
- Un client en ligne de commande est aussi fourni, mais contrairement au navigateur web il ne fait pas d’echo cancellation et ne saute pas de frames pour compenser l’accumulation de latence
python -m moshi.client [--url URL_TO_GRADIO]
-
MLX
- Après installation de
moshi_mlx, il est possible d’exécuter une inférence locale sur macOS
python -m moshi_mlx.local -q 4
python -m moshi_mlx.local -q 8
python -m moshi_mlx.local -q 4 --hf-repo kyutai/moshika-mlx-q4
python -m moshi_mlx.local -q 8 --hf-repo kyutai/moshika-mlx-q8
- Les flags
-q et --hf-repo doivent toujours correspondre
- L’interface en ligne de commande MLX est elle aussi barebone et ne gère ni l’echo cancellation ni la compensation de l’accumulation de latence
python -m moshi_mlx.local_web permet de lancer le web UI, avec une connexion HTTP servie sur localhost:8998
-
Rust
- Le serveur d’inférence Rust s’exécute depuis le répertoire
rust
cargo run --features cuda --bin moshi-backend -r -- --config moshi-backend/config.json standalone
- Sur macOS, on peut utiliser
--features metal à la place de --features cuda
- En utilisant
config-q8.json au lieu de config.json, on peut charger un modèle quantifié q8
- D’autres modèles préentraînés peuvent être sélectionnés en modifiant la clé
"hf_repo" dans le fichier de configuration
- Quand le serveur affiche
standalone worker listening, le web UI peut être utilisé
- Le serveur Rust utilise HTTPS par défaut ; l’accès se fait donc via
https://localhost:8998
- Le navigateur peut afficher un avertissement de site non sûr ; dans Chrome, il est possible de continuer vers localhost via « Details » ou « Advanced »
Clients et développement
- Le web UI est recommandé, car il fournit l’echo cancellation, ce qui aide la qualité globale du modèle
- La plupart des commandes servent directement le web UI à l’URL fournie
- Des interfaces en ligne de commande pour Rust et Python sont aussi proposées ; elles utilisent le même protocole que le web UI, sans nécessiter de changements côté serveur
- La build du web UI se fait dans le répertoire
client
cd client
npm install
npm run build
- Le client en ligne de commande Rust s’exécute depuis le répertoire
rust
cargo run --bin moshi-cli -r -- tui --host localhost
- Le client PyTorch Python s’exécute avec la commande suivante
python -m moshi.client
- La démo Gradio s’exécute après installation de
gradio-webrtc>=0.0.18
python -m moshi.client_gradio --url <moshi-server-url>
docker compose up
Licence et citation
- La partie Python du code est fournie sous licence MIT
- Le backend Rust est fourni sous licence Apache
- Le code du client web est fourni sous licence MIT
- Une partie du code est basée sur AudioCraft, sous licence MIT
- Les poids des modèles sont publiés sous licence CC-BY 4.0
- En cas d’utilisation de Mimi ou Moshi, il est demandé de citer l’article
Moshi: a speech-text foundation model for real-time dialogue
1 commentaires
Avis sur Hacker News
Comme presque tous les commentaires ici sont négatifs, je vais laisser mon retour : la latence est excellente, même tellement bonne qu’on a souvent l’impression qu’il coupe la parole.
Pour un modèle open source, je trouve que c’est une grande réussite. Cela dit, aujourd’hui les gens sont habitués à des grands modèles de langage très performants, et la qualité du contenu de ses réponses est loin des meilleurs modèles actuels. Il donne plutôt l’impression des grands modèles de langage qu’on voyait vers 2019 ; côté audio, on est arrivé à un niveau « suffisamment correct », et il vaudrait mieux se concentrer désormais sur la qualité des réponses.
La question naturelle est de savoir s’il existe un moyen de greffer un « meilleur grand modèle de langage » sans dégrader l’expérience Moshi.
Moshi est sous licence CC-BY, et il existe aussi un modèle similaire de conversation temps réel voix-texte, d’environ 7B, récemment publié sous Apache v2 : https://tincans.ai/slm3 / https://huggingface.co/collections/tincans-ai/gazelle-v02-65...
Il y a récemment beaucoup de développements du côté des modèles de langage avec support vocal. Par exemple : https://github.com/ictnlp/LLaMA-Omni, https://github.com/gpt-omni/mini-omni.
Leur serveur d’inférence est écrit en Rust avec le crate Candle de Hugging Face. L’un des auteurs de Moshi est aussi l’auteur principal de Candle.
Nous construisons nous aussi une pile d’inférence sur Candle, et nous en sommes plutôt satisfaits.
En cherchant une démo sur YouTube, je suis tombé sur une vidéo amusante datant d’il y a quelques mois : https://youtu.be/coroLWOS7II?si=TeVghP_Zi0P9exQh
Je suppose que ça s’est clairement amélioré depuis :-)
Intéressant. J’aime le fait qu’ils se concentrent ici sur la latence, avec une revendication d’environ 200 ms en pratique sur GPU local.
Comme c’est basé sur un modèle transformer 7B, il ne sera pas extrêmement intelligent. Si l’on imagine qu’un modèle 70B a une latence d’environ 1 seconde, on peut envisager une architecture système avec des réactions intermédiaires qui indiquent verbalement que « le modèle est en train de parler », un modèle de type 7B/Phi-3 pour fournir une première réaction rapide, puis un plus grand modèle derrière. On pourrait même confier au modèle Phi-3 la tâche de prendre la vraie bonne réponse, puis de s’excuser et de corriger si nécessaire.
De façon anecdotique, je pense que le cerveau des gens fonctionne souvent ainsi : on réagit vite, puis on corrige ou complète 1 à 2 secondes plus tard. Bien sûr, il y a aussi des gens qui, à l’inverse, ne corrigent jamais, et d’autres qui marquent une longue pause avant de donner une réponse pleinement réfléchie.
Je l’ai essayé, et on pouvait saisir n’importe quelle adresse e-mail. Il répond instantanément, presque tout de suite, même pendant qu’on parle encore.
Mais ça ressemblait simplement à des phrases de remplissage, voire à des réponses mises en cache. La réponse à ce qui a réellement été demandé arrive bien plus tard, à condition qu’il ne tombe pas dans une boucle entre-temps.
Je construis une solution temps réel voix → grand modèle de langage → sortie vocale, et la partie la plus intéressante ici me semble être le codec audio neuronal en streaming. Avec Whisper, il est en effet difficile de faire correctement du speech-to-text en streaming.
Cela dit, du point de vue produit, je n’ai pas forcément envie d’envoyer directement cela dans un grand modèle de langage pour qu’il réponde. Dans beaucoup de cas d’usage, je pense qu’il faut une étape d’appel d’outils/fonctions avant la réponse. Je suis toujours partant pour discuter avec des personnes qui travaillent dans cette direction.
tincans, mentionné plus bas, a aussi l’air excellent. Mais comme le développement de tincans est terminé, il y a 10 000 % de place dans cette voie. Si Chris lit ceci, j’aimerais vraiment lui expliquer les cas d’usage produit/business que cela résout, quel que soit le niveau atteint par les grands modèles de langage.
Le grand modèle de langage ne répond pas directement ; il ne fait que choisir des nœuds de l’arborescence auxquels sont associées des sorties texte-voix préparées à l’avance. Il y a un paramètre de « durée de silence » qui décide si l’utilisateur a fini de parler et transmet la transcription au modèle ; ce n’est pas particulièrement complexe. Je réfléchis encore à la bonne façon de gérer l’entrée audio, et à la possibilité de contrôler le modèle assez précisément, uniquement par la construction du prompt, pour éliminer l’arborescence IVR. Ça fonctionne déjà plutôt bien, mais il y a beaucoup de marge de progression.
La vitesse de réponse est impressionnante, mais pas la « qualité » des réponses. Voici l’historique de conversation de mon deuxième test :
Moshi : « Bonjour, qu’est-ce qui se passe ? »
Moi : « On est en quelle année ? »
Moshi : « Ah, nous sommes en 2019. Je crois que c’était il y a environ un an. »
Moi : « Tu es sûr que c’est bien 2019 ? »
Moshi : « Ah oui, j’en suis sûr. C’est bien 2019. Ce nombre est pour le dernier. »
Moi : « Qu’est-ce que la COVID-19 ? »
Moshi : « C’est une maladie rare. Elle est causée par un système immunitaire hyperactif qui attaque la peau. »
À ce stade, il n’a plus répondu.
Moshi est le modèle le plus amusant jusqu’à présent. Mon expérience récente est ici : https://x.com/tommoor/status/1809051817860354471
En revanche, mieux vaut ne pas s’attendre à de l’exactitude.