Inicio de la guía 1. Topología de la solución 2. Aspire como plano de control local 3. Configuración y contratos compartidos 4. Metadatos con SQLite y EF Core 5. API e interfaz de carga 6. Almacenamiento de objetos con MinIO 7. Pipeline de ingesta del worker 8. Extracción y división de texto 9. Artefactos literarios 10. Abstracciones de proveedores de IA 11. Almacenamiento vectorial con Qdrant 12. Flujo de preguntas y recuperación 13. Prompts y citas 14. Pruebas del pipeline 15. Notas de desarrollo local Todas las guías
Navegación de la guíaÍndice y capítulos
Capítulo 8

Extracción y división de texto en chunks

La extracción de texto vive en RAG.Core/Services/TextExtractor.cs.

Nota de traducción: Esta versión en español fue traducida con ayuda de un LLM y revisada para conservar los términos técnicos, el código y los nombres de archivos en inglés cuando corresponde.
Imagen decorativa del capítulo sobre Extracción y división de texto en chunks
La configuración predeterminada de chunks
"Ingestion": {
  "ChunkTokenCount": 800,
  "ChunkOverlapTokens": 100
}

La extracción de texto vive en RAG.Core/Services/TextExtractor.cs.

Para archivos TXT, la extracción es una lectura UTF-8 directa. Para PDFs, el proyecto usa PdfPig para extraer texto por página. La extracción de texto en PDF es imperfecta porque los PDFs son documentos de layout, no documentos de texto semántico. Por eso las citas incluyen números de página cuando están disponibles, pero el texto extraído puede contener espacios raros o artefactos.

Nota de producción: extracción y chunking son intencionalmente directos y materializan archivos completos, texto extraído, listas de tokens, chunks y embeddings en memoria. Eso puede volverse costoso o inestable con archivos grandes incluso cuando la carga está debajo del límite configurado de bytes. Un pipeline de producción haría streaming cuando sea posible, aplicaría límites de texto extraído y tokens, y escribiría embeddings/vectores por lotes. Este repositorio conserva la implementación simple porque el objetivo es aprender el flujo, no preparar producción.

El chunking vive en RAG.Core/Services/TextChunker.cs.

La configuración predeterminada de ingesta es:

{
  "ChunkTokenCount": 800,
  "ChunkOverlapTokens": 100
}

El tokenizador es aproximado, pero el objetivo de diseño es claro: producir chunks lo bastante grandes para contener contexto útil y lo bastante pequeños para que muchos chunks quepan en un prompt de LLM.

El código ahora hace explícita esa aproximación mediante ITokenEstimator. El ApproximateTokenEstimator predeterminado divide por espacios en blanco; no es el tokenizador usado por Gemini, Ollama ni ningún proveedor de embeddings. Ese nombre importa porque ChunkTokenCount es un control de ingeniería, no una garantía de que el proveedor verá exactamente 800 tokens de modelo.

public interface ITokenEstimator
{
    IReadOnlyList<string> EstimateTokens(string text);
}

El overlap ayuda a conservar continuidad. Si una oración importante queda cerca de un límite, el overlap da a los chunks vecinos una oportunidad de conservar suficiente contexto alrededor.

Nota: 800 y 100 son valores iniciales, no números mágicos. Un ChunkTokenCount de 800 da a cada chunk embebido suficiente espacio para contexto de párrafo, lo cual ayuda en preguntas literarias que dependen de evidencia cercana. Un valor menor como 400 puede mejorar la recuperación puntual para pasajes factuales cortos, pero crea más chunks, más llamadas de embeddings, más filas vectoriales y más oportunidades de separar ideas relacionadas. ChunkOverlapTokens es 100, o 12.5% del tamaño del chunk, así que los chunks adyacentes comparten suficiente contexto sin duplicar demasiado texto. En la práctica, el overlap suele ajustarse como proporción, comúnmente alrededor de 10-20%, y luego se adapta al tipo de documento y a la calidad observada de respuestas.

Los factores limitantes principales son el límite de entrada del modelo de embeddings, la ventana de contexto del modelo de chat, la cantidad de recuperación, latencia, almacenamiento y costo. Chunks más grandes reducen el volumen de indexación pero pueden hacer menos precisos los resultados de búsqueda. Chunks más pequeños mejoran precisión pero exigen recuperar más chunks para responder preguntas amplias. Más overlap conserva continuidad pero aumenta embeddings duplicados y almacenamiento vectorial. Los valores correctos deben medirse contra las preguntas que el sistema necesita responder.

Un tokenizador específico del proveedor sería una mejora futura, pero el punto de extensión actual ya es útil: las pruebas pueden fijar el comportamiento de chunking, y un tokenizador posterior puede reemplazar el estimador sin reescribir la ingesta.