33차시. Modular RAG 최적화
6-3. 하이브리드 검색 효과 측정
출처: 원본 PDF 33차시_ModularRAG최적화.pdf 17~18쪽 · 쪽 그림 17쪽 18쪽
📝 src/eval_hybrid.py
TESTS = [
{"q": "환불은 며칠 이내인가요?", "page": 4}, # 일반
{"q": "제품코드 A-7742 사양 알려줘", "page": 9}, # 고유명사
{"q": "제12조 내용이 뭔가요?", "page": 3}, # 조항 번호
{"q": "교환이 불가능한 경우는?", "page": 5}, # 부정문
# ... 20개
]
for name, fn in [("의미만", _search),
("하이브리드", _search_hybrid)]:
hit = 0
for t in TESTS:
pairs = fn(t["q"], config.TOP_K)
pages = [d.metadata["page_no"] for d, _ in pairs]
hit += (t["page"] in pages)
print(f"[{name:<10}] 검색 정확도 {hit}/{len(TESTS)} "
f"({hit/len(TESTS)*100:.0f}%)")
실행 결과 예시
─────────────────────────────────────────────
─────────
[의미만 ] 검색 정확도 17/20 (85%)
[하이브리드] 검색 정확도 19/20 (95%)
■ 하이브리드로 새로 잡은 질문
· 제품코드 A-7742 사양 알려줘 (고유명사)
· 제12조 내용이 뭔가요? (조항 번호)⚠️ 하이브리드의 비용
메모리 — BM25는 조각 전체를 메모리에 올립니다
조각 1만 개까지는 문제없습니다
속도 — 검색이 두 번 실행되어 약간 느려집니다
그래도 82ms → 120ms 수준입니다
전체 응답 시간에서 차지하는 비중은 여전히 작습니다
비용 — BM25는 API를 안 씁니다. 추가 비용 0원
정확도를 무료로 올릴 수 있다면 안 할 이유가 없습니다.
💡 부정문 문제는 완전히 해결되지 않습니다
"교환이 불가능한 경우"는 키워드가 겹쳐서
하이브리드로도 정확히 구분하기 어렵습니다.
근본 해결책은 분할 단계에 있습니다.
"가능한 경우"와 "불가능한 경우"가
다른 조각이 되도록 자르면 됩니다.
7차시에서 배운 "의미 단위로 자르기"가 여기서도 답입니다.