Codelab: Crea una app contextual de recomendación de posturas de yoga con Firestore, Búsqueda de vectores, Langchain y Gemini (versión de Python)

1. Introducción

En este codelab, compilarás una aplicación que use la búsqueda vectorial para recomendar posturas de yoga.

En el codelab, seguirás un enfoque paso a paso de la siguiente manera:

  1. Utiliza un conjunto de datos de poses de yoga existente de Hugging Face (formato JSON).
  2. Mejora el conjunto de datos con una descripción de campo adicional que use Gemini para generar descripciones para cada una de las poses.
  3. Usa Langchain para crear un documento y la integración de Langchain de Firestore para crear la colección y las incorporaciones en Firestore.
  4. Crea un índice compuesto en Firestore para permitir la Búsqueda de vectores.
  5. Utiliza la búsqueda vectorial en una aplicación de Flask que combine todo, como se muestra a continuación:

84e1cbf29cbaeedc.png

Actividades

  • Diseña, compila y, luego, implementa una aplicación web que emplee Vector Search para recomendar posturas de yoga.

Qué aprenderás

  • Cómo usar Gemini para generar contenido de texto y, en el contexto de este codelab, generar descripciones de posturas de yoga
  • Cómo usar el Cargador de documentos de Langchain para Firestore para cargar registros de un conjunto de datos mejorado de Hugging Face en Firestore junto con incorporaciones de vectores
  • Cómo usar el almacén de vectores de Langchain para Firestore para buscar datos según una consulta de lenguaje natural
  • Cómo usar la API de Text to Speech de Google Cloud para generar contenido de audio

Requisitos

  • Navegador web Chrome
  • Una cuenta de Gmail
  • Un proyecto de Cloud con la facturación habilitada

Este codelab, diseñado para desarrolladores de todos los niveles (incluidos los principiantes), usa Python en su aplicación de ejemplo. Sin embargo, no se requiere conocimiento de Python para comprender los conceptos presentados.

2. Antes de comenzar

Crea un proyecto

  1. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.
  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Obtén información para verificar si la facturación está habilitada en un proyecto .
  3. Usarás Cloud Shell, un entorno de línea de comandos que se ejecuta en Google Cloud y que viene precargado con bq. Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud.

Imagen del botón Activar Cloud Shell

  1. Una vez que te conectes a Cloud Shell, verifica que ya te hayas autenticado y que el proyecto esté configurado con tu ID de proyecto con el siguiente comando:
gcloud auth list
  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que el comando gcloud conoce tu proyecto.
gcloud config list project
  1. Si tu proyecto no está configurado, usa el siguiente comando para hacerlo:
gcloud config set project <YOUR_PROJECT_ID>
  1. Habilita las APIs requeridas con el siguiente comando. Este proceso puede tardar unos minutos, así que ten paciencia.
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

Si el comando se ejecuta correctamente, deberías ver un mensaje similar al siguiente:

Operation "operations/..." finished successfully.

La alternativa al comando gcloud es buscar cada producto en la consola o usar este vínculo.

Si falta alguna API, puedes habilitarla durante el transcurso de la implementación.

Consulta la documentación para ver los comandos y el uso de gcloud.

Clona el repositorio y configura el entorno

El siguiente paso es clonar el repositorio de muestra al que haremos referencia en el resto del codelab. Si estás en Cloud Shell, ingresa el siguiente comando desde tu directorio principal:

git clone https://github.com/rominirani/yoga-poses-recommender-python

Para iniciar el editor, haz clic en Abrir editor en la barra de herramientas de la ventana de Cloud Shell. Haz clic en la barra de menú en la esquina superior izquierda y selecciona File → Open Folder, como se muestra a continuación:

66221fd0d0e5202f.png

Selecciona la carpeta yoga-poses-recommender-python y deberías ver que se abre con los siguientes archivos, como se muestra a continuación:

44699efc7fb1b911.png

Ahora debemos configurar las variables de entorno que usaremos. Haz clic en el archivo config.template.yaml y deberías ver el contenido como se muestra a continuación:

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"

Actualiza los valores de project_id y location según lo que hayas seleccionado cuando creaste el proyecto de Google Cloud y la región de la base de datos de Firestore. Idealmente, nos gustaría que los valores de location sean los mismos para el proyecto de Google Cloud y la base de datos de Firestore, por ejemplo, us-central1.

A los efectos de este codelab, usaremos los valores preconfigurados (excepto, por supuesto, project_id y location, que debes configurar según tu configuración).

Guarda este archivo como config.yaml en la misma carpeta que el archivo config.template.yaml.

El último paso es crear un entorno de Python que usaremos de forma local con todas las dependencias de Python configuradas. Consulta el archivo pyproject.toml que contiene los detalles del mismo, cuyo contenido se muestra a continuación:

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",
]

Estas dependencias ya tienen la versión bloqueada en requirements.txt.. En resumen, debemos crear un entorno virtual de Python con las dependencias de paquetes de Python en requirements.txt para que se instalen en el entorno virtual. Para ello, ve a Command Palette (Ctrl + Mayúsculas + P) en el IDE de Cloud Shell y escribe Python: Create Environment. Sigue los próximos pasos para seleccionar un archivo Virtual Environment(venv), Python 3.x interpreter y requirements.txt.

Una vez creado el entorno, deberemos activarlo con el siguiente comando:

source .venv/bin/activate

Deberías ver (.venv) en la consola. P.ej., -> (.venv) yourusername@cloudshell:

¡Genial! Ya está todo listo para pasar a la tarea de configurar la base de datos de Firestore.

3. Configura Firestore

Cloud Firestore es una base de datos de documentos sin servidores y completamente administrada que usaremos como backend para los datos de nuestra aplicación. Los datos de Cloud Firestore están estructurados en colecciones de documentos.

Inicialización de la base de datos de Firestore

Visita la página de Firestore en la consola de Cloud.

Si no inicializaste una base de datos de Firestore en el proyecto, crea la base de datos default haciendo clic en Create Database. Durante la creación de la base de datos, usa los siguientes valores:

  • Modo de Firestore: Native.
  • Ubicación: Usa la configuración de ubicación predeterminada.
  • Para las reglas de seguridad, usa Test rules.
  • Crea la base de datos.

504cabdb99a222a5.png

En la siguiente sección, prepararemos los fundamentos para crear una colección llamada poses en nuestra base de datos de Firestore predeterminada. Esta colección contendrá datos de muestra (documentos) o información sobre posturas de yoga, que luego usaremos en nuestra aplicación.

Esto completa la sección de configuración de la base de datos de Firestore.

4. Prepara el conjunto de datos de posturas de yoga

Nuestra primera tarea es preparar el conjunto de datos de posturas de yoga que usaremos para la aplicación. Comenzaremos con un conjunto de datos existente de Hugging Face y, luego, lo mejoraremos con información adicional.

Consulta el conjunto de datos de Hugging Face para posturas de yoga. Ten en cuenta que, si bien este codelab usa uno de los conjuntos de datos, en realidad puedes usar cualquier otro y seguir las mismas técnicas que se muestran para mejorarlo.

298cfae7f23e4bef.png

Si vamos a la sección Files and versions, podemos obtener el archivo de datos JSON de todas las poses.

3fe6e55abdc032ec.png

Descargamos el archivo yoga_poses.json y te lo proporcionamos. Este archivo se llama yoga_poses_alldata.json y se encuentra en la carpeta /data.

Ve al archivo data/yoga_poses.json en el editor de Cloud Shell y observa la lista de objetos JSON, en la que cada objeto JSON representa una postura de yoga. Tenemos un total de 3 registros y, a continuación, se muestra un registro de muestra:

{
   "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 es una gran oportunidad para presentar Gemini y cómo podemos usar el modelo predeterminado para generar un campo description para él.

En el editor de Cloud Shell, ve al archivo generate-descriptions.py. El contenido de este archivo se muestra a continuación:

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()

Esta aplicación agregará un nuevo campo description a cada registro JSON de la postura de yoga. Obtendrá la descripción a través de una llamada al modelo de Gemini, donde le proporcionaremos la instrucción necesaria. El campo se agrega al archivo JSON y el archivo nuevo se escribe en el archivo data/yoga_poses_with_descriptions.json.

Veamos los pasos principales:

  1. En la función main(), verás que invoca la función add_descriptions_to_json y proporciona el archivo de entrada y el archivo de salida esperados.
  2. La función add_descriptions_to_json hace lo siguiente para cada registro JSON, es decir, la información de la publicación de yoga:
  3. Extrae pose_name, sanskrit_name, expertise_level y pose_types.
  4. Invoca la función generate_description que construye una instrucción y, luego, invoca la clase de modelo Langchain VertexAI para obtener el texto de la respuesta.
  5. Luego, este texto de respuesta se agrega al objeto JSON.
  6. Luego, la lista de objetos JSON actualizada se escribe en el archivo de destino.

Ejecutemos esta aplicación. Inicia una nueva ventana de terminal (Ctrl + Mayúsculas + C) y escribe el siguiente comando:

python generate-descriptions.py

Si se te solicita alguna autorización, bríndala.

Verás que la aplicación comienza a ejecutarse. Agregamos una demora de 30 segundos entre los registros para evitar cualquier cuota de límite de frecuencia que pueda haber en las cuentas de Google Cloud nuevas, así que ten paciencia.

A continuación, se muestra un ejemplo de una ejecución en curso:

8e830d9ea9b6c60.png

Una vez que se hayan mejorado los 3 registros con la llamada a Gemini, se generará un archivo data/yoga_poses_with_description.json. Puedes consultarlo.

Ya tenemos todo listo con nuestro archivo de datos y el siguiente paso es comprender cómo propagar una base de datos de Firestore con él, junto con la generación de incorporaciones.

5. Importa datos a Firestore y genera incorporaciones de vectores

Tenemos el archivo data/yoga_poses_with_description.json y ahora debemos propagarlo en la base de datos de Firestore y, lo que es más importante, generar las incorporaciones de vectores para cada uno de los registros. Las incorporaciones de vectores serán útiles más adelante cuando tengamos que hacer una búsqueda de similitud con la consulta del usuario que se proporcionó en lenguaje natural.

Usaremos los componentes de Firestore de Langchain para implementar el proceso anterior.

Los pasos para hacerlo son los siguientes:

  1. Convertiremos la lista de objetos JSON en una lista de objetos Langchain Document. Cada documento tendrá dos atributos: page_content y metadata. El objeto de metadatos contendrá todo el objeto JSON que tenga atributos como name, description, sanskrit_name, etcétera. page_content será un texto de cadena que será una concatenación de algunos campos.
  2. Una vez que tengamos una lista de objetos Document, usaremos la clase Langchain FirestoreVectorStore y, específicamente, el método from_documents con esta lista de documentos, un nombre de colección (usamos la variable TEST_COLLECTION que apunta a test-poses), una clase de incorporación de Vertex AI y los detalles de conexión de Firestore (nombres PROJECT_ID y DATABASE). Esto creará la colección y también generará un campo embedding para cada uno de los atributos.

A continuación, se muestra el código de import-data.py (se truncaron partes del código para evitar desarrollos extensos):

... 

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()

Ejecutemos esta aplicación. Inicia una nueva ventana de terminal (Ctrl + Mayúsculas + C) y escribe el siguiente comando:

python import-data.py

Si todo sale bien, deberías ver un mensaje similar al siguiente:

2025-01-21 14:50:06,479 - INFO - Added documents to the vector store.

Para verificar si los registros se insertaron correctamente y se generaron las incorporaciones, visita la página de Firestore en la consola de Cloud.

504cabdb99a222a5.png

Haz clic en la base de datos (predeterminada). Se debería mostrar la colección test-poses y varios documentos en ella. Cada documento es una postura de yoga.

d0708499e403aebc.png

Haz clic en cualquiera de los documentos para investigar los campos. Además de los campos que importamos, también encontrarás el campo embedding, que es un campo vectorial que se generó automáticamente a través de la clase VertexAIEmbeddings de Langchain que usamos, en la que proporcionamos el modelo de incorporación de Vertex AI text-embedding-004.

d67113e2dc63cd6b.png

Ahora que tenemos los registros subidos a la base de datos de Firestore con las incorporaciones en su lugar, podemos pasar al siguiente paso y ver cómo realizar la búsqueda de similitud de vectores en Firestore.

6. Importa poses de yoga completas a la colección de la base de datos de Firestore

Ahora, crearemos la colección poses, que es una lista completa de 160 posturas de yoga, para la que generamos un archivo de importación de base de datos que puedes importar directamente. Esto se hace para ahorrar tiempo en el lab. El proceso para generar la base de datos que contiene la descripción y las incorporaciones es el mismo que vimos en la sección anterior.

Sigue los pasos que se indican a continuación para importar la base de datos:

  1. Crea un bucket en tu proyecto con el comando gsutil que se indica a continuación. Reemplaza la variable <PROJECT_ID> en el siguiente comando por el ID de tu proyecto de Google Cloud.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
  1. Ahora que se creó el bucket, debemos copiar la exportación de la base de datos que preparamos en este bucket antes de poder importarla a la base de datos de Firebase. Usa el siguiente comando:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615  gs://<PROJECT_ID>-my-bucket

Ahora que tenemos los datos para importar, podemos pasar al paso final de importarlos a la base de datos de Firebase (default) que creamos.

  1. Usa el siguiente comando de gcloud:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615

La importación tardará unos segundos y, una vez que esté lista, podrás validar tu base de datos de Firestore y la colección. Para ello, ve a https://console.cloud.google.com/firestore/databases, selecciona la base de datos default y la colección poses, como se muestra a continuación:

a8f5a6ba69bec69b.png

Esto completa la creación de la colección de Firestore que usaremos en nuestra aplicación.

7. Realiza una búsqueda de similitud de vectores en Firestore

Para realizar la búsqueda de similitud de vectores, tomaremos la consulta del usuario. Un ejemplo de esta consulta puede ser "Suggest me some exercises to relieve back pain".

Consulta el archivo search-data.py. La función clave que debes observar es la de búsqueda, que se muestra a continuación. En un nivel alto, crea una clase de incorporación que se usará para generar la incorporación de la consulta del usuario. Luego, usa la clase FirestoreVectorStore para invocar su función 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 ejecutarlo con algunos ejemplos de consultas, primero debes generar un índice compuesto de Firestore, que es necesario para que tus consultas de búsqueda se realicen correctamente. Si ejecutas la aplicación sin crear el índice, se mostrará un error que indica que primero debes crear el índice con el comando para crearlo.

A continuación, se muestra el comando gcloud para crear el índice compuesto:

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

El índice tardará unos minutos en completarse, ya que hay más de 150 registros en la base de datos. Una vez que se complete, puedes ver el índice con el siguiente comando:

gcloud firestore indexes composite list

Deberías ver el índice que acabas de crear en la lista.

Prueba el siguiente comando ahora:

python search-data.py --prompt "Recommend me some exercises for back pain relief"

Se te deberían proporcionar algunas recomendaciones. A continuación, se muestra una ejecución de ejemplo:

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']

Una vez que esto funcione, habremos entendido cómo usar la base de datos de vectores de Firestore para subir registros, generar incorporaciones y realizar una búsqueda de similitud vectorial. Ahora podemos crear una aplicación web que integre la búsqueda de vectores en un frontend web.

8. La aplicación web

La aplicación web de Flask en Python está disponible en el archivo main.py y el archivo HTML del frontend está presente en templates/index.html..

Te recomendamos que revises ambos archivos. Comienza primero con el archivo main.py que contiene el controlador /search, que toma la instrucción que se pasó desde el archivo index.html HTML del frontend. Luego, invoca el método de búsqueda, que realiza la búsqueda de similitud de vectores que analizamos en la sección anterior.

Luego, la respuesta se envía a index.html con la lista de recomendaciones. Luego, index.html muestra las recomendaciones como tarjetas diferentes.

Ejecuta la aplicación de manera local

Inicia una nueva ventana de terminal (Ctrl + Mayúsculas + C) o cualquier ventana de terminal existente y escribe el siguiente comando:

python main.py

A continuación, se muestra una ejecución de muestra:

 * 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

Una vez que esté en funcionamiento, visita la URL principal de la aplicación haciendo clic en el botón Vista previa en la Web que se muestra a continuación:

de297d4cee10e0bf.png

Deberías ver el archivo index.html que se entrega como se muestra a continuación:

20240a0e885ac17b.png

Proporciona una consulta de muestra (por ejemplo, Provide me some exercises for back pain relief) y haz clic en el botón Search. Esto debería recuperar algunas recomendaciones de la base de datos. También verás un botón Play Audio, que generará una transmisión de audio basada en la descripción, que puedes escuchar directamente.

789b4277dc40e2be.png

9. Implementación en Google Cloud Run (opcional)

Nuestro último paso será implementar esta aplicación en Google Cloud Run. A continuación, se muestra el comando de implementación. Antes de implementarlo, asegúrate de reemplazar los valores de la variable (<<YOUR_PROJECT_ID>>) por los que sean específicos de tu proyecto. Estos son valores que podrás recuperar del archivo 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

Ejecuta el comando anterior desde la carpeta raíz de la aplicación. Es posible que también se te solicite que habilites las APIs de Google Cloud y que confirmes varios permisos. Hazlo.

El proceso de implementación tardará entre 5 y 7 minutos en completarse, así que ten paciencia.

3a6d86fd32e4a5e.png

Una vez que se implemente correctamente, el resultado de la implementación proporcionará la URL del servicio de Cloud Run. Tendrá el siguiente formato:

Service URL: https://yogaposes-<<UNIQUEID>.us-central1.run.app

Visita esa URL pública y deberías ver la misma aplicación web implementada y ejecutándose correctamente.

84e1cbf29cbaeedc.png

También puedes visitar Cloud Run desde la consola de Google Cloud y verás la lista de servicios en Cloud Run. El servicio yogaposes debe ser uno de los servicios (si no es el único) que aparece allí.

f2b34a8c9011be4c.png

Para ver los detalles del servicio, como la URL, las configuraciones, los registros y mucho más, haz clic en el nombre específico del servicio (yogaposes en nuestro caso).

faaa5e0c02fe0423.png

Con esto, se completa el desarrollo y la implementación de nuestra aplicación web de recomendación de posturas de yoga en Cloud Run.

10. Felicitaciones

¡Felicitaciones! Compilaste de manera correcta una aplicación que sube un conjunto de datos a Firestore, genera las incorporaciones y realiza una búsqueda de similitud de vectores en función de la consulta del usuario.

Documentos de referencia