Raccomandazione di film con Milvus
In questo quaderno esploreremo come generare embeddings di descrizioni di film utilizzando OpenAI e sfruttare questi embeddings all'interno di Milvus per raccomandare film che corrispondono alle preferenze dell'utente. Per migliorare i risultati della ricerca, utilizzeremo il filtraggio per eseguire ricerche sui metadati. Il set di dati utilizzato in questo esempio proviene da HuggingFace e contiene oltre 8.000 voci di film, fornendo una ricca gamma di opzioni per le raccomandazioni di film.
Dipendenze e ambiente
È possibile installare le dipendenze eseguendo il seguente comando:
$ pip install openai pymilvus datasets tqdm
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 "Riavvia sessione" dal menu a discesa).
In questo esempio utilizzeremo OpenAI come LLM. È necessario preparare la chiave api OPENAI_API_KEY
come variabile d'ambiente.
import os
os.environ["OPENAI_API_KEY"] = "sk-***********"
Inizializzare il client OpenAI e Milvus
Inizializzare il client OpenAI.
from openai import OpenAI
openai_client = OpenAI()
Impostare il nome della collezione e la dimensione degli embeddings.
COLLECTION_NAME = "movie_search"
DIMENSION = 1536
BATCH_SIZE = 1000
Connettersi a Milvus.
from pymilvus import MilvusClient
# Connect to Milvus Database
client = MilvusClient("./milvus_demo.db")
Come per l'argomento di url
e token
:
- L'impostazione di
uri
come file locale, ad esempio./milvus.db
, è il metodo più conveniente, poiché utilizza automaticamente Milvus Lite per memorizzare tutti i dati in questo file. - Se si dispone di una grande quantità di dati, ad esempio più di un milione di vettori, è possibile configurare un server Milvus più performante su Docker o Kubernetes. In questa configurazione, utilizzare l'indirizzo e la porta del server come uri, ad esempio
http://localhost:19530
. Se si abilita la funzione di autenticazione su Milvus, utilizzare "<nome_utente>:<password>" come token, altrimenti non impostare il token. - Se si desidera utilizzare Zilliz Cloud, il servizio cloud completamente gestito per Milvus, impostare
uri
etoken
, che corrispondono all'Endpoint pubblico e alla chiave Api di Zilliz Cloud.
# Remove collection if it already exists
if client.has_collection(COLLECTION_NAME):
client.drop_collection(COLLECTION_NAME)
Definire i campi per la raccolta, che includono id, titolo, tipo, anno di rilascio, valutazione e descrizione.
from pymilvus import DataType
# Create collection which includes the id, title, and embedding.
# 1. Create schema
schema = MilvusClient.create_schema(
auto_id=True,
enable_dynamic_field=False,
)
# 2. Add fields to schema
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="title", datatype=DataType.VARCHAR, max_length=64000)
schema.add_field(field_name="type", datatype=DataType.VARCHAR, max_length=64000)
schema.add_field(field_name="release_year", datatype=DataType.INT64)
schema.add_field(field_name="rating", datatype=DataType.VARCHAR, max_length=64000)
schema.add_field(field_name="description", datatype=DataType.VARCHAR, max_length=64000)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=DIMENSION)
# 3. Create collection with the schema
client.create_collection(collection_name=COLLECTION_NAME, schema=schema)
Creare l'indice sulla raccolta e caricarlo.
# Create the index on the collection and load it.
# 1. Prepare index parameters
index_params = client.prepare_index_params()
# 2. Add an index on the embedding field
index_params.add_index(
field_name="embedding", metric_type="IP", index_type="AUTOINDEX", params={}
)
# 3. Create index
client.create_index(collection_name=COLLECTION_NAME, index_params=index_params)
# 4. Load collection
client.load_collection(collection_name=COLLECTION_NAME, replica_number=1)
Set di dati
Con Milvus attivo e funzionante, possiamo iniziare a prelevare i nostri dati. Hugging Face Datasets
è un hub che contiene molti dataset di utenti diversi e per questo esempio utilizziamo il dataset netflix-shows di HuggingLearners. Questo set di dati contiene film e coppie di metadati per oltre 8 mila film. Incorporeremo ogni descrizione e la memorizzeremo all'interno di Milvus insieme al titolo, al tipo, all'anno di uscita e alla valutazione.
from datasets import load_dataset
dataset = load_dataset("hugginglearners/netflix-shows", split="train")
Inserire i dati
Ora che abbiamo i nostri dati sulla macchina, possiamo iniziare a incorporarli e inserirli in Milvus. La funzione di incorporamento accetta il testo e restituisce gli incorporamenti in un formato di elenco.
def emb_texts(texts):
res = openai_client.embeddings.create(input=texts, model="text-embedding-3-small")
return [res_data.embedding for res_data in res.data]
Il prossimo passo è l'inserimento vero e proprio. Si iterano tutte le voci e si creano dei lotti che vengono inseriti una volta raggiunta la dimensione del lotto impostata. Al termine del ciclo, inseriamo l'ultimo lotto rimasto, se esiste.
from tqdm import tqdm
# batch (data to be inserted) is a list of dictionaries
batch = []
# Embed and insert in batches
for i in tqdm(range(0, len(dataset))):
batch.append(
{
"title": dataset[i]["title"] or "",
"type": dataset[i]["type"] or "",
"release_year": dataset[i]["release_year"] or -1,
"rating": dataset[i]["rating"] or "",
"description": dataset[i]["description"] or "",
}
)
if len(batch) % BATCH_SIZE == 0 or i == len(dataset) - 1:
embeddings = emb_texts([item["description"] for item in batch])
for item, emb in zip(batch, embeddings):
item["embedding"] = emb
client.insert(collection_name=COLLECTION_NAME, data=batch)
batch = []
Interrogare il database
Dopo aver inserito i dati in Milvus, possiamo eseguire una query. La query contiene una tupla contenente la descrizione del film che si sta cercando e il filtro da utilizzare. Maggiori informazioni sul filtro sono disponibili qui. La ricerca stampa innanzitutto la descrizione e l'espressione del filtro. Successivamente, per ogni risultato vengono stampati il punteggio, il titolo, il tipo, l'anno di uscita, la valutazione e la descrizione dei film trovati.
import textwrap
def query(query, top_k=5):
text, expr = query
res = client.search(
collection_name=COLLECTION_NAME,
data=emb_texts(text),
filter=expr,
limit=top_k,
output_fields=["title", "type", "release_year", "rating", "description"],
search_params={
"metric_type": "IP",
"params": {},
},
)
print("Description:", text, "Expression:", expr)
for hit_group in res:
print("Results:")
for rank, hit in enumerate(hit_group, start=1):
entity = hit["entity"]
print(
f"\tRank: {rank} Score: {hit['distance']:} Title: {entity.get('title', '')}"
)
print(
f"\t\tType: {entity.get('type', '')} "
f"Release Year: {entity.get('release_year', '')} "
f"Rating: {entity.get('rating', '')}"
)
description = entity.get("description", "")
print(textwrap.fill(description, width=88))
print()
my_query = ("movie about a fluffly animal", 'release_year < 2019 and rating like "PG%"')
query(my_query)
Description: movie about a fluffly animal Expression: release_year < 2019 and rating like "PG%"
Results:
Rank: 1 Score: 0.42213767766952515 Title: The Adventures of Tintin
Type: Movie Release Year: 2011 Rating: PG
This 3-D motion capture adapts Georges Remi's classic comic strip about the adventures
of fearless young journalist Tintin and his trusty dog, Snowy.
Rank: 2 Score: 0.4041026830673218 Title: Hedgehogs
Type: Movie Release Year: 2016 Rating: PG
When a hedgehog suffering from memory loss forgets his identity, he ends up on a big
city journey with a pigeon to save his habitat from a human threat.
Rank: 3 Score: 0.3980264663696289 Title: Osmosis Jones
Type: Movie Release Year: 2001 Rating: PG
Peter and Bobby Farrelly outdo themselves with this partially animated tale about an
out-of-shape 40-year-old man who's the host to various organisms.
Rank: 4 Score: 0.39479154348373413 Title: The Lamb
Type: Movie Release Year: 2017 Rating: PG
A big-dreaming donkey escapes his menial existence and befriends some free-spirited
animal pals in this imaginative retelling of the Nativity Story.
Rank: 5 Score: 0.39370301365852356 Title: Open Season 2
Type: Movie Release Year: 2008 Rating: PG
Elliot the buck and his forest-dwelling cohorts must rescue their dachshund pal from
some spoiled pets bent on returning him to domesticity.