Prompt Caching
La mise en cache des prompts réutilise les états clé-valeur calculés par un LLM pour un préfixe de prompt récurrent. Les requêtes suivantes évitent ainsi ce calcul et coûtent moins cher.
La mise en cache des invites, également appelée mise en cache des préfixes, stocke les résultats intermédiaires calculés par un grand modèle de langage (LLM) pour le début d’une invite, puis les réutilise pour les requêtes ultérieures qui commencent exactement par le même texte. De nombreuses requêtes partagent un long préfixe inchangé, comme une invite système, des définitions d’outils, un ensemble d’exemples, un long document ou l’historique de la conversation, suivi d’un court nouvel élément. En cas d’accès au cache, le serveur ne traite que les nouveaux jetons, ce qui réduit le délai avant le premier jeton de sortie et, avec les API hébergées, ramène le prix de l’entrée mise en cache à une fraction du tarif normal.
Fonctionnement de la mise en cache des invites#
Un LLM à transformeur répond en deux phases. Lors du préremplissage, chaque couche calcule un vecteur de clé et un vecteur de valeur pour chaque jeton de l’invite ; lors du décodage, chaque nouveau jeton prête attention à toutes ces clés et valeurs par l’intermédiaire du mécanisme d’attention. Au sein d’une requête, le cache KV conserve ces tenseurs afin que chaque jeton généré ne recalcule pas l’invite. La mise en cache des invites les conserve d’une requête à l’autre. Comme l’attention de ces modèles est causale, les clés et les valeurs d’un jeton dépendent uniquement des jetons qui le précèdent. Deux invites ayant le même préfixe ont donc des clés et des valeurs identiques pour celui-ci, et la copie stockée peut remplacer un nouveau calcul.
L’exemple suivant montre cette réutilisation avec GPT-2 de Hugging Face Transformers. Il préremplit une fois une invite système de 409 jetons, répond ensuite à deux questions en traitant uniquement leurs jetons à partir du préfixe mis en cache, puis compare le résultat à un recalcul complet :
import copy
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")
# A long system prompt shared by every request, followed by different user questions
system = "You answer questions about a camera store. " + "Returns are accepted within 30 days with a receipt. " * 40
questions = [" Question: Can I return a lens?", " Question: Do you ship abroad?"]
prefix_ids = tokenizer(system, return_tensors="pt").input_ids
with torch.no_grad():
# Prefill the shared prefix once and keep its key-value cache
prefix_cache = model(prefix_ids).past_key_values
for question in questions:
ids = tokenizer(question, return_tensors="pt").input_ids
# Cache hit: only the question's tokens run through the model
cached = model(ids, past_key_values=copy.deepcopy(prefix_cache)).logits[0, -1]
# No cache: the whole prompt is computed from scratch
full = model(torch.cat([prefix_ids, ids], dim=1)).logits[0, -1]
same = torch.allclose(cached, full, atol=1e-3)
print(f"Computed {ids.shape[1]} of {prefix_ids.shape[1] + ids.shape[1]} tokens, same next-token scores: {same}")L’exécution affiche Computed 8 of 417 tokens, same next-token scores: True et Computed 7 of 416 tokens, same next-token scores: True : chaque requête a fait passer moins de 2 % de son invite dans le modèle et obtenu les mêmes scores pour le jeton suivant que le calcul complet.
Les moteurs open source de mise à disposition de modèles appliquent cette méthode automatiquement. vLLM conserve le cache KV dans des blocs de taille fixe, conformément à l’organisation mémoire de PagedAttention, réutilise, pour chaque nouvelle requête, les blocs du préfixe correspondant le plus long et évince les blocs les moins récemment utilisés lorsque la mémoire du GPU vient à manquer. RadixAttention de SGLang conserve les préfixes mis en cache dans un arbre radix, afin que les requêtes partageant une portion initiale commune puissent la réutiliser, et l’article sur SGLang fait état d’un débit jusqu’à 6,4 fois supérieur à celui d’autres moteurs d’inférence de pointe. L’article sur Prompt Cache d’In Gim et de ses collègues, présenté à MLSys 2024, étend la réutilisation au-delà des préfixes exacts aux modules de prompt déclarés, tels que les gabarits et les documents, et fait état de réductions du délai avant le premier jeton allant de 8 fois sur GPU à 60 fois sur CPU.
Mise en cache des invites dans les API de LLM#
Les API hébergées proposent le même mécanisme, moyennant un coût. La mise en cache des invites d’OpenAI est activée par défaut pour les modèles compatibles, tandis que la mise en cache des invites de Claude d’Anthropic s’active avec un champ cache_control, soit une fois par requête, soit sur un maximum de quatre blocs de contenu. Anthropic facture la lecture du cache au dixième du prix de base de l’entrée, ou moins, et l’écriture dans son cache par défaut de cinq minutes à 1,25 fois le prix de base ; chaque accès au cache réinitialise la durée de vie de cinq minutes. Les deux fournisseurs ne reconnaissent que les préfixes identiques : Anthropic compare les outils, puis l’invite système, puis les messages. Modifier une définition d’outil invalide donc tout le cache qui la suit. Le guide d’OpenAI recommande de placer d’abord les instructions stables et les documents de référence, puis les informations propres à chaque utilisateur.
Les charges de travail ayant de longs préfixes partagés sont celles qui en bénéficient le plus :
- Agents d’IA : chaque étape renvoie les définitions d’outils et l’historique complet, soit l’invite de l’étape précédente, complétée par la dernière action et son résultat.
- Chatbots : chaque tour d'une conversation prolonge l'invite du tour précédent, de sorte que l'historique est mis en cache jusqu'au nouveau message.
- Réponses aux questions sur des documents : de nombreuses questions portant sur un même contrat long, rapport ou dépôt réutilisent le document traité, et les pipelines de recherche le réutilisent chaque fois que les mêmes passages sont récupérés.
- Invites few-shot : des dizaines d'exemples fixes sont calculés une fois et réutilisés pour chaque entrée.
Les modèles de vision à vocabulaire ouvert réutilisent le calcul des invites de manière similaire. Ultralytics YOLOE encode une seule fois les invites de classe comme « chariot élévateur » avec un encodeur de texte MobileCLIP, lorsque set_classes() est appelé, et stocke les plongements obtenus dans le modèle, de sorte que les prédictions ultérieures ignorent entièrement l'encodeur de texte ; save_prompt_embeddings() les écrit dans un fichier NPZ qu'une session ultérieure charge avec load_prompt_embeddings() au lieu de relancer l'encodeur.
Mise en cache des invites et notions connexes#
- Cache KV : réutilise les clés et les valeurs entre les jetons d'une même génération. La mise en cache des invites les réutilise entre différentes requêtes.
- Mise en cache sémantique : stocke des réponses complètes et renvoie l'une d'elles lorsqu'une nouvelle requête signifie la même chose qu'une requête précédente, en ignorant entièrement le modèle. La mise en cache des invites exécute toujours le modèle sur la nouvelle partie de l'invite et génère une réponse inédite.
- Compression d'invite : raccourcit l'invite elle-même, ce qui convient aux textes qui changent à chaque requête. Les deux méthodes se combinent bien : la partie fixe d'une invite est mise en cache et la partie variable est compressée.
- Ingénierie des invites : détermine le contenu de l'invite. La mise en cache change uniquement la quantité de contenu que le serveur recalcule, et un cache hit laisse les scores du jeton suivant inchangés, à l'arrondi en virgule flottante près.










