HTMLHeaderTextSplitter y MarkdownHeaderTextSplitter
Cuando trabajamos con documentos que tienen una estructura jerárquica bien definida, como páginas web HTML o documentación en Markdown, podemos aprovechar esta organización para crear chunks más inteligentes. Los splitters especializados HTMLHeaderTextSplitter
y MarkdownHeaderTextSplitter
preservan la información contextual de los encabezados, manteniendo la relación entre el contenido y su posición en la jerarquía del documento.
Preservando la estructura con HTMLHeaderTextSplitter
El HTMLHeaderTextSplitter analiza documentos HTML y utiliza las etiquetas de encabezado (<h1>
, <h2>
, <h3>
, etc.) como puntos de división natural. Esto resulta especialmente útil cuando procesamos páginas web, documentación online o contenido exportado desde sistemas de gestión de contenido.
from langchain_text_splitters import HTMLHeaderTextSplitter
# Definir qué encabezados usar como separadores
headers_to_split_on = [
("h1", "Header 1"),
("h2", "Header 2"),
("h3", "Header 3"),
]
# Crear el splitter
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# Ejemplo de contenido HTML
html_content = """
<html>
<body>
<h1>Introducción a Machine Learning</h1>
<p>El machine learning es una rama de la inteligencia artificial...</p>
<h2>Algoritmos Supervisados</h2>
<p>Los algoritmos supervisados aprenden de datos etiquetados...</p>
<h3>Regresión Lineal</h3>
<p>La regresión lineal es uno de los algoritmos más básicos...</p>
<h3>Árboles de Decisión</h3>
<p>Los árboles de decisión dividen el espacio de características...</p>
<h2>Algoritmos No Supervisados</h2>
<p>Estos algoritmos trabajan con datos sin etiquetas...</p>
</body>
</html>
"""
# Dividir el contenido
html_chunks = html_splitter.split_text(html_content)
# Examinar los resultados
for i, chunk in enumerate(html_chunks):
print(f"Chunk {i + 1}:")
print(f"Contenido: {chunk.page_content}")
print(f"Metadatos: {chunk.metadata}")
print("-" * 50)
Cada chunk resultante incluye metadatos estructurados que indican su posición en la jerarquía del documento. Esto permite mantener el contexto semántico y facilita la recuperación de información relacionada durante las consultas.
Trabajando con documentación Markdown
El MarkdownHeaderTextSplitter funciona de manera similar pero está optimizado para documentos Markdown, reconociendo la sintaxis de encabezados (#
, ##
, ###
, etc.) y preservando la estructura de la documentación técnica.
from langchain_text_splitters import MarkdownHeaderTextSplitter
# Configurar los niveles de encabezado a utilizar
markdown_headers = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
# Crear el splitter para Markdown
markdown_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=markdown_headers,
strip_headers=False # Mantener los encabezados en el contenido
)
# Ejemplo de documentación técnica
markdown_content = """
# API de Autenticación
Esta API proporciona endpoints para la autenticación de usuarios.
## Endpoints Disponibles
La API incluye los siguientes endpoints principales.
### POST /auth/login
Autentica un usuario con credenciales.
**Parámetros:**
- username: Nombre de usuario
- password: Contraseña
**Respuesta:**
```json
{
"token": "jwt_token_here",
"expires_in": 3600
}
POST /auth/refresh
Renueva un token de acceso existente.
Parámetros:
- refresh_token: Token de renovación
Códigos de Error
La API utiliza códigos de estado HTTP estándar.
401 Unauthorized
Se devuelve cuando las credenciales son inválidas.
403 Forbidden
Indica que el usuario no tiene permisos suficientes. """
Procesar el contenido
markdown_chunks = markdown_splitter.split_text(markdown_content)
Mostrar los chunks generados
for i, chunk in enumerate(markdown_chunks): print(f"Chunk {i + 1}:") print(f"Contenido: {chunk.page_content[:100]}...") print(f"Metadatos: {chunk.metadata}") print("-" * 50)
### Combinando splitters para documentos complejos
En muchos casos reales, necesitamos **combinar múltiples estrategias** de splitting. Por ejemplo, podemos usar primero un splitter basado en encabezados para dividir por secciones, y luego aplicar un `RecursiveCharacterTextSplitter` para controlar el tamaño de los chunks resultantes.
```python
from langchain_text_splitters import (
MarkdownHeaderTextSplitter,
RecursiveCharacterTextSplitter
)
# Primer paso: dividir por encabezados
markdown_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
)
# Segundo paso: controlar el tamaño de chunks
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
# Procesar un documento largo
large_markdown = """
# Manual de Usuario
Este manual explica cómo usar la aplicación...
## Instalación
Para instalar la aplicación, sigue estos pasos detallados...
[Contenido muy largo aquí]
## Configuración
La configuración se realiza mediante archivos YAML...
[Más contenido extenso]
### Configuración Básica
Los parámetros básicos incluyen...
[Contenido adicional]
"""
# Aplicar splitting en dos fases
header_chunks = markdown_splitter.split_text(large_markdown)
final_chunks = []
for chunk in header_chunks:
# Si el chunk es muy grande, dividirlo adicionalmente
if len(chunk.page_content) > 500:
sub_chunks = text_splitter.split_documents([chunk])
final_chunks.extend(sub_chunks)
else:
final_chunks.append(chunk)
print(f"Chunks finales generados: {len(final_chunks)}")
Configuración avanzada de metadatos
Ambos splitters permiten personalizar los metadatos que se incluyen con cada chunk, lo que resulta fundamental para sistemas RAG que necesitan información contextual rica.
# Configuración personalizada para HTML
html_splitter = HTMLHeaderTextSplitter(
headers_to_split_on=[
("h1", "title"),
("h2", "section"),
("h3", "subsection"),
],
return_each_element=True # Incluir cada elemento HTML como chunk separado
)
# Para Markdown con configuración específica
markdown_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[
("#", "chapter"),
("##", "section"),
("###", "topic"),
],
strip_headers=False, # Mantener encabezados en el contenido
return_each_element=False # Agrupar contenido bajo cada encabezado
)
Esta aproximación estructural al chunking es especialmente valiosa cuando trabajamos con documentación técnica, manuales de usuario, artículos académicos o cualquier contenido que siga una jerarquía clara. Los metadatos preservados permiten implementar estrategias de recuperación más sofisticadas, como buscar dentro de secciones específicas o mantener el contexto jerárquico durante la generación de respuestas.
Configuración avanzada de separadores
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
Más allá de los separadores predeterminados, RecursiveCharacterTextSplitter
ofrece configuraciones avanzadas que permiten adaptar el comportamiento de división a las características específicas de diferentes tipos de contenido. Esta personalización resulta crucial cuando trabajamos con documentos técnicos, código fuente o formatos especializados que requieren estrategias de splitting más sofisticadas.
Separadores personalizados por tipo de contenido
El comportamiento por defecto de RecursiveCharacterTextSplitter
utiliza una jerarquía de separadores que funciona bien para texto general, pero podemos definir separadores específicos según el tipo de documento que estemos procesando.
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Separadores optimizados para documentación técnica
technical_separators = [
"\n\n", # Párrafos
"\n### ", # Subsecciones
"\n## ", # Secciones
"\n# ", # Títulos principales
"\n```\n", # Bloques de código
"\n---\n", # Separadores horizontales
"\n", # Saltos de línea simples
". ", # Puntos finales
"! ", # Exclamaciones
"? ", # Preguntas
" ", # Espacios
"" # Caracteres individuales
]
# Crear splitter con separadores personalizados
tech_splitter = RecursiveCharacterTextSplitter(
separators=technical_separators,
chunk_size=800,
chunk_overlap=100,
length_function=len,
is_separator_regex=False
)
# Ejemplo con documentación técnica
technical_doc = """
# Guía de Instalación
Esta guía explica el proceso de instalación paso a paso.
## Requisitos del Sistema
Antes de comenzar, asegúrate de tener:
### Hardware Mínimo
- RAM: 8GB mínimo
- Disco: 50GB libres
- CPU: Dual-core 2.5GHz
### Software Requerido
- Python 3.9+
- Node.js 16+
- Docker 20.10+
```bash
# Verificar versiones
python --version
node --version
docker --version
Proceso de Instalación
Sigue estos pasos en orden:
- Clonar el repositorio
- Instalar dependencias
- Configurar variables de entorno
- Ejecutar migraciones
Para más información, consulta la documentación oficial. """
chunks = tech_splitter.split_text(technical_doc) print(f"Chunks generados: {len(chunks)}")
### Separadores con expresiones regulares
Para casos más complejos, podemos utilizar **expresiones regulares** como separadores, lo que permite identificar patrones específicos en el texto que indiquen puntos de división naturales.
```python
import re
# Separadores basados en patrones regex
regex_separators = [
r"\n\n+", # Múltiples saltos de línea
r"\n(?=\d+\.)", # Listas numeradas
r"\n(?=[-*+]\s)", # Listas con viñetas
r"\n(?=#{1,6}\s)", # Encabezados Markdown
r"(?<=\.)\s+(?=[A-Z])", # Fin de oración seguido de mayúscula
r"\n(?=```)", # Inicio de bloque de código
r"```\n", # Fin de bloque de código
r"\s+", # Espacios en blanco
r"" # Caracteres individuales
]
# Configurar splitter con regex
regex_splitter = RecursiveCharacterTextSplitter(
separators=regex_separators,
chunk_size=600,
chunk_overlap=80,
is_separator_regex=True # Habilitar interpretación regex
)
# Contenido con patrones específicos
structured_content = """
1. Configuración inicial del proyecto
- Crear estructura de directorios
- Inicializar repositorio Git
2. Instalación de dependencias
- Instalar paquetes base
- Configurar entorno virtual
```python
# Ejemplo de configuración
config = {
'database': 'postgresql://localhost:5432/mydb',
'debug': True,
'port': 8000
}
- Configuración de la base de datos
- Crear esquemas necesarios
- Ejecutar migraciones iniciales
• Verificar conexión a la base de datos • Poblar datos de prueba • Configurar índices para optimización """
regex_chunks = regex_splitter.split_text(structured_content) for i, chunk in enumerate(regex_chunks): print(f"Chunk {i + 1}: {chunk[:100]}...")
### Funciones de medición personalizadas
El parámetro `length_function` permite definir **métricas personalizadas** para medir el tamaño de los chunks. Esto es especialmente útil cuando trabajamos con contenido que incluye tokens especiales o cuando necesitamos optimizar para modelos específicos.
```python
import tiktoken
# Función para contar tokens en lugar de caracteres
def count_tokens(text: str) -> int:
"""Cuenta tokens usando el tokenizador de OpenAI"""
encoding = tiktoken.encoding_for_model("gpt-4")
return len(encoding.encode(text))
# Función para contenido con código
def count_code_aware(text: str) -> int:
"""Cuenta dando más peso a las líneas de código"""
lines = text.split('\n')
total_weight = 0
for line in lines:
if line.strip().startswith(('def ', 'class ', 'import ', 'from ')):
total_weight += len(line) * 1.5 # Más peso a definiciones
elif '```' in line:
total_weight += len(line) * 0.5 # Menos peso a marcadores
else:
total_weight += len(line)
return int(total_weight)
# Splitter optimizado para tokens
token_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 1000 tokens aproximadamente
chunk_overlap=100,
length_function=count_tokens
)
# Splitter consciente de código
code_splitter = RecursiveCharacterTextSplitter(
chunk_size=1200,
chunk_overlap=150,
length_function=count_code_aware
)
Configuración adaptativa según el contenido
Para sistemas RAG que procesan múltiples tipos de documentos, podemos implementar una estrategia adaptativa que seleccione la configuración de separadores según las características del contenido.
def create_adaptive_splitter(content: str) -> RecursiveCharacterTextSplitter:
"""Crea un splitter adaptado al tipo de contenido"""
# Detectar tipo de contenido
has_code = '```' in content or 'def ' in content or 'class ' in content
has_markdown = content.count('#') > 2
has_html = '<' in content and '>' in content
is_structured = content.count('\n\n') > content.count('\n') * 0.3
if has_code:
# Configuración para código
separators = [
"\n\nclass ",
"\n\ndef ",
"\n\n```",
"\n```\n",
"\n\n",
"\n",
" ",
""
]
chunk_size = 1000
overlap = 100
elif has_markdown:
# Configuración para Markdown
separators = [
"\n## ",
"\n### ",
"\n#### ",
"\n\n",
"\n",
". ",
" ",
""
]
chunk_size = 800
overlap = 80
elif has_html:
# Configuración para HTML
separators = [
"</div>",
"</p>",
"<br>",
"\n\n",
"\n",
" ",
""
]
chunk_size = 600
overlap = 60
else:
# Configuración para texto general
separators = [
"\n\n",
"\n",
". ",
"! ",
"? ",
" ",
""
]
chunk_size = 700
overlap = 70
return RecursiveCharacterTextSplitter(
separators=separators,
chunk_size=chunk_size,
chunk_overlap=overlap,
length_function=len
)
# Uso del splitter adaptativo
mixed_content = """
# Documentación de la API
## Endpoint de autenticación
```python
@app.route('/auth', methods=['POST'])
def authenticate():
username = request.json.get('username')
password = request.json.get('password')
if validate_credentials(username, password):
token = generate_jwt_token(username)
return jsonify({'token': token})
return jsonify({'error': 'Invalid credentials'}), 401
Este endpoint maneja la autenticación de usuarios mediante JWT tokens. """
adaptive_splitter = create_adaptive_splitter(mixed_content) adaptive_chunks = adaptive_splitter.split_text(mixed_content)
### Optimización de overlap inteligente
El **overlap inteligente** va más allá de un simple solapamiento de caracteres, considerando el contexto semántico para determinar qué información debe preservarse entre chunks adyacentes.
```python
def smart_overlap_splitter(content: str, base_chunk_size: int = 800) -> list:
"""Implementa overlap inteligente basado en contexto"""
# Identificar puntos de división semánticamente relevantes
sentences = content.split('. ')
chunks = []
current_chunk = ""
for sentence in sentences:
# Verificar si agregar la oración excede el tamaño
if len(current_chunk + sentence) > base_chunk_size:
if current_chunk:
chunks.append(current_chunk.strip())
# Overlap inteligente: mantener última oración completa
last_sentence_start = current_chunk.rfind('. ')
if last_sentence_start != -1:
overlap_content = current_chunk[last_sentence_start + 2:]
current_chunk = overlap_content + sentence
else:
current_chunk = sentence
else:
current_chunk = sentence
else:
current_chunk += ". " + sentence if current_chunk else sentence
# Agregar último chunk
if current_chunk:
chunks.append(current_chunk.strip())
return chunks
# Ejemplo de uso
sample_text = """
La inteligencia artificial ha revolucionado múltiples industrias. Los algoritmos de machine learning permiten automatizar tareas complejas. El procesamiento de lenguaje natural facilita la interacción humano-máquina. Los sistemas de recomendación mejoran la experiencia del usuario. La visión por computadora permite el análisis automatizado de imágenes. Estas tecnologías continúan evolucionando rápidamente.
"""
smart_chunks = smart_overlap_splitter(sample_text, 150)
for i, chunk in enumerate(smart_chunks):
print(f"Smart Chunk {i + 1}: {chunk}")
Esta configuración avanzada de separadores permite crear sistemas RAG más precisos y eficientes, adaptándose a las características específicas del contenido y optimizando tanto la calidad de la división como el rendimiento del sistema de recuperación de información.
Aprendizajes de esta lección
- Comprender el uso de HTMLHeaderTextSplitter y MarkdownHeaderTextSplitter para preservar la estructura jerárquica en documentos.
- Aprender a configurar separadores personalizados y basados en expresiones regulares para diferentes tipos de contenido.
- Implementar funciones de medición personalizadas para optimizar el tamaño de los chunks según el tipo de texto o código.
- Aplicar estrategias combinadas y adaptativas para dividir documentos complejos de manera eficiente.
- Entender la importancia de metadatos estructurados y overlap inteligente para mejorar la recuperación de información en sistemas RAG.
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