Article

vLLM : introduction pratique au serving LLM, à l’inférence et au KV cache

Source principale : dépôt tutorials-vllm, chapitre 01-introduction/slides.md.
Vidéo : vLLM – 01. Introduction : C’est quoi ? (modèles, inférences, cache).

TL;DR

vLLM est un moteur d’inférence et de serving pour grands modèles de langage. Son objectif n’est pas d’entraîner un modèle, mais de le servir efficacement à des utilisateurs réels. Le chapitre 01-introduction présente vLLM comme la couche qui transforme un GPU et un modèle en service HTTP exploitable, avec API compatible OpenAI, batching, gestion mémoire, métriques, LoRA, quantization et support multi-GPU.

Le point central à retenir est simple : en production, le problème n’est pas seulement de générer du texte, mais de gérer la mémoire GPU, les files d’attente, les tokens, le KV cache et la concurrence.

La vidéo de référence

La vidéo associée à ce chapitre est disponible ici : https://www.youtube.com/watch?v=dHRy0KUTp_c. Son titre annonce bien le périmètre : vLLM - 01. Introduction : C'est quoi ? (modèles, inférences, cache).

Ce premier épisode sert d’entrée dans la formation vLLM. Il ne s’agit pas encore de déployer un modèle complet sur Kubernetes ou d’optimiser un cluster multi-GPU. L’objectif est d’abord de construire le bon modèle mental : modèle, tokenizer, token, inférence, mémoire GPU, KV cache, API compatible OpenAI, puis positionnement de vLLM dans l’écosystème.

vLLM, c’est quoi exactement ?

vLLM est un moteur d’inférence et de serving pour LLMs. Dans le dépôt de la formation, le chapitre 01-introduction/slides.md le résume comme un outil pour passer de “un prompt sur un GPU” à un vrai service LLM utilisable par des applications et des utilisateurs.

La nuance est importante. Faire tourner un modèle une fois dans un notebook ou dans un script Python n’est pas le même problème que servir des dizaines, centaines ou milliers de requêtes. Dans le premier cas, on veut surtout voir une réponse. Dans le second, il faut gérer la concurrence, la mémoire GPU disponible, la longueur variable des prompts, le streaming, la latence du premier token, le débit en tokens par seconde, les erreurs OOM, les métriques, les adaptateurs LoRA, la quantization et le multi-GPU.

Le vrai problème : l’inférence LLM n’est pas une API web classique

Un service web classique traite souvent des requêtes assez courtes : une entrée, une opération, une réponse. Avec un LLM, la réponse est générée token par token. Chaque nouveau token dépend des tokens précédents. La charge n’est donc pas seulement CPU ou réseau ; elle est fortement liée au GPU, à la VRAM et à la mémoire utilisée par l’attention.

L’inférence est la phase où un modèle déjà entraîné produit une réponse. Les poids sont gelés. Il n’y a pas d’apprentissage pendant l’inférence. Le modèle reçoit des tokens, calcule des probabilités pour le prochain token, puis répète ce mécanisme jusqu’à produire la réponse.

prompt -> tokenizer -> token IDs -> modèle -> prochain token -> prochain token -> ...

Modèle, tokens et tokenizer : les prérequis minimaux

Un modèle n’est pas “le chatbot”. Un modèle, c’est principalement une architecture, des poids, un tokenizer, une fenêtre de contexte et des règles de génération. Le tokenizer convertit du texte en identifiants numériques. Le modèle ne lit pas directement des mots humains, il manipule des tokens.

"Hello world"
     |
     v
["Hello", " world"]
     |
     v
[15496, 995]

Un token peut être un mot, un morceau de mot, un espace, une ponctuation ou une partie de code. Une URL, un JSON ou un prompt très structuré peuvent consommer beaucoup de tokens. Or plus il y a de tokens, plus le GPU travaille, plus la latence augmente, plus le KV cache grandit.

Découvrez  Headroom : compresser le contexte des agents IA avant l appel au LLM

Le KV cache : la notion clé à comprendre

Le KV cache est l’un des concepts les plus importants pour comprendre vLLM. Dans un transformer, les mécanismes d’attention produisent des tenseurs Key et Value. Pendant la génération, les anciens tokens restent utiles pour calculer les suivants. Plutôt que de recalculer inutilement certaines informations, le système conserve ces tenseurs en mémoire.

tour 1 : system prompt + question utilisateur
tour 2 : system prompt + messages précédents + nouvelle question
tour 3 : system prompt + messages précédents + nouvelle question

Le problème : ce cache prend de la place, surtout en VRAM. Il grandit avec la longueur du prompt, la longueur de la réponse, le nombre de requêtes simultanées, le nombre de couches du modèle, la taille du batch et la taille du modèle.

Le papier vLLM original, Efficient Memory Management for Large Language Model Serving with PagedAttention, explique que les systèmes de serving LLM doivent gérer une mémoire KV cache volumineuse, dynamique et difficile à allouer efficacement.

VRAM vs DRAM : pourquoi le GPU devient le goulet d’étranglement

Dans une application classique, on pense souvent CPU, RAM, disque, réseau. En serving LLM, il faut ajouter une contrainte forte : la VRAM GPU. La DRAM côté CPU contient l’OS, Python, FastAPI, les files de requêtes, le tokenizer, les logs et une partie de la logique applicative. La VRAM côté GPU contient les poids du modèle, le KV cache, les batches actifs, les kernels d’attention et les tenseurs temporaires.

CPU DRAM                         GPU VRAM
+-------------------+            +-------------------------+
| operating system  |            | model weights           |
| Python / FastAPI  |            | KV cache                |
| tokenizer         |  ----->    | active batches          |
| request queue     |            | attention kernels       |
| logs / metrics    |            | temporary tensors       |
+-------------------+            +-------------------------+

Les slides indiquent qu’un modèle comme Mistral 7B en FP16 représente environ 14 Go de poids. Sur une carte NVIDIA L4 24 Go, cela laisse de la marge, mais pas une marge infinie. Le KV cache peut vite remplir l’espace restant si les prompts sont longs ou si plusieurs utilisateurs arrivent en même temps.

Pourquoi une approche PyTorch naïve ne suffit pas

On peut très bien écrire une API minimale avec PyTorch, Transformers et FastAPI. Pour une démo, c’est suffisant. Pour apprendre, c’est même très utile. Mais dès que l’on ajoute de vrais usages, les limites apparaissent : utilisateurs concurrents, prompts longs, streaming, files d’attente, métriques, batching, limites de tokens, erreurs mémoire, chargement modèle et retries.

model = AutoModelForCausalLM.from_pretrained(MODEL_ID)

@app.post("/predict")
async def predict(req):
    inputs = tokenizer(req.prompt, return_tensors="pt")
    outputs = model.generate(**inputs, max_new_tokens=100)
    return tokenizer.decode(outputs[0])

Le chapitre suivant de la formation, 02-minimal-pytorch-inference, sert justement à construire cette approche naïve pour montrer ce que vLLM remplace ensuite.

Ce que vLLM ajoute dans la pile

vLLM ne remplace pas le modèle. Il ne transforme pas un mauvais modèle en bon modèle. Il fournit la couche d’exécution et de serving autour du modèle.

App / client
    |
    | OpenAI-compatible HTTP
    v
vLLM API server
    |
    | scheduler + tokenizer + request queue
    v
vLLM engine
    |
    | PagedAttention + batching + kernels + KV cache manager
    v
GPU / model weights

C’est cette couche qui permet à une application de parler à un endpoint /v1/chat/completions pendant que vLLM s’occupe du scheduling, de la mémoire et de l’exécution GPU.

API compatible OpenAI : l’intégration pratique

Un avantage pratique de vLLM est son serveur compatible avec le format OpenAI. Cela signifie que beaucoup d’outils savent déjà lui parler : clients HTTP, SDK Python, LangChain, LlamaIndex, Open WebUI, agents, gateways internes.

curl http://localhost:8000/v1/chat/completions   -H "Content-Type: application/json"   -d '{
    "model": "mistralai/Mistral-7B-Instruct-v0.3",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 64
  }'

Ce contrat permet de changer le backend d’inférence sans réécrire toute l’application. Le client continue à envoyer des messages dans un format connu, pendant que le moteur derrière peut être vLLM.

PagedAttention : l’idée forte derrière vLLM

L’idée fondatrice de vLLM est PagedAttention. Le papier publié sur arXiv en septembre 2023 présente PagedAttention comme une approche inspirée de la mémoire virtuelle et du paging dans les systèmes d’exploitation.

Dans une approche traditionnelle, le KV cache peut souffrir de fragmentation et de sur-réservation. Les slides indiquent que les anciens systèmes pouvaient gaspiller 60 à 80 % de la mémoire KV cache à cause de cette fragmentation. Le blog officiel vLLM explique aussi que le KV cache est volumineux, dynamique et difficile à gérer efficacement.

KV cache traditionnel :
[ requête A allocation contiguë ][ espace perdu ][ requête B ... ]

PagedAttention :
blocs logiques -> blocs physiques
comme des pages mémoire dans un OS

L’intérêt est direct : moins de mémoire gaspillée, plus de requêtes en batch, meilleure utilisation du GPU, débit plus élevé.

Découvrez  Ponytail : faire ecrire moins de code aux agents IA sans supprimer les garde-fous

Batching continu : mieux utiliser le GPU

Un GPU coûte cher. S’il attend, on gaspille de l’argent. Mais regrouper les requêtes de façon naïve peut augmenter la latence. Les LLMs compliquent encore le problème, car toutes les requêtes n’ont pas la même longueur.

vLLM introduit le batching continu pour mieux remplir le GPU au fil de l’eau. Au lieu de raisonner uniquement en batchs statiques, le scheduler peut intégrer de nouvelles requêtes pendant que d’autres sont en cours de génération.

vLLM vs Ollama, TGI, SGLang, TensorRT-LLM et llama.cpp

OutilCas d’usage naturelLimite ou compromis
vLLMServing production, API OpenAI, haut débit GPUApproche serveur, orientée GPU
OllamaTest local simple sur poste développeurMoins orienté haut débit multi-utilisateurs
Hugging Face TGIDéploiement Hugging Face-nativeMoins flexible pour certaines optimisations avancées
SGLangGénération structurée, préfixes partagésÉcosystème opérationnel plus jeune
TensorRT-LLMPerformance NVIDIA maximaleBuild et compilation plus complexes
llama.cppLocal, CPU, GGUF, portabilitéPas le même objectif que le serving GPU haut débit

La règle pratique du chapitre est simple : Ollama est très confortable pour tester localement. vLLM devient pertinent quand le sujet devient API, concurrence, GPU, batching, KV cache, métriques, LoRA, multi-GPU et production.

Les fonctionnalités vLLM que la série va explorer

L’introduction liste les grands sujets que la formation développera ensuite : PagedAttention, continuous batching, prefix caching, chunked prefill, speculative decoding, quantization, CUDA graphs, torch.compile, disaggregated prefill/decode, LoRA, multi-LoRA, tensor parallelism, pipeline parallelism, observabilité, benchmarking, Kubernetes, sécurité, production et guide matériel NVIDIA.

Premier setup : ce que le dépôt annonce

Le README du dépôt donne le fil pratique de la série. On commence par lire les slides avec mdp :

mdp 00-sommaire/slides.md
mdp 01-introduction/slides.md

Puis la formation prévoit un environnement Infomaniak Public Cloud avec OpenTofu, une VM GPU, CUDA, vLLM et un premier modèle servi via l’API HTTP.

source ~/vllm-env/bin/activate
export CUDA_HOME=/usr/local/cuda
vllm serve mistralai/Mistral-7B-Instruct-v0.3   --host 0.0.0.0 --port 8000   --max-model-len 8192 --gpu-memory-utilization 0.90

Test API :

curl http://$(tofu output -raw instance_ip):8000/v1/chat/completions   -H "Content-Type: application/json"   -d '{"model": "mistralai/Mistral-7B-Instruct-v0.3", "messages": [{"role": "user", "content": "Hello!"}]}'

Les métriques à surveiller en serving LLM

Un service web classique se surveille avec latence, taux d’erreur, saturation CPU, mémoire et réseau. Un service LLM demande des métriques plus spécifiques : TTFT, TPOT ou ITL, tokens par seconde, usage du KV cache, temps passé en file d’attente, utilisation GPU et taux de hit du prefix cache.

Ces métriques sont importantes parce qu’une API LLM peut sembler “en ligne” tout en étant inutilisable : premier token trop lent, débit trop faible, file d’attente saturée, VRAM pleine, GPU sous-utilisé ou prompts trop longs.

Où vLLM brille vraiment

vLLM est particulièrement adapté lorsque l’on veut servir des modèles ouverts derrière une API HTTP avec de vrais usages applicatifs : chatbot interne, assistant métier, plateforme RAG, gateway IA interne, assistant de code, extraction JSON, agents avec tool calling, serving de modèles fine-tunés et workloads multi-utilisateurs.

Quand vLLM n’est pas forcément le premier choix

Si l’objectif est de tester un modèle localement sur un laptop, Ollama ou llama.cpp peuvent être plus simples. Si l’objectif est de pousser au maximum une pile NVIDIA optimisée avec compilation spécifique, TensorRT-LLM peut être pertinent. Si l’objectif est un workflow très Hugging Face-native, TGI peut être à regarder.

Liens utiles

FAQ

vLLM sert-il à entraîner des modèles ?

Non. vLLM sert à l’inférence et au serving. Il utilise un modèle déjà entraîné pour générer des réponses. Les poids du modèle sont gelés pendant l’inférence.

Pourquoi le KV cache est-il si important ?

Parce que la génération LLM est token par token. Les anciens tokens restent nécessaires pour produire les suivants. Le KV cache stocke des tenseurs Key/Value pour éviter certains recalculs, mais il consomme beaucoup de VRAM.

Quelle est la différence entre vLLM et Ollama ?

Ollama est très pratique pour tester des modèles localement avec une bonne expérience développeur. vLLM est davantage orienté serving GPU, API compatible OpenAI, concurrence, batching, métriques, KV cache et production.

Qu’est-ce que PagedAttention ?

PagedAttention est l’approche introduite par vLLM pour gérer efficacement le KV cache. Elle s’inspire de la mémoire virtuelle : les blocs logiques peuvent être mappés vers des blocs physiques non contigus, ce qui réduit la fragmentation mémoire.

Pourquoi vLLM expose-t-il une API compatible OpenAI ?

Parce que ce format est devenu un standard d’intégration. Beaucoup d’applications, SDKs, outils RAG, interfaces web et agents savent déjà appeler /v1/chat/completions.

Peut-on utiliser vLLM avec Mistral ?

Oui. Le dépôt de la formation utilise notamment mistralai/Mistral-7B-Instruct-v0.3 dans ses exemples de serving.

Faut-il forcément Kubernetes pour utiliser vLLM ?

Non. La série commence par des usages simples avec vllm serve, puis évolue vers des sujets plus avancés comme Kubernetes, l’observabilité et la production.

Conclusion

Ce premier chapitre pose les fondations de la série vLLM. Le message principal est clair : servir un LLM n’est pas seulement charger un modèle et appeler generate(). Dès que l’on parle d’utilisateurs réels, il faut gérer les tokens, la VRAM, le KV cache, le batching, la latence, le débit, les métriques et les erreurs.

vLLM existe pour cette zone précise : transformer un modèle ouvert et un GPU en service LLM exploitable, avec une API compatible OpenAI et des mécanismes conçus pour mieux utiliser la mémoire et le calcul disponibles. La suite logique de la formation consiste à construire d’abord une inférence PyTorch minimale pour voir les limites de l’approche naïve, puis à introduire progressivement vLLM comme moteur de serving complet.

Explorer les formations Xavki

Pour apprendre dans l ordre, repartez depuis la roadmap ou une playlist thematique.