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

UsoChunk sizeJustificación
RAG general500-800 tokensBalance contexto/precisión
Búsqueda de código200-400 tokensFunciones completas
Documentación técnica800-1200 tokensSecciones completas
Artículos largos1000-1500 tokensMantener 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.