Blog
IA & ML · 15 min lectura

Búsqueda Semántica y RAG: Cómo tu IA Entiende Antes de Responder

Qué son los embeddings, por qué los vectores están reemplazando a las keywords, y cómo RAG convierte un LLM genérico en un experto de tu negocio — con datos reales, sin alucinaciones.

Red neuronal representando búsqueda semántica y embeddings

Pregúntale a ChatGPT algo sobre tu empresa. Sobre tus propios artículos. Sobre tus productos, tarifas o políticas internas. La respuesta será educada, elaborada… y probablemente inventada. Los modelos de lenguaje no saben nada de tu negocio — saben de todo lo demás.

RAG (Retrieval-Augmented Generation) resuelve exactamente esto. En lugar de esperar que el LLM "recuerde" tu contenido, primero buscas la información relevante en tu propia base de conocimiento y luego se la pasas al modelo como contexto. El resultado: respuestas precisas, con fuentes, sin alucinaciones.

En este artículo explicamos todo el pipeline — desde qué son los embeddings hasta cómo implementamos el chatbot de Codex que estás usando ahora mismo (sí, el botón de abajo a la derecha). Puedes probarlo mientras lees.

🎯

El problema que resuelve RAG

Un LLM tiene un corte de conocimiento (normalmente meses atrás) y no conoce tu contenido privado. Fine-tuning es caro y lento. RAG inyecta contexto real en cada pregunta — actualizable al instante, sin reentrenar nada, con coste por consulta de ~$0,0008.

Fundamentos

¿Qué Son los Embeddings?

Un embedding es la representación numérica del significado de un texto. En lugar de tratar las palabras como cadenas de caracteres, un modelo de embeddings las convierte en vectores — listas de números con cientos o miles de dimensiones — donde textos con significados similares quedan cerca en el espacio vectorial.

// Ejemplo conceptual de embeddings
"gato"       → [0.23, -0.41, 0.87, 0.12, ..., -0.33]  // 1024 dimensiones
"felino"     → [0.25, -0.39, 0.85, 0.14, ..., -0.31]  // ¡Muy cerca de "gato"!
"automóvil"  → [-0.67, 0.52, -0.11, 0.83, ..., 0.44]  // Lejos de ambos

// Distancia coseno:
// gato ↔ felino:     0.97 (casi idénticos semánticamente)
// gato ↔ automóvil:  0.12 (sin relación semántica)

La magia está en que esto funciona más allá de sinónimos. "¿Cómo protegen los datos de mis clientes?" y "Seguridad y compliance del CRM" quedan cerca en el espacio vectorial aunque no compartan casi ninguna palabra. El modelo entiende la intención, no las letras.

📐

Dimensiones

Cada embedding tiene cientos o miles de dimensiones. Más dimensiones = más matices semánticos capturados. bge-m3 que usamos genera vectores de 1.024 dimensiones.

🌐

Multilingüe por defecto

Los modelos modernos como bge-m3 son multilingües — una pregunta en español puede encontrar contenido en inglés porque el significado vive en el mismo espacio vectorial, independiente del idioma.

Generación instantánea

Generar el embedding de una pregunta toma ~50ms en Workers AI. No es como entrenar un modelo — es como convertir un texto a su "coordenada" semántica. Es una operación de inferencia, no de entrenamiento.

Comparación

Búsqueda por Keywords vs Búsqueda Semántica

La búsqueda tradicional (SQL LIKE '%keyword%' o full-text search) busca coincidencias exactas de palabras. Funciona bien cuando sabes exactamente qué palabras usar. Pero los humanos no pensamos en keywords — pensamos en preguntas.

Aspecto Keyword Search Búsqueda Semántica
Qué busca Coincidencia de palabras Similitud de significado
Sinónimos No los entiende Los captura automáticamente
Preguntas naturales Pobre — depende de que las palabras coincidan Excelente — entiende la intención
Multilingüe Requiere índices separados por idioma Un solo espacio vectorial sirve para todos
Escalabilidad Excelente con índices SQL Requiere base de datos vectorial (ANN)
Coste Prácticamente cero Bajo (embedding + query vectorial)
💡

Ejemplo real en Codex

Un usuario pregunta "¿cómo manejan la seguridad de los datos?". Con keyword search, necesitarías que el texto contenga exactamente "seguridad" y "datos". Con búsqueda semántica, también encuentra resultados sobre "GDPR", "compliance", "aislamiento multi-tenant", "encriptación" y "Turnstile" — aunque esas palabras no aparezcan en la pregunta.

Arquitectura

¿Qué Es RAG y Por Qué Funciona?

RAG (Retrieval-Augmented Generation) es un patrón de arquitectura que combina dos fases: primero recuperas (Retrieval) la información relevante de tu base de conocimiento, y luego se la pasas al modelo generativo (Generation) como contexto. El modelo no necesita "saber" tus datos — solo necesita leerlos en el momento correcto.

1

Pregunta del usuario

"¿Cómo conecta Cadences con sistemas externos?" — El usuario escribe en lenguaje natural, sin pensar en keywords.

2

Embedding de la pregunta

Workers AI convierte la pregunta en un vector de 1.024 dimensiones usando bge-m3 (~50ms, gratis en Cloudflare).

3

Búsqueda vectorial (Retrieval)

El vector se compara contra todos los chunks indexados en Vectorize usando distancia coseno. Se obtienen los 5 fragmentos más similares — aunque no compartan ninguna palabra con la pregunta.

4

Contexto enriquecido

El texto completo de cada chunk se recupera de D1 y se inyecta en el prompt del LLM como contexto. El modelo lee tu contenido real, no lo inventa.

5

Respuesta generada (Generation)

DeepSeek V3.2 genera una respuesta basada exclusivamente en el contexto recuperado. Si la información no está en los chunks, dice "no tengo información" — elimina alucinaciones.

Estrategias

RAG vs Fine-Tuning vs Contexto Completo

Hay tres formas de "enseñarle" a un LLM sobre tu negocio. Cada una tiene su lugar, pero para la mayoría de casos de uso empresarial, RAG es la elección correcta.

Método Coste Actualización Precisión Escalabilidad
Contexto completo Alto (tokens caros) Instantánea Excelente (si cabe) Limitado al context window
Fine-tuning Muy alto ($100s–$1000s) Días/semanas Variable Requiere reentrenamiento
RAG ~$0,0008/consulta Minutos Alta (fuentes verificables) 100K+ documentos

¿Cuándo NO usar RAG?

  • Cuando tu base de conocimiento completa cabe en el context window (~200K tokens = ~150K palabras). En ese caso, pasa todo directamente.
  • Cuando necesitas que el modelo cambie su estilo o personalidad, no sus datos. Eso es fine-tuning.
  • Cuando las preguntas son puramente conversacionales ("hola, ¿qué tal?") sin necesidad de datos específicos.
Infraestructura

Vectorize: La Base de Datos Vectorial en el Edge

Una base de datos vectorial almacena embeddings y permite buscar los más similares a un vector de consulta. El algoritmo estándar es ANN (Approximate Nearest Neighbors) — no compara contra todos los vectores uno por uno (sería lentísimo con millones), sino que usa estructuras de índice para encontrar los más cercanos en milisegundos.

Cloudflare Vectorize es la solución nativa de Cloudflare. Vive en el edge (junto a Workers y D1), tiene un tier gratuito generoso, y se integra directamente con Workers AI para generar embeddings — sin salir del ecosistema, sin latencia de red entre servicios.

🗄️

Almacenamiento dual: Vectorize + D1

Los vectores (embeddings) viven en Vectorize para búsqueda rápida. Los textos originales viven en D1 (SQL relacional). Cuando Vectorize devuelve IDs de chunks similares, D1 proporciona el texto completo. Cada servicio hace lo que mejor sabe hacer.

📊

Distancia coseno

La métrica que mide la similitud entre dos vectores. Un score de 1.0 = idénticos, 0.0 = sin relación. En la práctica, un resultado con score > 0.55 es relevante, > 0.70 es muy relevante, > 0.85 es prácticamente una coincidencia exacta.

🏷️

Namespaces para filtrado

Vectorize soporta namespaces — particiones lógicas dentro del mismo índice. Nosotros usamos el idioma (es, en) como namespace para que las búsquedas en español solo comparen contra contenido en español.

// Configuración del índice de Codex en wrangler.toml
[[vectorize]]
binding = "VECTORIZE"
index_name = "codex-knowledge"  # 1024 dimensiones, coseno
# Tier gratuito: 200K vectores, 5M dims almacenadas/mes
# Suficiente para ~195 artículos × ~30 chunks = ~5.850 vectores
Preparación de datos

Chunking: El Arte de Partir el Texto

No puedes generar un embedding de un artículo completo de 4.000 palabras — el significado se diluye. Necesitas partirlo en fragmentos (chunks) lo suficientemente pequeños para ser semánticamente precisos, pero lo suficientemente grandes para mantener contexto.

📏 Tamaño del chunk: ~400 palabras

Es el sweet spot para modelos como bge-m3. Demasiado corto (50 palabras) pierde contexto. Demasiado largo (1000+ palabras) diluye el significado. 400 palabras captura ~2-3 párrafos coherentes.

🔄 Overlap: 50 palabras

Cada chunk se solapa 50 palabras con el anterior. Esto evita que una idea que cruza el límite entre dos chunks se pierda. Si el punto clave está en la frontera, ambos chunks lo capturan.

🧹 Limpieza previa

Antes de chunk-ear, se elimina todo el HTML, CSS, SVG, clases de Tailwind, scripts, y metadatos. Solo queda el texto puro que un humano leería. Esto mejora dramáticamente la calidad de los embeddings.

📊

Números reales de Codex

  • 24 artículos (12 en español + 12 en inglés)
  • 98 chunks generados (~4 chunks por artículo)
  • 98 vectores de 1.024 dimensiones en Vectorize
  • ~100K dimensiones almacenadas (0,5% del tier gratuito)
  • Indexación completa en < 2 minutos
Implementación

El Stack Completo del Chatbot de Codex

El chatbot que ves en esta web es un sistema RAG completo corriendo 100% en Cloudflare. Aquí está cada componente y por qué lo elegimos:

Componente Tecnología Coste Función
Embeddings Workers AI bge-m3 Gratis Convierte texto → vector (1.024 dims)
Vector store Cloudflare Vectorize Gratis (tier actual) Almacena y busca vectores por similitud
Texto + metadatos Cloudflare D1 Gratis (tier actual) Almacena chunks de texto, títulos, URLs
LLM principal DeepSeek V3.2 $0,28 / 1M tokens in Genera respuestas con contexto RAG
LLM fallback Workers AI Llama 3.1 Gratis Respaldo si DeepSeek no disponible
Frontend Astro + vanilla JS Estático Widget de chat flotante, voz, markdown
// Flujo simplificado del endpoint RAG (codex-chat.js)
// 1. Embedding de la pregunta (~50ms)
const embedding = await env.AI.run('@cf/baai/bge-m3', {
  text: [question]
});

// 2. Búsqueda vectorial en Vectorize (~30ms)
const results = await env.VECTORIZE.query(embedding.data[0], {
  topK: 5,
  namespace: lang,         // 'es' o 'en'
  returnMetadata: 'all',
  filter: { minScore: 0.55 }
});

// 3. Recuperar texto completo de D1
const chunks = await db.prepare(
  'SELECT chunk_text, title, url FROM codex_chunks WHERE id IN (...)'
).all();

// 4. Generar respuesta con DeepSeek
const response = await fetch('https://api.deepseek.com/chat/completions', {
  body: JSON.stringify({
    model: 'deepseek-chat',
    messages: [
      { role: 'system', content: systemPrompt + context },
      ...history,
      { role: 'user', content: question }
    ]
  })
});
Economía

Análisis de Costes: ~$0,0008 por Consulta

Una de las grandes ventajas de RAG sobre otras arquitecturas es el coste. Al usar servicios con tiers gratuitos para embeddings y almacenamiento vectorial, el único coste variable es el LLM generativo. Aquí está el desglose real:

Embedding de la pregunta

$0,0000

Workers AI bge-m3: gratis en el tier de Workers AI. Sin límite práctico para uso normal.

Búsqueda vectorial

$0,0000

Vectorize: 30M queries/mes incluidos en el tier gratuito. Más que suficiente.

Lectura de D1

$0,0000

D1: 5M lecturas/día en tier gratuito. Cada consulta lee ~5 filas.

DeepSeek V3.2 (respuesta)

~$0,0008

~2K tokens input (contexto + pregunta) × $0,28/1M + ~500 tokens output × $0,42/1M ≈ $0,0008.

💰

Coste mensual estimado

Con 1.000 consultas/mes (un volumen razonable para un blog técnico): ~$0,80/mes. El equivalente en GPT-4o sería ~$60/mes. DeepSeek V3.2 ofrece calidad comparable a GPT-4 al 1,3% del precio.

Interfaz

Voz, Markdown y Fuentes: La Experiencia del Chat

Un sistema RAG solo es útil si la interfaz es buena. El chatbot de Codex incluye funcionalidades que van más allá de un simple campo de texto:

🎙️

Entrada por voz

Web Speech API nativa del navegador. Habla tu pregunta y se transcribe automáticamente. Sin coste adicional, funciona offline.

📝

Markdown rendering

Las respuestas se renderizan con formato: negritas, cursivas, listas, código inline, code blocks y enlaces clicables.

📎

Fuentes verificables

Cada respuesta incluye enlaces a los artículos originales que se usaron como contexto, con su score de similitud. Puedes verificar la información.

🌙

Dark mode + i18n

Se adapta al tema del sistema, soporta español e inglés, y es responsive — funciona a pantalla completa en móvil.

Escalabilidad

De 24 Artículos a 100K Documentos

El pipeline de Codex hoy indexa 24 artículos. Pero la arquitectura está diseñada para escalar varios órdenes de magnitud sin cambiar de tecnología:

Escala Vectores Latencia búsqueda Tier necesario
Blog (actual) ~100 ~30ms Gratuito
Wiki mediana ~5.000 ~30ms Gratuito
Knowledge base empresarial ~50.000 ~35ms Workers Paid ($5/mes)
Documentación masiva ~200.000 ~40ms Workers Paid ($5/mes)

Vectorize usa HNSW (Hierarchical Navigable Small World) como algoritmo de indexación — la misma familia de algoritmos que usa Pinecone o pgvector. La latencia de búsqueda crece logarítmicamente, no linealmente: pasar de 100 a 100K vectores apenas añade 10ms.

Buenas Prácticas

Errores Comunes y Cómo Evitarlos

❌ Chunks demasiado largos

Si un chunk tiene 2.000 palabras sobre 5 temas diferentes, su embedding será un promedio borroso de todos ellos. La búsqueda será imprecisa. Solución: 300–500 palabras por chunk.

❌ No limpiar el HTML

Generar embeddings de <div class="flex items-center gap-3 mb-6"> desperdicia dimensiones en información irrelevante. Solución: Strip todo el markup antes de embeddings.

❌ Threshold de similitud muy bajo

Aceptar resultados con score < 0.4 inyecta contexto irrelevante que confunde al LLM. Solución: Usa minScore ≥ 0.55 y verifica empíricamente.

❌ Ignorar el system prompt

Sin instrucciones claras, el LLM puede inventar información fuera del contexto recuperado. Solución: System prompt que diga explícitamente "solo responde con la información del contexto proporcionado".

❌ No incluir metadatos útiles

Si el LLM solo ve texto suelto sin saber de qué artículo viene, no puede citar fuentes. Solución: Incluir título, URL y categoría de cada chunk en el contexto.

Conclusión

La IA que Sabe de lo Tuyo

RAG no es una moda — es el patrón que resuelve el problema fundamental de los LLMs: que saben mucho de todo, pero nada de tu negocio. Con embeddings, búsqueda semántica y generación basada en contexto real, puedes tener un asistente que responda con precisión sobre tu contenido, cite fuentes y cueste menos de $1/mes.

El chatbot de Codex es la prueba viva. Pregúntale lo que quieras sobre Cadences — busca en 98 chunks de 24 artículos, encuentra los más relevantes por similitud semántica, y genera una respuesta fundamentada con DeepSeek. Todo en el edge, todo serverless, todo por ~$0,0008 por pregunta.

🧠

Resumen técnico

  • Embeddings: Workers AI bge-m3, 1.024 dimensiones, multilingüe, gratuito
  • Vector DB: Cloudflare Vectorize con distancia coseno, namespaces por idioma
  • Text store: D1 con chunks, metadatos (título, URL, categoría), indexado por slug
  • LLM: DeepSeek V3.2 ($0,28/$0,42 por 1M tokens) + fallback Workers AI Llama
  • Chunking: ~400 palabras con overlap de 50, HTML stripping completo
  • Pipeline: pregunta → embedding → Vectorize query → D1 fetch → DeepSeek → respuesta con fuentes
  • Coste real: ~$0,0008/consulta, ~$0,80/mes para 1.000 preguntas
  • Rate limit: 20 consultas/día por IP (configurable), Turnstile-ready
C

Cadences Engineering

Documentación técnica del equipo de ingeniería