Cache de prompt Ollama — où vous éditez décide de l’addition

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.

HUMANpar @msvram2d7 min de lecture

verify: six sondes, une VM neuve, seed 42 · temp 0 · ollama 0.40.16 · reçus ci-dessous, log promptcache-2026-11-12.log

secondes de prompt-eval · prompt de 1,539 jetons · qwen3:4b · 2 vCPU · demande à froid = la ligne 100% référence à froid 75.6 s 75.6 sP1 à froid 0.2 sP2 repeat 1.4 sP3 suffixe 49.2 sP4 édit milieu 79.9 sP5 réordre 4.2 sP6 près fin

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).

préfixe touché — jetons gratuits. Des octets identiques depuis la position 0 ne coûtent rien à re-traiter. 0.2 s pour 1,539 jetons, mesuré.
première divergence — la frontière. Un jeton modifié invalide tous les jetons après lui. Aucun crédit partiel vers l’arrière ; la queue refacture toujours.
résidence — keep_alive. Le cache vit autant que le modèle. Déchargez le modèle et la remise meurt avec lui ; épinglez 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.

sondece qui a changéprompt-evaldemande entièrevs froid
P1 à froidrien — VM neuve, première demande75.6 s111.8 sréférence
P2 repeatrien — corps identique0.2 s26.6 s370× plus vite
P3 suffixe+1 phrase après la question1.4 s27.2 s54× plus vite
P4 édit milieu1 mot au fait 41/9649.2 s75.2 s65% du froid
P5 réordresections 1–2 ↔ 7–8 permutées79.9 s135.5 spire qu’à froid
P6 près fin1 mot dans la dernière phrase4.2 s34.0 s18× 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ômece qui se passele correctif
chaque requête sent le chargement à froidle modèle se décharge entre les demandes — le cache meurt avec luimontez keep_alive ; vérifiez load_duration dans la réponse
minuscules éditions de prompt, latence énormel’édition siège au milieu du prompt ; la queue refacture depuis la divergencedéplacez la partie volatile en queue de prompt
le « même prompt » facture différemment à chaque runl’ordre ou le boilerplate a dérivé entre requêtesgelez la tête octet par octet ; diffez les prompts, pas les vibes
reçu · six sondes, une VM neuve (qwen3:4b · ollama 0.40.16 · 2 vCPU · prompt 1,539 tok)
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