Módulo 6: Diseño de Sistemas de Búsqueda
3. Pipeline de Indexación: Chunking y Embeddings
Descripción
La indexación es el proceso offline de convertir documentos crudos en vectores almacenados. Esta cápsula cubre chunking strategies (cómo dividir documentos), embedding generation, y almacenamiento con metadata.
Paso 1: Chunking (dividir documentos)
¿Por qué chunking?
- Documentos largos (10K+ tokens) no caben en embedding
- Chunks pequeños → más precisión en búsqueda
- Chunks grandes → más contexto
Estrategia 1: Fixed-size chunks
Documento: 5000 tokens
Chunk size: 500 tokens
Overlap: 50 tokens
Resultado:
- Chunk 1: tokens 0-500
- Chunk 2: tokens 450-950 (overlap de 50)
- Chunk 3: tokens 900-1400
...
Ventaja: Simple, predecible.
Desventaja: Puede cortar oraciones a la mitad.
Estrategia 2: Paragraph-based
Dividir por:
- Doble salto de línea (\n\n)
- Límite de tokens por chunk (ej: máximo 800)
Resultado:
- Chunk 1: Párrafos 1-3 (500 tokens)
- Chunk 2: Párrafos 4-5 (400 tokens)
Ventaja: Respeta estructura semántica.
Desventaja: Chunks de tamaño variable.
Estrategia 3: Sentence-based
Dividir por oraciones (. ! ?)
Agrupar hasta máximo N tokens
Ventaja: No corta oraciones.
Desventaja: Chunks muy pequeños (menos contexto).
Estrategia 4: Hierarchical (recursive)
1. Dividir por secciones (# headers en Markdown)
2. Si sección > 800 tokens → Dividir por párrafos
3. Si párrafo > 800 tokens → Dividir por oraciones
Ventaja: Respeta estructura jerárquica.
Desventaja: Más complejo de implementar.
Chunk size recomendado
| Uso | Chunk size | Justificación |
|---|---|---|
| RAG general | 500-800 tokens | Balance contexto/precisión |
| Búsqueda de código | 200-400 tokens | Funciones completas |
| Documentación técnica | 800-1200 tokens | Secciones completas |
| Artículos largos | 1000-1500 tokens | Mantener narrativa |
Regla general: 500-800 tokens con overlap de 50-100.
Overlap (solapamiento)
¿Por qué overlap?
Sin overlap:
Chunk 1: "El perro es leal."
Chunk 2: "Los gatos son independientes."
Query: "diferencia entre perros y gatos"
→ Ningún chunk contiene ambos ❌
Con overlap:
Chunk 1: "El perro es leal. Los gatos..."
Chunk 2: "...perro es leal. Los gatos son independientes."
Query: "diferencia entre perros y gatos"
→ Chunk 2 contiene contexto completo ✅
Overlap recomendado: 10-20% del chunk size (50-100 tokens para chunks de 500).
Paso 2: Metadata extraction
Metadata útil:
- source: Nombre del documento original
- page: Número de página (para PDFs)
- section: Sección/capítulo
- timestamp: Fecha de creación/actualización
- author: Autor del documento
- tags: Etiquetas manuales o automáticas
Ejemplo:
{
"id": "chunk-123",
"text": "RAG combina LLMs con búsqueda vectorial...",
"embedding": [0.23, -0.45, ...],
"metadata": {
"source": "guia-rag.pdf",
"page": 5,
"section": "Arquitectura de RAG",
"timestamp": "2024-12-01",
"tags": ["RAG", "LLMs", "vector search"]
}
}
Uso: Filtrar resultados por metadata (source = "guia-rag.pdf").
Paso 3: Embedding generation
Opción 1: OpenAI API
Input: Chunk text (hasta 8191 tokens)
Model: text-embedding-3-small (1536D)
Costo: $0.00002 / 1K tokens
Batch de 1000 chunks × 500 tokens = 500K tokens
→ Costo: $0.01 (un centavo)
Ventaja: Alta calidad, simple.
Desventaja: Costo recurrente (cada re-indexación).
Opción 2: Modelo local (Sentence-BERT)
Model: all-MiniLM-L6-v2 (384D)
Costo: $0 (después de setup)
Velocidad: ~100 chunks/segundo (CPU)
Ventaja: Gratis, privacidad.
Desventaja: Menor calidad que OpenAI.
Paso 4: Almacenamiento en Vector DB
Ejemplo Pinecone:
Para cada chunk:
1. Generar embedding
2. Upsert a Pinecone:
- id: "chunk-123"
- values: [0.23, -0.45, ...]
- metadata: {"source": "doc.pdf", "page": 5}
Batch upsert: 100-1000 chunks por request (más rápido).
Pipeline completo (ejemplo)
Input: 1000 PDFs (promedio 10 páginas cada uno)
Proceso:
1. Extraer texto de PDFs (PyPDF2, pdfplumber)
→ 10K páginas de texto
2. Chunking (500 tokens, overlap 50)
→ ~50K chunks
3. Generar embeddings (OpenAI API)
→ 50K embeddings (1536D)
→ 50K chunks × 500 tokens = 25M tokens
→ Costo: 25,000 × $0.00002 = ~$0.50
4. Upsert a Pinecone (batch de 100)
→ 500 requests
→ Tiempo: ~5-10 minutos
Total: ~15-20 minutos, ~$0.50
Troubleshooting común
Problema 1: Chunks muy pequeños
Síntoma: Resultados sin contexto suficiente
Solución: Aumentar chunk size (500 → 800 tokens)
Problema 2: Chunks muy grandes
Síntoma: Resultados poco precisos (mucho ruido)
Solución: Reducir chunk size (1500 → 800 tokens)
Problema 3: Pérdida de contexto entre chunks
Síntoma: Query que requiere 2 chunks no obtiene respuesta completa
Solución: Aumentar overlap (50 → 100 tokens) o usar parent-child chunks
Resumen
Puntos clave:
- Chunking: 500-800 tokens con overlap 50-100
- Estrategias: Fixed-size, paragraph, sentence, hierarchical
- Metadata: source, page, section, timestamp, tags
- Embeddings: OpenAI API (calidad) o local (gratis)
- Pipeline: Extraer → Chunk → Embed → Store
Próxima cápsula: 04-query-processing.md — Embedding de query, kNN, reranking.