Guide de prise en main rapide du sélecteur de modèles llama.swap pour les LLM locaux compatibles OpenAI
Échange à chaud de LLM locaux sans modifier les clients.
Bientôt, vous jonglerez avec vLLM, llama.cpp et plus encore — chaque pile sur son propre port. Tout ce qui se trouve en aval souhaite toujours une URL de base /v1; sinon, vous continuez à changer de ports, de profils et de scripts ponctuels. llama-swap est le proxy /v1 avant ces piles.
llama-swap fournit une porte d’entrée unique compatible OpenAI et Anthropic, avec un fichier YAML qui associe chaque nom de model à la commande qui lance le bon amont. Demandez un modèle et le proxy le lance ou bascule vers celui-ci ; configurez les TTL et les groupes lorsque la VRAM est limitée ou si plusieurs modèles doivent coexister. Ce guide couvre les chemins d’installation, un fichier config.yaml pratique, la surface HTTP et les modes de défaillance qui apparaissent une fois que le streaming et les proxies inverses entrent en jeu.
Pour une comparaison plus large des options d’hébergement de LLM, consultez LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared
Vue d’ensemble du commutateur de modèles llama-swap pour les API locales LLM compatibles OpenAI
llama-swap est un serveur proxy léger construit autour d’un modèle opérationnel simple : un seul binaire, un fichier de configuration YAML, aucune dépendance. Il est écrit en Go, ce qui signifie un seul binaire statique à côté du reste de la pile — pas besoin de runtime Python ou d’application de bureau. Il se place devant n’importe quel amont compatible OpenAI et Anthropic en tant que couche de commutation de modèles.
Conceptuellement, cela répond à une question très pratique qui apparaît dans les piles locales de LLM :
Comment passer d’un modèle à l’autre avec un client compatible OpenAI ?
Avec llama-swap, vous continuez d’utiliser des requêtes normales /v1/..., mais vous changez le model que vous demandez. llama-swap lit cette valeur model, charge la configuration du serveur correspondante, et si le mauvais amont est en cours d’exécution, il le remplace par le bon.
Quelques détails de conception sont importants pour des configurations quasi de production :
llama-swap est sous licence MIT avec aucune télémétrie — cela vaut toujours la peine de le confirmer pour tout hôte qui voit de vrais prompts.
Il est conçu pour le chargement à la demande de backends comme llama.cpp, vLLM, Whisper et stable-diffusion.cpp, et non pour vous verrouiller sur un moteur d’inférence unique.
Par défaut (sans regroupement spécial), il exécute un modèle à la fois : demandez un model différent et il arrête l’amont actuel pour lancer le bon. Pour plus d’un modèle résident ou un contrôle plus fin de la coexistence, configurez les groups.
Voici le modèle mental que la plupart des développeurs trouvent utile :
flowchart LR
C[Your app or SDK\nOpenAI-compatible client] -->|/v1/chat/completions\nmodel = qwen-coder| LS[llama-swap proxy\nsingle endpoint]
LS -->|starts or routes to| U1[Upstream server A\nllama-server]
LS -->|starts or routes to| U2[Upstream server B\nvLLM OpenAI server]
LS --> M[Management endpoints\nrunning, unload, events, metrics]
C’est aussi pourquoi un proxy de commutation de modèles diffère de “juste exécuter un modèle” : il s’agit d’orchestration et de routage au-dessus d’un ou plusieurs serveurs d’inférence.
llama-swap vs Ollama vs LM Studio vs serveur llama.cpp
Les quatre options peuvent vous fournir une “API LLM locale”, mais elles optimisent des flux de travail différents. Le moyen le plus rapide de choisir est de décider si vous voulez un runtime (téléchargement de modèle + exécution) ou un routeur/proxy (commutation + orchestration entre les runtimes).
llama-swap
llama-swap se concentre sur le fait d’être un proxy transparent qui prend en charge les points de terminaison compatibles OpenAI (y compris /v1/chat/completions, /v1/completions, /v1/embeddings et /v1/models) et achemine les requêtes vers l’amont correct en fonction du modèle demandé. Il fournit également des points de terminaison opérationnels non liés à l’inférence tels que /running, /logs/stream et une interface Web à /ui.
Ollama
Ollama expose sa propre API HTTP (POST /api/chat, POST /api/generate et le port local par défaut 11434).
keep_alive contrôle combien de temps un modèle reste chargé, y compris 0 pour le décharger immédiatement.
Il convient aux utilisateurs qui souhaitent tirer un modèle et discuter avec un câblage minimal. llama-swap convient aux commandes par modèle, aux backends mélangés et à une URL de forme OpenAI unique pour chaque client — orchestrer vLLM à côté de llama-server avec des drapeaux différents par modèle est hors de ce que vise Ollama.
LM Studio
LM Studio est une application de bureau avec un serveur API local depuis l’onglet Développeur (localhost ou LAN), incluant des modes compatibles OpenAI et compatibles Anthropic, ainsi que lms server start depuis le terminal.
Il convient à une boucle GUI-first : parcourir les modèles, cliquer, tester. llama-swap convient à un rôle de type serveur : YAML, supervision de processus, amonts mélangés, pas de session de bureau.
Serveur llama.cpp
llama-server expose /v1/completions, /v1/chat/completions, /v1/responses, et le schéma habituel consiste à pointer un client OpenAI vers celui-ci via base_url.
llama.cpp fournit également un mode routeur : lancez llama-server comme routeur, --models-dir, puis POST /models/load et POST /models/unload pour jongler avec les modèles GGUF sans proxy séparé. Pour un guide d’installation complet, consultez llama-server router mode: dynamic model switching without restarts.
Si chaque modèle se trouve sous un seul routeur llama.cpp, un proxy supplémentaire est souvent inutile. Lorsque llama.cpp doit s’asseoir à côté de vLLM ou d’autres serveurs de forme OpenAI, llama-swap fournit une surface /v1 unique et plusieurs processus derrière.
Pour des solutions d’hébergement compatibles OpenAI similaires, consultez LocalAI QuickStart: Run OpenAI-Compatible LLMs Locally ou SGLang QuickStart: Install, Configure, and Serve LLMs via OpenAI API
Installer le commutateur de modèles llama-swap avec Docker, Homebrew, WinGet ou les binaires
Linux, macOS et Windows sont tous de première classe : Docker, Homebrew, WinGet, binaires GitHub ou compilation à partir du code source. Choix courants : Docker sur les serveurs headless, Homebrew ou WinGet sur les postes de travail, binaires autonomes lorsque l’empreinte d’installation doit rester minimale.
Installation Docker
Tirez une image qui correspond à votre matériel. Les images suivent de près l’amont (builds nocturnes) et couvrent CUDA, Vulkan, Intel, MUSA et CPU — choisissez celle qui correspond à la façon dont vous accélérez réellement, pas “latest” par habitude.
# Example platform pulls
docker pull ghcr.io/mostlygeek/llama-swap:cuda
docker pull ghcr.io/mostlygeek/llama-swap:vulkan
docker pull ghcr.io/mostlygeek/llama-swap:intel
docker pull ghcr.io/mostlygeek/llama-swap:musa
docker pull ghcr.io/mostlygeek/llama-swap:cpu
Préférez les variantes d’images non-root lorsque c’est possible : moins de regrets si la limite du conteneur est jamais fausse.
Installation Homebrew
Sur macOS et Linux, utilisez le tap et installez :
brew tap mostlygeek/llama-swap
brew install llama-swap
llama-swap --config path/to/config.yaml --listen localhost:8080
Installation WinGet
Sur Windows :
winget install llama-swap
winget upgrade llama-swap
Binaires pré-construits et versions
GitHub Releases fournit des binaires Linux, macOS, Windows et FreeBSD si vous ne voulez pas de gestionnaire de paquets.
Les numéros de version avancent rapidement (par exemple v198, v197 autour du début 2026) — fixez une version dans l’automatisation plutôt que de flotter “ce qu’il y avait hier”.
Configurer llama-swap avec config.yaml pour le basculement de modèles, le TTL et les groupes
Tout dans llama-swap est piloté par la configuration. La configuration minimale viable est simplement un dictionnaire models: et une cmd pour chaque modèle, lançant souvent llama-server avec ${PORT} substitué par modèle.
Le système de configuration va bien au-delà du simple “lancement d’un processus”, et quelques options méritent d’être comprises tôt car elles répondent directement à des problèmes de style FAQ (déchargement automatique, sécurité et clients qui s’appuient sur /v1/models).
Paramètres globaux que vous utiliserez réellement
healthCheckTimeout est la durée pendant laquelle llama-swap attend qu’un modèle devienne sain après le démarrage (par défaut 120s, minimum 15s). Pour des chargements multi-Go sur des disques lents, augmentez cela avant de blâmer le proxy.
globalTTL est les secondes d’inactivité avant le déchargement automatique ; par défaut 0 signifie “ne jamais décharger” sauf si vous le définissez — choisissez explicitement des TTL pour tout ce qui dépasse une configuration de jouet afin que la VRAM ne se remplisse pas de modèles oubliés.
startPort ensemence la macro ${PORT} (par défaut 5800) ; l’attribution est déterministe par ID de modèle alphabétique, ce qui est une fonctionnalité lorsque vous déboguez “qui a pris quel port” et un piège si vous renommez les modèles avec négligence.
includeAliasesInList décide si les alias apparaissent comme des lignes séparées dans /v1/models ; activez-le si votre interface ne propose que des modèles énumérés.
apiKeys verrouille tout ce qui est accessible hors localhost : Basic, Bearer ou x-api-key. llama-swap supprime ces en-têtes avant de transmettre afin que les journaux amont soient moins susceptibles de retenir les secrets du client.
Paramètres de niveau modèle qui débloquent l’ergonomie de production
Par modèle, cmd est le seul champ requis.
proxy est par défaut http://localhost:${PORT} — c’est la cible de transmission pour l’amont de ce modèle.
checkEndpoint est par défaut /health ; définissez "none" lorsque le backend n’a pas de route de santé ou si le démarrage à froid dépasse ce que vous êtes prêt à attendre — ne laissez pas un /health cassé et vous demandez pourquoi rien n’atteint ready.
ttl : -1 hérite de globalTTL, 0 ne décharge jamais, N > 0 décharge après N secondes d’inactivité — utilisez un TTL par modèle lorsqu’un modèle doit persister et un autre disparaître rapidement.
aliases et useModelName gardent des noms stables face au client tout en satisfaisant les amonts qui nécessitent un identifiant spécifique.
cmdStop est non optionnel pour les conteneurs : mappez-le à docker stop (ou équivalent) ; sans cela, vous obtenez un SIGTERM POSIX / Windows taskkill contre quel que soit le PID que llama-swap a lancé — bien pour un binaire nu, faux pour un nom de conteneur.
concurrencyLimit limite les requêtes parallèles par modèle avec HTTP 429 lorsque la limite est dépassée — définissez-le lorsque vous préférez rejeter la charge plutôt que de faire la queue éternellement.
groups couvrent la coexistence (swap, exclusive) et les modèles toujours actifs (persistent). Les hooks peuvent précharger au démarrage ; si vous préchargez plusieurs modèles à la fois sans groupe, attendez-vous à ce qu’ils se battent — définissez un groupe en premier pour que le préchargement corresponde à la façon dont vous voulez que les modèles partagent le GPU.
Exemple minimal de config.yaml pour llama.cpp et vLLM
Cet exemple vise à être “juste assez” pour illustrer les molettes de bonnes pratiques : un TTL par défaut, une vérification de santé explicite, des alias stables et un groupe qui maintient un petit modèle “toujours actif” en cours d’exécution tandis que les gros modèles de discussion basculent.
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 minutes d'inactivité puis déchargement
includeAliasesInList: true
startPort: 5800
# Optionnel mais recommandé pour tout ce qui dépasse le développement local
apiKeys:
- "${env.LLAMASWAP_API_KEY}"
models:
llama-chat:
cmd: |
llama-server --port ${PORT} --model /models/llama-chat.gguf
--ctx-size 8192
aliases:
- "llama-chat-latest"
# Utilise les valeurs par défaut :
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (hériter de globalTTL)
qwen-coder:
cmd: |
llama-server --port ${PORT} --model /models/qwen-coder.gguf
--ctx-size 8192
aliases:
- "qwen-coder-latest"
vllm-coder:
# Modèle illustratif : gérer un serveur compatible OpenAI conteneurisé
proxy: "http://127.0.0.1:${PORT}"
cmd: |
docker run --name ${MODEL_ID} --init --rm -p ${PORT}:8000 vllm/vllm-openai:latest
cmdStop: docker stop ${MODEL_ID}
checkEndpoint: "none"
ttl: 0 # jamais de déchargement automatique (ex. garder sur GPU)
groups:
chat-models:
swap: true
exclusive: true
members: ["llama-chat", "qwen-coder"]
always-on:
persistent: true
swap: false
exclusive: false
members: ["vllm-coder"]
Aucune de cela n’est décoratif : cmd conduit le processus, proxy/checkEndpoint/ttl contrôlent le routage et le cycle de vie, cmdStop est ce qui fait que les amonts basés sur Docker s’arrêtent réellement, et groups séparent “un gros modèle à la fois” de “ces deux modèles de discussion peuvent coexister tandis que le serveur d’embedding reste verrouillé”.
Exécuter et basculer les modèles via des points de terminaison compatibles OpenAI
Une fois llama-swap en cours d’exécution, vous interagissez avec lui comme avec n’importe quel autre point de terminaison compatible OpenAI. La surface de l’API comprend des points de terminaison principaux tels que /v1/chat/completions, /v1/completions, /v1/embeddings et /v1/models, et llama-swap utilise le model demandé pour décider quel amont lancer et vers quoi acheminer.
Un flux de démarrage rapide pratique :
# 1) Démarrer llama-swap
llama-swap --config ./config.yaml --listen localhost:8080
# 2) Découvrir les modèles disponibles
curl http://localhost:8080/v1/models
La liste des modèles est une fonctionnalité de gestion de premier ordre et inclut des comportements comme le tri par ID, l’exclusion des modèles unlisted et l’inclusion optionnelle des alias.
# 3) Faire une requête de complétion de chat pour un modèle spécifique
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${LLAMASWAP_API_KEY}" \
-d '{
"model": "qwen-coder",
"messages": [{"role":"user","content":"Write a TypeScript function that retries fetch with backoff."}]
}'
Si vous répétez maintenant l’appel avec "model": "llama-chat", llama-swap basculera les processus amont (sauf si votre configuration de groupe leur permet de coexister) car il extrait le modèle demandé de la requête et charge la configuration du serveur appropriée.
Si vous utilisez une SDK, pointez le client vers http://localhost:8080/v1 — même astuce que viser la bibliothèque Python OpenAI vers llama-server, sauf que l’URL stable est maintenant llama-swap et le champ model sélectionne l’amont.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="sk-your-llamaswap-key"
)
resp = client.chat.completions.create(
model="qwen-coder",
messages=[{"role": "user", "content": "Explain the difference between mutexes and semaphores."}],
)
print(resp.choices[0].message.content)
Pour réchauffer un modèle avant la première requête réelle (masquer la latence de démarrage à froid), utilisez /upstream/<model> — il se charge automatiquement si nécessaire et transmet directement vers cet amont. Façon simple de s’assurer que les poids sont résidents avant un benchmark ou un test scripté.
Contrôler et surveiller llama-swap via les points de terminaison de l’API de gestion et les événements SSE
llama-swap n’est pas juste “un proxy” ; il expose également des points de terminaison de contrôle opérationnel qui vous permettent de construire des outils autour du cycle de vie et de l’observabilité des modèles.
Vérifier ce qui tourne
GET /running retourne l’état d’exécution pour les modèles chargés, y compris des valeurs d’état comme ready, starting, stopping, stopped et shutdown.
curl http://localhost:8080/running
Décharger les modèles pour libérer la VRAM
Pour décharger tout immédiatement, utilisez le point de terminaison versionné de l’API POST /api/models/unload. Pour décharger un seul modèle (par ID ou alias), utilisez POST /api/models/unload/<model>. Un GET /unload hérité existe pour la compatibilité ascendante.
# décharger tout
curl -X POST http://localhost:8080/api/models/unload
# décharger un modèle
curl -X POST http://localhost:8080/api/models/unload/qwen-coder
Utilisez ces points de terminaison lorsque la VRAM est nécessaire maintenant au lieu d’attendre le TTL — benchmarks, commutations rapides de modèles, ou après avoir chargé un point de contrôle beaucoup plus grand que prévu.
Diffuser les événements en direct via SSE
GET /api/events établit un flux Server-Sent Events et est conçu pour des mises à jour en temps réel qui incluent les changements d’état des modèles, les journaux, les métriques et les comptages de requêtes en cours.
curl -N http://localhost:8080/api/events
SSE et le streaming de tokens cassent lorsque n’importe quelle boîte intermédiaire tamponne — désactivez le tamponnage sur nginx (ou votre équivalent) pour /api/events et /v1/chat/completions. llama-swap définit X-Accel-Buffering: no sur SSE ; désactivez le tamponnage dans le proxy également — les en-têtes ne sont pas un substitut à une configuration de proxy correcte.
Métriques et captures de requêtes
GET /api/metrics retourne des métriques d’utilisation de jetons, avec une rétention en mémoire contrôlée par metricsMaxInMemory (par défaut 1000).
GET /api/captures/<id> peut récupérer des captures complètes de requêtes/réponses, mais seulement lorsque captureBuffer > 0 est configuré.
Journaux et interface Web
llama-swap expose /ui pour une interface Web, et des points de terminaison de journaux opérationnels tels que /logs et /logs/stream pour une surveillance en temps réel.

Si vous activez apiKeys, supposez une défense en profondeur : /health et des parties de /ui restent accessibles sans clé — bien pour des limites de confiance locales, pas bien si l’hôte est sur un réseau partagé. Placez llama-swap derrière quelque chose qui impose votre politique réelle ; l’authentification intégrée est pour garder les clients occasionnels honnêtes, pas pour une API multi-locataire publique.
Dépannage du basculement de modèles llama-swap en production
La plupart des problèmes de llama-swap tombent dans un petit ensemble de catégories opérationnelles : streaming à travers un proxy inversé, vérifications de santé pendant les démarrages à froid, ports et cycle de vie des processus, et authentification.
Le streaming casse derrière nginx ou un autre proxy inversé
nginx tamponnera gaiement votre SSE et vos complétions streamées. Désactivez proxy_buffering (et proxy_cache) pour /api/events et /v1/chat/completions. llama-swap émet X-Accel-Buffering: no sur SSE, ce qui aide — réparez le proxy quand même.
Un modèle ne devient jamais prêt
Par défaut, checkEndpoint par modèle est /health et doit retourner HTTP 200 pour que le processus soit considéré comme prêt. Vous pouvez définir checkEndpoint sur un autre chemin ou sur "none" pour désactiver entièrement les vérifications de santé.
Si les grands modèles prennent plus de temps à se charger, augmentez healthCheckTimeout (par défaut 120s), ou utilisez des vérifications de santé sur mesure pour votre amont spécifique.
Le basculement de modèles laisse un ancien conteneur en cours d’exécution
Si l’amont est Docker ou Podman, définissez cmdStop — sinon llama-swap arrête le processus wrapper tandis que le conteneur continue de consommer la VRAM en arrière-plan.
Je reçois des réponses 401 après avoir activé la sécurité
Lorsque apiKeys est configuré, llama-swap nécessite une clé valide et accepte trois méthodes (authentification Basic, jeton Bearer, x-api-key). Il supprime également les en-têtes d’authentification avant de transmettre vers l’amont.
Je reçois 429 Too Many Requests
concurrencyLimit retourne 429 lorsque la limite est dépassée — par conception. Augmentez la limite si vous l’avez sous-provisionnée, ou baissez-la si vous n’aviez pas l’intention de limiter.
Conflits de ports ou problèmes de routage étranges
Évitez les ports codés en dur dans cmd ; utilisez ${PORT} et déplacez startPort si 5800+ entre en collision avec autre chose. Rappelez-vous que les ports sont attribués dans l’ordre alphabétique par ID de modèle — renommez un modèle et le mappage des ports change.
Checklist de débogage opérationnel
/running pour la vérité, /logs/stream lorsque le démarrage est opaque, POST /api/models/unload lorsque la VRAM est nécessaire maintenant. Ce trio couvre la plupart des sessions “pourquoi le GPU est-il plein”.