25분
Hybrid Search, 이렇게 하면 망한다
Day 2: Hybrid Search
Hybrid Search, 이렇게 하면 망한다
RAG 심화 > Day 2: Hybrid Search
학습 목표
Hybrid Search 구현 시 자주 발생하는 실수를 파악한다 각 실수에 대한 해결책을 설명할 수 있다
Hybrid Search, 이렇게 하면 망한다
실수 1: 점수 정규화를 안 한다
# 잘못된 코드
bm25_score = 12.5 # BM25 스케일: 0 ~ 수십
semantic_score = 0.87 # Cosine 스케일: 0 ~ 1
# 그냥 합산하면?
hybrid = 0.5 * semantic_score + 0.5 * bm25_score
# = 0.5 * 0.87 + 0.5 * 12.5 = 6.685
# BM25가 지배적! Semantic은 영향력 없음
해결: Min-Max 정규화
def normalize(scores):
min_s, max_s = min(scores), max(scores)
if max_s == min_s:
return [1.0] * len(scores)
return [(s - min_s) / (max_s - min_s) for s in scores]
# 정규화 후: 둘 다 0~1 범위
bm25_norm = 0.95 # 최고점 대비 95%
semantic_norm = 0.87
hybrid = 0.5 * semantic_norm + 0.5 * bm25_norm # = 0.91 (공정한 합산)
실수 2: alpha를 고정한다
# 잘못된 코드
def search(query, alpha=0.5): # 항상 0.5
return hybrid_search(query, alpha)
# "E-4521 에러" -> alpha=0.5? BM25가 더 잘 찾는 쿼리인데!
# "장비 고장 원인" -> alpha=0.5? Semantic이 더 잘 찾는 쿼리인데!
해결: 쿼리 유형별 적응형 alpha
def get_alpha(query):
if has_code_pattern(query): # E-4521, ISO 9001
return 0.3 # BM25 가중
if has_numeric_query(query): # 몇 도, 얼마
return 0.4 # 약간 BM25
return 0.7 # Semantic 가중 (기본)
실수 3: 토크나이징 불일치
# 잘못된 코드
# 인덱싱 시: "CNC-M500" -> ["CNC", "M500"]
# 검색 시: "CNC-M500" -> ["CNC-M500"]
# 토큰이 다르니 BM25가 매칭 실패!
해결: 동일한 토크나이저 사용
# 인덱싱과 검색에서 동일 함수 사용
tokenizer = manufacturing_tokenize # 하나만!
corpus = [tokenizer(doc) for doc in documents]
query_tokens = tokenizer(query) # 같은 함수!
실수 4: 검색 후보 수가 부족
# 잘못된 코드
bm25_results = search_bm25(query, top_k=5) # 5개만!
semantic_results = search_semantic(query, top_k=5) # 5개만!
# 합치면 최대 10개, 겹치면 더 적음
# 좋은 문서를 놓칠 확률 높음
해결: initial_k를 final_k의 4~10배로
final_k = 5
initial_k = final_k * 4 # 최소 20개 후보
bm25_results = search_bm25(query, top_k=initial_k)
semantic_results = search_semantic(query, top_k=initial_k)
# 넉넉한 후보에서 Hybrid로 정렬 후 5개 선택
실수 5: 메타데이터 필터를 안 쓴다
# 잘못된 코드
# "CNC-M500 에러 코드"를 검색하면 모든 장비의 에러 코드가 나옴
# CNC-M500 문서만 보고 싶은데!
해결: 사전 필터링
# 장비 코드가 쿼리에 있으면 메타데이터로 필터
import re
equipment = re.search(r'[A-Z]+-[A-Z0-9]+', query)
if equipment:
results = collection.query(
query_texts=[query],
where={"equipment_code": equipment.group()},
n_results=top_k
)
Score Fusion vs RRF: 언제 뭘 쓸까?
| 기준 | Score Fusion | RRF |
|---|---|---|
| 장점 | alpha로 세밀 조절 가능 | 파라미터 최적화 불필요 |
| 단점 | 정규화 필수, alpha 튜닝 | 점수 차이 반영 약함 |
| 적합 | 쿼리 유형이 예측 가능할 때 | 다양한 쿼리가 올 때 |
| 제조 추천 | 적응형 alpha와 함께 | 빠른 프로토타이핑 |
체크리스트
- 점수 정규화 (Min-Max) 적용
- 쿼리 유형별 적응형 alpha 설정
- 인덱싱과 검색에 동일 토크나이저 사용
- initial_k를 final_k의 4배 이상으로 설정
- 메타데이터 필터 활용 (장비 코드, 문서 유형)
AI로 학습하기 — 꿀팁
✅Hybrid Search 구현 실수 점검AI 학습 팁
Hybrid Search에서 BM25와 벡터 점수 스케일 차이, alpha 설정 오류, RRF 파라미터 오용 등이 없는지 점검해 보세요.
Hybrid Search 구현 시 흔한 실수에 대한 아래 주장이 맞는지 검증해줘. (1) 'BM25 점수와 코사인 유사도 점수는 같은 스케일이므로 가중 평균을 바로 적용해도 된다.' (2) 'alpha=0.5는 BM25와 벡터 검색을 동등하게 사용하는 완벽히 균형 잡힌 설정이다.' (3) 'RRF 공식에서 k=60은 임의값이며 도메인에 따라 1~1000 범위에서 자유롭게 조정한다.' (4) 'Hybrid Search는 항상 벡터 단독 검색보다 Recall이 높다.' 제조 RAG 구현 맥락으로 교정해줘.
이 팁이 도움이 됐나요?