Caché de prompts para LLM en Python: tutorial práctico con código
Contenido
- 0. Preparación
- 1. Llamadas con caché (iguales para todos los proveedores)
- 2. Anthropic Claude — Marcadores cache_control explícitos
- 3. OpenAI GPT-5.x — Caché automática
- 4. Google Gemini — Caché implícita
- 5. DeepSeek-v4-flash — Caché automática persistente en disco
- 6. Alibaba Qwen — Hit informado, descuento variable
- 7. Comparativa entre proveedores (medición del 2026-05-25)
- 8. Lista de comprobación antes del despliegue
- 9. Patrones que tienen en cuenta el TTL
- 8.1 Cargas ligadas a una sesión (chat, asistentes de IDE)
- 8.2 Heartbeat para batch / cron
- 8.3 Documentos de acceso esporádico
- 10. Qué aporta realmente el gateway
- Preguntas frecuentes
TL;DR — Un solo SDK de OpenAI, un único base_url y acceso a los principales LLM. Las cifras de este artículo se midieron contra el gateway de Synthorai en producción el 2026-05-25, con un system prompt estable de unos 7,300 tokens. La aportación del gateway es sencilla: un único endpoint, una sola cabecera de autenticación y un campo usage.cost que evita mantener una matriz de precios por proveedor. Las matemáticas de Transformer que sustentan la caché se explican en la Parte 1: principios de la caché; las decisiones de diseño de cada proveedor se analizan en la Parte 2: comparativa de proveedores.
Serie: Parte 3 de 5 · Anteriores: Parte 1 — Principios de la caché · Parte 2 — Comparativa y evaluación de proveedores · Siguiente: Parte 4 — Mejor LLM según el caso de uso · Parte 5 — Integración con LangChain
0. Preparación
pip install openai
# common.py — reused across every example
import os, time
from openai import OpenAI
oai = OpenAI(
api_key=os.environ["SYNTHORAI_KEY"],
base_url="https://synthorai.io/v1",
)
El gateway usa el formato de intercambio de OpenAI para todos los modelos que expone (GPT, Claude, Gemini, DeepSeek y Qwen). Solo hay que cambiar el campo model, no el SDK. La autenticación usa Authorization: Bearer <key>.
IDs de modelos con caché disponibles en el gateway público (instantánea de 2026-05): claude-haiku-4-5, claude-sonnet-4-5 / 4-6, claude-opus-4-5 / 4-6 / 4-7, gpt-5.4-mini, gpt-5.4-nano, gpt-5.2, gpt-5.5-pro, gemini-2.5-flash, gemini-2.5-pro, gemini-3.1-pro-preview, deepseek-v4-flash, qwen3-max, qwen3.5-flash. La lista completa y actualizada está en GET /v1/models.
1. Llamadas con caché (iguales para todos los proveedores)
No hace falta activar nada. Si el modelo admite caché de prompts en el proveedor, el gateway transmite los metadatos de la respuesta. Dos campos indican qué ocurrió:
resp = oai.chat.completions.create(
model="gpt-5.4-mini",
max_tokens=128,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT}, # ~7K tokens
{"role": "user", "content": "First question"},
],
)
print(resp.usage.prompt_tokens_details.cached_tokens) # cache hit count
print(resp.usage.cost) # USD, gateway-computed
cached_tokens es el número de tokens de entrada encontrados en la caché de prefijos del proveedor. usage.cost es el precio en USD que el gateway calcula para esa llamada concreta, sin necesidad de mantener localmente las tarifas de cada proveedor.
Dos reglas derivadas de la arquitectura que se aplican a todos los proveedores:
- Primero el contenido estable; al final, el variable. El prefijo se compara desde el token cero. Cambiar un solo byte al principio invalida todo el prefijo.
- No incluyas datos dinámicos en el system prompt. Las marcas de tiempo actuales, los IDs de sesión y los UUID de petición invalidan la caché.
El resto son ejemplos específicos de cada proveedor que aplican el mismo patrón.
2. Anthropic Claude — Marcadores cache_control explícitos
Claude pertenece al grupo de marcadores explícitos: la API de Anthropic no crea la caché automáticamente. Para obtener un hit, se pueden marcar hasta cuatro puntos de corte cache_control en los arrays system o messages. Las lecturas de caché cuestan alrededor del 10% de la tarifa de entrada; las escrituras cuestan el 125% (un recargo del 25%).
La forma más limpia de usar cache_control a través del gateway es apuntar el SDK oficial anthropic al endpoint nativo de Anthropic del gateway. La ruta compatible con OpenAI /chat/completions todavía no propaga los marcadores cache_control; para la caché de Claude hay que usar /v1/messages.
import os
from anthropic import Anthropic
anth = Anthropic(
api_key=os.environ["SYNTHORAI_KEY"],
base_url="https://synthorai.io/", # SDK appends /v1/messages
)
msg = anth.messages.create(
model="claude-sonnet-4-5",
max_tokens=512,
system=[
{"type": "text", "text": SYSTEM_INSTRUCTIONS,
"cache_control": {"type": "ephemeral"}}, # BP 1: never changes
{"type": "text", "text": TOOL_DESCRIPTIONS,
"cache_control": {"type": "ephemeral"}}, # BP 2: rarely changes
{"type": "text", "text": RETRIEVED_DOCUMENTS}, # changes per call — not cached
],
messages=[{"role": "user", "content": question}],
)
print(msg.usage)
# Usage(input_tokens=18, output_tokens=64,
# cache_creation_input_tokens=0, cache_read_input_tokens=8123,
# cost=...)
Opciones de TTL. {"type": "ephemeral"} usa por defecto un TTL deslizante de 5 minutos: cada hit retrasa la caducidad. Para cargas con periodos de inactividad superiores a 5 minutos, se puede solicitar un TTL de 1 hora en el mismo marcador:
"cache_control": {"type": "ephemeral", "ttl": "1h"}
Puntos de corte por capas. Los cuatro marcadores permiten almacenar por separado las secciones que «nunca cambian», las que «cambian rara vez» y las que «cambian en cada tarea». Es el enfoque más flexible para agentes y cargas RAG, donde cada sección del prompt cambia con una frecuencia distinta. Aunque la última capa, por ejemplo los documentos recuperados, cambie entre llamadas, las capas anteriores siguen produciendo hits.
Elección del modelo. IDs de Claude disponibles en el gateway a fecha de 2026-05: claude-haiku-4-5, claude-sonnet-4-5 / 4-6, claude-opus-4-5 / 4-6 / 4-7. Haiku para chat económico; Sonnet para uso general y el patrón de caché más sólido para agentes; Opus para las tareas de razonamiento más complejas.
Referencia medida de hit, escritura y ausencia de caché (2026-05-25, system prompt de unos 7,976 tokens, max_tokens=64):
| Modelo | Escritura en caché | Lectura de caché | Referencia sin caché | Descuento de lectura | TTFT con hit (stream) |
|---|---|---|---|---|---|
claude-haiku-4-5 | $0.00916 | $0.00086 | $0.00725 | −88% | 1.31 s |
claude-sonnet-4-5 | $0.02713 | $0.00247 | $0.02175 | −89% | 1.76 s |
claude-sonnet-4-6 | $0.02736 | $0.00253 | $0.02198 | −88% | 1.81 s |
claude-opus-4-5 | $0.04522 | $0.00409 | $0.03624 | −89% | 2.08 s |
claude-opus-4-6 | $0.04522 | $0.00411 | $0.03625 | −89% | 2.55 s |
claude-opus-4-7 | $0.06545 | $0.00609 | $0.05259 | −88% | 2.30 s |
El descuento se mantiene uniforme en toda la familia. El recargo por escritura ronda el 25% respecto a una llamada sin caché, según la tarifa publicada por Anthropic. Basta un hit para alcanzar el punto de equilibrio.
3. OpenAI GPT-5.x — Caché automática
OpenAI almacena automáticamente las peticiones cuyo prefijo es lo bastante largo. No hay que cambiar el código ni añadir marcadores.
def ask_gpt(question: str):
t0 = time.perf_counter()
resp = oai.chat.completions.create(
model="gpt-5.4-mini",
max_tokens=64,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": question},
],
)
return resp, time.perf_counter() - t0
r1, t1 = ask_gpt("Which export formats are supported?")
r2, t2 = ask_gpt("How long is the refund window for annual plans?")
print(t1, r1.usage.prompt_tokens_details.cached_tokens, r1.usage.cost)
# 3.63 0 0.00267
print(t2, r2.usage.prompt_tokens_details.cached_tokens, r2.usage.cost)
# 1.23 6400 0.00257
El mismo prompt de 6,887 tokens, dos veces. En la segunda llamada, el 93% del system prompt se recupera de la caché y la latencia total baja de 3.6 s a 1.2 s. El coste apenas cambia en este caso porque el descuento de caché queda compensado por una respuesta más larga en la primera llamada. En §7 hay cifras más comparables entre proveedores.
Con gpt-5.4-nano, el descuento se aprecia mejor: el coste del hit baja un 44%. En interfaces de chat donde solo importa el tiempo hasta el primer token, las cifras relevantes son las de streaming:
def ttft(model, question):
t0 = time.perf_counter()
stream = oai.chat.completions.create(
model=model, max_tokens=64,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": question},
],
stream=True, stream_options={"include_usage": True},
)
for ev in stream:
if ev.choices and ev.choices[0].delta and ev.choices[0].delta.content:
return time.perf_counter() - t0 # first content token
TTFT medido en la pasada con caché: 0.73 s para gpt-5.4-mini y 1.00 s para gpt-5.4-nano.
4. Google Gemini — Caché implícita
La caché de Gemini también funciona automáticamente al usar el gateway. No hace falta crear previamente un cachedContent.
r = oai.chat.completions.create(
model="gemini-2.5-flash",
max_tokens=128,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "Summarize section 6 in two bullets."},
],
)
print(r.usage.prompt_tokens_details.cached_tokens, r.usage.cost)
En una prueba con gemini-2.5-flash y un system prompt de unos 7,300 tokens, se recuperaron 7,140 tokens de caché (97%). El coste bajó de $0.00198 a $0.00024, un 88% menos en esa pasada.
Dos particularidades que conviene conocer:
- Las variantes
*-prode Gemini son modelos de razonamiento. Con unmax_tokensbajo, es habitual vercompletion_tokens=0porque el razonamiento interno consume todo el presupuesto. Para cualquier respuesta visible por el usuario, usamax_tokens≥256. - El TTL de la caché implícita es corto y no está especificado oficialmente. En nuestras pruebas, hubo hit entre dos llamadas separadas por 5 s; una tercera llamada unos 10 s después falló algunas veces. No diseñes el sistema suponiendo que siempre habrá hit: comprueba
cached_tokensy contempla el miss sin degradar el servicio.
5. DeepSeek-v4-flash — Caché automática persistente en disco
La caché automática de DeepSeek persiste más tiempo que las cachés en memoria GPU de otros proveedores. La llamada tiene la misma forma:
r1 = oai.chat.completions.create(
model="deepseek-v4-flash", max_tokens=128,
messages=[{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "Q1"}],
)
# r1.usage.cost = $0.00091, cached_tokens = 0
r2 = oai.chat.completions.create(
model="deepseek-v4-flash", max_tokens=128,
messages=[{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "Q2"}],
)
# r2.usage.cost = $0.00023, cached_tokens = 6784 → 74% saved
TTFT en streaming para la pasada con caché: 2.93 s. DeepSeek no ofrece la menor latencia del grupo. Sus ventajas están en el coste y en que la caché se mantiene caliente incluso con intervalos de varias horas.
6. Alibaba Qwen — Hit informado, descuento variable
r = oai.chat.completions.create(
model="qwen3-max", max_tokens=128,
messages=[{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "Q1"}],
)
print(r.usage.prompt_tokens_details.cached_tokens, r.usage.cost)
# 7040 0.00549
En nuestra prueba, cached_tokens indicaba un hit (7,040 de 7,234 = 97%), pero usage.cost no bajó en la pasada con caché: se mantuvo en ≈ $0.0055. La caché del proveedor sí respondió, como demuestra la mejora del TTFT de 3.03 s en frío a 1.53 s, pero en esa fecha el campo de coste del gateway todavía no reflejaba el descuento de caché para este proveedor. Si el coste de Qwen es importante para tu carga, monitoriza cached_tokens y consulta las tarifas del proveedor hasta que el dato se normalice.
7. Comparativa entre proveedores (medición del 2026-05-25)
Una única ejecución secuencial. System prompt estable de 7,284 caracteres, unos 6,900–7,300 tokens según el tokenizer. max_tokens=64. Primero una llamada con miss y, justo después, otra con hit.
Proveedores con caché automática, sin marcadores:
| Modelo | Coste con miss | Coste con hit | Variación de coste | Total con miss | Total con hit | TTFT con hit (stream) | Tasa de hit |
|---|---|---|---|---|---|---|---|
gpt-5.4-nano | $0.00131 | $0.00074 | −44% | 2.18 s | 1.48 s | 1.00 s | 5,888 / 6,887 (85%) |
gpt-5.4-mini | $0.00267 | $0.00257 | −4%* | 3.63 s | 1.23 s | 0.73 s | 6,400 / 6,887 (93%) |
gemini-2.5-flash | $0.00198 | $0.00024† | −88% | 2.49 s | 1.37 s | n/a‡ | 7,140 / 7,322 (97%) |
gemini-2.5-pro | $0.00824 | $0.00205† | −75% | 2.99 s | 1.76 s | n/a‡ | 6,120 / 7,328 (84%) |
deepseek-v4-flash | $0.00091 | $0.00023 | −74% | 4.02 s | 3.71 s | 2.93 s | 6,784 / 7,101 (96%) |
qwen3-max | $0.00553 | $0.00549 | −1%§ | 4.80 s | 2.37 s | 1.53 s | 7,040 / 7,234 (97%) |
* En la llamada con miss, gpt-5.4-mini generó 44 tokens, frente a 19 en la llamada con hit. La diferencia de coste combina el descuento de caché con la distinta longitud de la respuesta. La reducción de latencia (3.63 → 1.23 s) es una señal más clara en este caso.
† Coste de la pasada en streaming, donde sí se informó cached_tokens. Para Gemini, la pasada sin streaming devolvió ocasionalmente cached_tokens=null y el coste no bajó. Los metadatos de Gemini en el gateway aún son inconsistentes; usa cached_tokens cuando esté presente.
‡ Los modelos de razonamiento *-pro / *-flash de Gemini suelen generar cero tokens de contenido con valores pequeños de max_tokens, por lo que el TTFT no aporta información con ese presupuesto. Aumenta max_tokens si lo mides en producción.
§ Consulta §6: hubo hit en la caché del proveedor y bajó la latencia, pero el campo usage.cost del gateway no reflejó el descuento de qwen3-max en esa fecha.
Anthropic Claude requiere marcadores explícitos. Sus cifras aparecen en una tabla aparte porque hay que activar el descuento mediante cache_control; el patrón se muestra en §2. Mismo prompt, comparando escritura y lectura de caché:
| Modelo | Coste de escritura | Coste de lectura | Descuento de lectura | TTFT con hit (stream) |
|---|---|---|---|---|
claude-haiku-4-5 | $0.00916 | $0.00086 | −88% | 1.31 s |
claude-sonnet-4-5 | $0.02713 | $0.00247 | −89% | 1.76 s |
claude-sonnet-4-6 | $0.02736 | $0.00253 | −88% | 1.81 s |
claude-opus-4-5 | $0.04522 | $0.00409 | −89% | 2.08 s |
claude-opus-4-6 | $0.04522 | $0.00411 | −89% | 2.55 s |
claude-opus-4-7 | $0.06545 | $0.00609 | −88% | 2.30 s |
Tus resultados variarán según la región, la hora y si otros tenants han calentado prefijos iguales. Es una sola ejecución en una fecha concreta; no tomes estas cifras como referencia universal.
8. Lista de comprobación antes del despliegue
Antes de desplegar un prompt diseñado para aprovechar la caché:
- Primero el contenido estable — system prompt, base de conocimiento y esquemas de herramientas al principio de
messages. - Al final, el contenido variable — entrada del usuario, documentos recuperados y marcas de tiempo.
- No incluyas variables dinámicas en
system— la hora actual, el ID de usuario y las semillas aleatorias invalidarán el prefijo. - Registra
cached_tokensen cada llamada. Si la tasa de hit en producción es inferior al 50%, el prefijo no es realmente estable. Revisa los prompts que producen misses. - No te fíes de una sola pasada con hit. Los TTL son cortos; diseña para
hit_rate ∈ [0, 1)en lugar de asumir que siempre habrá hit.
9. Patrones que tienen en cuenta el TTL
El fallo más habitual en producción no es olvidarse de activar la caché, sino obtener una tasa de hit del 12% porque las peticiones no llegan dentro del intervalo del TTL.
8.1 Cargas ligadas a una sesión (chat, asistentes de IDE)
La cadencia natural suele ser muy inferior al TTL. Si estructuras bien el prompt, la caché se mantiene caliente por sí sola. No hace falta añadir nada más.
8.2 Heartbeat para batch / cron
Supongamos que un informe diario empieza a las 09:00 y llama al modelo 50 veces durante 3 minutos. La primera escritura de caché a las 09:00 se desperdicia porque la caché se enfrió durante la noche. A partir de las 08:55, envía cada TTL/2 un «ping» de 1 token con el prefijo almacenado para mantenerla caliente:
def keepalive():
oai.chat.completions.create(
model="gpt-5.4-mini",
max_tokens=1,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "."},
],
)
El coste de cada ping es el número de tokens de entrada multiplicado por la tarifa de caché. Para nuestro prefijo de 7K tokens en gpt-5.4-mini, son unos $0.0026, mucho menos que hacer que el proceso batch pague el prefill completo en las primeras 50 llamadas reales.
8.3 Documentos de acceso esporádico
Para documentos consultados de forma esporádica, por ejemplo una vez por hora durante el día, las cachés en memoria estarán frías la mayor parte del tiempo. En este momento, el gateway no expone un endpoint alojado para crear una caché explícita. Si necesitas un TTL largo, usa deepseek-v4-flash, cuya caché persiste en disco y en la práctica soporta intervalos de varias horas, o llama directamente a la API nativa cachedContent de Google fuera del gateway.
10. Qué aporta realmente el gateway
No sería correcto afirmar que el gateway «se encarga de la caché». La caché funciona en la capa del modelo; el gateway se limita a exponerla. Frente a usar directamente el SDK nativo de cada proveedor, aporta tres cosas:
- Un
base_url, una cabecera de autenticación y todos los modelos. Se cambia el campomodely la forma de la llamada permanece igual. Se usan el mismo arraymessagesy la misma estructura del campousage. No hace falta mantener cinco SDK para cinco proveedores. usage.costen USD para cada llamada. El gateway calcula el coste con las tarifas vigentes del proveedor y lo incluye en cada respuesta. No necesitas mantener una matriz de precios en el código ni suscribirte a las notificaciones de cambios de precio de cada proveedor.- Un campo
cached_tokensuniforme. Anthropic informa los hits comocache_read_input_tokens, OpenAI comoprompt_tokens_details.cached_tokensy DeepSeek comoprompt_cache_hit_tokens. El gateway los normaliza al formato de OpenAI para evitar ramificaciones por proveedor en el código de observabilidad.
Esa es toda la propuesta. El siguiente artículo aborda el resto: cuándo usar la caché, cómo estructurar los prompts y qué modelo elegir.
Siguiente: Parte 4 — Cómo elegir el mejor LLM según el caso de uso: chat, API y agentes de IA — una matriz de decisión que relaciona cada tipo de carga con el modelo y la estrategia de caché óptimos, incluidos los cálculos de coste.
Preguntas frecuentes
¿Por qué usar el SDK de OpenAI con modelos que no son de OpenAI?
El gateway usa el formato de intercambio de OpenAI para todos los proveedores que expone. El SDK oficial openai ofrece respuestas tipadas, reintentos automáticos y utilidades de streaming. No tiene sentido implementar y mantener cinco clientes HTTP.
¿Funciona la caché con respuestas en streaming?
Sí. El objeto usage del último chunk informa del número de hits de caché si se pasa stream_options={"include_usage": True}. La mejora de latencia se aprecia especialmente en streaming porque el TTFT es lo que perciben los usuarios.
¿Qué proveedor ofrece el mayor descuento de caché para mi carga?
Con los precios de 2026-05 y una tasa de hit superior al 70%, gemini-2.5-flash y deepseek-v4-flash son los más baratos de la tabla de §7. gpt-5.4-mini ofrece el mejor TTFT. Para obtener el descuento de caché del 90% publicado por Claude, marca hasta cuatro puntos de corte cache_control (consulta §2). Ejecutar la misma comparativa con tu propio prompt lleva un día, no una migración de varias semanas.
¿Cuándo necesito marcadores cache_control?
Solo al llamar a Anthropic Claude; consulta §2. OpenAI, Gemini, DeepSeek y Qwen almacenan automáticamente en el proveedor cualquier prefijo lo bastante largo, por lo que no hace falta ningún marcador. Esos proveedores ignoran el campo silenciosamente.
¿De cuándo son estas cifras? Se midieron el 2026-05-25 en el gateway público. Trátalas como un único punto de referencia: los precios y la latencia cambian con cada ciclo de versiones.
¿Qué ocurre con Anthropic Claude?
El gateway admite Claude mediante marcadores cache_control explícitos. Usa el SDK anthropic con base_url="https://synthorai.io/"; el SDK añade /v1/messages. Actualmente, la ruta compatible con OpenAI /chat/completions no propaga los marcadores. Para usar la caché de Claude, recurre a la ruta nativa de Anthropic mostrada en §2.
Fuentes y verificación: Todas las cifras se midieron contra https://synthorai.io/v1 el 2026-05-25 con la versión 2.38.0 del SDK openai. Páginas de precios de los proveedores: Caché de prompts de Anthropic · Caché de prompts de OpenAI · Caché de contexto de Google Gemini · Guía de caché KV de DeepSeek · Caché de contexto de Alibaba Bailian.