Confissões de um PyMongoArrowholic: usando Atlas Vector Search e PyMongoArrow para pesquisar semanticamente itens de moda de luxo
Avalie esse Tutorial
Como um jovem de vinte e poucos anos que mora na cidade de Nova York, as compras online são meu segundo hobby favorito. Qual é o meu primeiro, você pergunta? Descobrir maneiras de otimizar meu vício em compras para que eu possa passar menos horas rolando.
Qualquer pessoa que fantasie com luxo (isso se chama manifestação, pessoal!) conhece o Net-A-Porter e todas as peças incríveis que o site oferece. Embora minha abordagem normal seja classificar por preço, do mais baixo ao mais alto, eu estaria mentindo se dissesse que não é incrivelmente divertido ver o escopo completo do que existe por aí. Então, vamos usar um conjunto de dados divertido que contém os itens da última temporada do Net-A-Porter e fazer uma busca semântica para explorar alguns dos itens mais caros, de qualquer marca, qualquer categoria e com consultas em linguagem natural.
Neste tutorial, usaremos o MongoDB Atlas, a bibliotecaPyMongoArrow , o MongoDB Atlas Vector Search e um conjunto de dados de moda de privilégio do Kaggle.
Antes de começarmos, vamos abordar alguns dos aspectos importantes que nos ajudarão a alcançar nosso resultado geral.
PyMongoArrow é uma biblioteca Python para análise de dados com MongoDB. Como nosso conjunto de dados é um arquivo
.csv
, vamos lê-lo usando a biblioteca Pandas, então ele será lido como um dataframe Pandas. Com a bibliotecapymongoarrow
, podemos exportar todos os nossos dados para o MongoDB Atlas no formato mais ideal para o nosso tutorial com algumas etapas fáceis. Ele é baseado no pymongo
, então nos permite trabalhar com dados do MongoDB de uma maneira superfácil e de alto desempenho. Ao trabalhar neste tutorial, você verá como é simples transferir seus dados e configurá-los ao usar a bibliotecapymongoarrow
, um problema com o qual muitos desenvolvedores de dados lidaram no passado.O MongoDB Atlas Vector Search realmente revolveu os recursos de pesquisa do Atlas. Ele permite que você Atlas Search semanticamente através do seu banco de dados facilmente, mantendo suas incorporações vetoriais no mesmo local que seus dados de origem. Pesquisar semanticamente significa Atlas Search por significado, portanto, em vez de usar palavras-chave exatas, podemos consultar e receber resultados que transmitem a mesma ideia sem palavras precisas.
Por exemplo, em vez de pesquisar o tamanho da amostra usando query simples como "dress, ", podemos usar frases ou generalidades, como "summer beach tropical " ou apenas "summer. ". Vamos utilizar o
$vectorSearch
estágio de agregação neste tutorial, que simplifica ainda mais o uso do Atlas Vector Search.Vamos começar!
- IDE de sua escolha — este tutorial usa o Google CoLab. Sinta-se à vontade para executar os comandos diretamente no bloco de anotações.
- Uma conta do MongoDB Atlas conta
- Uma chave de API OpenAI - é assim que vamos incorporar nossos dados antes de carregá-los no MongoDB Atlas.
Depois que seu cluster for criado e você tiver baixado o conjunto de dados localmente, você estará pronto para começar!
Nosso primeiro passo é fazer upload do nosso arquivo
.csv
no Google Colab. No lado esquerdo do Google Colab, acesse a seção “Arquivos”. Selecione o arquivonet-a-porter.csv
baixado e faça upload. Depois que seu arquivo for carregado, precisamos fazer duas coisas importantes:
- Precisamos usar o OpenAI para criar incorporações em cada item em nosso arquivo.
- Precisamos limpar nosso conjunto de dados e reconfigurá-lo em um formato mais adequado ao nosso objetivo final, que é garantir que possamos usar a pesquisa semântica para encontrar itens em nosso banco de dados.
Se você dar uma olhada no seu arquivo
.csv
, notará que ele consiste em quatro colunas (marca, descrição, preço_usd, tipo) e uma variedade de linhas. Precisamos adicionar uma coluna em nosso dataframe que contenha as incorporações para nossas descrições de itens. Para incorporar cada descrição de item, usaremos o modelode incorporação "text-embedding-3-small" e esta função de incorporação:
1 def get_embedding(text): 2 embedding = openai.embeddings.create(input=text, model=EMBEDDING_MODEL).data[0].embedding 3 return embedding
Também precisamos usar a biblioteca
pandas
para trabalhar com os dados que temos disponíveis. Pandas é uma biblioteca Python usada para trabalhar com conjuntos de dados e é superchave ao analisar, limpar, explorar e manipular dados.Para começar, queremos instalar nossas dependências. Isso significa instalar
openai
e importar pandas
.1 !pip install openai 2 import pandas as pd 3 import openai
Agora, precisamos pegar nossa chave secreta OpenAI. Certifique-se de salvar sua chave em algum lugar seguro e não a compartilhe em nenhum lugar, pois ela é muito sensível. Neste tutorial, para manter as coisas simples e demonstrar outras funcionalidades disponíveis, estamos codificando em nossa chave de API, mas na produção ou em qualquer outro lugar, é importante armazenar seus valores sensíveis em um arquivo
.env
.Copie sua chave e a função de incorporação de cima:
1 # we need our openai secret key 2 openai.api_key = 'OPENAI-APIKEY' 3 4 5 # we are going to use this embedding model for text 6 EMBEDDING_MODEL = "text-embedding-3-small" 7 8 9 # this is the embedding function we will use to create our embeddings for the descriptions 10 def get_embedding(text): 11 embedding = openai.embeddings.create(input=text, model=EMBEDDING_MODEL).data[0].embedding 12 return embedding
Nós nos preparamos para o sucesso no processamento de nossos embeddings, então vamos configurar nosso dataframe!
Primeiro, queremos ler o arquivo que acabou de ser carregado:
1 # we want to read in our file that we just uploaded 2 df = pd.read_csv('/content/net-a-porter.csv')
Queremos nos concentrar apenas nas três primeiras colunas, já que não precisamos necessariamente da coluna
type
, então vamos soltá-la:1 # drop the 'type' column 2 df.drop(columns=['type'], inplace=True)
É importante garantir que as colunas com as quais estamos lidando estejam limpas e não tenham valores nulos. Isso é crucial porque valores nulos podem atrapalhar nossos dados a longo prazo, e é uma boa prática sempre garantir que você esteja trabalhando com um conjunto de dados limpo. Para fazer isso, use
dropna
:1 # this is just saying to drop null values from our specific subsets, we want 'brand', price_usd', and 'description' 2 df.dropna(subset=['brand', 'price_usd', 'description'], inplace=True)
Para garantir que não estamos gastando muito dinheiro e tempo incorporando cada descrição em nosso grande conjunto de dados, vamos dividi-lo em 100 linhas. Isso ainda nos fornecerá um tamanho de amostra interessante, mas não ocupará muitos recursos:
1 # cut our entire file down to just 100 rows so that we don't spend a million dollars embedding the file 2 df = df.head(100)
Agora, estamos prontos para criar uma nova coluna para onde nossas incorporações Go e, em seguida, podemos imprimir nossas primeiras 20 linhas apenas para garantir que estamos no caminho certo:
1 # this is creating a new column with the embeddings 2 df["description_embedding"] = df['description'].apply(get_embedding) 3 4 5 # this is going to give us the first twenty rows from our file 6 print(df.head(20))
Esse deve ser seu resultado, com a nova coluna
description_embedding
:Como você pode ver, temos um dataframe com as colunas de que precisamos e, especificamente, nossa coluna
description_embedding
recém-incluída ! Vamos nos certificar de que podemos salvar isso em nosso cluster para que possamos usar o MongoDB Atlas Vector Search quando estivermos prontos para fazê-lo.Como o
pymongoarrow
usa o Apache Arrow nos detalhes, para mover nossos dados para o MongoDB Atlas, precisamos converter nosso dataframe do Pandas em uma tabela do Arrow. A grande parte das tabelas Arrow é que elas permitem colunas aninhadas, portanto, se tivéssemos um conjunto de dados mais complicado, não precisaremos pular muitos arcos para acomodar o aninhamento.Agora que temos todos os nossos itens e incorporações, vamos usar
pymongoarrow
para importar todos os nossos dados para o MongoDB Atlas. Utilize um comandopip
para instalar o pymongo
, pymongoarrow
e pyarrow
.1 !pip install pymongo pymongoarrow pyarrow
Depois que isso for feito, podemos classificar nossos itens do mais caro ao mais barato (apenas por conveniência) e, em seguida, podemos importar todos os nossos itens para o cluster. Certifique-se de ter sua cadeia de conexão MongoDB disponível para que você possa se conectar ao seu cluster e executar esta etapa. Embora estejamos codificando isso para este tutorial, lembre-se de que não é seguro e as variáveis devem sempre ser armazenadas em um arquivo separado.
Copie o código abaixo para fazer isso:
1 from pymongo import MongoClient 2 from pymongoarrow.api import write 3 import pyarrow as pa 4 5 6 # I want to sort by most expensive item to least expensive 7 df = df.sort_values(by=['price_usd'], ascending=False) 8 9 10 # this is your connection to your cluster 11 connection_string = "MONGODB-CONNECTION-STRING" 12 client = MongoClient(connection_string) 13 14 15 # you can name your database and collection anything you like 16 database = client['net-a-porter'] 17 collection = database['average_prices_descending'] 18 19 20 # in order to save our data, we need to first convert our Pandas DataFrame to an Arrow Table using pyarrow 21 arrow_table = pa.Table.from_pandas(df) 22 23 24 write(collection, arrow_table) 25 26 27 print("Successful") 28 print(arrow_table)
Depois de executar esse bloco de código, certifique-se de verificar novamente no MongoDB Atlas se tudo está conforme o esperado. As linhas do seu arquivo
.csv
terão sido transformadas em documentos separados, com cada coluna como um novo campo. Certifique-se de que seu novo campodescription_embedding
também esteja incluído!Agora que temos nossos documentos incorporados, podemos configurar o MongoDB Atlas Vector Search.
Vamos começar a pesquisar semanticamente nos dados recém-importados. Primeiro, precisamos criar um MongoDB Atlas Vector Search. Para fazer isso, acesse sua conta do Atlas e siga as etapas.
Depois de concluído, deve ficar assim.
1 { 2 "fields": [ 3 { 4 "numDimensions": 1536, 5 "path": "description_embedding", 6 "similarity": "cosine", 7 "type": "vector" 8 } 9 ] 10 }
O caminho que estamos usando é
description_embedding
, pois queremos que o índice do Vector Search seja usado em relação à nossa coluna de incorporação recém-incorporada. Para o camposimilarity
, estamos escolhendo "euclidean,", mas, dependendo do seu caso de uso, você pode usar "cosine" ou "dot-product."Mantenha seu "Index Name" como "vector_index," ou altere-o para algo que você se lembre, mas certifique-se de ter selecionado o banco de dados e a coleção corretos. Depois de salvar seu índice e carregá-lo, você saberá que ele está ativo quando o status for assim.
Tenha em mente que seu índice do Vector Search está isolado do MongoDB Atlas. Não faz parte do seu script Python geral e você não deve estar executando o índice em seu script.
Agora, Go ao arquivo do Google CoLab. Para pesquisar semanticamente, precisamos incorporar nossas queries. Essa é uma parte muito importante: Quando usamos a pesquisa semântica, não estamos comparando vetores com texto - estamos comparando vetores com vetores! Faça isso com estas duas linhas:
1 # my query 2 query_description = "summer" 3 4 5 # we need to embed the query as well, since our documents are embedded 6 query_vector = get_embedding(query_description)
Como já usamos o modelo de incorporação acima, também não é preciso muito trabalho incorporar nossas consultas.
Agora, precisamos definir o pipeline de agregação para que possamos pesquisar semanticamente. Podemos fazer isso usando
$vectorSearch
. O pipeline tem a seguinte aparência:1 # write the aggregation pipeline 2 pipeline = [ 3 { 4 '$vectorSearch': { 5 'index': 'vector_index', 6 'path': 'description_embedding', 7 'queryVector': query_vector, 8 # I only had 100 rows saved so that it's easier to use OpenAI 9 'numCandidates': 100, 10 'limit': 5 11 } 12 }, 13 { 14 '$project': { 15 # i do not need to see the ID, but I do want to see my other columns. 16 '_id': 0, 17 'brand': 1, 18 'description': 1, 19 'price_usd': 1, 20 'score': { 21 '$meta': 'vectorSearchScore' 22 } 23 } 24 }, 25 { 26 '$sort': { 27 'price_usd': -1 # sort by most expensive to least expensive 28 } 29 } 30 ]
Como você pode ver, usamos o recurso
$project
para mostrar apenas os campos que desejamos. Também usamos $vectorSearch para definir o índice, o caminho e nosso vetor de consulta. Verifique novamente se todos os campos estão corretos antes de prosseguir. Caso contrário, ele não será executado.Depois que o pipeline for gravado, defina em qual banco de dados e coleção você deseja que ele seja executado e imprima os resultados:
1 # the pipeline is run on this database and collection 2 database = client['net-a-porter'] 3 collection = database['average_prices_descending'] 4 result = collection.aggregate(pipeline) 5 6 7 8 9 for clothing in result: 10 print(clothing)
Neste tutorial usamos a query simples de "summer " e estes são os nossos resultados:
É interessante aqui porque quando eu perguntei sobre "summer," itens que incluíam meses de verão apareceram, como o mês de agosto.
Vamos mudar nossa query para "winter " e ver os resultados. Como você pode ver, do tamanho da nossa amostra, estamos obtendo resultados voltados para o clima mais frio, como casacos, jaquetas de esqui e calças de lã.
Eles também são classificados em ordem decrescente, do mais caro para o mais barato (para sonhar!), e podemos pesquisar os itens com rolagem limitada. Portanto, se você estiver no melhor modo de descanso e precisar de um modelo de cashmere com capuz e calça de moletom que custará quase $1300 (antes de impostos), você sabe onde procurar.
Embora este tutorial tenha sido feito usando um conjunto de dados simples, depois de realmente entender os conceitos sobre como incorporar as plataformas e bibliotecas introduzidas, sinta-se à vontade para criar um web scraper e tentar esse mesmo método em dados ao vivo.
Este tutorial fornece uma ótima visão geral do que é possível fazer com o PyMongoArrow e o MongoDB Atlas Vector Search. Conseguimos pegar um conjunto de dados, processá-lo usando o Pandas, gerar as incorporações necessárias com o OpenAI, armazenar nossa recém-desenvolvida tabela Arrow no MongoDB Atlas usando PyMongoArrow e, em seguida, consultar semanticamente nosso banco de dados.
Para obter mais informações sobre o PyMongoArrow, acesse a documentaçãoe, para obter mais informações sobre oMongoDB Atlas Vector Search, consulte o tutorial. Se você tiver dúvidas ou quiser compartilhar seu trabalho, junta-se a nós na comunidade de desenvolvedores do MongoDB.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.