Estrategias específicas para código y HTML
Aplique una división especializada al código Python mediante separadores de funciones basados en AST, al HTML mediante analizadores conscientes de las etiquetas y a Markdown mediante la jerarquía de encabezados.
Estrategias específicas para código y HTML es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.
Por qué falla la fragmentación genérica en documentos especializados
La fragmentación basada en texto se diseñó para la prosa, pero los datos del mundo real incluyen código fuente, páginas HTML y documentación Markdown. Dividir el código en un límite fijo de caracteres puede cortar una función por la mitad de su cuerpo, lo que inutiliza el fragmento para la recuperación. Los documentos especializados necesitan fragmentadores que comprendan su estructura interna, no solo su longitud.
Fragmentación de código Python basada en AST
El árbol de sintaxis abstracta (AST) de un archivo Python representa cada función, clase y módulo como un nodo estructurado. Al recorrer el AST, puede extraer cada función o método como su propio fragmento, manteniendo unidos la firma, el docstring y el cuerpo. PythonCodeTextSplitter de LangChain utiliza este enfoque internamente.
import ast
import textwrap
def extract_functions(source_code: str) -> list[dict]:
tree = ast.parse(source_code)
chunks = []
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
start = node.lineno - 1
end = node.end_lineno
lines = source_code.splitlines()[start:end]
chunks.append({
'name': node.name,
'code': '\n'.join(lines),
'start_line': node.lineno,
})
return chunksFragmentación por límites de clase
En las bases de código orientadas a objetos, fragmentar en el nivel de clase suele ser mejor que hacerlo en el nivel de función. Un fragmento de clase conserva la relación entre los métodos y el estado compartido sobre el que operan. Puede incluir el docstring de la clase y todos los cuerpos de sus métodos en un único fragmento, y después crear fragmentos independientes más detallados solo para los métodos largos.
from langchain_text_splitters import Language, RecursiveCharacterTextSplitter
python_splitter = RecursiveCharacterTextSplitter.from_language(
language=Language.PYTHON,
chunk_size=1000,
chunk_overlap=100,
)
with open('my_module.py', 'r') as f:
source = f.read()
chunks = python_splitter.create_documents([source])
print(f'Created {len(chunks)} code chunks')Adición de metadatos de código a los fragmentos
Los fragmentos de código sin procesar solo son tan útiles como sus metadatos. Al almacenar fragmentos de código en una base de datos vectorial, incluya la ruta del archivo, el nombre de la función, el lenguaje de programación y el intervalo de líneas. Estos metadatos permiten al recuperador filtrar por lenguaje o archivo, y al LLM citar la ubicación exacta del código fuente en su respuesta.
from langchain_core.documents import Document
def chunk_python_file(filepath: str) -> list[Document]:
with open(filepath) as f:
source = f.read()
functions = extract_functions(source) # from previous example
docs = []
for fn in functions:
docs.append(Document(
page_content=fn['code'],
metadata={
'source': filepath,
'function': fn['name'],
'language': 'python',
'start_line': fn['start_line'],
}
))
return docsHTML: la estructura por encima de los caracteres
Los documentos HTML tienen una estructura jerárquica formada por encabezados, secciones, párrafos y listas. Dividir HTML por cantidad de caracteres suele cortar las etiquetas y producir fragmentos malformados. El enfoque adecuado consiste en analizar el HTML con un analizador apropiado, como BeautifulSoup, y extraer elementos con significado semántico, como las etiquetas <article>, <section> y <p>.
from bs4 import BeautifulSoup
def chunk_html_by_section(html: str) -> list[dict]:
soup = BeautifulSoup(html, 'html.parser')
chunks = []
for tag in soup.find_all(['h1', 'h2', 'h3', 'p', 'li']):
text = tag.get_text(separator=' ', strip=True)
if len(text) > 40: # skip trivial fragments
chunks.append({
'tag': tag.name,
'text': text,
})
return chunksFragmentación jerárquica de HTML por encabezados
Una estrategia de HTML más sofisticada agrupa el contenido bajo su encabezado más cercano. Cada párrafo y lista que aparece después de un encabezado <h2> pertenece a esa sección. Al agrupar el texto con su encabezado principal, se conserva el contexto temático que un párrafo independiente perdería. HTMLHeaderTextSplitter de LangChain implementa este proceso automáticamente.
from langchain_text_splitters import HTMLHeaderTextSplitter
headers_to_split_on = [
('h1', 'Header 1'),
('h2', 'Header 2'),
('h3', 'Header 3'),
]
splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
with open('page.html') as f:
html = f.read()
sections = splitter.split_text(html)
for sec in sections[:3]:
print(sec.metadata)
print(sec.page_content[:200])
print('---')Markdown: respeto de la jerarquía de encabezados
La documentación Markdown se organiza mediante encabezados #, ## y ###. MarkdownHeaderTextSplitter divide el contenido en los límites de los encabezados y almacena la jerarquía de estos en los metadatos. Esto significa que cada fragmento conoce su ruta completa de encabezados, lo que mejora considerablemente la relevancia del contexto recuperado cuando los usuarios preguntan por secciones específicas de la documentación.
from langchain_text_splitters import MarkdownHeaderTextSplitter
headers_to_split_on = [
('#', 'H1'),
('##', 'H2'),
('###', 'H3'),
]
md_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
with open('README.md') as f:
markdown = f.read()
docs = md_splitter.split_text(markdown)
for doc in docs[:2]:
print('Metadata:', doc.metadata)
print('Content:', doc.page_content[:300])
print()División secundaria después de dividir por encabezados
Después de dividir por encabezados, algunas secciones individuales todavía pueden ser demasiado largas para el límite de tokens del modelo de incrustación. El patrón recomendado consta de dos pasos: primero, dividir según la jerarquía de encabezados para conservar el contexto semántico; después, aplicar un divisor basado en caracteres a cualquier sección que supere el límite de tamaño de los fragmentos. Así se garantiza que ningún fragmento sea demasiado grande sin perder los metadatos de los encabezados.
from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter
header_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[('#', 'H1'), ('##', 'H2')]
)
char_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
)
with open('docs.md') as f:
md = f.read()
header_chunks = header_splitter.split_text(md)
final_chunks = char_splitter.split_documents(header_chunks)
print(f'{len(final_chunks)} final chunks produced')Fragmentación de PDF con reconocimiento de tablas
Los PDF extraídos con herramientas como PyMuPDF o pdfplumber suelen perder la estructura de las tablas y producir filas de texto desordenadas. Para resolverlo, utilice analizadores de PDF que tengan en cuenta el diseño, detecten los límites de las tablas y las conviertan a formato Markdown o CSV antes de fragmentarlas. Trate cada tabla como un único fragmento con metadatos estructurados que la identifiquen como tabla y no como prosa.
import pdfplumber
def extract_pdf_chunks(pdf_path: str) -> list[dict]:
chunks = []
with pdfplumber.open(pdf_path) as pdf:
for page_num, page in enumerate(pdf.pages):
# Extract tables separately
for table in page.extract_tables():
rows = ['|'.join(str(c) for c in row) for row in table]
chunks.append({
'type': 'table',
'content': '\n'.join(rows),
'page': page_num + 1,
})
# Extract prose text
text = page.extract_text()
if text:
chunks.append({'type': 'text', 'content': text, 'page': page_num + 1})
return chunksDetección de idioma para corpus mixtos
Las bases de conocimiento empresariales suelen combinar distintos tipos de archivo: scripts de Python, documentación de API en HTML, notas de arquitectura en Markdown y exportaciones de datos en CSV. Una canalización de fragmentación sólida debe detectar el tipo de archivo a partir de la extensión o del tipo MIME y dirigir cada documento al fragmentador especializado adecuado. Así se evita aplicar la lógica de división de código a la prosa, o viceversa.
from pathlib import Path
def route_document(filepath: str) -> list[dict]:
ext = Path(filepath).suffix.lower()
if ext == '.py':
return chunk_python_file(filepath)
elif ext in ('.html', '.htm'):
with open(filepath) as f:
return chunk_html_by_section(f.read())
elif ext == '.md':
# use MarkdownHeaderTextSplitter
return chunk_markdown(filepath)
elif ext == '.pdf':
return extract_pdf_chunks(filepath)
else:
# fallback: plain text recursive splitter
return chunk_plain_text(filepath)Conservación del contexto mediante líneas circundantes
Al fragmentar código por función, suele ser útil incluir algunas líneas de contexto circundante, como las instrucciones de importación situadas al principio del archivo o la definición de la clase que contiene un método. Este contexto ayuda al LLM a comprender qué bibliotecas están disponibles y cuál es la función del método dentro de la clase general, lo que mejora la calidad de las respuestas generadas.
def chunk_with_imports(source_code: str, fn_node, lines: list[str]) -> str:
# Gather top-of-file imports (first block before first non-import)
import_lines = []
for line in lines:
stripped = line.strip()
if stripped.startswith('import ') or stripped.startswith('from '):
import_lines.append(line)
elif stripped and not stripped.startswith('#'):
break
fn_body = '\n'.join(lines[fn_node.lineno - 1:fn_node.end_lineno])
return '\n'.join(import_lines) + '\n\n' + fn_bodyComprobación rápida
Compruebe su comprensión de las estrategias de fragmentación específicas para documentos explicadas en esta lección.
Resumen de la lección
En esta lección ha aprendido que la fragmentación basada en AST conserva los límites de las funciones y clases de Python; HTMLHeaderTextSplitter y MarkdownHeaderTextSplitter respetan la jerarquía de encabezados para mantener el contexto junto a su sección; y un enfoque de dos pasos (división por encabezados seguida de división por caracteres) permite procesar secciones demasiado grandes sin perder los metadatos estructurales. A continuación exploraremos la búsqueda híbrida, que combina la recuperación densa y dispersa.
Preguntas frecuentes
¿La lección «Estrategias específicas para código y HTML» es gratis?
Sí — el texto completo de «Estrategias específicas para código y HTML» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Estrategias específicas para código y HTML»?
Aplique una división especializada al código Python mediante separadores de funciones basados en AST, al HTML mediante analizadores conscientes de las etiquetas y a Markdown mediante la jerarquía de… Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Engineering Academy?
No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Estrategias específicas para código y HTML»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?
Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Por qué la división ingenua perjudica la recuperación
- División semántica con similitud de embeddings
- Recuperación padre-hijo y de pequeño a grande
- Estrategias específicas para código y HTML