Ricerca semantica con Milvus e VoyageAI
Questa guida illustra come l 'API di embedding di VoyageAI possa essere utilizzata con il database vettoriale Milvus per condurre una ricerca semantica sul testo.
Come iniziare
Prima di iniziare, assicuratevi di avere pronta la chiave API di Voyage o di ottenerne una dal sito web di VoyageAI.
I dati utilizzati in questo esempio sono i titoli dei libri. È possibile scaricare il set di dati qui e inserirlo nella stessa directory in cui si esegue il codice seguente.
Innanzitutto, installare il pacchetto per Milvus e Voyage AI:
$ pip install --upgrade voyageai pymilvus milvus-lite
Se si utilizza Google Colab, per abilitare le dipendenze appena installate, potrebbe essere necessario riavviare il runtime. (Fare clic sul menu "Runtime" nella parte superiore dello schermo e selezionare "Restart session" dal menu a discesa).
A questo punto siamo pronti a generare embeddings e a utilizzare il database vettoriale per effettuare la ricerca semantica.
Ricerca di titoli di libri con VoyageAI e Milvus
Nell'esempio seguente, carichiamo i dati dei titoli dei libri dal file CSV scaricato, usiamo il modello di embedding di Voyage AI per generare rappresentazioni vettoriali e le memorizziamo nel database vettoriale di Milvus per la ricerca semantica.
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"])
Per quanto riguarda l'argomento di MilvusClient:
- L'impostazione di
uricome file locale, ad esempio./milvus.db, è il metodo più conveniente, in quanto utilizza automaticamente Milvus Lite per memorizzare tutti i dati in questo file. - Se si dispone di una grande quantità di dati, è possibile configurare un server Milvus più performante su docker o kubernetes. In questa configurazione, utilizzare l'uri del server, ad esempio
http://localhost:19530, comeuri. - Se si desidera utilizzare Zilliz Cloud, il servizio cloud completamente gestito per Milvus, regolare
urietoken, che corrispondono all'endpoint pubblico e alla chiave Api di Zilliz Cloud.
Con tutti i dati nel database vettoriale di Milvus, possiamo ora eseguire una ricerca semantica generando un'incorporazione vettoriale per la query e condurre una ricerca vettoriale.
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'}}]
Ricerca di immagini con VoyageAI e 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
Dobbiamo quindi preparare i dati di input per Milvus. Riutilizziamo il client VoyageAI creato nel capitolo precedente. Per il modello di incorporazione multimodale di VoyageAI disponibile, consultare questa pagina.
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))
]
Quindi, creiamo una connessione al database Milvus e inseriamo gli embeddings nel database 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"])
Ora siamo pronti a cercare le immagini. In questo caso, la query è una stringa, ma si può fare anche con le immagini. (consultare la documentazione dell'API multimodale qui). Usiamo matplotlib per mostrare le immagini dei risultati.
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()