"RAG 핵심 학습 (13/26) — Reranker: Cross-encoder의 역할"

Retriever가 "이 근처가 맞다"를 찾는다면, reranker는 "바로 이 문단이 맞다"를 고른다.

Hybrid Search까지 오면 대체로 좋은 후보군은 손에 들어온다. 하지만 top-20 안에 좋은 문맥이 있어도 top-3 순서가 어긋나면 생성 품질은 크게 흔들린다. Reranker는 query와 candidate chunk를 함께 읽고 관련도를 다시 계산하는 단계다. 이번 글은 bi-encoder retriever와 cross-encoder reranker의 역할 차이, 그리고 retrieve wide → rerank narrow가 왜 실무 표준이 되었는지 설명한다.


0. Prerequisites

  • 10편 Dense Retrieval
  • 12편 Hybrid Search
  • 7편 메타데이터 설계

1. 학습 목표

  1. retriever와 reranker의 차이를 구분한다.
  2. cross-encoder가 왜 더 정확하지만 더 느린지 설명한다.
  3. reranker를 어느 단계에 넣어야 하는지 안다.
  4. top-N 후보 수를 어떻게 정할지 감을 잡는다.

2. 핵심 요약

Retriever는 query와 문서를 각각 임베딩해 빠르게 찾는 bi-encoder 구조다. Reranker는 query와 문서를 한 쌍으로 함께 읽는 cross-encoder 구조라 훨씬 느리지만 더 정확하다. 그래서 실무 표준은 retriever top-50 → reranker top-5 같은 멀티스테이지다. Reranker는 특히 의미는 비슷하지만 질문 의도와 어긋난 후보를 밀어내는 데 강하다. 비용이 비싸므로 전 코퍼스 전체가 아니라 좁혀진 candidate set에만 적용한다.


3. 직관 — 왜 한 번 더 정렬하는가

질문: "사내 보안 정책에서 외부 공유 예외는 누가 승인하는가?"

retriever top-3: 1. 보안 정책 총론 2. 외부 공유 예외 신청 절차 3. 데이터 분류 기준

여기서 1번은 query와 관련 단어가 많아서 올라왔지만, 실제 답은 2번 문서에 있다. reranker는 query와 문서를 함께 읽으며 "누가 승인하는가"라는 질문 중심으로 다시 본다. 그래서 2번을 1위로 끌어올린다.


4. 정의 — reranker의 핵심 용어

용어 정의
Bi-encoder query와 문서를 각각 별도 임베딩해 유사도 계산
Cross-encoder query와 문서를 한 입력으로 함께 넣고 관련도 점수 예측
Candidate Set reranker가 재정렬할 후보 문서 묶음
Top-N / Top-K retriever가 넓게 가져오는 수, reranker가 최종 남기는 수
Relevance Score query-document 쌍의 관련도 점수

5. 메커니즘 — 왜 cross-encoder가 더 강한가

Bi-encoder는 문서를 미리 임베딩해 둘 수 있기 때문에 빠르다. 그러나 query와 문서가 토큰 단위로 직접 상호작용하지 않는다.

Cross-encoder는 보통 다음과 같이 본다.

[CLS] query tokens [SEP] document tokens [SEP]

이때 self-attention이 query 토큰과 document 토큰 사이를 직접 본다. 따라서 "외부 공유", "예외", "승인자" 같은 관계를 문맥 안에서 더 정교하게 읽는다.

수식으로 쓰면, reranker는 대개 다음과 같은 점수를 예측한다.

$$s(q, d) = W^\top h_{\text{[CLS]}}(q, d) + b$$

핵심은 임베딩 두 개의 dot product가 아니라, 쌍 전체를 읽어 얻은 표현이라는 점이다.


6. 원리 워크스루 — retrieve wide, rerank narrow

6.1 최소 파이프라인

query = "사내 보안 정책에서 외부 공유 예외는 누가 승인하는가?"

candidates = retriever.search(query, k=30)
rerank_inputs = [(query, doc.text) for doc in candidates]
scores = reranker.score(rerank_inputs)

ranked = sorted(
    zip(candidates, scores),
    key=lambda x: -x[1]
)
final_contexts = [doc for doc, _ in ranked[:5]]

6.2 모델 예시

from FlagEmbedding import FlagReranker

reranker = FlagReranker("BAAI/bge-reranker-v2-m3", use_fp16=True)
score = reranker.compute_score([
    "외부 공유 예외는 누가 승인하는가?",
    "외부 공유 예외 신청은 부서장과 보안 책임자의 승인을 받아야 한다."
])

6.3 top-N을 왜 너무 크게 잡지 않는가

후보 1,000개를 cross-encoder로 모두 재정렬하면 비용이 급격히 오른다. reranker는 "전체 검색기"가 아니라 "좁혀진 후보의 정밀 정렬기"다.

자기 설명: reranker를 전 코퍼스 전체에 적용하지 않는 이유를 한 문장으로 써 보라.


7. 변형과 사례

7.1 BERT 기반 cross-encoder

무엇이 바뀌는가
query와 문서를 한 입력으로 결합한다.

왜 등장했는가
bi-encoder가 빠르지만 세밀한 문맥 판단에서 한계가 있었기 때문이다.

무엇이 가능해졌는가
질문 의도와 문서 문장을 더 정교하게 맞출 수 있다.

한계와 다음 단계
느리다. 그래서 항상 retriever 뒤에 둔다.

7.2 LLM-as-reranker

LLM에게 후보 10개를 주고 직접 순서를 매기게 할 수도 있다. 하지만 비용과 응답시간이 커서 보통은 실험용이나 고부가가치 질의에서만 쓴다. 운영 기본값은 여전히 작은 cross-encoder다.

7.3 Metadata-aware reranking

본문 텍스트뿐 아니라 최신성, source authority, security level을 함께 반영하는 패턴도 있다. 다만 규칙을 너무 많이 섞으면 reranker가 아니라 규칙 엔진이 되어 버리므로 주의가 필요하다.


8. 한계와 실패 양상

8.1 좋은 후보가 애초에 없으면 reranker도 못 살린다

reranker는 후보 재정렬이지 후보 생성이 아니다. retriever가 답 문서를 top-50 안에 못 넣으면 reranker는 할 일이 없다.

8.2 chunk가 너무 길면 비교 비용이 올라간다

cross-encoder는 query와 chunk를 함께 읽기 때문에 입력 토큰 수에 민감하다. 이 때문에 5편, 6편의 chunking 설계가 중요했다.

8.3 도메인 불일치

법률, 코드, 의료처럼 특수 도메인에서는 일반 reranker가 질문 의도를 충분히 못 읽을 수 있다. 이 경우 도메인 특화 모델 또는 라벨링 데이터가 필요하다.

8.4 다음 단계 — 성능을 재현 가능하게 측정해야 한다

reranker를 넣으면 좋아진 것처럼 보이기 쉽다. 하지만 실제로 얼마나 좋아졌는지는 14편의 평가셋과 15편의 검색 지표로 측정해야 한다.


8.5 입문자가 자주 빠지는 함정 5선

# 함정 증상 빠른 점검
1 reranker가 retriever를 대체한다고 생각 비용 폭증 retriever 뒤에만 배치
2 top-N을 과도하게 크게 설정 latency 급증 20~100 사이에서 측정
3 답 문서 미회수 문제를 reranker로 해결하려 함 성능 개선 없음 retriever recall부터 점검
4 chunk 길이가 너무 김 재정렬 비용과 노이즈 증가 chunk length 분포 확인
5 offline eval 없이 체감만으로 결정 재현 불가 평가셋과 MRR/NDCG 기록

9. 정리된 결론 — 보지 않고 답해 보라

Q1. retriever와 reranker의 가장 큰 차이는?

정답 retriever는 빠르게 후보를 찾고, reranker는 좁혀진 후보를 더 정확히 다시 정렬한다.
bi-encoder와 cross-encoder의 구조 차이 때문이다.

Q2. reranker가 더 정확한 이유는?

정답 query와 문서를 한 입력으로 함께 읽기 때문이다.
토큰 단위 상호작용을 직접 볼 수 있기 때문이다.

Q3. reranker의 대표적 한계는?

정답 느리고 비용이 비싸다는 점이다.
candidate마다 query-document 쌍 연산을 다시 해야 하기 때문이다.

Q4. reranker 앞에서 가장 중요한 것은?

정답 retriever가 좋은 후보를 충분히 top-N 안에 넣는 것이다.
reranker는 없는 후보를 만들 수 없기 때문이다.


Cheat Sheet — 이 편의 식·정의 1페이지

- relevance score: \(s(q, d) = W^\top h_{\text{[CLS]}}(q, d) + b\)

정의 - Bi-encoder: 빠른 후보 검색 - Cross-encoder: 느리지만 정밀한 재정렬 - Candidate Set: reranker 입력 후보군

최소 코드

candidates = retriever.search(query, k=30)
scores = reranker.score([(query, doc.text) for doc in candidates])

언제 무엇을 | 상황 | 선택 | |---|---| | 전 코퍼스 검색 | retriever | | top-30 정밀 정렬 | reranker | | latency 엄격 | 작은 reranker | | 고정밀 QA | reranker 필수 |


참고 자료

1차 자료

  • Nogueira, R. and Cho, K. Passage Re-ranking with BERT. 2019.
  • Karpukhin, V. et al. Dense Passage Retrieval. 2020.

공식 docs

  • BGE reranker model card
  • Cohere Rerank docs
  • Jina AI reranker docs

보조 자료

  • 사용자 노트 10장 Hybrid, 11장 Reranker

다음 편으로 이어지는 흐름

좋은 reranker를 붙였더라도, 이제는 "정말 좋아졌는가"를 증명해야 한다. 다음 14편에서는 golden dataset, RAGAS, DeepEval로 RAG 평가셋을 어떻게 만들고 굴리는지를 다룬다.

시리즈 전체 안내: 시리즈 목차

댓글

이 블로그의 인기 게시물

"LLM 핵심 학습 (1/6) — 기본: 토큰화·임베딩·어텐션·위치 인코딩"

"LLM 핵심 학습 (2/6) — 파인튜닝: LoRA·QLoRA·증류·Adapter"

"ML 기초 학습 (1/9) — 머신러닝과 sklearn: 학습의 좌표계"