Jangada AIJangada AI

Cache de respostas

A jangada pode cachear respostas do LLM para economizar tokens e latência — plugado via LLM(..., cache=...). O cliente consulta o cache antes de chamar o provider e o popula depois de uma resposta bem-sucedida. Dois modos: exato e semântico.

Cache exato

Acerta só quando a requisição é idêntica (mesmo método, escopo provider/model/params e mensagens). LRU com max_size e ttl opcionais, sem custo de embedding.

from jangada_ai import LLM, ExactCache

llm = LLM("openai", "gpt-4o-mini", cache=ExactCache(max_size=512, ttl=3600))
llm.complete("Resuma a teoria da relatividade.")   # chama o provider
llm.complete("Resuma a teoria da relatividade.")   # vem do cache (idêntico)

Cache semântico

Acerta quando a pergunta é suficientemente parecida com uma anterior do mesmo escopo (similaridade de cosseno ≥ threshold). Reusa LLM.embed + um vector_store do RAG. Após o acerto semântico, aplica um filtro exato de escopo (provider/model/params/método) para alta precisão.

from jangada_ai import LLM, SemanticCache

embedder = LLM("openai", "text-embedding-3-small")
cache = SemanticCache(embedder, threshold=0.85)

llm = LLM("openai", "gpt-4o-mini", cache=cache)
llm.complete("Qual a capital da França?")
llm.complete("Me diga a capital francesa.")   # paráfrase → acerta o cache

Calibre o threshold por modelo de embedding

A escala de cosseno varia muito entre modelos — não existe número mágico:

Modelo de embeddingParáfrase (≈)Pergunta distinta (≈)
text-embedding-3-small (OpenAI)0.620.11
gemini-embedding-001 (Gemini)0.900.49

O padrão é 0.85 (meio-termo). Meça paráfrases vs. perguntas distintas no seu modelo e escolha um corte entre as duas distribuições. Alto demais = cache morto; baixo demais = respostas erradas (falso-positivo).

O que não é cacheado

  • Chamadas com tools ou MCP (tools=/mcp_servers=).
  • Streaming (stream/astream).
  • Respostas vindas de fallback (só o candidato primário popula o cache).
  • Recusas de guardrail.

complete/parse e suas versões async compartilham a mesma chave. O cache é local ao processo (a Completion fica em memória; o vector store é usado só para a similaridade).

O que mudou na 1.9.0

  • A chave inclui o schema do parse: parse(p, A) seguido de parse(p, B) não devolve mais o objeto do tipo A.
  • SemanticCache separa por contexto: system, histórico anterior e partes não-texto (imagens) entram no escopo. "sim" ou "continue" em conversas diferentes não dão mais hit com a resposta de outra conversa.
  • O hit devolve uma cópia com cost=0.0 e cached=True — somar custos num Flow/Agent não conta de novo uma chamada que não foi paga, e mexer no objeto devolvido não altera o que está no cache.
  • Evicção e expiração limpam o vector store do SemanticCache (antes as entradas mortas ficavam lá e derrubavam a taxa de acerto).
  • Erro no cache não derruba a chamada: falha no get/set (ex.: o embedder do cache semântico tomou rate limit) vira miss, com log em DEBUG.
  • ExactCache e SemanticCache são seguros entre threads.

On this page