Compila una app contextual de recomendación de posturas de yoga con Firestore, la Búsqueda de vectores y Gemini 2.0.

1. Descripción general

En el mundo de las apps de bienestar y fitness, es clave brindarles a los usuarios una experiencia atractiva y enriquecedora. En el caso de una app de yoga, esto significa ir más allá de las simples descripciones de texto de las posturas y ofrecer información integral, contenido multimedia y capacidades de búsqueda inteligente. En este blog, exploraremos cómo compilar una base de datos sólida de posturas de yoga con Firestore de Google Cloud, aprovechar su extensión de búsqueda de vectores para la coincidencia contextual y, además, integrar la potencia de Gemini 2.0 Flash (experimental) para trabajar con contenido multimodal.

¿Por qué usar Firestore?

Firestore, la base de datos de documentos NoSQL sin servidores de Google Cloud, es una excelente opción para compilar aplicaciones escalables y dinámicas. A continuación, te explicamos por qué es una excelente opción para nuestra app de yoga:

  • Escalabilidad y rendimiento: Firestore se escala automáticamente para controlar millones de usuarios y conjuntos de datos masivos, lo que garantiza que tu app siga siendo responsiva incluso a medida que crece.
  • Actualizaciones en tiempo real: La sincronización en tiempo real integrada mantiene la coherencia de los datos en todos los clientes conectados, lo que la hace ideal para funciones como clases en vivo o prácticas colaborativas.
  • Modelo de datos flexible: La estructura basada en documentos de Firestore te permite almacenar diversos tipos de datos, incluidos texto, imágenes y hasta incorporaciones, lo que lo hace ideal para representar información compleja de posturas de yoga.
  • Consultas potentes: Firestore admite consultas complejas, incluidas las de igualdad, desigualdad y, ahora, con la nueva extensión, las búsquedas de similitud de vectores.
  • Compatibilidad sin conexión: Firestore almacena datos en caché de forma local, lo que permite que tu app funcione incluso cuando los usuarios no tienen conexión.

Mejora la búsqueda con la extensión de búsqueda vectorial de Firestore

La búsqueda tradicional basada en palabras clave puede ser limitante cuando se trata de conceptos complejos, como las posturas de yoga. Un usuario puede buscar una postura que "abra las caderas" o "mejore el equilibrio" sin conocer el nombre específico de la postura. Aquí es donde entra en juego la Búsqueda de vectores.

La búsqueda vectorial con Firestore te permite hacer lo siguiente:

  • Genera incorporaciones: Transforma las descripciones de texto y, en el futuro, posiblemente las imágenes y el audio, en representaciones de vectores numéricos (incorporaciones) que capten su significado semántico con modelos como los disponibles en Vertex AI o modelos personalizados.
  • Almacenamiento de incorporaciones: Almacena estas incorporaciones directamente en los documentos de Firestore.
  • Realiza búsquedas de similitud: Consulta tu base de datos para encontrar documentos que sean semánticamente similares a un vector de consulta determinado, lo que permite la coincidencia contextual.

Integración de Gemini 2.0 Flash (experimental)

Gemini 2.0 Flash es el modelo de IA multimodal de vanguardia de Google. Si bien aún es experimental, ofrece posibilidades interesantes para enriquecer nuestra app de yoga:

  • Generación de texto: Usa Gemini 2.0 Flash para generar descripciones detalladas de las posturas de yoga, incluidos los beneficios, las modificaciones y las contraindicaciones.
  • Generación de imágenes (imitada): Si bien la generación de imágenes directa con Gemini aún no está disponible para el público, simulé esto con Imagen de Google, generando imágenes que representan visualmente las poses.
  • Generación de audio (imitada): Del mismo modo, podemos usar un servicio de texto a voz (TTS) para crear instrucciones de audio para cada postura y guiar a los usuarios a través de la práctica.

En principio, propongo la integración para mejorar la app y usar las siguientes funciones del modelo:

  • API de Multimodal Live: Esta nueva API te ayuda a crear aplicaciones de transmisión de audio y visión en tiempo real con el uso de herramientas.
  • Velocidad y rendimiento: Gemini 2.0 Flash tiene un tiempo hasta el primer token (TTFT) significativamente mejorado en comparación con Gemini 1.5 Flash.
  • Experiencias de agentes mejoradas: Gemini 2.0 ofrece mejoras en la comprensión multimodal, la programación, el seguimiento de instrucciones complejas y las llamadas a funciones. Estas mejoras funcionan en conjunto para ofrecer mejores experiencias de agentes.

Para obtener más detalles, consulta esta página de documentación sobre Gemini 1.5 Flash.

Para mejorar la credibilidad y proporcionar más recursos, podemos integrar la Búsqueda de Google para fundamentar la información que proporciona nuestra app. Esto significa lo siguiente:

  • Búsqueda contextual: Cuando un usuario administrador ingresa los detalles de una pose, podemos usar el nombre de la pose para realizar una Búsqueda de Google.
  • Extracción de URLs: De los resultados de la búsqueda, podemos extraer URLs relevantes, como artículos, videos o sitios web de yoga de buena reputación, y mostrarlas en la app.

Qué compilarás

Como parte de este lab, harás lo siguiente:

  1. Crea una colección de Firestore y carga documentos de Yoga
  2. Aprende a crear aplicaciones de CRUD con Firestore
  3. Genera una descripción de la postura de yoga con Gemini 2.0 Flash
  4. Habilita la Búsqueda de vectores de Firebase con la integración de Firestore
  5. Genera incorporaciones a partir de la descripción de Yoga
  6. Realiza una búsqueda de similitud para el texto de búsqueda del usuario

Requisitos

  • Un navegador, como Chrome o Firefox.
  • Un proyecto de Google Cloud con facturación habilitada.

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 API necesarias.
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 \
                       storage.googleapis.com \ 
                       secretmanager.googleapis.com \ 
                       texttospeech.googleapis.com

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.

3. Configuración de la base de datos

En la documentación, se incluyen pasos más completos para configurar una instancia de Firestore. En un nivel alto, para comenzar, seguiré estos pasos:

1 Ve al Visor de Firestore y, en la pantalla Selecciona un servicio de base de datos, elige Firestore en modo nativo.

  1. Selecciona una ubicación para tu Firestore
  2. Haz clic en Crear base de datos (si es la primera vez, déjala como base de datos “(default)”).

Cuando creas un proyecto de Firestore, también se habilita la API en el Administrador de API de Cloud

  1. IMPORTANTE: Elige la versión de prueba (no de producción) de las reglas de seguridad para que se pueda acceder a los datos.
  2. Una vez que se configure, deberías ver la vista de base de datos, colección y documento de Firestore en modo nativo, como se muestra en la siguiente imagen:

f7136d53253c59a.png

  1. No realices este paso todavía, pero ten en cuenta que puedes hacer clic en "Iniciar colección" y crear una nueva. Establece el ID de la colección como "poses". Haz clic en el botón Guardar.

a26eb470aa9bfda9.png

Sugerencias para profesionales para la aplicación de producción:

  1. Una vez que finalices tu modelo de datos y determines quién debe poder acceder a diferentes tipos de documentos, podrás crear, editar y supervisar las reglas de seguridad desde la interfaz de Firebase. Puedes acceder a las reglas de seguridad desde este vínculo: https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. Asegúrate de editar, supervisar y probar tus reglas de seguridad antes de implementar o lanzar el proyecto desde la fase de desarrollo, ya que a menudo son el culpable silencioso de que tu app funcione de forma diferente.

Para esta demostración, la usaremos en el modo de prueba.

4. API de REST de Firestore

  1. La API de REST puede ser útil en los siguientes casos de uso:a. Para acceder a Firestore desde un entorno con recursos restringidos en el que no es posible ejecutar una biblioteca cliente completa Para automatizar la administración de la base de datos o recuperar metadatos detallados de la base de datos
  2. Si bien la forma más fácil de usar Firestore es mediante una de las bibliotecas cliente nativas, en algunas situaciones es útil llamar directamente a la API de REST.
  3. En el alcance de este blog, verás el uso y la demostración de las APIs de REST de Firestore, no de las bibliotecas cliente nativas.
  4. Para la autenticación, la API de REST de Firestore acepta un token de ID de Firebase Authentication o uno de Google Identity OAuth 2.0. Para obtener más información sobre el tema Autenticación y autorización, consulta la documentación.
  5. Todos los extremos de la API de REST existen asociados a la URL base https://firestore.googleapis.com/v1/.

Spring Boot y la API de Firestore

Esta solución en Spring Boot Framework tiene como objetivo demostrar una aplicación cliente que usa las APIs de Firestore para recopilar y modificar los detalles de la postura y la respiración del yoga con una experiencia interactiva del usuario.

Si quieres obtener una explicación detallada paso a paso de la parte de la solución de CRUD de Firestore de la app de Yoga poses, puedes consultar el vínculo del blog.

Para enfocarte en la solución actual y aprender la parte de CRUD sobre la marcha, clona toda la solución enfocada en este blog desde el siguiente repositorio de la terminal de Cloud Shell y obtén una copia de la base de código.

git clone https://github.com/AbiramiSukumaran/firestore-poserecommender

Ten en cuenta lo siguiente:

  1. Una vez que hayas clonado este repositorio, solo tendrás que hacer algunos cambios en el ID de tu proyecto, las APIs, etc. No se requiere ningún otro cambio para que tu aplicación esté lista para funcionar. En las próximas secciones, se explica cada componente de la aplicación. A continuación, se incluye una lista de los cambios:
  2. En el archivo src/main/java/com/example/demo/GenerateImageSample.java, reemplaza "<<YOUR_PROJECT_ID>>" por el ID de tu proyecto.
  3. En el archivo src/main/java/com/example/demo/GenerateEmbeddings.java, reemplaza "<<YOUR_PROJECT_ID>>" por el ID de tu proyecto.
  4. En src/main/java/com/example/demo/PoseController.java, reemplaza todas las instancias de "<<YOUR_PROJECT_ID>>" y el nombre de la base de datos,, en este caso "(default)",, por los valores adecuados de tu configuración:
  5. En src/main/java/com/example/demo/PoseController.java, reemplaza "[YOUR_API_KEY]" por tu CLAVE DE API para Gemini 2.0 Flash. Puedes obtener esta información en AI Studio.
  6. Si quieres realizar pruebas de forma local, ejecuta los siguientes comandos desde la carpeta del proyecto en la terminal de Cloud Shell:
mvn package

mvn spring-boot:run

En este momento, puedes ver tu aplicación en ejecución haciendo clic en la opción "vista previa web" de la terminal de Cloud Shell. Aún no tenemos todo listo para realizar pruebas y probar la aplicación.

  1. Opcional: Si quieres implementar la app en Cloud Run, deberás iniciar una nueva aplicación de Java Cloud Run desde cero en el editor de Cloud Shell y agregar los archivos src y de plantillas del repo a tu proyecto nuevo en las carpetas correspondientes (ya que el proyecto actual del repositorio de GitHub no está configurado de forma predeterminada para la configuración de implementación de Cloud Run). En ese caso, estos son los pasos que debes seguir (en lugar de clonar el repo existente):
  2. Ve al editor de Cloud Shell (asegúrate de que el editor esté abierto y no la terminal) y haz clic en el ícono del nombre del proyecto de Google Cloud en el lado izquierdo de la barra de estado (la parte bloqueada en la captura de pantalla que aparece a continuación).

d3f0de417094237d.png

  1. Selecciona Nueva aplicación -> Aplicación de Cloud Run -> Java: Cloud Run en la lista de opciones y asígnale el nombre “firestore-poserecommender”.

d5ef8b4ca8bf3f85.png

  1. Ahora deberías ver una plantilla de pila completa para la aplicación de Java Cloud Run, preconfigurada y lista para usar.
  2. Quita la clase Controller existente y copia los siguientes archivos en sus respectivas carpetas en la estructura del proyecto:

firestore-poserecommender/src/main/java/com/example/demo/

  1. FirestoreSampleApplication.java
  2. GenerateEmbeddings.java
  3. GenerateImageSample.java
  4. Pose.java
  5. PoseController.java
  6. ServletInitializer.java
             firestore-poserecommender/src/main/resources/static/
    
  7. Index.html

firestore-poserecommender/src/main/resources/templates/

  1. contextsearch.html
  2. createpose.html
  3. errmessage.html
  4. pose.html
  5. ryoq.html
  6. searchpose.html
  7. showmessage.html

firestore-poserecommender/

  1. Dockerfile
  2. Debes realizar los cambios en los archivos correspondientes para reemplazar PROJECT_ID y API_KEY por tus valores respectivos. (pasos 1 a,b, c y d anteriores).

5. Transferencia de datos

Los datos de la aplicación están disponibles en este archivo data.json: https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

Si deseas comenzar con algunos datos predefinidos, puedes copiar el archivo JSON y reemplazar todas las instancias de "<<YOUR_PROJECT_ID>>" por tu valor.

  • Ve a Firestore Studio.
  • Asegúrate de haber creado una colección llamada "poses".
  • Agrega documentos del archivo del repositorio mencionado anteriormente de forma manual, uno a la vez

Como alternativa, puedes importar datos de una sola vez desde el conjunto predefinido que creamos para ti. Para ello, sigue estos pasos:

  1. Ve a la terminal de Cloud Shell y asegúrate de que tu proyecto activo de Google Cloud esté configurado y de que tengas autorización. Crea un bucket en tu proyecto con el siguiente comando gsutil. Reemplaza la variable <PROJECT_ID> en el siguiente comando por el ID de tu proyecto de Google Cloud:

gsutil mb -l us gs://<PROJECT_ID>-yoga-poses-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://demo-bq-gemini-public/yoga_poses gs://<PROJECT_ID>-yoga-poses-bucket

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

  1. Ve a la consola de Firestore ahora y haz clic en Importar/Exportar en el menú de navegación de la izquierda.

Selecciona Importar, elige la ruta de acceso de Cloud Storage que acabas de crear y navega hasta que puedas seleccionar el archivo “yoga_poses.overall_export_metadata”:

f5c1d16df7d5a64a.png

  1. Haz clic en Importar.

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 predeterminada y la colección poses, como se muestra a continuación:

  1. También puedes crear los registros de forma manual a través de la aplicación una vez que realices la implementación con la acción "Crear una nueva pose".

6. Búsqueda de vectores

Habilita la extensión de Búsqueda de vectores de Firestore

Usa esta extensión para incorporar y consultar automáticamente tus documentos de Firestore con la nueva función de búsqueda de vectores. Esta acción te llevará a Firebase Extensions Hub.

Cuando instalas la extensión de Búsqueda vectorial, especificas una colección y un nombre de campo de documento. Cuando se agrega o actualiza un documento con este campo, se activa la extensión para calcular una incorporación vectorial para el documento. Esta incorporación de vectores se vuelve a escribir en el mismo documento, y el documento se indexa en el almacén de vectores, listo para consultarse.

Veamos los pasos:

Instala la extensión:

Instala la extensión “Búsqueda de vectores con Firestore” desde el mercado de extensiones de Firebase. Para ello, haz clic en “Instalar en Firebase console”.

IMPORTANTE:

Cuando navegues por primera vez a esta página de extensiones, deberás seleccionar el mismo proyecto en el que estás trabajando en la consola de Google Cloud que aparece en Firebase console.

715426b97c732649.png

Si tu proyecto no aparece en la lista, agrégalo en Firebase (elige tu proyecto de Google Cloud existente en la lista).

Configura la extensión:

Especifica la colección ("poses"), el campo que contiene el texto que se incorporará ("posture") y otros parámetros, como las dimensiones de incorporación.

Si hay APIs que se deben habilitar en este paso, la página de configuración te permitirá hacerlo. Sigue los pasos correspondientes.

Si la página no responde después de habilitar las APIs durante un tiempo, simplemente actualízala y deberías poder ver las APIs habilitadas.

5ba59b45710c567b.png

En uno de los siguientes pasos, te permite usar el LLM que elijas para generar las incorporaciones. Elige "Vertex AI".

bb528a04ebb5f976.png

Los siguientes parámetros de configuración se relacionan con tu colección y el campo que deseas incorporar:

LLM: Vertex AI

Ruta de acceso de la colección: poses

Límite de consultas predeterminado: 3

Medida de distancia: coseno

Nombre del campo de entrada: postura

Nombre del campo de salida: embedding

Nombre del campo de estado: status

Incorporar documentos existentes: Sí

Actualizar las incorporaciones existentes: Sí

Ubicación de Cloud Functions: us-central1

Habilitar eventos: No marcado

fb8cdf1163fac7cb.png

Una vez que hayas configurado todo, haz clic en el botón Install Extension. Este proceso tardará entre 3 y 5 minutos.

Genera incorporaciones:

A medida que agregues o actualices documentos en la colección "poses", la extensión generará automáticamente incorporaciones con un modelo previamente entrenado o uno de tu elección a través de un extremo de API. En este caso, elegimos Vertex AI en la configuración de la extensión.

Creación de índices

Exigirá la creación de un índice en el campo de incorporación en el momento de usar la incorporación en la aplicación.

Firestore crea índices automáticamente para las consultas básicas. Sin embargo, puedes permitir que Firestore genere sintaxis de índice ejecutando consultas que no tengan un índice. De esta manera, se te proporcionará un vínculo al índice generado en el mensaje de error del lado de la aplicación. Esta es la lista de pasos para crear un índice vectorial:

  1. Ve a la terminal de Cloud Shell
  2. Ejecuta el siguiente comando:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

Obtén más información aquí.

Una vez que se crea un índice vectorial, puedes realizar una búsqueda de vecino más cercano con tus incorporaciones vectoriales.

Nota importante:

A partir de este punto, no tienes que hacer ningún cambio en la fuente. Solo sigue los pasos para comprender lo que hace la aplicación.

Veamos cómo tu aplicación recién compilada se aproxima a la Búsqueda de vectores. Una vez que se almacenen las incorporaciones, puedes usar la clase VectorQuery del SDK de Java de Firestore para realizar la Búsqueda de vectores y obtener resultados de vecino más cercano:

CollectionReference coll = firestore.collection("poses");
    VectorQuery vectorQuery = coll.findNearest(
        "embedding",
        userSearchTextEmbedding, 
        /* limit */ 3,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance")
         .setDistanceThreshold(2.0)
          .build());
ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();
List<Pose> posesList = new ArrayList<Pose>();
// Get the ID of the closest document (assuming results are sorted by distance)
String closestDocumentId = vectorQuerySnapshot.getDocuments().get(0).getId();

Este fragmento compara la incorporación del texto de búsqueda del usuario con las incorporaciones de los documentos en Firestore y extrae la más cercana contextualmente.

7. Gemini 2.0 Flash

Integración de Gemini 2.0 Flash (para la generación de descripciones)

Veamos cómo tu aplicación recién creada controla la integración de Gemini 2.0 Flash para la generación de descripciones.

Ahora supongamos que un usuario administrador o instructor de yoga quiere ingresar los detalles de las posturas con la ayuda de Gemini 2.0 Flash y, luego, realizar una búsqueda para ver las coincidencias más cercanas. Esto permite extraer los detalles de las poses coincidentes junto con los objetos multimodales que respaldan los resultados.

String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=[YOUR_API_KEY]";
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> contents = new ArrayList<>();
List<Map<String, Object>> tools = new ArrayList<>();
Map<String, Object> content = new HashMap<>();
List<Map<String, Object>> parts = new ArrayList<>();
Map<String, Object> part = new HashMap<>();
part.put("text", prompt);
parts.add(part);
content.put("parts", parts);
contents.add(content);
requestBody.put("contents", contents);
/**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, String.class);
System.out.println("Generated response: " + response);
String responseBody = response.getBody();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray candidates = jsonObject.getJSONArray("candidates");
JSONObject candidate = candidates.getJSONObject(0);
JSONObject contentResponse = candidate.getJSONObject("content");
JSONArray partsResponse = contentResponse.getJSONArray("parts");
JSONObject partResponse = partsResponse.getJSONObject(0);
String generatedText = partResponse.getString("text");
System.out.println("Generated Text: " + generatedText);

a. Simulación de la generación de imágenes y audio

Gemini 2.0 Flash Experimental puede generar resultados multimodales. Sin embargo, aún no me registré para obtener acceso anticipado, por lo que imité la salida de imagen y audio con las APIs de Imagen y TTS, respectivamente. Imagina lo bueno que es generar todo esto con una llamada a la API a Gemini 2.0 Flash.

try (PredictionServiceClient predictionServiceClient =
          PredictionServiceClient.create(predictionServiceSettings)) {
  
        final EndpointName endpointName =
            EndpointName.ofProjectLocationPublisherModelName(
                projectId, location, "google", "imagen-3.0-generate-001");
  
        Map<String, Object> instancesMap = new HashMap<>();
        instancesMap.put("prompt", prompt);
        Value instances = mapToValue(instancesMap);
  
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("sampleCount", 1);
        paramsMap.put("aspectRatio", "1:1");
        paramsMap.put("safetyFilterLevel", "block_few");
        paramsMap.put("personGeneration", "allow_adult");
        Value parameters = mapToValue(paramsMap);
  
        PredictResponse predictResponse =
            predictionServiceClient.predict(
                endpointName, Collections.singletonList(instances), parameters);
  
        for (Value prediction : predictResponse.getPredictionsList()) {
          Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
          if (fieldsMap.containsKey("bytesBase64Encoded")) {
            bytesBase64Encoded = fieldsMap.get("bytesBase64Encoded").getStringValue();
       }
      }
      return bytesBase64Encoded;
    }
 try {
            // Create a Text-to-Speech client
            try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
                // Set the text input to be synthesized
                SynthesisInput input = SynthesisInput.newBuilder().setText(postureString).build();

                // Build the voice request, select the language code ("en-US") and the ssml
                // voice gender
                // ("neutral")
                VoiceSelectionParams voice =
                        VoiceSelectionParams.newBuilder()
                                .setLanguageCode("en-US")
                                .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                                .build();

                // Select the type of audio file you want returned
                AudioConfig audioConfig =
                        AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

                // Perform the text-to-speech request on the text input with the selected voice
                // parameters and audio file type
                SynthesizeSpeechResponse response =
                        textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

                // Get the audio contents from the response
                ByteString audioContents = response.getAudioContent();

                // Convert to Base64 string
                String base64Audio = Base64.getEncoder().encodeToString(audioContents.toByteArray());

                // Add the Base64 encoded audio to the Pose object
               return base64Audio;
            }

        } catch (Exception e) {
            e.printStackTrace(); // Handle exceptions appropriately. For a real app, log and provide user feedback.
            return "Error in Audio Generation";
        }
}

b. Grounding with Google Search:

Si revisas el código de invocación de Gemini en el paso 6, verás el siguiente fragmento de código para habilitar la vinculación de la Búsqueda de Google para la respuesta del LLM:

 /**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

Esto nos permite garantizar lo siguiente:

  • Basamos nuestro modelo en los resultados de la búsqueda reales
  • Extraer las URLs relevantes a las que se hace referencia en la búsqueda

8. Ejecuta tu aplicación

Veamos todas las capacidades de tu aplicación Java Spring Boot recién compilada con una interfaz web Thymeleaf simple:

  1. Operaciones CRUD de Firestore (crear, leer, actualizar y borrar)
  2. Búsqueda por palabra clave
  3. Creación de contexto basada en IA generativa
  4. Búsqueda contextual (Búsqueda de vectores)
  5. Salida multimodal para relacionar con la búsqueda
  6. Ejecuta tu propia consulta (consultas en formato structuredQuery)

Ejemplo: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

Todas estas funciones que se analizaron hasta ahora forman parte de la aplicación que acabas de crear a partir del repositorio: https://github.com/AbiramiSukumaran/firestore-poserecommender

Para compilarla, ejecutarla y, luego, implementarla, ejecuta los siguientes comandos desde la terminal de Cloud Shell:

mvn package

mvn spring-boot:run

Deberías ver el resultado y poder probar las funciones de tu aplicación. Mira el siguiente video para ver la demostración del resultado:

Recomendador de poses con Firestore, Búsqueda vectorial y Gemini 2.0 Flash

Paso opcional:

Para implementarlo en Cloud Run (suponiendo que hayas iniciado una aplicación nueva con Dockerfile y copiado los archivos según sea necesario), ejecuta el siguiente comando desde la terminal de Cloud Shell desde el directorio de tu proyecto:

gcloud run deploy --source .

Proporciona el nombre de la aplicación, el código de región (elige el de us-central1) y elige la invocación no autenticada "Y" cuando se te solicite. Deberías recibir el extremo de tu aplicación en la terminal una vez que la implementación se realice correctamente.

9. Limpia

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que usaste en esta publicación:

  1. En la consola de Google Cloud, ve a la página Administrar recursos.
  2. En la lista de proyectos, elige el proyecto que deseas borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrarlo.

10. Felicitaciones

¡Felicitaciones! Usaste correctamente Firestore para crear una aplicación de administración de posturas de yoga sólida e inteligente. Combinando la potencia de Firestore, la extensión de búsqueda de vectores y las capacidades de Gemini 2.0 Flash (con generación de imágenes y audio simulados), creamos una app de yoga realmente atractiva y informativa para implementar las operaciones de CRUD, realizar búsquedas basadas en palabras clave, búsquedas de vectores contextuales y generar contenido multimedia.

Este enfoque no se limita a las apps de yoga. A medida que los modelos de IA como Gemini sigan evolucionando, las posibilidades de crear experiencias del usuario aún más inmersivas y personalizadas solo aumentarán. Recuerda mantenerte al tanto de los desarrollos y la documentación más recientes de Google Cloud y Firebase para aprovechar todo el potencial de estas tecnologías.

Si tuviera que extender esta app, intentaría hacer dos cosas con Gemini 2.0 Flash:

  1. Usa la API de Multimodal Live para crear transmisiones de audio y visión en tiempo real para el caso de uso.
  2. Activa el Modo de pensamiento para generar los pensamientos detrás de las respuestas para la interacción con datos en tiempo real y hacer que la experiencia sea más realista.

No dudes en probarlo y enviar una solicitud de extracción :>D.