🤖 AI/ML

리랭킹

Reranking

검색 결과를 재정렬하여 관련성을 높이는 기법. RAG 파이프라인에서 활용.

📖 상세 설명

리랭킹(Reranking)은 초기 검색 결과를 더 정교한 모델로 재정렬하여 관련성을 높이는 기법입니다. 첫 번째 단계에서 빠른 검색(sparse retrieval 또는 dense retrieval)으로 후보를 선별하고, 두 번째 단계에서 cross-encoder 같은 정밀 모델이 쿼리와 각 문서를 직접 비교하여 순위를 재조정합니다.

리랭킹이 등장한 배경은 검색 시스템의 정확도-속도 트레이드오프입니다. BM25 같은 sparse 검색은 빠르지만 의미를 놓치고, bi-encoder는 빠르지만 쿼리-문서 간 상호작용이 부족합니다. Cross-encoder는 정확하지만 느려서, 2단계 구조로 이 문제를 해결합니다. 2020년 BERT 기반 리랭커가 등장하며 주류가 되었습니다.

리랭킹의 핵심 원리는 cross-attention입니다. 쿼리와 문서를 함께 모델에 입력하면, 모델이 둘 사이의 세밀한 의미 관계를 파악합니다. bi-encoder가 각각을 독립적으로 임베딩하는 것과 달리, cross-encoder는 "이 문서가 이 쿼리에 얼마나 관련있는가"를 직접 스코어링합니다. 보통 top-20~100개 후보에 적용됩니다.

2024-2025년 RAG 시스템에서 리랭킹은 필수 구성요소가 되었습니다. Cohere Rerank API, Jina Reranker, BGE Reranker 등 상용 서비스가 성장 중이며, LLM 응답 품질을 10-30% 향상시킵니다. 특히 복잡한 질문이나 긴 문서에서 효과가 큽니다. LangChain, LlamaIndex 모두 리랭킹을 기본 지원합니다.

📊 성능 & 비용

리랭커모델 크기NDCG@10속도비용
Cohere Rerank v3비공개~0.72~100ms/1000문서$1/1K 검색
BGE-reranker-large560M~0.70~50ms/100문서오픈소스
Jina Reranker v2137M~0.68~30ms/100문서무료티어 있음
cross-encoder/ms-marco110M~0.65~40ms/100문서오픈소스

* 2025년 1월 기준, MS MARCO 벤치마크 참조

💻 코드 예제

# RAG 파이프라인에서 리랭킹 적용
from sentence_transformers import CrossEncoder
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

# 1단계: 벡터 검색으로 후보 추출
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings)

query = "LLM의 할루시네이션을 줄이는 방법"
initial_docs = vectorstore.similarity_search(query, k=20)

# 2단계: Cross-Encoder로 리랭킹
reranker = CrossEncoder('BAAI/bge-reranker-large')

# 쿼리-문서 쌍 생성
pairs = [[query, doc.page_content] for doc in initial_docs]

# 관련성 점수 계산
scores = reranker.predict(pairs)

# 점수로 재정렬
reranked = sorted(
    zip(initial_docs, scores),
    key=lambda x: x[1],
    reverse=True
)

# 상위 5개 선택
top_docs = [doc for doc, score in reranked[:5]]

print("🔝 리랭킹 후 상위 문서:")
for i, (doc, score) in enumerate(reranked[:5]):
    print(f"{i+1}. [점수: {score:.4f}] {doc.page_content[:80]}...")

# Cohere API 사용 예시
import cohere
co = cohere.Client("your-api-key")

results = co.rerank(
    query=query,
    documents=[doc.page_content for doc in initial_docs],
    top_n=5,
    model="rerank-v3.0"
)

for r in results.results:
    print(f"순위 {r.index}: 점수 {r.relevance_score:.4f}")

🗣️ 실무에서 이렇게 말하세요

💬 회의에서
"RAG 응답 품질이 낮은 건 검색 문제입니다. 벡터 검색 후 Cohere Rerank 적용하면 관련 문서 Hit Rate가 65%에서 85%로 올라갑니다. 월 비용은 1000달러 정도 예상되고요."
💬 면접에서
"리랭킹은 2-stage retrieval의 핵심입니다. Bi-encoder로 top-100 후보를 빠르게 추출하고, cross-encoder로 쿼리-문서 상호작용을 정밀 분석합니다. 속도는 약간 느려지지만 정확도가 크게 향상되어 LLM 컨텍스트 품질이 좋아집니다."
💬 기술 토론에서
"BGE-reranker-large가 오픈소스 중에서는 최고인데, 프로덕션에서는 Cohere v3가 더 안정적이에요. 특히 다국어 쿼리에서 성능 차이가 큽니다. 비용 대비 효과를 따지면 상용 API가 낫습니다."

⚠️ 흔한 실수 & 주의사항

1단계 검색 결과가 너무 적음 (k=5)

리랭킹은 있는 문서 중에서 재정렬합니다. 1단계에서 관련 문서가 없으면 리랭킹도 무의미합니다. 최소 k=20~50으로 시작하세요.

리랭킹 대상이 너무 많음 (k=1000)

Cross-encoder는 O(n) 비용입니다. 1000개 문서 리랭킹은 수 초가 걸릴 수 있습니다. 100-200개가 적정선입니다.

올바른 방법

1단계에서 k=50~100으로 충분히 추출하고, 리랭킹 후 top-5~10을 LLM에 전달하세요. 도메인 특화 리랭커 파인튜닝도 고려하세요.

🔗 관련 용어

📚 더 배우기