RAG, das nicht veraltet: Frische Webdaten und Aktualisierungsschleifen
Ein RAG-System ist nur so aktuell wie sein letzter Crawl. Die Abrufmathematik ist der einfache Teil – der schwierige Teil ist eine Aktualisierungsschleife, die jede Quelle in ihrem eigenen Rhythmus erneut crawlt, erneut in Stücke teilt und erneut einbettet, bevor die Antworten veralten.
Retrieval-augmented generation ist mittlerweile in etwa der Hälfte der Unternehmens-AI-Systeme integriert – die Akzeptanz stieg in den neuesten Umfragen auf 51 %, gegenüber 31 % im Vorjahr. Doch die meisten RAG-Projekte teilen denselben Fehlermodus: Sie wurden einmal befüllt, und dann hat sich die Welt weitergedreht. Die Abrufmathematik (die Abfrage einbetten, die Vektoren durchsuchen, die obersten Stücke in den Prompt einfügen) ist der einfache, gut dokumentierte Teil. Der schwierige Teil, der Teil, der entscheidet, ob Ihr Assistent vertrauenswürdig oder selbstbewusst falsch ist, ist die Frische – eine Pipeline, die jede Quelle erneut crawlt, erneut in Stücke teilt und erneut einbettet, bevor ihre Antworten veralten. Dieser Leitfaden handelt vom Aufbau dieser Aktualisierungsschleife, mit Markdown-First-Ingestion und TTLs pro Quelle im Kern.
Veralteter Abruf ist schlimmer als kein Abruf
Das ganze Versprechen von RAG ist, dass das Modell aus abgerufenen Beweisen antwortet, anstatt aus eingefrorenen Trainingsdaten. Brechen Sie die Frische, und Sie brechen das Versprechen: Ein Support-Bot zitiert die Rückgabebedingungen des letzten Quartals, ein Preisassistent nennt eine eingestellte Zahl, ein Forschungskopilot verpasst das Update, das die Antwort geändert hat. Schlimmer noch, das Modell gibt es mit voller Überzeugung an, weil das abgerufene Stück autorität aussieht. Ein veralteter Index scheitert nicht laut – er scheitert leise und plausibel, was die gefährlichste Art ist. Das Korpus aktuell zu halten, ist kein „Nice-to-have“; es ist der Unterschied zwischen Erdung und Halluzination mit zusätzlichen Schritten.
Markdown einlesen, nicht rohes HTML
Die Qualität von allem, was nachgelagert ist, wird bei der Ingestion festgelegt. Rohes HTML ist eine Katastrophe für den Abruf – Navigation, Cookie-Banner, Fußzeilen und Skripttags werden zu Rauschstücken, die die Ähnlichkeitssuche verschmutzen und Kontext-Token verschwenden. Der saubere Ansatz ist Markdown-First: Jede Seite crawlen und nur den primären Inhalt als strukturiertes Markdown extrahieren, Boilerplate verwerfen, bevor etwas in Stücke geteilt wird. Unsere Scraper API liefert direkt Markdown, rendert JavaScript auf Abruf und rotiert IPs, sodass blockierte Seiten keine Lücken in Ihrem Korpus hinterlassen – sie ersetzt die brüchige Puppeteer-und-BeautifulSoup-Ingestion-Schicht, auf der die meisten RAG-Stacks mühsam laufen. Der web-data-for-LLMs Endpunkt fasst Crawl, Reinigung und Strukturierung in einem Aufruf zusammen, der genau dafür entwickelt wurde.
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
}
Versorgen Sie Ihren RAG-Stack mit sauberen Webdaten
Kleine Stücke teilen, Metadaten tragen
Sobald Sie sauberes Markdown haben, teilen Sie es in Stücke von etwa 300 bis 500 Token – klein genug, dass ein abgerufenes Stück thematisch eng bleibt, groß genug, um einen zusammenhängenden Gedanken zu bewahren. Verwenden Sie einen rekursiven Teiler (LangChain oder LlamaIndex bieten beide einen), der Satz- und Überschriftengrenzen respektiert, anstatt mitten im Wort zu schneiden. Der kritische, oft übersprungene Schritt sind Metadaten: Jedes Stück muss seine Quell-URL, einen Zeitstempel und einen Inhalt-Hash tragen. Diese Metadaten ermöglichen Frische – der Abruf kann nach Aktualität filtern, und Ihre Aktualisierungsschleife kann erkennen, welche Stücke zu einer Quelle gehören, die sich gerade geändert hat.
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]
Betten Sie diese Stücke mit einem aktuellen Modell ein – text-embedding-3-large, ein Cohere-Modell oder eine offene Sentence-BERT-Variante – und speichern Sie die Vektoren zusammen mit den Metadaten in einer Vektordatenbank wie Pinecone, Weaviate, Milvus oder FAISS. Passen Sie die Ähnlichkeitsschwellen an und aktivieren Sie vor allem die Metadatenfilterung, damit eine Abfrage beispielsweise nur Stücke verlangt, die in den letzten 30 Tagen für eine Preisfrage abgerufen wurden.

TTLs pro Quelle: das Herz der Frische
Der Fehler, den die meisten Teams machen, ist, alles nach einem Zeitplan zu aktualisieren – ein nächtlicher vollständiger erneuter Crawl, der gleichzeitig zu langsam für Preise und verschwenderisch für Referenzdokumente ist. Verschiedene Quellen altern mit unterschiedlichen Geschwindigkeiten, also geben Sie jeder eine Lebensdauer, die dazu passt, wie schnell sich ihr Inhalt tatsächlich bewegt. Live-Preise und Bestände könnten eine TTL von Minuten benötigen; Nachrichten, Einträge und Forenthreads eine Stunde; Rankings und Kataloge einen Tag; Dokumentationen, Richtlinien und Referenzmaterial eine Woche oder mehr. Markieren Sie jedes Stück mit der TTL seiner Quelle, und ein Scheduler crawlt nur die Quellen erneut, deren Uhr abgelaufen ist. Der Inhalt-Hash ist Ihr Effizienzventil: Wenn die erneut gecrawlte Seite byte-identisch ist, überspringen Sie den Einbettungsschritt vollständig und setzen Sie einfach den Zeitstempel zurück.
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
Dies ist die Schleife, die eine Demo von einem Produktionssystem trennt. Sie hält den Abruf vorhersehbar, verbraucht Rechenleistung nur dort, wo sich die Welt tatsächlich verändert hat, und ermöglicht es Ihnen, eine echte Frischegarantie pro Quelle zu geben. Für das breitere Bild der Erdung von LLMs auf Live-Daten siehe unseren Leitfaden zu feeding LLMs fresh web data, und um eine einzelne Website in eine zitierbare Wissensbasis zu verwandeln, building a support-bot knowledge base.

Abrufen für Abdeckung, nicht nur Ähnlichkeit
Ein letztes Upgrade zur Abfragezeit. Reine Vektorähnlichkeit verpasst genaue Begriffe – Produktcodes, Fehlermeldungen, Eigennamen –, die eine Stichwortsuche trifft. Hybrider Abruf mischt beides, wendet dann Ihren Aktualitätsfilter an, sodass eine zeitkritische Abfrage frische Stücke bevorzugt. Protokollieren Sie die abgerufenen Stücke mit jeder Antwort, damit Sie prüfen können, welche Beweise das Modell tatsächlich verwendet hat; diese Rückverfolgbarkeit macht RAG erklärbar, und so fangen Sie ein veraltetes Stück, bevor es ein Benutzer tut. Techniken aus LLM-powered extraction passen hier gut, wenn Sie strukturierte Felder aus den abgerufenen Seiten benötigen, anstatt Prosa.
Häufig gestellte Fragen
Wie halte ich die Daten einer RAG-Pipeline frisch?
Weisen Sie jeder Quelle eine Lebensdauer zu, die dazu passt, wie schnell sich ihr Inhalt ändert, markieren Sie jedes Stück mit einer Quell-URL und einem Zeitstempel und führen Sie einen Scheduler aus, der nur abgelaufene Quellen erneut crawlt. Verwenden Sie einen Inhalt-Hash, um das erneute Einbetten von Seiten zu überspringen, die sich nicht tatsächlich geändert haben, und aktivieren Sie die Aktualitätsfilterung beim Abruf, damit zeitkritische Abfragen frische Stücke bevorzugen.
Warum Markdown statt HTML für RAG einlesen?
Rohes HTML enthält Navigation, Banner, Fußzeilen und Skripte, die zu Rauschstücken werden, die die Ähnlichkeitssuche verschmutzen und Kontext-Token verschwenden. Markdown-First-Ingestion extrahiert nur den primären Inhalt, sodass die Stücke sauber und thematisch sind. Eine Scraping-API, die gerendertes Markdown liefert, entfernt das brüchige benutzerdefinierte Parsen, auf das sich die meisten RAG-Stacks verlassen.
Welche Chunk-Größe sollte ich für RAG verwenden?
Etwa 300–500 Token sind der übliche Sweet Spot: klein genug, dass ein abgerufenes Stück thematisch eng bleibt, groß genug, um einen vollständigen Gedanken zu bewahren. Verwenden Sie einen rekursiven Teiler, der Satz- und Überschriftengrenzen respektiert, fügen Sie eine kleine Überlappung hinzu, damit der Kontext an den Nähten nicht verloren geht, und fügen Sie jedem Stück Quellmetadaten hinzu.
Brauche ich Proxies, um eine RAG-Datenpipeline aufzubauen?
Wenn Sie das offene Web in großem Maßstab crawlen, ja – Websites begrenzen die Rate und blockieren wiederholte Anfragen von einer IP, was Lücken in Ihrem Korpus hinterlässt. Eine Scraping-API oder rotierende Proxies halten den Crawl zuverlässig, sodass Quellen vollständig und nach Plan aktualisiert werden, was genau das ist, worauf sich TTLs pro Quelle verlassen.
RAG lebt oder stirbt mit der Frische. Lesen Sie sauberes Markdown ein, teilen Sie kleine Stücke mit Metadaten und treiben Sie die erneute Einbettung von TTLs pro Quelle an, sodass jede Quelle in ihrem eigenen Rhythmus aktualisiert wird. Bauen Sie diese Schleife einmal auf, und Ihr Assistent antwortet aus dem heutigen Web, nicht aus dem Schnappschuss des letzten Monats.