RAGAS : Open-Source-Framework zur Evaluierung von RAG
Beherrschen Sie RAGAS, um Ihre RAG-Systeme automatisch zu bewerten. Installation, Metriken, synthetische Datensätze und CI/CD-Integration.
RAGAS : Open-Source RAG-Bewertungsframework
RAGAS (Retrieval Augmented Generation Assessment) ist zum De-facto-Standard geworden, um RAG-Systeme zu bewerten. Dieses Open-Source-Framework bietet automatisierte Metriken, die die Qualität von retrieval und der Generierung messen, ohne ein vollständiges Ground Truth zu benötigen. Dieser Leitfaden führt Sie von der Installation bis zur Integration in die Produktion.
Pourquoi RAGAS ?
Manuelle Evaluation von RAG-Systemen ist zeitaufwändig und nicht reproduzierbar. RAGAS löst dieses Problem mit automatisch berechenbaren Metriken:
| Approche | Temps/100 samples | Reproductibilité | Coût |
|---|---|---|---|
| Évaluation humaine | 4-8 heures | Faible | Élevé |
| Tests manuels | 1-2 heures | Moyenne | Moyen |
| RAGAS automatisé | 5-15 minutes | Parfaite | Faible |
Avantages de RAGAS
- Open-source : Code auditierbar, kein Vendor Lock-in
- LLM-as-judge : Nutzt ein LLM, um Antworten zu bewerten
- Sans ground truth : Einige Metriken benötigen keine Referenz
- Intégrable CI/CD : Vollständige Automatisierung der Bewertungen
- Métriques granulaires : Identifiziert gezielt Schwachstellen
Installation et configuration
Setup de base
DEVELOPERpython# Installation # pip install ragas langchain-openai datasets from ragas import evaluate from ragas.metrics import ( faithfulness, answer_relevancy, context_recall, context_precision, answer_correctness, answer_similarity ) from langchain_openai import ChatOpenAI, OpenAIEmbeddings import os # Configuration du LLM évaluateur os.environ["OPENAI_API_KEY"] = "sk-..." # LLM pour l'évaluation (gpt-4 recommandé pour la précision) llm = ChatOpenAI(model="gpt-4o-mini", temperature=0) embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
Configuration avancée
DEVELOPERpythonfrom ragas.llms import LangchainLLMWrapper from ragas.embeddings import LangchainEmbeddingsWrapper # Wrapper pour utiliser d'autres LLMs class CustomEvaluator: def __init__(self, llm_model: str = "gpt-4o-mini"): self.llm = LangchainLLMWrapper( ChatOpenAI(model=llm_model, temperature=0) ) self.embeddings = LangchainEmbeddingsWrapper( OpenAIEmbeddings(model="text-embedding-3-small") ) def configure_metrics(self): """Configure les métriques avec le LLM custom""" metrics = [faithfulness, answer_relevancy, context_recall] for metric in metrics: metric.llm = self.llm if hasattr(metric, 'embeddings'): metric.embeddings = self.embeddings return metrics
Les métriques RAGAS en détail
1. Faithfulness (Fidélité)
Mesure si la réponse générée est fidèle au contexte fourni, sans hallucination.
DEVELOPERpythonfrom ragas.metrics import faithfulness from datasets import Dataset # Données d'évaluation eval_data = { "question": ["Quelle est la politique de retour ?"], "answer": ["Vous avez 30 jours pour retourner un produit non utilisé."], "contexts": [["Notre politique de retour permet le retour de tout produit non ouvert dans un délai de 30 jours."]] } dataset = Dataset.from_dict(eval_data) # Évaluer la fidélité result = evaluate(dataset, metrics=[faithfulness]) print(f"Faithfulness: {result['faithfulness']:.3f}")
Fonctionnement interne :
- Extrait les affirmations de la réponse
- Vérifie chaque affirmation contre le contexte
- Score = affirmations supportées / total affirmations
| Score | Interprétation | Action |
|---|---|---|
| > 0.9 | Excellent | Maintenir |
| 0.7-0.9 | Acceptable | Améliorer prompts |
| < 0.7 | Problématique | Revoir le pipeline |
2. Answer Relevancy (Pertinence)
Évalue si la réponse répond effectivement à la question posée.
DEVELOPERpythonfrom ragas.metrics import answer_relevancy eval_data = { "question": ["Comment réinitialiser mon mot de passe ?"], "answer": ["Pour réinitialiser votre mot de passe, cliquez sur 'Mot de passe oublié' sur la page de connexion, entrez votre email, et suivez le lien reçu."], "contexts": [["Guide de connexion : Le bouton 'Mot de passe oublié' envoie un email de réinitialisation."]] } dataset = Dataset.from_dict(eval_data) result = evaluate(dataset, metrics=[answer_relevancy]) print(f"Answer Relevancy: {result['answer_relevancy']:.3f}")
Fonctionnement interne :
- Génère des questions à partir de la réponse
- Compare ces questions avec la question originale (similarité cosinus)
- Score = similarité moyenne des questions générées
3. Context Recall
Mesure si le contexte récupéré contient les informations nécessaires pour répondre.
DEVELOPERpythonfrom ragas.metrics import context_recall eval_data = { "question": ["Quels sont les moyens de paiement acceptés ?"], "contexts": [["Nous acceptons Visa, Mastercard et PayPal. Le paiement en 3x sans frais est disponible."]], "ground_truth": ["Les moyens de paiement acceptés sont Visa, Mastercard, PayPal, et le paiement en 3x sans frais."] } dataset = Dataset.from_dict(eval_data) result = evaluate(dataset, metrics=[context_recall]) print(f"Context Recall: {result['context_recall']:.3f}")
4. Context Precision
Évalue si les contextes pertinents sont bien classés en haut des résultats.
DEVELOPERpythonfrom ragas.metrics import context_precision eval_data = { "question": ["Quels sont les délais de livraison ?"], "contexts": [[ "Livraison standard : 3-5 jours ouvrés. Express : 24h.", "Notre service client est disponible 24/7.", "Livraison gratuite à partir de 50 EUR." ]], "ground_truth": ["Livraison standard en 3-5 jours, express en 24h, gratuite dès 50 EUR."] } dataset = Dataset.from_dict(eval_data) result = evaluate(dataset, metrics=[context_precision]) print(f"Context Precision: {result['context_precision']:.3f}")
5. Answer Correctness
Combine similarité sémantique et factuelle pour une évaluation complète.
DEVELOPERpythonfrom ragas.metrics import answer_correctness eval_data = { "question": ["Quel est le prix de l'abonnement Premium ?"], "answer": ["L'abonnement Premium coûte 29,99 EUR par mois."], "ground_truth": ["L'abonnement Premium est à 29,99 EUR/mois avec engagement annuel."] } dataset = Dataset.from_dict(eval_data) result = evaluate(dataset, metrics=[answer_correctness]) print(f"Answer Correctness: {result['answer_correctness']:.3f}")
Création d'un dataset d'évaluation
Génération automatique avec RAGAS
DEVELOPERpythonfrom ragas.testset.generator import TestsetGenerator from ragas.testset.evolutions import simple, reasoning, multi_context from langchain_community.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter # Charger les documents loader = DirectoryLoader("./documents/", glob="**/*.md") documents = loader.load() # Découper en chunks splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) chunks = splitter.split_documents(documents) # Générer le dataset de test generator = TestsetGenerator.from_langchain( generator_llm=ChatOpenAI(model="gpt-4o-mini"), critic_llm=ChatOpenAI(model="gpt-4o-mini"), embeddings=OpenAIEmbeddings() ) testset = generator.generate_with_langchain_docs( documents=chunks, test_size=50, distributions={ simple: 0.5, reasoning: 0.25, multi_context: 0.25 } ) testset_df = testset.to_pandas() print(testset_df.head())
Structure du dataset généré
| Colonne | Description | Exemple |
|---|---|---|
| question | Question générée | "Comment configurer l'API ?" |
| contexts | Chunks sources | ["Doc API: Pour configurer..."] |
| ground_truth | Réponse attendue | "Créez une clé API dans..." |
| evolution_type | Type de question | simple, reasoning, multi_context |
Pipeline d'évaluation complet
Classe d'évaluation production-ready
DEVELOPERpythonfrom dataclasses import dataclass from datetime import datetime import json @dataclass class EvalConfig: metrics: list llm_model: str = "gpt-4o-mini" batch_size: int = 10 save_results: bool = True output_dir: str = "./eval_results" class RAGASEvaluator: def __init__(self, config: EvalConfig): self.config = config self.llm = ChatOpenAI(model=config.llm_model, temperature=0) self.embeddings = OpenAIEmbeddings() self._configure_metrics() def _configure_metrics(self): for metric in self.config.metrics: metric.llm = LangchainLLMWrapper(self.llm) if hasattr(metric, 'embeddings'): metric.embeddings = LangchainEmbeddingsWrapper(self.embeddings) async def evaluate_rag_system( self, rag_system, eval_dataset: Dataset, version: str = None ) -> dict: questions = eval_dataset["question"] ground_truths = eval_dataset["ground_truth"] answers = [] contexts = [] for question in questions: result = await rag_system.query(question) answers.append(result["answer"]) contexts.append(result["contexts"]) eval_data = { "question": questions, "answer": answers, "contexts": contexts, "ground_truth": ground_truths } dataset = Dataset.from_dict(eval_data) results = evaluate( dataset, metrics=self.config.metrics, llm=self.llm, embeddings=self.embeddings ) output = { "version": version or datetime.now().isoformat(), "timestamp": datetime.now().isoformat(), "sample_count": len(questions), "metrics": { metric.name: float(results[metric.name]) for metric in self.config.metrics }, "per_sample": results.to_pandas().to_dict(orient="records") } if self.config.save_results: self._save_results(output) return output def _save_results(self, results: dict): import os os.makedirs(self.config.output_dir, exist_ok=True) filename = f"eval_{results['version']}.json" filepath = os.path.join(self.config.output_dir, filename) with open(filepath, 'w') as f: json.dump(results, f, indent=2, default=str)
Intégration CI/CD
GitHub Actions
DEVELOPERyamlname: RAG Evaluation on: pull_request: paths: - 'rag/**' - 'prompts/**' schedule: - cron: '0 6 * * 1' jobs: evaluate: runs-on: ubuntu-latest 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 langchain-openai datasets - name: Run RAGAS evaluation env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} run: python scripts/run_ragas_eval.py - name: Check thresholds run: | python -c " import json with open('eval_results/latest.json') as f: results = json.load(f) thresholds = {'faithfulness': 0.8, 'answer_relevancy': 0.75} for metric, threshold in thresholds.items(): if results['metrics'].get(metric, 0) < threshold: exit(1) "
Analyse et debugging
Identifier les samples problématiques
DEVELOPERpythonimport pandas as pd def analyze_failures(results_df: pd.DataFrame, threshold: float = 0.7) -> dict: analysis = {"low_faithfulness": [], "low_relevancy": [], "patterns": {}} low_faith = results_df[results_df["faithfulness"] < threshold] for _, row in low_faith.iterrows(): analysis["low_faithfulness"].append({ "question": row["question"], "answer": row["answer"], "score": row["faithfulness"] }) low_rel = results_df[results_df["answer_relevancy"] < threshold] for _, row in low_rel.iterrows(): analysis["low_relevancy"].append({ "question": row["question"], "score": row["answer_relevancy"] }) return analysis results_df = pd.DataFrame(results["per_sample"]) analysis = analyze_failures(results_df) print(f"Samples avec faible fidélité: {len(analysis['low_faithfulness'])}")
Dashboard de suivi
DEVELOPERpythonclass EvalDashboard: def __init__(self, results_dir: str = "./eval_results"): self.results_dir = Path(results_dir) def load_history(self) -> pd.DataFrame: records = [] for file in self.results_dir.glob("eval_*.json"): with open(file) as f: data = json.load(f) records.append({ "version": data["version"], "timestamp": data["timestamp"], **data["metrics"] }) return pd.DataFrame(records).sort_values("timestamp") def generate_report(self) -> str: df = self.load_history() latest = df.iloc[-1] report = f"# RAG Evaluation Report\n\n## Version: {latest['version']}\n\n" for metric in ["faithfulness", "answer_relevancy", "context_recall"]: report += f"| {metric} | {latest[metric]:.3f} |\n" return report
Bonnes pratiques
Checklist d'évaluation
| Étape | Action | Fréquence |
|---|---|---|
| Dataset | Maintenir 100+ samples représentatifs | Mensuelle |
| Validation | Relire 10% du ground truth | Mensuelle |
| Thresholds | Ajuster selon le domaine | Trimestrielle |
| CI/CD | Bloquer les PR sous les seuils | Chaque PR |
| Monitoring | Tracker les tendances | Hebdomadaire |
Limitations de RAGAS
- Coût LLM : L'évaluation utilise des appels LLM
- Biais du juge : Le LLM évaluateur peut avoir ses propres biais
- Pas de test UX : Ne mesure pas la satisfaction utilisateur réelle
Pour aller plus loin
- Évaluation humaine - Compléter RAGAS par l'humain
- Métriques RAG - Vue d'ensemble des métriques
- Génération RAG - Améliorer les réponses
FAQ
Évaluation automatisée avec Ailog
Implémenter RAGAS demande configuration et maintenance. Avec Ailog, bénéficiez d'une évaluation intégrée :
- Dashboard métriques temps réel
- Alertes sur dégradation de qualité
- Historique des évaluations
- Suggestions d'amélioration automatiques
- Intégration CI/CD préconfigurée
Testez gratuitement et mesurez la qualité de votre RAG sans effort.
Tags
Verwandte Artikel
Bewertung eines RAG-Systems: Metriken und Methoden
Umfassender Leitfaden zur Messung der Leistung Ihres RAG: faithfulness, relevancy, recall und automatisierte Evaluations-Frameworks.
RAG-Latenz reduzieren: von 2000 ms auf 200 ms
RAG 10x schneller: Parallele Retrievals, Streaming-Antworten und architekturelle Optimierungen für eine Latenz unter 200 ms.
Caching-Strategien zur Reduzierung von Latenz und RAG-Kosten
Senken Sie die Kosten um 80 %: Implementieren Sie Semantic Caching, Embeddings Caching und Response Caching für ein RAG im Produktiveinsatz.