[!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 :

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 :

  1. Le modèle de base reste en mémoire pour l’ensemble des adaptateurs compatibles.
  2. 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.
  3. Le planificateur d’échange d’adaptateurs précharge et déplace les poids entre la mémoire GPU et la mémoire CPU.
  4. Le regroupement continu hétérogène des requêtes permet de cibler différents adaptateurs.

Chemin de requête LoRAX, de la résolution de l’adaptateur à la génération

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 :

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 :

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

Adapter le stockage des artefacts ainsi que la résidence de runtime au sein de LoRAX

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 :

CheminCe que cela inclut
GPU nombre d’incidentsAdapter les agents déjà résidentstemps d’attente dans la file et temps jusqu’au premier token
CPU nombre d’incidentsTransfert ou rematérialisation dans GPUdélai d’adaptation de la charge et latence bout en bout
Impact sur l’artefactLire depuis le disque local /data cachedélai de lecture/chargement et octets en cache
Échec de lancement à distanceTéléchargement, validation supplémentaire et chargementtemps 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 :

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 :

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 :

QuestionLoRAXvLLM
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 CPULimites actives configurées ainsi que les limites CPU LoRA, plus le comportement du résolveur
TGI-style /generate, client Python et chat compatible OpenAIserving 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érationnelleLa 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 :

  1. Un ensemble fixe de connexions actives afin d’établir un débit et une latence stables.
  2. Une distribution à queue longue pour mesurer CPU ainsi que le nombre d’accès au cache des artefacts.
  3. Une vague d’adaptateurs jamais vus auparavant mais figurant dans la liste autorisée.
  4. Le remplacement de pods afin d’évaluer le temps de récupération du système de base et des adaptateurs.
  5. Un adaptateur indisponible ou endommagé pour vérifier les mécanismes d’isolement et de basculement.
  6. 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