Generated banner for RAG Eval
Generated logo for RAG Eval

RAG Eval

NVIDIAOfficialCreated by NVIDIA RAG

  • Skill
  • Review and audit
  • Software development
  • Apache-2.0
  • Medium risk

From the author

Filesystem RAG benchmarks: corpus/, train.json, evaluate_rag.py (RAGAS quality). Not for prod monitoring, latency/throughput benchmarking (use rag-perf), or evals outside this repo layout.
— the description by NVIDIA RAG

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured approach to evaluating RAG (Retrieval-Augmented Generation) pipeline quality using the NVIDIA RAG Blueprint framework. It utilizes a specific filesystem layout consisting of a corpus directory and a train.json file to run automated evaluations via the evaluate_rag.py script. The process leverages RAGAS metrics to assess accuracy, context relevance, and groundedness, allowing developers to tune retrieval and generation parameters for optimal performance.

What it does

  • Automates RAG quality evaluation using RAGAS metrics.
  • Supports tuning of retrieval parameters like top_k and vdb_top_k.
  • Enables configuration of generation settings such as temperature and max-tokens.
  • Provides structured JSON output for headline metrics and per-query forensics.
  • Includes troubleshooting guidance for common ingestion and evaluation errors.
  • Facilitates comparative analysis of different pipeline configurations.

When to use it

  • When you need to measure the quality of your RAG pipeline's responses.
  • When comparing different retrieval or generation settings for your RAG system.
  • When you have prepared a dataset following the required corpus and train.json structure.
  • When you need to perform forensic analysis on specific query failures.

Advantages

  • Standardized evaluation workflow within the NVIDIA RAG Blueprint ecosystem.
  • Clear separation between quality evaluation and performance benchmarking.
  • Detailed per-query data for deep-dive analysis of retrieval and generation.
  • Flexible configuration for testing various RAG pipeline parameters.

Usage examples

“Run a full RAG evaluation on my dataset located at /data/my_rag_test.”
The agent will execute the evaluation script using the provided dataset path, host, and port, generating RAGAS metrics and summary reports in the results directory.
“How can I compare the impact of different top_k settings on my RAG quality?”
The agent will guide you to adjust the --top_k and --vdb_top_k flags in the evaluation command to perform comparative runs and analyze the resulting RAGAS scores.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/nvidia/rag-eval/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip rag-eval.zip -d .agents/skills

Documentation by NVIDIA RAG

On-disk RAG evaluation (corpus/ + train.json)

Purpose

Guide agents through NVIDIA RAG Blueprint filesystem benchmarks: preparing corpus/ and train.json, running scripts/eval/evaluate_rag.py, tuning retrieval and generation flags for quality comparisons, interpreting RAGAS JSON outputs, and triaging failures (HTTP/stream errors, empty contexts, collection mismatch, judge API).

For latency, throughput, and load testing, use the rag-perf skill (scripts/rag-perf, docs/performance-benchmarking.md) — not this skill.

When not to use

Do not use this skill for: deploying or repairing services (use rag-blueprint); evaluating APIs without the corpus/ + train.json layout; general ML experimentation unrelated to this evaluator; production monitoring/alerting; or latency/throughput benchmarking (use rag-perf).

Prerequisites

  • Repo cloned; run commands from repo root (imports and paths assume this).

  • Python 3.11+ and uv; eval deps: uv sync --project scripts/eval.

  • Reachable RAG server and ingestor (defaults often localhost:8081 / 8082).

  • NVIDIA_API_KEY for RAGAS (see credential hygiene); optional RAG_EVAL_JUDGE_MODEL.

  • Dataset roots passed to --dataset-paths each contain corpus/ and train.json.

Instructions

  1. Prepare data — Ensure each dataset directory matches the layout and train.json rules in references/dataset-and-conversion.md. When sources arrive as public links (sites or dataset pages), materialize documents under corpus/—prefer PDF for multimodal content so images stay embedded; convert CSV/JSONL/etc. using the patterns there.

  2. Run eval — uv run --project scripts/eval python scripts/eval/evaluate_rag.py with --dataset-paths, --host, and --port. See references/benchmark-execution.md for command examples, outputs, and errors. Use references/evaluate-rag-cli.md for flag-level detail.

  3. Tune quality — Adjust --top_k / --vdb_top_k, reranker and query-rewriting toggles, and generation overrides (--temperature, --top-p, --max-tokens) as documented in references/benchmark-execution.md when comparing retrieval/generation configs for RAGAS scores.

  4. Analyze results — Use references/result-analysis.md for scripts; scan rag_*_evaluation_summary.json for headline RAGAS metrics.

  5. Triage errors — Use the error signal table and the Troubleshooting section below.

Examples

Set API key without putting secrets in shell history (preferred patterns): load from a gitignored env file or secrets manager; avoid committing .env; rotate keys if exposed. Details: references/benchmark-execution.md#credential-hygiene-nvidia_api_key.

Minimal eval (key already in environment):

uv sync --project scripts/eval
uv run --project scripts/eval python scripts/eval/evaluate_rag.py \
  --dataset-paths /path/to/my_dataset \
  --host localhost \
  --port 8081

Pretty-print summary JSON:

python3 -m json.tool results/my_dataset/rag_my_dataset_evaluation_summary.json

More examples (skip ingestion, quality sweeps): references/benchmark-execution.md.

Limitations

  • Evaluator behavior is fixed to the filesystem contract and evaluate_rag.py; it does not substitute for custom offline judges or non-RAG benchmarks.

  • Vector DB / embedding choices follow deployed ingestor and RAG env — not overridden by this CLI alone.

  • Scores depend on retrieval quality, judge model availability, and NVIDIA_API_KEY; empty contexts yield partial RAGAS metrics (see references).

  • Large procedural detail lives under references/ to keep routing concise; read those files when the user needs step-by-step conversion, full flags, or error tables.

Troubleshooting

Error / signalLikely causeWhat to do
Immediate exit mentioning NVIDIA_API_KEYMissing or invalid keySet key via secure channel; see credential hygiene in references/benchmark-execution.md.
train.json must be a JSON arrayWrong JSON shapeTop-level array of objects; validate per references/dataset-and-conversion.md.
Fewer rows in evaluation_data.json than train.jsonPer-query failuresCheck stderr: network or stream JSON errors; see error table in benchmark-execution.
Empty generated_contexts everywhereRetrieval gapVerify collection, ingestion, top_k / vdb_top_k, and ingestor_server_url without /v1 suffix.
Ingestor 404 on uploadBad ingestor base URLPass http://host:port only — code appends /v1/.

Full signal table: references/benchmark-execution.md#common-error-cases-and-signals.

Gotchas

  • Run from repo root: paths and imports in scripts/eval/evaluate_rag.py assume this; a wrong directory silently breaks imports.

  • --ingestor_server_url: pass http://host:port without /v1—the code appends /v1/ automatically. Including /v1 causes 404s on ingestor calls.

  • Vector DB / embedding settings: not set by this CLI; configure via the deployed ingestor and RAG server env vars (e.g. APP_VECTORSTORE_URL, embedding model).

  • --model / --llm_endpoint: forwarded verbatim only when explicitly set; omit to keep the server's configured LLM.

  • Stale collections: a previous run's ingested data persists unless you use --force_ingestion. Use --collection with a unique name when comparing quality across isolated runs.

  • Empty context metrics: if all generated_contexts are empty, RAGAS scores only nv_accuracy and leaves the other two metrics blank—this is not a silent success.

Source of truth

PieceLocation
Driverscripts/eval/evaluate_rag.py (CORPUS_DIRECTORY = corpus, EVAL_DATA = train.json)
Human README (always in-repo)scripts/eval/README.md
Full CLI (flags, defaults)scripts/eval/evaluate_rag.py --help; references/evaluate-rag-cli.md
Dataset / conversionreferences/dataset-and-conversion.md
Runs, outputs, errorsreferences/benchmark-execution.md
Result analysis scriptsreferences/result-analysis.md
Latency / throughputrag-perf skill, docs/performance-benchmarking.md

Agent playbook

  1. Run eval — uv sync --project scripts/eval then uv run --project scripts/eval python scripts/eval/evaluate_rag.py with required --dataset-paths, --host, and --port (and env NVIDIA_API_KEY). Argument --ingestor_server_url is optional (defaults to http://localhost:8082); pass it only when overriding the ingestor endpoint.

  2. Quality tuning — See references/benchmark-execution.md: --top_k/--vdb_top_k, reranker and query-rewriting toggles, --temperature, --top-p, --max-tokens.

  3. Data conversion — Follow references/dataset-and-conversion.md.

  4. Analyze results — references/result-analysis.md; quick scan: python3 -m json.tool results/<dataset>/rag_<dataset>_evaluation_summary.json.

  5. Error triage — references/benchmark-execution.md#common-error-cases-and-signals.

Files

references/dataset-and-conversion.md

Dataset layout, train.json, and conversion

Load this when shaping corpus/ + train.json or converting external benchmarks.

Dataset layout

Each --dataset-paths entry is a directory containing:

  1. corpus/ — files indexed recursively for ingestion.

  2. train.json — evaluation questions and answers.

train.json schema

The driver accepts a top-level JSON array of objects only. Required per row: question, answer. Optional: id or query_id.

Field rules:

  • id: integer from the source row index. Do not use prefixed strings (e.g. "dataset-0").

  • is_impossible: include as a boolean if the source dataset carries it; use false for benchmarks that have no unanswerable questions.

  • contexts: optional array of objects — one entry per supporting document. filename (required on each object) is the file’s basename under corpus/ exactly as on disk (including any percent-encoding in the name). text is optional: include it when you have a ground-truth span; omit it when you only need to tie the row to corpus files by name (for example multimodal PDFs where no span was curated).

  • Omit benchmark-internal metadata fields (reasoning category labels, source tags, etc.) that are not question, answer, id, is_impossible, or contexts.

[
  {
    "id": 0,
    "question": "...",
    "answer": "...",
    "is_impossible": false,
    "contexts": [
      { "filename": "Article_Title" },
      { "filename": "Another%20Article", "text": "…" }
    ]
  }
]

Multiple context entries per row are allowed. Plain strings (["...", "..."]) remain acceptable for minimal bundles without per-file tagging.

Quick validation
python3 -c "import json,sys; d=json.load(open(sys.argv[1])); assert isinstance(d, list) and all(isinstance(x, dict) for x in d), 'train.json must be a list of objects'" train.json

Run this after any conversion step to catch shape errors before the eval.

Corpus format when converting external benchmarks

Prefer putting sources in corpus/ as PDF. That matches typical production RAG on documents, aligns with the evaluator default --file-type pdf, and unlocks PDF page counts in ingestion metrics.

Eval requires a real corpus/ tree on disk. When the only inputs are public links—dataset landing pages, file listings, paper or supplement URLs, or arbitrary websites—download or render into corpus/ as documents the ingestor can index, do not point the eval at URLs alone.

For multimodal material (figures, tables, charts, photos, diagrams, or screenshots that carry meaning), standardize on PDF as the file format under corpus/ whenever practical so images and layout stay inside the same artifact the retriever will chunk and embed. Goals:

  • Preserve visuals: Use the publisher’s official PDF download or export when it exists. Avoid workflows that rebuild PDFs from plain text only (for example simple text-to-PDF libraries): those often drop graphics and produce a corpus that no longer matches multimodal retrieval expectations.

  • Web-only pages: Prefer full-fidelity print paths (browser print-to-PDF, or headless Chromium / Playwright rendering) so embedded and inline images survive in the PDF. HTML or .txt alone usually discard or isolate visuals from the indexed blob you need side-by-side with questions.

  • One logical source → one primary file: Keep a stable basename under corpus/ and reference that same basename in train.json contexts[].filename (see below). If a source truly splits into separate image files plus text, still align names with how citations and ingestion expose document_name.

After materializing files, pass --file-type to evaluate_rag.py according to what sits under corpus/ (for example keep the default when the corpus is mostly PDF).

Image-heavy web articles: When upstream pages mix text and images, still prefer a PDF export or faithful render over generating PDFs with text-only toolkits. If an API offers binary PDF download, use it before HTML-to-text shortcuts.

If the upstream artifact only gives URLs or document pointers that do not name a concrete file (common in published benchmarks), assume PDF as the target format. Use plain text or HTML only when converting to PDF is impractical; then set --file-type to match what dominates under corpus/.

Each contexts object’s filename must match the actual corpus file basename (same as the file’s name in corpus/, e.g. Report_2023 for corpus/Report_2023 or corpus/subdir/Report_2023). text, when present, should be the reference span or excerpt; when omitted, only the filename association is carried through.

Deriving corpus filenames from URLs

When the benchmark provides a URL per source document, derive the corpus filename and contexts[].filename using this rule — it preserves the source URL's identity exactly and ensures downstream citation matching works:

stem = path_last_segment + "#" + fragment   (if URL has a fragment)
stem = path_last_segment                     (if no fragment)

The file you write under corpus/ must start with stem and follow the same naming pattern as the rest of that dataset so --file-type and document_name from ingestion stay consistent.

Where:

  • path_last_segment = last /-separated component of urllib.parse.urlparse(url).path.

  • Do not call urllib.parse.unquote() on the segment — keep percent-encoding exactly as it appears in the URL.

  • fragment = urllib.parse.urlparse(url).fragment — include verbatim if non-empty.

  • Do not pass the segment through any slug or sanitize function that strips or replaces characters (%, ', ., #, -, non-ASCII bytes, etc.). Any such transformation breaks alignment between the corpus file, the train.json context reference, and the ingestor's document_name.

If the content must be fetched via an API that requires a decoded title (e.g. a REST endpoint that does not accept percent-encoded paths), decode only for that API call: urllib.parse.unquote(path_last_segment). The on-disk filename stays encoded.

Bringing external data into this layout

Benchmarks packaged elsewhere (CSV, JSONL, parquet, archives, APIs, annotation exports, etc.) are not consumed directly. Convert them so each eval root has corpus/ documents and a train.json that follows the schema. Keep corpus/ filenames consistent with how the ingestor and citations surface document_name so retrieval and scoring align.

Conversion checklist:

  1. Normalize source encodings to UTF-8.

  2. train.json: top-level array of objects, each with at minimum question and answer.

  3. id: integer from the source row index — not a prefixed or composite string.

  4. is_impossible: carry over from the source if present; add as false if the benchmark has no unanswerable questions.

  5. Corpus filenames: if derived from URLs, use the stem rule above (raw path last segment + #fragment if any, no decoding, no sanitization).

  6. contexts entries: filename must equal the corpus file basename; text is optional (add when you have a gold span).

  7. Drop any benchmark-internal fields that are not part of the schema (question, answer, id, is_impossible, contexts).

  8. Run the quick train.json validation above after any conversion.

Conversion patterns

JSONL → train.json
import json, pathlib

rows = [json.loads(l) for l in pathlib.Path("source.jsonl").read_text().splitlines() if l.strip()]
train = [{"id": r.get("id"), "question": r["question"], "answer": r["answer"]} for r in rows]
pathlib.Path("my_dataset/train.json").write_text(json.dumps(train, indent=2, ensure_ascii=False))
CSV → train.json
import csv, json, pathlib

with open("source.csv", newline="", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

train = [{"question": r["question"], "answer": r["answer"]} for r in rows]
pathlib.Path("my_dataset/train.json").write_text(json.dumps(train, indent=2, ensure_ascii=False))

Map source column names to question / answer as needed. Add "id" from the source if available to aid per-query traceability.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Declares allowed tools, Needs an API key, Needs Python

The author says: Repository checkout with uv; Python 3.11+; run from repo root; uv sync --project scripts/eval (eval deps live in scripts/eval/pyproject.toml); network to RAG, ingestor, and vdb endpoints; NVIDIA_API_KEY for RAGAS; optional RAG_EVAL_JUDGE_MODEL (default mistralai/mixtral-8x22b-instruct-v0.1).

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA RAG
Publisher
NVIDIA (Official)
Source
NVIDIA/skills · skills/rag-eval · commit fce3cca
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE-APACHE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA RAG or NVIDIA.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download rag-eval.zip