Hybrid Search (하이브리드 검색)
Dense + Sparse를 결합하여 의미적 유사도와 키워드 매칭의 장점을 동시에 활용하는 검색 전략입니다. 프로덕션 RAG에서 가장 권장되는 접근법입니다.
Reciprocal Rank Fusion (RRF)
서로 다른 검색기의 결과를 랭킹 기반으로 합산하는 방법입니다.
RRF 점수 공식: score(d) = Σ 1 / (k + rank_i(d)) (k=60이 기본값)
LangChain EnsembleRetriever
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Dense Retriever
vectorstore = Chroma(collection_name="docs", embedding_function=embeddings)
vectorstore.add_documents(chunks)
dense_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# Sparse Retriever
bm25_retriever = BM25Retriever.from_documents(chunks, k=4)
# Hybrid: Ensemble Retriever (RRF)
ensemble_retriever = EnsembleRetriever(
retrievers=[dense_retriever, bm25_retriever],
weights=[0.5, 0.5], # Dense:Sparse = 50:50
)
results = ensemble_retriever.invoke("Self-RAG Reflection Token")
가중치 조정 전략
Dense와 Sparse의 가중치 비율에 따라 검색 특성이 달라집니다.
| 비율 (Dense:Sparse) | 적합한 경우 | 이유 |
|---|
| 70:30 | 일반 Q&A, 대화형 | 의미 검색 중심 |
| 50:50 | 균형 잡힌 기본 선택 | 양쪽 장점 균형 |
| 30:70 | 기술 문서, 코드 | 키워드 정확 매칭 중시 |
도메인별 최적 가중치
# 일반 Q&A
qa_retriever = EnsembleRetriever(
retrievers=[dense_retriever, bm25_retriever],
weights=[0.7, 0.3],
)
# 기술 문서 (코드, API 문서)
tech_retriever = EnsembleRetriever(
retrievers=[dense_retriever, bm25_retriever],
weights=[0.3, 0.7],
)
# 균형 (기본 추천)
balanced_retriever = EnsembleRetriever(
retrievers=[dense_retriever, bm25_retriever],
weights=[0.5, 0.5],
)
벡터 DB 내장 Hybrid Search
일부 벡터 DB는 하이브리드 검색을 네이티브로 지원하여, 별도의 Ensemble 구성 없이 사용할 수 있습니다.
from langchain_qdrant import QdrantVectorStore
vectorstore = QdrantVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
location=":memory:",
collection_name="hybrid_docs",
)
# MMR(Maximal Marginal Relevance) 검색
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 4, "fetch_k": 20},
)
results = retriever.invoke("RAG 검색 전략")
from langchain_weaviate import WeaviateVectorStore
import weaviate
client = weaviate.connect_to_local()
vectorstore = WeaviateVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
client=client,
)
# Weaviate 내장 Hybrid Search
retriever = vectorstore.as_retriever(
search_type="hybrid",
search_kwargs={"k": 4, "alpha": 0.5}, # alpha: dense 가중치
)
results = retriever.invoke("RAG 검색 전략")
from langchain_milvus import Milvus
vectorstore = Milvus.from_documents(
documents=chunks,
embedding=embeddings,
connection_args={"host": "localhost", "port": "19530"},
)
# Milvus Hybrid Search
retriever = vectorstore.as_retriever(
search_kwargs={"k": 4},
)
results = retriever.invoke("RAG 검색 전략")
벡터 DB Hybrid 지원 비교
| 벡터 DB | Hybrid Search | 방식 | 특징 |
|---|
| Qdrant | O | Dense + Sparse 네이티브 | 성능 우수, 프로덕션 추천 |
| Weaviate | O | BM25 + Dense 통합 | alpha로 가중치 조정 |
| Milvus | O | Multi-vector 검색 | 대규모 데이터 최적화 |
| Chroma | X | Dense만 지원 | EnsembleRetriever 필요 |
| FAISS | X | Dense만 지원 | EnsembleRetriever 필요 |
프로덕션 추천: 벡터 DB 내장 Hybrid Search를 사용하세요. Qdrant, Weaviate는 네이티브 Hybrid Search를 지원하여 성능과 편의성이 모두 우수합니다. Chroma나 FAISS를 사용 중이라면 LangChain EnsembleRetriever로 Hybrid를 구현하세요.