Field Log · Entry

Reranker 평가: Candidate Ceiling·nDCG·MRR·Latency·RAG 품질 (9/14)

고정 후보의 Recall 상한에서 MRR와 nDCG, p95 latency, 최종 답변 품질까지 단계별로 검증하는 reranker evaluation funnel

이번 글의 결론

  • Reranker 비교에서는 query별 candidate IDs와 text를 고정해야 first-stage 변화와 model 효과를 분리할 수 있습니다.
  • Recall@N은 후보 상한, MRR은 첫 relevant의 위치, nDCG는 graded relevance와 rank discount, MAP은 여러 relevant의 전반적 순서를 봅니다.
  • 평균 metric 하나만으로 release하지 않습니다. Paired query-level delta, confidence interval, failure slice, p95 latency와 비용을 함께 봅니다.
  • BEIR는 heterogeneous zero-shot, BRIGHT는 reasoning-intensive retrieval, AIR-Bench는 동적·다국어 영역 확장에 유용하지만 어느 것도 내 corpus의 qrel을 대신하지 않습니다.
  • RAG에서는 topical relevance gain이 answer correctness·support·citation으로 이어지는지 end-to-end로 확인해야 합니다.

앞 글에서 학습 objective를 만들었습니다. 이제 “새 reranker가 좋아졌다”는 문장을 어떤 증거로 뒷받침할지 정합니다.

Stage 1 ceiling
  gold가 candidate 안에 있는가?

Stage 2 ranking
  relevant evidence를 위로 올렸는가?

Stage 3 selection
  충분하고 중복 없는 context를 골랐는가?

Stage 4 generation
  답이 맞고 근거가 지지하는가?

단계별 metric을 섞으면 첫 실패 지점을 찾을 수 없습니다.


1. Frozen Candidate Replay를 만든다

같은 query에 model A는 BM25 top-100, model B는 hybrid top-100을 받았다면 차이는 reranker만의 효과가 아닙니다.

평가 artifact를 먼저 저장합니다.

{
  "query_id": "q-17",
  "query": "Orion S2 승인된 emergency shutdown 온도",
  "candidate_source": "hybrid-rrf-v6",
  "corpus_version": "support-corpus-v181",
  "candidates": [
    {
      "document_id": "manual-s1-v3",
      "document_version": "sha256:...",
      "text": "...",
      "retrieval_rank": 1,
      "retrieval_score": null,
      "relevance_grade": 0
    }
  ]
}

Model마다 이 파일을 replay합니다.

same query
same candidate IDs
same candidate text bytes
same qrels
same top-k metric implementation
different reranker only

Document ID만 저장하고 evaluation 때 최신 corpus text를 fetch하면 content drift가 들어갑니다. Content hash나 snapshot을 보존합니다.

2. Candidate Recall은 Reranker가 바꿀 수 없다

Binary gold set을 G_q, top-N candidate를 C_q^N이라 하겠습니다.

Hit@N(q) = 1 if G_q ∩ C_q^N ≠ ∅ else 0
Recall@N = mean_q Hit@N(q)

Multi-evidence coverage는 다음처럼 봅니다.

Coverage@N(q) = |G_q ∩ C_q^N| / |G_q|

Candidate set을 고정했다면 reranker 전후 Recall@N은 동일해야 합니다. Rerank 후 top-k recall은 바뀔 수 있지만 그것은 Recall@k after reranking입니다.

명칭을 구분합니다.

candidate_recall_at_100
reranked_recall_at_5

3. Oracle Ceiling을 계산한다

Candidate 안에서 qrel grade 순으로 완벽하게 정렬한 결과를 oracle이라고 합시다.

oracle ranking = sort candidates by true relevance grade

이 candidate set에서 가능한 oracle nDCG@k가 1보다 작을 수 있습니다. Ideal ranking의 gold가 candidate에 없기 때문입니다.

두 가지 denominator convention을 구분합니다.

  1. Candidate-relative IDCG: candidate 안의 label만 이상적으로 정렬
  2. Corpus/qrel-relative IDCG: 전체 known relevant set을 기준으로 이상적 정렬

첫 방식은 reranker ordering 능력을 분리하고, 둘째는 end-to-end candidate miss까지 반영합니다. Report에 convention을 명시합니다.

reranker headroom
  = oracle_metric_on_candidates - current_metric

Headroom이 거의 없으면 더 큰 reranker보다 retriever·qrel·context selection을 볼 차례입니다.

4. Precision@k와 Recall@k

Binary relevance에서:

Precision@k = relevant in top-k / k
Recall@k    = relevant in top-k / all known relevant

RAG context 5개 중 실제 유용한 passage 비율을 볼 때 Precision@5가 직관적입니다. 하지만 relevant가 하나뿐인 dataset에서는 상한이 1/5라 해석이 달라질 수 있습니다.

Success@k 또는 Hit@k는 top-k에 relevant가 하나라도 있는지 봅니다.

Success@k(q) = 1 if top-k ∩ G_q ≠ ∅ else 0

5. MRR: 첫 Relevant가 얼마나 빨리 나오는가

Query q의 첫 relevant rank를 r_q라 하면:

RR(q) = 1 / r_q
MRR   = mean_q RR(q)

예:

first relevant rank 1 → 1.0
first relevant rank 2 → 0.5
first relevant rank 5 → 0.2
no relevant in cutoff → 0

MRR은 첫 relevant 뒤의 순서를 보지 않습니다. 답 하나만 있으면 충분한 navigation·QA에는 유용하지만 multiple evidence quality에는 부족합니다.

6. AP와 MAP: 여러 Relevant의 전반적 순서

Relevant를 만날 때마다 그 위치의 Precision을 평균합니다.

AP(q)
  = (1 / |G_q|) Σ_{r=1}^{k} Precision@r × rel(r)

MAP = mean_q AP(q)

첫 relevant뿐 아니라 두 번째·세 번째 relevant가 위에 오는지도 반영합니다. Unjudged와 cutoff, denominator convention을 명시합니다.

7. DCG와 nDCG: Graded Relevance와 Rank Discount

한 convention은 다음과 같습니다.

DCG@k = Σ_{r=1}^{k} (2^rel_r - 1) / log2(r + 1)
nDCG@k = DCG@k / IDCG@k

Grade 3을 grade 2보다 크게 보며, 같은 grade라도 앞 rank에 더 큰 가치를 줍니다.

예를 들어 grade sequence가:

Run A: [3, 0, 2, 0, 1]
Run B: [2, 3, 0, 1, 0]

둘 다 relevant 수는 같지만 top position과 grade가 달라 nDCG가 다릅니다.

Python 구현

import math


def dcg_at_k(grades: list[int], k: int) -> float:
    return sum(
        (2.0 ** grade - 1.0) / math.log2(rank + 1)
        for rank, grade in enumerate(grades[:k], start=1)
    )


def ndcg_at_k(grades: list[int], k: int) -> float:
    actual = dcg_at_k(grades, k)
    ideal = dcg_at_k(sorted(grades, reverse=True), k)
    return 0.0 if ideal == 0.0 else actual / ideal

이 구현은 주어진 candidate grade list 내부에서 IDCG를 만듭니다. Corpus 전체 qrel denominator가 필요하면 별도 ideal grades를 인자로 받습니다.

8. Unjudged는 0이 아니다

TREC-style pooling에서는 top result 일부만 사람이 판단합니다. 강한 새 model이 기존 pool 밖의 relevant document를 올리면 unjudged일 수 있습니다.

unjudged document
≠ known irrelevant document

Unjudged를 0으로 처리하면 novel result를 벌줄 수 있습니다.

대응:

  • Pool을 확장해 top unjudged를 재판정합니다.
  • Judged-only metric과 standard metric을 함께 봅니다.
  • bpref 같은 incomplete judgment 대응 metric을 검토합니다.
  • Unjudged rate@k를 report합니다.
  • Model별로 top unjudged 비율이 다른지 확인합니다.

Teacher가 만든 synthetic qrel도 human qrel과 같은 것으로 숨기지 않습니다.

9. Query-level Paired Delta를 본다

평균 nDCG 하나만 보면 일부 query의 큰 gain이 많은 regression을 가릴 수 있습니다.

Δ_q = metric_new(q) - metric_baseline(q)

Report:

  • mean·median delta
  • improved / tied / regressed query count
  • percentile of delta
  • worst regressions
  • slice별 mean delta
improved: 412
tied:     361
regressed:227

Traffic-weighted 결과와 macro query 평균을 모두 봅니다.

10. Confidence Interval과 Significance

Query가 sampling unit이므로 query-level paired bootstrap을 사용할 수 있습니다.

for b in 1...B:
  sample query IDs with replacement
  compute mean(metric_new - metric_base)

CI = percentiles of bootstrap deltas

간단한 Paired Bootstrap

import numpy as np


def paired_bootstrap_ci(
    baseline: np.ndarray,
    challenger: np.ndarray,
    *,
    samples: int = 10_000,
    seed: int = 17,
) -> tuple[float, float, float]:
    if baseline.shape != challenger.shape:
        raise ValueError("paired arrays must have the same shape")

    rng = np.random.default_rng(seed)
    deltas = challenger - baseline
    n = len(deltas)
    draws = rng.integers(0, n, size=(samples, n))
    means = deltas[draws].mean(axis=1)
    low, high = np.quantile(means, [0.025, 0.975])
    return float(deltas.mean()), float(low), float(high)

Confidence interval이 0을 넘는다고 제품 가치가 자동으로 크다는 뜻은 아닙니다. Effect size와 latency·cost를 함께 봅니다. 여러 model과 metric을 반복 비교하면 multiple comparison 문제도 생깁니다.

11. Slice Evaluation이 평균보다 중요할 때

최소 slice 예시:

language:
  - ko
  - en
  - ko_en_code_switch
intent:
  - exact_id
  - troubleshooting
  - temporal
  - comparison
  - multi_hop
document:
  - short_text
  - long_policy
  - table
  - ocr
  - code
failure:
  - wrong_entity
  - wrong_attribute
  - outdated
  - contradiction
  - partial_evidence

전체 nDCG가 올라도 최신 정책 query가 나빠지면 release하지 않을 수 있습니다. Critical slice에는 regression budget을 따로 둡니다.

12. Benchmark를 목적에 맞게 쓴다

MS MARCO·TREC Deep Learning

Passage ranking의 대표 in-domain training·evaluation 자원입니다. 많은 reranker가 MS MARCO로 학습되므로 강한 baseline 비교에 유용하지만, 영어 web passage와 target 한국어 domain 사이의 차이를 인지해야 합니다.

BEIR

서로 다른 domain과 retrieval task를 모아 zero-shot generalization을 평가합니다. 원 연구는 18개 공개 dataset을 선정해 lexical·dense·sparse·late-interaction·reranking model을 비교했습니다. 평균 하나뿐 아니라 dataset별 결과를 봅니다.

BRIGHT

표면 keyword·semantic similarity를 넘어 reasoning이 필요한 현실 query를 겨냥합니다. ICLR 2025 논문은 경제·심리·수학·코딩 등 1,398개 query를 구성했고, 당시 강한 general retrieval model도 크게 어려워함을 보였습니다. Reasoning reranker를 볼 때 유용하지만 일반 FAQ traffic 전체를 대표하지 않습니다.

AIR-Bench

LLM 기반 자동 data generation으로 task·domain·language를 동적으로 확장하는 heterogeneous benchmark입니다. Emerging domain을 빠르게 점검하는 데 유용하지만 synthetic judgment pipeline 자체를 검증해야 합니다.

MTEB Reranking·Retrieval Tasks

다국어·다양한 task를 공통 framework에서 실행하기 쉽습니다. 현재 MTEB 문서는 reranking task와 two-stage reranking 사용법을 제공합니다. Leaderboard 평균 대신 내 language·domain·document length와 가까운 task를 고릅니다.

MIRACL 등 Multilingual Retrieval

한국어를 포함한 multilingual retrieval transfer를 볼 수 있지만 first-stage retrieval benchmark와 reranker-only evaluation을 구분합니다. 같은 candidate set으로 다시 구성해야 reranker 효과만 볼 수 있습니다.

13. Benchmark Score를 Model 선택표로 바로 쓰지 않는다

Leaderboard 차이에는 다음이 섞일 수 있습니다.

  • first-stage candidate model
  • rerank depth
  • query instruction
  • document truncation
  • model revision·precision
  • evaluation qrel version
  • dataset contamination
  • score aggregation
  • hardware·batching

“평균 1등” model이 내 pipeline에서 1등일 근거는 없습니다.

가장 안전한 순서:

public benchmark로 후보 model shortlist
→ frozen in-domain candidates로 offline bake-off
→ shadow traffic
→ guarded online experiment

14. Efficiency Evaluation은 재현 조건을 고정한다

Latency를 잴 때 기록할 값:

hardware:
  gpu: exact model and memory
  driver: version
  runtime: torch/cuda/serving-engine versions
model:
  revision: pinned
  dtype: bf16
  quantization: none
traffic:
  candidate_depth: 50
  pair_token_p50: 180
  pair_token_p95: 472
  concurrency: [1, 8, 32]
batcher:
  max_batch_tokens: 8192
  max_wait_ms: 4
measurement:
  warmup_requests: 200
  measured_requests: 5000

분해할 Latency

end-to-end rerank latency
  = queue
  + serialization / network
  + tokenization
  + model compute
  + parsing / sort

API model은 provider network와 rate limit을 포함합니다. Local model과 pure compute만 비교하지 않습니다.

Throughput와 Tail

  • requests/s
  • pairs/s
  • input tokens/s
  • p50/p95/p99
  • timeout·retry rate
  • GPU memory peak
  • cost per 1k queries

Average latency가 낮아도 long document 때문에 p99가 SLO를 넘을 수 있습니다.

15. Quality–Cost Pareto Frontier

Model A가 B보다 quality도 낮고 latency도 높으면 dominated입니다. 그렇지 않으면 trade-off입니다.

             high quality

     large LLM    ●

   cross-encoder ●
 small reranker ●
                  └────────→ high cost / latency

Candidate depth, max length, quantization, cascade policy도 각각 한 점입니다.

Release decision은 단일 model보다 configuration을 고릅니다.

configuration
  = model
  + candidate depth
  + max length
  + batch policy
  + fallback
  + threshold

16. RAG End-to-End Metric

Reranker nDCG가 올라도 generator가 이미 정답을 알거나, context를 무시하거나, relevant passage가 답을 직접 지지하지 않으면 answer는 그대로일 수 있습니다.

평가:

  • answer correctness / exact match / task score
  • claim-level support
  • citation precision·recall
  • unsupported claim rate
  • abstention precision·recall
  • context precision·utilization
  • end-to-end latency·token cost

2×2 Ablation

Retriever candidates + no reranker
Retriever candidates + reranker

각각에 대해:
  fixed generator
  fixed context budget
  fixed prompt

Generator·prompt·top-k를 동시에 바꾸지 않습니다.

17. Online Evaluation

검색 UI라면 click·task success·reformulation·time-to-resolution을 볼 수 있습니다. RAG assistant라면 answer acceptance·escalation·citation open·resolution rate가 더 적절할 수 있습니다.

Guardrail

  • ACL violation은 0 허용
  • Critical stale document rate
  • p95/p99 SLO
  • empty result·timeout
  • user segment fairness
  • query abandonment

Interleaving은 두 ranked list를 섞어 어느 쪽 결과가 선호되는지 더 민감하게 비교하는 방법입니다. 하지만 RAG generator가 하나의 context set으로 합성하면 search interleaving을 그대로 적용하기 어렵습니다.

18. Evaluation Report Template

evaluation:
  id: rerank-eval-2026-07-20-09
  queries: support-eval-v8
  qrels: support-qrels-v11
  candidates: hybrid-v6-top100-frozen
  corpus_snapshot: support-corpus-v181
  idcg_convention: corpus_qrels
  systems:
    - no_rerank
    - cross_encoder_small
    - cross_encoder_large
    - llm_listwise
  ranking_metrics:
    - candidate_recall_at_100
    - mrr_at_10
    - map_at_100
    - ndcg_at_5
    - ndcg_at_10
  uncertainty:
    method: paired_bootstrap
    samples: 10000
    seed: 17
  efficiency:
    concurrency: [1, 8, 32]
    percentiles: [50, 95, 99]
  rag_metrics:
    - answer_correctness
    - claim_support
    - citation_precision

19. Release 체크리스트

  • Candidate text snapshot과 qrels를 고정했다.
  • Candidate Recall과 reranked top-k metric을 구분했다.
  • IDCG·unjudged·cutoff convention을 기록했다.
  • Query-level paired delta와 confidence interval이 있다.
  • Critical slice regression budget을 통과했다.
  • Long document·한국어·no-answer·multi-hop slice를 본다.
  • p95/p99, throughput, token, cost를 실제 concurrency에서 측정했다.
  • Public benchmark와 in-domain 결과를 구분했다.
  • Fixed generator에서 end-to-end RAG gain을 확인했다.
  • Online guardrail과 rollback threshold가 있다.

스스로 확인하기

  1. Reranker 비교에서 candidate text까지 freeze해야 하는 이유는 무엇인가?
  2. MRR과 nDCG는 multiple graded relevant document를 어떻게 다르게 취급하는가?
  3. Candidate-relative IDCG와 corpus-relative IDCG의 차이는 무엇인가?
  4. Unjudged document를 모두 0으로 두면 새 model이 불리할 수 있는 이유는 무엇인가?
  5. Offline nDCG gain이 RAG answer gain으로 이어지는지 검증하는 가장 단순한 ablation은 무엇인가?

다음 글에서는 public leaderboard를 넘어 한국어·도메인·긴 문서·API·local serving 조건에 맞는 model shortlist와 bake-off를 설계합니다.

참고자료