Inicio / Artículos / Notas prácticas: Estrategias de fragmentación RAG: La guía completa de ingeniería

Notas prácticas: Estrategias de fragmentación RAG: La guía completa de ingeniería

Guía paso a paso operativa de las notas prácticas: Estrategias de fragmentación RAG: La guía de ingeniería completa: contratos, verificaciones y espacios para código listo para usar para los equipos que implementan este patrón.

2654 palabras

Las notas siguientes reconstruyen un camino práctico para abordar “RAG Chunking Strategies: The Complete Engineering Guide”. Se da énfasis en los contratos, las verificaciones y los marcadores de código reutilizables, en lugar de en un enfoque motivacional. Al trabajar en la etapa de descripción general, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Considere esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los elementos generados, defina las verificaciones de éxito y evite completaciones parciales silenciosas.

El principal compromiso: contexto versus precisión

La etapa de contexto del principal compromiso comercial funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la demostración a entornos compartidos. Separe la política de fragmentación de la política de recuperación; cambiar una no debe obligar a reescribir la otra cuando cambian las métricas de calidad.

[ TOO SMALL CHUNKS ]                  [ TOO LARGE CHUNKS ]
Loss of Context / Meaning             "Lost in the Middle" Effect
(e.g., "IF request is made...")       (Dense with irrelevant fluff)
            │                                      │
            └───────────────► 🎯 ◄─────────────────┘
                      THE GOLDILOCKS ZONE
                    (High Precision + Context)

Estrategia 1: División de tamaño fijo y recursiva (Las líneas base)

La etapa recursiva de tamaño fijo de la Estrategia 1 funciona mejor cuando se trata como una superficie medible. Capture un transcripte ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema.

División en trozos de tamaño fijo (El enfoque ingenuo)

La etapa de particionamiento de tamaño fijo “Naive” funciona mejor cuando se trata como una superficie medible. Capture un transcripto ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Separe la política de particionamiento de la política de recuperación; cambiar una no debe obligar a reescribir la otra cuando cambian las métricas de calidad. La etapa de particionamiento de tamaño fijo “Naive” funciona mejor cuando se trata como una superficie medible. Capture un transcripto ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas.

Particionamiento recursivo de caracteres (La línea base de producción)

En la etapa de fragmentación recursiva de caracteres, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Registre los tiempos de ejecución y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana del costo evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos. Cite los pasajes que realmente sirvieron de base para la respuesta; sin citas, los operadores no pueden distinguir entre alucinaciones y brechas en el indexado.

# Example: LangChain Recursive Character Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=50,
    separators=["\n\n", "\n", ". ", " ", ""]
)

Estrategia 2: Fragmentación consciente de la estructura y semántica

En la fase Semántica Consciente de Estructura de Estrategia 2, se deben definir las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Se debe mantener la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos confidenciales y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema. Se deben citar los pasajes que realmente sustentan la respuesta. Sin citas, los operadores no pueden distinguir entre una alucinación y una laguna en el indexado.

Fragmentación Consciente de Estructura (Propia del Documento)

En la etapa de fragmentación nativa de documentos consciente de la estructura, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Cite los pasajes que realmente sustentan la respuesta. Sin citas, los operadores no pueden distinguir entre alucinaciones y brechas en el indexado. En la etapa de fragmentación nativa de documentos consciente de la estructura, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las entregas parciales silenciosas.

Finalización.

Fragmentación semántica (límites basados en el significado)

Al trabajar en la etapa de fragmentación semántica con límites basados en el significado, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana del costo evita facturas inesperadas cuando el proceso pasa de la versión de demostración a entornos compartidos. Mida la capacidad de recuperación con un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente.

Sentence A ──► Embed ──┐
Sentence B ──► Embed ──┴── Similarity: 0.89 (Keep together)
Sentence C ──► Embed ──── Similarity: 0.32 (Drop below threshold -> CUT HERE)

Estrategia 3: Arquitecturas avanzadas que preservan el contexto

Al trabajar en la etapa Avanzada de Preservación de Contexto de la Estrategia 3, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Mida la capacidad de recuperación con un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente.

1. División en fragmentos de pequeño a grande (padre-hijo)

Al trabajar en la etapa 1 de fragmentación de tamaño pequeño a grande entre padre e hijo, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no de mejoras posteriores. Mida la capacidad de recuperación con un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente. Al trabajar en la etapa 1 de fragmentación de tamaño pequeño a grande entre padre e hijo, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas.

2. Fragmentación tardía

La etapa 2 de procesamiento por bloques funciona mejor cuando se trata como una superficie medible. Capture una transcripción exitosa, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo por token o consulta junto con los resultados funcionales. Tener visibilidad del costo desde temprano evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos. Separe la política de procesamiento por bloques de la política de recuperación de datos; cambiar una no debería obligar a reescribir la otra cuando cambian las métricas de calidad.

Matriz de decisiones para producción

La etapa de la Matriz de Decisiones de Producción funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema.

Reglas de ingeniería resumidas para el éxito

Las Reglas de Ingeniería Resumidas para las etapas funcionan mejor cuando se tratan como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación. Los intentos repetidos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son ajustes realizados posteriormente. Separe la política de fragmentación de la política de recuperación. Cambiar una no debe obligar a reescribir la otra cuando cambian las métricas de calidad. Las Reglas de Ingeniería Resumidas para las etapas funcionan mejor cuando se tratan como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas.

Es hora de ponerse a trabajar...

Para poder llevar a cabo la fase, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Registre los tiempos de ejecución y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos. Cite los pasajes que realmente sirvieron de base para la respuesta; sin citas, los operadores no pueden distinguir entre alucinaciones y lagunas en el indexado.

Requisitos previos

En la fase de Requisitos previos, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema. Mencione las secciones que realmente sirvieron como base para la respuesta. Sin citaciones, los operadores no podrán distinguir entre una alucinación y una laguna en el indexado.

pip install langchain langchain-community langchain-experimental llama-index llama-index-embeddings-openai openai chromadb
export OPENAI_API_KEY="your-openai-api-key"

1. Fragmentación recursiva de caracteres (LangChain)

Para la etapa 1 de Fragmentación Recursiva de Caracteres, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Cite los pasajes que realmente sustentan la respuesta. Sin citas, los operadores no pueden distinguir entre alucinaciones y brechas en el indexado. Para la etapa 1 de Fragmentación Recursiva de Caracteres, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas.

from langchain_text_splitters import RecursiveCharacterTextSplitter

# Sample document
sample_text = """
# RAG System Design
Retrieval-Augmented Generation (RAG) decouples knowledge storage from reasoning capability.
Instead of forcing the AI to answer strictly from memory, RAG searches an external database first.
## The Ingestion Pipeline
1. Document Extraction: PDFs and web pages are converted into clean text.
2. Chunking: Documents are chopped into smaller, manageable text blocks.
3. Vectorization: Each block is converted into a numeric representation.
"""

# Initialize Recursive Splitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,        # Target chunk size in characters/tokens
    chunk_overlap=30,      # Overlap to prevent mid-sentence context loss
    separators=["\n\n", "\n", ". ", " ", ""] # Try double line breaks first
)
chunks = text_splitter.create_documents([sample_text])
print(f"Total chunks created: {len(chunks)}\n")
for i, chunk in enumerate(chunks):
    print(f"--- Chunk {i+1} ---")
    print(chunk.page_content)

2. Fragmentación padre-hijo / de pequeño a grande (LangChain + Chroma)

Al trabajar en la fase de fragmentación padre-hijo de pequeño a grande, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de entornos de demostración a entornos compartidos. Mida el rendimiento en la recuperación de información con un conjunto fijo de preguntas antes de ajustar los prompts. Cambiar constantemente los prompts rara vez soluciona un sistema de recuperación deficiente.

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.retrievers import ParentDocumentRetriever
from langchain_community.vectorstores import Chroma
from langchain_community.storage import InMemoryStore
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
# 1. Initialize Vector Store (for small child embeddings) and DocStore (for large parent text)
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(collection_name="parent_child_rag", embedding_function=embeddings)
docstore = InMemoryStore()

# 2. Define Parent (Big) and Child (Small) Splitters
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=600, chunk_overlap=50)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=120, chunk_overlap=20)

# 3. Create the ParentDocumentRetriever
retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=docstore,
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)

# 4. Ingest Documents
docs = [
    Document(
        page_content="""
        System Architecture: The Two Pipelines.
        A production RAG framework runs on two main pipelines: Ingestion and Inference.
        The Ingestion pipeline extracts text, creates chunks, embeds them, and stores them in a vector DB.
        The Inference pipeline encodes user queries, performs vector similarity search, injects context into prompts, and generates LLM answers.
        Hybrid search combines keyword and vector retrieval to handle exact SKU IDs alongside general concepts.
        """
    )
]
retriever.add_documents(docs)

# 5. Query the Retriever
query = "What happens during inference in RAG?"
retrieved_parents = retriever.invoke(query)
print(f"Retrieved Parent Context (Full Block):\n")
print(retrieved_parents[0].page_content)

3. Fragmentación semántica (LlamaIndex)

Al trabajar en las 3 etapas de Semantic Chunking de LlamaIndex, primero anote el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Mida la tasa de recuperación con un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente.

from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.schema import Document
# 1. Initialize the Embedding Model used for detecting topic shifts
embed_model = OpenAIEmbedding(model="text-embedding-3-small")

# 2. Configure the Semantic Splitter
semantic_parser = SemanticSplitterNodeParser(
    buffer_size=1,                         # Number of surrounding sentences to evaluate together
    breakpoint_percentile_threshold=90,     # Split threshold percentile (higher = fewer, larger chunks)
    embed_model=embed_model
)

# 3. Sample document with distinct thematic shifts
raw_text = """
Quantum computing leverages qubits that can exist in superposition states, unlike classical bits.
Superposition allows algorithms to process vast potential outcomes simultaneously.
Entanglement further connects qubit states instantaneously across physical space.
On a totally different topic, baking sourdough bread requires maintaining a wild yeast starter.
You feed the starter equal parts flour and water every 24 hours to encourage fermentation.
Proper gluten development requires folding the dough during the bulk fermentation stage.
"""
doc = Document(text=raw_text)

# 4. Generate Nodes (Chunks)
nodes = semantic_parser.get_nodes_from_documents([doc])
print(f"Total Semantically Coherent Chunks: {len(nodes)}\n")
for i, node in enumerate(nodes):
    print(f"--- Chunk {i+1} ---")
    print(node.get_content().strip())
    print("\n")

Resumen de implementación

Al trabajar en la etapa de Resumen de Implementación, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no de mejoras posteriores. Mida la capacidad de recuperación con un conjunto fijo de preguntas antes de ajustar los prompts. El cambio constante de prompts rara vez soluciona un sistema de recuperación deficiente. Al trabajar en la etapa de Resumen de Implementación, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina las verificaciones de éxito y rechace las completaciones parciales silenciosas.

Conclusión: El fragmentado es un problema de ingeniería, no de inteligencia artificial

El método de fragmentación en la fase de conclusión funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos. Separe la política de fragmentación de la política de recuperación; cambiar una no debe obligar a reescribir la otra cuando cambian las métricas de calidad.

Lista de verificación operativa

En la fase de lista de verificación operativa, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto.