How to evaluate rerankers

Evaluation · ~8 min read ·

Public BEIR scores are a starting point, not a verdict. A reranker that wins on English news may flop on your support tickets. You need a small labelled set of real queries and two metrics: NDCG@k (ranking quality) and MRR (is the best answer near the top?).

Build a labelled query set

Pull 30–100 real queries from logs (anonymised). For each query, mark which document IDs are relevant (binary is enough to start). Store as JSON:

{
  "q-001": {
    "query": "How do I reset my API key?",
    "relevant": ["doc-42", "doc-108"]
  }
}

Thirty queries with one gold document each is enough to see whether reranking beats retrieval-only — you’re measuring relative lift, not publishing a leaderboard.

Metrics that matter

MetricWhat it tells youTypical k
NDCG@kRewards putting highly relevant docs at the top; graded relevance if you have it5 or 10
MRRHow high the first relevant doc ranks — great for single-answer RAG
Recall@kIs the right doc in the shortlist at all? Diagnoses retrieval, not reranker50–100

Run metrics before and after reranking on the same retrieved candidates. If NDCG@5 jumps but Recall@50 is low, your problem is retrieval — reranking can’t invent missing chunks.

Evaluation protocol

  1. Fix a retrieval pipeline (vector-only or hybrid) and log top-50 candidates per query.
  2. Score baseline: order as retrieved (or bi-encoder scores).
  3. Apply reranker A, measure NDCG@5 and MRR.
  4. Swap reranker B (different model or hosted API), repeat.
  5. Track latency p50/p95 alongside quality — a 2-point NDCG gain may not justify 400 ms.

Python with ranx

from ranx import Qrels, Run, evaluate

qrels = Qrels.from_file("qrels.json")      # ground truth
run_before = Run.from_file("retrieve.json")
run_after = Run.from_file("rerank.json")

for name, run in [("retrieve", run_before), ("rerank", run_after)]:
    print(name, evaluate(qrels, run, ["ndcg@5", "mrr@10"]))

ir-measures and BEIR’s evaluator work too. The important part is consistent qrels and the same candidate pool — not which library you pick.

Comparing rerankers

Use the model comparison table for ballpark BEIR numbers, then validate on your labelled set. Hosted APIs (Cohere, Jina, Voyage) are fastest to A/B; open models (bge, mxbai) need GPU for fair latency comparison.

Regression tests: check eval metrics into CI. When you change chunk size, embedding model, or reranker version, re-run the same JSON qrels — quality drops should block deploys.

Build intuition before you benchmark

Use the live demo to see how a cross-encoder reorders a hand-picked shortlist — then scale up with labelled queries.

Try the demo →

Keep reading