세 가지 Python 코드는 Qdrant 벡터 데이터베이스를 활용한 기본적인 벡터 검색 워크플로우를 보여줍니다. 각 코드가 어떤 역할을 하는지, 그리고 전체적인 흐름은 어떻게 되는지 상세히 정리합니다.
전체 워크플로우 개요
이 세 가지 코드는 다음과 같은 순서로 실행되어야 하며, 각기 다른 역할을 수행합니다.
- 첫 번째 코드: Qdrant에 벡터를 저장할 **컬렉션(Collection)**을 생성합니다.
- 두 번째 코드: OpenAI 임베딩 모델을 사용하여 텍스트를 벡터로 변환한 후, 이 벡터들을 생성된 컬렉션에 **삽입(Upsert)**합니다.
- 세 번째 코드: 새로운 텍스트를 벡터로 변환한 후, 이 쿼리 벡터와 가장 유사한 벡터들을 컬렉션에서 **검색(Query)**합니다.
이 과정은 RAG(Retrieval Augmented Generation) 시스템의 "Retrieval" 부분의 핵심적인 동작 방식과 유사합니다.
1. 첫 번째 코드 해설: Qdrant 컬렉션 생성
이 코드는 Qdrant 서버에 데이터를 저장할 공간인 '컬렉션'을 정의하고 생성합니다.
from qdrant_client import QdrantClient # Qdrant 서버와 통신하기 위한 클라이언트 라이브러리
from qdrant_client.models import Distance, VectorParams # Qdrant 모델 정의 (거리 측정 방식, 벡터 파라미터)
client = QdrantClient(host="localhost", port=6333) # Qdrant 클라이언트 초기화. 로컬 Qdrant 서버에 연결합니다.
collection_name = "test3" # 생성할 컬렉션의 이름을 'test3'으로 정의합니다.
response = client.create_collection( # Qdrant 클라이언트를 통해 컬렉션을 생성합니다.
collection_name = collection_name, # 컬렉션 이름 지정
vectors_config = VectorParams(size = 1536, distance=Distance.COSINE) # 벡터 저장소 설정
# size = 1536: 이 컬렉션에는 1536차원의 벡터만 저장할 수 있습니다.
# 이는 OpenAI의 'text-embedding-3-small' 모델이 기본적으로 1536차원 벡터를 생성하기 때문에 이에 맞춰 설정한 것입니다.
# distance=Distance.COSINE: 벡터 간의 유사도를 코사인 유사도 방식으로 측정합니다.
)
print(response) # 컬렉션 생성 작업의 성공 여부를 출력합니다. (성공 시 True)
코드의 역할:
- Qdrant에 test3라는 이름의 빈 컬렉션을 만듭니다.
- 이 컬렉션은 1536차원의 벡터만 저장할 수 있으며, 벡터 유사도 계산에는 코사인 유사도 방식이 사용됩니다.
- 실행 전제: Qdrant 서버가 localhost:6333에서 실행 중이어야 합니다.
- 실행 결과: 성공 시 True를 출력합니다. (만약 이미 test3 컬렉션이 존재하면 에러가 발생할 수 있으므로, 실제 환경에서는 client.recreate_collection을 사용하는 것이 더 안전합니다.)
2. 두 번째 코드 해설: 텍스트 임베딩 및 Qdrant에 데이터 삽입 (Upsert)
이 코드는 OpenAI 임베딩 모델을 사용하여 텍스트를 고차원 벡터로 변환하고, 이 벡터들과 원본 텍스트 정보를 Qdrant의 test3 컬렉션에 저장합니다.
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct # PointStruct: Qdrant에 저장될 데이터(ID, 벡터, 페이로드) 구조 정의
import openai # OpenAI API와 통신하기 위한 라이브러리
from dotenv import load_dotenv # .env 파일에서 환경 변수를 로드하기 위한 라이브러리
import os # 운영체제 환경 변수에 접근하기 위한 모듈
load_dotenv() # .env 파일(예: .env)에 정의된 환경 변수들을 현재 스크립트의 환경 변수로 로드합니다.
openai_api_key = os.getenv("OPENAI_API_KEY") # 환경 변수에서 OpenAI API 키를 가져옵니다.
# if not openai_api_key: # API 키가 없는 경우 에러를 발생시키는 로직 (원래 코드에는 없지만 추가 권장)
# raise ValueError("OPENAI_API_KEY 환경 변수가 설정되지 않았습니다.")
client = QdrantClient(host= "localhost", port=6333) # Qdrant 클라이언트 초기화
openai_client = openai.OpenAI(api_key= openai_api_key) # OpenAI 클라이언트 초기화. API 키를 사용하여 OpenAI 서비스에 접근합니다.
# 첫 번째 텍스트 리스트를 임베딩합니다.
response = openai_client.embeddings.create(
input = ["한국인, 미국인, 프랑스인"], # 임베딩할 텍스트입니다. 리스트 형태로 여러 텍스트를 한 번에 임베딩할 수 있습니다.
model = "text-embedding-3-small", # 사용할 OpenAI 임베딩 모델입니다. 이 모델은 1536차원 벡터를 생성합니다.
)
# 두 번째 텍스트 리스트를 임베딩합니다.
response2 = openai_client.embeddings.create(
input = ["독일인, 중국인"],
model = "text-embedding-3-small",
)
points =[ # Qdrant에 저장할 포인트(PointStruct) 리스트를 정의합니다.
PointStruct( # 첫 번째 포인트: ID 1번
id = 1, # 포인트의 고유 ID
vector = response.data[0].embedding, # 첫 번째 임베딩 결과의 벡터 (response.data[0].embedding은 1536차원 벡터)
payload = {"name": "한국인, 미국인, 프랑스인"}, # 벡터와 연결된 메타데이터. 원본 텍스트를 저장하여 검색 후 활용할 수 있습니다.
),
PointStruct( # 두 번째 포인트: ID 2번
id =2,
vector = response2.data[0].embedding, # 두 번째 임베딩 결과의 벡터
payload ={"name": "독일인, 중국인"},
),
]
response = client.upsert( # Qdrant 클라이언트를 통해 정의된 포인트들을 컬렉션에 삽입하거나 업데이트합니다.
collection_name = "test3", # 포인트를 삽입할 대상 컬렉션 (첫 번째 코드에서 생성한 'test3' 컬렉션)
points= points, # 삽입할 포인트 리스트
)
# print(response) # upsert 작업의 성공 여부를 출력할 수 있습니다. (성공 시 status: ok)
코드의 역할:
- OPENAI_API_KEY 환경 변수를 로드합니다.
- OpenAI의 text-embedding-3-small 모델을 사용하여 두 개의 텍스트("한국인, 미국인, 프랑스인", "독일인, 중국인")를 각각 1536차원 벡터로 변환합니다.
- 변환된 벡터와 원본 텍스트를 페이로드로 포함하는 두 개의 PointStruct 객체를 생성합니다.
- 이 포인트들을 test3 컬렉션에 upsert (삽입 또는 업데이트)합니다.
- 실행 전제:
- test3 컬렉션이 첫 번째 코드를 통해 미리 생성되어 있어야 합니다.
- .env 파일에 OPENAI_API_KEY가 올바르게 설정되어 있어야 합니다.
- openai 및 python-dotenv 라이브러리가 설치되어 있어야 합니다 (pip install openai python-dotenv).
- 실행 결과: test3 컬렉션에 두 개의 벡터 데이터가 저장됩니다.
3. 세 번째 코드 해설: Qdrant 컬렉션에서 벡터 검색 (Query)
이 코드는 새로운 질의 텍스트를 벡터로 변환한 후, test3 컬렉션에 저장된 벡터들 중에서 이 질의 벡터와 가장 유사한 벡터들을 찾아 반환합니다.
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct # 필요한 모델 임포트
import openai
from dotenv import load_dotenv
import os
load_dotenv()
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key: # API 키가 없는 경우 에러 발생
raise ValueError("OPENAI_API_KEY 환경 변수가 설정되지 않았습니다.")
openai_client = openai.OpenAI(api_key=openai_api_key) # OpenAI 클라이언트 초기화
client = QdrantClient(host="localhost", port = 6333) # Qdrant 클라이언트 초기화
try:
collections = client.get_collections() # Qdrant 서버에 연결하여 현재 존재하는 컬렉션 목록을 가져옵니다.
print("Qdrant 클라이언트 연결 및 컬렉션 정보 가져오기 성공:", collections) # 연결 성공 메시지와 컬렉션 목록 출력
except Exception as e:
print(f"Qdrant 클라이언트 연결 또는 작업 중 오류 발생: {e}") # 연결 실패 시 오류 메시지 출력
# 검색할 질의 텍스트를 임베딩합니다.
response = openai_client.embeddings.create(
input ="한국인이 들어있는 POINT", # 검색 질의 텍스트
model = "text-embedding-3-small", # 임베딩 모델은 데이터 삽입 시 사용한 모델과 동일해야 합니다.
)
query_vector = response.data[0].embedding # 생성된 쿼리 벡터를 가져옵니다.
search_response = client.query_points( # Qdrant 클라이언트를 사용하여 벡터 유사도 검색을 수행합니다.
collection_name = "test3", # 검색 대상 컬렉션
query = query_vector, # 검색 기준이 되는 쿼리 벡터
limit = 2, # 가장 유사한 상위 2개의 결과만 반환
with_payload = True, # 검색 결과에 페이로드(메타데이터) 포함
)
print(search_response) # 검색 결과 객체 전체를 출력합니다.
# 이 객체는 search_response.points 속성에 검색된 PointStruct 리스트를 포함합니다.
# 각 PointStruct는 id, vector, payload, score 속성을 가집니다.
코드의 역할:
- OPENAI_API_KEY를 로드하고 OpenAI 클라이언트를 초기화합니다.
- Qdrant 서버에 연결하여 컬렉션 목록을 확인합니다 (연결 상태 확인용).
- 질의 텍스트 "한국인이 들어있는 POINT"를 OpenAI 임베딩 모델로 1536차원 벡터로 변환합니다.
- 변환된 쿼리 벡터를 사용하여 test3 컬렉션에서 가장 유사한 상위 2개의 포인트를 검색합니다.
- 검색된 포인트의 ID, 벡터, 페이로드, 유사도 점수를 포함하는 search_response 객체를 출력합니다.
- 실행 전제:
- 첫 번째 코드와 두 번째 코드가 성공적으로 실행되어 test3 컬렉션이 생성되고 데이터가 삽입되어 있어야 합니다.
- openai 및 python-dotenv 라이브러리가 설치되어 있어야 합니다.
- 실행 결과: query_vector와 가장 유사한 test3 컬렉션 내의 포인트들이 반환됩니다. query_vector = "한국인이 들어있는 POINT"는 "한국인, 미국인, 프랑스인" 벡터와 더 유사할 것이므로, id=1인 포인트가 더 높은 점수로 검색될 것입니다.
실행 순서 요약
이 세 가지 코드를 순서대로 실행해야 전체 워크플로우가 정상적으로 작동합니다.
- 1.py (컬렉션 생성 코드) 실행:
- python 1.py
- 2.py (데이터 삽입 코드) 실행:
- python 2.py
- 3.py (데이터 검색 코드) 실행:
- python 3.py
이 과정을 통해 Qdrant를 이용한 벡터 데이터베이스의 기본 동작 방식(컬렉션 생성 - 데이터 삽입 - 데이터 검색)을 이해하실 수 있을 것입니다.
반응형
'AI, 클라우드, 협업, 교육, 문서, 업무자동화' 카테고리의 다른 글
간단한 RAG(Retrieval Augmented Generation) 기반 챗봇 서비스 (0) | 2025.07.20 |
---|---|
벡터DB, Qdrant 컬렉션 검색 코드 설명 (0) | 2025.07.20 |
Qdrant 컬렉션에 포인트(Vector & Payload) 삽입 코드 설명 (0) | 2025.07.20 |
Qdrant 벡터 데이터베이스에 새로운 컬렉션(Collection)을 생성하는 예시 (0) | 2025.07.20 |
React 기본 사용법 (0) | 2025.07.14 |