Auto-héberger LiteLLM comme passerelle LLM
Déployez LiteLLM sur un VPS avec un endpoint OpenAI compatible, des clés virtuelles, des budgets par clé, des fallbacks et des images Docker figées.
Ce que fait une passerelle LLM auto-hébergée
LiteLLM est une passerelle LLM open source que vous hébergez vous-même : un endpoint HTTP unique que toutes vos applications utilisent, puis qui transmet chaque requête au fournisseur chargé d’y répondre. LLM signifie « grand modèle de langage ». La passerelle utilise l’API de chat completions d’OpenAI (interface de programmation applicative). Toute bibliothèque cliente qui communique déjà avec OpenAI fonctionne donc avec elle après deux modifications : l’URL de base et la clé.
Cette couche d’indirection est l’objectif principal. Vos applications ne contiennent plus les identifiants des fournisseurs. Pour changer de modèle, une seule ligne du fichier de configuration sur le serveur suffit, au lieu de modifier le code de cinq services. Comme chaque appel passe par un seul processus, vous disposez aussi d’un emplacement pour définir un budget et conserver un relevé des dépenses.
Une fois le service démarré, vous disposez des éléments suivants :
- Un endpoint unique. Les applications utilisent
https://gateway.example.com/v1et demandent un nom de modèle que vous avez choisi, commebulkoustrong. - Des clés virtuelles. Chaque application reçoit sa propre clé, avec sa propre liste de modèles autorisés et son propre plafond de dépenses. Vous pouvez en révoquer une sans modifier les autres.
- Des solutions de repli. Un appel en échec ou un prompt trop volumineux est automatiquement relancé avec un autre modèle.
- Un relevé journalisé. Chaque requête écrit une ligne contenant son coût. Vous pouvez donc savoir quelle application a engagé chaque dépense.
Pourquoi exécuter vous-même la gateway
Un routeur managé a la même architecture, mais le processus d’un tiers s’interpose dans chaque requête. En l’exécutant vous-même, vous conservez les clés de votre fournisseur et le texte de vos prompts sur une machine que vous contrôlez. Le coût est réel : vous devez désormais exploiter le composant dont dépend chaque application. La dernière section de ce guide traite de ce coût, car c’est généralement la partie omise par les autres guides.
Ce dont vous avez besoin
- Un VPS (serveur privé virtuel) sous Ubuntu 24.04, avec Docker et le plugin Compose installés.
- Un nom de domaine qui pointe vers ce serveur, si des machines externes accèdent à la gateway en TLS (transport layer security).
- Au moins une clé d’API d’un provider.
La gateway n’effectue aucune inférence. Elle transmet les requêtes et renvoie les réponses en streaming. Sa charge CPU dépend donc du volume de requêtes, et non de la taille du modèle. Une machine avec 1 vCPU peut faire fonctionner sans problème quelques applications internes. En revanche, la base de données augmente, car la gateway écrit une ligne de dépense pour chaque requête.
Écrivez d’abord config.yaml
Le fichier de configuration détermine les modèles qu’un client peut demander. Quatre sections de premier niveau sont importantes : model_list, litellm_settings, router_settings et general_settings.
model_list:
- model_name: bulk
litellm_params:
model: anthropic/claude-haiku-4-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: strong
litellm_params:
model: anthropic/claude-sonnet-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: strong
litellm_params:
model: openai/gpt-5.5
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
num_retries: 2
request_timeout: 120
json_logs: true
set_verbose: false
router_settings:
allowed_fails: 3
cooldown_time: 30
fallbacks: [{"bulk": ["strong"]}]
context_window_fallbacks: [{"bulk": ["strong"]}]
general_settings:
background_health_checks: true
health_check_interval: 300model_name est le nom que vos clients envoient. litellm_params.model est le modèle réel, écrit sous la forme provider/model. Nommez vos modèles selon leur fonction plutôt que selon leur fournisseur. Une application qui demande bulk continue de fonctionner si vous décidez le mois prochain que bulk doit utiliser un autre modèle.
api_key: os.environ/ANTHROPIC_API_KEY indique à LiteLLM de lire cette variable au moment de l’exécution. La clé littérale n’apparaît jamais dans le fichier, ce qui est important puisque config.yaml est le fichier que vous committez.
Deux entrées portent volontairement le même nom strong. Lorsque plusieurs déploiements utilisent le même model_name, le routeur les considère comme interchangeables et répartit les requêtes portant ce nom entre eux. C’est ainsi que strong continue de fonctionner lorsqu’un fournisseur rencontre une difficulté temporaire : dès qu’un déploiement passe en cooldown (voir ci-dessous), les nouvelles requêtes pour strong sont envoyées à l’autre.
num_retries: 2 réessaie une erreur réessayable jusqu’à deux fois. Ces nouvelles tentatives peuvent sélectionner un autre déploiement disponible dans le même groupe de modèles : la documentation d’architecture de LiteLLM, vérifiée le 2026-10-29, décrit les nouvelles tentatives au sein du groupe et les fallbacks entre groupes comme deux étapes distinctes. Une nouvelle tentative pour strong peut donc aboutir chez l’autre fournisseur sans activer le failover pondéré. Un fallback ne s’applique qu’une fois ces nouvelles tentatives épuisées.
allowed_fails et cooldown_time sont des options du routeur ; elles se trouvent donc sous router_settings. Le proxy construit son routeur à partir de cette section et, dans v1.95.0, un cooldown_time placé sous litellm_settings ne lui parvient jamais. Les cooldowns restent alors silencieusement à la valeur par défaut de 5 secondes. cooldown_time: 30 définit la durée pendant laquelle un déploiement reste exclu de la rotation après son passage en cooldown. La référence de configuration décrit allowed_fails comme le nombre d’échecs qu’un déploiement doit dépasser dans cooldown_time avant de passer en cooldown. Dans le code source de v1.95.0, allowed_fails: 3 est la valeur par défaut. Avec cette valeur, le routeur conserve les déclencheurs intégrés ; le nombre d’échecs ne prend effet que si vous définissez une autre valeur. Ces déclencheurs incluent un cooldown immédiat après une réponse 429 pour un groupe comportant plusieurs déploiements, plus de 50 % d’échecs pendant la minute en cours après au moins 5 requêtes pour un tel groupe, ainsi que les erreurs que le routeur ne réessaie pas, comme une réponse 401 due à une clé incorrecte. Un autre déclencheur place également un déploiement unique en cooldown lorsque toutes les requêtes de la minute en cours échouent et que le trafic atteint SINGLE_DEPLOYMENT_TRAFFIC_FAILURE_THRESHOLD, qui vaut 1000 requêtes par défaut. Un fournisseur qui renvoie des réponses 500 en rafale cesse d’être sollicité à chaque requête, tandis qu’une réponse 500 isolée toutes les quelques minutes ne déclenche jamais le cooldown.
fallbacks et context_window_fallbacks ont des déclencheurs différents, et le second est celui qui s’avère utile mais que beaucoup de personnes ignorent.
fallbacksse déclenche lorsque l’appel principal échoue.context_window_fallbacksse déclenche lorsque le fournisseur rejette la requête parce qu’elle dépasse la fenêtre de contexte de ce modèle. Une invite trop longue est alors envoyée à un modèle qui peut la traiter, au lieu de renvoyer une erreur à l’appelant.
Il existe également content_policy_fallbacks, pour le cas où un fournisseur refuse une requête pour des raisons de politique de contenu. Définissez-le uniquement si vous disposez d’une destination appropriée pour ces appels.
Déployer LiteLLM sur un VPS avec Docker Compose
Créez un répertoire contenant trois fichiers : config.yaml, docker-compose.yml et .env. Le guide de démarrage rapide en amont utilise le tag latest. Épinglez plutôt un tag de release afin que docker compose up -d le mois prochain vous donne la même gateway qu’aujourd’hui et qu’un rollback tienne sur une seule ligne.
services:
litellm:
image: ghcr.io/berriai/litellm:v1.95.0
restart: unless-stopped
command: ["--config", "/app/config.yaml", "--num_workers", "1"]
ports:
- "127.0.0.1:4000:4000"
volumes:
- ./config.yaml:/app/config.yaml:ro
env_file: .env
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: litellm
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
POSTGRES_DB: litellm
healthcheck:
test: ["CMD-SHELL", "pg_isready -U litellm"]
interval: 5s
timeout: 5s
retries: 10
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Compose lit .env deux fois ici. Une première fois pour remplacer ${POSTGRES_PASSWORD} directement dans le fichier Compose, et une seconde fois via env_file pour transmettre toutes les variables au conteneur.
v1.95.0 était la release courante en août 2026. Consultez la page des releases du projet et utilisez la version courante au moment du déploiement. Chaque release publie une signature. Vous pouvez donc vérifier l’image avant de lui faire confiance :
cosign verify --key https://raw.githubusercontent.com/BerriAI/litellm/v1.95.0/cosign.pub ghcr.io/berriai/litellm:v1.95.0La ligne de port est 127.0.0.1:4000:4000. Elle publie le port sur l’interface loopback uniquement. Écrivez plutôt 4000:4000 : votre gateway sera alors accessible depuis tout Internet, car Docker ajoute ses propres règles dans la chaîne FORWARD d’iptables et celles-ci sont évaluées avant les règles d’ufw. Par conséquent, ufw deny 4000 ne bloque pas cet accès. C’est la cause la plus fréquente d’exposition d’une gateway auto-hébergée : voir comment Docker publie directement un port de conteneur en contournant ufw. Le trafic externe arrive ensuite via le reverse proxy.
Éviter d’inclure les clés des fournisseurs dans l’image
Le fichier .env contient tous les secrets. Il est transmis comme variable d’environnement au moment de l’exécution. Il n’est donc jamais intégré à l’image et n’est jamais commité.
LITELLM_MASTER_KEY=sk-REPLACE_ME
LITELLM_SALT_KEY=sk-REPLACE_ME_TOO
POSTGRES_PASSWORD=REPLACE_ME_AS_WELL
DATABASE_URL=postgresql://litellm:REPLACE_ME_AS_WELL@db:5432/litellm
STORE_MODEL_IN_DB=True
LITELLM_MODE=PRODUCTION
LITELLM_LOG=ERROR
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-proj-...Générez les deux clés LiteLLM avec une vraie source d’aléa, puis restreignez les permissions du fichier :
printf 'sk-%s\n' "$(openssl rand -hex 32)"
chmod 600 .envLITELLM_MASTER_KEY est l’identifiant d’administration. Il authentifie l’API de gestion et sert de mot de passe pour l’interface d’administration à l’adresse /ui. Aucune application ne doit jamais le détenir.
LITELLM_SALT_KEY chiffre les identifiants des fournisseurs stockés dans la base de données. Définissez-le une seule fois et ne le modifiez plus. Si vous le changez ultérieurement, les identifiants déjà stockés ne pourront plus être déchiffrés. La gateway démarrera normalement, puis chaque appel à ces fournisseurs échouera lors de l’authentification.
STORE_MODEL_IN_DB=True permet d’ajouter et de modifier des modèles depuis l’interface d’administration, sans modifier config.yaml. C’est pratique, mais la source de vérité est alors répartie entre deux emplacements. Décidez lequel fait autorité et notez cette décision à côté de la configuration.
Le raisonnement qui consiste à exclure les clés du fichier de configuration s’applique aussi aux outils que vous fournissez à un agent. Exclure les secrets des fournisseurs des agents IA présente cette approche, et fichiers env et secrets dans Docker Compose en décrit la mise en œuvre.
Démarrez la gateway et surveillez le premier boot :
docker compose up -d
docker compose logs -f litellmVérifier que le service fonctionne réellement
Il existe deux sondes sans authentification et une sonde avec authentification. Elles échouent pour des raisons différentes.
curl -s http://127.0.0.1:4000/health/liveliness
curl -s http://127.0.0.1:4000/health/readiness/health/liveliness ne nécessite aucune authentification et répond "I'm alive!" lorsque le processus fonctionne. /health/readiness ne nécessite pas non plus d’authentification. Il renvoie un objet JSON contenant "status": "healthy" et un champ db, ou renvoie 503 lorsque la base de données est inaccessible. Configurez votre monitoring sur la readiness, car la liveliness reste au vert sur une gateway qui ne peut résoudre aucune virtual key.
La vérification avec authentification est celle qui communique avec les providers :
curl -s http://127.0.0.1:4000/health \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"Elle répond avec les tableaux healthy_endpoints et unhealthy_endpoints. Un modèle présent dans unhealthy_endpoints avec une erreur d’authentification signifie que la clé du provider dans .env est incorrecte ou absente. C’est l’échec que vous devez rechercher maintenant. Comme background_health_checks: true est défini, le proxy exécute automatiquement ces sondes toutes les health_check_interval secondes et /health renvoie le dernier résultat. Le polling de cet endpoint n’envoie donc pas une requête de test à vos providers à chaque appel.
Clés virtuelles et budgets par clé
Chaque application reçoit sa propre clé, créée à partir de la clé maître.
curl -s http://127.0.0.1:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H 'Content-Type: application/json' \
-d '{
"key_alias": "nightly-summariser",
"models": ["bulk"],
"max_budget": 5,
"budget_duration": "30d",
"rpm_limit": 60,
"tpm_limit": 200000
}'La réponse contient un champ key qui commence par sk-. Cette chaîne est celle que reçoit l’application. C’est la seule information qu’elle reçoit.
modelsest une liste d’autorisation qui définit les requêtes que cette clé peut effectuer. La clé ci-dessus peut demanderbulk, et rien d’autre.max_budget: 5avecbudget_duration: "30d"correspond à cinq dollars américains par mois civil. LiteLLM réinitialise le budget30dle 1er de chaque mois à minuit, en UTC, sauf si vous définisseztimezonesouslitellm_settings. Il ne s’agit pas d’une période glissante de 30 jours. Une fois que la clé a dépensé cinq dollars, elle cesse donc de fonctionner jusqu’au 1er du mois suivant.rpm_limitettpm_limitlimitent respectivement les requêtes par minute et les tokens par minute pour cette seule clé.key_aliasest le nom que vous reconnaîtrez dans le journal des dépenses six semaines plus tard. Définissez-le toujours.
Lorsque le budget est épuisé, l’appel échoue avec une erreur de type budget_exceeded et un message de cette forme :
Budget has been exceeded! Key=<key> Current cost: <spend>, Max budget: <max_budget>Le code de statut dépend de la release. Dans la v1.95.0 utilisée ici, il s’agit de HTTP 429. À partir de la v1.104.0, la valeur par défaut est HTTP 422. La définition de budget_exceeded_status_code: 429 sous litellm_settings rétablit l’ancien code. Les dépassements réels de rpm_limit et tpm_limit renvoient toujours 429 dans les deux releases. Vérifiez le code obtenu après chaque mise à niveau.
Le code de statut est à l’origine de la confusion, car aucun des deux codes n’indique « budget ». Une bibliothèque cliente interprète 429 comme une limite de débit et peut réessayer avec un backoff alors que le budget ne sera pas rétabli avant la réinitialisation. Elle interprète 422 comme une requête qui n’a pas pu être traitée. Journalisez le corps de la réponse avec le code de statut. Sinon, l’épuisement du budget semblera toujours correspondre à un autre problème.
Inspectez et modifiez les clés via la même API de gestion :
curl -s "http://127.0.0.1:4000/key/info?key=sk-..." \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
curl -s -X POST http://127.0.0.1:4000/key/update \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H 'Content-Type: application/json' \
-d '{"key": "sk-...", "max_budget": 25}'Un budget appliqué au niveau de la gateway reste effectif même lorsque le problème vient de l’agent lui-même. C’est pourquoi il constitue la base du contrôle des coûts des agents IA sur un VPS.
Envoyer les traitements en volume vers un modèle économique
Configurez le client pour utiliser la gateway. Indiquez l’URL de base, la clé et le nom du modèle :
curl -s http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-<the virtual key>" \
-H 'Content-Type: application/json' \
-d '{
"model": "bulk",
"messages": [{"role": "user", "content": "Say hello in five words."}]
}'Toutes les bibliothèques clientes OpenAI fonctionnent de la même manière : définissez base_url sur https://gateway.example.com/v1 et api_key sur la clé virtuelle.
La politique de routage de config.yaml s’applique désormais sans que l’appelant le sache. Une requête pour bulk est envoyée vers le modèle économique. Si cet appel échoue après ses nouvelles tentatives, la requête est réessayée avec strong. Si le prompt est trop long pour bulk, context_window_fallbacks l’envoie vers strong au lieu de renvoyer une erreur. Les traitements en volume, comme une passe de classification ou la synthèse d’un backlog, utilisent par défaut le modèle économique. Seules les requêtes complexes coûtent davantage.
C’est également dans ce cas qu’une gateway est utile avec des agents qui utilisent des outils. Un serveur MCP (model context protocol) sur le même VPS et l’agent qui le pilote peuvent tous deux utiliser un seul endpoint. Le modèle utilisé peut ainsi changer sans redéployer aucun des deux.
Comment savoir qu’un fallback s’est produit ?
C’est le mode de défaillance qui coûte de l’argent, car rien ne semble cassé. Un fallback réussi renvoie HTTP 200 avec un corps de réponse ordinaire. Votre modèle économique peut être indisponible pendant une journée, chaque appel étant discrètement traité par le modèle plus coûteux, et le premier indice sera la facture.
Les éléments de preuve se trouvent bien dans les en-têtes de réponse. Demandez-les :
curl -s -D - -o /dev/null http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-<the virtual key>" \
-H 'Content-Type: application/json' \
-d '{"model":"bulk","messages":[{"role":"user","content":"ping"}]}' \
| grep -i '^x-litellm'x-litellm-model-groupest le nom du modèle vers lequel la requête a été routée, par exemplebulk.x-litellm-model-idest l’ID du déploiement qui a répondu. Vous pouvez le rechercher avec/v1/model/info?litellm_model_id=.... Si cet ID ne correspond à aucun de vos déploiementsbulk, un fallback s’est produit.x-litellm-attempted-fallbacksetx-litellm-attempted-retriesles comptabilisent. Pour un appel sain, aucun des deux ne doit afficher un nombre supérieur à 0.x-litellm-response-costest le coût de cet appel en dollars américains.x-litellm-call-idest l’identifiant qui permet de retrouver le même appel dans vos journaux.
Enregistrez x-litellm-attempted-fallbacks pour chaque requête et déclenchez une alerte dès que sa valeur est supérieure à 0. Ce nombre fait la différence entre une stratégie de routage qui fonctionne et une stratégie qui est devenue silencieusement « toujours utiliser le modèle le plus coûteux ».
La version complète repose sur le tracing, qui mérite sa propre configuration : Langfuse auto-hébergé pour le tracing des appels d’agents. LiteLLM fournit le callback. Sa configuration se résume donc à deux lignes et aux identifiants d’accès.
litellm_settings:
success_callback: ["langfuse"]
failure_callback: ["langfuse"]LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=https://langfuse.example.comPour Langfuse v3 et les versions ultérieures, la page Langfuse de LiteLLM recommande désormais son preset langfuse_otel ; le callback langfuse ci-dessus reste documenté. Définissez aussi failure_callback et success_callback. Si vous l’omettez, vous ne conserverez que les traces des appels qui se sont déroulés sans problème. Indépendamment de cela, LiteLLM écrit une ligne de consommation par requête dans Postgres, et l’interface d’administration à /ui lit cette table. Elle grossit avec le trafic : surveillez donc l’espace disponible sur un petit disque.
Placez la passerelle derrière un reverse proxy
Rien en dehors du serveur ne doit pouvoir accéder au port 4000. Terminez TLS dans nginx ou Caddy, puis transmettez les requêtes à l’adresse loopback.
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 600s;
}Ce sont deux des lignes que l’on oublie souvent. proxy_buffering off est important, car une réponse streaming est une série de server-sent events. Lorsque le buffering est activé, nginx accumule les fragments dans des buffers avant de les transmettre, ce qui retarde leur réception par le client. proxy_read_timeout 600s est important, car la valeur par défaut de 60 secondes dans nginx correspond au délai maximal entre deux lectures effectuées auprès de la passerelle, et non à une limite sur la durée totale de la réponse. Une réponse sans streaming n’envoie rien tant que la génération n’est pas terminée. Une génération longue dépasse donc 60 secondes sans recevoir un seul octet, et le client reçoit une erreur 504 tandis que le journal d’erreurs enregistre upstream timed out (110: Connection timed out) while reading response header from upstream. Une réponse streaming qui continue d’envoyer des fragments peut durer bien plus de 60 secondes. Le timeout ne se déclenche que si le modèle reste silencieux pendant cette durée.
Pour le certificat, Certbot avec Let's Encrypt sur nginx est la méthode la plus directe. Si le serveur héberge déjà plusieurs conteneurs, Traefik devant plusieurs applications Compose gère le routage et les certificats au même endroit.
La passerelle est désormais un point de défaillance unique
Soyez honnête sur ce que vous avez déployé. Chaque application dont vous avez la charge dépend désormais d’un seul conteneur sur un seul VPS. Tant qu’il est indisponible, rien ne peut appeler le moindre modèle, y compris les providers qui fonctionnent parfaitement. Quatre conséquences en découlent.
- Une mauvaise configuration met tout hors service d’un coup.
restart: unless-stoppedredémarre un processus qui s’est arrêté brutalement, y compris un conteneur qui ne peut pas analyser config.yaml, et recommence indéfiniment. Consultezdocker compose logs litellmaprès chaque modification de configuration, et effectuez ces modifications lorsque vous avez le temps de les surveiller. - Postgres se trouve sur le chemin des requêtes en cas de cache miss. La recherche de clé virtuelle l’utilise lorsque la clé n’est pas en cache ; l’enregistrement des dépenses s’effectue de manière asynchrone après la réponse. Le retour de
/health/readinessavec le code 503 vous avertit que la passerelle fonctionne, mais qu’elle ne peut faire ni l’un ni l’autre. - Utilisez d’abord les cœurs, puis ajoutez des instances. La recommandation de production du projet, à savoir un worker par instance (
--num_workers 1), concerne Kubernetes ou un autre autoscaler de pods qui ajoute les instances à votre place. Pour une VM unique ou un conteneur autonome comme celui-ci, elle indique l’inverse : définissez le nombre de workers sur le nombre de vCPU de la machine. Sur la machine à 1 vCPU présentée plus haut, cela reste--num_workers 1; sur une machine plus puissante, augmentez cette valeur, en gardant à l’esprit que chaque worker utilise sa propre mémoire. Une deuxième passerelle derrière un load balancer retire le conteneur unique de l’équation. Elle ne supprime pas la base de données. - Sauvegardez ce que vous ne pouvez pas recréer. Il s’agit de
config.yamlet.env, ainsi que d’unpg_dumpde la base de données. La perte deLITELLM_SALT_KEYrend inutilisables les identifiants chiffrés des providers contenus dans ce dump. Le fichier d’environnement et le dump doivent donc être inclus dans le même job de sauvegarde : sauvegardes restic vers un stockage externe.
La mise à niveau consiste à modifier le tag de l’image et à exécuter docker compose up -d. LiteLLM exécute prisma migrate deploy au démarrage par défaut. Le nouveau conteneur migre donc le schéma de la base de données lors de son premier démarrage. Effectuez le dump avant de modifier le tag, car remettre l’ancienne image ne permet pas d’annuler une migration déjà exécutée.
Lisez les notes de version de chaque version ignorée, et pas seulement celles de la version installée. Le passage de v1.95.0 à v1.104.0 ou une version ultérieure franchit plusieurs changements incompatibles : le code d’état du budget mentionné plus haut, une proxy qui refuse de démarrer si la clé maître est non définie, vide ou connue publiquement, et une proxy qui s’arrête lorsque l’initialisation de la base de données échoue au démarrage, ce qui apparaît comme une boucle de redémarrage avec restart: unless-stopped. Si vous venez de v1.102.x ou d’une version antérieure, les notes de v1.104.0 vous demandent également de créer vous-même deux index LiteLLM_SpendLogs.
FAQ
LiteLLM ajoute-t-il une latence perceptible à chaque appel ?
Le projet annonce 8 ms au 95e percentile pour 1000 requêtes par seconde, comme indiqué dans son README en octobre 2026. Considérez cette valeur comme une donnée du fournisseur. Le facteur qui modifie réellement votre latence est la distance réseau entre vos applications et la gateway, car vous ajoutez un aller-retour réseau à chaque appel. Exécutez la gateway dans la même région que les applications qui l’appellent, puis mesurez votre propre surcharge avec l’en-tête x-litellm-overhead-duration-ms sur une réponse réelle.
Pourquoi le streaming a-t-il cessé de fonctionner après avoir placé nginx devant la gateway ?
Parce que nginx met en buffer les réponses upstream par défaut et qu’une réponse en streaming est une série de server-sent events. Lorsque proxy_buffering est activé, nginx collecte les chunks dans des buffers avant de les transmettre, ce qui retarde leur livraison au client. Définissez proxy_buffering off; dans le bloc location. Augmentez également proxy_read_timeout dans ce même bloc. Par défaut, nginx abandonne après 60 secondes sans données de la gateway, délai qu’une génération longue sans streaming atteint facilement ; le client reçoit alors une erreur 504.
Que se passe-t-il lorsqu’une virtual key n’a plus de budget ?
L’appel échoue avec une erreur de type budget_exceeded et un message de la forme Budget has been exceeded! Key=<key> Current cost: <spend>, Max budget: <max_budget>. Dans la version v1.95.0 verrouillée, le statut est HTTP 429 ; à partir de v1.104.0, la valeur par défaut est HTTP 422. Aucun de ces codes n’indique le budget, ce qui constitue le piège : une bibliothèque cliente interprète 429 comme une limite de débit et peut effectuer une nouvelle tentative. Les utilisateurs cherchent alors un problème de throttling au lieu de lire le message. Journalisez le corps de la réponse avec le code de statut. Vérifiez la position réelle de la key avec /key/info?key=sk-... en utilisant la master key, puis augmentez le plafond avec /key/update si le budget a été défini trop bas.
La gateway peut-elle router vers un modèle local en plus des modèles hébergés ?
Oui. Il s’agit d’une entrée supplémentaire dans model_list. Utilisez le préfixe ollama_chat/ avec un api_base, par exemple model: ollama_chat/llama3.1 avec api_base: http://ollama:11434. Avec le réseau par défaut de Compose, localhost dans un conteneur désigne ce conteneur. Utilisez donc le nom du service Compose ou l’adresse de l’hôte sur le réseau Docker, jamais 127.0.0.1. Le host networking, dans lequel le conteneur partage la stack réseau de l’hôte, constitue l’exception. La mise en service du modèle local est une tâche distincte : consultez auto-héberger un LLM avec Ollama sur un VPS.