Milvus와 VoyageAI를 사용한 시맨틱 검색
이 가이드에서는 VoyageAI의 임베딩 API를 Milvus 벡터 데이터베이스와 함께 사용하여 텍스트에 대한 의미론적 검색을 수행하는 방법을 소개합니다.
시작하기
시작하기 전에 Voyage API 키가 준비되어 있는지 확인하거나 VoyageAI 웹사이트에서 키를 받으세요.
이 예제에서 사용된 데이터는 책 제목입니다. 여기에서 데이터 세트를 다운로드하여 다음 코드를 실행하는 동일한 디렉터리에 넣을 수 있습니다.
먼저 Milvus 및 Voyage AI용 패키지를 설치합니다:
$ pip install --upgrade voyageai pymilvus
Google Colab을 사용하는 경우 방금 설치한 종속 요소를 사용하려면 런타임을 다시 시작해야 할 수 있습니다. (화면 상단의 "런타임" 메뉴를 클릭하고 드롭다운 메뉴에서 "세션 다시 시작"을 선택합니다.)
이제 임베딩을 생성하고 벡터 데이터베이스를 사용해 시맨틱 검색을 수행할 준비가 되었습니다.
VoyageAI 및 Milvus로 책 제목 검색하기
다음 예제에서는 다운로드한 CSV 파일에서 책 제목 데이터를 로드하고, Voyage AI 임베딩 모델을 사용하여 벡터 표현을 생성한 다음, 의미 검색을 위해 Milvus 벡터 데이터베이스에 저장합니다.
import voyageai
from pymilvus import MilvusClient
MODEL_NAME = "voyage-law-2" # Which model to use, please check https://docs.voyageai.com/docs/embeddings for available models
DIMENSION = 1024 # Dimension of vector embedding
# Connect to VoyageAI with API Key.
voyage_client = voyageai.Client(api_key="<YOUR_VOYAGEAI_API_KEY>")
docs = [
"Artificial intelligence was founded as an academic discipline in 1956.",
"Alan Turing was the first person to conduct substantial research in AI.",
"Born in Maida Vale, London, Turing was raised in southern England.",
]
vectors = voyage_client.embed(texts=docs, model=MODEL_NAME, truncation=False).embeddings
# Prepare data to be stored in Milvus vector database.
# We can store the id, vector representation, raw text and labels such as "subject" in this case in Milvus.
data = [
{"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
for i in range(len(docs))
]
# Connect to Milvus, all data is stored in a local file named "milvus_voyage_demo.db"
# in current directory. You can also connect to a remote Milvus server following this
# instruction: https://milvus.io/docs/install_standalone-docker.md.
milvus_client = MilvusClient(uri="milvus_voyage_demo.db")
COLLECTION_NAME = "demo_collection" # Milvus collection name
# Create a collection to store the vectors and text.
if milvus_client.has_collection(collection_name=COLLECTION_NAME):
milvus_client.drop_collection(collection_name=COLLECTION_NAME)
milvus_client.create_collection(collection_name=COLLECTION_NAME, dimension=DIMENSION)
# Insert all data into Milvus vector database.
res = milvus_client.insert(collection_name="demo_collection", data=data)
print(res["insert_count"])
MilvusClient
의 인수는 다음과 같습니다:
uri
을 로컬 파일(예:./milvus.db
)로 설정하는 것이 가장 편리한 방법인데, 이 파일에 모든 데이터를 저장하기 위해 Milvus Lite를 자동으로 활용하기 때문입니다.- 데이터 규모가 큰 경우, 도커나 쿠버네티스에 더 고성능의 Milvus 서버를 설정할 수 있습니다. 이 설정에서는 서버 URL(예:
http://localhost:19530
)을uri
으로 사용하세요. - 밀버스의 완전 관리형 클라우드 서비스인 질리즈 클라우드를 사용하려면, 질리즈 클라우드의 퍼블릭 엔드포인트와 API 키에 해당하는
uri
와token
을 조정하세요.
이제 밀버스 벡터 데이터베이스에 있는 모든 데이터로 쿼리에 대한 벡터 임베딩을 생성하여 시맨틱 검색을 수행하고 벡터 검색을 수행할 수 있습니다.
queries = ["When was artificial intelligence founded?"]
query_vectors = voyage_client.embed(
texts=queries, model=MODEL_NAME, truncation=False
).embeddings
res = milvus_client.search(
collection_name=COLLECTION_NAME, # target collection
data=query_vectors, # query vectors
limit=2, # number of returned entities
output_fields=["text", "subject"], # specifies fields to be returned
)
for q in queries:
print("Query:", q)
for result in res:
print(result)
print("\n")
Query: When was artificial intelligence founded?
[{'id': 0, 'distance': 0.7196218371391296, 'entity': {'text': 'Artificial intelligence was founded as an academic discipline in 1956.', 'subject': 'history'}}, {'id': 1, 'distance': 0.6297335028648376, 'entity': {'text': 'Alan Turing was the first person to conduct substantial research in AI.', 'subject': 'history'}}]
VoyageAI & Milvus로 이미지 검색하기
import base64
import voyageai
from pymilvus import MilvusClient
import urllib.request
import matplotlib.pyplot as plt
from io import BytesIO
import urllib.request
import fitz # PyMuPDF
from PIL import Image
def pdf_url_to_screenshots(url: str, zoom: float = 1.0) -> list[Image]:
# Ensure that the URL is valid
if not url.startswith("http") and url.endswith(".pdf"):
raise ValueError("Invalid URL")
# Read the PDF from the specified URL
with urllib.request.urlopen(url) as response:
pdf_data = response.read()
pdf_stream = BytesIO(pdf_data)
pdf = fitz.open(stream=pdf_stream, filetype="pdf")
images = []
# Loop through each page, render as pixmap, and convert to PIL Image
mat = fitz.Matrix(zoom, zoom)
for n in range(pdf.page_count):
pix = pdf[n].get_pixmap(matrix=mat)
# Convert pixmap to PIL Image
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
images.append(img)
# Close the document
pdf.close()
return images
def image_to_base64(image):
buffered = BytesIO()
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue())
return img_str.decode("utf-8")
DIMENSION = 1024 # Dimension of vector embedding
이제 Milvus를 위한 입력 데이터를 준비해야 합니다. 이전 장에서 만든 VoyageAI 클라이언트를 재사용해 보겠습니다. 사용 가능한 VoyageAI 멀티모달 임베딩 모델은 이 페이지에서 확인하세요.
pages = pdf_url_to_screenshots("https://www.fdrlibrary.org/documents/356632/390886/readingcopy.pdf", zoom=3.0)
inputs = [[img] for img in pages]
vectors = client.multimodal_embed(inputs, model="voyage-multimodal-3")
inputs = [i[0] if isinstance(i[0], str) else image_to_base64(i[0]) for i in inputs]
# Prepare data to be stored in Milvus vector database.
# We can store the id, vector representation, raw text and labels such as "subject" in this case in Milvus.
data = [
{"id": i, "vector": vectors.embeddings[i], "data": inputs[i], "subject": "fruits"}
for i in range(len(inputs))
]
다음으로 Milvus 데이터베이스 연결을 생성하고 임베딩을 Milvus 데이터베이스에 삽입합니다.
milvus_client = MilvusClient(uri="milvus_voyage_multi_demo.db")
COLLECTION_NAME = "demo_collection" # Milvus collection name
# Create a collection to store the vectors and text.
if milvus_client.has_collection(collection_name=COLLECTION_NAME):
milvus_client.drop_collection(collection_name=COLLECTION_NAME)
milvus_client.create_collection(collection_name=COLLECTION_NAME, dimension=DIMENSION)
# Insert all data into Milvus vector database.
res = milvus_client.insert(collection_name="demo_collection", data=data)
print(res["insert_count"])
이제 이미지를 검색할 준비가 되었습니다. 여기서 쿼리는 문자열이지만 이미지로도 쿼리할 수 있습니다. ( 여기에서 멀티모달 API에 대한 설명서를 확인하세요.) 결과 이미지를 표시하기 위해 matplotlib를 사용합니다.
queries = [["The consequences of a dictator's peace"]]
query_vectors = client.multimodal_embed(
inputs=queries, model="voyage-multimodal-3", truncation=False
).embeddings
res = milvus_client.search(
collection_name=COLLECTION_NAME, # target collection
data=query_vectors, # query vectors
limit=4, # number of returned entities
output_fields=["data", "subject"], # specifies fields to be returned
)
for q in queries:
print("Query:", q)
for result in res:
fig, axes = plt.subplots(1, len(result), figsize=(66, 6))
for n, page in enumerate(result):
page_num = page['id']
axes[n].imshow(pages[page_num])
axes[n].axis("off")
plt.tight_layout()
plt.show()