Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Join us at AWS re:Invent 2024! Learn how to use MongoDB for AI use cases.
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Sorva, Swig e Pesquise Com Playwright, OpenAI e MongoDB Atlas Search

Anaiya Raisinghani12 min read • Published Sep 27, 2024 • Updated Oct 01, 2024
IAPythonAtlas
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
44The Secret Lives of Mormon Wives,
Se você ainda não experimentou um soda “dirty, eu o recomendamos. É uma combinação interessantes de qualquer soda de sua escolha, metade a metade ou natas e Xaropes aromáticos. Se você não curte soda, vai odiá-lo, mas temo que isso seja um dado. Admito que estava cético, mas se você preferir soda como sua bebida, sua maior conclusão será se perguntar quais outras coisas delicadas as pessoas de Utá estão ocultando do resto de nós.
Depois de consultar os profissionais (uma pesquisa muito rápida no Google), verifiquei que Swig é “home of the original dirty soda.”. J
Vamos usar o Playwright para raspar o menu com os componentes de seu website, as saídas estruturadas da OpenAI para nos ajudar a decidir quais bebidas são mais apropriadas para cada estação, e o MongoDB Atlas Search para filtrar nossos sodas "dirty" com base em seus componentes e o que desejamos.
Antes de começarmos, Go essas plataformas com um pouco mais de detalhes, para que estejamos todos na mesma página.

O que é o Playwright e por que o estamos usando?

O Playwright é uma poderosa ferramenta de automação de navegador que foi construída pela Microsoft. É útil para sites executados em mecanismos de renderização modernos, como o Storeium (o Google Chrome é executado nele), Firefox e WebKit, pois permite que os desenvolvedores criem novas páginas do navegador, abram vários URLs e até mesmo permite que você interaja com todos os elementos localizados em uma página.
O Playwright foi escolhido para este tutorial por ser simples retornar os elementos de um site, especialmente de sites dinâmicos, como o que estamos raspando. Embora haja uma série de outras capacidades incríveis para o Playwright, ele é ideal para o nosso caso de uso, pois nossos itens de bebida são carregados usando JavaScript após o carregamento da página inicial. Com outros raspadores de web Python mais tradicionais, eu estava recebendo erros de tempo limite ou listas vazias, pois os itens de menu não estavam incorporados no HTML bruto do site. O Playwright, por outro lado, pode lidar muito bem com a execução do JavaScript e espera que o conteúdo carregue totalmente antes de obter as informações de que precisamos.

O que são saídas estruturadas do OpenAI?

As novas Saídas estruturadas do OpenAI garantem que qualquer resposta da tenha exatamente a maneira especificada pelo desenvolvedor. Isso funciona forçando qualquer modelo que você use (estamos usando GPT- API 4o) a ter uma resposta que corresponda ao esquema fornecido pelo desenvolvedor. Este tutorial está usando-o para garantir que as bebidas do menu Swig sejam mostradas em um JSON formato estruturado, já que queremos analisar as respostas do modelo mais tarde no Go tutorial. como fazer isso em detalhes no tutorial!
O MongoDB Atlas Search é uma pesquisa de texto completo incorporada dentro do MongoDB Atlas, o serviço de banco de banco de dados em nuvem do MongoDBpara desenvolvedores. É crucial para este tutorial, pois salvaremos nossos itens de menu raspados em um cluster Atlas e, em seguida, criaremos um pipeline de agregação nos dados para descobrir quais bebidas correspondem à nossa estação e aos nossos componentes específicos.

Pré-requisitos do tutorial

Esses pré-requisitos são cruciais para garantir que sejamos bem-sucedidos neste tutorial.
  1. Um IDE de sua escolha: este tutorial usa um bloco de notas doGoogle CoLab. Sinta-se à vontade para acompanhar.
  2. Chave de API OpenAI: você precisará pagar para acessar uma chave de API.
  3. Cluster MongoDB Atlas : Verifique se você está usando a camada grátis, se definiu seu endereço IP como "access from anywhere, " e se copiou a string de conexão para um local seguro para referência futura.
Depois de salvar sua chave de API OpenAI em um local seguro, provisionar o cluster do MongoDB Atlas e salvar a string de conexão em um local seguro, você estará pronto para começar!

Parte 1: Raspar todos os itens de menu do site do Swig

Inspecione seu website!

Antes de escrever nossa função principal para raspar o website, precisamos ter certeza de que realmente inspecionamos o website que queremos raspar para que possamos descobrir corretamente onde ficam as informações que queremos.
Vá até Swig, clique na opção "Dirty Dr Pepper " ou em qualquer opção de soda de sua escolha e, em seguida, clique na loja American Fork. Isso é para ver todos os itens de menu disponíveis para um local. Você pode escolher qualquer local que quiser. rsrsrsrsrsrsrsrsrsrsrsrsrsrsrsrsrsrs,smites pelo, mas por ele porque foi o primeiro a ser exibido.
Clique no Suja Dr. Peper ou em qualquer opção de soda
Apenas escolhendo American Fork porque é o primeiro mostrado
Em seguida, você verá todos os itens de menu desse local, conforme mostrado abaixo: Itens de menu para a localização em American Fork
Agora, podemos clicar em qualquer soda, clique com o botão direito do mouse para inspecionar a página e ver com o que estamos trabalhando.
A primeira coisa que gostaria de destacar é que este website é um website dinâmico. Como posso saber disso? O Swig é um website dinâmico
Percebo que, quando TENTO inspecionar um item de menu para descobrir como raspar nosso HTML, as informações estão localizadas dentro de um iframe, o que significa que o conteúdo que pretendo raspar é HTML incorporado em outra página da Web. A partir deste exemplo, posso ver que tudo o que gostaria de encontrar (e sabe disso porque destaquei e inspeccionei outras partes, como o nome "Dirty Dr Pepper " e os componentes "Dr Pepper + Coconut (120 - 440 Calories) ") está aninhado sob o mesmo iframe URL, https://swig-orders.crispknow.com/tabs/locations/menu.
Então, o que média um website dinâmico? Isso significa que não posso simplesmente raspar o HTML do nível superior diretamente, pois o site está mudando e não carrega inteiramente de uma Go vez. Felizmente, o Playwright é um raspador que suporta esperar o carregamento dos outros elementos da página antes de raspar, mas nem todos os raspadores da web são iguais nisso. Antes de perceber isso, e ao usar um raspador diferente para tentar atingir meu objetivo, eu estava obtendo saídas vazias toda vez que executava meu código. Então, por favor, inspecione sua página da web antes de tentar raspar!
Depois de ter uma compreensão sólida do site que estamos tentando raspar, vamos escrever nossa função de raspagem.

Escreva nossa função de raspagem

Então agora, vamos raspar todos os itens do menu que o Swig oferece para ver quais combinações são mais adequadas para o queda. Queremos obter o nome de cada item do menu e sua descrição. Um exemplo disso é o nome "Dirty Dr Pepper 440 120 a descrição "Dr.
Para fazer isso, vamos primeiro instalar o próprio Playwright. Isso pode ser feito com uma simples declaraçãopip e lembre-se de que estamos executando isso em nosso bloco de anotações doGoogle Coab:
1!pip install playwright
2!playwright install
Agora, vamos definir nossas importações. Como estamos usando um bloco de anotações, precisamos usar async. Se você estiver trabalhando localmente por meio do seu IDE, fique à vontade para usar sync.
1import asyncio
2from playwright.async_api import async_playwright
Vamos usar o nome swigScraper para nossa definição. Mais uma vez, vamos usar async e, em seguida, o modo headless, pois estamos usando um laptop. Saiba mais sobre quando usar o modo headless versus headless.
Também queremos ter certeza de que estamos usando a URL correta . Lembre-se do que foi mencionado acima, queremos usar o URL localizado dentro do iframe do qual nossos elementos estão sendo gerados dinamicamente. Não queremos o URL normal do site Swig .
1async def swigScraper():
2 async with async_playwright() as playwright:
3
4 browser = await playwright.chromium.launch(headless=True)
5 page = await browser.new_page()
6
7 # make sure to have the correct URL
8 await page.goto('https://swig-orders.crispnow.com/tabs/locations/menu')
Como a página da web que estamos tentando raspar tem muitos elementos ocultos, vamos primeiro rolar pelo menu para ver o que carrega depois de cerca de um minuto. Em seguida, podemos clicar com o botão direito do mouse e inspecionar a página para ver onde nosso nome e descrição estão aninhados. Depois de rolar por um minuto, destaquei o nome da bebida e, em seguida, cliquei com o botão direito e selecionei "inspect. " Esta captura de tela mostra meu resultado:
Resultado da inspeção do nome da bebida
Como podemos ver nesta captura de tela, precisamos esperar o carregamento de nosso ion-card-content antes de podermos ver onde as informações que queremos estão. Isso nos permite terminar nossa função com um wait_for_selector dizendo que queremos esperar até que esse seletor específico carregue:
1await page.wait_for_selector('ion-card-content', state='attached', timeout=60000)
2
3
4# our items names and descriptions are all located in this area
5items = await page.query_selector_all('ion-card-content')
Agora, podemos criar uma lista para armazenar nosso menu, percorrer o HTML e pegar o que precisamos, extrair nosso texto e torná-lo bonito:
1 menu = []
2
3 for item in items:
4 result = {}
5
6 name = await item.query_selector('p.text-h3')
7 description = await item.query_selector('p.text-b2')
8
9 # use inner text to extract our info
10 if name and description:
11 result = {}
12 result['name'] = await name.inner_text()
13 result['description'] = await description.inner_text()
14 menu.append(result)
15
16 for item in menu:
17 print(f"Name: {item['name']}, Description: {item['description']}")
18
19 await browser.close()
20 return menu
21
22scraped_menu = await swigScraper()
23print(scraped_menu)
Nossos resultados ficarão assim: Resultados da raspagem do nosso menu Swig
Agora que temos todos os itens do nosso menu bem formatados, vamos usar as saídas estruturadas do OpenAI para saber quais bebidas são perfeitas para cada estação e por que!

Parte 2: Saídas do esquema estruturado OpenAI

Certifique-se de ter sua chave de API OpenAI pronta! Iremos usá-lo nesta seção.
Vamos usar saídas estruturadas para que possamos informar ao modelo exatamente o que estamos procurando e como queremos que nossa saída seja estilizada.
Nosso primeiro passo é instalar o OpenAI:
1!pip install openai
Agora, vamos importar openai junto com json e getpass para nossa chave de API OpenAI.
1import openai
2import json
3import getpass
Usando getpass, insira sua chave de API para que seja fácil usarmos esta seção do tutorial.
1# put in your OpenAI API key here
2openai_api_key = getpass.getpass(prompt= "Put in OpenAI API Key here")
Antes de começarmos, precisamos garantir que nosso menu esteja formatado corretamente para que o OpenAI e nosso modelo entendam. Podemos fazer isso colocando todas as nossas bebidas e suas descrições em uma única string. Também queremos informar à OpenAI nosso prompt para saber o que exatamente é e quais bebidas e componentes estão disponíveis. Vou informar ao nosso modelo que eles são os melhores mestrandos de soda que já vi e estou fornecendo uma lista de nossos soda com suas descrições. Também gostaria de perguntar quais sodas são melhores para cada estação (primavera, verão, queda, verão) com base em suas descrições:
1def swigJoined(scraped_menu):
2 drink_list = []
3
4 # just formatting our menu from above
5 for drink in scraped_menu:
6 drink_format = f"{drink['name']}: {drink['description']}]"
7 drink_list.append(drink_format)
8
9 # put all the drinks into a single string for OpenAI to understand it
10 drink_string = "\n".join(drink_list)
11
12 # we have to tell OpenAI which drinks/combinations are available
13 prompt = (
14 "You are the best soda mixologist Utah has ever seen! This is a list of sodas and their descriptions, or ingredients:\n"
15 f"{drink_string}\n\n Please sort each and every drink provided into spring, summer, fall, or winter seasons based on their ingredients\n"
16 "and give me reasonings as to why by stating which ingredients make it best for each season. For example, cinnamon is more fall, but peach\n"
17 "is more summer."
18 )
19
20 return prompt
Agora, vamos gerar nosso prompt usando o menu que raspamos. Usaremos nosso prompt abaixo em nossa parte de saídas estruturadas deste tutorial:
1my_prompt = swigJoined(scraped_menu)
2openai.api_key = openai_api_key
Agora que isso está pronto, podemos usar nossa chamada estruturada e JSON schema. Para obter ajuda sobre esta parte, consulte a documentação:
Podemos ver na seção "extracting structured data from unstructured data " que a solicitação deve seguir estas especificações:
1POST /v1/chat/completions
2{
3 "model": "gpt-4o-2024-08-06",
4 "messages": [
5 {
6 "role": "system",
7 "content": "Extract action items, due dates, and owners from meeting notes."
8 },
9 {
10 "role": "user",
11 "content": "...meeting notes go here..."
12 }
13 ],
14 "response_format": {
15 "type": "json_schema",
16 "json_schema": {
17 "name": "action_items",
18 "strict": true,
19 "schema": {
20 "type": "object",
21 "properties": {
22 "action_items": {
23 "type": "array",
24 "items": {
25 "type": "object",
26 "properties": {
27 "description": {
28 "type": "string",
29 "description": "Description of the action item."
30 },
31 "due_date": {
32 "type": ["string", "null"],
33 "description": "Due date for the action item, can be null if not specified."
34 },
35 "owner": {
36 "type": ["string", "null"],
37 "description": "Owner responsible for the action item, can be null if not specified."
38 }
39 },
40 "required": ["description", "due_date", "owner"],
41 "additionalProperties": false
42 },
43 "description": "List of action items from the meeting."
44 }
45 },
46 "required": ["action_items"],
47 "additionalProperties": false
48 }
49 }
50 }
51}
Então, podemos pegar esse código de esqueleto e torná-lo nosso. Este tutorial usa a GPT-4o, mas fique à vontade para usar a GPT com a qual se sentir mais familiarizado:
1response = openai.chat.completions.create(
2 model="gpt-4o-2024-08-06",
3 messages=[
4 {"role": "system", "content": "You are the best soda mixologist Utah has ever seen!"},
5 {"role": "user", "content": my_prompt}
6 ],
7 response_format={
8 "type": "json_schema",
9 "json_schema": {
10 "name": "drink_response",
11 "strict": True,
12 "schema": {
13 "type": "object",
14 "properties": {
15 "seasonal_drinks": {
16 "type": "array",
17 "items": {
18 "type": "object",
19 "properties": {
20 "drink": {"type": "string"},
21 "reason": {"type": "string"}
22 },
23 "required": ["drink", "reason"],
24 "additionalProperties": False
25 }
26 }
27 },
28 "required": ["seasonal_drinks"],
29 "additionalProperties": False
30 }
31 }
32 }
33)
Agora, vamos imprimi-lo e ver nossa resposta estruturada:
1print(json.dumps(response.model_dump(), indent=2))
Saída estruturada do OpenAI Saídas estruturadas na API
Aqui, podemos ver que a saída que procuramos está localizada dentro da parte "content " para nossas bebidas de queda. Vamos extraí-lo para ver uma lista das bebidas e as razões pelas quais cada bebida é melhor para cada estação. Vamos fazer isso imprimindo-o usando model_dump:
1content = response.model_dump()['choices'][0]['message']['content']
2print(content)
Após imprimir a linha "content " do nosso esquema estruturado
Ainda está em uma linha, então vamos imprimir as bebidas para que fiquem bonita:
1parsed_drinks = json.loads(content)
2seasonal_drinks_pretty = parsed_drinks['seasonal_drinks']
3print(json.dumps(seasonal_drinks_pretty, indent=2))
As nossas bebidas e as razões pelas quais são boas para cada época do ano
Agora podemos ver todas as bebidas perfeitas para cada estação no menu Swig! Vamos dar uma olhada em alguns deles.
A OpenAI acredita que o Suja SOP é perfeita para o verão, pois "a inclusão de pesseguigo torna essa bebida mais adequada para o verão, já que o pesquiso é normalmente associado ao tempo quente e às vindimas de verão". Uma ótima bebida para o queda e o inver no é o Dr. Spice: "A caneleira e o pau de caneleira são Temperos quentes normalmente associados ao queda e ao inver no, tornando esta bebida mais adequada para o tempo mais frio."
Agora que sabemos quais bebidas à base de soda são perfeitas para cada estação, com base em nossa saída, Go em frente e insira nossas bebidas como documentos em nosso cluster MongoDB Atlas para que possamos executar um pipeline de agregação nelas e descobrir quais são perfeitas para nossa próxima estação de queda.

Parte 3: Inserir no MongoDB Atlas e criar um pipeline de agregação

Nosso primeiro passo é instalar o pymongo. PyMongo é o driver oficial do MongoDB para aplicativos Python.
Instale-o usando pip:
1!pip install pymongo
Aqui, vamos importar nosso MongoClient, configurar nossa conexão MongoDB usando getpasse, em seguida, podemos nomear nosso banco de dados de dados e coleção o que quisermos, pois ele será criado quando inserirmos nossos dados. Estou nomeando meu banco de dados de dados "swig_menu " e a coleção "fall_drinks. "
1from pymongo import MongoClient
2
3# set up your MongoDB connection
4connection_string = getpass.getpass(prompt= "Enter connection string WITH USER + PASS here")
5client = MongoClient(connection_string, appname = "devrel.showcase.swig_menu")
6
7# name your database and collection anything you want since it will be created when you enter your data
8database = client['swig_menu']
9collection = database['seasonal_drinks']
10
11# insert our fall drinks
12collection.insert_many(seasonal_drinks_pretty)
Depois de executar este bloco, verifique se tudo foi importado corretamente: Documentos importados corretamente no MongoDB Atlas
Agora, vamos criar um índice do Atlas Search para que possamos usar a Atlas Searchdo MongoDB em nossos documentos!
Depois de criar seu índice de pesquisa, crie um pipeline de agregação usando a UI do MongoDB Atlas . Para fazer isso, vá até "Collections " e clique em "Aggregation. " Aqui, podemos pesquisar em nossas bebidas sazonais e usar o recurso de correspondência exata do Atlas Search para descobrir quais bebidas são as melhores para o queda!
Como criar um pipeline de agregação na UI do MongoDB Atlas
Vamos primeiro ver todas as bebidas de queda que nosso modelo de AI encontrou para nós. Para fazer isso, podemos usar nosso operador$searche criar um estágio em nosso pipeline de agregação :
1{
2 "text": {
3 "query": "fall",
4 "path": "reason"
5 }
6}
Temos oito resultados! resultados ao encontrar bebidas com “fall” nelas
Agora, digamos que eu queira coquetéis para o fim de ano que tenham o segredo apple. Para fazer isso, precisamos usar um operadorcomposto que combine duas ou mais queries. Então, isso está mostrando que preciso encontrar bebidas que contenham "fall " E "apple. " O operador precisa ser um "must. " Se eu quisesse "fall " OU "apple, ", precisaria para usar um “should. "
1{
2 "compound": {
3 "must": [
4 {
5 "text": {
6 "query": "fall",
7 "path": "reason"
8 }
9 },
10 {
11 "text": {
12 "query": "apple",
13 "path": "reason"
14
15 }
16 }
17 ],
18 }
19}
Saída após executar o pipeline de agregação
Temos duas ótimas opções para bebidas de cairo que incluem Maçãs!
Agora, podemos encontrar bebidas no site da Swig que são superespecíficas para o que desejamos em cada estação.

Conclusão

Neste tutorial, examinamos como raspar um site usando o Playwright, colocamos nossas informações raspadas no OpenAI e obtemos resultados para bebidas sazonais a partir do menu com argumentos e uma saída estruturada, e finalizamos o tutorial importando nosso bebidas com suas razões no MongoDB Atlas e usei oMongoDB Atlas Search para encontrar bebidas de queda e seus componentes!
Esperemos que tenhas preferido este tutorial. Conecte-se conosco no Fórum de desenvolvedores.

Recursos utilizados

Saídas estruturadas: https://openai.com/index/introducing-Structured-outputs-in-the-api/
Correspondências exatas no MongoDB Atlas Search: https://www.mongodb.com/developer/products/atlas/atlas-search-exact-match/
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Modelagem de dados em várias linguagens do Atlas Search


Sep 09, 2022 | 2 min read
Tutorial

Configurando o Atlas no Postman com a API de administração do Atlas


Aug 19, 2024 | 7 min read
Artigo

Usando o SuperDuperDB para acelerar o desenvolvimento de IA no MongoDB Atlas Vector Search


Sep 18, 2024 | 6 min read
Início rápido

Como conectar o MongoDB Atlas ao Vercel usando a nova integração


Aug 05, 2024 | 4 min read
Sumário