Chaque requête envoyée à un service d'IA hébergé quitte votre réseau, traverse Internet et se termine dans un centre de données dont vous ne contrôlez ni l'emplacement ni la politique de conservation. Pour un contrat, un dossier patient ou du code source, cela pose des questions de confidentialité. Cela en pose d'autres de disponibilité (que se passe-t-il quand la connexion tombe ?) et de coût (que devient la facture quand toute l'organisation s'y met ?).

Faire tourner un modèle sur ses propres machines est possible, et la question n'est plus « est-ce faisable » mais « quelle machine, quel format, quel moteur, pour quelle charge ». Cet article est le guide de dimensionnement que j'aurais voulu avoir au départ : des formules que l'on peut refaire à la main, des ordres de grandeur qualifiés comme tels, des commandes à adapter à sa version, et les limites. Les exemples chiffrés utilisent des configurations génériques et sont illustratifs : aucune mesure de performance n'y est revendiquée. Mesurez toujours sur votre matériel et vos requêtes.

Où tourne l'IA que vous utilisez ?

Une IA « dans le cloud » s'exécute sur les machines d'un fournisseur : vous envoyez du texte, vous recevez du texte. Une IA « locale » s'exécute sur des machines que vous contrôlez : un portable, un serveur dans vos locaux, ou un hébergeur de votre juridiction. Le critère pertinent n'est pas la géographie mais le contrôle : qui voit les prompts, qui garde les journaux, qui décide des mises à jour.

Inférence hébergéeVos équipesvia Internetprompts et documents sortentFournisseur d'APIjuridiction à vérifierInférence localeVotre organisationVos équipesréseau interneServeur d'inférencesous votre contrôle
Dans le cloud, chaque requête quitte votre organisation. En local, le trafic d'inférence reste sur votre réseau, même sans connexion Internet.

Le schéma ne dit pas qu'un des deux modes est meilleur. Il dit où passent les données. Le reste de l'article porte sur ce que coûte, en mémoire, en latence et en exploitation, de ramener ce point de passage chez soi.

Un modèle est un fichier de poids

Un modèle de langage, une fois entraîné, se réduit à des tenseurs de nombres (les poids, ou paramètres) et à une description de l'architecture. Pour la présentation de base des réseaux de neurones, voir L'IA expliquée simplement. Ce qui compte ici : ce fichier se copie. Entraîner demande des milliers d'accélérateurs pendant des semaines ; inférer demande de charger les poids en mémoire et d'enchaîner des multiplications de matrices. L'écart de coût entre les deux est considérable, et c'est ce qui rend l'inférence locale envisageable.

Encore faut-il pouvoir obtenir les poids. Les modèles propriétaires de premier rang ne sont accessibles que par API. À côté, de nombreuses familles de modèles à poids ouverts sont publiées : Llama (Meta), Mistral, Qwen (Alibaba), Gemma (Google), DeepSeek, Falcon (Abou Dhabi), ou Jais, conçu d'abord pour l'arabe. Chaque famille existe en plusieurs tailles.

Deux précautions. D'abord, « poids ouverts » n'est pas « open source » au sens strict : la licence peut limiter l'usage commercial, imposer des seuils d'utilisateurs ou des clauses d'usage acceptable, et les données d'entraînement ne sont généralement pas publiées. Lisez la licence de la version exacte que vous déployez. Ensuite, un fichier téléchargé est du code et des données non fiables : préférez des formats sans exécution arbitraire (safetensors, GGUF) et vérifiez la provenance.

Dimensionner la mémoire

La mémoire de l'accélérateur, et non la puissance de calcul brute, détermine d'abord ce qui peut tourner. Elle se décompose en trois postes.

Poids du modèleparamètres x octets par poidsCache KVcroît avec tokens x séquencesActivations et tamponsgraphes, workspace, fragmentationMarge de sécuritééviter les erreurs OOMMémoire GPU disponible
La mémoire GPU se partage entre les poids (fixes), le cache KV (proportionnel aux tokens en vol) et les activations plus les tampons du moteur. Le cache KV est le poste qui grossit avec la charge.

Les poids

La formule est directe :

mémoire_poids ≈ nombre_de_paramètres × octets_par_poids

Un modèle de 8 milliards de paramètres en 16 bits (2 octets) occupe environ 16 Go ; en 8 bits, environ 8 Go ; en 4 bits, un peu plus de 4 Go, car les formats quantifiés stockent aussi des facteurs d'échelle (l'ordre de 4,5 à 5 bits effectifs par poids pour les formats 4 bits courants). Un modèle de 70 milliards occupe environ 140 Go en 16 bits et de l'ordre de 40 Go en 4 bits. Ici, 1 Go vaut 10^9 octets.

Le cache KV

Pendant la génération, chaque couche d'attention a besoin des clés (K) et des valeurs (V) de tous les tokens précédents. Le moteur les garde en mémoire plutôt que de les recalculer : c'est le cache KV. Sa taille est :

mémoire_KV = 2 × couches × têtes_KV × dim_tête × octets × tokens × séquences

Le facteur 2 compte K et V. Les « têtes KV » sont celles de l'attention à requêtes groupées (GQA), où plusieurs têtes de requête partagent une même tête de clé et de valeur, ce qui réduit fortement le cache. Les valeurs exactes sont dans la configuration du modèle (fichier config.json pour un modèle Hugging Face). Prenons deux configurations génériques, en cache 16 bits :

Configuration (générique)CouchesTêtes KVDim. têteOctets par token
Type 8 milliards3281282 x 32 x 8 x 128 x 2 = 131 072 (128 Kio)
Type 70 milliards8081282 x 80 x 8 x 128 x 2 = 327 680 (320 Kio)
Type 70 milliards sans GQA80641282 x 80 x 64 x 128 x 2 = 2 621 440 (2,5 Mio)

La dernière ligne montre pourquoi la GQA existe : sans elle, une seule séquence de 8 192 tokens coûterait environ 21 Go de cache pour la configuration de 70 milliards. Avec 8 têtes KV, elle en coûte environ 2,7 Go.

Les totaux illustratifs, activations et marge non comptées :

Scénario (illustratif)PoidsCache KVTotal approx.
8 Md, 4 bits, 1 séquence de 8 192 tokens≈ 4,5 Go≈ 1,1 Go≈ 5,6 Go
8 Md, 16 bits, 16 séquences de 8 192 tokens16 Go≈ 17,2 Go≈ 33 Go
70 Md, 4 bits, 1 séquence de 8 192 tokens≈ 40 Go≈ 2,7 Go≈ 42 Go
70 Md, FP8, 32 séquences de 8 192 tokens70 Go≈ 86 Go≈ 156 Go
Idem, cache KV en FP870 Go≈ 43 Go≈ 113 Go

Deux enseignements. Pour un utilisateur seul, les poids dominent. Pour un service mutualisé, le cache KV dépasse vite les poids : la ligne à 32 séquences ne tient pas sur deux GPU de 80 Go, alors que la même charge avec un cache en 8 bits y tient, avec une marge qu'il faut encore réserver aux activations. Plusieurs moteurs savent quantifier le cache KV (par exemple en FP8 ou en 8 bits) ; l'effet sur la qualité dépend du modèle et de la longueur de contexte, donc à évaluer. Le contexte maximal annoncé d'un modèle n'est pas gratuit : doubler la longueur doublera, au pire, le cache par séquence.

Les activations et les tampons (graphes de calcul, espaces de travail des noyaux, fragmentation) représentent un poste plus modeste, mais jamais nul. C'est pourquoi les moteurs exposent un plafond d'utilisation de la mémoire (voir plus bas) plutôt que d'allouer tout le GPU.

Quantifier : moins d'octets par poids

La quantification remplace les poids 16 bits par des représentations plus courtes. L'intuition de la compression d'image est correcte à un détail près : l'objectif n'est pas seulement de gagner de la place, mais de lire moins d'octets à chaque token généré, ce qui accélère aussi le décodage (voir la section suivante).

Un modèle de 8 milliards de paramètres16 bits (FP16 ou BF16)16 Go8 bits (INT8 ou FP8)≈ 8,5 Go4 bits (k-quants, AWQ, GPTQ)≈ 5 Go
Tailles illustratives d'un modèle de 8 milliards de paramètres selon la précision des poids (calcul : paramètres x bits effectifs / 8). Ces valeurs ne sont pas des mesures.

Les familles de formats

  • FP16 / BF16 : la référence. BF16 garde la plage dynamique du FP32 et se trouve dans la plupart des publications officielles.
  • FP8 et INT8 : un octet par poids. Le FP8 offre un gain de calcul natif seulement sur des GPU récents qui le supportent ; sur d'autres, il ne réduit que la mémoire. À vérifier selon l'accélérateur et le moteur.
  • 4 bits : le point de départ habituel pour les grands modèles sur matériel contraint. Trois écosystèmes dominent : les k-quants du format GGUF (llama.cpp, Ollama ; des variantes nommées par exemple Q4_K_M, Q5_K_M, Q6_K, Q8_0), AWQ et GPTQ.

AWQ (Lin et al.) choisit les poids à protéger d'après les activations observées sur des données de calibration, plutôt que d'après leur seule magnitude. GPTQ (Frantar et al.) quantifie couche par couche en minimisant l'erreur de reconstruction. Les k-quants de GGUF sont des quantifications par blocs, avec des échelles stockées par bloc ; ils fonctionnent aussi bien sur CPU que sur GPU et permettent de décharger une partie des couches sur le GPU quand la mémoire ne suffit pas.

GGUF (k-quants)moteur llama.cppou OllamaCPU, GPU ou lesdeuxdécharge partielledes couchesun seul fichier àcopierAWQ4 bits sur GPUbien supporté parles serveurs GPUcalibration surdes donnéesvérifier lesupport du modèleGPTQ4 bits sur GPUécosystème largecalibration surdes donnéesqualité variableselon laconfigurationFP8 ou INT8un octet par poidsperte généralementfaiblegain de calculselon le GPUcache KVquantifiable aussi
Le choix du format dépend d'abord du moteur cible, puis de la mémoire disponible. Il n'y a pas de format universellement meilleur, il y a un compromis à mesurer.

Pourquoi la qualité ne se dégrade pas uniformément

Il serait confortable de croire à une perte de qualité de quelques pourcents, partout. Ce n'est pas ce que l'on observe en pratique, pour des raisons qui sont en partie mécaniques :

  • Les erreurs d'arrondi s'accumulent sur les tâches longues : un raisonnement en plusieurs étapes, un calcul ou un programme exige que chaque étape reste exacte, alors qu'un résumé tolère une imprécision lexicale.
  • Les petits modèles ont moins de redondance et supportent moins bien les bits retirés. À mémoire égale, un grand modèle plus quantifié bat souvent un modèle plus petit moins quantifié (règle empirique, pas une loi, et à vérifier sur vos tâches).
  • Les données de calibration, quand le format en utilise (AWQ, GPTQ, et certaines variantes GGUF à matrice d'importance), sont souvent majoritairement en anglais. Mon hypothèse, que je n'ai pas de mesure générale pour appuyer, est que les langues et les domaines peu représentés (arabe dialectal, vocabulaire juridique ou médical local) sont plus exposés à la dégradation. C'est exactement le genre d'effet qu'un test sur vos propres textes détecte et qu'un benchmark anglophone ne voit pas.
  • La perplexité, souvent citée pour comparer des quantifications, mesure la prédiction du texte suivant, pas la réussite d'une tâche : deux quantifications de perplexité voisine peuvent se comporter différemment sur l'extraction structurée ou l'appel d'outils.

La règle pratique : partir d'un 8 bits ou d'un 4 bits de qualité supérieure (par exemple un k-quant de type Q5 ou Q6) si la mémoire le permet, descendre ensuite, et chaque fois comparer sur son jeu de test (voir plus bas).

Latence, débit et bande passante mémoire

Deux métriques d'usage distinctes :

  • TTFT (time to first token) : le délai entre l'envoi de la requête et le premier token reçu. Il dépend du préremplissage.
  • Débit de génération : le nombre de tokens par seconde après le premier, côté utilisateur (vitesse perçue) ou côté serveur (somme sur toutes les requêtes).
ClientMoteurGPURequête (prompt de N tokens)Préremplissage : N tokens enun passageCalcul intensif, remplit le cache KVPremier token (TTFT)Décodage : 1 token parpassageRelit poids et cache KV à chaque tokenTokens diffusés en flux
Le préremplissage traite tout le prompt en parallèle (limité par le calcul), puis le décodage produit un token à la fois en relisant les poids et le cache KV (limité par la bande passante mémoire).

Préremplissage : limité par le calcul

Traiter un prompt de N tokens coûte à peu près 2 x paramètres x N opérations en virgule flottante (règle d'ordre de grandeur pour un modèle dense). Pour un modèle de 8 milliards et un prompt de 4 000 tokens, cela fait environ 6,4 x 10^13 opérations : avec, par hypothèse, un calcul soutenu de 100 TFLOP/s, de l'ordre d'une demi-seconde. Le préremplissage exploite bien les unités de calcul, car tous les tokens du prompt sont traités ensemble. Un long prompt (RAG, historique de conversation) allonge donc directement le TTFT.

Décodage : limité par la bande passante mémoire

Pour générer un token, il faut lire tous les poids actifs (et le cache KV de la séquence) depuis la mémoire, pour très peu de calcul par octet lu. Un plafond théorique pour une séquence unique est donc :

tokens_par_seconde ≲ bande_passante_mémoire / octets_lus_par_token

Illustration : un modèle quantifié de 4,5 Go sur une mémoire à 100 Go/s plafonne autour de 22 tokens par seconde ; sur une mémoire dix fois plus rapide, autour de 220. La réalité est plus basse (noyaux imparfaits, cache KV, surcoût du moteur), mais l'ordre de grandeur explique deux faits pratiques. La quantification accélère le décodage, parce qu'elle réduit les octets lus. Et deux machines de puissance de calcul comparable peuvent avoir des vitesses de génération très différentes selon leur mémoire.

Pour un utilisateur interactif, quelques dizaines de tokens par seconde suffisent à dépasser la vitesse de lecture. Le vrai problème est la charge simultanée.

Pourquoi le batching change tout

En décodage, lire les poids une fois peut servir à générer le token suivant de plusieurs séquences à la fois : le coût en mémoire est quasi partagé, le calcul s'additionne. Le débit total croît donc presque linéairement avec le nombre de séquences, jusqu'à ce que le calcul ou la lecture des caches KV deviennent le goulot. Le prix est une latence par requête qui monte avec la charge. Tout l'art d'un serveur d'inférence est de maximiser ce débit sans dégrader la latence au-delà de ce que votre service tolère.

Mélange d'experts : paramètres totaux et paramètres actifs

Certains modèles sont de type mélange d'experts (MoE) : à chaque token, un routeur n'active qu'une fraction des blocs feed-forward (les « experts »). On parle de paramètres totaux et de paramètres actifs. Exemple hypothétique : un modèle de 100 milliards de paramètres totaux dont 10 milliards actifs par token.

  • La mémoire suit les paramètres totaux : il faut charger tous les experts, car on ne sait pas à l'avance lesquels seront appelés. Ce modèle hypothétique demande donc une mémoire de classe 100 milliards.
  • Le calcul et les octets lus pour un token isolé suivent les paramètres actifs : à bande passante égale, un décodage proche de celui d'un modèle de 10 milliards.

Cet avantage s'érode avec le batching. Avec de nombreuses séquences simultanées, des tokens différents sollicitent des experts différents, et la quasi-totalité des experts finit par être lue à chaque pas. Un MoE est donc particulièrement intéressant quand on a beaucoup de mémoire (grande mémoire unifiée, serveur multi-GPU) mais peu de bande passante par token, et moins quand la mémoire est la contrainte. La parallélisation sur plusieurs GPU (parallélisme d'experts ou de tenseurs) ajoute en outre des coûts de communication.

Moteurs : mono-utilisateur ou serveur mutualisé

Deux familles d'usage appellent des moteurs différents.

Usage individuel ou petit groupe. llama.cpp exécute des modèles GGUF sur CPU, GPU, ou les deux, avec une installation légère. Ollama emballe un moteur de la famille llama.cpp (à l'origine) avec un catalogue de modèles, une API locale et une gestion du chargement en mémoire. LM Studio et Jan offrent une interface graphique. L'objectif est la simplicité et la souplesse du matériel, pas le débit maximal.

Service mutualisé. vLLM et SGLang visent le débit sous charge concurrente. Deux mécanismes expliquent leur intérêt :

  • Le batching continu : au lieu d'attendre qu'un lot entier de requêtes soit terminé, le moteur insère de nouvelles requêtes dans le lot dès qu'une séquence se termine, token par token. Le GPU reste occupé même quand les requêtes ont des longueurs de sortie très différentes.
  • Le cache KV paginé (PagedAttention, introduit avec vLLM par Kwon et al.) : le cache n'est plus alloué en un bloc contigu de la taille maximale, mais en blocs de taille fixe, référencés par une table par séquence, à la manière d'une mémoire virtuelle. Cela réduit le gaspillage dû à la fragmentation et permet de partager des blocs entre séquences. SGLang ajoute avec RadixAttention une réutilisation des préfixes communs (prompt système, documents partagés) entre requêtes. Le gain dépend fortement de la part de préfixes communs dans votre trafic : à mesurer, pas à supposer.

llama.cpp propose lui aussi du batching continu et plusieurs emplacements parallèles dans son serveur, ce qui le rend utilisable pour quelques utilisateurs concurrents. L'écart avec vLLM ou SGLang se creuse quand la concurrence et les contextes augmentent.

llama.cppGGUFCPU, GPU ou mixteportable ou posteserveur HTTPintégréOllamainstallationsimplecatalogue demodèlesAPI localeidéal pour essayervLLMbatching continucache KV paginéAPI compatibleOpenAIserveur GPUSGLangbatching continuréutilisation despréfixessortiesstructuréesserveur GPU
Le choix du moteur suit la charge attendue : un utilisateur et du matériel hétérogène pour llama.cpp et Ollama, de la concurrence et des GPU dédiés pour vLLM et SGLang.

Quelques commandes (à vérifier pour votre version)

Les options changent d'une version à l'autre : vérifiez avec l'aide intégrée (--help) et la documentation de la version installée. Les noms de modèles ci-dessous sont des exemples ou des espaces réservés.

Ollama, usage local :

# Télécharger et ouvrir une session interactive
ollama run llama3.1:8b

# Voir les modèles chargés et où ils tournent (colonne PROCESSOR : GPU, CPU, ou partagé)
ollama ps

# Appel via l'API compatible OpenAI exposée en local (port 11434 par défaut)
curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "llama3.1:8b", "messages": [{"role": "user", "content": "Bonjour"}]}'

Selon la documentation d'Ollama, le serveur écoute par défaut sur 127.0.0.1:11434, garde un modèle 5 minutes en mémoire après la dernière requête (OLLAMA_KEEP_ALIVE), traite une requête à la fois par modèle par défaut (OLLAMA_NUM_PARALLEL) et met en file d'attente jusqu'à 512 requêtes (OLLAMA_MAX_QUEUE). Ces valeurs par défaut ont varié selon les versions. Exposer le serveur sur le réseau avec OLLAMA_HOST=0.0.0.0 n'ajoute aucune authentification : placez-le derrière un proxy qui en fournit une.

llama.cpp, serveur HTTP :

# -ngl : couches déchargées sur le GPU, -c : contexte, -np : emplacements parallèles
llama-server -m ./modele-q4_k_m.gguf -ngl 99 -c 16384 -np 2 --port 8080

Le serveur expose notamment /v1/chat/completions. Selon la documentation, le contexte demandé est en principe partagé entre les emplacements parallèles : vérifiez ce comportement pour votre version avant de dimensionner -c.

vLLM, API compatible OpenAI :

# Plafond d'utilisation mémoire du GPU et longueur de contexte maximale
vllm serve <organisation>/<modele> \
  --max-model-len 16384 \
  --gpu-memory-utilization 0.90 \
  --api-key "$VLLM_API_KEY"

Le serveur écoute par défaut sur le port 8000 et expose /v1/chat/completions ainsi qu'un point /metrics au format Prometheus. L'option --max-model-len borne la mémoire de cache par séquence ; --gpu-memory-utilization fixe la fraction de la mémoire GPU que le moteur peut utiliser ; ce qui reste après les poids et les activations sert au cache KV. Confirmez les noms d'options avec vllm serve --help.

Les paliers de matériel

Ordinateur portablePetits modèles :1 à 8 milliardsde paramètresMémoire : 1 à 6 GoPoste aveccarte graphiqueModèles moyens :12 à 32 milliardsde paramètresMémoire : 8 à 20 GoServeuravec GPUGrands modèles :70 milliardsde paramètres et plusMémoire : 40 Go et +
Plus le modèle est grand, plus il faut de mémoire. Ordres de grandeur pour des modèles quantifiés en 4 bits, cache KV d'un seul utilisateur inclus.

Portable. Pour un usage individuel : assistance de rédaction, résumé, code de faible complexité. Un modèle de 1 à 8 milliards en 4 bits tient en quelques gigaoctets. Les machines à mémoire unifiée (Mac à puce Apple, certaines machines x86 récentes) partagent la mémoire entre CPU et GPU et peuvent charger des modèles plus gros que ne le permettrait une carte graphique dédiée de même prix, avec une bande passante qui reste le facteur limitant en décodage. La concurrence y est très faible : pensez à un seul utilisateur.

Poste avec carte graphique. La mémoire vidéo de la carte fixe le plafond : un modèle moyen quantifié plus un contexte raisonnable. Si les poids ne tiennent pas entièrement, llama.cpp peut décharger une partie des couches sur le GPU et laisser le reste sur le CPU, au prix d'une vitesse nettement réduite car chaque token traverse la partie lente. Convient à une petite équipe pour un usage peu concurrent ou à un poste de développement.

Serveur GPU. Là, le dimensionnement porte sur la concurrence : combien de séquences simultanées, quelle longueur de contexte, quel TTFT acceptable. Les poids déterminent le nombre de GPU minimal ; le cache KV détermine combien de séquences s'y ajoutent (voir le tableau plus haut). Au-delà d'un GPU, le parallélisme de tenseurs répartit les poids mais demande des interconnexions rapides entre cartes ; sur des cartes reliées seulement par le bus PCIe, la communication peut devenir le goulot. Prévoyez aussi l'alimentation, le refroidissement et la disponibilité des cartes sur votre marché, ce qui n'est pas toujours garanti.

Un serveur d'inférence mutualisé

Passer d'un poste à une organisation, ce n'est pas seulement changer de machine : on ajoute des couches autour du moteur.

Applicationschat interne, outils métier, RAGPasserelle d'APIauthentification, quotas, journauxMoteur d'inférencebatching continu, cache KV paginéModèles et GPUpoids quantifiés, un ou plusieurs GPUSupervision, sécurité, audit
Un serveur mutualisé empile un moteur d'inférence, une passerelle qui authentifie et limite les requêtes, et des applications clientes. La supervision et la sécurité traversent toutes les couches.

Les applications parlent à une API compatible OpenAI, ce qui permet de changer de moteur ou de modèle sans réécrire les clients et de basculer vers un service hébergé en cas de besoin. La passerelle (un proxy ou une passerelle d'API existante) porte l'authentification, les quotas par équipe, la limitation de débit et la journalisation. Ne laissez pas un moteur d'inférence directement exposé : la plupart n'offrent qu'une authentification minimale par clé partagée, et aucune gestion fine des identités. Pour fournir à l'assistant l'accès à vos documents, voir L'IA et vos documents : la récupération se place devant le moteur, qui ne reçoit que le contexte déjà filtré par les droits.

Superviser

Un serveur d'inférence se supervise comme un service, avec des métriques propres. À suivre en priorité :

  • TTFT et latence entre tokens, en percentiles (p50, p95, p99) et non en moyennes : ce sont les queues de distribution que les utilisateurs remarquent.
  • Requêtes en cours et en attente : une file d'attente qui s'allonge signale la saturation, avant que les utilisateurs ne se plaignent.
  • Occupation du cache KV : proche de 100 %, le moteur doit évincer ou refuser des séquences, et la latence se dégrade.
  • Tokens par seconde agrégés, en entrée et en sortie, pour suivre la charge et le coût.
  • Mémoire et température du GPU, erreurs matérielles, et taux d'erreurs HTTP.

vLLM expose ces informations au format Prometheus sur /metrics (par exemple des métriques nommées vllm:time_to_first_token_seconds ou vllm:num_requests_running à la date de rédaction ; les noms évoluent selon les versions, comme celui de l'occupation du cache KV). Combinez-les avec des métriques GPU (par exemple celles de l'exportateur DCGM de NVIDIA, si vous êtes sur ce matériel) et avec un tableau de bord par équipe.

Évaluer avant de choisir

Les classements publics de modèles aident à présélectionner, pas à décider. Votre trafic a ses langues, ses formats, ses documents, ses exigences de précision. Une évaluation minimale tient en une journée :

  1. Rassembler 50 à 200 requêtes représentatives, anonymisées, avec une réponse attendue ou un critère de réussite vérifiable (extraction de champs, classification, citation correcte, code qui passe des tests).
  2. Passer chaque candidat (modèle, quantification, taille de contexte) sur ce jeu avec la même configuration de génération, de préférence à température basse pour la répétabilité.
  3. Noter automatiquement ce qui peut l'être, faire relire par un humain le reste, et séparer les résultats par langue et par type de tâche.
  4. Mesurer en parallèle le TTFT et le débit sous la concurrence réelle attendue, pas sur une requête isolée.
  5. Rejouer le même jeu à chaque changement de modèle, de format ou de version de moteur : c'est votre test de non-régression.

Si vous utilisez un modèle juge pour noter, sachez qu'il a ses propres biais (préférence pour les réponses longues, pour son propre style) et validez-le sur un échantillon relu à la main. Le test dira souvent qu'un modèle plus petit, bien quantifié, suffit pour une tâche précise : c'est la meilleure façon de réduire le matériel nécessaire.

Cloud ou local : le comparatif

IA hébergéeIA locale
DonnéesEnvoyées au fournisseur, selon son contrat et sa juridictionRestent sur votre infrastructure
Sans InternetImpossiblePossible
CoûtÀ l'usage, croît avec le volumeInvestissement et exploitation, relativement fixes
QualitéAccès aux modèles les plus avancésBons modèles ouverts, souvent un cran en dessous sur les tâches les plus difficiles
ExploitationAssurée par le fournisseurÀ votre charge
Mise en routeImmédiateQuelques heures (un poste) à quelques semaines (un service)

Le coût total

Comparer un abonnement à un prix de carte graphique est une erreur classique. Le coût d'une inférence locale comprend :

  • le matériel, amorti sur sa durée d'usage réaliste (les GPU et les modèles évoluent vite) ;
  • l'énergie et le refroidissement, proportionnels à la puissance et à l'utilisation ;
  • l'exploitation : installation, mises à jour des moteurs et des modèles, supervision, astreinte, sécurité, et le temps d'ingénieur que cela représente ;
  • l'hébergement : emplacement, réseau, redondance si le service est critique.

Le calcul qui compte est le coût par million de tokens réellement servis :

coût_par_million_de_tokens ≈ (matériel amorti + énergie + exploitation) / tokens_servis_sur_la_période × 10^6

Le dénominateur est le point faible : un GPU utilisé à 10 % coûte dix fois plus par token qu'un GPU utilisé à 100 %. Les prix des API évoluent, de même que ceux du matériel : je ne donne volontairement aucun chiffre. Faites le calcul avec vos devis, votre prix d'électricité et votre trafic mesuré, et comparez-le au prix par token de l'API que vous remplaceriez.

Quand le local n'a pas de sens

  • Faible volume. Si votre usage est occasionnel, l'amortissement d'un serveur ne sera jamais rentable, et une API (avec un contrat adapté aux données traitées) coûtera moins cher.
  • Besoin du meilleur modèle. Pour du raisonnement long, des tâches agentiques complexes ou des évaluations où l'écart de qualité se voit, les modèles ouverts restent souvent un cran en dessous des meilleurs modèles propriétaires. Mesurez cet écart sur vos cas, il varie.
  • Pas d'équipe pour l'exploiter. Un serveur sans supervision ni mises à jour devient vite une dette, et un risque de sécurité.
  • Charge très variable. Une capacité dimensionnée pour le pic reste inutilisée le reste du temps, alors qu'un service à l'usage absorbe l'élasticité.
  • Local ne veut pas dire sécurisé. Un serveur dans vos murs doit être protégé comme tout système sensible : segmentation réseau, authentification, journaux, sauvegardes, mises à jour. Une API locale sans authentification est une fuite potentielle.

L'inverse existe aussi : des données qui ne peuvent légalement ou contractuellement pas sortir, un fonctionnement hors ligne, ou un volume élevé et stable justifient souvent le local. L'approche hybride, qui garde en local les données sensibles et délègue le reste à un service hébergé, est fréquente ; elle est liée à la question de la souveraineté des données.

Ce qu'il faut retenir

En résumé

  • Mémoire des poids ≈ paramètres x octets par poids. Mémoire du cache KV = 2 x couches x têtes KV x dimension de tête x octets x tokens x séquences. Le premier poste est fixe, le second croît avec la charge.
  • La quantification réduit la mémoire et accélère le décodage, mais la perte de qualité n'est pas uniforme : elle dépend de la tâche, de la taille du modèle et de la langue. Mesurez.
  • Le préremplissage est limité par le calcul, le décodage par la bande passante mémoire. Le batching continu et le cache KV paginé rendent les serveurs comme vLLM et SGLang adaptés à la concurrence ; llama.cpp et Ollama visent l'usage individuel.
  • Un MoE demande la mémoire de ses paramètres totaux mais ne calcule que ses paramètres actifs, avec un avantage qui s'érode sous forte concurrence.
  • Supervisez TTFT, files d'attente et occupation du cache KV. Évaluez sur vos propres cas avant de choisir. Calculez le coût par token servi, pas le prix d'une carte.

Pour commencer : installez Ollama ou llama.cpp sur un poste, chargez un modèle de 8 milliards quantifié, et passez vos propres requêtes dessus avec un petit jeu de test. Vous saurez en une journée si le local vous suffit, et quelle taille de modèle et de contexte justifie du matériel dédié. La suite, ce sont les questions d'architecture : passerelle, accès aux documents, supervision. Elles sont traitées dans les autres articles liés ci-dessus.

Références

  • Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention : https://arxiv.org/abs/2309.06180
  • Zheng et al., SGLang: Efficient Execution of Structured Language Model Programs : https://arxiv.org/abs/2312.07104
  • Lin et al., AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration : https://arxiv.org/abs/2306.00978
  • Frantar et al., GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers : https://arxiv.org/abs/2210.17323
  • Documentation du serveur llama.cpp : https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md
  • Documentation vLLM, service en ligne : https://docs.vllm.ai/en/latest/serving/online_serving/
  • Documentation vLLM, métriques : https://docs.vllm.ai/en/latest/design/metrics/
  • FAQ Ollama : https://docs.ollama.com/faq