7. OptimizationExperte

Automatisierte RAG-Evaluierungs-Pipeline: Regressionen erkennen bevor Ihre Nutzer es tun

7. September 2026
27 min Lesezeit
Ailog Team

Kompletter Guide zum Aufbau einer automatisierten RAG-Evaluierungs-Pipeline: Golden Datasets, RAGAS-Metriken, Regressionserkennung, Alerting und CI/CD-Integration mit GitHub Actions.

TL;DR

83% der RAG-Teams entdecken Regressionen durch Nutzerbeschwerden. Dieser Guide zeigt Ihnen, wie Sie eine automatisierte Evaluierungs-Pipeline aufbauen, die Probleme vor der Produktion erkennt: verwaltete Golden Datasets, automatisierte RAGAS-Metriken (Faithfulness, Relevancy, Context Recall), Alarmschwellenwerte und GitHub-Actions-Integration. Mit einer gut konfigurierten Pipeline erkennen Sie 95% der Regressionen, bevor sie die Nutzer erreichen.

Warum eine automatisierte Evaluierungs-Pipeline

Das Problem mit manuellen Evaluierungen

AnsatzAbdeckungHaeufigkeitKostenRegressionserkennung
Manuelle Tests5-10% der FaelleAd-hocHoch (Zeit)Spaet
Nutzer-FeedbackAuswahlbiasKontinuierlichKostenlosSehr spaet
Automatisierte Evaluierung100% des Golden DatasetBei jeder AenderungNiedrigSofort

Ursachen von Regressionen in RAG

┌────────────────────────────────────────────────────┐
│              RAG-REGRESSIONSURSACHEN                 │
├────────────────────────────────────────────────────┤
│                                                    │
│  Dokumentenaenderungen                             │
│  ├─ Schlecht formatierte neue Dokumente            │
│  ├─ Geloeschte relevante Dokumente                 │
│  └─ Updates die das Chunking beschaedigen          │
│                                                    │
│  Konfigurationsaenderungen                         │
│  ├─ Neues Embedding-Modell                         │
│  ├─ Chunk-Groessenaenderung                        │
│  ├─ Prompt-Modifikation                            │
│  └─ Reranker-Update                                │
│                                                    │
│  LLM-Modellaenderungen                             │
│  ├─ Neue Modellversion                             │
│  ├─ Provider-Wechsel                               │
│  └─ Temperatur/Top-p Aenderung                     │
│                                                    │
│  Stille Degradation                                │
│  ├─ Daten-Drift                                    │
│  ├─ Fragmentierter Vektor-Index                    │
│  └─ Embedding-Provider API-Aenderung               │
└────────────────────────────────────────────────────┘

Architektur der Evaluierungs-Pipeline

Ueberblick

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│   Golden     │     │    RAG       │     │ Automatische │
│   Dataset    │────▶│   Pipeline   │────▶│ Evaluierung  │
│              │     │              │     │              │
│ - Fragen     │     │ - Retrieval  │     │ - RAGAS      │
│ - Antworten  │     │ - Generation │     │ - DeepEval   │
│ - Kontexte   │     │              │     │ - Custom     │
└─────────────┘     └──────────────┘     └──────┬───────┘
                                                 │
                                        ┌────────┴────────┐
                                        │                 │
                                  ┌─────┴─────┐    ┌──────┴──────┐
                                  │ Schwellen  │    │  Dashboard  │
                                  │ & Alarme   │    │  Langfuse   │
                                  └─────┬─────┘    └─────────────┘
                                        │
                                  ┌─────┴─────┐
                                  │  CI/CD    │
                                  │  Gate     │
                                  └───────────┘

Schritt 1: Golden Dataset aufbauen

Struktur des Golden Dataset

DEVELOPERpython
from dataclasses import dataclass, field from typing import List, Optional import json @dataclass class GoldenExample: """Ein Beispiel aus dem Golden Dataset.""" id: str question: str expected_answer: str expected_contexts: List[str] category: str # "factual", "comparison", "multi-hop", "opinion" difficulty: str # "easy", "medium", "hard" tags: List[str] = field(default_factory=list) metadata: dict = field(default_factory=dict) @dataclass class GoldenDataset: """Vollstaendiges Evaluierungs-Dataset.""" version: str created_at: str examples: List[GoldenExample] def to_json(self, path: str): with open(path, "w") as f: json.dump(self.__dict__, f, indent=2, default=str) @classmethod def from_json(cls, path: str): with open(path) as f: data = json.load(f) examples = [GoldenExample(**ex) for ex in data["examples"]] return cls( version=data["version"], created_at=data["created_at"], examples=examples )

Golden Dataset automatisch generieren

DEVELOPERpython
import anthropic client = anthropic.Anthropic() def generate_golden_examples( documents: list, num_questions: int = 50, categories: list = None ) -> list: """Generiert Testbeispiele aus Dokumenten.""" if categories is None: categories = ["factual", "comparison", "multi-hop"] examples = [] for doc in documents: response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=2000, messages=[{ "role": "user", "content": f"""Generiere aus dem folgenden Dokument {num_questions // len(documents)} Frage/Antwort-Paare zum Testen eines RAG-Systems. Fuer jedes Paar: - question: natuerlich, wie ein echter Nutzer fragen wuerde - expected_answer: die korrekte und vollstaendige Antwort - context: die exakte Passage aus dem Dokument mit der Antwort - category: {', '.join(categories)} - difficulty: easy, medium, oder hard Gib JSON zurueck: [{{"question": "...", "expected_answer": "...", "context": "...", "category": "...", "difficulty": "..."}}] Dokument: {doc['text'][:5000]}""" }] ) batch = json.loads(response.content[0].text) for item in batch: examples.append(GoldenExample( id=f"gen_{len(examples)}", question=item["question"], expected_answer=item["expected_answer"], expected_contexts=[item["context"]], category=item["category"], difficulty=item["difficulty"], tags=[doc.get("source", "unknown")] )) return examples

Empfohlene Golden-Dataset-Groesse

KorpusgroesseEmpfohlene BeispieleVerteilung
< 100 Docs30-5050% faktisch, 30% Vergleich, 20% Multi-Hop
100-1000 Docs50-10040% faktisch, 30% Vergleich, 20% Multi-Hop, 10% Randfaelle
1000-10000 Docs100-200Wie oben + 10% adversarial
> 10000 Docs200-500Stratifiziert nach Dokumentkategorie

Schritt 2: Metriken implementieren

Mit RAGAS

DEVELOPERpython
from ragas import evaluate from ragas.metrics import ( faithfulness, answer_relevancy, context_precision, context_recall, answer_correctness, ) from datasets import Dataset def evaluate_rag_with_ragas( golden_dataset: GoldenDataset, rag_pipeline, metrics=None ): """Evaluiert die RAG-Pipeline mit RAGAS.""" if metrics is None: metrics = [ faithfulness, answer_relevancy, context_precision, context_recall, answer_correctness, ] questions = [] answers = [] contexts = [] ground_truths = [] for example in golden_dataset.examples: result = rag_pipeline.query(example.question) questions.append(example.question) answers.append(result["answer"]) contexts.append(result["retrieved_contexts"]) ground_truths.append(example.expected_answer) eval_dataset = Dataset.from_dict({ "question": questions, "answer": answers, "contexts": contexts, "ground_truth": ground_truths, }) results = evaluate(eval_dataset, metrics=metrics) return results results = evaluate_rag_with_ragas(golden_dataset, my_rag_pipeline) print(f"Faithfulness: {results['faithfulness']:.3f}") print(f"Answer Relevancy: {results['answer_relevancy']:.3f}") print(f"Context Recall: {results['context_recall']:.3f}")

Mit DeepEval

DEVELOPERpython
from deepeval import evaluate from deepeval.metrics import ( FaithfulnessMetric, AnswerRelevancyMetric, ContextualRecallMetric, ContextualPrecisionMetric, HallucinationMetric, ) from deepeval.test_case import LLMTestCase def evaluate_with_deepeval( golden_dataset: GoldenDataset, rag_pipeline ): """Evaluiert die RAG-Pipeline mit DeepEval.""" test_cases = [] for example in golden_dataset.examples: result = rag_pipeline.query(example.question) test_case = LLMTestCase( input=example.question, actual_output=result["answer"], expected_output=example.expected_answer, retrieval_context=result["retrieved_contexts"], context=example.expected_contexts, ) test_cases.append(test_case) metrics = [ FaithfulnessMetric(threshold=0.8), AnswerRelevancyMetric(threshold=0.7), ContextualRecallMetric(threshold=0.7), ContextualPrecisionMetric(threshold=0.7), HallucinationMetric(threshold=0.2), ] results = evaluate(test_cases, metrics) return results

Custom-Metriken mit pytest

DEVELOPERpython
# tests/test_rag_quality.py import pytest import json GOLDEN_DATASET = GoldenDataset.from_json("tests/golden_dataset.json") RAG_PIPELINE = init_rag_pipeline() THRESHOLDS = { "faithfulness": 0.85, "answer_relevancy": 0.80, "context_recall": 0.75, "context_precision": 0.70, "answer_correctness": 0.75, "latency_p95_ms": 3000, "hallucination_rate": 0.05, } class TestRAGQuality: """Automatisierte RAG-Qualitaetstests.""" @pytest.fixture(autouse=True) def setup(self): self.results = [] for example in GOLDEN_DATASET.examples: result = RAG_PIPELINE.query(example.question) self.results.append({ "example": example, "result": result }) def test_faithfulness_above_threshold(self): """Antworten sind quellentreu.""" scores = [ compute_faithfulness(r["result"]["answer"], r["result"]["retrieved_contexts"]) for r in self.results ] avg_score = sum(scores) / len(scores) assert avg_score >= THRESHOLDS["faithfulness"], \ f"Faithfulness {avg_score:.3f} < {THRESHOLDS['faithfulness']}" def test_context_recall_above_threshold(self): """Die richtigen Dokumente werden abgerufen.""" scores = [] for r in self.results: retrieved = r["result"]["retrieved_contexts"] expected = r["example"].expected_contexts recall = compute_context_recall(retrieved, expected) scores.append(recall) avg_score = sum(scores) / len(scores) assert avg_score >= THRESHOLDS["context_recall"], \ f"Context Recall {avg_score:.3f} < {THRESHOLDS['context_recall']}" def test_no_hallucination_spike(self): """Nicht mehr als 5% Halluzinationen.""" hallucination_count = sum( 1 for r in self.results if is_hallucination( r["result"]["answer"], r["result"]["retrieved_contexts"] ) ) rate = hallucination_count / len(self.results) assert rate <= THRESHOLDS["hallucination_rate"], \ f"Halluzinationsrate {rate:.3f} > {THRESHOLDS['hallucination_rate']}" def test_latency_within_bounds(self): """P95-Latenz unter 3 Sekunden.""" latencies = [r["result"]["latency_ms"] for r in self.results] latencies.sort() p95 = latencies[int(len(latencies) * 0.95)] assert p95 <= THRESHOLDS["latency_p95_ms"], \ f"P95-Latenz {p95}ms > {THRESHOLDS['latency_p95_ms']}ms"

Schritt 3: CI/CD-Integration mit GitHub Actions

GitHub Actions Workflow

DEVELOPERyaml
# .github/workflows/rag-evaluation.yml name: RAG Evaluation Pipeline on: push: paths: - 'backend/rag/**' - 'backend/prompts/**' - 'backend/config/**' pull_request: branches: [main, develop] schedule: - cron: '0 6 * * 1' # Jeden Montag um 6 Uhr jobs: evaluate: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | pip install ragas deepeval pytest langfuse pip install -r backend/requirements.txt - name: Run RAG evaluation env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} QDRANT_URL: ${{ secrets.QDRANT_URL }} LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }} run: | pytest tests/test_rag_quality.py \ --tb=long \ --json-report \ --json-report-file=eval_results.json \ -v - name: Check thresholds run: | python scripts/check_eval_thresholds.py \ --results eval_results.json \ --baseline tests/baseline_scores.json - name: Alert on regression if: failure() run: | python scripts/send_regression_alert.py \ --results eval_results.json \ --channel slack \ --webhook ${{ secrets.SLACK_WEBHOOK }}

Schritt 4: Dashboard und Monitoring

Vergleich der Evaluierungs-Tools

ToolMetrikenCI/CDOpen-SourceDashboardPreis
RAGASFaithfulness, Relevancy, Recall, PrecisionVia pytestJaNein (custom)Kostenlos
DeepEval14+ Metriken, Halluzination, ToxizitaetNativJaJa (Confident AI)Freemium
LangfuseCustom + LLM-as-JudgeVia SDKJaJa (ausgezeichnet)Freemium
BraintrustCustom, RAGAS, A/B-VergleichNativNeinJaKostenlos / $249/Mo (Pro)
Arize PhoenixTraces, Embeddings, DriftsVia SDKJaJaFreemium
TruLensFeedback-Funktionen, GroundednessVia SDKJaJaKostenlos

Langfuse-Integration

DEVELOPERpython
from langfuse import Langfuse langfuse = Langfuse( secret_key="sk-lf-...", public_key="pk-lf-...", host="https://cloud.langfuse.com" ) def log_evaluation_to_langfuse( results: dict, run_id: str, metadata: dict = None ): """Protokolliert Evaluierungsergebnisse in Langfuse.""" for example_result in results["examples"]: trace = langfuse.trace( name="rag-evaluation", metadata={ "run_id": run_id, "category": example_result["category"], **(metadata or {}) } ) trace.span( name="retrieval", input=example_result["question"], output=example_result["retrieved_contexts"], ) trace.score(name="faithfulness", value=example_result["faithfulness"]) trace.score(name="answer_relevancy", value=example_result["relevancy"]) trace.score(name="context_recall", value=example_result["context_recall"]) langfuse.flush()

Dashboard-Metriken zum Tracken

MetrikKritischer SchwellenwertAlarm-SchwellenwertHaeufigkeit
Faithfulness< 0,80< 0,85Pro Commit
Answer Relevancy< 0,75< 0,80Pro Commit
Context Recall< 0,70< 0,75Pro Commit
Context Precision< 0,65< 0,70Pro Commit
Halluzinationsrate> 0,10> 0,05Pro Commit
Latenz P95> 5000ms> 3000msPro Commit
Kosten pro Anfrage> $0,10> $0,05Woechentlich
Drift-Score> 0,15> 0,10Taeglich

Schritt 5: Fortgeschrittene Regressionserkennung

Statistische Erkennung

DEVELOPERpython
import numpy as np from scipy import stats def detect_regression( current_scores: list, baseline_scores: list, alpha: float = 0.05, min_delta: float = 0.03 ) -> dict: """Erkennt statistisch signifikante Regressionen.""" current = np.array(current_scores) baseline = np.array(baseline_scores) # Welch t-Test (fuer ungleiche Stichprobengroessen) t_stat, p_value = stats.ttest_ind( baseline, current, equal_var=False, alternative='greater' ) delta = np.mean(baseline) - np.mean(current) is_regression = ( p_value < alpha and delta > min_delta ) return { "is_regression": is_regression, "p_value": p_value, "delta": delta, "current_mean": np.mean(current), "baseline_mean": np.mean(baseline), "confidence": 1 - p_value, "effect_size": delta / np.std(baseline) }

Intelligentes Alerting

DEVELOPERpython
def evaluate_and_alert(rag_pipeline, golden_dataset, config): """Evaluiert RAG und sendet Alarme bei Bedarf.""" results = evaluate_rag_with_ragas(golden_dataset, rag_pipeline) baseline = load_baseline() alerts = [] for metric, value in results.items(): threshold = config["thresholds"].get(metric) previous = baseline.get(metric) if threshold and value < threshold: alerts.append({ "level": "critical", "metric": metric, "value": value, "threshold": threshold, "message": ( f"{metric} fiel auf {value:.3f}, " f"unter kritischem Schwellenwert {threshold:.3f}" ) }) elif previous and value < previous - 0.03: alerts.append({ "level": "warning", "metric": metric, "value": value, "previous": previous, "message": ( f"{metric} sank von {previous:.3f} auf " f"{value:.3f} (Delta: {value - previous:+.3f})" ) }) if alerts: send_alerts(alerts, config) if not any(a["level"] == "critical" for a in alerts): update_baseline(results) return results, alerts

Best Practices

Golden-Dataset-Verwaltung

  1. Versionieren Sie das Golden Dataset in Git (wie Code)
  2. Aktualisieren wenn sich Dokumente wesentlich aendern
  3. Stratifizieren nach Kategorie, Schwierigkeit und Quelle
  4. Menschlich validieren Sie regelmaessig eine Stichprobe
  5. Niemals fuer das Golden Dataset optimieren (Overfitting)

Robuste Pipeline

PraxisWarumWie
Deterministische TestsReproduzierbare ErgebnisseFester Seed, Temperatur 0
Versionierte BaselineEntwicklungen vergleichenJSON in Git
Abgestufte AlarmeKeine Alarm-MuedigkeitCritical vs Warning
Archivierte ErgebnisseTrendanalyseLangfuse oder DB
Timeout pro TestBlockierungen vermeidenpytest-timeout

Evaluierungshaeufigkeit

EreignisEvaluierungUmfang
Push auf developSchnell (20 Beispiele)Smoke Test
PR nach mainVollstaendig (gesamtes Golden Dataset)Gate
WoechentlichVollstaendig + DriftMonitoring
ModellaenderungVollstaendig + A/B-TestValidierung
DokumentenaenderungNur RetrievalFokus

FAQ

Wie viele Beispiele im Golden Dataset?

Minimum 30 fuer statistisch signifikante Ergebnisse. Ideal sind 100-200 Beispiele, stratifiziert nach Fragenkategorie. Ueber 500 steigen die Evaluierungskosten ohne proportionalen Vertrauensgewinn. Beginnen Sie mit 50 und erhoehem Sie schrittweise. Siehe unseren Guide zu RAG-Evaluierungsmetriken fuer Details zu den Metriken.

RAGAS oder DeepEval, welches waehlen?

RAGAS ist reifer, besser dokumentiert und die akademische Referenz. DeepEval bietet mehr Metriken (14+), native CI/CD-Integration und ein Dashboard. Fuer ein einfaches Projekt reicht RAGAS. Fuer eine Produktions-Pipeline mit Monitoring ist DeepEval + Langfuse vollstaendiger. Beide sind Open-Source und mit pytest kompatibel.

Wie geht man mit Fragen um, die keine gute Antwort haben?

Nehmen Sie in Ihr Golden Dataset Fragen auf, die das RAG nicht beantworten sollte (ausserhalb des Umfangs, fehlende Information). Fuegen Sie eine "Refusal Accuracy"-Metrik hinzu: Das RAG sollte die Antwort verweigern oder "Ich weiss nicht" sagen, anstatt zu halluzinieren. Dies ist oft die schwierigste Metrik zum Aufrechterhalten.

Ist die Evaluierungs-Pipeline teuer?

Fuer 100 Beispiele mit RAGAS (das standardmaessig GPT-4o-mini fuer die Evaluierung verwendet): von wenigen Cent bis zu einigen Dollar pro Durchlauf, je nach gewaehltem Judge-Modell. Mit DeepEval und einem lokalen Modell ist es nahezu kostenlos. Die Hauptkosten sind die Laufzeit (~5-15 Minuten fuer 100 Beispiele). Das ist vernachlaessigbar im Vergleich zu den Kosten einer Regression in der Produktion. Siehe unseren Guide zur RAG-Kostenoptimierung.

Wie testet man Prompt-Aenderungen?

Verwenden Sie A/B-Evaluierung: Fuehren Sie das Golden Dataset mit dem alten und neuen Prompt aus und vergleichen Sie die Metriken. Der neue Prompt muss statistisch besser sein (nicht nur marginal), um die Aenderung zu rechtfertigen. Integrieren Sie diesen Vergleich in Ihre PR-Review. Siehe unseren Guide zum RAG Prompt Engineering.


Eine automatisierte RAG-Evaluierungs-Pipeline ist Ihr Sicherheitsnetz gegen stille Regressionen. Ein paar Stunden Investition in den Aufbau sparen Ihnen Tage des Debuggings und schuetzen das Vertrauen Ihrer Nutzer. Testen Sie Ailog, um von integriertem Qualitaetsmonitoring auf Ihrem RAG-Chatbot zu profitieren.

Tags

RAGEvaluierungRAGASCI/CDTestingMetrikenDeepEvalLangfuseQualitaet

Verwandte Artikel

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !