Model Serving
Le model serving est le processus qui consiste à rendre un modèle de machine learning entraîné disponible en production pour répondre à des requêtes d’inférence en temps réel ou en batch, généralement via une API REST ou gRPC.
Entraîner un modèle, c’est de la recherche. Le servir en production, c’est de l’ingénierie. Le model serving est le pont entre les deux : il prend un artefact entraîné (un fichier de poids, un modèle sérialisé) et le transforme en service réseau capable de recevoir des données, exécuter l’inférence et retourner des prédictions, le tout avec des garanties de performance, de disponibilité et de scalabilité.
- Catégorie
- Infrastructure ML / MLOps
- Rôle
- Exposer un modèle entraîné comme service d’inférence
- Protocoles
- REST, gRPC, OpenAI-compatible
- Runtimes
- vLLM, Triton, TorchServe, TensorFlow Serving, BentoML
- Plateformes
- KServe, Seldon Core, SageMaker Endpoints, Vertex AI Endpoints
- Infra
- Docker, Kubernetes, GPU
Model serving vs model deployment : clarification
Ces termes sont souvent utilisés de manière interchangeable, mais ils désignent des concepts distincts :
Model serving runtime : l’outil qui package un modèle entraîné dans un conteneur, crée des API optimisées pour l’inférence ML, et gère le chargement du modèle en mémoire. Exemples : BentoML, Triton, TorchServe, vLLM.
Model serving platform : l’environnement qui déploie et scale les conteneurs de serving en réponse au trafic. Gère l’auto-scaling, le load balancing, le routing, les canary deployments. Exemples : KServe, Seldon Core, BentoCloud.
Model deployment : le processus complet d’intégration d’un modèle packagé dans une plateforme de serving et de connexion avec l’infrastructure (bases de données, services aval, monitoring). C’est l’étape qui relie le serving au reste de votre système.
En pratique, une stack de serving complète combine ces trois couches. Par exemple : vous packagez votre LLM avec BentoML (runtime), vous le déployez sur KServe (Kubernetes platform) qui gère l’auto-scaling et le routing, et vLLM fournit le moteur d’inférence optimisé sous-jacent.
Les deux modes d’inférence
Inférence en temps réel (online serving)
Le modèle reçoit des requêtes individuelles et retourne des prédictions en temps réel. C’est le mode utilisé pour les chatbots, la recherche sémantique, les recommandations en temps réel, la détection de fraude, et toute application qui nécessite une réponse immédiate.
Les contraintes clés : latence faible (typiquement < 100ms pour le ML classique, quelques secondes acceptables pour les LLM), haute disponibilité (99,9%+), et scalabilité élastique pour absorber les pics de trafic.
Le modèle est exposé comme un service réseau permanent (API REST ou gRPC), avec un ou plusieurs réplicas derrière un load balancer. Des frameworks comme KServe gèrent l’auto-scaling automatiquement, y compris le scale-to-zero (arrêt des instances quand il n’y a pas de trafic) et le scale-up rapide quand les requêtes arrivent.
Inférence batch (offline serving)
Le modèle traite un volume de données en une seule exécution programmée (par exemple, une fois par jour). C’est le mode utilisé pour le scoring de bases de données clients, la génération de recommandations hebdomadaires, les pipelines de classification documentaire, et toute tâche où la fraîcheur des résultats n’est pas critique.
L’inférence batch est plus simple à opérer : pas besoin de service permanent, pas de contrainte de latence par requête. Le modèle est téléchargé depuis un registre de modèles, exécuté sur les données, et les résultats sont stockés dans une base de données ou un data lake. Les frameworks comme Spark, Ray ou des data pipelines classiques (Airflow, Prefect) conviennent bien.
Les runtimes de model serving
Un runtime de serving crée des images Docker optimisées pour l’inférence ML, avec des API standardisées. Voici les principaux runtimes et leurs cas d’usage :
| Runtime | Spécialisation | Frameworks supportés | LLM | Licence |
|---|---|---|---|---|
| vLLM | Inférence LLM haute performance | Tous les LLM Hugging Face (Llama, Mistral, Qwen, etc.) | ✅ Optimisé | Apache 2.0 |
| NVIDIA Triton | Multi-framework, GPU optimisé | TensorFlow, PyTorch, ONNX, TensorRT, vLLM | ✅ Via TensorRT-LLM | BSD-3 |
| BentoML | Packaging multi-framework, DX | Tous (PyTorch, TF, Scikit-learn, XGBoost, vLLM) | ✅ Via vLLM/OpenLLM | Apache 2.0 |
| TorchServe | Modèles PyTorch | PyTorch | Partiel | Apache 2.0 |
| TF Serving | Modèles TensorFlow | TensorFlow/Keras | Non | Apache 2.0 |
| TGI | LLM Hugging Face | Modèles Hugging Face | ✅ Optimisé | Apache 2.0 |
| ONNX Runtime | Inférence cross-platform | ONNX (tous frameworks exportables) | Partiel | MIT |
vLLM : la référence pour le serving LLM
vLLM, développé initialement par des chercheurs de UC Berkeley, est devenu le moteur d’inférence LLM le plus utilisé en production. Ses innovations clés : PagedAttention (gestion optimisée de la mémoire KV-cache), continuous batching (traitement simultané de requêtes arrivant à des moments différents), speculative decoding, prefill-decode disaggregation, et automatic prefix caching.
vLLM expose des endpoints compatibles OpenAI, ce qui signifie que n’importe quel client OpenAI peut interagir avec votre modèle auto-hébergé sans modification de code. Le setup minimal :
pip install vllm
vllm serve meta-llama/Llama-3.1-8B-Instruct --port 8000Votre modèle est maintenant accessible via une API compatible OpenAI à http://localhost:8000/v1/chat/completions.
NVIDIA Triton Inference Server
Triton est le serveur d’inférence de référence pour les déploiements multi-modèles sur GPU NVIDIA. Contrairement à vLLM (spécialisé LLM), Triton est un serveur d’inférence généraliste qui peut servir simultanément des modèles TensorFlow, PyTorch, ONNX, TensorRT et même vLLM. C’est le choix naturel quand vous servez plusieurs types de modèles sur la même infrastructure GPU.
Triton supporte le dynamic batching (regroupement automatique des requêtes pour optimiser l’utilisation GPU), le model ensemble (chaîne de modèles exécutés séquentiellement), et le multi-model serving sur un seul GPU. Depuis la version « Dynamo Triton » (mars 2025), le serveur intègre des optimisations spécifiques pour les LLM via TensorRT-LLM.
BentoML
BentoML se distingue par son expérience développeur. Là où Triton et vLLM sont des moteurs d’inférence, BentoML est un framework de packaging qui simplifie la création d’images Docker optimisées pour l’inférence, avec des API REST/gRPC standardisées et un support natif pour le pre/post-processing custom.
BentoML est framework-agnostique : il supporte PyTorch, TensorFlow, Scikit-learn, XGBoost, et peut intégrer vLLM comme backend pour les LLM. Le workflow typique : vous définissez un Service Python, BentoML le package en image OCI, et vous le déployez sur n’importe quelle infrastructure (Kubernetes, cloud, BentoCloud managé).
import bentoml
@bentoml.service(resources={"gpu": 1})
class SentimentClassifier:
model = bentoml.models.get("sentiment-model:latest")
@bentoml.api
def predict(self, text: str) -> dict:
# pre-processing, inférence, post-processing
result = self.model.predict(text)
return {"sentiment": result, "confidence": 0.95}Les plateformes de serving
KServe
KServe (anciennement KFServing) est le framework Kubernetes-natif de référence pour le model serving. Projet incubé par la CNCF, KServe fournit un CRD (Custom Resource Definition) InferenceService qui standardise le déploiement de modèles sur Kubernetes.
KServe gère automatiquement l’auto-scaling (y compris le scale-to-zero), le load balancing, les canary rollouts, les health checks, et supporte de multiples runtimes (TensorFlow Serving, TorchServe, Triton, vLLM, Hugging Face, Scikit-learn, XGBoost, LightGBM).
La version 0.15 (mai 2025) a ajouté le support natif de vLLM comme backend LLM, avec distributed KV cache via LMCache pour les séquences longues. C’est désormais la solution recommandée pour servir des LLM sur Kubernetes.
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: llama3-service
spec:
predictor:
model:
modelFormat:
name: huggingface
runtime: kserve-huggingfaceserver
storageUri: "hf://meta-llama/Llama-3.1-8B-Instruct"
resources:
limits:
nvidia.com/gpu: 1Seldon Core
Seldon Core est une alternative open source à KServe, également basée sur Kubernetes. Seldon se distingue par ses capacités avancées de déploiement (A/B testing, multi-armed bandits, shadow deployments) et son focus sur l’explainability des prédictions. Seldon est plus adapté aux scénarios enterprise qui nécessitent des stratégies de déploiement complexes.
Endpoints cloud managés
| Service | Cloud | Forces | Prix indicatif |
|---|---|---|---|
| SageMaker Endpoints | AWS | Serverless inference, multi-model endpoints, auto-scaling natif | Pay per instance-hour + invocations |
| Vertex AI Endpoints | GCP | Intégration Vertex AI, modèles Google natifs, Agent Builder | Pay per node-hour + predictions |
| Azure ML Endpoints | Azure | Intégration Azure DevOps, MLflow managé, RBAC | Pay per instance-hour |
| BentoCloud | Multi-cloud | BentoML managé, auto-scaling rapide, observabilité LLM | Pay per GPU-second |
Optimisations clés du model serving
Batching dynamique
Le batching regroupe plusieurs requêtes individuelles en un seul batch traité par le modèle. Sur GPU, le traitement d’un batch de 32 requêtes est souvent à peine plus lent que le traitement d’une seule requête, ce qui multiplie le throughput par 10-30x sans augmenter la latence proportionnellement.
Le dynamic batching (ou adaptive batching) attend un court délai (quelques millisecondes) pour accumuler des requêtes, puis les traite ensemble. Tous les runtimes sérieux le supportent (Triton, vLLM, BentoML, TorchServe).
Continuous batching (LLM spécifique)
Pour les LLM, le continuous batching est une avancée majeure par rapport au static batching. Au lieu d’attendre que toutes les séquences d’un batch soient terminées avant de commencer le batch suivant, le continuous batching insère de nouvelles requêtes dans le batch dès qu’une séquence existante se termine. Cela élimine les temps morts et maximise l’utilisation GPU.
vLLM a popularisé cette technique, qui est maintenant standard dans tous les moteurs d’inférence LLM modernes (TGI, Triton/TensorRT-LLM).
Quantization
La quantization réduit la précision des poids du modèle (de FP32 à FP16, INT8, ou INT4) pour diminuer l’empreinte mémoire et accélérer l’inférence. Un modèle quantifié en INT4 occupe environ 4x moins de mémoire GPU qu’en FP16, ce qui permet de servir des modèles plus gros sur du hardware plus petit.
Les techniques courantes : GPTQ (post-training quantization), AWQ (Activation-aware Weight Quantization), et GGUF (format de quantization de llama.cpp). vLLM, TGI et Triton supportent nativement les modèles quantifiés.
PagedAttention (LLM spécifique)
PagedAttention, introduit par vLLM, gère le KV-cache (la mémoire des tokens déjà générés) comme la mémoire virtuelle d’un OS : en pages non contiguës. Cela élimine la fragmentation mémoire et permet de servir 2-4x plus de requêtes simultanées sur le même GPU. C’est l’innovation qui a rendu vLLM dominant pour le serving LLM.
Parallélisme de modèle
Les modèles trop gros pour tenir sur un seul GPU nécessitent du model parallelism : le modèle est réparti sur plusieurs GPU. Deux approches principales : le tensor parallelism (chaque couche est répartie sur N GPU, adapté au serving temps réel) et le pipeline parallelism (les couches sont réparties séquentiellement, adapté au batch). vLLM et Triton supportent nativement le tensor parallelism multi-GPU.
Architecture de serving en production
Une architecture de model serving production-ready comprend plusieurs composants au-delà du simple runtime d’inférence :
Load balancer / Ingress : distribue le trafic entre les réplicas du modèle. Sur Kubernetes, Istio ou un Ingress Controller standard. Pour les déploiements LLM, le routing intelligent (basé sur la longueur du prompt ou le type de requête) optimise l’utilisation des ressources.
Auto-scaler : ajuste le nombre de réplicas en fonction du trafic. KServe utilise Knative pour l’auto-scaling (y compris scale-to-zero). Pour les GPU, le scaling est plus lent (le démarrage d’un conteneur avec chargement de modèle prend 30s à plusieurs minutes), ce qui nécessite du pre-scaling prédictif pour les pics anticipés.
API Gateway : authentification, rate limiting, transformation des requêtes. Pour les LLM, le gateway gère aussi le streaming SSE (Server-Sent Events) pour la génération token par token.
Pre/post-processing : transformation des données d’entrée (tokenization, normalisation, extraction de features depuis un feature store) et des sorties (formatage, filtrage, guardrails). KServe supporte un composant Transformer dédié pour le pre/post-processing.
Monitoring : métriques Prometheus (latence, throughput, taux d’erreur, utilisation GPU/mémoire), logs structurés, tracing distribué. Tous les runtimes sérieux exposent des métriques Prometheus nativement.
Model registry : stockage versionné des artefacts de modèle. Le serving platform tire le modèle du registry (MLflow, S3, GCS) au démarrage du conteneur.
Serving LLM vs serving ML classique
| Aspect | ML classique | LLM |
|---|---|---|
| Taille du modèle | Mo à quelques Go | Dizaines à centaines de Go |
| Hardware | CPU souvent suffisant | GPU obligatoire (sauf petits modèles quantifiés) |
| Latence | 1-100ms typique | 0,5-30s selon la longueur de réponse |
| Coût par requête | Négligeable | Significatif (tokens) |
| Batching | Static/dynamic batching | Continuous batching (requêtes de longueur variable) |
| Mémoire | Relativement stable | KV-cache dynamique (croît avec le contexte) |
| Scaling | Horizontal facile (réplicas CPU/GPU) | Horizontal coûteux (chaque réplica = 1+ GPU) |
| Streaming | Rarement nécessaire | Essentiel (token par token via SSE) |
| Runtime typique | TorchServe, TF Serving, Triton | vLLM, TGI, Triton/TensorRT-LLM |
Combiner les outils : la stack vLLM + BentoML + KServe
En 2026, la stack de serving LLM la plus répandue combine trois couches spécialisées :
vLLM fournit le moteur d’inférence haute performance (PagedAttention, continuous batching, tensor parallelism). C’est lui qui exécute réellement le LLM sur GPU.
BentoML fournit le packaging : il wrape vLLM dans un Service avec des API standardisées, gère le pre/post-processing custom, et produit une image Docker reproductible.
KServe fournit l’orchestration Kubernetes : auto-scaling, routing/ingress, canary deployments, health checks, et gestion du cycle de vie.
Chaque couche fait ce qu’elle fait le mieux. vLLM optimise l’inférence. BentoML simplifie le packaging. KServe gère les opérations. C’est une approche modulaire qui évite le vendor lock-in tout en offrant des performances de production.
Comment choisir son outil de serving
Le choix dépend de trois facteurs : le type de modèle, votre infrastructure existante, et la taille de votre équipe.
Vous servez un LLM open source sur vos GPU ? vLLM est le choix par défaut. Ajoutez KServe si vous avez Kubernetes, ou déployez directement avec Docker si vous êtes sur une seule machine.
Vous servez plusieurs types de modèles (LLM + classique + vision) sur GPU NVIDIA ? Triton est conçu pour ce cas. Il peut servir simultanément des modèles TensorFlow, PyTorch, ONNX et LLM sur la même infrastructure.
Vous voulez un packaging propre avec du pre/post-processing custom ? BentoML simplifie la création d’images Docker avec des API standardisées, et s’intègre avec vLLM pour les LLM.
Vous êtes sur un cloud provider et voulez du managé ? SageMaker Endpoints (AWS), Vertex AI Endpoints (GCP) ou Azure ML Endpoints éliminent la gestion d’infrastructure, au prix du vendor lock-in.
Vous êtes une petite équipe sans infrastructure Kubernetes ? Un simple serveur FastAPI dans un conteneur Docker suffit pour démarrer. Ou utilisez une API hébergée (OpenAI, Anthropic) et ajoutez l’auto-hébergement quand le volume le justifie.
Erreurs courantes en model serving
Flask/FastAPI en production sans optimisation. Un wrapper Python naïf fonctionne pour un prototype, mais n’offre ni batching, ni gestion GPU optimisée, ni metrics, ni graceful shutdown. Utilisez un runtime dédié dès que vous passez en production.
Pas de health check ni de graceful shutdown. Kubernetes doit savoir si votre pod est prêt à recevoir du trafic (readiness probe) et si le modèle est chargé (liveness probe). Sans cela, vous envoyez du trafic à des pods en cours de démarrage ou en échec.
Ignorer le cold start GPU. Charger un modèle LLM en mémoire GPU prend de 30 secondes à plusieurs minutes. Si votre auto-scaler crée un nouveau pod pendant un pic de trafic, les premières requêtes attendront. Anticipez avec du pre-scaling ou maintenez un minimum de réplicas à chaud.
Pas de monitoring GPU. L’utilisation GPU (compute et mémoire) est la métrique la plus importante pour le serving sur GPU. Un GPU sous-utilisé gaspille de l’argent. Un GPU saturé en mémoire crashe le pod sans avertissement.
Oublier le versionnement des modèles. En production, vous devez pouvoir faire un rollback instantané vers la version précédente du modèle. Sans registre de modèles (MLflow, S3 versionné), un déploiement raté peut bloquer votre service.
Questions fréquentes sur le model serving
Quelle est la différence entre model serving et model deployment ?
Le model serving est la couche technique qui rend un modèle accessible via une API (chargement en mémoire, gestion des requêtes, optimisation d’inférence). Le model deployment est le processus complet d’intégration du modèle dans l’infrastructure de production : packaging, déploiement sur la plateforme de serving, connexion aux services aval, configuration du monitoring et des alertes. Le serving est un composant du deployment.
Quel est le meilleur outil pour servir un LLM en production ?
vLLM est le moteur d’inférence LLM le plus performant et le plus adopté en 2026. Il offre le meilleur throughput grâce au PagedAttention et au continuous batching. Pour l’orchestration sur Kubernetes, combinez-le avec KServe. Pour un packaging simplifié, utilisez BentoML comme couche intermédiaire. Si vous préférez une solution managée, TGI via les Inference Endpoints de Hugging Face est une alternative solide.
Peut-on servir un modèle ML sans GPU ?
Oui, pour les modèles ML classiques (Scikit-learn, XGBoost, LightGBM, petits réseaux de neurones), le CPU est souvent suffisant et plus économique. Pour les modèles de deep learning de taille moyenne, un CPU peut fonctionner mais avec une latence plus élevée. Pour les LLM, le GPU est quasi-obligatoire en production, sauf pour les très petits modèles (< 3B paramètres) fortement quantifiés.
Comment gérer le scaling pour le model serving ?
Utilisez l’auto-scaling horizontal : ajoutez des réplicas quand le trafic augmente, supprimez-les quand il diminue. KServe gère cela nativement sur Kubernetes, avec le scale-to-zero pour éliminer les coûts à zéro trafic. Pour les GPU, le scaling est plus lent (cold start), donc maintenez un minimum de réplicas et utilisez du pre-scaling prédictif avant les pics anticipés. Monitorez l’utilisation GPU pour dimensionner correctement chaque réplica.
Combien coûte le model serving en production ?
Pour du ML classique sur CPU, le coût est modeste (quelques dizaines de dollars par mois sur un petit serveur cloud). Pour du serving LLM sur GPU, le coût est significatif : une instance GPU A100 coûte environ 2 à 4 $/heure selon le cloud provider. Servir un LLM 70B 24/7 revient donc à environ 1 500 à 3 000 $/mois minimum. Les optimisations (quantization, batching, scale-to-zero) peuvent réduire les coûts de 50 à 80%. Alternative : l’inférence via API (OpenAI, Anthropic) transfert le coût en pay-per-token, souvent plus économique sous 10 000 requêtes/jour.