Tu as un GPU, un modèle de langage, et une application qui l'appelle. Tu lances le modèle avec Hugging Face, tu l'enveloppes dans une petite API, et ça marche. Sauf que ça rame : cinq requêtes simultanées et le serveur sature, la carte graphique tourne à 30 % pendant que ta file d'attente s'allonge. Le problème n'est pas le modèle. C'est la façon dont tu le sers. Servir un LLM, ce n'est pas seulement le faire tourner : c'est l'art de remplir la mémoire et le calcul en permanence.
vLLM est le moteur d'inférence créé par l'équipe de l'université de Berkeley pour régler exactement ça. Deux idées au coeur. D'abord PagedAttention, qui gère la mémoire du modèle comme un système d'exploitation gère la RAM : au lieu de réserver d'un bloc un gros cache pour chaque requête, il découpe en pages et réutilise les trous. Ensuite le batching continu, qui regroupe les requêtes en continu au lieu d'attendre que tout le monde ait fini. Résultat : jusqu'à 24 fois plus de débit que la méthode naïve, sans toucher au modèle lui-même. Et une API compatible OpenAI, pour que ton code existant continue de marcher.
Concrètement, le débit se mesure en tokens par seconde. Passe de 50 à 1 200, et tu sers la même application avec une seule carte au lieu de trois. Ce n'est pas de la cosmétique : sur un GPU cloud facturé à l'heure, un débit dix fois supérieur divise ta facture d'inférence par dix.
Étape 1 : installe vLLM
vLLM exige une machine équipée d'un GPU NVIDIA (CUDA) pour les gros modèles. Sur un 7B quantifié, une carte de 8 Go suffit ; pour un 70B, il faudra compter plus large. Une installation propre passe par un environnement virtuel :
python -m venv venv
source venv/bin/activate # sous Windows : venv\Scripts\activate
pip install vllmPour un vrai serveur en production, Docker reste le plus simple : l'image officielle embarque déjà toutes les dépendances CUDA, tu évites ainsi des heures de galère à aligner les versions de pilotes.
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
--ipc=host vllm/vllm-openai:latest \
--model Qwen/Qwen2.5-7B-InstructÉtape 2 : lance le serveur OpenAI-compatible
La force de vLLM, c'est d'exposer une API identique à celle d'OpenAI. Ton code existant, tes clients, tes librairies : tout fonctionne sans la moindre modification. On démarre le serveur avec un modèle de 7 milliards de paramètres, un bon point de départ pour apprendre sans vider ta VRAM :
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 --port 8000 \
--gpu-memory-utilization 0.9Le serveur télécharge le modèle au premier lancement, puis écoute sur le port 8000. Les logs affichent le débit atteint, en tokens par seconde. Si un port est déjà occupé, change --port ; si le modèle ne rentre pas en mémoire, baisse --gpu-memory-utilization à 0.8.
Étape 3 : interroge-le depuis Python
On utilise le client OpenAI standard, en pointant simplement sur l'adresse locale. Installe-le avec pip install openai si ce n'est pas déjà fait :
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="token-inutile", # vLLM ne vérifie pas la clé en local
)
reponse = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[
{"role": "system", "content": "Tu réponds en une phrase, sans détour."},
{"role": "user", "content": "Pourquoi mon GPU dort quand je sers un LLM ?"},
],
temperature=0.7,
max_tokens=128,
)
print(reponse.choices[0].message.content)La clé API n'a aucune importance en local : vLLM l'accepte sans la vérifier. Le paramètre model doit correspondre au modèle chargé au démarrage du serveur. Tu peux d'ailleurs interroger l'endpoint avec n'importe quel outil compatible OpenAI, de curl à un agent autonome.
Étape 4 : l'inférence en lot, sans serveur
Pas besoin de serveur pour du traitement par lots. L'API Python de vLLM charge le modèle une seule fois en mémoire et traite tes prompts en continu :
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
prompts = [
"Résume en une phrase : " + t
for t in ["La mémoire d'un LLM coûte cher.", "vLLM batche les requêtes."]
]
params = SamplingParams(temperature=0.7, max_tokens=64)
sorties = llm.generate(prompts, params)
for prompt, sortie in zip(prompts, sorties):
print("Prompt :", prompt[:40])
print("Réponse :", sortie.outputs[0].text, "\n")Cette approche est idéale pour le traitement différé : résumer des documents, annoter un corpus, générer des légendes. Le modèle reste chaud en mémoire et vLLM empile les requêtes au fil de l'eau, ce qui maximise l'utilisation du GPU sans jamais le laisser attendre.
Étape 5 : pousse le débit
Trois leviers font la différence quand tu montes en charge. --gpu-memory-utilization fixe la part de VRAM réservée au cache de clés et de valeurs, le fameux cache KV. --max-model-len plafonne la longueur de contexte, ce qui libère de la mémoire. Enfin, la quantification compresse les poids du modèle :
vllm serve Qwen/Qwen2.5-7B-Instruct \
--quantization awq \
--max-model-len 4096 \
--tensor-parallel-size 2 # si tu disposes de 2 GPUSur un modèle qui dépasse ta VRAM, --tensor-parallel-size répartit les couches sur plusieurs cartes. La quantification AWQ ou GPTQ divise la mémoire nécessaire par deux ou trois, au prix d'une perte de précision quasi imperceptible. Teste toujours le modèle quantifié sur tes cas réels avant de le mettre en production.
À toi de jouer
vLLM transforme un GPU qui bâille en une machine à débiter du texte. Le vrai gain n'est pas dans le modèle : c'est de ne plus payer une carte graphique pour qu'elle attende. Commence par un 7B comme Qwen ou Llama, mesure ton débit avant et après, et regarde la différence.
Le code ci-dessus est prêt à coller dans ton projet. Et si ton serveur croule un jour sous les requêtes, tu sauras par où commencer. Un dernier conseil : surveille ta VRAM et ton débit avec nvidia-smi et les logs du serveur, c'est là que se cachent les vrais gains, pas dans un prompt miracle.






