RAG Que Não Está Obsoleto: Dados Web Frescos e Ciclos de Atualização
Um sistema RAG é tão atual quanto sua última varredura. A matemática da recuperação é a parte fácil — a parte difícil é um ciclo de atualização que re-varre, re-fraciona e re-incorpora cada fonte em seu próprio ritmo antes que as respostas fiquem obsoletas.
A geração aumentada por recuperação está agora em cerca de metade dos sistemas de IA empresariais — a adoção saltou para 51% nas últimas pesquisas, em comparação com 31% um ano antes. No entanto, a maioria dos projetos RAG compartilha o mesmo modo de falha: foram populados uma vez, e então o mundo seguiu em frente. A matemática da recuperação (incorporar a consulta, buscar os vetores, colocar os principais fragmentos no prompt) é a parte fácil e bem documentada. A parte difícil, a parte que decide se seu assistente é confiável ou confiantemente errado, é a atualidade — uma pipeline que continua re-varrendo, re-fracionando e re-incorporando cada fonte antes que suas respostas fiquem obsoletas. Este guia é sobre construir esse ciclo de atualização, com ingestão markdown-first e TTLs por fonte em seu núcleo.
Recuperação obsoleta é pior do que nenhuma recuperação
Toda a promessa do RAG é que o modelo responde a partir de evidências recuperadas em vez de dados de treinamento congelados. Quebre a atualidade e você quebra a promessa: um bot de suporte cita a política de devolução do último trimestre, um assistente de preços cita um valor descontinuado, um copiloto de pesquisa perde a atualização que mudou a resposta. Pior, o modelo afirma isso com total confiança porque o fragmento recuperado parece autoritativo. Um índice obsoleto não falha de forma ruidosa — falha de forma silenciosa e plausível, que é o tipo mais perigoso. Manter o corpus atual não é um luxo; é a diferença entre fundamentar e alucinar com passos extras.
Ingerir markdown, não HTML bruto
A qualidade de tudo a jusante é definida na ingestão. HTML bruto é um desastre para recuperação — navegação, banners de cookies, rodapés e tags de script tornam-se fragmentos de ruído que poluem a busca por similaridade e desperdiçam tokens de contexto. A abordagem limpa é markdown-first: varrer cada página e extrair apenas o conteúdo principal como markdown estruturado, descartando o boilerplate antes que qualquer coisa seja fracionada. Nossa Scraper API retorna markdown diretamente, renderiza JavaScript sob demanda e rotaciona IPs para que páginas bloqueadas não deixem lacunas em seu corpus — substitui a camada de ingestão frágil de Puppeteer e BeautifulSoup que a maioria das pilhas RAG se arrasta. O endpoint web-data-for-LLMs envolve varredura, limpeza e estrutura em uma única chamada projetada exatamente para isso.
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
}
Alimente sua pilha RAG com dados web limpos
Fracionar pequeno, carregar metadados
Uma vez que você tenha markdown limpo, divida-o em fragmentos de aproximadamente 300 a 500 tokens — pequenos o suficiente para que um fragmento recuperado esteja estritamente no tópico, grandes o suficiente para manter um pensamento coerente. Use um divisor recursivo (LangChain ou LlamaIndex ambos fornecem um) que respeite os limites de sentença e título em vez de cortar no meio da palavra. O passo crítico, frequentemente ignorado, são os metadados: cada fragmento deve carregar seu URL de origem, um carimbo de data/hora e um hash de conteúdo. Esses metadados são o que torna a atualidade possível — a recuperação pode filtrar por atualidade, e seu ciclo de atualização pode dizer quais fragmentos pertencem a uma fonte que acabou de mudar.
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]
Incorpore esses fragmentos com um modelo atual — text-embedding-3-large, um modelo Cohere ou uma variante aberta do Sentence-BERT — e armazene os vetores junto com os metadados em um banco de dados vetorial como Pinecone, Weaviate, Milvus ou FAISS. Ajuste os limiares de similaridade e, principalmente, habilite a filtragem de metadados para que uma consulta possa exigir, por exemplo, apenas fragmentos buscados nos últimos 30 dias para uma questão de preços.

TTLs por fonte: o coração da atualidade
O erro que a maioria das equipes comete é atualizar tudo em um único cronograma — uma re-varredura completa noturna que é simultaneamente muito lenta para preços e desperdiçadora para documentos de referência. Diferentes fontes envelhecem em diferentes ritmos, então dê a cada uma um tempo de vida que corresponda à velocidade com que seu conteúdo realmente se move. Preços e estoque ao vivo podem precisar de um TTL de minutos; notícias, listagens e tópicos de fórum uma hora; classificações e catálogos um dia; documentação, políticas e material de referência uma semana ou mais. Marque cada fragmento com o TTL de sua fonte, e um agendador re-varre apenas as fontes cujo relógio expirou. O hash de conteúdo é sua válvula de eficiência: se a página re-varrida for byte-idêntica, pule a etapa de incorporação completamente e apenas redefina o carimbo de data/hora.
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 é o ciclo que separa uma demonstração de um sistema de produção. Mantém a recuperação previsível, gasta computação apenas onde o mundo realmente mudou, e permite que você faça uma garantia real de atualidade por fonte. Para uma visão mais ampla de fundamentar LLMs em dados ao vivo, veja nosso guia para alimentar LLMs com dados web frescos, e para transformar um único site em uma base de conhecimento citável, construindo uma base de conhecimento para um bot de suporte.

Recupere para cobertura, não apenas similaridade
Uma última melhoria no momento da consulta. A pura similaridade vetorial perde termos exatos — códigos de produto, strings de erro, nomes próprios — que uma busca por palavras-chave acerta. A recuperação híbrida mistura os dois, depois aplica seu filtro de atualidade para que uma consulta sensível ao tempo prefira fragmentos frescos. Registre os fragmentos recuperados com cada resposta para que você possa auditar quais evidências o modelo realmente usou; essa rastreabilidade é o que torna o RAG explicável, e é como você detecta um fragmento obsoleto antes que um usuário o faça. Técnicas de extração impulsionada por LLM combinam bem aqui quando você precisa de campos estruturados das páginas recuperadas em vez de prosa.
Perguntas frequentes
Como mantenho os dados de uma pipeline RAG atualizados?
Atribua a cada fonte um tempo de vida que corresponda à velocidade com que seu conteúdo muda, marque cada fragmento com um URL de origem e carimbo de data/hora, e execute um agendador que re-varre apenas as fontes expiradas. Use um hash de conteúdo para pular a re-incorporação de páginas que não mudaram realmente, e habilite a filtragem de atualidade na recuperação para que consultas sensíveis ao tempo prefiram fragmentos frescos.
Por que ingerir markdown em vez de HTML para RAG?
HTML bruto carrega navegação, banners, rodapés e scripts que se tornam fragmentos de ruído, poluindo a busca por similaridade e desperdiçando tokens de contexto. A ingestão markdown-first extrai apenas o conteúdo principal, então os fragmentos são limpos e no tópico. Uma API de scraping que retorna markdown renderizado remove a análise personalizada frágil da qual a maioria das pilhas RAG depende.
Qual tamanho de fragmento devo usar para RAG?
Aproximadamente 300–500 tokens é o ponto ideal comum: pequeno o suficiente para que um fragmento recuperado permaneça estritamente relevante, grande o suficiente para preservar um pensamento completo. Use um divisor recursivo que respeite os limites de sentença e título, adicione uma pequena sobreposição para que o contexto não se perca nas junções, e anexe metadados de origem a cada fragmento.
Preciso de proxies para construir uma pipeline de dados RAG?
Se você varrer a web aberta em qualquer escala, sim — sites limitam a taxa e bloqueiam solicitações repetidas de um único IP, deixando lacunas em seu corpus. Uma API de scraping ou proxies rotativos mantêm a varredura confiável para que as fontes sejam atualizadas completamente e no cronograma, que é exatamente do que os TTLs por fonte dependem.
O RAG vive ou morre pela atualidade. Ingerir markdown limpo, fracionar pequeno com metadados, e conduzir a re-incorporação a partir de TTLs por fonte para que cada fonte seja atualizada em seu próprio ritmo. Construa esse ciclo uma vez e seu assistente responderá da web de hoje, não do instantâneo do mês passado.