사이드프로젝트

[사이드 프로젝트] #2. RAG 챗봇 개발기 (6) - 하이브리드 검색과 '의외의' 결과

Jaejin Sim 2025. 11. 21. 22:01
반응형

4편에서는 FAQ 기반 문서 재설계를 통해 답변 품질을 극적으로 끌어올렸고, 5편에서는 메타데이터 필터링으로 검색의 정확도와 신뢰도를 높였습니다.

이제 마지막 퍼즐 한 조각이 남았습니다. 바로 '하이브리드 검색(Hybrid Search)'입니다. 이번 글에서는 RAG 시스템의 검색 품질을 극대화하기 위해 하이브리드 검색을 도입한 과정과, 그 테스트 결과에서 얻은 예상치 못한 교훈을 공유합니다.

1. 벡터(Vector) 검색의 2% 부족함

현재까지 구축한 챗봇은 벡터 검색만으로도 약 90%의 높은 정확도를 보여주고 있습니다. 벡터 검색은 문맥과 의미(Semantic)를 이해하는 데 탁월하기 때문입니다.

질문: "결제가 안 될 때 어떻게 하나요?"

벡터 검색 결과:
"결제 실패 처리 방법" 문서를 찾아냄 (성공 ✅)
"Error Handling Guide" 문서도 찾아냄 (성공 ✅)

 

하지만 벡터 검색에도 치명적인 약점이 있습니다. 바로 '정확한 키워드 매칭'입니다.

예를 들어, "ABC 서비스 API 키는 어디서 받나요?"라고 물었을 때, 벡터 검색은 의미적으로 비슷한 문서들을 가져옵니다.

  1. "API 키 발급 방법" (일반적인 가이드)
  2. "서비스 설정 가이드" (관련 있어 보임)
  3. "ABC 서비스 API 키 발급" (우리가 찾는 정답!)

의미적으로는 1번과 2번도 매우 가깝기 때문에, 정작 고유명사('ABC')가 포함된 3번 문서가 뒤로 밀리거나 검색되지 않을 수 있습니다.

2. 해결책: 하이브리드 검색 (Vector + Keyword)

이 문제를 해결하기 위해 도입한 것이 하이브리드 검색입니다.

  • 벡터 검색 (Dense): 문맥과 의미를 파악 (60% 비중)
  • BM25 검색 (Sparse): 정확한 단어/키워드 매칭을 파악 (40% 비중)

이 두 가지 검색 결과를 **앙상블(Ensemble)**하여, 의미도 통하고 핵심 키워드도 포함된 최적의 문서를 찾아내는 방식입니다.

💡 잠깐, BM25가 뭔가요?

단순한 SQL의 LIKE %검색어%와는 다릅니다. BM25는 '똑똑한 키워드 검색' 알고리즘입니다.

단순히 단어가 포함되었는지만 보는 것이 아니라, "이 문서에서 해당 단어가 얼마나 자주 등장하는가?"(빈도)"이 단어가 전체 문서군에서 얼마나 희귀한가?"(희귀도)를 따져 점수를 매깁니다.

3. 구현: LangChain으로 앙상블 구성하기

구현은 생각보다 간단합니다. LangChain의 EnsembleRetriever를 사용하면 됩니다.

from langchain.retrievers import BM25Retriever, EnsembleRetriever

# 1. 벡터 검색기 (의미 기반)
vector_retriever = vector_store.as_retriever(
    search_kwargs={"k": 5}
)

# 2. BM25 검색기 (키워드 기반)
# 가지고 있는 모든 FAQ 문서(documents)를 기반으로 생성
bm25_retriever = BM25Retriever.from_documents(
    documents,
    k=5
)

# 3. 앙상블 (하이브리드 조합)
ensemble_retriever = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.6, 0.4]  # 벡터 60%, BM25 40% 가중치 부여
)

# 검색 실행
results = ensemble_retriever.invoke(query)

이렇게 하면 벡터 검색 결과와 BM25 검색 결과를 가중치에 따라 합산(Weighted Sum)하고, 최종 순위(Rank)를 다시 매겨 상위 문서를 반환합니다.

4. 테스트 결과: 어라? 차이가 없네? 😮

구현을 마치고 부푼 기대를 안고 테스트를 진행했습니다. 실제 질문 30개를 던져 정확도를 측정했습니다.

검색 방식  정확도  비고
벡터 검색 27/30 (90%) 의미 기반
하이브리드 27/30 (90%) 벡터 + BM25

놀랍게도 결과에 차이가 없었습니다. 하이브리드 검색을 도입하면 정확도가 비약적으로 상승할 줄 알았는데, 왜 그대로였을까요?

5. 원인 분석 및 교훈: 기술보다 중요한 것

실망감을 뒤로하고 원인을 분석해 보니, 오히려 매우 긍정적인 신호를 발견할 수 있었습니다.

1) 문서의 구조가 너무 좋았다 (Perfect Structure)

가장 큰 이유는 4편에서 진행한 'FAQ 문서 재설계' 덕분이었습니다.

이미 문서가 "1 질문 = 1 답변" 형태로 완벽하게 쪼개져 있고, 질문 의도가 명확히 반영되어 있다 보니, 벡터 검색만으로도 이미 정답을 100% 가까이 찾아내고 있었던 것입니다.

2) 데이터셋의 크기 (Small Data)

현재 FAQ 문서는 약 33개입니다. 데이터가 적고 문서 품질이 높으면 벡터 검색만으로도 충분합니다. 하이브리드 검색은 문서가 수백, 수천 개로 늘어나서 벡터 간의 의미가 겹칠 때 진가를 발휘합니다.

3) 핵심 교훈

이번 결과에서 저는 RAG 개발의 가장 중요한 본질을 깨달았습니다.

"좋은 임베딩 모델이나 복잡한 검색 알고리즘보다, 잘 설계된 문서 구조(Data Quality)가 훨씬 중요하다."
  • 4편(FAQ 문서화): 정확도 20% → 90% (대도약 🚀)
  • 6편(하이브리드): 정확도 90% → 90% (유지)

결국 가장 큰 성능 향상은 코드가 아니라 데이터를 다루는 방식에서 나왔습니다.

6. 마치며: '보험'으로서의 하이브리드

비록 당장의 수치 변화는 없었지만, 하이브리드 검색 코드는 그대로 유지하기로 했습니다. 그 이유는 '확장성''안정성' 때문입니다.

  • 확장성: 향후 문서가 500개, 1000개로 늘어나면 벡터 검색만으로는 한계가 옵니다. 그때 하이브리드 검색이 진가를 발휘할 것입니다.
  • 안정성: 사용자의 오타나, 매우 특이한 고유명사 검색 등 벡터가 놓칠 수 있는 예외 케이스를 BM25가 방어해 주는 '보험' 역할을 합니다.

이로써 약 한 달간 진행된 [RAG 기반 업무 지식 챗봇 만들기]의 핵심 개발 과정이 마무리되었습니다.

  1. 기획: 막연한 아이디어에서 구체적 설계로
  2. 위기: 답변 품질의 한계 직면
  3. 도약: FAQ 문서 재설계 (Quality)
  4. 정교화: 메타데이터 필터링 (Precision)
  5. 완성: 하이브리드 검색 (Stability)

이번 프로젝트를 통해 단순히 랭체인(LangChain) 사용법을 익힌 것을 넘어, "AI 서비스를 만들 때 데이터를 어떻게 바라봐야 하는가"에 대한 귀중한 경험을 얻었습니다.

다음 글에서는 이 프로젝트의 최종 회고와, 앞으로의 고도화 계획을 정리하며 시리즈를 마무리하겠습니다.

반응형