Démarrage rapide du sélecteur de modèles llama.swap pour les LLM locaux compatibles OpenAI

Échange à chaud des LLM locaux sans modifier les clients.

Sommaire

Vous voilà bientôt à jongler avec vLLM, llama.cpp et d’autres composants — chaque pile sur son propre port. Tout en aval exige toujours une URL de base /v1 unique ; sinon, vous continuez à jongler avec des ports, des profils et des scripts spécifiques. llama-swap est le proxy /v1 situé devant ces piles.

llama-swap fournit une seule interface frontale compatible OpenAI et Anthropic, avec un fichier YAML qui associe chaque nom de model à la commande qui démarre le bon serveur amont. Réclamez un modèle et le proxy le démarre ou bascule vers lui ; configurez les TTLs et les groupes lorsque la VRAM est limitée ou lorsque plusieurs modèles doivent coexister. Ce guide couvre les chemins d’installation, un config.yaml pratique, la surface HTTP et les modes de défaillance qui apparaissent lorsque le streaming et les proxies inversés entrent en jeu.

llama swap llm infographic Pour une comparaison plus large des options d’hébergement de LLM, consultez Hébergement de LLM en 2026 : Local, Auto-hébergé et Infrastructure Cloud comparés

Vue d’ensemble du commutateur de modèles llama-swap pour les API locales compatibles OpenAI

llama-swap est un serveur proxy léger construit autour d’un modèle opérationnel simple : un seul binaire, un seul 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 de runtime Python ou d’application de bureau requise. Il se situe devant n’importe quel amont compatible OpenAI et Anthropic en tant que couche de bascule de modèles.

Conceptuellement, cela répond à une question très pratique qui se pose dans les piles de LLM locaux :

Comment basculer entre les modèles avec un client compatible OpenAI ?
Avec llama-swap, vous continuez à utiliser des requêtes normales /v1/..., mais vous changez le model que vous réclamez. llama-swap lit cette valeur model, charge la configuration de serveur correspondante et, si l’amont « incorrect » est en cours d’exécution, il le remplace par le bon.

Quelques détails de conception importent pour les configurations quasi de production :

llama-swap est sous licence MIT sans télémétrie — il reste toutefois utile de le vérifier 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 seul moteur d’inférence. Par défaut (sans regroupement spécial), il exécute un modèle à la fois : réclamez un autre model et il arrête l’amont actuel et démarre 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[Votre application ou SDK\nClient compatible OpenAI] -->|/v1/chat/completions\nmodel = qwen-coder| LS[Proxy llama-swap\npoint de terminaison unique] LS -->|démarre ou achemine vers| U1[Serveur amont A\nllama-server] LS -->|démarre ou achemine vers| U2[Serveur amont B\nserveur OpenAI vLLM] LS --> M[Points de terminaison de gestion\nrunning, unload, events, metrics]

C’est aussi pourquoi un proxy de commutateur de modèles est différent de « simplement exécuter un modèle » : c’est une orchestration et une achemination 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 donner une « API LLM locale », mais elles optimisent pour des flux de travail différents. La façon la plus rapide de choisir est de décider si vous voulez un runtime (téléchargement de modèles + exécution) ou un routeur/proxy (bascule + 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 qui achemine les requêtes vers le bon amont 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 sur /ui.

Ollama
Ollama expose sa propre API HTTP (POST /api/chat, POST /api/generate et le port local par défaut habituel 11434). keep_alive contrôle la durée pendant laquelle un modèle reste chargé, y compris 0 pour le décharger immédiatement. Il convient aux utilisateurs qui souhaitent télécharger un modèle et discuter avec un câblage minimal. llama-swap convient aux commandes par modèle, aux backends mixtes et à une seule URL de forme OpenAI pour chaque client — orchestrer vLLM à côté de llama-server avec différents drapeaux par modèle dépasse ce à quoi Ollama est destiné.

LM Studio
LM Studio est une application de bureau avec un serveur API local à partir de l’onglet Developer (localhost ou LAN), incluant des modes compatibles OpenAI et compatibles Anthropic, ainsi que lms server start depuis le terminal. Il convient à une boucle centrée sur l’interface graphique : parcourir les modèles, cliquer, tester. llama-swap convient à un rôle de type serveur : YAML, supervision de processus, amonts mixtes, 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 lui via base_url. L’installation de ce serveur et des drapeaux qu’il prend réellement en charge est couverte dans le démarrage rapide llama.cpp. llama.cpp embarque également un mode routeur : exécutez llama-server en tant que 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 de configuration complet, consultez Mode routeur llama-server : bascule dynamique de modèles sans redémarrage. Si tous les modèles se trouvent sous un seul routeur llama.cpp, un proxy supplémentaire est souvent inutile. Lorsque llama.cpp doit se trouver à côté de vLLM ou d’autres serveurs de forme OpenAI, llama-swap fournit une seule surface /v1 et de nombreux processus derrière elle.

Pour des solutions d’hébergement compatibles OpenAI similaires, consultez Démarrage rapide LocalAI : Exécutez des LLM compatibles OpenAI localement ou Démarrage rapide SGLang : Installation, configuration et service de LLM via l’API OpenAI

Installer le commutateur de modèles llama-swap avec Docker, Homebrew, WinGet ou des binaires

Linux, macOS et Windows sont tous pris en charge de première classe : Docker, Homebrew, WinGet, binaires GitHub ou construction depuis le source. Choix courants : Docker sur les serveurs sans interface graphique, Homebrew ou WinGet sur les postes de travail, binaires autonomes lorsque l’empreinte d’installation doit rester minimale.

Installation Docker

Téléchargez une image correspondant à votre matériel. Les images suivent de près les amonts (constructions nocturnes) et couvrent CUDA, Vulkan, Intel, MUSA et CPU — choisissez celle qui correspond à la manière dont vous accélérez réellement, et non « latest » par habitude.

# Exemple de téléchargements de plateformes
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 : il y a moins de choses à regretter si la frontière du conteneur est incorrecte.

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

Les versions GitHub proposent des binaires Linux, macOS, Windows et FreeBSD si vous ne souhaitez pas utiliser un gestionnaire de paquets. Les numéros de version évoluent rapidement (par exemple v198, v197 au début de 2026) — fixez une version dans l’automatisation plutôt que de laisser flotter « ce qu’il y avait la veille ».

Configurer llama-swap avec config.yaml pour la bascule de modèles, les 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à de « démarrer un processus », et quelques options méritent d’être comprises tôt car elles répondent directement à des problèmes courants de type FAQ (déchargement automatique, sécurité et clients qui reposent 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 (défaut 120s, minimum 15s). Pour les chargements de plusieurs Go sur des disques lents, augmentez cette valeur avant de blâmer le proxy. globalTTL est le nombre de secondes d’inactivité avant le déchargement automatique ; la valeur par défaut 0 signifie « ne jamais décharger » sauf si vous la configurez — choisissez explicitement des TTLs pour toute configuration qui dépasse un jouet afin que la VRAM ne se remplisse pas de modèles oubliés. startPort initialise la macro ${PORT} (défaut 5800) ; l’attribution est deterministe par ID de modèle alphabétique, ce qui est un avantage quand vous dépannez « qui a pris quel port » et un piège si vous renommez les modèles sans précaution. includeAliasesInList décide si les alias apparaissent comme des lignes séparées dans /v1/models ; activez-le si votre interface ne propose que les modèles énumérés. apiKeys régit tout ce qui est accessible depuis l’extérieur de localhost : Basic, Bearer ou x-api-key. llama-swap retire ces en-têtes avant de transmettre, de sorte que les journaux amont sont moins susceptibles de conserver les secrets du client.

Paramètres au niveau du modèle qui débloquent l’ergonomie de production

Par modèle, cmd est le seul champ obligatoire. proxy a par défaut la valeur http://localhost:${PORT} — c’est la cible de transfert pour l’amont de ce modèle. checkEndpoint a par défaut la valeur /health ; définissez "none" lorsque le backend n’a pas de route de santé ou que le démarrage à froid dépasse ce que vous êtes prêt à attendre — ne laissez pas un /health cassé et ne vous demandez pas 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 des TTL par modèle lorsqu’un modèle doit persister et qu’un autre doit disparaître rapidement. aliases et useModelName maintiennent des noms stables côté client tout en satisfaisant les amonts qui exigent un identifiant spécifique. cmdStop est optionnel pour les conteneurs : mappez-le vers docker stop (ou équivalent) ; sans lui, vous obtenez un SIGTERM POSIX / taskkill Windows contre le PID que llama-swap a démarré — correct pour un binaire nu, incorrect pour un nom de conteneur. concurrencyLimit limite les requêtes parallèles par modèle avec HTTP 429 lorsque le plafond est dépassé — définissez-le si vous préférez rejeter la charge plutôt que de mettre en file d’attente indéfiniment.

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 d’abord un groupe afin que le préchargement corresponde à la manière 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 réglages de bonnes pratiques : un TTL par défaut, des vérifications de santé explicites, des alias stables et un groupe qui maintient un petit modèle « toujours actif » en exécution pendant que les grands modèles de chat 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 en 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érite de globalTTL)

  qwen-coder:
    cmd: |
      llama-server --port ${PORT} --model /models/qwen-coder.gguf
      --ctx-size 8192
    aliases:
      - "qwen-coder-latest"

  vllm-coder:
    # Schéma 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                 # ne jamais décharger automatiquement (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"]

Rien de tout cela n’est décoratif : cmd pilote le processus, proxy/checkEndpoint/ttl contrôlent l’acheminement et le cycle de vie, cmdStop est ce qui permet aux amonts basés sur Docker de s’arrêter réellement, et groups sont ce qui sépare « un grand modèle à la fois » de « ces deux modèles de chat peuvent coexister pendant que le serveur d’embedding reste épinglé ».

Exécuter et basculer les modèles via les points de terminaison compatibles OpenAI

Une fois llama-swap en cours d’exécution, vous interagissez avec lui comme avec tout autre point de terminaison compatible OpenAI. La surface API comprend des points de terminaison de base tels que /v1/chat/completions, /v1/completions, /v1/embeddings et /v1/models, et llama-swap utilise le model demandé pour décider quel amont exécuter et vers lequel acheminer.

Un flux de démarrage 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 fonction de gestion de premier ordre et inclut des comportements tels que le tri par ID, l’exclusion des modèles unlisted et l’inclusion facultative des alias.

# 3) Effectuer 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 permet leur coexistence) car il extrait le modèle demandé de la requête et charge la configuration de serveur appropriée.

Si vous utilisez un SDK, pointez le client vers http://localhost:8080/v1 — même ruse que de pointer la bibliothèque Python OpenAI vers llama-server, à la différence que l’URL stable est maintenant llama-swap et que le champ model choisit 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 préchauffer un modèle avant la première vraie requête (masquer la latence de démarrage à froid), utilisez /upstream/<model> — il charge automatiquement si nécessaire et transfère directement vers cet amont. Une 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 est en cours d’exécution
GET /running renvoie l’état d’exécution des modèles chargés, y compris des valeurs d’état telles que ready, starting, stopping, stopped et shutdown.

curl http://localhost:8080/running

Décharger les modèles pour libérer la VRAM
Pour tout décharger immédiatement, utilisez le point de terminaison avec version d’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 legacy existe pour la rétrocompatibilité.

# 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, basculages de modèles rapides ou après le chargement d’un point de contrôle beaucoup plus grand que prévu.

Diffuser des é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 comptes de requêtes en cours.

curl -N http://localhost:8080/api/events

Le SSE et le streaming de jetons cassent lorsque n’importe quelle boîte intermédiaire met en tampon — désactivez la mise en tampon sur nginx (ou votre équivalent) pour /api/events et /v1/chat/completions. llama-swap définit X-Accel-Buffering: no sur le SSE ; désactivez la mise en tampon 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 renvoie les métriques d’utilisation des jetons, avec une rétention en mémoire contrôlée par metricsMaxInMemory (défaut 1000). GET /api/captures/<id> peut récupérer les 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 la surveillance en temps réel.

Interface Web llama-swap pour basculer les modèles

Si vous activez apiKeys, supposez une défense en profondeur : /health et certaines parties de /ui restent accessibles sans clé — correct pour les frontières de confiance locales, incorrect si l’hôte est sur un réseau partagé. Placez llama-swap derrière quelque chose qui impose votre véritable politique ; l’authentification intégrée sert à garder les clients occasionnels honnêtes, pas pour une API publique multi-locataires.

Dépanner la bascule 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 inverse, vérifications de santé lors des démarrages à froid, ports et cycle de vie des processus, et authentification.

Le streaming casse derrière nginx ou un autre proxy inverse
nginx mettra volontiers en tampon vos SSE et complétions en streaming. Désactivez proxy_buffering (et proxy_cache) pour /api/events et /v1/chat/completions. llama-swap émet X-Accel-Buffering: no sur le 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 renvoyer 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 complètement les vérifications de santé. Si les grands modèles mettent plus de temps à charger, augmentez healthCheckTimeout (défaut 120s), ou utilisez des vérifications de santé adaptées à votre amont spécifique.

La bascule 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 enveloppe pendant que le conteneur continue de mâcher 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 exige une clé valide et accepte trois méthodes (auth Basic, jeton Bearer, x-api-key). Il retire également les en-têtes d’authentification avant la transmission amont.

Je reçois des erreurs 429 Trop de requêtes
concurrencyLimit renvoie 429 lorsque le plafond est dépassé — par conception. Augmentez le plafond si vous l’avez sous-dimensionné, ou baissez la limite si vous ne vouliez pas de limitation.

Conflits de ports ou problèmes d’acheminement étranges
Évitez les ports codés en dur dans cmd ; utilisez ${PORT} et déplacez startPort si 5800+ entre en collision avec autre chose. N’oubliez pas que les ports sont attribués dans l’ordre alphabétique par ID de modèle — renommez un modèle et le mappage de port change.

Liste de contrôle du 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 ».

S'abonner

Recevez de nouveaux articles sur les systèmes, l'infrastructure et l'ingénierie IA.