Cache de prompts LLM #3: tutorial prático em Python
Conteúdo
- 0. Configuração
- 1. A chamada ciente do cache (igual em todos os fornecedores)
- 2. Anthropic Claude — marcadores cache_control explícitos
- 3. OpenAI GPT-5.x — cache automático
- 4. Google Gemini — cache implícito
- 5. DeepSeek-v4-flash — cache automático respaldado em disco
- 6. Alibaba Qwen — acerto reportado, desconto variável
- 7. Benchmark entre fornecedores (medido em 2026-05-25)
- 8. Lista de verificação pré-lançamento
- 9. Padrões cientes do TTL
- 8.1 Cargas de trabalho ligadas à sessão (chat, assistentes de IDE)
- 8.2 Heartbeat para batch / cron
- 8.3 Documentos em armazenamento frio
- 10. O que o gateway realmente acrescenta
- FAQ
TL;DR — Um único SDK da OpenAI, uma única base_url, todos os grandes LLMs. Os números deste artigo foram medidos no gateway Synthorai em produção em 2026-05-25 com um prompt de sistema estável de cerca de 7.300 tokens. O propósito do gateway aqui é modesto e honesto: um único endpoint, um único cabeçalho de autenticação e um campo usage.cost que poupa você de manter uma matriz de preços por fornecedor. A matemática do Transformer por trás do cache é abordada na Parte 1: Princípios do cache; as escolhas de design por fornecedor estão na Parte 2: Comparação de fornecedores.
Série: Parte 3 de 4 · Anteriormente: Parte 1 — Princípios do cache · Parte 2 — Comparação e avaliação de fornecedores · Próximo: Parte 4 — O melhor LLM por caso de uso
0. Configuração
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",
)
O gateway fala o formato de transmissão da OpenAI para cada modelo que ele disponibiliza (GPT, Claude, Gemini, DeepSeek, Qwen). Você muda o campo model, não o SDK. A autenticação usa Authorization: Bearer <key>.
IDs de modelos com capacidade de cache disponíveis no gateway público (instantâneo 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. A lista completa ao vivo está em GET /v1/models.
1. A chamada ciente do cache (igual em todos os fornecedores)
Você não precisa optar por isso. Para qualquer modelo que suporte cache de prompt no upstream, o gateway simplesmente repassa os metadados da resposta. Dois campos indicam o que aconteceu:
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 é a contagem de tokens de entrada que atingiram o cache de prefixo do upstream. usage.cost é o preço calculado pelo gateway para esta única chamada em USD — não há necessidade de manter localmente uma tabela de tarifas por fornecedor.
Duas regras que decorrem da arquitetura e se aplicam a todos os fornecedores:
- Conteúdo estável primeiro, conteúdo volátil por último. O prefixo é comparado a partir do token zero; uma única mudança de byte no início invalida todo o prefixo.
- Mantenha os dados dinâmicos fora do prompt de sistema. Carimbos de data/hora atuais, IDs de sessão e UUIDs de requisição vão todos invalidar o cache.
Tudo abaixo são apenas exemplos por fornecedor do mesmo padrão.
2. Anthropic Claude — marcadores cache_control explícitos
O Claude pertence à família de marcadores explícitos — a API da Anthropic não faz cache automaticamente. Para obter um acerto de cache, marque até quatro pontos de quebra cache_control no seu array system ou messages. As leituras de cache custam ~10 % da tarifa de entrada; as escritas de cache custam 125 % (um prêmio de 25 %).
A maneira mais limpa de usar cache_control através do gateway é com o SDK oficial anthropic apontando para o endpoint nativo da Anthropic do gateway (o caminho compatível com OpenAI /chat/completions atualmente não propaga os marcadores cache_control — use /v1/messages para cache do Claude).
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=...)
Opções de TTL. {"type": "ephemeral"} usa por padrão um TTL deslizante de 5 minutos (cada acerto empurra a expiração para frente). Para cargas de trabalho com intervalos de inatividade superiores a 5 minutos, solicite o TTL de 1 hora no mesmo marcador:
"cache_control": {"type": "ephemeral", "ttl": "1h"}
Pontos de quebra em camadas. Até quatro marcadores permitem que você faça cache de «nunca muda» + «raramente muda» + «muda por tarefa» de forma independente — o melhor da categoria para cargas de trabalho de agentes e RAG, onde as seções do prompt mudam em cadências diferentes. Mesmo quando a camada final (por exemplo, os documentos recuperados) muda entre as chamadas, as camadas anteriores ainda acertam.
Escolher um modelo. IDs do Claude disponíveis no gateway em 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 geral com o padrão de cache de agente mais robusto; Opus para as tarefas de raciocínio mais difíceis.
Referência medida de acerto de cache / escrita / sem cache (2026-05-25, prompt de sistema de ~7.976 tokens, max_tokens=64):
| Modelo | Escrita de cache | Leitura de cache | Ref. sem cache | Desconto leitura | TTFT acerto (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 |
O desconto se mantém uniforme em toda a família. O prêmio de escrita é de aproximadamente 25 % acima do sem cache (a tarifa documentada da Anthropic); o ponto de equilíbrio é um único acerto de cache.
3. OpenAI GPT-5.x — cache automático
A OpenAI faz cache automaticamente de qualquer requisição com um prefixo suficientemente longo. Sem mudança de código, sem marcador.
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
O mesmo prompt de 6.887 tokens duas vezes. Segunda chamada: 93 % do prompt de sistema atinge o cache, a latência total cai de 3,6 s para 1,2 s. O custo mal muda aqui porque o desconto de cache é compensado por uma completação mais longa na primeira chamada — veja §7 para números mais limpos entre fornecedores.
gpt-5.4-nano mostra o desconto com mais clareza (redução de custo de 44 % no acerto). Para interfaces de chat onde você só se importa com o tempo até o primeiro token, o que conta são os números 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 na passagem com cache: 0,73 s para gpt-5.4-mini, 1,00 s para gpt-5.4-nano.
4. Google Gemini — cache implícito
O cache do Gemini também é automático quando você passa pelo gateway. Não há nenhuma etapa de criação cachedContent que você precise executar.
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)
Um acerto medido em gemini-2.5-flash para um prompt de sistema de ~7.300 tokens: 7.140 tokens em cache (97 %), o custo cai de $0.00198 para $0.00024 — 88 % a menos para essa passagem.
Dois detalhes que vale a pena conhecer:
- As variantes
*-prodo Gemini são modelos de raciocínio. Com ummax_tokenspequeno, você frequentemente vêcompletion_tokens=0porque o orçamento é consumido pelo pensamento oculto. Aumentemax_tokenspara ≥256 para qualquer coisa voltada ao usuário. - O TTL do cache implícito é curto e não está oficialmente especificado. No nosso teste, um acerto entre duas chamadas separadas por 5 s teve sucesso; uma terceira chamada cerca de 10 s depois às vezes falhou. Não projete lógica que pressuponha o acerto; verifique
cached_tokense degrade com elegância.
5. DeepSeek-v4-flash — cache automático respaldado em disco
O cache automático do DeepSeek sobrevive mais tempo do que os caches residentes em memória GPU de outros fornecedores. A mesma forma de chamada:
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 em streaming na passagem com cache: 2,93 s. O DeepSeek não é a opção de menor latência neste conjunto — as vantagens estão no custo e no fato de que o cache permanece quente ao longo de intervalos da ordem de horas.
6. Alibaba Qwen — acerto reportado, desconto variável
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
Ressalva observada na nossa execução de teste: cached_tokens reporta um acerto (7.040 de 7.234 = 97 %), mas usage.cost não caiu na passagem com cache (ainda ≈ $0.0055). Isso significa que o acerto de cache do upstream aconteceu (TTFT mais rápido, 1,53 s contra 3,03 s a frio), mas o campo de custo do gateway para este fornecedor ainda não refletia o desconto da tarifa de cache nesta data. Se você é sensível ao custo no Qwen, observe cached_tokens e confie nas páginas de preços do upstream até que isso se normalize.
7. Benchmark entre fornecedores (medido em 2026-05-25)
Execução sequencial única. Prompt de sistema estável de 7.284 caracteres (~6.900–7.300 tokens dependendo do tokenizador). max_tokens=64. Uma chamada com falha seguida imediatamente de uma chamada com acerto.
Os fornecedores de cache automático (nenhum marcador necessário):
| Modelo | Custo falha | Custo acerto | Δ custo | Total falha | Total acerto | TTFT acerto (stream) | Taxa de acerto de cache |
|---|---|---|---|---|---|---|---|
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%) |
* A completação da chamada com falha do gpt-5.4-mini foi de 44 tokens contra 19 no acerto — o delta de custo mistura o desconto de cache com a diferença no comprimento da completação. A queda de latência (3,63 → 1,23 s) é o sinal mais limpo aqui.
† Custo da passagem em streaming (onde cached_tokens foi reportado); a passagem sem stream ocasionalmente retornava cached_tokens=null para o Gemini e o custo não caía. Os metadados do gateway para o Gemini são atualmente inconsistentes — confie em cached_tokens quando presente.
‡ Os modelos de raciocínio *-pro / *-flash do Gemini frequentemente emitem zero tokens de conteúdo com um max_tokens pequeno, então o TTFT não tem sentido nesse orçamento. Aumente max_tokens se você medir isso em produção.
§ Veja §6 — o acerto de cache do upstream aconteceu (a latência caiu), mas o campo usage.cost do gateway não refletiu o desconto para o qwen3-max nesta data.
O Anthropic Claude é orientado por marcadores explícitos; os números ficam em uma tabela separada porque o desconto é opcional via cache_control (veja §2 para o padrão). O mesmo prompt, escrita de cache medida contra leitura de cache:
| Modelo | Custo escrita | Custo leitura | Desconto leitura | TTFT acerto (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 |
Seus números diferirão por região, hora do dia e calor dos prefixos de outros locatários. Execução única, data única — não cite estes como verdade absoluta de benchmark.
8. Lista de verificação pré-lançamento
Antes de colocar em produção um prompt ciente do cache:
- Conteúdo estável primeiro — prompt de sistema, base de conhecimento, esquemas de ferramentas no topo de
messages. - Conteúdo volátil por último — entrada do usuário, documentos recuperados, carimbos de data/hora na parte inferior.
- Sem variáveis dinâmicas em
system— hora atual, ID do usuário, sementes aleatórias destruirão seu prefixo. - Registre
cached_tokensem cada chamada. Se a taxa de acerto estiver abaixo de 50 % em produção, seu prefixo não é realmente estável. Inspecione os prompts que falham. - Não confie em uma única passagem com acerto. Os TTLs são curtos; projete para
hit_rate ∈ [0, 1)em vez de «sempre acerto».
9. Padrões cientes do TTL
O modo de falha mais comum em produção não é «esqueci de ativar o cache» — é «minha taxa de acerto é de 12 % porque minhas requisições não chegam de fato dentro da janela de TTL».
8.1 Cargas de trabalho ligadas à sessão (chat, assistentes de IDE)
A cadência natural está bem abaixo do TTL. Estruture seu prompt corretamente e o cache permanece quente por si só — não projete mais nada.
8.2 Heartbeat para batch / cron
Se você executa um relatório diário às 09:00 que chama seu modelo 50 vezes em uma rajada de 3 minutos, a primeira escrita de cache às 09:00 é desperdiçada porque o cache esfriou durante a noite. A partir das 08:55, envie um «ping» de 1 token com o prefixo em cache a cada TTL/2 para mantê-lo quente:
def keepalive():
oai.chat.completions.create(
model="gpt-5.4-mini",
max_tokens=1,
messages=[
{"role": "system", "content": LONG_STABLE_PROMPT},
{"role": "user", "content": "."},
],
)
O custo por ping é tokens de entrada × tarifa de cache, que para o nosso prefixo de 7K tokens no gpt-5.4-mini é de cerca de $0.0026 — muito menos do que deixar seu job em lote pagar o prefill completo nas primeiras 50 chamadas reais.
8.3 Documentos em armazenamento frio
Para documentos consultados de forma esporádica (uma vez por hora ao longo do dia), os caches em memória estarão frios na maior parte do tempo. No momento em que isto é escrito, o gateway não expõe um endpoint hospedado de criação de cache explícito — para necessidades de TTL longo, use deepseek-v4-flash (respaldado em disco; sobrevive na prática a intervalos da ordem de horas) ou chame diretamente a API nativa cachedContent do Google fora do gateway.
10. O que o gateway realmente acrescenta
Seria desonesto afirmar que o gateway «faz o cache por você». O cache acontece na camada do modelo — o gateway expõe o que está lá. O que ele de fato acrescenta, medido em relação ao uso direto do SDK nativo de cada fornecedor, são três coisas:
- Uma base_url, um cabeçalho de autenticação, todos os modelos. Troque o campo
modele a forma da chamada permanece inalterada. O mesmo arraymessages, a mesma estrutura do campousage. Você não carrega cinco SDKs para cinco fornecedores. usage.costem USD por chamada. O gateway calcula o custo em dólares usando as tarifas atuais do upstream e o inclui em cada resposta. Você não mantém uma matriz de preços no seu código, nem precisa se inscrever em notificações de mudança de preço por fornecedor.- Um campo
cached_tokensuniforme. A Anthropic reporta os acertos de cache comocache_read_input_tokens, a OpenAI comoprompt_tokens_details.cached_tokens, o DeepSeek comoprompt_cache_hit_tokens. O gateway normaliza esses valores no formato da OpenAI para que seu código de observabilidade não se ramifique por fornecedor.
Esse é todo o argumento. Todo o resto — quando fazer cache, como estruturar os prompts, qual modelo escolher — é o trabalho do próximo artigo.
Próximo: Parte 4 — Como escolher o melhor LLM por caso de uso: chat, API e agentes de IA — uma matriz de decisão que associa o tipo de carga de trabalho ao modelo ideal + estratégia de cache, com cálculos de custo.
FAQ
Por que usar o SDK da OpenAI para modelos que não são da OpenAI?
O gateway fala o formato de transmissão da OpenAI para cada fornecedor que ele disponibiliza. O SDK oficial openai lhe dá respostas tipadas, novas tentativas automáticas e auxiliares de streaming — não há razão para programar à mão cinco clientes HTTP.
O cache funciona com respostas em streaming?
Sim. O objeto usage no último fragmento reporta as contagens de acerto de cache (quando você passa stream_options={"include_usage": True}). O ganho de latência é mais visível no streaming porque o TTFT é o que os usuários veem.
Qual fornecedor tem o desconto de cache mais profundo para minha carga de trabalho?
Aos preços de 2026-05 e com uma taxa de acerto superior a 70 %, gemini-2.5-flash e deepseek-v4-flash são os mais baratos na tabela de §7. gpt-5.4-mini vence no TTFT. Para o desconto de cache documentado de 90 % do Claude, marque até quatro pontos de quebra cache_control (veja §2). Execute o mesmo benchmark contra o seu próprio prompt — é um exercício de um dia, não uma migração de várias semanas.
Quando preciso de marcadores cache_control?
Apenas ao chamar o Anthropic Claude — veja §2. Para OpenAI/Gemini/DeepSeek/Qwen, o upstream faz cache automaticamente de qualquer prefixo suficientemente longo, então nenhum marcador é necessário; o campo é silenciosamente ignorado com esses fornecedores.
Quão recentes são esses números? Medidos em 2026-05-25 no gateway público. Trate-os como um único ponto de dados — preços e latência mudam a cada ciclo de versão.
E o Anthropic Claude?
O Claude é suportado através do gateway com marcadores cache_control explícitos — use o SDK anthropic com base_url="https://synthorai.io/" (o SDK acrescenta /v1/messages). O caminho compatível com OpenAI /chat/completions não propaga os marcadores hoje; especificamente para o cache do Claude, use o caminho nativo da Anthropic mostrado em §2.
Fontes e verificação: todos os números foram medidos em relação a https://synthorai.io/v1 em 2026-05-25 usando o SDK openai 2.38.0. Páginas de preços dos fornecedores: Anthropic Prompt Caching · OpenAI Prompt Caching · Google Gemini Context Caching · DeepSeek KV Cache Guide · Alibaba Bailian Context Cache.