"RAG 핵심 학습 (12/26) — Hybrid Search와 Score Fusion"

고유명사와 정확 매칭은 BM25가, 의미 유사성은 Dense가 강하다. Hybrid Search는 둘 중 하나를 버리지 않는 설계다.

Hybrid Search는 Dense RetrievalSparse Retrieval을 동시에 돌린 뒤 결과를 합치는 검색 전략이다. 핵심은 "둘 다 돌린다"가 아니라 어떤 질문에서 어떤 신호를 더 믿을지를 설계하는 데 있다. 이번 글은 10편과 11편에서 본 Dense, BM25를 하나의 파이프라인으로 묶고, 실무에서 가장 많이 쓰는 RRF(Reciprocal Rank Fusion) 와 가중 합산 방식을 비교한다.


0. Prerequisites

  • 10편 Dense Retrieval
  • 11편 Sparse Retrieval과 BM25
  • 7편 메타데이터 설계

1. 학습 목표

  1. Dense와 Sparse를 왜 함께 써야 하는지 설명한다.
  2. RRF와 weighted fusion의 차이를 안다.
  3. Hybrid Search가 특히 강한 질문 유형을 구분한다.
  4. 13편 reranker와의 역할 분담을 이해한다.

2. 핵심 요약

Dense는 의미 유사성에 강하고, Sparse는 정확 토큰 일치에 강하다. Hybrid Search는 둘의 top-K를 합쳐 한쪽의 약점을 다른 쪽으로 덮는다. 가장 실무적인 기본값은 RRF다. 점수 스케일을 맞출 필요 없이 순위만 합치기 때문이다. 반면 weighted fusion은 튜닝 여지가 크지만 score normalization이 어렵다. 운영에서는 보통 metadata filter → dense/sparse 병렬 검색 → fusion → reranker 순서가 안정적이다.


3. 직관 — 왜 두 엔진을 함께 돌리는가

질문: "2024년 3분기 보고서의 환율 적용 기준은?"

  • Dense는 "환율 적용 기준"과 의미가 비슷한 문장을 넓게 가져온다.
  • BM25는 "2024년 3분기 보고서"라는 정확 문자열을 강하게 잡는다.
  • Hybrid는 둘을 같이 본다. 그래서 문서 식별의미 회수를 동시에 만족시킨다.
diagram-1

Hybrid가 강한 이유는 "중간값"이어서가 아니다. 서로 다른 오류를 내는 두 검색기가 독립된 실패 모드를 갖기 때문이다.


4. 정의 — Hybrid의 핵심 용어

용어 정의
Hybrid Search Dense와 Sparse를 함께 실행하고 결과를 결합하는 검색
Fusion 여러 랭킹이나 점수를 하나의 최종 순위로 합치는 단계
RRF 각 랭킹의 순위를 \(1 / (k + rank)\)로 바꿔 더하는 방식
Weighted Fusion Dense 점수와 Sparse 점수에 가중치를 주어 합산
Score Normalization 점수 범위가 다른 두 검색기의 값을 비교 가능하게 바꾸는 과정
Candidate Set fusion 전에 각 검색기에서 뽑아온 top-K 문서 묶음

5. 수식 — RRF와 가중 합산

RRF의 핵심 식:

$$\text{RRF}(d) = \sum_{r \in R} \frac{1}{k + \text{rank}_r(d)}$$

  • \(R\): 결합할 랭킹 집합
  • \(\text{rank}_r(d)\): 랭킹 \(r\)에서 문서 \(d\)의 순위
  • \(k\): 보통 60 안팎의 완충 상수

직관은 단순하다. 1등은 큰 보상을 받고, 순위가 내려갈수록 기여도가 빠르게 줄어든다. 점수 절대값이 아니라 순위 자체를 믿는다.

Weighted fusion은 보통 이렇게 쓴다.

$$\text{score}(d) = \alpha \cdot \tilde{s}_{dense}(d) + (1-\alpha) \cdot \tilde{s}_{sparse}(d)$$

여기서 핵심은 \(\tilde{s}\)다. 원점수 그대로는 비교가 어렵기 때문에 min-max, z-score, rank-based normalization 같은 보정이 필요하다.


6. 원리 워크스루 — Dense + BM25를 합치는 최소 구현

6.1 RRF 기본 구현

def rrf(rankings, k=60):
    scores = {}
    for ranking in rankings:
        for rank, doc_id in enumerate(ranking, start=1):
            scores[doc_id] = scores.get(doc_id, 0.0) + 1.0 / (k + rank)
    return sorted(scores.items(), key=lambda x: -x[1])

dense_rank = ["c17", "c03", "c08", "c11"]
bm25_rank = ["c03", "c17", "c09", "c11"]
final_rank = rrf([dense_rank, bm25_rank])

6.2 Qdrant / Weaviate 식 Hybrid 구조

query = "2024년 3분기 보고서의 환율 적용 기준은?"

dense_hits = vector_store.similarity_search(query, k=20, filter={"version": "2024Q3"})
sparse_hits = bm25_store.search(query, k=20, filter={"version": "2024Q3"})

fused = rrf([
    [hit.id for hit in dense_hits],
    [hit.id for hit in sparse_hits],
])

6.3 언제 weighted fusion을 쓰는가

def weighted_fusion(dense_scores, sparse_scores, alpha=0.6):
    merged = {}
    for doc_id, score in dense_scores.items():
        merged[doc_id] = merged.get(doc_id, 0.0) + alpha * score
    for doc_id, score in sparse_scores.items():
        merged[doc_id] = merged.get(doc_id, 0.0) + (1 - alpha) * score
    return sorted(merged.items(), key=lambda x: -x[1])

이 방식은 잘 튜닝하면 좋지만, 점수 정규화가 틀리면 한 검색기가 다른 검색기를 완전히 덮어버린다.

자기 설명: RRF가 점수 대신 순위를 쓰는 이유를 한 문장으로 설명해 보라.


7. 변형과 사례

7.1 RRF — 가장 안전한 기본값

무엇이 바뀌는가
검색기 점수 대신 순위만 사용한다.

왜 등장했는가
Dense cosine score와 BM25 score는 스케일이 완전히 다르다. 원점수를 섞으면 비교가 불안정했다.

무엇이 가능해졌는가
서로 다른 검색 엔진을 비교적 손쉽게 결합할 수 있다.

한계와 다음 단계
검색기별 확신도 차이를 세밀하게 반영하긴 어렵다. 그래서 20편의 dynamic weighting이 이어진다.

7.2 Weighted Fusion — 더 높은 상한, 더 큰 관리비

무엇이 바뀌는가
Dense와 Sparse에 질문별 또는 도메인별 가중치를 준다.

왜 등장했는가
상품 코드 검색처럼 Sparse가 훨씬 강한 영역과, 자연어 FAQ처럼 Dense가 강한 영역을 구분하고 싶기 때문이다.

무엇이 가능해졌는가
도메인 맞춤 최적화가 가능하다.

한계와 다음 단계
튜닝 데이터가 필요하고 drift에 취약하다. 운영에서는 14편, 15편의 평가 체계가 먼저 있어야 한다.

7.3 멀티스테이지 Hybrid

pre-filter → sparse top-50 + dense top-50 → fusion → rerank top-20 → answer top-5 같은 구조가 대표적이다. 이 구조에서 Hybrid는 최종 답을 고르는 단계가 아니라 후보군을 넓고 안전하게 만드는 단계다.


8. 한계와 실패 양상

8.1 Dense와 Sparse를 무조건 섞는다고 좋아지지는 않는다

Dense와 Sparse가 이미 비슷한 실패를 내고 있으면 Hybrid 이점이 작다. 예를 들어 전처리 자체가 잘못되어 문서 경계가 무너진 경우, 두 검색기는 똑같이 나쁜 후보를 반환한다.

8.2 Candidate 수가 너무 작으면 fusion 효과가 사라진다

top-3와 top-3만 합치면 서로 보완할 기회가 부족하다. 보통 fusion 전 단계에서는 top-20에서 top-100 사이 후보를 확보한다.

8.3 운영 비용이 늘어난다

두 검색기를 병렬로 돌리면 latency, 인프라 비용, observability 부담이 늘어난다. 이때 16편의 실험 자동화와 모니터링이 필요해진다.

8.4 다음 단계 — reranker가 왜 필요한가

Hybrid는 후보를 잘 모으는 단계다. 그러나 최종 상위 5개를 더 정확히 고르려면 query-document 쌍을 직접 읽는 reranker가 필요하다. 그 역할이 13편이다.


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

# 함정 증상 빠른 점검
1 점수 스케일을 그대로 합산 한 엔진이 결과를 독점 normalization 여부 확인
2 candidate 수가 너무 작음 fusion 효과 미미 각 검색기 top-K를 20 이상으로 확대
3 메타데이터 필터를 뒤에 적용 노이즈 문서 대량 유입 filter-first 구조 유지
4 Hybrid를 final answer selection으로 오해 상위 문맥 품질 불안정 reranker 단계를 분리
5 질문 유형 구분 없이 고정 가중치 사용 특정 도메인에서 성능 급락 17편 분류기 설계 검토

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

Q1. Hybrid Search는 무엇을 결합하는가?

정답 Dense Retrieval과 Sparse Retrieval의 후보 랭킹을 결합한다.
10편과 11편의 서로 다른 강점을 동시에 활용하기 위해서다.

Q2. RRF의 가장 큰 장점은?

정답 점수 정규화 없이 여러 랭킹을 안정적으로 합칠 수 있다.
절대 점수 대신 순위만 사용하기 때문이다.

Q3. Weighted fusion은 언제 유리한가?

정답 질문 유형이나 도메인별로 어느 검색기를 더 믿을지 이미 아는 경우다.
가중치를 조정해 더 높은 상한을 노릴 수 있기 때문이다.

Q4. Hybrid 다음에 reranker가 필요한 이유는?

정답 Hybrid는 후보를 넓게 모으는 단계이지 최종 정렬을 세밀하게 하는 단계가 아니기 때문이다.
query-document를 함께 읽는 cross-encoder가 상위 문맥 정밀도를 더 높여 준다.


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

- RRF: \(\text{RRF}(d) = \sum 1/(k + rank)\) - Weighted fusion: \(\alpha \tilde{s}_{dense} + (1-\alpha)\tilde{s}_{sparse}\)

정의 - Hybrid Search: Dense + Sparse 결합 - Fusion: 여러 검색 결과를 하나로 합치는 단계 - Candidate Set: reranker 이전 후보군

최소 코드

fused = rrf([
    [hit.id for hit in dense_hits],
    [hit.id for hit in sparse_hits],
])

언제 무엇을 | 상황 | 선택 | |---|---| | 안전한 기본값 | RRF | | 충분한 튜닝 데이터 있음 | weighted fusion | | exact match가 중요 | sparse 비중 확대 | | 의미 유사성이 중요 | dense 비중 확대 |


참고 자료

1차 자료

  • Cormack, G. V. et al. Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods. SIGIR 2009.
  • Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. EMNLP 2020.
  • Robertson, S. and Zaragoza, H. The Probabilistic Relevance Framework: BM25 and Beyond. 2009.

공식 docs

  • Qdrant Hybrid Search docs
  • Weaviate Hybrid Search docs
  • Elasticsearch BM25 docs

보조 자료

  • 사용자 노트 8장 Dense, 9장 Sparse, 10장 Hybrid

다음 편으로 이어지는 흐름

Hybrid는 후보를 잘 모으는 기술이다. 다음 편 13편에서는 이 후보들을 query-document 쌍으로 직접 읽어 다시 정렬하는 reranker를 다룬다. Dense와 Sparse가 "넓게 찾는 기술"이라면 reranker는 "정확히 고르는 기술"이다.

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

댓글

이 블로그의 인기 게시물

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

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

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