Skip to main content

rag-eval-toolkit

Python License: MIT

Python toolkit for evaluating RAG (Retrieval-Augmented Generation) pipelines with LLM-as-judge metrics: faithfulness, hallucination, groundedness, relevancy, and more. Local-first via Ollama, with async execution and result caching.

Why this exists

Ragas and DeepEval cover more ground and are the more mature choice for most teams. This toolkit exists for a narrower case: when you want to read and edit the exact judge prompt driving a score, without going through a metrics registry or a hosted dashboard. Every prompt lives in a single readable file under src/rag_eval/metrics/, asks the judge to reason before scoring, and is easy to fork.

It's also local-first: Ollama is a first-class backend, not an afterthought, so you can run a full evaluation without an API key or per-token cost.

If you need the full "RAG Triad" with production tracing, or 50+ metrics with a pytest-native CI story, use TruLens/Phoenix or DeepEval instead. See Limitations before trusting these scores for anything high-stakes.

Installation

# Core (no LLM backends, just the framework)
pip install rag-eval-toolkit

# With a specific backend
pip install rag-eval-toolkit[openai]
pip install rag-eval-toolkit[anthropic]
pip install rag-eval-toolkit[ollama]

# Everything
pip install rag-eval-toolkit[all]

Or from source:

git clone https://gitlab.com/abanoub.rodolf/rag-eval-toolkit.git
cd rag-eval-toolkit
pip install -e ".[all]"

Quick start

Python API

from rag_eval import RAGEvaluator
from rag_eval.backends import OllamaBackend
from rag_eval.metrics import FaithfulnessMetric, HallucinationMetric, GroundednessMetric

backend = OllamaBackend(model="llama3")
evaluator = RAGEvaluator(backend=backend)

evaluator.add_metric(FaithfulnessMetric())
evaluator.add_metric(HallucinationMetric())
evaluator.add_metric(GroundednessMetric())

dataset = [
    {
        "question": "What is RAG?",
        "context": "RAG stands for Retrieval-Augmented Generation. It retrieves relevant documents and uses them to ground LLM responses.",
        "answer": "RAG is a technique that retrieves documents to ground AI responses.",
    }
]

results = evaluator.evaluate(dataset)
print(results["averages"])
# {'faithfulness': 0.92, 'hallucination': 0.95, 'groundedness': 0.88}

A sample that fails to score (backend error, or a judge response with no parseable score) is excluded from averages rather than counted as a 0.0. Check results["errors"] for per-metric failure counts and results["per_sample"] for which samples came back None.

CLI

# Generate a config template
rag-eval init

# Run evaluation from config
rag-eval run --config eval_config.yaml

# Run with CLI flags
rag-eval run --dataset data.jsonl --backend ollama --model llama3

# Point a self-hosted backend at a non-default server
rag-eval run --dataset data.jsonl --backend ollama --base-url http://192.168.1.20:11434

# List available metrics
rag-eval metrics

# Measure judge test-retest reliability (self-consistency, not accuracy)
rag-eval reliability --dataset data.jsonl --backend ollama --model llama3 --runs 5

Metrics

13 evaluation metrics, each returning a float from 0.0 (worst) to 1.0 (best).

RAG quality (LLM-as-judge)

Metric What it measures Required fields
faithfulness Fraction of answer claims supported by the context question, context, answer
hallucination Presence of claims not in (or contradicting) the context question, context, answer
groundedness NLI-style entailment check, context as premise context, answer
context_precision Retrieved context relevance, rank-aware if context is a chunk list question, context
context_recall Ground-truth coverage in the context, statement-level question, context, ground_truth
context_utilization How much of the retrieved context was actually used question, context, answer
answer_relevancy Does the answer address the question? question, answer
completeness Does the answer cover every part of the question? question, answer
chunk_attribution Are claims attributed to the right source chunk? context, answer

faithfulness, hallucination, and groundedness ask a version of the same underlying question under the terminology different frameworks use for it (Ragas, DeepEval/Galileo, and TruLens/Azure AI, respectively). Keep the one whose name matches what you're used to; running all three on the same sample is redundant.

Answer quality (LLM-as-judge)

Metric What it measures Required fields
coherence Is the answer logically structured? answer
conciseness Is the answer free of filler? answer
toxicity Coarse safety/bias screen, not a moderation classifier answer

Classical (no LLM needed)

Metric What it measures Required fields
semantic_similarity Embedding cosine similarity answer, ground_truth

semantic_similarity requires a backend with embed(). OpenAIBackend and AnthropicBackend don't implement it; use OllamaBackend, GeminiBackend, or LiteLLMBackend.

Backends

Backend Provider Default model Install
OpenAIBackend OpenAI gpt-5.1 pip install rag-eval-toolkit[openai]
AnthropicBackend Anthropic (Claude) claude-sonnet-5 pip install rag-eval-toolkit[anthropic]
OllamaBackend Local models (llama3, mistral) llama3 pip install rag-eval-toolkit[ollama]
GeminiBackend Google Gemini gemini-2.5-flash pip install rag-eval-toolkit[gemini]
LiteLLMBackend 100+ providers via LiteLLM gpt-5.1 pip install rag-eval-toolkit[litellm]

Dataset format

Each item in your dataset is a dictionary. Required keys depend on which metrics you use (see table above). A typical item:

{
    "question": "What is retrieval-augmented generation?",
    "context": "RAG combines retrieval with LLM generation...",
    "answer": "RAG is a technique that...",
    "ground_truth": "RAG retrieves documents and generates grounded answers."  # optional
}

context can also be a list of chunk strings in retrieval order. Passing a list unlocks rank-aware scoring for context_precision; a plain string is scored holistically since there's no chunk boundary or rank to weight.

Supported formats: JSON, JSONL, CSV.

Features

  • Async execution: Metrics are scored in parallel using asyncio + thread pool, capped by max_concurrency (default 20)
  • Result caching: SQLite-backed cache keyed on (metric, model, input hash), opt-in via cache_path
  • YAML config: Reproducible evaluation runs via eval_config.yaml
  • HTML reports: Visual report generation, zero extra deps
  • Rich CLI output: Colored tables, progress bars, clear error messages
  • Honest failure modes: a judge response with no parseable score raises rather than silently scoring 0.0; RAGEvaluator tracks and reports these separately from real low scores

Custom metrics

from rag_eval.metrics.base import BaseMetric

class MyMetric(BaseMetric):
    def __init__(self):
        super().__init__(name="my_metric")

    def score(self, row, backend) -> float:
        prompt = f"Evaluate this answer: {row['answer']}\nScore 0.0-1.0:"
        response = backend.generate(prompt)
        try:
            return max(0.0, min(1.0, float(response.strip())))
        except ValueError:
            return 0.0

Limitations

  • Judge-to-human agreement has not been measured for this toolkit. The Ragas paper reports 95%/78%/70% agreement with human annotators for faithfulness/answer relevancy/context relevance on their own WikiEval benchmark; that number is theirs, not ours. Nothing here has been validated against a human-labeled dataset. Treat scores as a fast, cheap signal for regression detection, not as ground truth. If you need a validated signal, budget for a small human-labeled sample and check your own judge-human agreement before relying on it, or use rag-eval reliability to at least confirm the judge is self-consistent first.
  • LLM judges have well-documented biases: verbosity bias (rating longer answers higher regardless of quality) and self-preference bias (rating a model's own outputs more favorably) are the most relevant ones for single-response scoring like this toolkit does. Position bias mostly affects pairwise comparison setups, which this toolkit doesn't do.
  • Several metrics (faithfulness, answer_relevancy, context_precision, context_recall) implement a single-call simplification of the Ragas/DeepEval definitions rather than a full claim-extraction pipeline. Where the simplification is significant, it's documented in the metric's module docstring.
  • toxicity is a single LLM judge call, not a dedicated moderation classifier. Don't use it as the only safety gate in front of production traffic.

Architecture

src/rag_eval/
    __init__.py          # Package root, version
    evaluator.py          # Core orchestrator (sync + async)
    reliability.py        # Judge test-retest measurement
    cli.py                # Click CLI (init, run, metrics, reliability)
    backends/              # LLM provider integrations
        base.py            # BaseBackend abstract class
        openai_backend.py
        anthropic_backend.py
        ollama_backend.py
        gemini_backend.py
        litellm_backend.py
    metrics/                # Evaluation metrics
        base.py             # BaseMetric, shared judge-prompt builder and score parser
        faithfulness.py
        relevancy.py
        hallucination.py
        groundedness.py
        context_precision.py
        context_recall.py
        ... (13 total)
    report/                # HTML report generation
    utils/                 # Caching, dataset loaders, helpers

Contributing

PRs welcome. Open an issue first to discuss major changes. Run PYTHONPATH=src pytest tests/ -v before submitting.

Author

Abanoub Rodolf Boctor - GitLab - LinkedIn

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rag_eval_toolkit-3.0.0.tar.gz (48.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rag_eval_toolkit-3.0.0-py3-none-any.whl (39.9 kB view details)

Uploaded Python 3

File details

Details for the file rag_eval_toolkit-3.0.0.tar.gz.

File metadata

  • Download URL: rag_eval_toolkit-3.0.0.tar.gz
  • Upload date:
  • Size: 48.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for rag_eval_toolkit-3.0.0.tar.gz
Algorithm Hash digest
SHA256 80431e377f42638175d45fc686e279678963256cb0051951423172b622616f79
MD5 20bc2a195cbce5548196e0c3dfbb7c4e
BLAKE2b-256 5d144b808b8c41069c04847464e5ee0cd6cf0539f2de4cdad9f0ce4ce0607233

See more details on using hashes here.

File details

Details for the file rag_eval_toolkit-3.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rag_eval_toolkit-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6731e63986037a2109996ecacef9c0539d87eb3d0a5023d3afaffa25675c45dd
MD5 27d3b56f9475ec480044ed4e9344067e
BLAKE2b-256 554c90dd3f10e09d6aa611adedffc8db11700fc8e74e46ac4355cdc6f2de36ea

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page