Chunking Semántico para RAG: Construir un Pipeline de Datos Web
Advanced Data Extraction Specialist
TL;DR:
- El agrupamiento semántico agrupa texto utilizando cambios en el significado. Necesita un método de segmentación definido, un modelo de incrustación y una regla para decidir dónde termina un fragmento.
- El texto fuente limpio es parte de la calidad de recuperación. Los menús de navegación y los banners repetidos pueden distorsionar los fragmentos antes de que el recuperador los vea.
- Cada fragmento debe mantener su origen y posición. La procedencia hace que un pasaje recuperado sea útil para citas y diagnósticos.
- Un divisor semántico necesita una comparación base. El trabajo adicional de incrustación no garantiza mejores respuestas que una estrategia de división más simple.
- Gratis para empezar. Usa el crédito de cuenta de Scrapeless para evaluar el paso de colección upstream en un pequeño conjunto de documentos aprobados.
Introducción: La recuperación comienza antes de la tienda de vectores
Un recuperador solo puede devolver los pasajes almacenados en su índice. En generación aumentada por recuperación, la evidencia recuperada forma parte de la entrada de generación. Si un pasaje contiene la mitad de una explicación, o combina una declaración de política con texto de navegación no relacionado, el generador de respuestas recibe un contexto incompleto incluso cuando la puntuación de similitud parece fuerte.
El agrupamiento semántico cambia dónde comienzan y terminan esos pasajes. En lugar de cortar solo a una longitud fija, el divisor compara representaciones de oraciones vecinas y crea un límite cuando sus significados divergen lo suficiente. Un límite de tamaño sigue siendo importante porque un tema coherente puede ser más largo de lo que el modelo downstream puede aceptar.
Este artículo describe un pipeline web-a-RAG con Scrapeless como la capa de adquisición y un divisor de Python transparente como la capa de transformación. Complementa la extracción estructurada con un modelo de lenguaje: la extracción produce campos de tareas, mientras que el agrupamiento prepara pasajes para una posterior recuperación.
Lo que hace el Agrupamiento Semántico
El agrupamiento semántico utiliza una representación del significado para elegir los límites de texto. Una implementación común divide un documento en oraciones, incrusta esas oraciones, compara vectores adyacentes y comienza un nuevo grupo en un cambio suficientemente grande.
Métodos de incrustación de oraciones mapean el texto de las oraciones en vectores que pueden ser comparados en términos de similitud. El significado de una puntuación de similitud depende del modelo y de la entrada, por lo que establecer un límite numérico es un parámetro a evaluar en lugar de una definición universal de cambio de tema.
| Estrategia | Regla de límite | Punto de partida útil | Principal compensación |
|---|---|---|---|
| Tamaño fijo | Una longitud configurada | Una línea base simple | Puede cortar a través de una explicación |
| Consciente de la estructura | Encabezados y saltos de párrafo | Páginas de referencia organizadas | Depende de una estructura de documento limpia |
| Semántico | Cambios en la similitud de incrustación | Texto con cambios de tema | Agrega computación y ajuste de modelo |
| Híbrido | Estructura, revisiones semánticas y límites | Colecciones de documentos mixtas | Más configuración para evaluar |
Los encabezados, tablas, bloques de código y listas necesitan tratamiento especial. Un divisor de oraciones puede dañar una tabla al desprender un valor de su etiqueta de columna. Preserve estas unidades durante el preprocesamiento o enrútelas por un camino consciente de la estructura.
Pipeline a Primera Vista
El pipeline convierte un documento web capturado en pasajes indexados que retienen su origen. Sus etapas son adquisición → normalización de texto → segmentación de oraciones → incrustación → formación de fragmentos → evaluación de recuperación.
Desbloqueador Web de Scrapeless maneja la solicitud objetivo. Tu aplicación limpia el contenido devuelto, genera incrustaciones a través de un modelo seleccionado y almacena los pasajes resultantes. La adquisición web no crea por sí misma un índice de vectores ni elige la estrategia de agrupamiento correcta.
Guarda la respuesta original antes de la transformación. Mantén la URL solicitada, cualquier URL canónica establecida, el tiempo de colección, el título de la página y un hash del texto normalizado. Una URL canónica debe provenir de evidencia fuente; no la fabriques eliminando segmentos de la ruta.
Requisitos Previos
Necesitas un conjunto aprobado de páginas fuente públicas, una clave API de Scrapeless para adquisición, Python para procesamiento y un modelo de incrustación que puedas ejecutar localmente o a través de tu proveedor elegido. El proveedor o modelo determina la configuración de incrustación y los requisitos de acceso.
El divisor de este tutorial consume un sentences.json archivo con una cadena source_url, una lista sentences ordenada, y una lista embeddings que contiene un vector numérico por oración. No asume un modelo hospedado o dimensión de vector particular. El mismo modelo debe usarse para cada oración en una ejecución.
La adquisición de páginas autenticadas y la generación de incrustaciones son requisitos previos que no se han ejecutado de extremo a extremo para este ejemplo. El separador se puede verificar de forma independiente, pero las comprobaciones del algoritmo local no establecen la calidad de recuperación ni la integración exitosa del modelo.
Etapa 1: Captura y Limpieza del Documento Fuente
Un documento útil comienza con el contenido de la página previsto en lugar de una página de desafío, un formulario de inicio de sesión o un contenedor de navegación. Adquiere la página a través de la interfaz de solicitud de Web Unlocker y verifica que su contenido esperado esté presente antes de extraer texto.
Para cada página aceptada, elimina scripts, estilos, navegación repetida y bloques promocionales no relacionados. Preserva los encabezados y los límites de los párrafos. Si la página se renderiza dinámicamente, utiliza la configuración de renderizado documentada y verifica que el contenido devuelto incluya el texto relevante.
Almacena el contenido en bruto y normalizado por separado. Eso hace posible diagnosticar si un pasaje recuperado erróneamente provino de la colección, limpieza, segmentación o del modelo de incrustación. Las relaciones de procedencia entre los datos fuente y derivados son útiles aquí: el fragmento se deriva de una versión específica del documento normalizado.
No combines silenciosamente el cuerpo de una página con un título o fecha de publicación de otra. Si un campo no está disponible, déjalo sin asignar. El tiempo de colección de la página y el tiempo de publicación de la fuente son diferentes campos de metadatos.
Etapa 2: Segmentación de Oraciones y Generación de Incrustaciones Consistentes
La segmentación de oraciones produce las unidades de texto ordenadas que el separador semántico comparará. Utiliza un segmentador apropiado para el idioma e inspecciona su tratamiento de abreviaturas, decimales, encabezados y listas de viñetas en tus documentos de muestra.
Evita afirmar que una división básica por puntos funciona para cada página. Un párrafo que contenga una abreviatura o un ejemplo de código puede romperse en fragmentos engañosos. Para páginas de referencia cortas, los límites de encabezados y párrafos pueden ya proporcionar una estructura suficiente sin un pase semántico.
Genera una incrustación para cada oración y preserva el orden exacto. Registra el identificador del modelo, la configuración de normalización y el hash del texto fuente junto a los vectores. Rechaza vectores faltantes, dimensiones inconsistentes o valores no finitos antes de calcular similitudes.
Una ventana de contexto a nivel de párrafo puede mejorar algunas representaciones de oraciones, pero cambia el experimento. Mantén esa configuración fija al comparar reglas de separación para que un cambio en la entrada de la incrustación no se atribuya erróneamente al algoritmo de límites.
Comienza a Raspar con Scrapeless
¡Potencia tu flujo de trabajo de raspado web y automatización con Scrapeless!
Regístrate hoy y obtén $5 en crédito gratis — sin tarjeta de crédito requerida.Reclama tu crédito gratis ahora en el Tablero de Scrapeless.
Etapa 3: Crear Fragmentos Semánticos Acotados
El separador a continuación comienza un nuevo fragmento cuando la similitud de oraciones adyacentes cae por debajo de un umbral configurado o el presupuesto de caracteres se excedería. Guárdalo como chunk_sentences.py.
Nota: Este script requiere un archivo real
sentences.jsongenerado a partir de tu texto capturado y el modelo de incrustaciones. La generación de incrustaciones sigue siendo un requisito previo; el ejemplo no incluye un conjunto de vectores fabricados ni reclama una mejora en la recuperación medida.
python
import json
import math
import os
from pathlib import Path
source = json.loads(Path("sentences.json").read_text())
sentences = source["sentences"]
vectors = source["embeddings"]
threshold = float(os.environ["SIMILARITY_THRESHOLD"])
max_chars = int(os.environ["MAX_CHUNK_CHARS"])
if not -1 <= threshold <= 1 or max_chars <= 0:
raise ValueError("Invalid chunking configuration")
if not sentences or len(sentences) != len(vectors):
raise ValueError("Each sentence needs one embedding")
dimension = len(vectors[0])
if not dimension:
raise ValueError("Embeddings must not be empty")
for text, vector in zip(sentences, vectors):
if not isinstance(text, str) or not text.strip():
raise ValueError("Sentence text must be nonempty")
if len(text) > max_chars:
raise ValueError("Segment oversized sentences before chunking")
if len(vector) != dimension or not all(math.isfinite(v) for v in vector):
raise ValueError("Invalid embedding dimension or value")
if sum(v * v for v in vector) == 0:
raise ValueError("A zero vector has no cosine direction")
def cosine(a, b):
numerator = sum(x * y for x, y in zip(a, b))
denominator = math.sqrt(sum(x*x for x in a) * sum(y*y for y in b))
return max(-1.0, min(1.0, numerator / denominator))
chunks, start, current = [], 0, []
for index, sentence in enumerate(sentences):
topic_change = index > 0 and cosine(vectors[index-1], vectors[index]) < threshold
too_long = len(" ".join(current + [sentence])) > max_chars
if current and (topic_change or too_long):
chunks.append({"start_sentence": start, "end_sentence": index,
"text": " ".join(current)})
current, start = [], index
current.append(sentence)
chunks.append({"start_sentence": start, "end_sentence": len(sentences),
"text": " ".join(current)})
records = [dict(chunk, source_url=source["source_url"], chunk_index=index)
for index, chunk in enumerate(chunks)]
Path("chunks.json").write_text(json.dumps(records, ensure_ascii=False, indent=2))
print(json.dumps({"chunk_count": len(records)}))
El intervalo de oraciones utiliza un inicio inclusivo y un final exclusivo. Esa convención hace posible reconstruir exactamente qué oraciones de entrada produjeron un fragmento. Las entradas vacías y los vectores no válidos fallan explícitamente en lugar de producir un índice vacío aparentemente exitoso.
El límite de tamaño aquí cuenta caracteres. No es un límite de tokens. Si tu sistema de incrustación o generación tiene un presupuesto de tokens, mide los tokens con el tokenizador de ese sistema antes de enviar texto. El código rechaza una oración de gran tamaño para que el segmentador ascendente pueda manejarlo deliberadamente.
Esta implementación es intencionalmente simple: compara vectores de oraciones vecinas. No implementa agrupamiento a través de partes distantes de un documento, umbrales percentuales adaptativos o un clasificador de límites entrenado. Esos son enfoques separados que necesitan su propia evaluación.
Etapa 4: Indexar Pasajes Sin Perder Su Fuente
La indexación debe preservar suficiente metadato para reconectar un fragmento recuperado con su documento fuente. Almacena el texto del fragmento, la URL fuente, el hash del texto, el índice del fragmento, el rango de oraciones, el tiempo de colección y el identificador del modelo de incrustaciones.
Cree embeddings de fragmentos a partir del texto final del fragmento si esa es la representación que utiliza su recuperador. Promediar embeddings de oraciones es una elección de diseño diferente; no asuma que produce el mismo ranking de recuperación que insertar el pasaje ensamblado.
Cuando un documento fuente cambia, mantenga las versiones antigua y nueva distinguibles. Reutilizar el mismo identificador de fragmento mientras se cambia el texto subyacente puede hacer que las citas almacenadas sean ambiguas. Una clave de versión basada en el hash de fuente normalizado ayuda a separar las observaciones.
Una tienda de vectores es solo un índice posible. Una pequeña evaluación puede recuperar pasajes en memoria. Comience con el arreglo más simple que le permita inspeccionar el texto devuelto para cada pregunta.
Etapa 5: Comparar Recuperación, No Solo Apariencia de Fragmentos
El fragmentado semántico debe evaluarse según las preguntas que la aplicación necesita responder. Un conjunto de pasajes visualmente ordenados no prueba que el recuperador devuelva la evidencia correcta.
Construya un pequeño conjunto de preguntas con pasajes de apoyo marcados en los documentos originales. Ejecute una línea base de tamaño fijo, una línea base que tenga en cuenta la estructura y el divisor semántico contra el mismo contenido normalizado. Mantenga constante el modelo de embedding, la configuración de recuperación y la evaluación de respuestas.
| Medición | Pregunta que responde |
|---|---|
| Recuperación de pasajes de apoyo | ¿Se recuperó la evidencia necesaria? |
| Texto recuperado no relacionado | ¿Cuánto contexto se desperdició? |
| Soporte de respuesta | ¿Sigue la respuesta generada la evidencia? |
| Tiempo de procesamiento | ¿Cuál fue el costo operativo de segmentación y embedding? |
| Volumen de entrada | ¿Cuánto texto llegó a cada paso del modelo? |
La investigación sobre los trade-offs computacionales del fragmentado semántico apoya tratar el método como una elección empírica. El trabajo adicional no produce consistentemente una mejora en cada tarea y conjunto de datos.
Inspeccione fallos por etapa. La falta de evidencia en la captura en bruto es un problema de adquisición. Los párrafos rotos son un problema de limpieza. Un pasaje relevante clasificado por debajo de pasajes irrelevantes puede señalar la configuración de embedding o recuperación. Estos problemas requieren cambios diferentes.
Siga el componente de adquisición por separado a través de precios de Scrapeless. Los costos de embedding e indexación pertenecen a la pila de downstream; no deben ser informados como uso de Web Unlocker.
Conclusión: Elija el Divisor que Recupere Mejor la Evidencia
El fragmentado semántico es útil cuando el significado cambia dentro de los documentos de maneras que los límites más simples no logran captar. El flujo de trabajo práctico es preservar un texto fuente limpio, producir embeddings consistentes, hacer cumplir límites de pasajes y comparar la recuperación con alternativas más simples.
Mantenga los metadatos de la fuente adjuntos en todo momento. Un pasaje recuperado se vuelve mucho más útil cuando la aplicación puede mostrar de dónde provino y qué versión del documento representa.
¿Listo para Construir su Pipeline de Datos Web?
Únase a los desarrolladores que trabajan en la recolección de datos web en Discord y Telegram.
Cree una cuenta de Scrapeless y adapte el flujo de trabajo a sus propias fuentes de datos aprobadas.
FAQ
Q: ¿Es el fragmentado semántico siempre mejor que el fragmentado de tamaño fijo?
No. Su beneficio depende de los documentos, el modelo de embedding, la configuración de recuperación y la tarea. Compare estrategias en un conjunto de evaluación compartido antes de elegir una.
Q: ¿Scrapeless genera los embeddings en este flujo de trabajo?
No. Scrapeless proporciona el paso de acceso a la web en la parte superior. Su modelo de embedding e índice seleccionados manejan la representación y la recuperación de downstream.
Q: ¿Cómo deben ser fragmentadas las tablas y bloques de código?
Preserve su estructura o enrútelas a través de un divisor dedicado que tenga en cuenta la estructura. Los límites de oración por sí solos pueden separar valores de encabezados o romper el contexto del código.
Q: ¿Qué pasa si una página adquirida contiene un desafío o HTML diferente?
Rechace el contenido que no cumpla con el contrato de fuente e inspeccione la etapa de adquisición o de analizador. La similitud semántica no puede reparar un documento fuente incorrecto.
Q: ¿La recolección necesita un proxy separado?
Utilice las opciones de enrutamiento de su solicitud de Web Unlocker elegida. No infiera requisitos de proxy del algoritmo de fragmentación, que se ejecuta después de la recolección.
Q: ¿Puede el pipeline ejecutarse sin un agente de IA?
Sí. Una aplicación puede adquirir documentos y ejecutar fragmentación basada en embedding sin un agente autónomo. Aún se requiere un modelo de embedding para la comparación semántica.
Q: ¿Qué límites deben aplicarse a la recolección de fuentes paralelas?
Comience con una colección limitada, como no más de tres trabajadores por host, y respete límites de objetivos y cuentas más estrictos. Los lotes de incrustación tienen límites específicos del modelo diferentes.
P: ¿Se puede agregar cualquier página pública a un índice RAG?
La disponibilidad pública por sí sola no establece permiso para cada colección o reutilización. Revise los términos de la fuente, los derechos aplicables y el manejo de datos previsto antes de la ingestión.
En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.



