Spaces:
Runtime error
Runtime error
| """End-to-end RAG evaluation demo. | |
| This script shows the full workflow: | |
| 1. Build a real RAG system on a knowledge base document | |
| 2. Run it against a curated dataset of questions | |
| 3. Evaluate every answer with 8 quality metrics | |
| 4. Save results to the database | |
| 5. Print a summary table | |
| Run with: | |
| python examples/rag_eval.py | |
| Optional flags: | |
| python examples/rag_eval.py --doc data/knowledge_base.txt | |
| python examples/rag_eval.py --doc my_report.pdf --name my-rag-v2 | |
| """ | |
| import asyncio | |
| import argparse | |
| import json | |
| import sys | |
| from pathlib import Path | |
| # Add src to path | |
| sys.path.insert(0, str(Path(__file__).parent.parent / "src")) | |
| from rich.console import Console | |
| from rich.table import Table | |
| from rich.panel import Panel | |
| from eval_framework.config import get_settings, configure_logging | |
| from eval_framework.rag.pipeline import RAGPipeline | |
| from eval_framework.judges.pipeline import EvaluationPipeline | |
| from eval_framework.storage.database import EvalDatabase | |
| from eval_framework.types import QAPair | |
| from eval_framework.utils.llm_client import get_llm_client | |
| from eval_framework.evaluators import ( | |
| FaithfulnessEvaluator, | |
| RelevanceEvaluator, | |
| CompletenessEvaluator, | |
| HallucinationRateEvaluator, | |
| LatencyEvaluator, | |
| CostEvaluator, | |
| ) | |
| from eval_framework.evaluators.conciseness import ConcisenessEvaluator | |
| from eval_framework.evaluators.coherence import CoherenceEvaluator | |
| configure_logging() | |
| console = Console() | |
| def build_evaluators(model_name: str): | |
| """Build the set of evaluators to run.""" | |
| client = get_llm_client("groq") | |
| return [ | |
| FaithfulnessEvaluator(client, model_name), | |
| RelevanceEvaluator(client, model_name), | |
| CompletenessEvaluator(client, model_name), | |
| HallucinationRateEvaluator(client, model_name), | |
| ConcisenessEvaluator(client, model_name), | |
| CoherenceEvaluator(client, model_name), | |
| LatencyEvaluator(model_name=model_name), | |
| CostEvaluator(model_name=model_name), | |
| ] | |
| async def main(doc_path: str, dataset_path: str, system_name: str, concurrency: int): | |
| settings = get_settings() | |
| if not settings.groq_api_key: | |
| console.print("[red]GROQ_API_KEY not set in .env[/red]") | |
| return | |
| # ββ Step 1: Build the RAG system ββββββββββββββββββββββββββββββββββββββββββ | |
| console.print(Panel( | |
| f"Document: [cyan]{doc_path}[/cyan]\n" | |
| f"Dataset: [cyan]{dataset_path}[/cyan]\n" | |
| f"System: [cyan]{system_name}[/cyan]", | |
| title="RAG Evaluation", | |
| expand=False, | |
| )) | |
| with console.status("[bold green]Building RAG index..."): | |
| rag = RAGPipeline( | |
| doc_path=doc_path, | |
| chunk_size=500, | |
| chunk_overlap=75, | |
| top_k=3, | |
| model_name=settings.groq_model, | |
| ).build() | |
| console.print("[green]RAG pipeline ready[/green]") | |
| # ββ Step 2: Load dataset βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with open(dataset_path) as f: | |
| raw_data = json.load(f) | |
| dataset = [ | |
| QAPair( | |
| question=item["question"], | |
| answer=item["answer"], | |
| context=item.get("context"), # May be None β RAG will fill this in | |
| ) | |
| for item in raw_data | |
| ] | |
| console.print(f"[green]Loaded {len(dataset)} questions[/green]") | |
| # ββ Step 3: Build evaluators βββββββββββββββββββββββββββββββββββββββββββββββ | |
| evaluators = build_evaluators(settings.groq_model) | |
| console.print(f"[green]{len(evaluators)} evaluators ready[/green]") | |
| # ββ Step 4: Run evaluation βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| pipeline = EvaluationPipeline(evaluators=evaluators, concurrency=concurrency) | |
| console.print( | |
| f"\n[yellow]Running {len(dataset)} questions Γ {len(evaluators)} metrics " | |
| f"(concurrency={concurrency})...[/yellow]" | |
| ) | |
| console.print("[dim]This takes ~2-4 minutes on Groq free tier[/dim]\n") | |
| with console.status("[bold green]Evaluating..."): | |
| report = await pipeline.run( | |
| system=rag.query, | |
| dataset=dataset, | |
| system_name=system_name, | |
| ) | |
| # ββ Step 5: Save to database βββββββββββββββββββββββββββββββββββββββββββββββ | |
| db_path = Path(__file__).parent.parent / "data" / "results.db" | |
| db = EvalDatabase(str(db_path)) | |
| db.save_report(report) | |
| console.print(f"\n[green]Saved report {report.id[:8]}... to {db_path}[/green]") | |
| # ββ Step 6: Print summary ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| table = Table( | |
| title=f"Results: {system_name}", | |
| show_header=True, | |
| header_style="bold magenta", | |
| ) | |
| table.add_column("Metric", style="cyan", min_width=22) | |
| table.add_column("Score", min_width=8) | |
| table.add_column("Rating", min_width=12) | |
| for metric, score in report.summary_scores.items(): | |
| metric_name = metric.value if hasattr(metric, "value") else str(metric) | |
| if score >= 0.8: | |
| rating = "[green]EXCELLENT[/green]" | |
| elif score >= 0.6: | |
| rating = "[yellow]GOOD[/yellow]" | |
| elif score >= 0.4: | |
| rating = "[orange1]FAIR[/orange1]" | |
| else: | |
| rating = "[red]POOR[/red]" | |
| table.add_row(metric_name, f"{score:.3f}", rating) | |
| console.print(table) | |
| console.print( | |
| f"\n[dim]Total cost: ${report.total_cost:.4f} | " | |
| f"Examples: {report.total_examples_evaluated} | " | |
| f"Run ID: {report.id[:8]}[/dim]" | |
| ) | |
| console.print("\n[bold]Open the dashboard to explore results:[/bold]") | |
| console.print(" streamlit run dashboard/app.py") | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description="RAG Evaluation Demo") | |
| parser.add_argument( | |
| "--doc", | |
| default="data/knowledge_base.txt", | |
| help="Path to knowledge base document (.txt or .pdf)", | |
| ) | |
| parser.add_argument( | |
| "--dataset", | |
| default="data/rag_dataset.json", | |
| help="Path to QA dataset JSON", | |
| ) | |
| parser.add_argument( | |
| "--name", | |
| default="rag-langchain-groq", | |
| help="System name for the evaluation report", | |
| ) | |
| parser.add_argument( | |
| "--concurrency", | |
| type=int, | |
| default=2, | |
| help="Max concurrent Groq API calls (2 = safe for free tier)", | |
| ) | |
| args = parser.parse_args() | |
| asyncio.run(main( | |
| doc_path=args.doc, | |
| dataset_path=args.dataset, | |
| system_name=args.name, | |
| concurrency=args.concurrency, | |
| )) | |