Ir al contenido principal
Semantic cache para agentes IA: reduce el coste un 50%

Semantic cache para agentes IA: reduce el coste un 50%

AI Integration
6 min readPor Daily Miranda Pardo

Tienes un agente de atención al cliente. Cada mes, el 35% de las preguntas que llegan son variaciones de lo mismo:

"¿Cuánto cuesta?", "¿Qué precio tiene?", "¿Cuáles son vuestros planes?", "¿Tenéis tarifa mensual?", "¿El precio incluye IVA?"

Son la misma pregunta. Formulada de cinco formas distintas. Y tu agente llama al LLM cinco veces, pagando por cada llamada.

La caché exacta no sirve aquí. Una caché tradicional busca coincidencias exactas de texto. "¿Cuánto cuesta?" y "¿Qué precio tiene?" son cadenas completamente distintas — no hay hit posible.

La solución es una caché semántica: en vez de comparar texto, comparas el significado.

Por qué las preguntas repetidas se llevan la mitad del presupuesto en LLM

Un agente IA de producción con 500 usuarios diarios puede tener entre el 40% y el 70% de sus preguntas en zonas de alta recurrencia — preguntas sobre precios, horarios, políticas, funcionamiento del producto. Son distintas en la forma, idénticas en la intención.

Cada llamada a un modelo de alta gama cuesta entre 0,003€ y 0,015€ dependiendo del volumen de tokens. Parece poco. Pero con 350 preguntas recurrentes al día, estás pagando entre 1€ y 5€ diarios por respuestas que ya tienes.

Al mes: hasta 150€ que podrías eliminar casi por completo.

Y eso sin contar la latencia. Una llamada al LLM tarda entre 600ms y 2 segundos. Una respuesta desde caché tarda menos de 50ms. La diferencia la nota el usuario en cada interacción.

Cómo funciona la caché semántica

En vez de guardar la pregunta como texto y buscar coincidencias exactas, guardas su embedding — una representación vectorial del significado — y comparas por similitud coseno.

Flujo completo:

  1. Llega la pregunta del usuario
  2. Calculas el embedding de la pregunta (una sola llamada barata a un modelo de embeddings)
  3. Buscas en la caché vectorial si hay alguna entrada con similitud > 0.92 (umbral configurable)
  4. Si hay hit: devuelves la respuesta cacheada en < 50ms, coste cero en LLM
  5. Si hay miss: llamas al LLM, guardas la respuesta en caché junto con su embedding

La clave está en el umbral de similitud. Con 0.92, capturas variaciones del mismo concepto sin confundir preguntas semánticamente distintas.

Implementación con TypeScript, Supabase y pgvector

Primero, el schema en Supabase con la extensión vector:

create extension if not exists vector;

create table semantic_cache (
  id uuid primary key default gen_random_uuid(),
  agent_id text not null,
  question text not null,
  response text not null,
  embedding vector(1536),
  created_at timestamptz default now()
);

-- Índice para búsqueda por similitud coseno
create index on semantic_cache
  using ivfflat (embedding vector_cosine_ops)
  with (lists = 100);

-- Función de búsqueda por similitud
create function match_cache_entries(
  query_embedding vector(1536),
  match_threshold float,
  match_count int,
  p_agent_id text
) returns table (id uuid, question text, response text, similarity float)
language sql stable as $$
  select id, question, response,
    1 - (embedding <=> query_embedding) as similarity
  from semantic_cache
  where 1 - (embedding <=> query_embedding) > match_threshold
    and agent_id = p_agent_id
  order by embedding <=> query_embedding
  limit match_count;
$$;

Y la implementación en TypeScript con el Vercel AI SDK:

import { embed } from 'ai'
import { openai } from '@ai-sdk/openai'
import { createClient } from '@supabase/supabase-js'
import Anthropic from '@anthropic-ai/sdk'

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
)
const anthropic = new Anthropic()
const SIMILARITY_THRESHOLD = 0.92

async function getEmbedding(text: string): Promise<number[]> {
  const { embedding } = await embed({
    model: openai.embedding('text-embedding-3-small'),
    value: text,
  })
  return embedding
}

export async function agentWithSemanticCache(
  question: string,
  agentId: string,
  systemPrompt: string
): Promise<{ response: string; cacheHit: boolean }> {

  // 1. Embedding de la pregunta entrante
  const embedding = await getEmbedding(question)

  // 2. Buscar en caché semántica
  const { data: cacheResult } = await supabase.rpc('match_cache_entries', {
    query_embedding: embedding,
    match_threshold: SIMILARITY_THRESHOLD,
    match_count: 1,
    p_agent_id: agentId,
  })

  if (cacheResult && cacheResult.length > 0) {
    return { response: cacheResult[0].response, cacheHit: true }
  }

  // 3. Cache miss: llamar al LLM
  const result = await anthropic.messages.create({
    model: 'claude-sonnet-5-20260101',
    max_tokens: 1024,
    system: systemPrompt,
    messages: [{ role: 'user', content: question }],
  })

  const response =
    result.content[0].type === 'text' ? result.content[0].text : ''

  // 4. Guardar en caché para consultas futuras
  await supabase.from('semantic_cache').insert({
    agent_id: agentId,
    question,
    response,
    embedding,
  })

  return { response, cacheHit: false }
}

El coste de un embedding con text-embedding-3-small es aproximadamente 50 veces menor que una llamada a Claude. Vale la pena calcularlo incluso en cada pregunta.

Qué preguntas cachear y cuáles no

No todas las preguntas se benefician igual de la caché semántica. La regla práctica:

Sí cachear:

  • Preguntas sobre producto, precio o políticas de la empresa
  • Preguntas sobre funcionamiento general del sistema
  • FAQs con respuesta fija o que cambia raramente

No cachear:

  • Preguntas que dependen del contexto del usuario (saldo, historial, estado del pedido)
  • Preguntas con datos personales o identificadores únicos
  • Preguntas cuya respuesta cambia en tiempo real

Para las que no deberían cachearse, añade una capa de detección antes de la búsqueda en caché:

function shouldSkipCache(question: string): boolean {
  const skipPatterns = [
    /mi\s+(cuenta|pedido|factura|saldo)/i,
    /\b\d{5,}\b/, // números de referencia o pedido
    /cuándo\s+llega\s+mi/i,
  ]
  return skipPatterns.some(p => p.test(question))
}

Una caché mal aplicada — que sirve respuestas genéricas a preguntas que necesitan datos del usuario — genera respuestas incorrectas que frustran al usuario más que la latencia.

Cuándo tiene sentido implementarlo

La caché semántica empieza a amortizarse cuando tienes más de 200 preguntas diarias a tu agente con un porcentaje de recurrencia mayor al 30%.

Por debajo de eso, el overhead de mantener la caché (coste de embeddings, complejidad de infraestructura) no justifica el ahorro.

En los proyectos de integración IA que construimos en DAILYMP, implementamos la caché semántica en la fase de optimización — después de tener el agente funcionando y con datos reales de uso. Añadirla desde el primer día sin conocer los patrones de pregunta es optimización prematura.

Si ya tienes un agente en producción y los costes de API empiezan a ser relevantes, este patrón suele reducirlos entre un 40% y un 70% sin cambiar el comportamiento del agente para el usuario.

Métricas que deberías monitorizar

Una vez en producción, mide:

  • Cache hit rate: porcentaje de preguntas respondidas desde caché. Objetivo: > 40% en agentes con alto volumen de FAQ
  • Average similarity score: la similitud media de los hits. Si está muy cerca del umbral (< 0.94), considera subirlo para evitar respuestas incorrectas
  • Cache entry age distribution: qué tan "fresca" es tu caché. Entradas con más de 30 días deben revisarse si el producto o los precios han cambiado

Loguea los hits y misses en Supabase — con el agentId y un timestamp — y tendrás los datos para ajustar el umbral semana a semana.

Si quieres ver cómo aplicaría este sistema a tu agente y estimar el ahorro real antes de implementarlo, en 30 minutos te hago el cálculo con tus datos actuales.

Optimiza los costes de tu agente IA →

Compartir artículo

LinkedInXWhatsApp

¿Procesos repetitivos en tu empresa?

Descarga gratis el Mapa de Automatización IA — los 5 procesos que más tiempo roban y cómo resolverlos.

Sin spam. Solo el PDF. Puedes darte de baja cuando quieras.

Escrito por Daily Miranda Pardo

Ayudo a empresas a automatizar procesos, crear agentes IA y conectar sistemas inteligentes.