Crie um Mecanismo de Recomendação de Filmes com Milvus e Python
Este artigo foi originalmente publicado em The New Stack e é republicado aqui com permissão.
Use ferramentas de código aberto para ajudar as pessoas a encontrar filmes que talvez tenham interesse em assistir.
Sistemas de recomendação ou mecanismos de recomendação são sistemas de filtragem de informações que visam prever e sugerir coisas nas quais os usuários possam estar interessados. Esses itens incluem produtos, serviços e conteúdos como filmes, livros, músicas ou artigos de notícias.
Há vários tipos de sistemas de recomendação, como filtragem colaborativa, filtragem baseada em conteúdo, sistemas de recomendação híbridos e sistemas de recomendação baseados em vetores. Sistemas baseados em vetores usam o espaço vetorial para encontrar (recomendar) os itens mais próximos no banco de dados. Há várias maneiras de armazenar esses vetores; uma das mais eficientes é usar o Milvus banco de dados vetorial de código aberto. Esse banco de dados é altamente flexível, rápido e confiável e permite adição, exclusão, atualização e busca quase em tempo real de vetores em escala de trilhões de bytes.
Este artigo explica como criar um recomendador de filmes com Milvus e Python. Esse sistema usará SentenceTransformers para converter as informações de texto em vetores e armazenar esses vetores no Milvus. O Milvus permite que os usuários pesquisem um filme no banco de dados com base nas informações de texto que eles fornecem.
Imagem em destaque por Tima Miroshnichenko no Pexels
Configurando o ambiente
Para este artigo, você precisará ter os seguintes requisitos instalados:
Python Package Manager (PIP) para instalar pacotes
Jupyter Notebook para escrever código
Um sistema com pelo menos 32GB de RAM ou uma conta Zilliz Cloud
Requisitos do Python
Você também precisa instalar um conjunto de bibliotecas que serão necessárias ao longo deste tutorial. Instale as bibliotecas usando PIP:
$ python -m pip install pymilvus pandas sentence_transformers kaggle
Armazenamento de dados vetoriais (Milvus)
Você usará o banco de dados vetorial Milvus para armazenar os embeddings que gerará usando descrições de filmes. O conjunto de dados é relativamente grande, pelo menos para um servidor em execução em um computador pessoal. Portanto, talvez você queira usar uma instância do Zilliz Cloud para armazenar esses vetores.
Se preferir ficar com uma instância local, você pode baixar uma configuração docker-compose e executá-la com:
$ wget https://github.com/milvus-io/milvus/releases/download/v2.3.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
$ docker-compose up -d
Agora você tem todos os requisitos para criar seu próprio sistema de recomendação de filmes com Milvus.
Coleta e pré-processamento de dados
Para este projeto, você usará o Movies Dataset do Kaggle, que contém metadados de 45.000 filmes. Você pode baixar este dataset diretamente ou usar a API do Kaggle para baixar o dataset usando Python. Para fazer isso com Python, você precisa baixar o arquivo kaggle.json da seção de perfil do Kaggle.com e colocá-lo em um local onde a API o encontrará.
Em seguida, configure algumas variáveis de ambiente para autenticação no Kaggle. Para isso, você pode abrir o Jupyter Notebook e escrever as seguintes linhas de código:
%env KAGGLE_USERNAME=username
%env KAGGLE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
%env TOKENIZERS_PARALLELISM=true
Feito isso, você pode usar a dependência Python do Kaggle para baixar o dataset do Kaggle:
# import kaggle dependency
import kaggle
kaggle.api.authenticate()
kaggle.api.dataset_download_files('rounakbanik/the-movies-dataset', path='dataset', unzip=True)
Depois que o dataset for baixado, você pode usar o método read_csv() do pandas para ler o dataset:
# import pandas
import pandas as pd
# read csv data
movies=pd.read_csv('dataset/movies_metadata.csv',low_memory=False)
# check shape of data
movies.shape
Formato do Dataset
A imagem mostra que você tem 45.466 registros com 24 colunas de metadados. Verifique todas essas colunas de metadados com:
# check column names
movies.columns
Colunas do Dataset
Há muitas colunas de que você não precisa para criar o sistema de recomendação. Você pode filtrar as colunas necessárias com:
# filter required columns
trimmed_movies = movies[["id", "title", "overview", "release_date", "genres"]]
trimmed_movies.head(5)
Colunas necessárias
Além disso, alguns dos campos nos dados estão ausentes, então remova essas linhas para produzir um dataset limpo:
unclean_movies_dict = trimmed_movies.to_dict('records')
print('{} movies'.format(len(unclean_movies_dict)))
movies_dict = []
for movie in unclean_movies_dict:
if movie["overview"] == movie["overview"] and movie["release_date"] == movie["release_date"] and movie["genres"] == movie["genres"] and movie["title"] == movie["title"]:
movies_dict.append(movie)
Conectar ao Milvus
Agora que você tem todas as colunas necessárias, conecte-se ao Milvus para começar a enviar os dados. Para se conectar à instância na nuvem do Milvus, você precisará do Uniform Resource Identifier (URI) e do token, que pode baixar do seu painel do Zilliz Cloud.
Painel do Zilliz
Depois de ter seu URI e chave de API, você pode usar o método connect() do PyMilvus para se conectar ao servidor Milvus:
# import milvus dependency
from pymilvus import *
# connect to milvus
milvus_uri="YOUR_URI"
token="YOUR_API_TOKEN"
connections.connect("default", uri=milvus_uri, token=token)
print("Connected!")
Gerar embeddings para filmes
Agora é hora de calcular os embeddings para os dados de texto no dataset de filmes. Primeiro, crie um objeto collection que armazenará o ID do filme e os embeddings para os dados de texto. Crie também um campo index para tornar as buscas mais eficientes:
COLLECTION_NAME = 'film_vectors'
PARTITION_NAME = 'Movie'
# Here's our record schema
"""
"title": Film title,
"overview": description,
"release_date": film release date,
"genres": film generes,
"embedding": embedding
"""
id = FieldSchema(name='title', dtype=DataType.VARCHAR, max_length=500, is_primary=True)
field = FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=384)
schema = CollectionSchema(fields=[id, field], description="movie recommender: film vectors", enable_dynamic_field=True)
if utility.has_collection(COLLECTION_NAME): # drop the same collection created before
collection = Collection(COLLECTION_NAME)
collection.drop()
collection = Collection(name=COLLECTION_NAME, schema=schema)
print("Collection created.")
index_params = {
"index_type": "IVF_FLAT",
"metric_type": "L2",
"params": {"nlist": 128},
}
collection.create_index(field_name="embedding", index_params=index_params)
collection.load()
print("Collection indexed!")
Agora que você tem uma coleção indexada, crie uma função para gerar os embeddings para o texto. Embora overview seja a coluna principal usada para gerar os embeddings, você também usará as informações de genre e release data junto com um overview para tornar os dados mais lógicos.
Para gerar os embeddings, use o SentenceTransformer:
from sentence_transformers import SentenceTransformer
import ast
# function to extract the text from genre column
def build_genres(data):
genres = data['genres']
genre_list = ""
entries= ast.literal_eval(genres)
genres = ""
for entry in entries:
genre_list = genre_list + entry["name"] + ", "
genres += genre_list
genres = "".join(genres.rsplit(",", 1))
return genres
# create an object of SentenceTransformer
transformer = SentenceTransformer('all-MiniLM-L6-v2')
# function to generate embeddings
def embed_movie(data):
embed = "{} Released on {}. Genres are {}.".format(data["overview"], data["release_date"], build_genres(data))
embeddings = transformer.encode(embed)
return embeddings
Esta função usa o método build_genres() para limpar a coluna de gênero e extrair o texto dela. Em seguida, ela cria um objeto SentenceTransformer para ajudar a gerar os embeddings a partir do texto. Por fim, ela usa o método encode() para gerar os embeddings usando os recursos overview, release_date e genre.
Envie embeddings para o Milvus
Agora você pode criar os embeddings usando o método embed_movie(). Este conjunto de dados é grande demais para ser enviado ao Milvus em uma única instrução insert, mas enviar linhas de dados uma por vez criaria tráfego de rede desnecessário e acrescentaria muito tempo. Portanto, em vez disso, crie lotes (por exemplo, 5.000 linhas) de dados para enviar ao Milvus:
# Loop counter for batching and showing progress
j = 0
batch = []
for movie_dict in movies_dict:
try:
movie_dict["embedding"] = embed_movie(movie_dict)
batch.append(movie_dict)
j += 1
if j % 5 == 0:
print("Embedded {} records".format(j))
collection.insert(batch)
print("Batch insert completed")
batch=[]
except Exception as e:
print("Error inserting record {}".format(e))
pprint(batch)
break
collection.insert(movie_dict)
print("Final batch completed")
print("Finished with {} embeddings".format(j))
Observação: Você pode ajustar o tamanho do lote para atender às suas necessidades e preferências individuais. Além disso, alguns filmes falharão para IDs que não podem ser convertidos para inteiros. Você poderia corrigir isso com uma alteração de esquema ou verificando o formato deles.
Enviar embeddings para o Milvus
Recomende novos filmes usando o Milvus
Agora você pode aproveitar a funcionalidade de pesquisa vetorial quase em tempo real do Milvus para obter uma correspondência próxima de filmes que atendam aos critérios do espectador. Para isso, crie duas funções diferentes:
embed_search(): Você precisa de um transformer para converter a string de pesquisa do usuário em um embedding. Esta função pega os critérios do espectador e os passa para o mesmo transformer que você usou para popular o Milvus.
search_for_movies(): Esta função realiza a pesquisa vetorial propriamente dita usando a outra função como suporte.
# load collection memory before search
collection.load()
# Set search parameters
topK = 5
SEARCH_PARAM = {
"metric_type":"L2",
"params":{"nprobe": 20},
}
# convert search string to embeddings
def embed_search(search_string):
search_embeddings = transformer.encode(search_string)
return search_embeddings
# search similar embeddings for user's query
def search_for_movies(search_string):
user_vector = embed_search(search_string)
return collection.search([user_vector],"embedding",param=SEARCH_PARAM, limit=topK, expr=None, output_fields=['title', 'overview'])
O código acima define os parâmetros topK para obter os cinco principais vetores semelhantes, metric_type como L2 (euclidiana ao quadrado), que calcula a distância entre dois vetores, e nprobe, que indica o número de unidades de cluster a pesquisar. Ele também implementa diferentes funções para obter vetores semelhantes a partir da consulta do usuário (recomendação).
Por fim, use a função search_for_movies() para recomendar filmes com base na string de pesquisa do usuário:
from pprint import pprint
search_string = "A comedy from the 1990s set in a hospital. The main characters are in their 20s and are trying to stop a vampire."
results = search_for_movies(search_string)
# check results
for hits in iter(results):
for hit in hits:
print(hit.entity.get('title'))
print(hit.entity.get('overview'))
print("-------------------------------")
Recomendar filmes
Ao usar o recurso de pesquisa vetorial do Milvus, o código recomenda os cinco principais filmes semelhantes com base na consulta do usuário. É isso: agora você criou seu próprio sistema de recomendação de filmes usando o Milvus.
Conclusão
Depois de ler este artigo, você sabe o que é um sistema de recomendação baseado em vetores e como criar um sistema de recomendação de filmes com o Milvus. O Milvus ajuda a criar um sistema de recomendação de filmes eficiente e escalável. Aproveitando o armazenamento vetorial e a pesquisa por similaridade, o Milvus tem grande potencial para possibilitar recomendações personalizadas, aumentar o engajamento dos usuários e demonstrar o papel dos modelos avançados baseados em vetores nos sistemas de recomendação modernos. Você pode saber mais sobre isso no site do Milvus.
Continue lendo

From Vector Database to Vector Lakebase
Zilliz offers a fully managed Vector Lakebase powered by Milvus, unifying real-time vector search, lake-scale discovery, and Al data operations.

Introducing Business Critical Plan: Enterprise-Grade Security and Compliance for Mission-Critical AI Applications
Discover Zilliz Cloud’s Business Critical Plan—offering advanced security, compliance, and uptime for mission-critical AI and vector database workloads.

Introducing Zilliz MCP Server: Natural Language Access to Your Vector Database
Developers can easily manage and query vector databases with natural language via Zilliz MCP Server in AI-native environments.



