1. 개요
Qdrant는 벡터 유사도 검색을 위한 엔진으로, 고성능의 검색 기능과 편리한 API를 제공한다. 벡터 데이터 외에도 JSON 기반의 payload와 확장된 필터링 기능을 제공하므로, 의미 기반 검색(semantic search)이나 facet 검색, 추천 시스템 등 다양한 애플리케이션에 활용할 수 있다.
LangChain은 Qdrant를 위한 통합 모듈인 langchain-qdrant를 통해 밀접하게 연동할 수 있으며, 임베딩 기반 검색(dense), 희소 벡터 검색(sparse), 하이브리드 검색(hybrid retrieval)을 모두 지원한다. 이 문서는 Qdrant를 LangChain에서 효과적으로 활용하는 방법을 정리한 것이다.
2. 설치
다음 명령어로 필요한 라이브러리를 설치한다.
pip install -qU langchain-qdrant
pip install -qU langchain-openai
3. 임베딩 설정
OpenAI 기반 임베딩 모델을 설정한다. 예시는 text-embedding-3-large 모델을 사용하는 경우이다.
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
4. Qdrant 초기화
(1) 인메모리 모드
테스트 및 실험 용도로는 Qdrant 서버 없이 인메모리 모드로 실행할 수 있다.
from qdrant_client import QdrantClient
from qdrant_client.http.models import Distance, VectorParams
client = QdrantClient(":memory:")
client.create_collection(
collection_name="demo_collection",
vectors_config=VectorParams(size=3072, distance=Distance.COSINE),
)
(2) 온디스크 모드
로컬 디스크에 데이터를 저장하도록 설정할 수 있다.
client = QdrantClient(path="/tmp/langchain_qdrant")
5. LangChain Vector Store 구성
Qdrant 인스턴스를 LangChain의 QdrantVectorStore에 연결한다.
from langchain_qdrant import QdrantVectorStore
vector_store = QdrantVectorStore(
client=client,
collection_name="demo_collection",
embedding=embeddings,
)
6. 문서 삽입 및 삭제
LangChain의 Document 클래스를 사용하여 데이터를 삽입할 수 있다.
from langchain_core.documents import Document
from uuid import uuid4
documents = [
Document(page_content="문장 A", metadata={"source": "test"}),
Document(page_content="문장 B", metadata={"source": "test"})
]
uuids = [str(uuid4()) for _ in range(len(documents))]
vector_store.add_documents(documents=documents, ids=uuids)
삭제는 다음과 같이 수행한다.
vector_store.delete(ids=[uuids[0]])
7. 벡터 검색
(1) 기본 유사도 검색
results = vector_store.similarity_search("LangChain 관련 프로젝트", k=2)
for doc in results:
print(doc.page_content, doc.metadata)
(2) 유사도 점수 포함 검색
results = vector_store.similarity_search_with_score("내일 날씨", k=1)
for doc, score in results:
print(f"SIM={score:.3f} | {doc.page_content}")
8. 검색 모드 구성
(1) Dense Vector 검색
from langchain_qdrant import RetrievalMode
qdrant = QdrantVectorStore(
client=client,
collection_name="my_documents",
embedding=embeddings,
retrieval_mode=RetrievalMode.DENSE,
)
(2) Sparse Vector 검색
from langchain_qdrant import FastEmbedSparse
from qdrant_client.http.models import SparseVectorParams
sparse_embeddings = FastEmbedSparse(model_name="Qdrant/bm25")
client.create_collection(
collection_name="my_documents",
vectors_config={"dense": VectorParams(size=3072, distance=Distance.COSINE)},
sparse_vectors_config={
"sparse": SparseVectorParams(index={"on_disk": False})
}
)
qdrant = QdrantVectorStore(
client=client,
collection_name="my_documents",
sparse_embedding=sparse_embeddings,
retrieval_mode=RetrievalMode.SPARSE,
sparse_vector_name="sparse",
)
(3) Hybrid 검색
qdrant = QdrantVectorStore(
client=client,
collection_name="my_documents",
embedding=embeddings,
sparse_embedding=sparse_embeddings,
retrieval_mode=RetrievalMode.HYBRID,
vector_name="dense",
sparse_vector_name="sparse",
)
9. 메타데이터 필터링
Qdrant는 JSON 기반의 payload에 대한 조건 검색을 지원한다. LangChain에서도 이를 사용할 수 있다.
from qdrant_client import models
results = vector_store.similarity_search(
query="축구 선수",
k=1,
filter=models.Filter(
should=[
models.FieldCondition(
key="metadata.source",
match=models.MatchValue(value="website")
)
]
),
)
10. Retriever로 변환
QdrantVectorStore를 LangChain Retriever로 변환하여 chain이나 agent에서 사용할 수 있다.
retriever = vector_store.as_retriever(search_type="mmr", search_kwargs={"k": 1})
results = retriever.invoke("도둑이 훔친 돈은 얼마인가?")
11. 기존 Collection 사용
이미 생성된 Collection을 사용할 경우 다음처럼 불러올 수 있다.
qdrant = QdrantVectorStore.from_existing_collection(
embedding=embeddings,
collection_name="my_documents",
url="http://localhost:6333"
)
12. Named Vector, Custom Payload 키 사용
Qdrant는 하나의 point에 여러 개의 named vector를 저장할 수 있다. 또한, page_content와 metadata 키 대신 커스텀 필드를 사용할 수도 있다.
QdrantVectorStore.from_documents(
docs,
embeddings,
location=":memory:",
collection_name="my_documents",
content_payload_key="custom_content",
metadata_payload_key="custom_meta",
vector_name="my_vector",
sparse_vector_name="my_sparse"
)
13. 정리
Qdrant는 LangChain과 완벽하게 통합되며, 다양한 검색 모드와 메타데이터 필터링, 점수 기반 검색 등을 유연하게 지원한다. 서버 기반 또는 로컬 기반으로 실행할 수 있고, 기존 Collection의 재사용 또한 가능하다. Retrieval-Augmented Generation (RAG)을 구축하는 데 매우 적합한 벡터 검색 스토어이다.