vllm-mlx : un serveur d'inférence Apple Silicon avec batching continu et double API
High-performance OpenAI and Anthropic compatible LLM inference server for Apple Silicon. Native MLX, continuous batching, multimodal models, MCP tool calling, and Claude Code support.
En bref
- De quoi s’agit-il ?
- vllm-mlx regroupe sous un seul processus un serveur compatible OpenAI et Anthropic, un cache KV paginé et un ordonnanceur à batching continu, uniquement sur Mac Apple Silicon. Le projet est utile si vous voulez servir un modèle local à Claude Code ou au SDK OpenAI sans écrire de couche d'adaptation.
- À qui s’adresse-t-il ?
- vllm-mlx convient aux développeurs sur Mac Apple Silicon qui veulent une seule commande pour exposer un modèle MLX derrière les API OpenAI et Anthropic, notamment pour brancher Claude Code ou un client existant. Il ne convient pas à ceux qui déploient sur Linux ou CUDA, ni à ceux qui cherchent un serveur multi-utilisateurs à haute disponibilité : le projet cible une machine, pas un cluster.
- Puis-je l’utiliser commercialement ?
- Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 10 jours.
- En quel langage est-il écrit ?
- Principalement Python, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème concret : deux API, un seul Mac
Faire tourner un modèle local sur un Mac ne pose plus de difficulté technique. Le problème arrive au moment du branchement. Un client écrit pour OpenAI attend /v1/chat/completions, un outil comme Claude Code attend /v1/messages avec des blocs de contenu et des appels d'outils au format Anthropic, et un troisième script veut des embeddings ou un rerank. Sans serveur commun, il faut soit modifier chaque client, soit maintenir une passerelle maison. vllm-mlx prend le parti inverse : un seul processus expose les deux familles de routes. Le README liste /v1/chat/completions, /v1/completions, /v1/embeddings, /v1/rerank et /v1/responses côté OpenAI, et /v1/messages côté Anthropic, avec streaming, tool use et system prompts. Le public visé est donc précis : développeur sur Mac, qui veut un endpoint local compatible avec des clients déjà écrits, et qui accepte de rester sur une seule machine.
Ce que le dépôt met en avant face à Ollama ou mlx-lm
La comparaison est faite explicitement dans le README : contrairement à Ollama ou à mlx-lm utilisé directement, le projet annonce du batching continu, un cache KV paginé, du prefix caching et un cache à débordement sur SSD. Ce sont des mécanismes de serveur, pas de moteur d'inférence. La différence se voit quand plusieurs requêtes arrivent en même temps : un ordonnanceur à batching continu peut insérer de nouvelles requêtes dans un lot en cours au lieu d'attendre la fin de la génération précédente. Le cache KV paginé et le prefix caching partagent les préfixes communs entre requêtes. Le README cite aussi un cache hiérarchisé sur disque via --ssd-cache-dir, présenté comme utile aux agents à long contexte, et un préchargement de préfixes via --warm-prompts. Ces choix indiquent une cible : plusieurs clients simultanés sur un même Mac, avec des prompts qui se ressemblent. Pour une seule requête interactive, l'écart avec mlx-lm est probablement faible, mais le dépôt ne fournit pas de mesure comparative directe, donc je ne l'affirme pas.
Le chemin d'une requête, du client au Metal
L'architecture visible dans le matériel tient en trois couches. En entrée, un client parle HTTP en OpenAI ou en Anthropic. Le serveur normalise la requête, applique le gabarit de chat du modèle, puis passe par un parseur d'outils : le README mentionne 19 parseurs couvrant OpenAI, Anthropic, Gemini, Qwen, DeepSeek et Gemma, ce qui laisse entendre que le format d'appel d'outil varie selon la famille de modèles et doit être traduit. Vient ensuite l'ordonnanceur avec batching continu, appuyé sur le cache KV paginé et le prefix cache en trie partagé entre requêtes. En sortie, l'exécution se fait via MLX sur les kernels Metal, sans étape de conversion de modèle, ce que le README présente comme un avantage sur les chaînes qui exportent d'abord vers un autre format. Pour le raisonnement, l'option --reasoning-parser prend en charge Qwen3, DeepSeek-R1 et DeepSeek-V4, et la réponse expose un champ reasoning distinct du contenu. Pour la sortie structurée, response_format avec un JSON Schema passe par lm-format-enforcer. Le point à retenir est que la logique de parsing est côté serveur : le client n'a pas à connaître le dialecte d'outil du modèle.
Installation et configuration réelle
L'installation tient en une ligne : pip install vllm-mlx. Le démarrage minimal donné par le README est vllm-mlx serve mlx-community/Llama-3.2-3B-Instruct-4bit --port 8000 --continuous-batching. Côté client OpenAI, il suffit de pointer base_url vers http://localhost:8000/v1 avec une clé quelconque, le serveur ne la vérifie pas dans cet exemple. Côté Claude Code, le README exporte ANTHROPIC_BASE_URL=http://localhost:8000 et ANTHROPIC_API_KEY=not-needed avant de lancer claude. Les options utiles sont nommées : --ssd-cache-dir pour le cache sur disque, --warm-prompts pour précharger des préfixes, --reasoning-parser qwen3 pour extraire le raisonnement, --moe-top-k pour réduire le nombre d'experts actifs sur un modèle MoE, --mtp pour le décodage spéculatif sur Qwen3-Next, --spec-prefill pour le préremplissage épars, --metrics pour exposer /metrics au format Prometheus et --embedding-model pour charger un modèle d'embedding séparé. L'audio demande un extra : pip install vllm-mlx[audio], plus brew install espeak-ng sur macOS pour le TTS non anglophone. Le bench intégré s'appelle via vllm-mlx bench-serve avec --url, --concurrency, --prompts et --output, ou --workload pour un scénario décrit en JSON.
Multimodal, audio et rerank : ce que le serveur accepte
Le serveur ne se limite pas au texte. Le README cite des modèles vision (Gemma 3, Gemma 4, Qwen3-VL, Pixtral, Llama vision) et des blocs audio_url dans les messages de chat, donc image, vidéo et audio passent par la même route que le texte. Pour la synthèse vocale, le projet annonce 11 voix et plus de 15 langues via Kokoro, Chatterbox, VibeVoice et VoxCPM. Pour la transcription, la famille Whisper est prise en charge, avec un facteur temps réel annoncé jusqu'à 197x sur M4 Max pour whisper-tiny, 55x pour whisper-large-v3-turbo et 24x pour whisper-large-v3. Ces chiffres viennent du tableau du README, pas d'un test que j'aurais mené. Le rerank mérite une mention pour son traitement des cas limites : le README précise que le chemin de forward du reranker MLX accepte les poids de classification de séquence BERT/XLM-RoBERTa avec les activations gelu, gelu_new, gelu_fast, relu, silu ou swish, et que les autres activations échouent explicitement plutôt que d'utiliser silencieusement la mauvaise. C'est un choix défendable : une erreur visible vaut mieux qu'un score de pertinence faux.
Les limites que le matériel rend visibles
La contrainte principale est dans le titre du dépôt : Apple Silicon uniquement, M1 à M5, avec des kernels Metal via MLX. Sur Linux ou sur une machine NVIDIA, le projet n'a pas de chemin d'exécution. Cela exclut d'emblée les équipes qui servent depuis un cluster ou qui mutualisent un parc GPU. Ensuite, le positionnement est celui d'un serveur pour une machine : le batching continu améliore le débit en concurrence, mais rien dans le matériel ne décrit de répartition sur plusieurs nœuds, de redémarrage transparent ou de file d'attente persistante. Un Mac qui dort ou qui ferme son capot interrompt le service. Il y a aussi la question du format des modèles : la promesse d'absence de conversion suppose des poids déjà publiés en MLX, ce qui restreint le catalogue disponible par rapport à ce qu'on trouve en GGUF ou en safetensors classiques. Enfin, la sortie structurée repose sur lm-format-enforcer, un composant qui impose ses propres règles de schéma ; un JSON Schema exotique peut ne pas passer. Aucun de ces points n'est un défaut caché, mais ils dessinent le périmètre.
Où situer le projet face à mlx-lm et llama.cpp
mlx-lm est la bibliothèque de référence pour exécuter des modèles MLX en Python. Elle sert de moteur, pas de serveur : pas de routes OpenAI complètes, pas de /v1/messages au format Anthropic, pas d'ordonnanceur à batching continu documenté. vllm-mlx s'ajoute au-dessus de cette couche et vend précisément ce qui manque à mlx-lm. L'autre alternative courante sur Mac est llama.cpp via son serveur, qui parle OpenAI et tourne sur CPU comme sur GPU Metal avec des poids GGUF. La différence d'approche est nette : llama.cpp convertit et quantifie vers GGUF, ce qui ouvre un large catalogue de modèles quantifiés et un fonctionnement hors Mac, tandis que vllm-mlx reste sur MLX et sur les poids au format MLX. Choisir l'un ou l'autre dépend donc moins des performances annoncées que de deux questions : votre modèle existe-t-il en MLX, et avez-vous besoin de la route /v1/messages pour un outil comme Claude Code. Si la réponse est non aux deux, llama.cpp couvre le besoin avec moins de dépendances spécifiques à une plateforme.
Maintenance, licence et coût de mise à jour
Le dépôt est actif : dernier push en septembre 2026, version v0.4.1 publiée en août 2026, après v0.4.0 en juin et une release candidate v0.4.0rc1 en mai. Le rythme observé sur ces trois versions est celui d'un projet qui itère vite, ce qui a un revers : les options de ligne de commande et les formats de réponse peuvent bouger entre deux versions mineures. Sur un serveur local utilisé par des scripts, cela implique de figer la version dans un requirements.txt plutôt que de suivre pip install vllm-mlx sans contrainte. La licence est Apache-2.0, donc permissive : usage commercial, modification et redistribution sont autorisés, avec les obligations habituelles de conservation de la notice de licence et du fichier NOTICE, et la clause de brevets qui accompagne cette licence. Je ne donne pas d'avis juridique : si vous redistribuez le serveur dans un produit, faites relire les mentions par qui de droit. Un point pratique : la dépendance à MLX et à Metal signifie que le support dépend du matériel Apple et de macOS, pas d'un cycle de publication Linux, ce qui réduit la surface de compatibilité mais lie la durée de vie du projet à celle de la plateforme.
Conclusion éditoriale
vllm-mlx convient aux développeurs sur Mac Apple Silicon qui veulent une seule commande pour exposer un modèle MLX derrière les API OpenAI et Anthropic, notamment pour brancher Claude Code ou un client existant. Il ne convient pas à ceux qui déploient sur Linux ou CUDA, ni à ceux qui cherchent un serveur multi-utilisateurs à haute disponibilité : le projet cible une machine, pas un cluster. Avant d'adopter, vérifiez que votre modèle est bien publié au format MLX et que la version de Python installée est au moins 3.10, puis lancez vllm-mlx serve avec --port et --continuous-batching pour confirmer le comportement de l'ordonnanceur sur votre matériel.
Notes de la communauté