RecursiveCharacterTextSplitter
El RecursiveCharacterTextSplitter es la herramienta principal de LangChain para dividir documentos largos en fragmentos más pequeños y manejables. A diferencia de otros métodos de división más básicos, este splitter utiliza una estrategia jerárquica que respeta la estructura natural del texto, intentando mantener párrafos, oraciones y palabras completas siempre que sea posible.
Funcionamiento interno del splitter
El RecursiveCharacterTextSplitter funciona mediante un algoritmo recursivo que intenta dividir el texto utilizando una lista ordenada de separadores. Primero intenta dividir por párrafos (dobles saltos de línea), luego por oraciones (puntos seguidos de espacio), después por palabras (espacios) y finalmente por caracteres individuales si es necesario.
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Configuración básica del splitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
is_separator_regex=False,
)
Esta jerarquía de separadores garantiza que el texto se divida de la manera más natural posible. Si un párrafo completo cabe dentro del tamaño de chunk especificado, se mantendrá intacto. Solo cuando el párrafo es demasiado largo, el algoritmo intentará dividirlo por oraciones, y así sucesivamente.
Separadores por defecto
El splitter utiliza una lista predefinida de separadores que está optimizada para texto en inglés, pero funciona eficazmente también con español:
# Los separadores por defecto (en orden de prioridad)
default_separators = [
"\n\n", # Párrafos
"\n", # Líneas
" ", # Palabras
"", # Caracteres individuales
]
Puedes personalizar estos separadores según el tipo de documento que estés procesando:
# Splitter personalizado para código Python
code_splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=100,
separators=[
"\n\nclass ",
"\n\ndef ",
"\n\n",
"\n",
" ",
""
]
)
Ejemplo práctico con texto real
Veamos cómo funciona el splitter con un documento de ejemplo:
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Texto de ejemplo que simula un documento técnico
documento = """
La inteligencia artificial ha revolucionado múltiples sectores en las últimas décadas.
Sus aplicaciones van desde el reconocimiento de voz hasta la conducción autónoma.
En el ámbito del procesamiento de lenguaje natural, los modelos de transformers han
marcado un antes y un después. Estos modelos utilizan mecanismos de atención que
permiten procesar secuencias de texto de manera más eficiente.
Los sistemas RAG (Retrieval-Augmented Generation) combinan la recuperación de
información con la generación de texto. Esta aproximación permite a los modelos
acceder a conocimiento actualizado sin necesidad de reentrenamiento.
Para implementar un sistema RAG efectivo, es crucial dividir los documentos en
fragmentos apropiados. El tamaño de estos fragmentos afecta directamente la
calidad de la recuperación de información.
"""
# Configurar el splitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=50
)
# Dividir el documento
chunks = splitter.split_text(documento)
# Mostrar los resultados
for i, chunk in enumerate(chunks):
print(f"Chunk {i + 1}:")
print(chunk)
print(f"Longitud: {len(chunk)} caracteres")
print("-" * 50)
Trabajando con objetos Document
En aplicaciones RAG reales, normalmente trabajarás con objetos Document que incluyen metadatos además del contenido textual:
from langchain_core.documents import Document
# Crear documentos con metadatos
documentos = [
Document(
page_content="Contenido del primer documento sobre IA...",
metadata={"fuente": "articulo_ia.pdf", "pagina": 1}
),
Document(
page_content="Contenido del segundo documento sobre ML...",
metadata={"fuente": "libro_ml.pdf", "pagina": 15}
)
]
# El splitter preserva los metadatos en cada chunk
chunks_con_metadatos = splitter.split_documents(documentos)
# Verificar que los metadatos se mantienen
for chunk in chunks_con_metadatos:
print(f"Contenido: {chunk.page_content[:100]}...")
print(f"Metadatos: {chunk.metadata}")
Ejemplo de uso con documentos leídos de PDF, primero cargo el pdf:
Segundo hago el split:
Consideraciones para diferentes tipos de contenido
El tipo de contenido que estés procesando influye en cómo debes configurar el splitter:
Para documentos académicos o técnicos:
academic_splitter = RecursiveCharacterTextSplitter(
chunk_size=1200, # Chunks más grandes para mantener contexto
chunk_overlap=200,
separators=["\n\n", "\n", ". ", " ", ""]
)
Para código fuente:
code_splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=100,
separators=["\n\nclass ", "\n\ndef ", "\n\n", "\n", " ", ""]
)
Para contenido conversacional o chat:
chat_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # Chunks más pequeños para respuestas rápidas
chunk_overlap=50,
separators=["\n\n", "\n", ". ", "! ", "? ", " ", ""]
)
El RecursiveCharacterTextSplitter es especialmente eficaz para mantener la coherencia semántica del texto, ya que su enfoque jerárquico evita cortes abruptos en medio de ideas importantes. Esta característica lo convierte en la opción preferida para la mayoría de aplicaciones RAG donde la calidad del contexto es fundamental para obtener respuestas precisas.
chunk_size y chunk_overlap
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
Los parámetros chunk_size y chunk_overlap son fundamentales para controlar cómo se divide el texto y determinar la calidad del retrieval en sistemas RAG. Una configuración inadecuada de estos valores puede resultar en pérdida de contexto importante o en chunks demasiado fragmentados que dificulten la comprensión.
Entendiendo chunk_size
El chunk_size define el tamaño máximo en caracteres que puede tener cada fragmento de texto. Este parámetro actúa como un límite superior, pero el splitter intentará crear chunks más pequeños si encuentra separadores naturales antes de alcanzar este límite.
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Ejemplo con diferentes tamaños de chunk
texto_ejemplo = """
Los sistemas de recomendación utilizan algoritmos de machine learning para predecir
las preferencias de los usuarios. Estos sistemas analizan patrones de comportamiento
histórico para sugerir productos, contenido o servicios relevantes.
Existen principalmente tres tipos de sistemas de recomendación: colaborativos,
basados en contenido e híbridos. Los sistemas colaborativos se basan en las
similitudes entre usuarios, mientras que los basados en contenido analizan
las características de los elementos.
La implementación de un sistema de recomendación requiere considerar factores
como la escalabilidad, la precisión y la diversidad de las recomendaciones.
"""
# Chunk pequeño (200 caracteres)
splitter_pequeño = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=0
)
chunks_pequeños = splitter_pequeño.split_text(texto_ejemplo)
print(f"Chunks pequeños generados: {len(chunks_pequeños)}")
for i, chunk in enumerate(chunks_pequeños):
print(f"Chunk {i+1} ({len(chunk)} chars): {chunk[:100]}...")
El impacto del tamaño en la recuperación
Un chunk_size demasiado pequeño puede fragmentar información relacionada, mientras que uno demasiado grande puede incluir información irrelevante que diluya la relevancia del contenido recuperado.
# Comparación práctica de diferentes tamaños
tamaños = [300, 600, 1200]
for tamaño in tamaños:
splitter = RecursiveCharacterTextSplitter(
chunk_size=tamaño,
chunk_overlap=50
)
chunks = splitter.split_text(texto_ejemplo)
print(f"\nTamaño {tamaño}:")
print(f"Número de chunks: {len(chunks)}")
print(f"Tamaño promedio: {sum(len(c) for c in chunks) / len(chunks):.0f} chars")
# Mostrar el primer chunk como ejemplo
print(f"Primer chunk: {chunks[0][:150]}...")
Comprendiendo chunk_overlap
El chunk_overlap especifica cuántos caracteres se solapan entre chunks consecutivos. Este solapamiento es crucial para mantener la continuidad del contexto y evitar que información importante se pierda en los límites entre fragmentos.
# Ejemplo sin solapamiento
sin_overlap = RecursiveCharacterTextSplitter(
chunk_size=400,
chunk_overlap=0
)
# Ejemplo con solapamiento
con_overlap = RecursiveCharacterTextSplitter(
chunk_size=400,
chunk_overlap=100
)
texto_continuidad = """
La arquitectura de transformers revolucionó el procesamiento de lenguaje natural.
El mecanismo de atención permite al modelo enfocarse en diferentes partes del texto
de entrada simultáneamente. Esta capacidad de atención paralela es lo que hace
a los transformers tan eficientes para tareas de comprensión de texto.
Los modelos como BERT y GPT utilizan esta arquitectura para lograr resultados
excepcionales en múltiples tareas de NLP.
"""
chunks_sin = sin_overlap.split_text(texto_continuidad)
chunks_con = con_overlap.split_text(texto_continuidad)
print("Sin solapamiento:")
for i, chunk in enumerate(chunks_sin):
print(f"Chunk {i+1}: ...{chunk[-50:]}")
print("\nCon solapamiento:")
for i, chunk in enumerate(chunks_con):
print(f"Chunk {i+1}: ...{chunk[-50:]}")
Calculando el overlap óptimo
Una regla práctica es establecer el overlap entre el 10% y 20% del chunk_size. Esto proporciona suficiente contexto sin crear redundancia excesiva:
def calcular_overlap_recomendado(chunk_size):
"""Calcula el overlap recomendado basado en el tamaño del chunk"""
return int(chunk_size * 0.15) # 15% del tamaño del chunk
# Ejemplos de configuraciones balanceadas
configuraciones = [
{"chunk_size": 500, "chunk_overlap": calcular_overlap_recomendado(500)},
{"chunk_size": 1000, "chunk_overlap": calcular_overlap_recomendado(1000)},
{"chunk_size": 1500, "chunk_overlap": calcular_overlap_recomendado(1500)}
]
for config in configuraciones:
splitter = RecursiveCharacterTextSplitter(**config)
print(f"Chunk size: {config['chunk_size']}, Overlap: {config['chunk_overlap']}")
chunks = splitter.split_text(texto_continuidad)
print(f"Chunks generados: {len(chunks)}")
print(f"Eficiencia: {(sum(len(c) for c in chunks) / len(texto_continuidad)):.2f}x")
print("-" * 40)
Configuraciones según el caso de uso
La elección de parámetros debe adaptarse al tipo de aplicación RAG que estés desarrollando:
Para chatbots de atención al cliente:
# Respuestas rápidas y precisas
customer_service_splitter = RecursiveCharacterTextSplitter(
chunk_size=600, # Suficiente para procedimientos completos
chunk_overlap=120 # 20% de overlap para mantener contexto
)
Para análisis de documentos legales:
# Precisión máxima, contexto extenso
legal_splitter = RecursiveCharacterTextSplitter(
chunk_size=1500, # Chunks grandes para cláusulas completas
chunk_overlap=300 # Overlap generoso para referencias cruzadas
)
Para búsqueda en bases de conocimiento técnico:
# Balance entre precisión y cobertura
technical_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # Tamaño medio para explicaciones técnicas
chunk_overlap=150 # Overlap moderado para conceptos relacionados
)
Midiendo la efectividad de la configuración
Para evaluar si tu configuración es óptima, puedes analizar métricas como la distribución de tamaños y la redundancia:
def analizar_chunks(chunks):
"""Analiza las características de los chunks generados"""
tamaños = [len(chunk) for chunk in chunks]
estadisticas = {
"total_chunks": len(chunks),
"tamaño_promedio": sum(tamaños) / len(tamaños),
"tamaño_mínimo": min(tamaños),
"tamaño_máximo": max(tamaños),
"desviación_estándar": (sum((t - sum(tamaños)/len(tamaños))**2 for t in tamaños) / len(tamaños))**0.5
}
return estadisticas
# Analizar diferentes configuraciones
documento_prueba = "Tu documento de prueba aquí..." * 100 # Documento largo
for chunk_size in [500, 1000, 1500]:
overlap = int(chunk_size * 0.15)
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=overlap
)
chunks = splitter.split_text(documento_prueba)
stats = analizar_chunks(chunks)
print(f"\nConfiguración: chunk_size={chunk_size}, overlap={overlap}")
for key, value in stats.items():
print(f"{key}: {value:.2f}")
La configuración óptima de chunk_size y chunk_overlap depende del equilibrio entre mantener suficiente contexto para respuestas coherentes y evitar la dilución de información relevante. Experimentar con diferentes valores y medir el rendimiento en tu caso de uso específico es la mejor estrategia para encontrar la configuración ideal.
Aprendizajes de esta lección
- Comprender el funcionamiento jerárquico y recursivo del RecursiveCharacterTextSplitter.
- Aprender a configurar los parámetros chunk_size y chunk_overlap para dividir textos de forma eficiente.
- Saber personalizar separadores según el tipo de contenido para mantener la coherencia semántica.
- Entender la importancia del solapamiento entre fragmentos para preservar contexto en aplicaciones RAG.
- Evaluar y ajustar configuraciones según el caso de uso específico para optimizar la calidad de la recuperación de información.
Completa LangChain y certifícate
Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs