MongoDB Atlas 하이브리드 검색 리트리버

MongoDB Atlas 하이브리드 검색 리트리버 (MongoDBAtlasHybridSearchRetriever)

하이브리드 검색은 벡터 검색과 키워드 검색을 함께 써서 두 방식의 장점을 모두 살리는 전략이에요. MongoDB Atlas의 MongoDBAtlasHybridSearchRetriever는 벡터 검색과 전체 텍스트 검색(BM25)을 **RRF(Reciprocal Rank Fusion)**로 결합해 컬렉션에서 가장 관련성 높은 문서를 반환해요. 검색 결과를 RAG 체인에 바로 연결하는 방법까지 이 페이지에서 함께 볼게요.

출처: 공식문서

MongoDB Atlas는 AWS, Azure, GCP에서 제공되는 완전 관리형 클라우드 데이터베이스예요. MongoDB 문서 데이터에 대해 네이티브 벡터 검색, 전체 텍스트 검색(BM25), 하이브리드 검색을 모두 지원해요.

  • MongoDBAtlasHybridSearchRetriever: 벡터 검색과 전체 텍스트 검색을 RRF로 결합해 가장 관련성 높은 문서를 반환해요.
  • MongoDBAtlasFullTextSearchRetriever: 벡터 인덱스 없이 Atlas Search의 Lucene(BM25) 분석기만으로 키워드 검색을 수행해요.

두 리트리버 모두 BaseRetriever를 상속하며 langchain-mongodb 패키지에 포함돼 있어요. MongoDB Atlas 벡터스토어를 .as_retriever()로 리트리버에 캐스팅할 수도 있지만, 하이브리드 또는 전체 텍스트 전용 검색이 필요할 때는 전용 리트리버 클래스를 쓰는 게 좋아요.

설정

실행 중인 MongoDB Atlas 클러스터(Atlas Search 활성화)가 필요해요. 아직 없으면 Atlas UI에서 클러스터를 만들어요.

MongoDBAtlasHybridSearchRetriever는 대상 컬렉션에 두 개의 검색 인덱스가 필요해요.

  • 의미 검색(recall)을 위한 벡터 검색 인덱스
  • 키워드 검색(recall)을 위한 전체 텍스트 검색 인덱스

각 쿼리의 자동 트레이싱을 원하면 LangSmith API 키를 설정해요.

import getpass
import os

os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
os.environ["LANGSMITH_TRACING"] = "true"

설치

langchain-mongodb를 설치해요. 아래 예시들은 Voyage AI 임베딩을 함께 사용해요.

pip install -qU langchain-mongodb langchain-voyageai
uv add langchain-mongodb langchain-voyageai

설정

Atlas 연결 문자열을 설정하고 컬렉션 핸들을 열어요.

import getpass
import os

from pymongo import MongoClient

if not os.environ.get("MONGODB_ATLAS_URI"):
    os.environ["MONGODB_ATLAS_URI"] = getpass.getpass("Enter your MongoDB Atlas URI: ")

client = MongoClient(os.environ["MONGODB_ATLAS_URI"])
collection = client["<db_name>"]["<collection_name>"]

인덱스 만들기

하이브리드 검색을 쓰기 전에 컬렉션에 벡터 검색 인덱스와 전체 텍스트 검색 인덱스를 만들어야 해요. dimensions는 임베딩 모델(voyage-4-lite는 1024)에 맞춰요.

from langchain_mongodb import MongoDBAtlasVectorSearch
from langchain_mongodb.index import create_fulltext_search_index
from langchain_voyageai import VoyageAIEmbeddings  # swap in any embeddings class

embeddings = VoyageAIEmbeddings(model="voyage-4-lite")

vector_store = MongoDBAtlasVectorSearch(
    collection=collection,
    embedding=embeddings,
    index_name="vector_index",
)

# Create the vector search index (runs asynchronously on Atlas)
vector_store.create_vector_search_index(
    dimensions=1024,
    wait_until_complete=60,
)

# Create the full-text search index on the text field
create_fulltext_search_index(
    collection=collection,
    field="text",
    index_name="search_index",
    wait_until_complete=60,
)

인스턴스 생성

하이브리드 검색

MongoDBAtlasHybridSearchRetriever는 벡터와 키워드 결과를 RRF로 융합해요. vector_penaltyfulltext_penalty를 높이면 해당 채널의 가중치가 줄어들어요.

from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever

retriever = MongoDBAtlasHybridSearchRetriever(
    vectorstore=vector_store,
    search_index_name="search_index",
    k=5,
    vector_penalty=60.0,
    fulltext_penalty=60.0,
)

전체 텍스트 검색

MongoDBAtlasFullTextSearchRetriever는 BM25 키워드 검색을 수행하며 벡터 인덱스가 필요 없어요.

from langchain_mongodb.retrievers import MongoDBAtlasFullTextSearchRetriever

ft_retriever = MongoDBAtlasFullTextSearchRetriever(
    collection=collection,
    search_index_name="search_index",
    search_field="text",
    k=5,
)

사용

docs = retriever.invoke("What is MongoDB Atlas?")

체인 안에서 사용하기

리트리버를 RAG 체인에 직접 연결할 수 있어요. context 자리에 리트리버를 넣으면, 질문에 맞는 문서를 자동으로 가져와 프롬프트에 채워 넣어요.

from langchain_anthropic import ChatAnthropic
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

prompt = ChatPromptTemplate.from_template(
    "Answer the question based only on the following context:\n\n{context}\n\nQuestion: {question}"
)

llm = ChatAnthropic(model="claude-sonnet-4-6")

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

chain.invoke("What is MongoDB Atlas?")

더 알아보기 (Learn more)