Conteúdo da trilha
RefatoraçãoOperação

Introduzir Cache

Introduce Cache

Introduzir Cache (Introduce Cache) é uma refatoração de IA para sistemas com LLM, do grupo Operação. Reaproveitar prefixos de prompt e respostas para perguntas equivalentes.

Elemento
33/35
Nível
Intermediário
Leitura
5 min
Atualizado
Nesta página 8
  1. 01Problema
  2. 02Solução
  3. 03Antes e depois
  4. 04Por que funciona
  5. 05Passo a passo seguro
  6. 06Riscos
  7. 07Desafio
  8. 08Teste seu entendimento
  9. ··Perguntas rápidas

Problema

O assistente de uma loja online manda, em toda pergunta, o mesmo system prompt de 9 mil tokens: regras de troca, políticas de frete, descrição das ferramentas. Um terço das perguntas do dia é alguma versão de “como tiro a segunda via do boleto?”. Cada uma é processada do zero, e a fatura do provedor cresce na mesma proporção do tráfego.

O mesmo prefixo grande e as mesmas perguntas são processados do zero toda vez. É o smell Pagando Duas Vezes.

Solução

Reaproveite o que se repete, em três níveis: cache de prompt para o prefixo fixo (instruções, ferramentas, documentos), cache de embeddings para textos que não mudam, e cache de resposta (exato ou semântico) para perguntas equivalentes, com regra de validade.

Antes e depois

-def answer(question):
-    q_vec = embed(question)                                      # pago toda vez
-    docs = index.search(q_vec, k=6)
-    return llm(SYSTEM_9K_TOKENS, docs, question)                 # prefixo pago toda vez
+def answer(question):
+    key = normalize(question)                                    # minúsculas, sem pontuação
+    if (hit := answer_cache.get(key)) and hit.sources_unchanged():
+        return hit.answer                                        # 1. cache de resposta
+
+    q_vec = embedding_cache.get_or_compute(key, embed)           # 2. cache de embedding
+    docs = index.search(q_vec, k=6)
+    reply = client.messages.create(
+        model=MODEL, max_tokens=1500,
+        system=[{"type": "text", "text": SYSTEM_9K_TOKENS,
+                 "cache_control": {"type": "ephemeral"}}],      # 3. cache de prompt
+        messages=[{"role": "user", "content": render(docs, question)}],
+    )
+    text = next(b.text for b in reply.content if b.type == "text")
+    answer_cache.set(key, text, ttl="24h",
+                     sources=[(d.id, d.version) for d in docs])  # validade ligada às fontes
+    return text

Antes: tudo processado do zero.

flowchart LR
  Q(["1. Pergunta"]):::io --> E["2. Embedding"]:::tool
  E --> S["3. Busca"]:::tool
  S --> M(["4. Modelo lê 9 mil tokens fixos"]):::llm

Depois: três camadas de reaproveitamento.

flowchart LR
  Q(["1. Pergunta"]):::io --> C{"2. Já respondida?"}
  C -->|sim e fontes iguais| OUT(["Resposta do cache"]):::io
  C -->|não| E["3. Embedding do cache ou novo"]:::tool
  E --> S["4. Busca"]:::tool
  S --> M(["5. Modelo com prefixo cacheado"]):::llm
  M --> OUT2(["Resposta, gravada no cache"]):::io
  1. A pergunta chega e é normalizada.
  2. Se a mesma pergunta foi respondida e as fontes não mudaram, a resposta volta na hora.
  3. O embedding de perguntas repetidas não é recalculado.
  4. A busca acontece normalmente.
  5. O prefixo fixo é lido do cache de prompt, com desconto e menos latência.

Por que funciona

Cada camada ataca um tipo de repetição. Antes de escolher, descubra qual repetição você tem.

Camada O que se repete O que você economiza Risco principal
Cache de prompt O começo do prompt, idêntico em toda chamada A maior parte do custo e parte da latência do prefixo Quase nenhum: a resposta continua sendo gerada
Cache de embedding O mesmo texto vetorizado de novo A chamada de embedding Vetor velho se o modelo de embedding mudar
Cache de resposta exato A mesma pergunta, depois de normalizada A chamada inteira Resposta velha ou de outra pessoa
Cache semântico Perguntas diferentes com o mesmo sentido A chamada inteira Devolver a resposta de uma pergunta parecida, mas diferente

Como o cache de prompt funciona por dentro

O provedor processa o prompt em ordem. Se o começo é idêntico ao de uma chamada recente, ele reaproveita esse processamento e cobra menos por ele. Na API da Anthropic, a ordem é ferramentas, depois system, depois mensagens, e o cache_control marca até onde o prefixo deve ser guardado. Na OpenAI, prompts longos são cacheados automaticamente, sem marcação.

Três regras práticas saem daí. O prefixo precisa ser idêntico byte a byte; um espaço a mais quebra o acerto. Existe um tamanho mínimo de prefixo para entrar no cache, que varia por modelo. E o cache expira: na Anthropic, a validade padrão é de alguns minutos, renovada a cada acerto, com opção de uma hora pagando mais na escrita.

Uma conta de exemplo

Suponha 10 mil perguntas por dia, um prefixo de 9 mil tokens e um preço ilustrativo de US$ 3 por milhão de tokens de entrada. Na tabela da Anthropic, ler do cache custa 10% do preço normal de entrada, e gravar no cache custa 25% a mais (confira os valores atuais do seu provedor).

sem cache:  10.000 × 9.000 = 90 milhões de tokens/dia × US$ 3/M  = US$ 270/dia só de prefixo
com cache:  quase tudo vira leitura a 10%                          ≈ US$ 27/dia
            mais as gravações, que acontecem só quando o cache expira

O ganho depende do tráfego ser contínuo. Com uma pergunta a cada meia hora, o cache expira entre uma e outra e quase toda chamada paga a gravação.

A regra de validade é o que torna o cache de resposta seguro: a resposta cacheada guarda de quais fontes veio, em qual versão, e deixa de valer se alguma delas mudou. Os padrões de destino são o Cache de Prompt e o Cache Semântico.

Checagem +20 XP de primeiraUm assistente interno de RH tem system prompt fixo de 9 mil tokens. Cada funcionário pergunta algo diferente, e quase nenhuma pergunta se repete no mês. Qual camada de cache traz mais ganho aqui?

Passo a passo seguro

  1. Meça. Levante a distribuição de perguntas (quantas se repetem depois de normalizar), o tamanho do prefixo fixo e o custo por pergunta. Confira os campos de cache no usage da API.
  2. Comece pelo cache de prompt. Ordene o prompt com o fixo primeiro e o variável no fim, e marque o ponto de cache. É a camada com menos risco, porque não muda nenhuma resposta.
  3. Confirme o acerto. A partir da segunda chamada, cache_read_input_tokens deve ser positivo. Se vier zero, procure algo variável no começo do prompt (data, nome, ordem de ferramentas que muda).
  4. Acrescente cache de embeddings para textos repetidos. Inclua o nome do modelo de embedding na chave, para que uma troca de modelo não misture vetores.
  5. Se houver muita repetição, acrescente cache de resposta com chave normalizada, validade e invalidação por mudança de fonte.
  6. Considere cache semântico só com um limiar testado no eval, para não devolver a resposta de uma pergunta parecida mas diferente.
  7. Meça de novo: taxa de acerto de cada camada, custo e latência por pergunta, e qualidade no eval.

Normalizar sem mudar o sentido

A chave do cache exato decide o que conta como “a mesma pergunta”. Minúsculas, espaços e pontuação podem sair. Números, nomes de cidade, datas e negações precisam ficar.

"Como tiro a 2ª via do boleto?"   e  "como tiro a 2ª via do boleto"     mesma chave
"Qual o frete para Manaus?"       e  "Qual o frete para Belém?"         chaves diferentes
"Posso trocar depois de 30 dias?" e  "Posso trocar antes de 30 dias?"   chaves diferentes

Uma normalização agressiva (tirar números, aplicar sinônimos) sobe a taxa de acerto e começa a errar sem aviso.

Checagem +20 XP de primeiraVocê marcou cache_control no system prompt, que é fixo e tem 9 mil tokens. Mesmo assim, cache_read_input_tokens vem quase sempre zero. O serviço recebe uma pergunta a cada 20 minutos. Qual é o diagnóstico mais provável?

Riscos

  • Resposta velha. Cache de resposta sem validade serve informação desatualizada. Ligue a validade às fontes e à versão de cada uma.
  • Resposta de outra pessoa. Perguntas com dados pessoais (“qual meu saldo?”, “cadê meu pedido?”) não podem ter resposta compartilhada. Inclua o usuário na chave ou não cacheie. Uma resposta com dado de um cliente entregue a outro é incidente de LGPD.
  • Cache semântico frouxo. “Cancelar assinatura” e “assinar plano” são parecidas no vetor. Teste o limiar com pares difíceis.
  • Prefixo instável. Um detalhe variável no começo do prompt zera o cache de prompt sem ninguém perceber. Um alerta na taxa de cache_read_input_tokens pega isso no dia.
  • Cache que esconde regressão. Depois de trocar o prompt, respostas antigas continuam saindo do cache de resposta. Inclua a versão do prompt e do modelo na chave.
Checagem +20 XP de primeiraO cache de resposta usa como chave só a pergunta normalizada. Um cliente pergunta 'qual o status do meu pedido?' e recebe o status do pedido de outra pessoa, que fez a mesma pergunta antes. O que você muda?

Desafio

Por que este prompt nunca acerta o cache, e como reorganizar?

system = f"""Data: {datetime.now().isoformat()}
Usuário: {user.name} (plano {user.plan})
Você é o assistente da loja. [8 mil tokens de regras e catálogo de ferramentas]"""
Ver solução

O começo do prompt muda a cada chamada (data com segundos, nome do usuário), então o prefixo nunca é igual. Reorganize com o fixo primeiro e o variável depois:

system = [
    {"type": "text", "text": RULES_AND_TOOLS_8K, "cache_control": {"type": "ephemeral"}},
    {"type": "text", "text": f"Usuário: {user.name} (plano {user.plan}). Data: {date.today()}"},
]

A data só com o dia, e depois do ponto de cache.

Teste seu entendimento

Checagem +20 XP de primeiraUm cache semântico com limiar 0,85 devolveu, para 'qual o frete para Manaus?', a resposta guardada de 'qual o frete para Belém?'. O que você faz?

Checagem +20 XP de primeiraA política de troca mudou de 7 para 30 dias. O cache de resposta tem validade de 24 horas e nenhuma ligação com as fontes. O que acontece, e como evitar?

Checagem +20 XP de primeiraSeu time quer cortar custo. O prefixo fixo tem 9 mil tokens, e 30% das perguntas são repetições exatas depois de normalizar. Qual é a ordem mais segura?

Perguntas rápidas

O que é Introduzir Cache?

Introduzir Cache (Introduce Cache) é uma refatoração de IA para sistemas com LLM, do grupo Operação. Reaproveitar prefixos de prompt e respostas para perguntas equivalentes.

Que problema Introduzir Cache resolve?

Trata Pagando Duas Vezes.

Aonde Introduzir Cache leva?

Ao padrão de projeto Cache Semântico e Cache de Prompt.

Para ir além

Relações

Smells que trata 1
Buscar