· 6 min · API

La cache dei prompt spiegata: quando fa risparmiare e quando no

La cache dei prompt spiegata: quando fa risparmiare e quando no

Alle 9:12 del mattino di un lunedì, uno dei nostri agenti di assistenza ha iniziato a costare 4x più del previsto.

Il modello non stava producendo allucinazioni, il grafico del traffico non era sbagliato e nessuno era passato per errore da Haiku a Opus. Il problema era più semplice: ogni richiesta includeva lo stesso manuale delle policy di 42,000 token, ma il nostro tasso di hit della cache dei prompt era praticamente nullo perché inserivamo un timestamp aggiornato e metadati specifici dell'utente prima del manuale.

Stesso contenuto. Stesso modello. Stessa applicazione. Nessun risparmio grazie alla cache.

Il caching dei prompt è una di quelle funzionalità che sembrano automatiche finché non provi a ridurre la spesa. In pratica, premia una struttura del prompt molto specifica: un prefisso ampio e stabile riutilizzato in molte richieste. Se comprendi questa frase, di solito puoi prevedere se il caching farà risparmiare o se, senza dare segnali, non produrrà alcun effetto.

Che cosa memorizza davvero il caching dei prompt

Il caching dei prompt non è memoria semantica. Il provider non sta dicendo: «Questo assomiglia a qualcosa che hai inviato prima». Il concetto è più vicino a:

«L'inizio di questa richiesta corrisponde abbastanza a una sequenza di token precedente, per questo modello e questa policy di cache, quindi possiamo riutilizzare i calcoli interni per quel prefisso».

Questa distinzione è importante.

Il caching dei prompt è generalmente utile quando invii ripetutamente lo stesso prefisso lungo:

  • Istruzioni di sistema
  • Schemi degli strumenti
  • Raccolte estese di documentazione
  • Cataloghi di prodotti
  • Contesto della base di codice
  • Manuali legali o delle policy
  • Esempi few-shot
  • Risultati di recupero statici riutilizzati in molte richieste

Di solito non aiuta molto quando ogni richiesta inizia in modo diverso:

  • Timestamp dinamici all'inizio
  • Dati specifici dell'utente prima del contenuto condiviso
  • Ordine casuale degli esempi
  • UUID specifici di ogni richiesta nella sezione memorizzabile in cache
  • Frammenti recuperati che cambiano ordine o formattazione
  • Cronologia della chat inserita prima delle istruzioni stabili

L'intervento tecnico fondamentale consiste nel mettere prima il contesto stabile e costoso, e poi quello variabile.

Anthropic e OpenAI a confronto: obiettivo simile, controlli diversi

Anthropic e OpenAI supportano entrambi il caching dei prompt, ma l'esperienza per gli sviluppatori è diversa.

Anthropic espone il caching dei prompt in modo più esplicito. Puoi contrassegnare i blocchi di contenuto con controlli della cache e poi esaminare campi di utilizzo come cache_creation_input_tokens e cache_read_input_tokens. Questo rende più facile capire se stai creando voci nella cache o leggendo da quelle esistenti.

Il caching dei prompt di OpenAI è più automatico sui modelli supportati. Quando un prefisso del prompt viene riutilizzato, i token di input in cache possono essere fatturati diversamente e riportati nei metadati di utilizzo. Di solito non inserisci punti di interruzione espliciti della cache nello stesso modo; strutturi invece le richieste affinché il prefisso riutilizzabile sia stabile a livello di byte e token.

La differenza pratica è tra controllo e comodità.

AspettoCaching esplicito in stile AnthropicCaching automatico in stile OpenAI
Controllo dello sviluppatoreMaggiore; puoi contrassegnare i blocchi memorizzabili in cacheMinore; il provider rileva i prefissi riutilizzabili
Facilità di debugDi solito maggiore grazie ai contatori di creazione e lettura della cacheDipende dai metadati di utilizzo esposti dal modello o dall'API
Importanza della struttura del promptMolto elevataMolto elevata
Ideale perGrandi blocchi statici, strumenti, documentazione, esempiPrefissi lunghi riutilizzati in chiamate ripetute
Problema tipicoPunto di interruzione della cache inserito dopo il contenuto dinamicoIl prefisso cambia prima che la cache possa trovare una corrispondenza
Modello mentale«Sto scrivendo e leggendo un prefisso che ha una sorta di nome»«Il provider riconosce questo prefisso ripetuto»

I dettagli di implementazione variano in base al modello e al provider e continuano a evolversi. Ma la regola architetturale resta stabile: il caching riguarda i prefissi ripetuti, non i prompt simili.

Il modello di prezzo: creazione e lettura

Un modo utile di ragionare sul caching dei prompt è dividere i token di input in tre categorie:

  1. Token di input normali: fatturati al consueto prezzo di input.
  2. Token di creazione della cache: token usati per creare una voce nella cache, spesso fatturati a un prezzo maggiorato o a una tariffa di scrittura specifica.
  3. Token di lettura della cache: token letti da una voce esistente nella cache, di solito fatturati a una tariffa scontata.

Anthropic espone direttamente questa distinzione con campi di utilizzo come:

{
  "usage": {
    "input_tokens": 812,
    "cache_creation_input_tokens": 42000,
    "cache_read_input_tokens": 0,
    "output_tokens": 684
  }
}

In una richiesta successiva, se il prefisso trova una corrispondenza nella cache, dovresti vedere qualcosa di più simile a:

{
  "usage": {
    "input_tokens": 936,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 42000,
    "output_tokens": 711
  }
}

La prima chiamata crea la cache. Le chiamate successive leggono da essa.

La convenienza economica dipende dai prezzi correnti del provider, dal TTL della cache e dal modello. Poiché i prezzi cambiano, preferisco rappresentarli con variabili nel codice anziché inserire numeri fissi nei documenti di progettazione.

Ecco una piccola funzione Python che uso quando devo decidere se vale la pena implementare il caching per una route:

def cache_savings(
    cached_tokens: int,
    normal_input_per_mtok: float,
    cache_write_per_mtok: float,
    cache_read_per_mtok: float,
    requests: int,
) -> dict:
    mtok = cached_tokens / 1_000_000

    no_cache = requests * mtok * normal_input_per_mtok
    with_cache = (
        mtok * cache_write_per_mtok +
        (requests - 1) * mtok * cache_read_per_mtok
    )

    return {
        "no_cache": round(no_cache, 6),
        "with_cache": round(with_cache, 6),
        "savings": round(no_cache - with_cache, 6),
        "savings_pct": round((1 - with_cache / no_cache) * 100, 2),
    }


print(cache_savings(
    cached_tokens=42_000,
    normal_input_per_mtok=3.00,
    cache_write_per_mtok=3.75,
    cache_read_per_mtok=0.30,
    requests=100,
))

Qui vengono usati solo prezzi a scopo illustrativo. È la struttura che conta.

Con un prefisso riutilizzabile di 42,000 token e 100 richieste, il caching è di solito eccellente. Con lo stesso prefisso e una sola richiesta, il caching può essere più costoso se il prezzo di scrittura è superiore al normale prezzo di input.

Questa è la prima grande insidia: il caching dei prompt è una forma di ammortamento. Se non riutilizzi il prefisso in cache, non ottieni il vantaggio.

La formula del punto di pareggio

Puoi stimare il punto di pareggio con:

no_cache_cost = N * T * normal_price

cache_cost = T * write_price + (N - 1) * T * read_price

Dove:

  • N è il numero di richieste che usano lo stesso prefisso
  • T è il numero di token memorizzabili in cache
  • normal_price è il normale prezzo dei token di input
  • write_price è il prezzo di creazione della cache
  • read_price è il prezzo di lettura della cache

Il caching fa risparmiare quando:

T * write_price + (N - 1) * T * read_price
  <
N * T * normal_price

La T si semplifica nel calcolo del puro pareggio economico, il che significa che il numero di riutilizzi e i prezzi relativi determinano la decisione. Ma il numero di token conta comunque sul piano operativo: risparmiare il 80% su 500 token è trascurabile; risparmiare la stessa percentuale su 80,000 token è una voce di bilancio.

Una versione utile per un calcolo approssimativo:

break_even_requests =
  (write_price - read_price) / (normal_price - read_price)

Se le scritture nella cache costano solo leggermente più dell'input normale e le letture costano molto meno, il punto di pareggio può essere molto basso. Se le scritture nella cache sono costose o il prefisso si ripete raramente, la convenienza del caching è fragile.

Come strutturare i prompt per avere prefissi stabili

La migliore ottimizzazione per il caching dei prompt non è un flag dell'API. È la disposizione del prompt.

Disposizione inefficace:

Request ID: req_8f19a
Current time: 2026-02-14T09:12:33Z
User: customer_4812
Locale: en-US

SYSTEM INSTRUCTIONS:
...

POLICY MANUAL:
[42,000 tokens of stable text]

USER QUESTION:
Can I get a refund after 45 days?

Questo impedisce il caching del prefisso perché il prompt diverge immediatamente.

Disposizione migliore:

SYSTEM INSTRUCTIONS:
...

POLICY MANUAL:
[42,000 tokens of stable text]

DYNAMIC REQUEST METADATA:
Request ID: req_8f19a
Current time: 2026-02-14T09:12:33Z
User: customer_4812
Locale: en-US

USER QUESTION:
Can I get a refund after 45 days?

Il blocco stabile viene prima. Il blocco dinamico viene dopo.

Per il caching esplicito in stile Anthropic, la struttura concettuale può essere questa:

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 800,
  "system": [
    {
      "type": "text",
      "text": "You are a support policy assistant..."
    },
    {
      "type": "text",
      "text": "Refund policy manual v2026-02-01:\n\n...",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Can I get a refund after 45 days?"
    }
  ]
}

Lo schema esatto della richiesta varia in base alla versione dell'API e all'SDK, quindi considera questo esempio come una struttura e non come codice da copiare e incollare. L'aspetto importante è che il grande blocco stabile sia esplicitamente memorizzabile in cache e rimanga invariato tra le chiamate.

Per il caching automatico in stile OpenAI, la struttura del prompt conta altrettanto, anche se non contrassegni manualmente un blocco:

{
  "model": "gpt-5.5",
  "messages": [
    {
      "role": "system",
      "content": "You are a support policy assistant...\n\nRefund policy manual v2026-02-01:\n\n..."
    },
    {
      "role": "user",
      "content": "Can I get a refund after 45 days?"
    }
  ]
}

Se il messaggio di sistema cambia a ogni richiesta, non dovresti aspettarti letture regolari dalla cache.

Un modello architetturale pratico

Per i sistemi in produzione, preferisco rendere espliciti nel codice dell'applicazione i prefissi dei prompt memorizzati in cache.

Un modello semplice:

prompt_prefix/
  support_policy_v17.txt
  tool_schema_v4.json
  examples_v9.md

runtime_request/
  user_question
  user_profile
  retrieved_recent_orders

Poi componi le richieste così:

from pathlib import Path

POLICY_PREFIX = Path("prompt_prefix/support_policy_v17.txt").read_text()
TOOL_SCHEMA = Path("prompt_prefix/tool_schema_v4.json").read_text()
EXAMPLES = Path("prompt_prefix/examples_v9.md").read_text()

def build_prompt(user_question: str, user_profile: dict) -> str:
    stable_prefix = f"""
You are a support policy assistant.

TOOLS:
{TOOL_SCHEMA}

POLICY:
{POLICY_PREFIX}

EXAMPLES:
{EXAMPLES}
""".strip()

    dynamic_suffix = f"""
USER PROFILE:
{user_profile}

USER QUESTION:
{user_question}
""".strip()

    return stable_prefix + "\n\n--- DYNAMIC REQUEST ---\n\n" + dynamic_suffix

In pratica, assegno anche una versione al prefisso. Se il manuale delle policy cambia, voglio che questo costituisca un evento deliberato di invalidazione della cache:

sha256sum prompt_prefix/support_policy_v17.txt

Quell'hash viene inserito nei log accanto al nome del modello, ai token di creazione della cache, ai token di lettura della cache e alla route della richiesta. Senza questa osservabilità, i bug della cache sono difficili da gestire perché la risposta continua a funzionare; costa semplicemente di più.

Una riga di log utile ha questo aspetto:

{
  "route": "support.answer",
  "model": "claude-sonnet-4-6",
  "prefix_hash": "9d3a4a...",
  "input_tokens": 932,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 42000,
  "output_tokens": 688,
  "latency_ms": 1840
}

Non ottimizzare basandoti solo sulla fatturazione. Registra nei log il comportamento della cache per ogni route.

Latenza: spesso migliore, ma non fa miracoli

Il caching dei prompt può ridurre la latenza perché il provider del modello può riutilizzare i calcoli per il prefisso in cache. Ma non definirei uno SLA presumendo una riduzione fissa della latenza senza averla misurata sul mio carico di lavoro.

Ciò che accade davvero in produzione è più complesso:

  • I prompt brevi potrebbero non mostrare variazioni significative della latenza.
  • I prefissi lunghi memorizzati nella cache spesso migliorano il tempo al primo token.
  • La lunghezza dell'output resta il fattore dominante in molte richieste.
  • Le chiamate agli strumenti, la latenza di rete e le attese in coda possono nascondere i vantaggi della cache.
  • I mancati riscontri nella cache provocano picchi nella latenza di coda se le scritture sono più lente delle letture.

Una configurazione realistica per il benchmark è semplice:

# warm cache
python run_eval.py --case support_refund --repeat 1

# measure cache reads
python run_eval.py --case support_refund --repeat 50 --jsonl out.jsonl

# inspect p50/p95 by cache_read_input_tokens > 0
python analyze_latency.py out.jsonl

Misura separatamente le richieste con riscontro nella cache e quelle senza. Mescolarle produce un valore che non spiega né le une né le altre.

Insidie che incontro nei sistemi reali

1. Contenuti dinamici prima dei contenuti stabili

Questo è l'errore più comune. Un timestamp, un ID di richiesta, un dump dei flag di funzionalità, le impostazioni locali dell'utente o l'assegnazione a un esperimento vengono inseriti all'inizio del prompt di sistema.

Spostali più in basso.

2. Un JSON «equivalente» non è equivalente

Questi due frammenti sono semanticamente identici, ma non necessariamente identici ai fini della cache:

{"name":"refund_lookup","timeout":3,"strict":true}
{
  "strict": true,
  "timeout": 3,
  "name": "refund_lookup"
}

Se includi schemi degli strumenti o configurazioni nel prefisso memorizzato nella cache, serializzali in modo deterministico:

import json

def stable_json(data: dict) -> str:
    return json.dumps(data, sort_keys=True, separators=(",", ":"))

Questo evita mancati riscontri accidentali nella cache dovuti a variazioni nell'ordine delle chiavi o negli spazi bianchi.

3. Il recupero dei contenuti può compromettere la memorizzazione nella cache

I sistemi RAG spesso costruiscono prompt di questo tipo:

Retrieved documents:
[doc A]
[doc B]
[doc C]

Instructions:
...

Se i risultati del recupero variano per ogni query, anche il prefisso varia per ogni query. Va bene se il contesto recuperato è effettivamente dinamico, ma non inserire le istruzioni stabili dopo di esso.

Meglio:

Instructions:
...

Long-lived product documentation:
[stable docs]

Query-specific retrieved documents:
[doc A]
[doc B]
[doc C]

Per i sistemi con volumi elevati, valuta la suddivisione del contesto in:

  • Istruzioni stabili a livello globale
  • Documentazione stabile per ciascun tenant
  • Contenuti recuperati specifici per utente o query

Ogni livello ha un comportamento diverso rispetto alla cache.

4. I TTL della cache contano

Alcune voci della cache scadono. Se il traffico arriva a raffiche, un prefisso può essere riutilizzato intensamente per dieci minuti e poi smettere di essere usato. Una durata maggiore della cache può aiutare, ma prezzi o disponibilità potrebbero variare a seconda del fornitore e del modello.

È qui che conta la distribuzione delle richieste. «Riceviamo 10,000 richieste al giorno» è meno utile di «riceviamo 200 richieste al minuto per questo esatto prefisso tra le 9 e le 10 del mattino».

5. I cambi di modello invalidano le ipotesi

Non dare per scontato che un prefisso memorizzato nella cache per un modello sia riutilizzabile per un altro. Se instradi le richieste tra Claude Opus 4.8, Sonnet 4.6, GPT-5.5, Gemini 3 o modelli aperti come Llama, Qwen, DeepSeek, MiniMax o Kimi, monitora il comportamento della cache per ciascun modello.

L'instradamento tra più modelli è utile, ma complica l'ammortamento. Se il traffico viene suddiviso tra cinque modelli, ciascuno potrebbe ricevere meno prefissi ripetuti.

6. La personalizzazione dei prompt può essere controproducente

I team spesso personalizzano i prompt di sistema:

You are helping {{customer_name}}, who is on plan {{plan_name}}.

Sembra innocuo, ma se la personalizzazione compare prima del contenuto memorizzato nella cache, ogni cliente avrà un prefisso diverso. Inserisci la personalizzazione più avanti, a meno che non cambi davvero il modo in cui il modello interpreta il blocco stabile.

Quando la memorizzazione dei prompt nella cache fa risparmiare

La cache è solitamente molto adatta quando:

  • Il prefisso memorizzabile nella cache è lungo, spesso migliaia o decine di migliaia di token.
  • Lo stesso identico prefisso viene riutilizzato molte volte.
  • Il prefisso rimane stabile tra le richieste.
  • Il traffico arriva entro il periodo di validità della cache.
  • Puoi monitorare i token di creazione della cache e quelli letti dalla cache.
  • Il percorso di instradamento ha una composizione del prompt prevedibile.

Esempi concreti:

  • Un assistente di programmazione include ripetutamente la stessa mappa del repository e la stessa guida di stile.
  • Un bot di assistenza include lo stesso manuale delle politiche per ogni domanda sui rimborsi.
  • Un agente usa uno schema degli strumenti statico e di grandi dimensioni in ogni richiesta.
  • Un assistente di ricerca interno include la stessa panoramica del corpus per un team.

Per questi carichi di lavoro, la memorizzazione dei prompt nella cache può essere una delle ottimizzazioni dei costi più efficaci, perché non richiede di ridurre la qualità del contesto. Mantieni il prompt lungo; semplicemente smetti di pagare ogni volta il prezzo pieno dell'input.

Quando la memorizzazione dei prompt nella cache non aiuta

La cache offre benefici limitati o risulta controproducente quando:

  • Il prompt è breve.
  • I prefissi vengono riutilizzati raramente.
  • La maggior parte del contesto è costituita da contenuti recuperati specifici per la query.
  • I dati dinamici compaiono prima dei dati stabili.
  • Modifichi continuamente le istruzioni durante gli esperimenti.
  • Il traffico è distribuito in piccoli volumi tra molti modelli, tenant o varianti del prompt.
  • Le scritture nella cache costano di più e le letture sono troppo rare per ammortizzarle.

Un'insidia comune durante la valutazione: la memorizzazione dei prompt nella cache sembra poco vantaggiosa in un notebook perché esegui ogni caso una sola volta. Poi sembra eccellente in produzione perché migliaia di utenti condividono lo stesso prefisso stabile. Succede anche il contrario: una demo ripete lo stesso prompt 100 volte e mostra grandi risparmi, ma in produzione la personalizzazione per tenant impedisce il riutilizzo.

Esegui i test con la distribuzione reale delle richieste.

Una semplice checklist per valutare l'idoneità alla cache

Prima di abilitare la memorizzazione dei prompt nella cache o farvi affidamento, verifico:

  • Esiste almeno un prefisso stabile che superi qualche migliaio di token?
  • Compare prima di tutti i contenuti dinamici?
  • La serializzazione è deterministica?
  • Il prefisso è versionato e ne viene calcolato l'hash?
  • Posso registrare i token di creazione della cache e quelli letti dalla cache?
  • Conosco il numero previsto di riutilizzi entro il periodo di validità della cache?
  • Ho misurato separatamente la latenza per i riscontri nella cache e per i mancati riscontri?

Se la risposta a tre o più domande è «no», la cache potrebbe comunque funzionare, ma stai andando per ipotesi.

Indicazioni pratiche

La memorizzazione dei prompt nella cache non è una compressione magica. È il riutilizzo di un prefisso stabile di token, e il vantaggio economico deriva dal pagare una volta il costo di creazione e molte volte un costo di lettura inferiore.

Le indicazioni operative per gli ingegneri sono semplici:

  • Metti prima i contenuti stabili di grandi dimensioni: istruzioni, strumenti, documentazione, esempi.
  • Sposta timestamp, metadati dell'utente, risultati del recupero e ID di richiesta dopo il prefisso memorizzabile nella cache.
  • Monitora cache_creation rispetto a cache_read token per percorso di instradamento e modello.
  • Usa una serializzazione deterministica per gli schemi degli strumenti e le configurazioni JSON.
  • Calcola il punto di pareggio usando i prezzi effettivi del tuo fornitore e la distribuzione del traffico.
  • Presta attenzione all'instradamento tra più modelli, alla personalizzazione per tenant e ai prompt brevi.
  • Misura separatamente la latenza per i riscontri e i mancati riscontri nella cache, invece di affidarti alle medie.

La migliore ottimizzazione della cache dei prompt che ho visto non aveva nulla di ingegnoso: abbiamo spostato 42,000 token stabili prima di 12 token dinamici. Il comportamento del modello non è cambiato. La fattura sì.

A

AI Prime Tech pubblica questo blog. Gli articoli sono redatti con l'assistenza dell'AI; verifica nella documentazione ufficiale i dettagli specifici della versione, come gli ID dei modelli, i prezzi e i limiti, prima di farvi affidamento.

Ottieni accesso all'API Claude a un costo inferiore

Un'unica chiave API per Claude Opus 5.5, Sonnet 5, Haiku 4.5 e Fable 5.1, oltre a GPT-6 modelli. Pagamento a consumo, senza abbonamento.

Ottieni la tua chiave API →
AI Prime Tech è un gateway API indipendente di terze parti. Claude™ e Anthropic® sono marchi di Anthropic, PBC. Non si intende suggerire alcuna affiliazione o approvazione.