Startseite / Artikel / RAG ohne Geheimniskrämerei: Zuerst Abruf, dann Erstellung.

RAG ohne Geheimniskrämerei: Zuerst Abruf, dann Erstellung.

Ein einfacher Weg von der Aufteilung in Blöcke und Indizes bis zu fundierten Antworten, die mit Zitieroperatoren überprüft werden können.

2179 Wörter

Nutzen Sie dies als für Operator zugängliche Neuformulierung der Ideen aus „RAG, Explained the Way I Wish Someone Had Explained It to Me“: klare Phasen, geordnete Codeabschnitte sowie Wiederherstellungshinweise, die auch bei Übergaben erhalten bleiben. Die Übersicht funktioniert am besten, wenn sie als messbarer Überblick betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein optimales Transkript, einen Fehlerfall sowie die Notizen zur Rücksetzung. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Wiederherstellungsprozess gemeinsam. Versuche, menschliche Kontrollpunkte sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen.

1. Die Analogie, die RAG verständlich macht

Für 1. Die Analogie, die RAG verständlich macht: Definieren Sie vor dem Ändern des Codes die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

2. Die beiden Bestandteile jedes RAG-Systems

Für 2. Die beiden Teile jedes RAG-Systems sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Zitieren Sie die Passagen, die tatsächlich die Antwort begründen. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

3. Phase 1 – Indizierung: Dokumente in suchbare Inhalte umwandeln

Für 3. Phase 1 – Indexierung: Dokumente in suchbare Inhalte umwandeln sollten Sie die Eingabedaten, den Verantwortlichen für diesen Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definieren. Die Operator:innen sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erhalten Sie Zeiten sowie Kosten für Token oder Abfragen zusammen mit den funktionalen Ergebnissen auf. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo-Umgebung in gemeinsam genutzte Umgebungen übergeht. Zitieren Sie die Passagen, die tatsächlich die Antwort begründen. Ohne Zitate können die Operator:innen nicht zwischen Halluzinationen und Lücken in der Indexierung unterscheiden.

Schritt 1: Laden Sie Ihre Dokumente hoch

Zu Schritt 1: Ihre Dokumente laden sollten Sie die Eingabedaten, den Verantwortlichen für diesen Schritt sowie die Abbruchkriterien definieren, bevor Sie den Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den die Operator überprüfen können, ohne den gesamten Ablauf durchzulesen. Zitieren Sie die Passagen, die tatsächlich die Antwort begründen. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader("company_policy.pdf")
documents = loader.load()

print(f"Loaded {len(documents)} pages")

Schritt 2: In Abschnitte aufteilen – und dieser Schritt ist wichtiger, als viele denken

Zur Schritt 2: Aufteilen in Blöcke – und dieser Schritt ist wichtiger, als viele denken: Definieren Sie vor dem Ändern des Codes die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholungsversuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,      # characters per chunk
    chunk_overlap=80,    # overlap between consecutive chunks
    separators=["\n\n", "\n", ". ", " "]
)

chunks = splitter.split_documents(documents)
print(f"Split into {len(chunks)} chunks")

Schritt 3: Die Blöcke einbetten

Zur Schritt 3: Einbetten der Chunks sollten Sie die Eingaben, den Verantwortlichen für diesen Schritt sowie die Abbruchkriterien definieren, bevor Sie den Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Bevorzugen Sie kleine, testbare Einheiten vor umfangreichen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

from langchain_openai import OpenAIEmbeddings

embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")

# under the hood, this is what happens per chunk:
vector = embedding_model.embed_query("30-day refund window for annual plans")
print(len(vector))   # e.g. 1536 numbers representing this sentence's meaning
        "refund policy" •
                          \
                           • "money-back guarantee"
   "vacation days" •
                     \
                      • "paid time off"

Schritt 4: Speichern der Vektoren in einer Vektordatenbank

Zur Schritt 4: Speichern der Vektoren in einer Vektordatenbank sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Erzeugnisse, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Zitieren Sie die Passagen, die tatsächlich die Antwort begründen. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken bei der Indizierung unterscheiden.

from langchain_community.vectorstores import FAISS

vectorstore = FAISS.from_documents(chunks, embedding_model)
vectorstore.save_local("faiss_index")

4. Phase 2 – Abruf + Erstellung: Beantwortung einer echten Frage

Für 4. Phase 2 – Abruf + Erstellung: Beantwortung einer echten Frage sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Bediener sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erhalten Sie die Laufzeiten sowie die Kosten für Token oder Abfragen zusammen mit den funktionalen Ergebnissen auf. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Ablauf von einer Demo-Umgebung in eine gemeinsam genutzte Umgebung wechselt. Zitieren Sie die Passagen, die tatsächlich der Grundlage für die Antwort waren. Ohne Zitate können die Bediener nicht zwischen Halluzinationen und Lücken im Indexing unterscheiden. Für 4. Phase 2 – Abruf + Erstellung: Beantwortung einer echten Frage sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Bediener sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallweg gemeinsam. Retr

Ja, die Benutzeroberfläche, die menschlichen Eingabemöglichkeiten sowie die Handhabung von Fehlern gehören zum Produkt und nicht zu späteren Optimierungen.

Schritt 1: Die Abfrage einbetten – mit dem gleichen Modell

Beim Bearbeiten von Schritt 1: Die Abfrage einbetten – mit dem gleichen Modell sollten Sie zunächst den Ablaufplan aufschreiben: erforderliche Eingaben, Erfolgsindikatoren sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Ziehen Sie kleine, testbare Einheiten vor großen, komplexen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen und nicht auf ein verworrenes Ablaufschema. Speichern Sie stabile Systemanweisungen sowie Tool-Schemata im Cache. Das erneute Senden identischer Vorlagen ist eine häufige Ursache für Ressourcenverschwendung.

query = "Can I get a refund on my annual subscription?"

Schritt 2: Die relevantesten Teile abrufen

Beim Bearbeiten von Schritt 2: Die relevantesten Abschnitte abrufen sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Ergebnisse, definieren Sie Erfolgskontrollen und lehnen Sie stille, teilweise abgeschlossene Ergebnisse ab. Messen Sie die Erinnerungsfähigkeit anhand eines festgelegten Fragebogens, bevor Sie die Anfragen anpassen. Eine häufige Änderung der Anfragen behebt selten ein schwaches Abrufverhalten.

retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
relevant_chunks = retriever.invoke(query)

for chunk in relevant_chunks:
    print(chunk.page_content[:100], "...")

Schritt 3: Die Abschnitte in eine Anfrage einfügen

Beim Bearbeiten von Schritt 3: Die Teile in einen Prompt einfügen sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgszeichen sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Notieren Sie die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Weg von einer Demo in gemeinsam genutzte Umgebungen wechselt. Speichern Sie stabile Systemanweisungen sowie Tool-Schemata im Cache. Das erneute Senden identischer Vorlagen ist eine häufige Ursache für unnötige Ressourcenverbrauch. Beim Bearbeiten von Schritt 3: Die Teile in einen Prompt einfügen sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgszeichen sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen.

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("""
Answer the question using ONLY the context below.
If the answer isn't in the context, say "I don't have that information."

Context:
{context}

Question: {question}
""")

Schritt 4: Alles miteinander verknüpfen

Schritt 4: Alles miteinander verknüpfen funktioniert am besten, wenn er als messbare Struktur betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Ziehen Sie kleine, testbare Einheiten vor umfangreichen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren. Trennen Sie die Aufteilungspolitik von der Abrufpolitik. Eine Änderung in einer sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.

from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4o-mini")

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

answer = rag_chain.invoke("Can I get a refund on my annual subscription?")
print(answer)

5. Warum das besser ist als das Einfügen des gesamten Dokuments in die Anweisung

5. Warum dies besser ist als das Einfügen des gesamten Dokuments direkt in die Anfrage funktioniert am besten, wenn es als messbarer Rahmen betrachtet wird. Erfassen Sie eine optimale Transkription, einen Fehlerfall sowie die Notizen zum Rücksetzen, bevor Sie den Umfang erweitern. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Erzeugnisse, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Ergebnisse ab. Legen Sie einen Token-Haushalt pro Turnus und pro Sitzung fest. Agierende Tools erweitern den Kontext oft übermäßig; feste Obergrenzen verhindern, dass Demonstrationen zu unerwarteten Rechnungen werden.

6. Häufige Fehlerquellen (aus eigener Erfahrung gelernt)

6. Häufige Fehlerquellen (am eigenen Leib erfahren) funktioniert am besten, wenn sie als messbarer Bereich betrachtet werden. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Notieren Sie die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn sich der Prozess von einer Demo in gemeinsame Umgebungen verschiebt. Trennen Sie die Aufteilung in Blöcke von der Abrufstrategie. Ein Änderungsbedarf bei einer Seite sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern. 6. Häufige Fehlerquellen (am eigenen Leib erfahren) funktioniert am besten, wenn sie als messbarer Bereich betrachtet werden. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen.

7. Was kommt als Nächstes?

Für 7. Wo geht es von hier aus weiter sollten die Eingabedaten, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Zur Vorzugsbehandlung kommen kleine, testbare Einheiten vor umfangreichen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen und nicht auf ein verworrenes Ablaufverfahren. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.

Operative Checkliste

Beim Bearbeiten der operativen Checkliste sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingabedaten, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben.

Halten Sie die Konfiguration außerhalb des Anwendungscode. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort zusammengefasst sein, den die Betreiber überprüfen können, ohne den gesamten Code durchzulesen.

Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragen anpassen. Ein häufiger Wechsel der Anfragemuster behebt selten ein schwaches Suchsystem.

Pinnen Sie die Versionsnummern der Abhängigkeiten und dokumentieren Sie den Bilddigest, mit dem die Demo ausgeführt wurde. Reproduzierbarkeit ist besser als „stammesbezogenes Wissen“.

Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallweg gemeinsam. Wiederholte Versuche, menschliche Überprüfungen sowie die Handhabung fehlerhafter Nachrichten gehören zum Produkt selbst und nicht zu späteren Optimierungen.

Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragen anpassen. Ein häufiger Wechsel der Anfragemuster behebt selten ein schwaches Suchsystem.

Vor der Einführung des Stacks sollten Versionen eingefroren werden, ein „goldener“ Transkript für den kritischen Pfad erstellt und die Rollback-Schritte bestätigt werden. Gemeinsam genutzte Umgebungen benötigen Rate Limits, Überprüfungen der Nutzerzuordnung sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen. Man sollte langweilige Zuverlässigkeit vor cleveren, einmaligen Demonstrationen bevorzugen.

Batch-Hinweis für 372916c7a432: Halten Sie die Anbieter-Schlüssel außerhalb des Repositories, legen Sie eine Obergrenze für Tokens pro Sitzung fest und speichern Sie die Transkripte neben den Evaluierungs-Dateien, damit spätere Modellwechsel vergleichbar bleiben.