De RAG a CAG: Evolución en Proyectos de IA
Durante los últimos años, RAG (Retrieval-Augmented Generation) se convirtió en el estándar de facto para dotar de conocimiento actualizado a los modelos de lenguaje. Pero en 2025 emergió una alternativa que está cambiando las reglas del juego: CAG (Cache-Augmented Generation). Si trabajas con IA en tus proyectos, necesitas entender esta evolución y cuándo cada enfoque es la mejor opción.
¿Qué es RAG y cuál es su problema real?
RAG resuelve el problema del "conocimiento estático" de los LLMs. Cuando el modelo no sabe algo (porque su base de conocimiento tiene una fecha de corte, o porque el dato es privado), RAG lo busca en tiempo real: fragmenta los documentos, genera embeddings, almacena en una base vectorial y recupera los más relevantes para cada consulta.
El proceso RAG clásico:
Usuario → Pregunta → Embedding query → Búsqueda vectorial →
Recuperar chunks → Construir prompt → LLM → Respuesta
Funciona bien, pero arrastra limitaciones significativas:
- Latencia doble: el tiempo de retrieval se suma al de inferencia
- Chunking frágil: dividir mal los documentos degrada la calidad de las respuestas
- Contexto fragmentado: el modelo solo ve trozos, nunca el documento completo
- Coste operativo: mantener índices vectoriales actualizados tiene un precio
- Alucinaciones por recuperación: si el chunk recuperado no es el correcto, la respuesta falla
¿Qué es CAG y por qué es diferente?
CAG (Cache-Augmented Generation) aprovecha los modelos de contexto ultralargo (Gemini 1.5 Pro con 1M tokens, Claude con 200K, GPT-4o con 128K) para eliminar por completo el paso de retrieval. En lugar de buscar lo relevante, precargas toda la base de conocimiento en el contexto del modelo de una sola vez, generando una caché KV (Key-Value) que persiste entre consultas.
El proceso CAG:
[Una vez] Documentos completos → Precarga en KV cache → LLM
[Por consulta] Usuario → Pregunta → LLM (ya tiene el contexto) → Respuesta
La clave técnica está en el KV cache: cuando el modelo procesa el contexto inicial, almacena internamente las representaciones calculadas (keys y values de la atención). Las consultas posteriores reutilizan esa caché sin reprocesar los documentos, reduciendo drásticamente la latencia por query.
Ventajas reales de CAG
| Aspecto | RAG tradicional | CAG |
|---|---|---|
| Arquitectura | Pipeline complejo (embed, index, retrieve) | Simple (precarga + consulta) |
| Latencia por query | Alta (retrieval + inferencia) | Baja (solo inferencia) |
| Calidad de contexto | Fragmentada (chunks) | Completa (documento íntegro) |
| Mantenimiento | Índices vectoriales continuos | Actualización periódica de caché |
| Consistencia | Variable según retrieval | Determinista |
| Coste de setup | Alto (embeddings + BBDD vectorial) | Bajo |
Cuándo usar CAG vs RAG: la decisión correcta
CAG no reemplaza a RAG en todos los escenarios. La elección depende de tres variables: tamaño del conocimiento, frecuencia de actualización y requisitos de latencia.
Usa CAG cuando:
- Tu base de conocimiento cabe en el contexto del modelo (hasta ~200K-1M tokens)
- Necesitas respuestas coherentes con visión global del documento
- La baja latencia es crítica (chatbots, asistentes en tiempo real)
- Quieres arquitectura simple sin infraestructura vectorial
- El contenido se actualiza de forma periódica, no continua
Usa RAG cuando:
- Tu base de conocimiento es masiva (millones de documentos)
- Necesitas búsqueda semántica precisa entre corpus muy heterogéneos
- El coste de tokens es una restricción severa
- Los datos cambian en tiempo real (noticias, logs en vivo)
El enfoque híbrido RAG+CAG
Para casos intermedios, la arquitectura más potente combina ambos:
async function hybridQuery(question: string, knowledgeBase: Document[]) {
// CAG: documentos críticos siempre en contexto
const coreContext = knowledgeBase
.filter(doc => doc.priority === 'critical')
.map(doc => doc.content)
.join('\n\n');
// RAG: documentos secundarios solo cuando son relevantes
const retrieved = await vectorSearch(question, knowledgeBase
.filter(doc => doc.priority !== 'critical'));
const prompt = `
=== CONOCIMIENTO BASE (siempre disponible) ===
${coreContext}
=== CONTEXTO ADICIONAL RECUPERADO ===
${retrieved.map(d => d.content).join('\n')}
=== PREGUNTA ===
${question}
`;
return await llm.complete(prompt);
}
Cómo aplicar CAG en tus proyectos de IA: ejemplos reales
Ejemplo 1: Chatbot de atención al cliente con CAG
El caso de uso más inmediato. Si tienes un negocio con documentación de producto, FAQs, políticas y catálogo, CAG te permite cargar todo en contexto y ofrecer respuestas perfectamente coherentes sin infraestructura vectorial.
import Anthropic from "@anthropic-ai/sdk";
import fs from "fs";
const client = new Anthropic();
// Precarga: preparar todo el conocimiento del negocio
async function buildCacheContext(docsDir: string): Promise<string> {
const files = fs.readdirSync(docsDir);
const sections = files.map(file => {
const content = fs.readFileSync(`${docsDir}/${file}`, 'utf-8');
return `=== ${file.replace('.txt', '').toUpperCase()} ===\n${content}`;
});
return sections.join('\n\n');
}
// Query: reutiliza el contexto cacheado
async function queryWithCAG(
userQuestion: string,
cachedContext: string
): Promise<string> {
const response = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 1024,
system: `Eres un asistente experto. Usa EXCLUSIVAMENTE la siguiente
base de conocimiento para responder. Si la información no está
en la base, indícalo claramente.\n\n${cachedContext}`,
messages: [{ role: "user", content: userQuestion }],
});
return response.content[0].type === 'text' ? response.content[0].text : '';
}
// Uso en API Route de Next.js
export async function POST(req: Request) {
const { question } = await req.json();
// En producción: cachear en Redis/memoria, no reconstruir en cada request
const context = await buildCacheContext('./data/knowledge');
const answer = await queryWithCAG(question, context);
return Response.json({ answer });
}
Ejemplo 2: Asistente de código con contexto de repositorio
Un caso donde CAG brilla especialmente: cargar el contexto completo de un repositorio de código pequeño-mediano para que el asistente entienda toda la arquitectura sin perder coherencia entre archivos.
import Anthropic from "@anthropic-ai/sdk";
import { glob } from "glob";
import fs from "fs";
const client = new Anthropic();
interface RepoContext {
files: { path: string; content: string }[];
totalTokens: number;
}
async function loadRepoContext(repoPath: string): Promise<RepoContext> {
// Carga selectiva: solo archivos relevantes para no saturar el contexto
const files = await glob(`${repoPath}/src/**/*.{ts,tsx,js}`, {
ignore: ['**/node_modules/**', '**/*.test.*', '**/dist/**']
});
const loaded = files.map(file => ({
path: file.replace(repoPath, ''),
content: fs.readFileSync(file, 'utf-8')
}));
return {
files: loaded,
totalTokens: loaded.reduce((acc, f) => acc + f.content.length / 4, 0)
};
}
async function askAboutCode(
question: string,
repoCtx: RepoContext
): Promise<string> {
const contextStr = repoCtx.files
.map(f => `// FILE: ${f.path}\n${f.content}`)
.join('\n\n---\n\n');
const response = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 2048,
system: `Eres un experto en este repositorio. Tienes acceso completo
al código fuente:\n\n${contextStr}`,
messages: [{ role: "user", content: question }],
});
return response.content[0].type === 'text' ? response.content[0].text : '';
}
Ejemplo 3: CAG con actualización incremental de caché
En proyectos reales, el conocimiento cambia. Este patrón gestiona actualizaciones sin reconstruir toda la caché:
interface CacheEntry {
context: string;
version: string;
createdAt: Date;
ttlHours: number;
}
class CAGCacheManager {
private cache = new Map<string, CacheEntry>();
async getOrBuild(
cacheKey: string,
buildFn: () => Promise<string>,
ttlHours = 24
): Promise<string> {
const cached = this.cache.get(cacheKey);
const isExpired = cached &&
(Date.now() - cached.createdAt.getTime()) > ttlHours * 3600 * 1000;
if (cached && !isExpired) {
return cached.context;
}
// Reconstruir solo cuando ha expirado o no existe
const freshContext = await buildFn();
this.cache.set(cacheKey, {
context: freshContext,
version: Date.now().toString(),
createdAt: new Date(),
ttlHours
});
return freshContext;
}
invalidate(cacheKey: string): void {
this.cache.delete(cacheKey);
}
}
// En tu API de Next.js
const cacheManager = new CAGCacheManager();
export async function POST(req: Request) {
const { question, namespace } = await req.json();
const context = await cacheManager.getOrBuild(
namespace,
() => loadKnowledgeBase(namespace),
ttlHours = 12
);
const answer = await queryWithCAG(question, context);
return Response.json({ answer });
}
El futuro: CAG como estándar en aplicaciones de IA
La tendencia es clara. Los modelos con ventanas de contexto de 1 millón de tokens (y creciendo) están haciendo que CAG sea viable para bases de conocimiento cada vez más grandes. Lo que hoy requiere RAG con chunking, mañana cabrá en contexto directamente.
Para proyectos de tamaño mediano —documentación de producto, manuales técnicos, catálogos, repositorios de código— CAG ya es la arquitectura más pragmática hoy mismo: menos complejidad, mejor calidad de respuesta, menor latencia.
El camino a seguir en 2026:
- Proyectos nuevos: Empieza con CAG. Añade RAG solo si el conocimiento supera el contexto disponible.
- Proyectos existentes con RAG: Evalúa si tu base de conocimiento cabe en contexto. Si sí, migrar a CAG simplificará tu stack y mejorará resultados.
- Casos complejos: Implementa el híbrido CAG+RAG con documentos críticos en contexto y el resto en retrieval.
¿Quieres implementar CAG en tu proyecto o migrar desde una arquitectura RAG existente? En dailymp.es ayudo a equipos a diseñar e implementar arquitecturas de IA adaptadas a sus necesidades reales. Consulta también cómo el desarrollo impulsado por IA puede transformar tu flujo de trabajo completo.