[!NOTE] Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.
Guide LoRAX Serving : Gestion de plusieurs LoRA adaptateurs sur Kubernetes
Un modèle de base et de nombreux adaptateurs LoRA créent un problème d’orchestration serving particulier. Les poids de base sont partagés, mais chaque requête peut nécessiter un ensemble distinct de poids d’adaptateur. Une approche classique consistant à déployer une version différente pour chaque variant gaspille de la mémoire GPU, car la plupart de ces variants restent inactifs.
LoRAX Il cible cette partie du spectre d’usage peu fréquentée. Il charge les adaptateurs sur demande, groupe les requêtes destinées à des adaptateurs différents, et transfère les poids des adaptateurs entre la mémoire GPU et CPU. L’argument publicitaire attrayant est celui de « milliers de modèles affinés sur une seule GPU ». La question technique est plus précise : votre ensemble d’adaptateurs actifs, le rythme d’arrivée des données et l’objectif de latence bénéficient-ils suffisamment d’un planification des échanges pour justifier l’utilisation d’un autre serving runtime ?
Ce guide répond à cette question, vérifie localement le API, puis transforme le diagramme Helm de démarrage du répertoire en un plan de déploiement en production explicite.
En résumé. Préférez LoRAX lorsque de nombreux adaptateurs compatibles LoRA partagent un même modèle de base et que le trafic est faible ou à distribution allongée. La capacité dépend du ensemble de données actif en traitement, et non de la taille du catalogue. Fixez les runtime, authentifiez et ajoutez les ID des adaptateurs à une liste blanche, implémentez un stockage en cache fiable ainsi que des sondes, orientez le routage vers la localité en mémoire, et gérez séparément les chemins de traitement pour les données froides et chaudes benchmark.
Le problème serving correspond au ensemble en cours d’utilisation
LoRA permet de figer un modèle de base et d’apprendre des mises à jour à rang faible pour des matrices de poids spécifiques. L’adaptateur ainsi obtenu est généralement bien plus petit qu’un checkpoint complet, mais sa taille dépend néanmoins du rang, des modules cibles, du nombre de couches et du type de données. Des affirmations absolues du type « chaque adaptateur pèse 100 Mo » constituent de mauvaises indications quant à sa capacité réelle.
Pour serving, il convient de distinguer trois grandeurs :
- Taille du catalogue : tous les adaptateurs que une plateforme peut récupérer depuis le stockage
- Ensemble de travail actif : les adaptateurs qui reçoivent des requêtes pendant la fenêtre de conservation en mémoire cache
- Ensemble concurrent : les adaptateurs représentés par lots au même instant
Un catalogue peut contenir des milliers d’adaptateurs sans pour autant occuper VRAM de mémoire. Ce qui importe, c’est la fréquence à laquelle l’ensemble actif évolue, la taille de ces adaptateurs, ainsi que la possibilité pour les requêtes visant des adaptateurs différents d’utiliser des lots communs utiles.
LoRAX combine quatre mécanismes :
- Le modèle de base reste en mémoire pour l’ensemble des adaptateurs compatibles.
- Une requête spécifie un adaptateur, que l’on peut identifier à partir de Hugging Face, de Predibase ou d’un système de fichiers.
- Le planificateur d’échange d’adaptateurs précharge et déplace les poids entre la mémoire GPU et la mémoire CPU.
- Le regroupement continu hétérogène des requêtes permet de cibler différents adaptateurs.
Le rapport du projet indique que le lotage hétérogène maintient le débit et la latence presque constants à mesure que le nombre d’adaptateurs simultanés augmente dans son benchmarks. Considérez cela comme une hypothèse pour votre charge de travail. La longueur de Prompt, la longueur des résultats, le rang, les modules cibles, le taux d’occupation des lots, le turnover de la mémoire cache, ainsi que la génération de GPU peuvent modifier ce résultat.
Lorsque LoRAX constitue une solution adaptée
LoRAX mérite un benchmark lorsque toutes ces conditions sont remplies :
- Les adaptateurs ont été entraînés en utilisant le même modèle de base pris en charge ainsi que les mêmes contraintes de tokenisation.
- Le trafic est distribué sur de nombreux adaptateurs, présentant une véritable queue longue.
- Il est préférable de charger un adaptateur « froid » sur demande plutôt que d’attribuer une ressource de déploiement spécifique à celui-ci.
- Un mécanisme de routage des utilisateurs ou des tâches existe déjà au niveau de l’application.
- L’équipe peut gérer une inférence spécialisée runtime ainsi que son comportement de mise en cache.
Parmi les cas typiques, on trouve des assistants spécifiques à chaque locataire, de nombreuses variantes par domaine, ainsi que des expériences en ligne qui reposent sur une base commune checkpoint.
La solution est moins adaptée lorsque quelques adaptateurs dominent le trafic, que les modèles ne partagent pas de base commune, que des objectifs de latence stricts ne permettent pas de gérer des charges initiales faibles, ou encore lorsque la plateforme ne peut pas contrôler de manière fiable quels artefacts le serveur charge. Dans de tels cas, une implémentation standard avec vLLM ou TGI, associée à un ensemble d’adaptateurs fixe, peut s’avérer plus simple.
Ne vous contentez pas d’utiliser Kubernetes uniquement parce que le catalogue est volumineux. Prouvez d’abord la compatibilité du runtime ainsi que de l’adaptateur sur un GPU.
Vérifier une base et deux adaptateurs localement
Le README de LoRAX recommande son conteneur prédéfini. Dans un environnement réel, il convient d’utiliser un digest d’image immuable ; main Il est affiché ici uniquement parce qu’il s’agit de la balise de démarrage rapide documentée par le dépôt.
mkdir -p data
docker run --rm --gpus all --shm-size 1g \
-p 8080:80 \
-v "$PWD/data:/data" \
ghcr.io/predibase/lorax:main \
--model-id mistralai/Mistral-7B-Instruct-v0.1
La configuration minimale requise, telle que documentée, est Linux, Docker, une carte graphique NVIDIA d’Ampere ou plus récente GPU, ainsi que des pilotes compatibles avec CUDA 11.8. Les licences des modèles et les dépôts protégés peuvent également nécessiter un jeton Hugging Face.
Commencez par le modèle de base :
curl http://127.0.0.1:8080/generate \
-H 'Content-Type: application/json' \
-d '{
"inputs": "[INST] Give one reason to measure cold-adapter latency. [/INST]",
"parameters": {"max_new_tokens": 64}
}'
Ensuite, envoyez un adaptateur compatible :
curl http://127.0.0.1:8080/generate \
-H 'Content-Type: application/json' \
-d '{
"inputs": "[INST] Solve: Natalia sold 48 clips in April and half as many in May. What is the total? [/INST]",
"parameters": {
"max_new_tokens": 64,
"adapter_id": "vineetsharma/qlora-adapter-Mistral-7B-Instruct-v0.1-gsm8k"
}
}'
La première requête peut télécharger et charger l’adaptateur ; les requêtes ultérieures peuvent utiliser des artefacts en mémoire cache ainsi que des poids résiduels. Enregistrez les deux chemins. Une seule requête de type « warm » ne fournit que peu d’informations sur le comportement lié aux cas rares.
Utilisez le client OpenAI actuel
LoRAX expose une interface de chat compatible avec OpenAI. Le model Le champ identifie l’adaptateur :
from openai import OpenAI
client = OpenAI(
api_key="EMPTY",
base_url="http://127.0.0.1:8080/v1",
)
response = client.chat.completions.create(
model="alignment-handbook/zephyr-7b-dpo-lora",
messages=[
{"role": "user", "content": "Explain cache locality in two sentences."},
],
max_tokens=100,
)
print(response.choices[0].message.content)
Par défaut, le serveur n’a pas besoin de la clé API. Cela est pratique pour les environnements localhost, mais constitue une pratique peu sûre en configuration destinée à être accessible depuis Internet. Il convient donc d’implémenter d’abord la mise en œuvre d’une authentification, d’une autorisation par tenant, de quotas, ainsi que d’une liste blanche d’adaptateurs.
Définir une porte de compatibilité
Avant qu’un adaptateur ne soit ajouté au catalogue, vérifiez au moins :
- modèle de base déclaré et version
- compatibilité du tokeniseur avec les modèles de conversation
- rangs LoRA et modules cibles pris en charge par le runtime
- format des artefacts et formes des tenseurs
- licence, provenance et digest d’intégrité
- un petit ensemble de tests comportementaux et de régression
Rejeter les artefacts incompatibles lors de l’enregistrement, et non à la première demande de l’utilisateur.
Comprendre la résidence avant le déploiement
Le modèle de base consomme la majeure partie fixe de la mémoire GPU. Les poids des adaptateurs, KV cache, l’espace de travail par lot ainsi que les noyaux runtime se disputent le reste. La RAM CPU peut stocker les adaptateurs déplacés en mémoire externe, tandis que /data stocke les artefacts téléchargés.
Il ne s’agit pas de niveaux interchangeables. Un artefact de disque ou de hub doit d’abord être lu et matérialisé avant de devenir un adaptateur résident CPU- ou GPU-. Il convient de mesurer ces transitions séparément :
| Chemin | Ce que cela inclut | |
|---|---|---|
| GPU nombre d’incidents | Adapter les agents déjà résidents | temps d’attente dans la file et temps jusqu’au premier token |
| CPU nombre d’incidents | Transfert ou rematérialisation dans GPU | délai d’adaptation de la charge et latence bout en bout |
| Impact sur l’artefact | Lire depuis le disque local /data cache | délai de lecture/chargement et octets en cache |
| Échec de lancement à distance | Téléchargement, validation supplémentaire et chargement | temps de téléchargement, échecs et latence totale en mode froid |
La planification des capacités doit reproduire la distribution réelle de popularité des adaptateurs. L’utilisation d’identifiants d’adaptateur aléatoires et uniformes engendre un problème de cache différent de celui causé par une charge de travail de type locataire selon la loi de Zipf.
Déployez avec prudence le diagramme du dépôt
Le répertoire contient charts/loraxAinsi, le point de départ reproductible est une révision de dépôt verrouillée ainsi qu’un diagramme local :
git clone https://github.com/predibase/lorax.git
cd lorax
git checkout <reviewed-commit-or-release>
helm dependency update charts/lorax
helm template lorax charts/lorax -f values.production.yaml
helm upgrade --install lorax charts/lorax \
--namespace inference \
--create-namespace \
-f values.production.yaml
Comme cela a été examiné le 15 juillet 2026, les paramètres par défaut du graphique méritent une attention particulière :
- l’attribut image est
latest /dataest unemptyDir, ce qui entraîne le retrait des artefacts téléchargés lors du remplacement du pod- Les sondes de vitalité et de disponibilité sont vides
- Le token Hugging Face est modélisé comme une valeur d’environnement littérale
- Un GPU est demandé par défaut
Cela fait de ce diagramme un cadre utile, et non une politique de production.
Partir de la structure de valeurs réelle du graphique
Le diagramme hiérarchise la configuration runtime en dessous de deploymentLes arguments du lanceur constituent une liste de paires nom/valeur. Une superposition minimale ressemble à ceci :
deployment:
replicas: 1
image:
repository: ghcr.io/predibase/lorax
tag: "<tested-tag>" # Prefer an immutable digest in rendered manifests.
args:
- name: "--model-id"
value: "mistralai/Mistral-7B-Instruct-v0.1"
- name: "--max-input-length"
value: "2048"
- name: "--max-total-tokens"
value: "3072"
- name: "--max-batch-total-tokens"
value: "8192"
- name: "--max-batch-prefill-tokens"
value: "4096"
resources:
requests:
nvidia.com/gpu: "1"
limits:
nvidia.com/gpu: "1"
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 5
failureThreshold: 600
service:
serviceType: ClusterIP
port: 80
Les limites de tokens indiquées ci-dessus ne sont que des valeurs de départ indicatives, et non des recommandations relatives à la taille des ressources. Il convient de les déterminer en se basant sur des prompts représentatifs, le niveau de concurrence attendu, la quantité de mémoire GPU requise, ainsi que des tests de charge.
Corriger explicitement les lacunes
Le modèle de tableau actuel contient des valeurs codées en dur emptyDir des volumes ainsi que des valeurs d’environnement basiques. Une déploiement renforcé nécessite donc un fichier YAML révisé fork, un correctif appliqué après le rendu, ou une couche de manifeste de niveau supérieur afin d’ajouter :
- un PersistentVolumeClaim ou un cache d’artefacts local au nœud monté à
/data - Une référence secrète pour les identifiants du hub
- Une sonde de démarrage avant une sonde de disponibilité agressive
- Une politique de perturbation des pods ainsi qu’une répartition en topologie pour plusieurs répliques
- NetworkPolicy, restrictions des comptes de service et un gateway authentifié
- Fixation par hash de l’image et vérifications d’intégrité des artefacts
Ne placez pas de jeton Hub directement dans un fichier de valeurs déjà commité. Ne supposez pas que deux réplicas assurent une haute disponibilité réelle tant qu’ils ne parviennent pas tous deux à charger le modèle de base et que le routeur ne peut pas éviter d’envoyer tous les adaptateurs « froids » vers les deux pods.
Chemin pour la localité en mémoire cache
Le mécanisme d’équilibrage round‑robin peut transformer chaque réplica en un cache inactif. Un routeur utile associe, par hachage ou par d’autres moyens d’affinité, une identité d’adaptateur autorisée à un réplica, tout en préservant une voie de basculement en cas d’indisponibilité de ce dernier.
La clé de routage doit provenir de l’état de l’application authentifiée, et non d’un paramètre URL public arbitraire. Sinon, un appelant peut forcer des téléchargements à distance, vider les caches ou tenter d’accéder aux noms d’adaptateurs privés.
LoRAX ou vLLM ?
Le vLLM actuel peut gérer les modules LoRA déclarés au moment du démarrage, et il est également capable de les charger dynamiquement via des points d’entrée ou des plugins de résolution. Sa propre documentation met en garde contre les risques de sécurité liés à la mise à jour de l’adaptateur runtime, indiquant qu’il ne doit pas être utilisé en environnement de production en dehors d’un espace isolé et fiable.
La comparaison pertinente est opérationnelle plutôt que numérique :
| Question | LoRAX | vLLM |
|---|---|---|
| Comment les adaptateurs de queue longue sont-ils découverts ? | L’ID d’adaptation peut résoudre Hugging Face, Predibase, ou des artefacts de système de fichiers sur demande. | Modules statiques, points de terminaison de gestion dynamique, ou plugins de résolution |
| Comment la gestion de la résidence est-elle assurée ? | Planification explicite de l’échange d’adaptateurs entre GPU et CPU | Limites actives configurées ainsi que les limites CPU LoRA, plus le comportement du résolveur |
TGI-style /generate, client Python et chat compatible OpenAI | serving compatible avec OpenAI et APIs natif en Python | |
| Qu’est-ce qui doit prendre la décision ? | Latence froide/chaude, taux de renouvellement du cache, débit par lots hétérogènes, et adéquation opérationnelle | La même réexécution du travail de charge ainsi que les critères opérationnels |
Évitez des règles du type « LoRAX pour 1 000 adaptateurs, vLLM pour dix ». La taille du catalogue à elle seule ne détermine pas les performances. Benchmark, avec une même base, des adaptateurs, prompts, des classements, un suivi d’arrivée ainsi que du matériel, influencent également ce résultat.
Un test d’acceptation en production
Avant d’élargir le catalogue, exécutez une relecture qui inclut :
- Un ensemble fixe de connexions actives afin d’établir un débit et une latence stables.
- Une distribution à queue longue pour mesurer CPU ainsi que le nombre d’accès au cache des artefacts.
- Une vague d’adaptateurs jamais vus auparavant mais figurant dans la liste autorisée.
- Le remplacement de pods afin d’évaluer le temps de récupération du système de base et des adaptateurs.
- Un adaptateur indisponible ou endommagé pour vérifier les mécanismes d’isolement et de basculement.
- Des utilisateurs simultanés pour tester les processus d’authentification, les quotas et l’étiquetage des métriques.
Suivez le taux de requêtes, le temps d’attente dans la file d’attente, le temps nécessaire pour obtenir le premier token, la latence entre tokens, la latence totale, le temps de chargement de l’adaptateur, la catégorie de hit en cache, la mémoire GPU et CPU, le nombre d’octets téléchargés, ainsi que les échecs par cause. Évitez d’inclure les identifiants des adaptateurs dans les étiquettes des métriques non limitées ; assignez-les plutôt à des dimensions contrôlées ou à des traces échantillonnées.
Définissez les seuils d’acceptation avant de lancer les tests. Parmi les exemples, on peut citer un taux d’erreur maximal sur le chemin froid, une cible P99 pour les cas en charge normaux, une cible de taux de hits dans le cache correspondant à la distribution observée de popularité, ainsi qu’un objectif de temps de récupération en cas de perte de pod.
Conclusion
LoRAX transforme de nombreux ajustements fins compatibles, issus d’une flotte de copies de modèles de base, en un problème de placement d’adaptateurs. Ce principe peut s’avérer très efficace pour les charges de travail à distribution étirée, mais il ne garantit pas par défaut une stabilité des coûts ou des délais de traitement. Le jeu de données actif en cours d’utilisation, le chemin d’échange, le mélange par lots ainsi que la couche de stockage continuent d’influencer fortement le résultat final.
Vérifiez d’abord le fonctionnement de ces mécanismes sur un GPU. Ensuite, abordez Kubernetes avec sérieux : fixez les artefacts, conservez le cache, protégez les identifiants, autorisez les adaptateurs, assurez une routage basée sur la proximité géographique, et mesurez chaque itinéraire de résidence. Si LoRAX surpasse une configuration vLLM actuelle lors du même test de réexécution, la décision de déploiement sera étayée par des preuves concrètes.
Références
- repositoire LoRAX et fichier README — fonctionnalités prises en charge, exigences, APIs, ainsi que le diagramme Helm
- Valeurs du graphique LoRAX et Modèle de déploiement — valeurs par défaut actuelles et comportement en fonction du volume vLLM LoRA adaptateurs — adaptateur statique et dynamique serving
- LoRA article de recherche — méthode d’adaptation à rang faible Hugging Face PEFT documentation — adapter les formats et l’intégration à l’entraînement