1. Introdução
Neste codelab, você vai criar um aplicativo que usa a pesquisa de vetor para recomendar poses de ioga.
No codelab, você vai usar uma abordagem detalhada da seguinte forma:
- Use um conjunto de dados do Hugging Face de poses de ioga (formato JSON).
- Melhore o conjunto de dados com uma descrição de campo adicional que usa o Gemini para gerar descrições de cada pose.
- Use o Langchain para criar um documento e a integração do Firestore Langchain para criar a coleção e as incorporações no Firestore.
- Crie um índice composto no Firestore para permitir a pesquisa vetorial.
- Use a pesquisa de vetor em um aplicativo Flask que reúne tudo, conforme mostrado abaixo:
O que você aprenderá
- Projete, crie e implante um aplicativo da Web que usa a Pesquisa de vetor para recomendar posições de ioga.
O que você vai aprender
- Como usar o Gemini para gerar conteúdo de texto e, no contexto deste codelab, gerar descrições de poses de ioga
- Como usar o Langchain Document Loader para o Firestore para carregar registros de um conjunto de dados aprimorado do Hugging Face no Firestore com embeddings de vetor
- Como usar o Langchain Vector Store para Firestore para pesquisar dados com base em uma consulta em linguagem natural
- Como usar a API Text-to-Speech do Google Cloud para gerar conteúdo de áudio
O que é necessário
- Navegador da Web Google Chrome
- Uma conta do Gmail
- Um projeto do Cloud com faturamento ativado
Este codelab, desenvolvido para desenvolvedores de todos os níveis (inclusive iniciantes), usa Python no aplicativo de exemplo. No entanto, não é necessário ter conhecimento de Python para entender os conceitos apresentados.
2. Antes de começar
Criar um projeto
- No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Verifique se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto .
- Você vai usar o Cloud Shell, um ambiente de linha de comando executado no Google Cloud que vem pré-carregado com bq. Clique em "Ativar o Cloud Shell" na parte de cima do console do Google Cloud.
- Depois de se conectar ao Cloud Shell, verifique se você já está autenticado e se o projeto está definido como seu ID usando o seguinte comando:
gcloud auth list
- Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto.
gcloud config list project
- Se o projeto não estiver definido, use este comando:
gcloud config set project <YOUR_PROJECT_ID>
- Ative as APIs necessárias usando o comando mostrado abaixo. Isso pode levar alguns minutos. Tenha paciência.
gcloud services enable firestore.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
cloudfunctions.googleapis.com \
aiplatform.googleapis.com \
texttospeech.googleapis.com
Após a execução do comando, uma mensagem semelhante à mostrada abaixo vai aparecer:
Operation "operations/..." finished successfully.
A alternativa ao comando gcloud é pelo console, pesquisando cada produto ou usando este link.
Se alguma API for perdida, você poderá ativá-la durante a implementação.
Consulte a documentação para ver o uso e os comandos gcloud.
Clonar o repositório e configurar o ambiente
A próxima etapa é clonar o repositório de exemplo que vamos usar como referência no restante do codelab. Supondo que você esteja no Cloud Shell, execute o seguinte comando no diretório principal:
git clone https://github.com/rominirani/yoga-poses-recommender-python
Para iniciar o editor, clique em "Abrir editor" na barra de ferramentas da janela do Cloud Shell. Clique na barra de menu no canto superior esquerdo e selecione "File" → "Open Folder", conforme mostrado abaixo:
Selecione a pasta yoga-poses-recommender-python
. Ela será aberta com os seguintes arquivos, conforme mostrado abaixo:
Agora precisamos configurar as variáveis de ambiente que vamos usar. Clique no arquivo config.template.yaml
e o conteúdo vai aparecer conforme mostrado abaixo:
project_id: your-project-id
location: us-central1
gemini_model_name: gemini-1.5-flash-002
embedding_model_name: text-embedding-004
image_generation_model_name: imagen-3.0-fast-generate-002
database: (default)
collection: poses
test_collection: test-poses
top_k: "3"
Atualize os valores de project_id
e location
de acordo com o que você selecionou ao criar o projeto do Google Cloud e a região do banco de dados do Firestore. O ideal é que os valores de location
sejam iguais para o projeto do Google Cloud e o banco de dados do Firestore, por exemplo, us-central1
.
Para este codelab, vamos usar os valores pré-configurados, exceto project_id
e location
, que precisam ser definidos de acordo com sua configuração.
Salve este arquivo como config.yaml
na mesma pasta que o arquivo config.template.yaml
.
A etapa final agora é criar um ambiente Python que usaremos localmente com todas as dependências do Python configuradas para nós. Confira o arquivo pyproject.toml
, que contém os detalhes, conforme mostrado abaixo:
dependencies = [
"datasets>=3.2.0",
"flask>=3.1.0",
"google-cloud-aiplatform>=1.78.0",
"google-cloud-texttospeech>=2.24.0",
"langchain-community>=0.3.15",
"langchain-core>=0.3.31",
"langchain-google-community>=2.0.4",
"langchain-google-firestore>=0.5.0",
"langchain-google-vertexai>=2.0.7",
"pydantic-settings>=2.7.1",
"pyyaml>=6.0.2",
"tenacity>=9.0.0",
]
Essas dependências já estão bloqueadas pela versão no requirements.txt
.
. Para resumir, precisamos criar um ambiente virtual do Python com as dependências de pacotes do Python no requirements.txt
para serem instaladas no ambiente virtual. Para fazer isso, acesse o Command Palette
(Ctrl+Shift+P) no Cloud Shell IDE e digite Python: Create Environment
. Siga as próximas etapas para selecionar um Virtual Environment(venv)
, Python 3.x interpreter
e o arquivo requirements.txt
.
Depois que o ambiente for criado, vamos precisar ativar o ambiente criado com o seguinte comando:
source .venv/bin/activate
Você vai encontrar (.venv) no console. Por exemplo, -> (.venv) yourusername@cloudshell:
Ótimo! Agora está tudo pronto para prosseguir com a tarefa de configurar o banco de dados do Firestore.
3. Configurar o Firestore
O Cloud Firestore é um banco de dados de documentos sem servidor totalmente gerenciado que vamos usar como back-end para os dados do aplicativo. Os dados no Cloud Firestore são estruturados em coleções de documentos.
Inicialização do banco de dados do Firestore
Acesse a página do Firestore no Console do Cloud.
Se você não tiver inicializado um banco de dados do Firestore antes no projeto, crie o banco de dados default
clicando em Create Database
. Durante a criação do banco de dados, use os seguintes valores:
- Modo do Firestore:
Native.
- Localização: use as configurações de localização padrão.
- Para as regras de segurança, use
Test rules
. - Crie o banco de dados.
Na próxima seção, vamos preparar o terreno para criar uma coleção chamada poses
no nosso banco de dados padrão do Firestore. Essa coleção vai conter dados de amostra (documentos) ou informações sobre as posições de ioga, que serão usadas no nosso aplicativo.
Isso conclui a seção de configuração do banco de dados do Firestore.
4. Preparar o conjunto de dados de poses de ioga
Nossa primeira tarefa é preparar o conjunto de dados de posturas de ioga que vamos usar no aplicativo. Vamos começar com um conjunto de dados do Hugging Face e depois aprimorar com mais informações.
Confira o conjunto de dados do Hugging Face para posturas de ioga. Embora este codelab use um dos conjuntos de dados, você pode usar qualquer outro conjunto de dados e seguir as mesmas técnicas demonstradas para aprimorar o conjunto de dados.
Se formos à seção Files and versions
, vamos conseguir o arquivo de dados JSON de todas as poses.
Fizemos o download do arquivo yoga_poses.json
e o enviamos para você. Esse arquivo é chamado yoga_poses_alldata.json
e está na pasta /data
.
Acesse o arquivo data/yoga_poses.json
no editor do Cloud Shell e confira a lista de objetos JSON, em que cada objeto JSON representa uma postura de ioga. Temos um total de 3 registros, e um exemplo é mostrado abaixo:
{
"name": "Big Toe Pose",
"sanskrit_name": "Padangusthasana",
"photo_url": "https://pocketyoga.com/assets/images/full/ForwardBendBigToe.png",
"expertise_level": "Beginner",
"pose_type": ["Standing", "Forward Bend"]
}
Esta é uma ótima oportunidade para apresentar o Gemini e como podemos usar o modelo padrão para gerar um campo description
.
No editor do Cloud Shell, acesse o arquivo generate-descriptions.py
. O conteúdo do arquivo é mostrado abaixo:
import json
import time
import logging
import vertexai
from langchain_google_vertexai import VertexAI
from tenacity import retry, stop_after_attempt, wait_exponential
from settings import get_settings
settings = get_settings()
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
# Initialize Vertex AI SDK
vertexai.init(project=settings.project_id, location=settings.location)
logging.info("Done Initializing Vertex AI SDK")
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=4, max=10),
)
def generate_description(pose_name, sanskrit_name, expertise_level, pose_types):
"""Generates a description for a yoga pose using the Gemini API."""
prompt = f"""
Generate a concise description (max 50 words) for the yoga pose: {pose_name}
Also known as: {sanskrit_name}
Expertise Level: {expertise_level}
Pose Type: {", ".join(pose_types)}
Include key benefits and any important alignment cues.
"""
try:
model = VertexAI(model_name=settings.gemini_model_name, verbose=True)
response = model.invoke(prompt)
return response
except Exception as e:
logging.info(f"Error generating description for {pose_name}: {e}")
return ""
def add_descriptions_to_json(input_file, output_file):
"""Loads JSON data, adds descriptions, and saves the updated data."""
with open(input_file, "r") as f:
yoga_poses = json.load(f)
total_poses = len(yoga_poses)
processed_count = 0
for pose in yoga_poses:
if pose["name"] != " Pose":
start_time = time.time() # Record start time
pose["description"] = generate_description(
pose["name"],
pose["sanskrit_name"],
pose["expertise_level"],
pose["pose_type"],
)
end_time = time.time() # Record end time
processed_count += 1
end_time = time.time() # Record end time
time_taken = end_time - start_time
logging.info(
f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
)
else:
pose["description"] = ""
processed_count += 1
logging.info(
f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
)
# Adding a delay to avoid rate limit
time.sleep(30)
with open(output_file, "w") as f:
json.dump(yoga_poses, f, indent=2)
def main():
# File paths
input_file = "./data/yoga_poses.json"
output_file = "./data/yoga_poses_with_descriptions.json"
# Add descriptions and save the updated JSON
add_descriptions_to_json(input_file, output_file)
if __name__ == "__main__":
main()
Esse aplicativo vai adicionar um novo campo description
a cada registro JSON de pose de ioga. Ela vai receber a descrição por uma chamada ao modelo Gemini, onde vamos fornecer o comando necessário. O campo é adicionado ao arquivo JSON, e o novo arquivo é gravado no arquivo data/yoga_poses_with_descriptions.json
.
Vamos conferir as principais etapas:
- Na função
main()
, ela invoca a funçãoadd_descriptions_to_json
e fornece o arquivo de entrada e o arquivo de saída esperados. - A função
add_descriptions_to_json
faz o seguinte para cada registro JSON, ou seja, informações sobre a postagem de ioga: - Ele extrai
pose_name
,sanskrit_name
,expertise_level
epose_types
. - Ele invoca a função generate_description, que constrói um comando e, em seguida, invoca a classe de modelo Langchain VertexAI para receber o texto de resposta.
- Esse texto de resposta é adicionado ao objeto JSON.
- A lista JSON atualizada de objetos é gravada no arquivo de destino.
Vamos executar este aplicativo. Inicie uma nova janela de terminal (Ctrl+Shift+C) e digite o seguinte comando:
python generate-descriptions.py
Se você receber uma solicitação de autorização, envie-a.
O aplicativo vai começar a ser executado. Adicionamos um atraso de 30 segundos entre os registros para evitar cotas de limite de taxa nas novas contas do Google Cloud. Tenha paciência.
Confira abaixo um exemplo de execução em andamento:
Depois que os três registros forem aprimorados com a chamada do Gemini, um arquivo data/yoga_poses_with_description.json
será gerado. Confira.
Agora que temos o arquivo de dados, a próxima etapa é entender como preencher um banco de dados do Firestore com ele, além da geração de incorporações.
5. Importar dados para o Firestore e gerar embeddings vetoriais
Temos o arquivo data/yoga_poses_with_description.json
e agora precisamos preencher o banco de dados do Firestore com ele e, principalmente, gerar as inclusões de vetor para cada um dos registros. As incorporações vetoriais serão úteis mais tarde, quando precisarmos fazer uma pesquisa de similaridade com elas usando a consulta do usuário fornecida em linguagem natural.
Vamos usar os componentes do Langchain Firestore para implementar o processo acima.
Para isso, siga estas etapas:
- Vamos converter a lista de objetos JSON em uma lista de objetos Langchain Document. Cada documento terá dois atributos:
page_content
emetadata
. O objeto de metadados vai conter todo o objeto JSON com atributos comoname
,description
,sanskrit_name
etc. Opage_content
será um texto de string que será uma concatenação de alguns campos. - Depois de ter uma lista de objetos
Document
, vamos usar a classe LangchainFirestoreVectorStore
e, especificamente, o métodofrom_documents
com essa lista de documentos, um nome de coleção (usamos a variávelTEST_COLLECTION
que aponta paratest-poses
), uma classe de incorporação do Vertex AI e os detalhes de conexão do Firestore (nomePROJECT_ID
eDATABASE
). Isso vai criar a coleção e gerar um campoembedding
para cada um dos atributos.
Confira abaixo o código de import-data.py
(partes do código foram truncadas para encurtar):
...
def create_langchain_documents(poses):
"""Creates a list of Langchain Documents from a list of poses."""
documents = []
for pose in poses:
# Convert the pose to a string representation for page_content
page_content = (
f"name: {pose.get('name', '')}\n"
f"description: {pose.get('description', '')}\n"
f"sanskrit_name: {pose.get('sanskrit_name', '')}\n"
f"expertise_level: {pose.get('expertise_level', 'N/A')}\n"
f"pose_type: {pose.get('pose_type', 'N/A')}\n"
).strip()
# The metadata will be the whole pose
metadata = pose
document = Document(page_content=page_content, metadata=metadata)
documents.append(document)
logging.info(f"Created {len(documents)} Langchain documents.")
return documents
def main():
all_poses = load_yoga_poses_data_from_local_file(
"./data/yoga_poses_with_descriptions.json"
)
documents = create_langchain_documents(all_poses)
logging.info(
f"Successfully created langchain documents. Total documents: {len(documents)}"
)
embedding = VertexAIEmbeddings(
model_name=settings.embedding_model_name,
project=settings.project_id,
location=settings.location,
)
client = firestore.Client(project=settings.project_id, database=settings.database)
vector_store = FirestoreVectorStore.from_documents(
client=client,
collection=settings.test_collection,
documents=documents,
embedding=embedding,
)
logging.info("Added documents to the vector store.")
if __name__ == "__main__":
main()
Vamos executar este aplicativo. Inicie uma nova janela de terminal (Ctrl+Shift+C) e digite o seguinte comando:
python import-data.py
Se tudo correr bem, você vai receber uma mensagem semelhante a esta:
2025-01-21 14:50:06,479 - INFO - Added documents to the vector store.
Para verificar se os registros foram inseridos e as incorporações foram geradas, acesse a página do Firestore no Console do Cloud.
Clique no banco de dados (padrão), que vai mostrar a coleção test-poses
e vários documentos nessa coleção. Cada documento é uma pose de ioga.
Clique em qualquer um dos documentos para investigar os campos. Além dos campos importados, você também encontra o campo embedding
, que é um campo de vetor gerado automaticamente para você pela classe VertexAIEmbeddings
do Langchain, em que fornecemos o modelo de embedding text-embedding-004
da Vertex AI.
Agora que temos os registros enviados para o banco de dados do Firestore com os embeddings, podemos passar para a próxima etapa e conferir como fazer a pesquisa de similaridade vetorial no Firestore.
6. Importar poses de yoga completas para a coleção do banco de dados do Firestore
Agora vamos criar a coleção poses
, que é uma lista completa de 160 posturas de ioga, para as quais geramos um arquivo de importação de banco de dados que você pode importar diretamente. Isso é feito para economizar tempo no laboratório. O processo de geração do banco de dados que contém a descrição e as embeddings é o mesmo que vimos na seção anterior.
Siga as etapas abaixo para importar o banco de dados:
- Crie um bucket no seu projeto com o comando
gsutil
abaixo. Substitua a variável<PROJECT_ID>
no comando abaixo pelo ID do projeto do Google Cloud.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
- Agora que o bucket foi criado, precisamos copiar a exportação de banco de dados que preparamos para ele antes de importar para o banco de dados do Firebase. Use o comando abaixo:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615 gs://<PROJECT_ID>-my-bucket
Agora que temos os dados para importar, podemos passar para a etapa final de importação dos dados para o banco de dados do Firebase (default
) que criamos.
- Use o comando gcloud abaixo:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615
A importação vai levar alguns segundos. Quando estiver pronta, você poderá validar seu banco de dados do Firestore e a coleção acessando https://console.cloud.google.com/firestore/databases, selecionando o banco de dados default
e a coleção poses
, conforme mostrado abaixo:
Isso conclui a criação da coleção do Firestore que vamos usar no nosso app.
7. Realizar pesquisa de similaridade vetorial no Firestore
Para realizar a pesquisa de similaridade vetorial, vamos usar a consulta do usuário. Um exemplo dessa consulta pode ser "Suggest me some exercises to relieve back pain"
.
Confira o arquivo search-data.py
. A função principal a ser analisada é a de pesquisa, mostrada abaixo. De forma geral, ele cria uma classe de embedding que será usada para gerar a embedding da consulta do usuário. Em seguida, ele usa a classe FirestoreVectorStore
para invocar a função similarity_search
.
def search(query: str):
"""Executes Firestore Vector Similarity Search"""
embedding = VertexAIEmbeddings(
model_name=settings.embedding_model_name,
project=settings.project_id,
location=settings.location,
)
client = firestore.Client(project=settings.project_id, database=settings.database)
vector_store = FirestoreVectorStore(
client=client, collection=settings.collection, embedding_service=embedding
)
logging.info(f"Now executing query: {query}")
results: list[Document] = vector_store.similarity_search(
query=query, k=int(settings.top_k), include_metadata=True
)
for result in results:
print(result.page_content)
Antes de executar isso com alguns exemplos de consulta, gere um índice composto do Firestore, que é necessário para que as consultas de pesquisa sejam bem-sucedidas. Se você executar o aplicativo sem criar o índice, um erro indicando que você precisa criar o índice primeiro será exibido com o comando para criar o índice primeiro.
O comando gcloud
para criar o índice composto é mostrado abaixo:
gcloud firestore indexes composite create --project=<YOUR_PROJECT_ID> --collection-group=poses --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
A indexação vai levar alguns minutos, porque há mais de 150 registros no banco de dados. Quando ele for concluído, você poderá conferir o índice usando o comando mostrado abaixo:
gcloud firestore indexes composite list
Você vai encontrar o índice que acabou de criar na lista.
Teste o seguinte comando:
python search-data.py --prompt "Recommend me some exercises for back pain relief"
Você vai receber algumas recomendações. Confira um exemplo de execução abaixo:
2025-01-21 15:48:51,282 - INFO - Now executing query: Recommend me some exercises for back pain relief
name: Supine Spinal Twist Pose
description: A gentle supine twist (Supta Matsyendrasana), great for beginners. Releases spinal tension, improves digestion, and calms the nervous system. Keep shoulders flat on the floor and lengthen the spine.
sanskrit_name: Supta Matsyendrasana
expertise_level: Beginner
pose_type: ['Supine', 'Twist']
name: Cow Pose
description: Cow Pose (Bitilasana) is a gentle backbend, stretching the chest, shoulders, and abdomen. Maintain a neutral spine, lengthen the tailbone, and avoid hyperextension. Benefits include improved posture and stress relief.
sanskrit_name: Bitilasana
expertise_level: Beginner
pose_type: ['Arm Leg Support', 'Back Bend']
name: Locust I Pose
description: Locust Pose I (Shalabhasana A) strengthens the back, glutes, and shoulders. Lie prone, lift chest and legs simultaneously, engaging back muscles. Keep hips grounded and gaze slightly forward.
sanskrit_name: Shalabhasana A
expertise_level: Intermediate
pose_type: ['Prone', 'Back Bend']
Agora que você já sabe como usar o Banco de Dados Vetorial do Firestore para fazer upload de registros, gerar embeddings e realizar uma pesquisa de similaridade de vetores, vamos continuar. Agora podemos criar um aplicativo da Web que vai integrar a pesquisa vetorial a um front-end da Web.
8. O aplicativo da Web
O aplicativo da Web Python Flask está disponível no arquivo main.py
, e o arquivo HTML do front-end está presente no templates/index.html.
.
Recomendamos que você analise os dois arquivos. Comece com o arquivo main.py
que contém o gerenciador /search
, que recebe a solicitação transmitida do arquivo HTML index.html
do front-end. Isso invoca o método de pesquisa, que faz a pesquisa de similaridade vetorial que analisamos na seção anterior.
A resposta é enviada de volta para o index.html
com a lista de recomendações. O index.html
mostra as recomendações como cards diferentes.
Executar o aplicativo localmente
Inicie uma nova janela de terminal (Ctrl+Shift+C) ou qualquer janela de terminal existente e execute o seguinte comando:
python main.py
Confira abaixo um exemplo de execução:
* Serving Flask app 'main'
* Debug mode: on
2025-01-21 16:02:37,473 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
* Running on http://10.88.0.4:8080
2025-01-21 16:02:37,473 - INFO - Press CTRL+C to quit
2025-01-21 16:02:37,474 - INFO - * Restarting with stat
2025-01-21 16:02:41,462 - WARNING - * Debugger is active!
2025-01-21 16:02:41,484 - INFO - * Debugger PIN: 440-653-555
Quando estiver tudo pronto, acesse o URL da página inicial do aplicativo clicando no botão "Visualização da Web" mostrado abaixo:
O arquivo index.html
vai ser mostrado como mostrado abaixo:
Forneça uma consulta de exemplo (por exemplo, Provide me some exercises for back pain relief
) e clique no botão Search
. Isso vai recuperar algumas recomendações do banco de dados. Você também vai encontrar um botão Play Audio
, que vai gerar um stream de áudio com base na descrição, que você pode ouvir diretamente.
9. (Opcional) Implantar no Google Cloud Run
A etapa final será implantar este aplicativo no Google Cloud Run. O comando de implantação é mostrado abaixo. Antes de implantar, substitua os valores da variável (<<YOUR_PROJECT_ID>>) pelos específicos do seu projeto. Esses são valores que você poderá recuperar do arquivo config.yaml
.
gcloud run deploy yogaposes --source . \
--port=8080 \
--allow-unauthenticated \
--region=us-central1 \
--platform=managed \
--project=<<YOUR_PROJECT_ID>> \
--env-vars-file=config.yaml
Execute o comando acima na pasta raiz do aplicativo. Talvez você também precise ativar as APIs do Google Cloud e confirmar várias permissões.
O processo de implantação leva de 5 a 7 minutos para ser concluído. Tenha paciência.
Depois de implantada, a saída da implantação vai fornecer o URL do serviço do Cloud Run. Ele vai estar neste formato:
Service URL: https://yogaposes-<<UNIQUEID>.us-central1.run.app
Acesse esse URL público e o mesmo aplicativo da Web implantado e em execução vai aparecer.
Você também pode acessar o Cloud Run no console do Google Cloud e conferir a lista de serviços no Cloud Run. O serviço yogaposes
precisa ser um dos serviços (ou o único) listados.
Para conferir os detalhes do serviço, como URL, configurações, registros e muito mais, clique no nome do serviço específico (yogaposes
no nosso caso).
Isso conclui o desenvolvimento e a implantação do nosso aplicativo da Web de recomendação de poses de ioga no Cloud Run.
10. Parabéns
Parabéns! Você criou um aplicativo que faz upload de um conjunto de dados para o Firestore, gera os embeddings e realiza uma pesquisa de similaridade vetorial com base na consulta do usuário.