RAG: IA con tu propio conocimiento
RAG (Retrieval-Augmented Generation) resuelve el mayor problema de los LLMs: su conocimiento está congelado en la fecha de entrenamiento y no sabe nada de tu empresa, tu documentación, o datos privados.
La idea es como darle a la IA un libro de referencia antes de responder: conviertes tus documentos en vectores (embeddings), y cuando el usuario hace una pregunta, buscas los fragmentos más relevantes y los incluyes en el contexto de la IA junto con la pregunta.
El proceso tiene dos fases: indexación (offline) donde conviertes todos tus documentos en embeddings y los guardas en una base de datos vectorial; y recuperación (runtime) donde al recibir una pregunta, calculas su embedding, buscas los K documentos más similares por similitud coseno, y los envías como contexto al LLM.
La similitud coseno mide el ángulo entre dos vectores: textos con significado parecido producen vectores "apuntando en la misma dirección". RAG es la tecnología detrás de Notion AI, Cursor y cualquier chatbot que "conoce tu empresa".
// RAG (Retrieval-Augmented Generation)
// 1. Indexación: convierte documentos en embeddings
// 2. Búsqueda: encuentra docs relevantes a la pregunta
// 3. Generación: la IA responde con ese contexto
import OpenAI from "openai";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// Base de conocimiento (normalmente en una BD vectorial)
const documentos = [
{ id: 1, texto: "Para instalar React: npx create-react-app mi-app" },
{ id: 2, texto: "useState se importa desde react: import { useState } from 'react'" },
{ id: 3, texto: "useEffect para efectos secundarios, recibe función y dependencias" },
];
// Función de similitud coseno
function similitudCoseno(vec1, vec2) {
const dotProduct = vec1.reduce((sum, v, i) => sum + v * vec2[i], 0);
const mag1 = Math.sqrt(vec1.reduce((sum, v) => sum + v * v, 0));
const mag2 = Math.sqrt(vec2.reduce((sum, v) => sum + v * v, 0));
return dotProduct / (mag1 * mag2);
}
async function rag(pregunta, topK = 3) {
// 1. Obtener embedding de la pregunta
const embPregunta = (await openai.embeddings.create({
model: "text-embedding-3-small",
input: pregunta
})).data[0].embedding;
// 2. Calcular similitud con cada documento
const conSimilitud = await Promise.all(
documentos.map(async (doc) => {
const embDoc = (await openai.embeddings.create({
model: "text-embedding-3-small",
input: doc.texto
})).data[0].embedding;
return { ...doc, similitud: similitudCoseno(embPregunta, embDoc) };
})
);
// 3. Top K más relevantes
const contexto = conSimilitud
.sort((a, b) => b.similitud - a.similitud)
.slice(0, topK)
.map(d => d.texto)
.join("\n");
// 4. Generar respuesta con contexto
const resp = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{
role: "user",
content: `Responde basándote solo en este contexto:\n${contexto}\n\nPregunta: ${pregunta}`
}]
});
return resp.choices[0].message.content;
}
Practica esta lección
Resuelve los ejercicios del curso de IA para Devs en la app, gratis y con corrección automática.
Empezar a practicar