RAG que no está obsoleto: Datos web frescos y bucles de actualización

Un sistema RAG es tan fresco como su último rastreo. Las matemáticas de recuperación son la parte fácil; la parte difícil es un bucle de actualización que vuelve a rastrear, dividir y reinsertar cada fuente en su propio reloj antes de que las respuestas se vuelvan obsoletas.

La generación aumentada por recuperación está ahora en aproximadamente la mitad de los sistemas de IA empresariales; la adopción saltó al 51% en las últimas encuestas, desde el 31% del año anterior. Sin embargo, la mayoría de los proyectos RAG comparten el mismo modo de fallo: se poblaron una vez, y luego el mundo siguió adelante. Las matemáticas de recuperación (insertar la consulta, buscar los vectores, meter los mejores fragmentos en el prompt) son la parte fácil y bien documentada. La parte difícil, la parte que decide si tu asistente es confiable o está equivocadamente seguro, es la frescura: una canalización que sigue rastreando, dividiendo y reinsertando cada fuente antes de que sus respuestas se vuelvan obsoletas. Esta guía trata sobre construir ese bucle de actualización, con ingestión primero en markdown y TTLs por fuente en su núcleo.

La recuperación obsoleta es peor que ninguna recuperación

La promesa completa de RAG es que el modelo responde a partir de evidencia recuperada en lugar de datos de entrenamiento congelados. Rompe la frescura y rompes la promesa: un bot de soporte cita la política de devoluciones del trimestre pasado, un asistente de precios cita una cifra descontinuada, un copiloto de investigación pierde la actualización que cambió la respuesta. Peor aún, el modelo lo afirma con total confianza porque el fragmento recuperado parece autoritativo. Un índice obsoleto no falla ruidosamente; falla de manera silenciosa y plausible, que es el tipo más peligroso. Mantener el corpus actualizado no es un lujo; es la diferencia entre fundamentar y alucinar con pasos adicionales.

Ingiere markdown, no HTML bruto

La calidad de todo lo que sigue se establece en la ingestión. El HTML bruto es un desastre para la recuperación: la navegación, los banners de cookies, los pies de página y las etiquetas de script se convierten en fragmentos de ruido que contaminan la búsqueda de similitud y desperdician tokens de contexto. El enfoque limpio es primero en markdown: rastrea cada página y extrae solo el contenido principal como markdown estructurado, descartando el relleno antes de que se divida en fragmentos. Nuestra Scraper API devuelve markdown directamente, renderiza JavaScript bajo demanda y rota IPs para que las páginas bloqueadas no dejen huecos en tu corpus; reemplaza la frágil capa de ingestión de Puppeteer y BeautifulSoup en la que la mayoría de las pilas RAG cojean. El endpoint web-data-for-LLMs envuelve rastreo, limpieza y estructura en una sola llamada diseñada exactamente para esto.

import requests

# markdown-first ingestion: clean text, JS rendered, IPs rotated
def fetch_markdown(url):
    r = requests.post(
        "https://api.quantumproxies.io/scrape",
        headers={"Authorization": f"Bearer {QP_KEY}"},
        json={"url": url, "format": "markdown", "render": True},
        timeout=60,
    )
    doc = r.json()
    return {
        "url": url,
        "markdown": doc["markdown"],       # no nav, no boilerplate
        "fetched_at": doc["fetchedAt"],     # timestamp for TTL logic
        "content_hash": doc["contentHash"], # skip re-embed if unchanged
    }

Alimenta tu pila RAG con datos web limpios

Divide en fragmentos pequeños, lleva metadatos

Una vez que tienes markdown limpio, divídelo en fragmentos de aproximadamente 300 a 500 tokens: lo suficientemente pequeños para que un fragmento recuperado esté estrechamente enfocado, lo suficientemente grandes para mantener un pensamiento coherente. Usa un divisor recursivo (LangChain o LlamaIndex ambos tienen uno) que respete los límites de oraciones y encabezados en lugar de cortar a mitad de palabra. El paso crítico, a menudo omitido, son los metadatos: cada fragmento debe llevar su URL de origen, una marca de tiempo y un hash de contenido. Esos metadatos son lo que hace posible la frescura: la recuperación puede filtrar por recencia, y tu bucle de actualización puede saber qué fragmentos pertenecen a una fuente que acaba de cambiar.

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1800, chunk_overlap=200,  # ~400 tokens per chunk
)

def to_chunks(doc):
    parts = splitter.split_text(doc["markdown"])
    return [{
        "text": p,
        "source": doc["url"],
        "fetched_at": doc["fetched_at"],   # drives recency filtering
        "ttl": ttl_for(doc["url"]),          # per-source refresh clock
    } for p in parts]

Inserta esos fragmentos con un modelo actual — text-embedding-3-large, un modelo de Cohere, o una variante abierta de Sentence-BERT — y almacena los vectores junto con los metadatos en una base de datos vectorial como Pinecone, Weaviate, Milvus o FAISS. Ajusta los umbrales de similitud y, lo que es importante, habilita el filtrado de metadatos para que una consulta pueda exigir, por ejemplo, solo fragmentos obtenidos en los últimos 30 días para una pregunta de precios.

Diagrama de un bucle de actualización de frescura RAG desde el rastreo en markdown hasta la división e inserción en la indexación y el re-rastreo impulsado por TTL
El bucle que mantiene honesto a RAG: rastreo primero en markdown, fragmentos pequeños ricos en metadatos y un TTL que desencadena la reinserción antes de que se desvíe.

TTLs por fuente: el corazón de la frescura

El error que cometen la mayoría de los equipos es actualizar todo en un solo horario: un re-rastreo completo nocturno que es simultáneamente demasiado lento para los precios y derrochador para los documentos de referencia. Diferentes fuentes envejecen a diferentes ritmos, así que dale a cada una un tiempo de vida que coincida con la rapidez con la que su contenido realmente cambia. Los precios y el stock en vivo podrían necesitar un TTL de minutos; las noticias, listados y hilos de foros una hora; los rankings y catálogos un día; la documentación, políticas y material de referencia una semana o más. Etiqueta cada fragmento con el TTL de su fuente, y un programador vuelve a rastrear solo las fuentes cuyo reloj ha expirado. El hash de contenido es tu válvula de eficiencia: si la página re-rastreada es idéntica en bytes, omite el paso de inserción por completo y solo restablece la marca de tiempo.

import time

TTL = {"prices": 300, "news": 3600, "catalog": 86400, "docs": 604800}

def needs_refresh(chunk, now=None):
    now = now or time.time()
    return (now - chunk["fetched_at"]) > chunk["ttl"]

# refresh only what has expired; re-embed only what actually changed
for src in due_sources(TTL):
    doc = fetch_markdown(src.url)
    if doc["content_hash"] != src.last_hash:
        reindex(to_chunks(doc))     # re-chunk + re-embed
    src.touch(doc["content_hash"])  # reset the clock either way

Este es el bucle que separa una demostración de un sistema de producción. Mantiene la recuperación predecible, gasta computación solo donde el mundo realmente cambió, y te permite hacer una garantía de frescura real por fuente. Para una visión más amplia de fundamentar LLMs en datos en vivo, consulta nuestra guía sobre alimentar LLMs con datos web frescos, y para convertir un solo sitio en una base de conocimiento citable, construir una base de conocimiento para un bot de soporte.

Bandas de TTL escalonadas que muestran minutos para precios y stock, por hora para noticias, diariamente para catálogos y semanalmente para documentos de referencia
Actualiza cada fuente en el reloj que su contenido realmente se mueve: minutos para precios, una semana para documentos de referencia.

Recupera para cobertura, no solo similitud

Una última mejora en el momento de la consulta. La similitud vectorial pura omite términos exactos: códigos de producto, cadenas de error, nombres propios, que una búsqueda por palabras clave clava. La recuperación híbrida mezcla los dos, luego aplica tu filtro de recencia para que una consulta sensible al tiempo prefiera fragmentos frescos. Registra los fragmentos recuperados con cada respuesta para que puedas auditar qué evidencia usó realmente el modelo; esa trazabilidad es lo que hace que RAG sea explicable, y es cómo detectas un fragmento obsoleto antes que un usuario. Las técnicas de extracción potenciada por LLM combinan bien aquí cuando necesitas campos estructurados de las páginas recuperadas en lugar de prosa.

Preguntas frecuentes

¿Cómo mantengo frescos los datos de una canalización RAG?

Asigna a cada fuente un tiempo de vida que coincida con la rapidez con la que cambia su contenido, etiqueta cada fragmento con una URL de origen y una marca de tiempo, y ejecuta un programador que vuelva a rastrear solo las fuentes expiradas. Usa un hash de contenido para omitir la reinserción de páginas que realmente no cambiaron, y habilita el filtrado por recencia en la recuperación para que las consultas sensibles al tiempo prefieran fragmentos frescos.

¿Por qué ingerir markdown en lugar de HTML para RAG?

El HTML bruto lleva navegación, banners, pies de página y scripts que se convierten en fragmentos de ruido, contaminando la búsqueda de similitud y desperdiciando tokens de contexto. La ingestión primero en markdown extrae solo el contenido principal, por lo que los fragmentos son limpios y relevantes. Una API de scraping que devuelve markdown renderizado elimina el análisis personalizado frágil del que dependen la mayoría de las pilas RAG.

¿Qué tamaño de fragmento debo usar para RAG?

Aproximadamente 300–500 tokens es el punto óptimo común: lo suficientemente pequeño para que un fragmento recuperado se mantenga estrechamente relevante, lo suficientemente grande para preservar un pensamiento completo. Usa un divisor recursivo que respete los límites de oraciones y encabezados, agrega un pequeño solapamiento para que el contexto no se pierda en las uniones, y adjunta metadatos de origen a cada fragmento.

¿Necesito proxies para construir una canalización de datos RAG?

Si rastreas la web abierta a cualquier escala, sí — los sitios limitan la tasa y bloquean las solicitudes repetidas desde una IP, dejando huecos en tu corpus. Una API de scraping o proxies rotativos mantienen el rastreo confiable para que las fuentes se actualicen completamente y a tiempo, que es exactamente de lo que dependen los TTLs por fuente.

RAG vive o muere por la frescura. Ingiere markdown limpio, divide en fragmentos pequeños con metadatos, y dirige la reinserción desde los TTLs por fuente para que cada fuente se actualice en su propio reloj. Construye ese bucle una vez y tu asistente responde desde la web de hoy, no desde la instantánea del mes pasado.

Construye una canalización RAG fresca en la Scraper API