Cache de prompt Ollama — où vous éditez décide de l’addition
Six sondes, une VM neuve : le repeat exact ré-évalue 1,539 jetons en 0.2 s contre 75.6 s à froid — et un mot déplacé en plein milieu du prompt refacture 49 s.
verify: six sondes, une VM neuve, seed 42 · temp 0 · ollama 0.40.16 · reçus ci-dessous, log promptcache-2026-11-12.log
Fig 1 — six sondes, un prompt. Les barres estompées sont le reçu : une édition au milieu du prompt a remboursé 65% de l’addition à froid, et le réordonnancement a surfacturé le chargement à froid lui-même.
Que garde vraiment le cache de prompts d’ollama ?
Pas votre texte. Quand ollama évalue un prompt, il calcule un tenseur KV pour chaque jeton — l’empreinte d’attention de ce jeton contre tous ceux d’avant — et le runner garde ces tenseurs en RAM tant que le modèle reste chargé. Un nouveau prompt est confronté à ce magasin jeton par jeton, depuis le début. Chaque jeton qui prolonge exactement l’ancien préfixe est gratuit. Le premier jeton qui diffère est la frontière : tout, de là jusqu’à la fin, est relu au prix fort. C’est la même résidence KV que couvrait notre article KV-cache pour le timing de déchargement — le cache qui sert la vitesse est le cache qui retient la RAM (et pourquoi keep_alive décide combien de temps l’un comme l’autre survit — l’article fenêtre de contexte détient le volet dimensionnement de cette addition).
keep_alive si votre boucle bavarde avec des pauses.Pourquoi le repeat exact n’a coûté que 0.2 seconde ?
La sonde : un prompt de 1,539 jetons — huit sections numérotées de faits de logs de fixture, puis une question — posé à froid sur une VM neuve. Le moteur a lu les 1,539 jetons à 20.4 tok/s et facturé 75.6 s d’évaluation de prompt. La demande identique, renvoyée avec le modèle toujours résident : 0.2 s. Même endpoint, même corps, rien n’a été basculé — ollama fait ça sans flag, sans cache: true, sans incantation de préchauffage. Vous touchez la remise à chaque re-demande ; ce post parle de ne pas la rendre.
curl http://localhost:11434/api/generate -d '{
"model": "qwen3:4b",
"prompt": "<your 1,500-token prompt>",
"keep_alive": "45m",
"think": false,
"options": {"seed": 42, "temperature": 0, "num_predict": 128}
}'
verify: P1 à froid 75.6 s → P2 repeat 0.2 s, corps de sonde identique à l’octet près, modèle résident · promptcache-2026-11-12.log
L’endroit où vous éditez décide de ce que vous payez
Nous avons gardé le corps de 1,539 jetons et déplacé exactement un mot, de trois façons. Changez un mot dans la dernière phrase : 4.2 s — la tête partagée a survécu, seule la queue a été relue. Ajoutez une phrase après la question : 1.4 s — hit quasi total, cinq nouveaux jetons facturés à la marge. Changez un mot au fait 41 sur 96, en plein corps : 49.2 s — 65% de l’addition à froid, payés pour déplacer un adjectif. Le cache a la mémoire d’un éléphant et le pardon d’un douanier : il se souvient de tout, et un seul formulaire fautif annule tous les tampons du carnet — pour tout ce qui suit le formulaire fautif.
| sonde | ce qui a changé | prompt-eval | demande entière | vs froid |
|---|---|---|---|---|
| P1 à froid | rien — VM neuve, première demande | 75.6 s | 111.8 s | référence |
| P2 repeat | rien — corps identique | 0.2 s | 26.6 s | 370× plus vite |
| P3 suffixe | +1 phrase après la question | 1.4 s | 27.2 s | 54× plus vite |
| P4 édit milieu | 1 mot au fait 41/96 | 49.2 s | 75.2 s | 65% du froid |
| P5 réordre | sections 1–2 ↔ 7–8 permutées | 79.9 s | 135.5 s | pire qu’à froid |
| P6 près fin | 1 mot dans la dernière phrase | 4.2 s | 34.0 s | 18× plus vite |
prompt de 1539 jetons · le prompt-eval est l’addition de relecture ; la « demande entière » ajoute la génération de 128 jetons, restée ~25–29 s tout du long.
Pourquoi réordonner facture plus qu’un chargement à froid ?
Parce que la frontière est au jeton ~1. Permutez les deux premières sections avec les deux dernières et le préfixe partagé est vide — le match meurt immédiatement et chaque jeton refacture. Mais P5 a facturé 79.9 s, pas 75.6 s : 5.7% au-dessus du chargement à froid pour lequel il a jeté la remise. Nous n’allons pas prétendre avoir attrapé le coupable — la note honnête, c’est que la passe de génération a aussi tourné 2.1× plus lentement sur cette sonde (55.4 s contre 25.5–29.4 s pour toute autre demande, même seed, même budget). L’état chaud du serveur rejoint l’addition de façons qu’un diagramme de cache ne montre pas ; l’article déterminisme a déjà rencontré ce témoin avec un jeton basculé à temp 0. Ce que nous pouvons affirmer en reçu : un prompt réordonné n’est pas un « même prompt, ordre différent ». C’est une addition toute neuve, plus du bruit.
La liste des correctifs
| symptôme | ce qui se passe | le correctif |
|---|---|---|
| chaque requête sent le chargement à froid | le modèle se décharge entre les demandes — le cache meurt avec lui | montez keep_alive ; vérifiez load_duration dans la réponse |
| minuscules éditions de prompt, latence énorme | l’édition siège au milieu du prompt ; la queue refacture depuis la divergence | déplacez la partie volatile en queue de prompt |
| le « même prompt » facture différemment à chaque run | l’ordre ou le boilerplate a dérivé entre requêtes | gelez la tête octet par octet ; diffez les prompts, pas les vibes |
P1 cold-full-ask prompt_eval 75,646 ms (1,539 tok · 20.4 tok/s) wall 111.8 s P2 exact-repeat prompt_eval 203 ms wall 26.6 s P3 suffix-only prompt_eval 1,402 ms (+5 tok) wall 27.2 s P4 mid-edit-kill prompt_eval 49,176 ms (1 word, fact 41/96) wall 75.2 s P5 reorder-full-miss prompt_eval 79,878 ms (secs 1–2 ↔ 7–8) wall 135.5 s P6 edit-near-end prompt_eval 4,189 ms (1 word, last sentence) wall 34.0 s
Un prompt. Six additions, de 0.2 à 79.9 secondes — un écart de 370× sans aucun réglage changé ni aucun flag basculé. Le cache était toujours actif. La seule variable, c’était l’endroit où nous osions éditer.
dernier test 2026-11-12
qwen3:4b · 2,497,293,931 B · sha256 359d7dd4…74e7 · ollama 0.40.16 · une VM Arch neuve, 2 vCPU — bench CPU, zéro prétention VRAM