Praktische Hinweise: Ich habe RAG durch den Aufbau eines Q&A-Systems gelernt.
Schritt-für-Schritt-Anleitung zu den Praktischen Hinweisen: Ich habe RAG durch den Aufbau eines Q&A-Systems gelernt – Verträge, Überprüfungen sowie Code-Slots für Teams, die dieses Muster einsetzen.
Nutzen Sie dies als für Operator zugängliche Neuformulierung der Ideen aus „I Learned RAG by Building a Q&A System“: klare Phasen, geordnete Codeabschnitte sowie Wiederherstellungshinweise, die auch bei Übergaben erhalten bleiben. Die Überblicksphase funktioniert am besten, wenn sie als messbarer Rahmen betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein optimales Transkript, einen Fehlerfall sowie die Notizen zur Rücksetzung. Protokollieren Sie neben den funktionalen Ergebnissen auch die Dauer sowie die Kosten pro Token oder Abfrage. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsame Umgebungen übergeht.
Kurze Anmerkung zu RAG
Für eine kurze Anmerkung vor Ort: Definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie 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 sowie 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 untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken in der Indizierung unterscheiden.
Wie das System strukturiert ist
Für die Phase „Wie funktioniert das System“ sollten vor der Codeänderung die Eingaben, der Verantwortliche für den jeweiligen 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. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallweg gemeinsam. Wiederholungsversuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und 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.
Aufbau des Eingabepipelines
Zur Erstellung der Eingabepipeline-Phase 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. Vorzuziehen sind kleine, testbare Einheiten statt umfangreicher Skripte. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf eine verworrene Pipeline. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken im Indexing unterscheiden.
Herunterladen
Zur Download-Phase 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.
{
"doc_id": "bsp-mpr-2023-q3",
"title": "Monetary Policy Report Q3 2023",
"period_label": "Q3 2023",
"publication_date": "2023-08-17",
"url": "https://www.bsp.gov.ph/..."
}
Parsing
Zur Parschierungsphase 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. Erfassen Sie die Laufzeiten sowie die Kosten für Token oder Abfragen zusammen mit den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Weg von einer Demo-Umgebung in gemeinsam genutzte Umgebungen wechselt. 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.
Chunking, Embedding und Upserting
Für die Phasen des Chunking-Embeddings und der Upserts 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. Die Konfiguration sollte außerhalb des Anwendungscode gespeichert werden. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort zusammengefasst 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 im Indexing unterscheiden.
def chunk_text_by_tokens(text, enc, chunk_size=512, overlap=64):
tokens = enc.encode(text)
stride = chunk_size - overlap
chunks = []
start = 0
while start < len(tokens):
window = tokens[start : start + chunk_size]
chunks.append(enc.decode(window))
if start + chunk_size >= len(tokens):
break
start += stride
return chunks
Die Abrufschicht und das Problem der Aktualität
Für die Abrufschicht und -phase sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den Schritt sowie die Beendigungskriterien 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. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlnachrichten 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 keine Halluzinationen von Lücken im Indexing unterscheiden.
RECENCY_WEIGHT = 0.85
def combined_score(hit):
relevance = hit.score / max_score
recency = (pub_date - min_date).days / date_span_days # 0.0 to 1.0
return (1 - RECENCY_WEIGHT) * relevance + RECENCY_WEIGHT * recency
# scope to Q1 2023 only
retrieve_chunks(query, period_label_key="q1_2023")
# scope to a date range
retrieve_chunks(query, publication_date_from="2023-01-01", publication_date_to="2023-12-31")
Die Generierungsschicht
Im Stadium der Generierungsschicht 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 verborgene Zustände 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 Pipeline-System. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Indexierungsfehlern unterscheiden. Im Stadium der Generierungsschicht 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 verborgene Zustände schließen zu müssen. Erhalten Sie neben den funktionalen Ergebnissen auch Aufzeichnungen der Laufzeiten sowie der Kosten pro Token oder Abfrage. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von Demonstrationsumgebungen in gemeinsam genutzte Umgebungen übergeht.
Probleme, auf die Sie tatsächlich gestoßen sind
Wenn Sie die Phase „Probleme, auf die Sie tatsächlich gestoßen sind“ bearbeiten, notieren Sie zunächst den Vertrag: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne das Durchlesen des gesamten Systems überprüfen können. Messen Sie die Trefferquote anhand eines festgelegten Fragebogens, bevor Sie die Anfragen anpassen. Eine Änderung der Anfragen behebt selten ein schwaches Suchsystem.
PDF-Vorlagen, die Datenblöcke verschmutzen
Wenn Sie die Phase zur Beseitigung von störenden Teilen im PDF-Boilerplate durchgehen, notieren Sie zunächst den Vertrag: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie gleichzeitig den erfolgreichen Ablauf sowie den Wiederherstellungsprozess. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen. Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragen anpassen – eine häufige Änderung der Anfragen behebt selten ein schwaches Suchsystem.
def _clean_parsed_text(text):
text = text.replace("\x0c", "\n\n")
text = re.sub(r"Classification:\s*GENERAL\s*\n", "", text)
text = re.sub(r"Monetary Policy Report\s*[--][^\n]+\|\s*\d+\s*\n", "", text)
text = re.sub(r"\n{3,}", "\n\n", text)
return text.strip()
Zufällige Löschung der Sammlung
Beim Bearbeiten der Löschphase der Accidental-Kollektion sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsignal 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 Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema. Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragen anpassen. Eine häufige Änderung der Anfragen behebt selten ein schwaches Suchsystem. Beim Bearbeiten der Löschphase der Accidental-Kollektion sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgssignal 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 Prozess von einer Demo-Umgebung in gemeinsam genutzte Umgebungen übergeht.
def _should_recreate_qdrant_collection():
if _is_production_environment():
return False
explicit = os.environ.get("QDRANT_RECREATE_COLLECTION", "").lower()
if explicit in ("1", "true", "yes"):
return True
app_env = (os.environ.get("ENVIRONMENT") or "").lower()
return app_env in ("development", "dev", "local")
Doppelte Blöcke nach erneuter Aufnahme
Die Phase „Doppelte Blöcke nach erneuter Aufnahme“ funktioniert am besten, wenn sie als messbarer Indikator betrachtet wird. Erfassen Sie ein optimales Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung, bevor Sie den Umfang erweitern. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne Durchsicht des gesamten Systems prüfen können. Trennen Sie die Politik zur Blöckenaufteilung von der Politik zur Abrufung. Ein Änderungs an einer sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.
client.delete(
collection_name=collection,
points_selector=models.Filter(must=[
models.FieldCondition(
key="source_file",
match=models.MatchValue(value=source_file)
)
]),
)
Latenz beim ersten Start auf der kostenlosen Ebene
Die Latenz beim Kaltstart in der Produktentwicklung funktioniert am besten, wenn sie als messbarer Wert betrachtet wird. Erfassen Sie vor Erweiterung des Umfangs ein erfolgreiches Szenario, einen Fehlerfall sowie die Notizen zur Rücksetzung. Dokumentieren Sie gleichzeitig den erfolgreichen Ablauf und den Wiederherstellungsprozess. Versuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Trennen Sie die Strategie zur Aufteilung in Blöcke von der Strategie zum Abrufen. Ein Änderungsbedarf bei einer dieser Strategien sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.
Auswahl der Blockgröße
Die Phase „Größe des Chunk auswählen“ funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zur Rücksetzung, bevor Sie den Umfang erweitern. 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 einen verworrenen Ablauf. Trennen Sie die Strategie zur Aufteilung in Chunks von der Strategie zum Abrufen. Eine Änderung an einer sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern. Die Phase „Größe des Chunk auswählen“ funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zur Rücksetzung, bevor Sie den Umfang erweitern. Protokollieren 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 Ablauf von einer Demo in gemeinsame Umgebungen wechselt.
Was Sie anders machen würden
Zur Phase „Was würden Sie tun?“ 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 versteckten Zuständen 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.
Probieren Sie es aus
Zur Phase „Ausprobieren“ sollten Sie die Eingabedaten, den Verantwortlichen für den Schritt sowie die Abbruchkriterien definieren, bevor Sie 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. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholungsversuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. 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.
Operative Checkliste
Während der Bearbeitung der operativen Checkliste sollten Sie zunächst den Vertrag festhalten: erforderliche Eingabedaten, Erfolgsindikatoren 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 Eingabedaten und validierten Ausgaben. Benennen Sie die relevanten Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, teilweise abgeschlossene Abläufe ab.
Messen Sie die Recall-Rate anhand eines festgelegten Fragekatalogs, bevor Sie die Prompts anpassen. Regelmäßige Änderungen der Prompts beheben selten ein schwaches Retrieval-System.
Festlegen Sie die Abhängigkeitsversionen und dokumentieren Sie den Bild-Digest, mit dem die Demo ausgeführt wurde. Reproduzierbarkeit ist besser als kollektives Wissen.
Notieren Sie die Laufzeiten sowie die Kosten pro Token oder Abfrage zusammen mit den funktionalen Ergebnissen. Frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsame Umgebungen übergeht.
Messen Sie die Recall-Rate anhand eines festgelegten Fragekatalogs, bevor Sie die Prompts anpassen. Regelmäßige Änderungen der Prompts beheben selten ein schwaches Retrieval-System.
Vor der Einführung des gesamten Systems sollten Sie die Versionen einfrieren, ein „goldenes Transkript“ für den kritischen Ablauf erstellen und die Rollback-Schritte überprüfen. Gemeinsame Umgebungen erfordern Rate-Limits, Überprüfungen der Nutzungsrechte sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen. Wählen Sie langweilige Zuverlässigkeit statt cleverer, einmaliger Demos.
Batch-Hinweis für a30a0175d827: 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.