Planejador de partes favoritas do operador Joe com Playwright, LlamaIndex e MongoDB Atlas Vector Search
Avalie esse Tutorial
Como alguém que sobrevive apenas de petiscos, o MongoDB é para nós o que o Costco é para meus pais: uma cozinha não negociável.
Quando eu vivi na mesma milha 0.2 raio de um durante a Universidade, ir era uma ocorrência diária (às vezes várias vezes ao dia). Quer pegar um Iogurte no café da manhã? Uma Salada para o Almoço? Pegar alguns itens congelados e fazer um festim para o menu do motorista? O operador Joe tinha de tudo e muito mais, especialmente as coisas que você nem notou que estava faltando. De "Everything But the Bagel " tempero a "Philly Cheesesteak Bao Buns, ", cada viagem doTrader Joe vem com algo novo para a sua despensa e o seu sabor.
O fato de o MongoDB ter todos os produtos legalizados que você vai querer servir durante o Dia de Ação de Graças o torna a escolha mais fácil para as festividades de fim de ano. Mas e todos os outros fatores do planejamento de uma grupo, como o esgotamento de uma decisão, ou ter que ficar em longas filas tentando ver cada produto de queda que os TJ têm a oferecer e depois decidir entre eles? É aqui que uma combinação incrivel de Playwright, LlamaIndex e MongoDB Atlas Vector Search entram para salvar o dia.
Vamos usar essas plataformas para criar um planejador de festividades de fim de ano do Trader Joe. Usaremos oPlaywright para raspar o site doTrader Joe para todos os produtos relacionados ao queda, o LlamaIndex e a Integração de Atlas Vector Search para criar um chatbot de geração aumentada de recuperação (RAG) com nossos produtos de queda como nosso armazenamento de dados e Mecanismo de bate-papo do LlamaIndex para obter as respostas mais interativas e de conversação com base em nossos dados de produtos de queda para que possamos planejar a melhor parte!
O que está coberto
- Construindo um planejador de AI festividades de IA do analista usando Playwright, LlamaIndex e MongoDB Atlas Vector Search
- Raspando os itens de queda do Corretor Joe com o Playwright e formatando-os para uso do chatbot
- Configuração e incorporação de dados do produto no MongoDB Atlas Vector Store para pesquisa semântica
- Criação de um chatbot de geração aumentada de recuperação de recuperação para responder a perguntas de planejamento de festividades
- Adicionando funcionalidade de mecanismo de bate-papo interativo para perguntas e respostas sobre itens de queda
Antes de mergulhar de cabeça, vamos Go examinar essas plataformas com mais detalhes.
O Playwright torna super fácil retornar elementos dinâmicos de sites, e é por isso que ele foi escolhido para este tutorial. Depois de inspecionar o website do MongoDB, ficou claro que o JavaScript é necessário para carregar o conteúdo e os vários produtos que podemos ver, o que significa que o conteúdo da página é renderizado dinamicamente! Por causa disso, outros raspadores Python simples não funcionariam para raspar os itens que procuramos.
MongoDB Atlas Vector Search é um recurso no MongoDB Atlas que permite armazenar e consultar incorporações vetoriais em seu banco de dados de dados. Ele permite que você crie aplicativos incríveis que exigem pesquisa semântica ou pesquisa com base no significado e no contexto, em vez de palavras-chave exatas.
Neste tutorial, com nosso planejador de partes, usamos o MongoDB Atlas Vector Search como nossa camada de armazenamento e recuperação de dados. Ele nos permite armazenar todas as nossas incorporações de produtos de queda e pesquisar os itens mais relevantes dependendo de nossas consultas!
A integração do LlamaIndex e do MongoDB Atlas Vector Search combina ambas as plataformas, permitindo que o LlamaIndex organize e consulte os dados. Ao mesmo tempo, o Atlas Vector Search tem armazenamento vetorial e recursos de pesquisa semântica. Portanto, todas as informações do nosso produto (os produtos do Traer Joe que raspamos) são vetorizadas e armazenadas em nosso cluster.
Então, o que isso média? Isso significa que, quando uma pergunta é feita — como "Which three sides are best served if I’m making a turkey? " — a LlamaIndex obtém o produto mais preciso comparando diferentes vetores armazenados no MongoDB Atlas, garantindo que as respostas sejam baseadas no significado geral!
Certifique-se de ter os seguintes pré-requisitos para ser bem-sucedido:
- IDE de sua escolha: este tutorial usa um bloco de anotações do Google CoLab. Sinta-se à vontade para acompanhar.
- Chave de API OpenAI: você precisará pagar para acessar uma chave de API.
- Cluster MongoDB Atlas : certifique-se de que está usando uma camada grátis, de que seu endereço IP esteja definido como " "access from anywhere(não é recomendado para produção, mas é perfeitamente adequado para este tutorial) e de que você copiou a string de conexão do cluster para um local seguro.
Quando você tiver todos os requisitos do tutorial, estamos prontos para começar!
Inspecione seu website!
Nosso primeiro passo é inspecionar todos os favoritos de queda do site doTrader Joe e salvá-los para que possamos raspar o site facilmente. OTraderJoe's facilita isso para nós, pois eles já indexam tudo em tags específicas. Então, vamos clicar naFood categoria “ ”, role para baixo e clique naFall Faves tag “ . Ambas as opções estão no lado esquerdo da página da web.
Quando pudermos ver que esses são todos os itens "Fall Faves, ", salve o URL. Agora, podemos fazer isso novamente para todas as outras categorias:Bebidas,Flores e plantas e tudo mais! Certifique-se de que estamos focados apenas nos produtos listados na tag "Fall Faves ".
Lembre-se de que, como estamos lidando com dados ativos, esses produtos e opções podem mudar dependendo de quando você decidir raspar as informações, de modo que os produtos que aparecem para nós podem parecer diferentes para você!
Depois de conhecermos os URLs dos quais extrairemos, vamos descobrir quais seletores também precisamos. Queremos formatar nossos produtos como "Name " e "Price. "
A maneira mais fácil de encontrar essas informações é realçar o nome de um item, clicar com o botão direito do mouse e pressionar "Inspect. ". Em seguida, você pode abrir cada menu suspenso até encontrar as informações que está procurando!
Aqui, podemos ver que cada nome de produto está localizado em uma tag "h2 " dentro de uma classe"ProductCard_card__title__text__uiWLe a ", e cada preço está localizado em uma tag "span " dentro de uma classe"ProductPrice_productPrice__price__3-50j ". Recomendamos verificar dois ou mais produtos para garantir que esse padrão esteja por toda parte.
Também podemos ver que todos os produtos estão aninhados dentro de tags "li " na classe"ProductList_productList__item__1EIvq ".
Isso significa que teremos que esperar que essa classe apareça durante a raspagem antes de podermos Vá em frente Go e extrair as informações dela.
Agora que temos nossos fall Fevers e sabemos exatamente onde estão as informações que queremos recuperar, estamos prontos para criar nossa função de raspagem.
Primeiro, vamos instalar o Playwright:
1 !pip install playwright 2 !playwright install
Quando terminar de instalar, podemos importar nossos pacotes necessários:
1 import asyncio 2 from playwright.async_api import async_playwright
Lembre-se de que estamos usando
async
porque estamos executando tudo dentro de um bloco de anotações do Google CoLab.Agora, vamos começar a construir nosso
traderJoesScraper
:1 async def traderJoesScraper(): 2 async with async_playwright() as playwright: 3 # use headless mode since we are using Colab 4 browser = await playwright.chromium.launch(headless=True) 5 page = await browser.new_page() 6 7 8 # all the URLs for my foods, bevs, flowers&plants, and everything else categories 9 pages = [ 10 {'url': 'https://www.traderjoes.com/home/products/category/food-8?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%7D', 'category': 'Food'}, 11 {'url': 'https://www.traderjoes.com/home/products/category/food-8?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%2C%22page%22%3A2%7D', 'category': 'Food'}, 12 {'url': 'https://www.traderjoes.com/home/products/category/food-8?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%2C%22page%22%3A3%7D', 'category': 'Food'}, 13 {'url': 'https://www.traderjoes.com/home/products/category/food-8?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%2C%22page%22%3A4%7D', 'category': 'Food'}, 14 {'url': 'https://www.traderjoes.com/home/products/category/food-8?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%2C%22page%22%3A5%7D', 'category': 'Food'}, 15 {'url': 'https://www.traderjoes.com/home/products/category/beverages-182?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%7D', 'category': 'Beverage'}, 16 {'url': 'https://www.traderjoes.com/home/products/category/flowers-plants-203?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%7D', 'category': 'Flowers&Plants'}, 17 {'url': 'https://www.traderjoes.com/home/products/category/everything-else-215?filters=%7B%22tags%22%3A%5B%22Fall+Faves%22%5D%7D', 'category': 'EverythingElse'} 18 ] 19 20 21 items = [] 22 23 24 # loop through each URL 25 for info in pages: 26 await page.goto(info['url']) 27 28 29 # let page load 30 await page.wait_for_selector('li.ProductList_productList__item__1EIvq', state='attached', timeout=60000) 31 32 33 # li.ProductList_productList__item__1EIvq is where all our info lives 34 products = await page.query_selector_all('li.ProductList_productList__item__1EIvq') 35 36 37 # get all our info 38 for product in products: 39 result = {} 40 41 42 name = await product.query_selector('h2.ProductCard_card__title__text__uiWLe a') 43 price = await product.query_selector('span.ProductPrice_productPrice__price__3-50j') 44 45 46 if name and price: 47 result['name'] = await name.inner_text() 48 49 50 # have to make price a number 51 price_text = await price.inner_text() 52 convert_price = float(price_text.replace('$', '').strip()) 53 result['price'] = convert_price 54 55 56 # category is so we can save it nicely later 57 result['category'] = info['category'] 58 items.append(result) 59 60 61 for item in items: 62 print(f"Name: {item['name']}, Price: {item['price']}, Category: {item['category']}") 63 64 65 await browser.close() 66 return items 67 68 69 70 71 scraped_products = await traderJoesScraper() 72 print(scraped_products)
Começamos colocando manualmente todos os links dos quais queremos extrair as informações. Lembre-se de que, se você deseja transformar isso em um aplicação escalável, é recomendável usar a paginação para esta parte, mas, por uma questão de simplicidade, podemos inseri-los manualmente.
Em seguida, percorremos cada uma das URLs listadas, aguardamos que nosso seletor principal aparecesse com todos os elementos que espervamos raspar e, em seguida, extraímos nosso "name " e "price. "
Depois de executar isso, obtemos uma lista de todos os nossos produtos da tag fall Fevers! Lembre-se de que esta captura de tela não inclui todos os produtos raspados.
Para acompanhar os itens, podemos contá-los rapidamente:
1 scraped_products_count = len(scraped_products) 2 print(scraped_products_count)
Na data em que foi raspado, Tínhamos 89 produtos.
Agora, vamos salvar nossos produtos em um
.txt
arquivo para que possamos usá-lo mais tarde em nosso tutorial quando estivermos usando nossa integração entre o LlamaIndex e o Atlas Vector Search . Dê um nome ao arquivo como quiser. Para fins de rastreamento, estou nomeando o meu tj_fall_faves_oct30.txt
.1 with open('tj_fall_faves_oct30.txt', 'w') as f: 2 for item in scraped_products: 3 f.write(f"Name: {item['name']}, Price: ${item['price']}, Category: {item['category']}\n")
Como estamos usando um bloco de anotações, certifique-se de baixar o arquivo localmente, pois, assim que nosso tempo de execução for desconectado, o
.txt
arquivo será perdido.Agora que temos todos os produtos AI de fim de semana do nosso Trocador Joe, vamos construir nosso Planejador de partes do IA!
Para ter sucesso com esta parte do tutorial, siga nosso início rápido. Veremos como usar o Atlas Vector Search com o LlamaIndex para criar um aplicação RAG com recursos de bate-papo!
Esta seção abordará em detalhes como configurar o ambiente, armazenar nossos dados personalizados que raspamos anteriormente no Atlas, criar um índice do Atlas Vector Search sobre nossos dados e, para finalizar, implementaremos o RAG e usaremos o Atlas Vector Search para responder a perguntas do nosso armazenamento de dados exclusivo.
Vamos primeiro usar
pip
o para instalar todas as nossas bibliotecas necessárias. Vamos precisar incluir llama-index
, llama-index-vector-stores-mongodb
e llama-index-embeddings-openai
.1 pip install --quiet --upgrade llama-index llama-index-vector-stores-mongodb llama-index-embeddings-openai pymongo
Agora, importe as declarações de importação necessárias:
1 import getpass, os, pymongo, pprint 2 from pymongo.operations import SearchIndexModel 3 from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, StorageContext 4 from llama_index.core.settings import Settings 5 from llama_index.core.retrievers import VectorIndexRetriever 6 from llama_index.core.vector_stores import MetadataFilter, MetadataFilters, ExactMatchFilter, FilterOperator 7 from llama_index.core.query_engine import RetrieverQueryEngine 8 from llama_index.embeddings.openai import OpenAIEmbedding 9 from llama_index.llms.openai import OpenAI 10 from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch
Insira sua chave de API OpenAI e sua string de conexão do MongoDB Atlas cluster quando solicitado:
1 os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") 2 ATLAS_CONNECTION_STRING = getpass.getpass("MongoDB Atlas SRV Connection String:")
Quando suas chaves estiverem dentro, vamos atribuir nossos modelos específicos para
llama_index
para que ele saiba como incorporar nosso arquivo corretamente. Isso é apenas para manter tudo consistente!1 Settings.llm = OpenAI() 2 Settings.embed_model = OpenAIEmbedding(model="text-embedding-ada-002")
Agora, podemos ler nosso
.txt
arquivo com nossos produtos raspados. Estamos fazendo isso usando o SimpleDirectoryReader
de .llama_index
Os arquivos de texto não são os únicos arquivos que podem ser bem carregados no LlamaIndex. Há muitos outros métodos suportados, e nós recomendamos verificar alguns dos tipos de arquivos suportados.Então, aqui estamos, lendo o conteúdo de nosso arquivo e devolvendo-o como uma lista de documentos, o formato que o LlamaIndex exige.
1 sample_data = SimpleDirectoryReader(input_files=["/content/tj_fall_faves_oct30.txt"]).load_data() 2 sample_data[0]
Agora que nosso arquivo foi lido, vamos nos conectar ao nosso cluster MongoDB Atlas e configurar um armazenamento de vetor! Sinta-se livre para nomear o banco de dados de dados e a coleção como quiser. Estamos inicializando um armazenamento de vetor usando
MongoAtlasVectorSearch
de llama_index
, permitindo-nos trabalhar com nossos documentos incorporados diretamente em nosso cluster.1 # connect to your Atlas cluster 2 mongo_client = pymongo.MongoClient(ATLAS_CONNECTION_STRING, appname = "devrel.showcase.tj_fall_faves") 3 4 5 # instantiate the vector store 6 atlas_vector_store = MongoDBAtlasVectorSearch( 7 mongo_client, 8 db_name = "tj_products", 9 collection_name = "fall_faves", 10 vector_index_name = "vector_index" 11 ) 12 vector_store_context = StorageContext.from_defaults(vector_store=atlas_vector_store)
Já que nosso armazenamento de vetor foi definido (pelo nosso
vector_store_context
), vamos Go criar um índice vetorial no MongoDB para nossos documentos no sample_data
.1 vector_store_index = VectorStoreIndex.from_documents( 2 sample_data, storage_context=vector_store_context, show_progress=True 3 )
Depois que essa célula for executada, você poderá visualizar seus dados com as incorporações dentro do Atlas cluster.
Para permitir queries de pesquisa vetorial em nosso armazenamento de vetores criado, precisamos criar um índice do Atlas Vector Search em nossa coleção tj_products. fall_faves. Podemos fazer isso por meio da UI do Atlas ou diretamente de nosso bloco de anotações:
1 # Specify the collection for which to create the index 2 collection = mongo_client["tj_products"]["fall_faves"] 3 4 5 # Create your index model, then create the search index 6 search_index_model = SearchIndexModel( 7 definition={ 8 "fields": [ 9 { 10 "type": "vector", 11 "path": "embedding", 12 "numDimensions": 1536, 13 "similarity": "cosine" 14 }, 15 { 16 "type": "filter", 17 "path": "metadata.page_label" 18 } 19 ] 20 }, 21 name="vector_index", 22 type="vectorSearch", 23 ) 24 25 26 collection.create_search_index(model=search_index_model)
Você poderá ver esse índice quando ele estiver instalado e funcionando na aba "Atlas Search " na interface do usuário do Atlas . Depois de feito, podemos começar a consultar nossos dados e fazer alguns RAG básicos.
Com o nosso índice Atlas Vector Search instalado e funcionando, estamos prontos para nos AI Diversão e dar vida ao nosso IA Cluster Planner! Continuaremos com esse equipe dos ideais, onde usaremos o Atlas Vector Search para obter nossos documentos e o mecanismo de query do LlamaIndex para responder nossas perguntas com base em nossos documentos.
Para fazer isto, precisaremos que o Atlas Vector Search se torne um recuperador de índice vetorial e precisaremos inicializar um
RetrieverQueryEngine
para lidar com as queries, passando cada pergunta pelo nosso sistema de recuperação vetorial. Essa combinação nos permitirá fazer quaisquer perguntas que quisermos em linguagem natural e nos combinar com os documentos mais precisos.1 vector_store_retriever = VectorIndexRetriever(index=vector_store_index, similarity_top_k=5) 2 3 4 query_engine = RetrieverQueryEngine(retriever=vector_store_retriever) 5 6 7 response = query_engine.query('Which plant items are available right now? Please provide prices') 8 9 10 print(response)
Para a pergunta "Which plant items are available right now? Please provide prices, ", obtemos a resposta:
1 Mum Fleurettes are available for $4.99 and Assorted Mum Plants are available for $6.99.
Mas e se quisermos continuar fazendo perguntas e obter respostas com a memória? Vamos construir rapidamente um mecanismo de bate-papo.
Em vez de ter que fazer uma pergunta de cada vez sobre os produtos do nosso Expresso Mongo para a nossa festividade, podemos incorporar uma conversa de vai e vem para aproveitar ao máximo o nosso AI IA Planejador de festividades.
Primeiro precisamos inicializar o mecanismo de chat do nosso
vector_store_index
e habilitar uma resposta de transmissão. Omodo de pergunta condensada também é usado para garantir que o mecanismo reduza suas perguntas ou as reescreva para fazer mais sentido quando usado em uma conversa de vai e vem. A transmissão também está ativada, para que possamos ver a resposta:1 # llamaindex chat engine 2 chat_engine = vector_store_index.as_chat_engine( 3 chat_mode="condense_question", streaming=True 4 )
Então, podemos criar nosso loop de bate-papo! Este é apenas um
while
loop básico que será executado até que o usuário insira "exit. "1 while True: 2 # ask question 3 question = input("Ask away! Type 'exit' to quit >>> ") 4 5 # exit to quit 6 if question == 'exit': 7 print("Exiting chat. Have a happy fall!") 8 break 9 10 11 print("\n")
Nossa última etapa é enviar a resposta para nosso mecanismo de bate-papo e fluxo e exibir a resposta.
1 # llamaindex ask 2 response_stream = chat_engine.stream_chat(question) 3 4 # llamaindex print 5 response_stream.print_response_stream() 6 print("\n")
Execute os blocos de código acima e experimente você mesmo. Aqui estão minhas perguntas e respostas:
1 Ask away! Type 'exit' to quit >>> hi! i am planning a fall party 2 3 4 Consider including a variety of fall-themed food and beverages such as pumpkin pie, apple cider donuts, maple-flavored fudge, pumpkin spiced cookies, and harvest blend herbal tea to create a festive atmosphere for your fall party. Additionally, you could incorporate seasonal decorations like cinnamon brooms, scented candles, and mum plants to enhance the autumn ambiance. 5 6 Ask away! Type 'exit' to quit >>> i want to make a turkey, which three sides with prices and reasonings will be best 7 8 9 The best three side dishes to serve with turkey at a fall party would be Cut Butternut Squash, Brussels Sprouts, and Cornbread Stuffing. Cut Butternut Squash and Brussels Sprouts are reasonably priced at $3.99 and $4.99 respectively, offering a balance of flavors and textures that complement the turkey well. Cornbread Stuffing, priced at $5.99, adds a traditional touch to the meal and enhances the overall fall-themed dining experience. 10 11 Ask away! Type 'exit' to quit >>> which drinks should i serve? i want something caffinated 12 13 14 Harvest Blend Herbal Tea and Autumn Maple Coffee would be ideal caffeinated drinks to serve at a fall party to complement the autumn-themed food and create a festive atmosphere. 15 16 Ask away! Type 'exit' to quit >>> what are the prices of these drinks 17 18 19 $2.49 for Harvest Blend Herbal Tea and $8.99 for Autumn Maple Coffee. 20 21 Ask away! Type 'exit' to quit >>> which decor should i use? i want my home to smell nice 22 23 24 Cinnamon Whisk, Cinnamon Broom, Orange & Spice Scented Candle & Room Spritz 25 26 Ask away! Type 'exit' to quit >>> what are the prices? 27 28 29 $5.99, $1.29, $4.99 30 31 Ask away! Type 'exit' to quit >>> exit 32 Exiting chat. Have a happy fall!
Neste tutorial, construímos um planejador de festividades do Trocador superútil usando oPlaywright para raspar todos os itens favoritos do queda e a integração do LlamaIndex e do MongoDB Atlas Vector Search para salvar, incorporar e consultar nossos dados usando linguagem natural.
Demos um passo além e incorporamos um mecanismo de bate-papo em nosso tutorial para levar as coisas um passo além do apenas perguntas e respostas autônomo !
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.