Aufbau vertrauenswürdiger Produktions-RAG-Systeme durch kontinuierliche Evaluierung


Dann haben Sie diese Scenario bereits erlebt, in der es so aussieht, als ob Ihr RAG-System intestine funktioniert, es aber immer noch falsch ist. Der Abruf ruft einige Blöcke ab, übergibt sie an das generative Modell und schreibt eine flüssige Antwort. Nichts wirft einen Fehler aus, und dennoch basiert die Antwort möglicherweise auf dem falschen Dokument, es fehlen die Hälfte der benötigten Informationen oder sie basiert auf etwas, das technisch wahr ist, aber drei Versionen veraltet ist. Die einzige Möglichkeit, dies tatsächlich zu erkennen und zu mildern, besteht darin, es regelmäßig richtig zu bewerten.

In diesem Artikel erfahren Sie, wie Sie diese Evaluierungspipeline selbst aufbauen können, beginnend mit den Teilen, die zu einfach erscheinen, um darüber zu schreiben, über die automatisierte Evaluierung mit RAGAS bis hin zu dem Punkt, an dem RAGAS nicht mehr ausreicht, und was es braucht, um dies als tatsächlichen Prozess und nicht als Notizbuch, das Sie vor einem Stakeholder-Assembly öffnen, auszuführen. Die Schritte sind so geschrieben, dass Sie sie für Ihre eigene RAG-Anwendung befolgen und sie nicht nur als Theorie lesen können.

Dies ist Teil 4 von Die RAG for Enterprise-Reiheund wenn Sie die früheren Teile verpasst haben, würde ich Ihnen dringend empfehlen, sich Teil 3 hier anzusehen: Hybride Suche und Neubewertung im Produktions-RAG

Was steht in diesem Artikel?

  1. Aufbau des Goldenen Datensatzes
  2. Führen Sie vor der Automatisierung eine einfache manuelle Bestandsprüfung durch
  3. Automatisieren Sie das Scoring mit RAGAS
  4. Hinzufügen eines benutzerdefinierten LLM-Richters für das, was RAGAS nicht prüfen kann
  5. Mit einem Menschen auf dem Laufenden bleiben
  6. Achten Sie nach dem Versand des Techniques auf Abweichungen
  7. Führen Sie es als Pipeline aus
  8. Abschluss

Aufbau des Goldenen Datensatzes

Bevor Sie eine Bewertungsbibliothek anfassen, benötigen Sie eine Reihe von Fragen mit bekanntermaßen richtigen Antworten. Dies nennt man a Goldener Datensatzund das Überspringen ist der häufigste Fehler, den Groups bei der Arbeit an einem RAG-System machen. Wenn Sie RAGAS direkt auf zufälligen Abfragen ausführen, ohne dass es einen Vergleich gibt, erfahren Sie quick nichts darüber, ob das System tatsächlich richtig oder falsch ist.

Ein guter goldener Datensatzeintrag besteht aus drei Teilen: der Frage, einer korrekten Antwort, die von jemandem geschrieben wurde, der sich mit dem Fachgebiet auskennt, und dem Dokument, das die Antwort enthält. Mit dem dritten Feld können Sie einen Abruffehler (falscher Block abgerufen) von einem Generierungsfehler (richtiger Block, falsche daraus geschriebene Antwort) unterscheiden. Dabei handelt es sich um unterschiedliche Fehler mit unterschiedlichen Korrekturen, und ein Datensatz ohne dieses Feld lässt Sie beim Debuggen blind zurück.

golden_set = (
    {
        "query": "What's the most file dimension for uploads?",
        "ground_truth": "25 MB per file on the free plan, 200 MB on paid plans.",
        "source_doc": "upload_limits.md",
        "class": "single_fact",
    },
    {
        "query": "Can I cancel my subscription mid-cycle and get a refund?",
        "ground_truth": "No, cancellations take impact on the finish of the billing cycle. No partial refunds.",
        "source_doc": "billing_policy.md",
        "class": "single_fact",
    },
)

Zwanzig bis dreißig Fragen reichen aus, um zu Beginn ein echtes Sign zu erhalten. Das Kategoriefeld ist wichtiger als die Anzahl der Einträge, und hier investieren die Groups normalerweise am meisten. Ein Datensatz, der nur aus einfachen sachlichen Nachschlagevorgängen besteht, wird alles passieren und Ihnen nichts sagen, da einfache sachliche Nachschlagevorgänge der einzige Fehlermodus sind, den RAG-Systeme selten haben. Die Kategorien, die es wert sind, hinzugefügt zu werden, in der Reihenfolge, in der sie in der Produktion tatsächlich Anklang finden:

  • Multi-Hop – Für die Antwort müssen zwei oder mehr Blöcke kombiniert werden, was beim Abrufen zu einem stillschweigenden Unterabruf führt
  • Keine Antwort erwartet – Das richtige Verhalten besteht darin, die Antwort zu verweigern und nicht aus dem nächsten semantisch ähnlichen Block zu raten
  • Widersprüchliche oder veraltete Dokumente – Im Korpus gibt es eine alte und eine aktuelle Model derselben Richtlinie, von denen nur eine richtig ist
  • Widersprüchliche Formulierung – Dieselbe Frage wurde mit einer anderen Terminologie gestellt als im Quelldokument

Die dritte Kategorie „Widersprüchliche oder veraltete Dokumente“ ist die am häufigsten übersprungene Kategorie in den goldenen Sätzen und auch diejenige, die tendenziell mehr Produktionsvorfälle im Zusammenhang mit einer Antwort hervorruft, die fließend und intestine zitiert struggle, aber vollständig auf einem Dokument aufbaute, zu dessen Archivierung niemand gekommen struggle. Wenn sich in Ihrem Korpus alte Versionen von Dingen ansammeln (was bei den meisten Dokumentenspeichern in Unternehmen der Fall ist), muss Ihr Evaluierungssatz darauf testen, sonst ist Ihre Pipeline genauso blind dafür wie Ihre Prüfer.


Führen Sie vor der Automatisierung eine einfache manuelle Bestandsprüfung durch

Führen Sie das goldene Set durch Ihre Pipeline und lesen Sie die Antworten neben der Grundwahrheit, bevor Sie ein Bewertungstool einrichten. Dieser Schritt wird ständig übersprungen, weil er sich zu einfach anfühlt, um echte Ingenieursarbeit zu sein. Er zeigt Ihnen jedoch, ob Ihr Datensatz selbst solide ist, und gibt Ihnen ein Gefühl dafür, wie „falsch“ in Ihrem spezifischen System aussieht, bevor Sie einer Metrik vertrauen, die es für Sie erkennt.

outcomes = ()
for merchandise in golden_set:
    reply = rag_pipeline.question(merchandise("query"))
    outcomes.append({
        "query": merchandise("query"),
        "generated_answer": reply,
        "ground_truth": merchandise("ground_truth"),
        "appropriate": None,  # fill in manually
    })

Dadurch werden peinliche Fehler frühzeitig erkannt, z. B. eine defekte Eingabeaufforderungsvorlage, ein Retriever, der nichts zurückgibt, ein Modell, das den Kontext vollständig ignoriert usw. Durch die Automatisierung der Bewertung einer defekten Pipeline erhalten Sie lediglich eine genaue Zahl für etwas, das niemals nützlich sein würde.


Automatisieren Sie das Scoring mit RAGAS

Sobald die Grundlagen stimmen, bietet Ihnen RAGAS eine schnelle und wiederholbare Möglichkeit, die Pipeline in vier Dimensionen zu bewerten, ohne jede Antwort von Hand lesen zu müssen.

from ragas import consider
from ragas.metrics import (
    context_precision,
    context_recall,
    faithfulness,
    answer_relevancy,
)
from datasets import Dataset

eval_dataset = Dataset.from_list((
    {
        "query": merchandise("query"),
        "reply": rag_pipeline.question(merchandise("query")),
        "contexts": rag_pipeline.retrieve(merchandise("query")),
        "ground_truth": merchandise("ground_truth"),
    }
    for merchandise in golden_set
))

consequence = consider(
    eval_dataset,
    metrics=(context_precision, context_recall, faithfulness, answer_relevancy),
)
print(consequence)
  • Kontextpräzision – Wie viele der abgerufenen Brocken waren tatsächlich related, was das Rauschen benachteiligt?
  • Kontexterinnerung – schätzt, ob beim Abruf die Informationen erfasst wurden, die zur Erstellung der Referenzantwort erforderlich sind
  • Treue – ist die Antwort, die auf dem Abgerufenen basiert und eine Halluzination hervorruft
  • Antwortrelevanz – Bezieht sich die Antwort auf die eigentliche Frage und nicht auf eine nahegelegene Frage?

Ein typischer Lauf sieht in etwa so aus (die Zahlen dienen zur Erläuterung der einzelnen Metriken):

Metrisch Punktzahl
Kontextpräzision 0,81
Kontextrückruf 0,74
Treue 0,88
Antwortrelevanz 0,85

Ein hoher Treuewert wird als „die Antwort ist richtig“ interpretiert, und das ist genau die Fehlinterpretation, die schlechte Antworten durchlässt. Faithfulness prüft nur, ob die Antwort durch den abgerufenen Kontext unterstützt wird oder nicht, es sagt nicht aus, ob dieser Kontext der richtige Abruf struggle. Ein veraltetes oder veraltetes Dokument liefert, getreu zusammengefasst, eine Antwort, die völlig fundiert und gleichzeitig völlig falsch ist. Dies ist die strukturelle Grenze von RAGAS: Es ist sehr intestine darin, Halluzinationen zu erkennen, und sehr schlecht darin, eine sicher falsche Quelle zu erkennen.


Hinzufügen eines benutzerdefinierten LLM-Richters für das, was RAGAS nicht prüfen kann

Die meisten RAGAS-Metriken basieren auf einer LLM-basierten Auswertung mit vordefinierten Eingabeaufforderungen, die nichts über Ihre Area wissen. Wenn die Korrektheit für Sie von etwas Bestimmtem abhängt, wie z. B. genauen Zahlen, der Aktualität der Quelle, einem erforderlichen Haftungsausschluss, dem Ton usw., wird sie von den Standardaufforderungen nicht erfasst, da sie nie dazu aufgefordert wurde.

Um dieses Downside zu lösen, können Sie einen LLM als Richter einsetzen und ihm eine benutzerdefinierte Eingabeaufforderung übergeben, die ihn anweist, die Antworten auf der Grundlage Ihrer spezifischen Bedürfnisse zu beurteilen.

import json
from google import genai
from google.genai.varieties import GenerateContentConfig

shopper = genai.Shopper(
    vertexai=True,
    mission="YOUR_GCP_PROJECT_ID",
    location="us-central1",
)

JUDGE_PROMPT = """
Evaluate the generated reply to the bottom fact. Rating 1-5 on every dimension.

Query: {query}
Floor Fact: {ground_truth}
Generated Reply: {reply}
Supply Doc Date: {doc_date}

1. numeric_accuracy - are all numbers and information appropriate, not simply believable?
2. recency_awareness - if the supply is outdated, does the reply flag
   uncertainty as a substitute of stating it as present reality?

Return JSON solely:
{{
    "numeric_accuracy": int,
    "recency_awareness": int,
    "reasoning": str
}}
"""

def custom_judge(query, ground_truth, reply, doc_date, shopper):
    immediate = JUDGE_PROMPT.format(
        query=query,
        ground_truth=ground_truth,
        reply=reply,
        doc_date=doc_date,
    )

    response = shopper.fashions.generate_content(
        mannequin="gemini-2.5-flash",
        contents=immediate,
        config=GenerateContentConfig(
            temperature=0,
            max_output_tokens=250,
            response_mime_type="software/json",
        ),
    )

    return json.masses(response.textual content)

Führen Sie dies nicht jedes Mal für den gesamten Datensatz aus, da es langsamer ist und mehr professional Aufruf kostet als RAGAS. Beschränken Sie es auf die Kategorien, in denen die RAGAS-Bewertung tatsächlich begrenzt ist, was in der Praxis bedeutet conflicting_docs Und no_answer_expected. Wenn Sie es überall sonst einsetzen, zahlen Sie für Präzision, die Sie bei Fragen nicht benötigen. RAGAS punktet bereits zuverlässig.


Mit einem Menschen auf dem Laufenden bleiben

Sowohl RAGAS als auch ein benutzerdefinierter Juror sind immer noch LLMs, die die Leistung eines anderen LLM bewerten, und sie werden nicht immer mit einem Menschen übereinstimmen. Die hier zu wissende ehrliche Zahl, die die meisten Groups nie messen, ist, wie oft Ihr Richter einer Individual tatsächlich zustimmt. In der Praxis ist eine LLM-Richter-zu-Mensch-Übereinstimmung im unteren bis mittleren Bereich von 80 % üblich, kein Zeichen dafür, dass etwas kaputt ist, aber eine tatsächliche Obergrenze ist eher wissenswert als anzunehmen.

def needs_human_review(ragas_score, judge_score, threshold=1.0):
    return abs(ragas_score - judge_score) > threshold

Dadurch bleibt die menschliche Bewertungswarteschlange klein und zielgerichtet, sodass nur die Fälle berücksichtigt werden, in denen zwei Bewertungsmethoden nicht übereinstimmen, nicht jede Antwort. Es lohnt sich auch, gelegentlich zwei Personen unabhängig voneinander die gleiche Handvoll grenzwertiger Antworten bewerten zu lassen. Wenn Domänenexperten bei einem bestimmten Fragetyp in quick einem Drittel der Fälle unterschiedlicher Meinung sind, handelt es sich nicht um ein Downside der Scoring-Pipeline. Die Grundwahrheit selbst ist nicht eindeutig, und keine Instruments können das beheben. Dies bedeutet normalerweise, dass der Golden-Set-Eintrag neu geschrieben werden muss, nicht der Richter.


Achten Sie nach dem Versand des Techniques auf Abweichungen

Eine Pipeline, die nur gegen einen festen Golden Set läuft, weist einen blinden Fleck auf, da sich der Dwell-Korpus darunter ändert. Neue Dokumente werden hinzugefügt, alte archiviert und echte Benutzeranfragen weichen von dem ab, was Sie ursprünglich getestet haben. Nichts davon taucht in einem Datensatz auf, der an dem Tag, an dem Sie ihn geschrieben haben, eingefroren wurde.

import random
from datetime import datetime, timedelta

def sample_production_queries(logs, n=50, days=7):
    latest = (q for q in logs if q("timestamp") > datetime.now() - timedelta(days=days))
    return random.pattern(latest, min(n, len(latest)))

Wenn Sie wöchentlich einen kleinen Teil des Dwell-Verkehrs abtasten und ihn mit der Kontextpräzision und -treue von RAGAS durchlaufen lassen – beide Metriken funktionieren ohne eine Floor-Fact-Antwort –, erhalten Sie ein zweites Sign. Ein plötzlicher Ausfall ohne entsprechende Codeänderung bedeutet normalerweise, dass sich etwas im Korpus und nicht in der Pipeline geändert hat, und es handelt sich um einen anderen Fehlermodus als alles, was eine Zusammenführungszeitprüfung jemals erkennen wird.


Führen Sie es als Pipeline aus

Zwei Dinge machen es zu einer echten Pipeline und nicht zu einer einmaligen Übung: Kostenbewusste Planungund a CI-Tor.

Das Ausführen des gesamten Stacks: RAGAS, der benutzerdefinierte Richter und die menschliche Überprüfung jedes einzelnen Commits ist so teuer, dass die meisten Groups innerhalb eines Monats stillschweigend damit aufhören. In der Praxis funktioniert die Abstufung besser:

  • RAGAS auf dem kompletten goldenen Set: Jede Pull-Anfrage berührt den Abruf oder die Eingabeaufforderungen
  • Benutzerdefinierte Beurteilung nur für gekennzeichnete Kategorien: jede Pull-Anfrage, beschränkt auf eine Handvoll Beispiele
  • Menschliche Überprüfung: wöchentlich, nur in der Meinungsverschiedenheitswarteschlange
  • Produktionsstichprobe: wöchentlich, auf einem rotierenden Teil des Dwell-Verkehrs
def check_regression(current_scores, baseline_scores, threshold=0.03):
    regressions = (
        (metric, baseline_scores(metric), rating)
        for metric, rating in current_scores.objects()
        if baseline_scores(metric) - rating > threshold
    )
    if regressions:
        elevate SystemExit(f"Blocking merge — regressions discovered: {regressions}")
    print("No regressions. Secure to merge.")

Verknüpfen Sie dies mit CI, sodass es bei jeder Pull-Anfrage ausgeführt wird, die Abruf, Chunking oder Eingabeaufforderungen berührt, und lassen Sie den Construct fehlschlagen, wenn eine Metrik Ihren Schwellenwert überschreitet. Dies ist der wichtigste Teil der gesamten Einrichtung und auch derjenige, der tatsächlich Vorfälle verhindert. Hier wird beispielsweise eine Chunking-Änderung abgefangen, die stillschweigend eine Klasse von Abfragen unterbricht, bevor sie drei Wochen später zu einem Assist-Ticket wird und nicht heute zu einer fehlgeschlagenen Prüfung.


Abschluss

Keiner der oben genannten sechs Schritte ist für sich genommen beeindruckend, wenn er unabhängig voneinander angewendet wird. Was jedoch den Unterschied macht, ist die gemeinsame Ausführung nach einem Zeitplan, als etwas, dem das Staff vertraut, und nicht als etwas, an das sich jemand hin und wieder erinnert. Das ist die Absicht dieses Artikels, von der Durchführung der Evaluierung als einmalige Bauchprüfung bis hin zur Integration in die RAG-Systeminfrastruktur, dem stillen Sitzen im CI und dem Erfassen der Änderung, die andernfalls erfolgt wäre.

Wenn Sie bei Null anfangen, versuchen Sie nicht, alle sechs Schritte auf einmal aufzubauen. Ein goldener Datensatz mit zwanzig guten Fragen und einem manuell überprüften RAGAS-Rating ist den meisten heute in Produktion befindlichen RAG-Systemen bereits voraus. Der Relaxation kann hinzugefügt werden, wenn das System wächst und Ihre Geduld für das manuelle Lesen von Antworten wächst.

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert