1. Introduction
Dans cet atelier de programmation, vous allez créer une application qui utilise la recherche vectorielle pour recommander des postures de yoga.
Au cours de l'atelier de programmation, vous allez suivre une approche par étapes:
- Utilisez un ensemble de données Hugging Face existant sur les postures de yoga (format JSON).
- Améliorez l'ensemble de données avec une description de champ supplémentaire qui utilise Gemini pour générer des descriptions pour chacune des poses.
- Chargez les données sur les postures de yoga en tant que collection de documents dans la collection Firestore avec des représentations vectorielles continues générées.
- Créez un index composite dans Firestore pour permettre la recherche vectorielle.
- Utilisez la recherche vectorielle dans une application Node.js qui rassemble tout, comme indiqué ci-dessous:
Objectifs de l'atelier
- Concevez, créez et déployez une application Web qui utilise Vector Search pour recommander des postures de yoga.
Points abordés
- Utiliser Gemini pour générer du contenu textuel et, dans le cadre de cet atelier de programmation, générer des descriptions de postures de yoga
- Charger des enregistrements d'un ensemble de données amélioré de Hugging Face dans Firestore avec des représentations vectorielles continues
- Rechercher des données à l'aide de la recherche vectorielle Firestore en fonction d'une requête en langage naturel
- Utiliser l'API Google Cloud Text-to-Speech pour générer du contenu audio
Prérequis
- Navigateur Web Chrome
- Un compte Gmail
- Un projet Cloud pour lequel la facturation est activée
Cet atelier de programmation, conçu pour les développeurs de tous niveaux (y compris les débutants), utilise JavaScript et Node.js dans son exemple d'application. Toutefois, vous n'avez pas besoin de connaître JavaScript ni Node.js pour comprendre les concepts présentés.
2. Avant de commencer
Créer un projet
- Dans la console Google Cloud, sur la page du sélecteur de projet, sélectionnez ou créez un projet Google Cloud.
- Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier si la facturation est activée sur un projet .
- Vous allez utiliser Cloud Shell, un environnement de ligne de commande exécuté dans Google Cloud et fourni avec bq. Cliquez sur "Activer Cloud Shell" en haut de la console Google Cloud.
- Une fois connecté à Cloud Shell, vérifiez que vous êtes déjà authentifié et que le projet est défini avec votre ID de projet à l'aide de la commande suivante:
gcloud auth list
- Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet.
gcloud config list project
- Si votre projet n'est pas défini, utilisez la commande suivante pour le définir :
gcloud config set project <YOUR_PROJECT_ID>
- Activez les API requises à l'aide de la commande ci-dessous. Cette opération peut prendre quelques minutes. Veuillez patienter.
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 l'exécution de la commande aboutit, un message semblable à celui ci-dessous s'affiche:
Operation "operations/..." finished successfully.
Vous pouvez également rechercher chaque produit dans la console ou utiliser ce lien.
Si une API est manquante, vous pouvez toujours l'activer au cours de l'implémentation.
Consultez la documentation pour connaître les commandes gcloud ainsi que leur utilisation.
Cloner le dépôt et configurer les paramètres de l'environnement
L'étape suivante consiste à cloner l'exemple de dépôt que nous allons référencer dans le reste de l'atelier de programmation. Si vous êtes dans Cloud Shell, exécutez la commande suivante à partir de votre répertoire d'accueil:
git clone https://github.com/rominirani/yoga-poses-recommender-nodejs
Pour lancer l'éditeur, cliquez sur "Ouvrir l'éditeur" dans la barre d'outils de la fenêtre Cloud Shell. Cliquez sur la barre de menu en haut à gauche, puis sélectionnez "File" (Fichier) → "Open Folder" (Ouvrir un dossier), comme illustré ci-dessous:
Sélectionnez le dossier yoga-poses-recommender-nodejs
. Il devrait s'ouvrir avec les fichiers suivants, comme indiqué ci-dessous:
Nous devons maintenant configurer les variables d'environnement que nous allons utiliser. Cliquez sur le fichier env-template
. Le contenu devrait s'afficher comme indiqué ci-dessous:
PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
LOCATION=us-<GOOGLE_CLOUD_REGION_NAME>
GEMINI_MODEL_NAME=<GEMINI_MODEL_NAME>
EMBEDDING_MODEL_NAME=<GEMINI_EMBEDDING_MODEL_NAME>
IMAGE_GENERATION_MODEL_NAME=<IMAGEN_MODEL_NAME>
DATABASE=<FIRESTORE_DATABASE_NAME>
COLLECTION=<FIRESTORE_COLLECTION_NAME>
TEST_COLLECTION=test-poses
TOP_K=3
Veuillez mettre à jour les valeurs de PROJECT_ID
et de LOCATION
en fonction de ce que vous avez sélectionné lors de la création du projet Google Cloud et de la région de la base de données Firestore. Idéalement, les valeurs de LOCATION
doivent être identiques pour le projet Google Cloud et la base de données Firestore, par exemple us-central1
.
Pour les besoins de cet atelier de programmation, nous allons utiliser les valeurs suivantes (à l'exception, bien sûr, de PROJECT_ID
et LOCATION
, que vous devez définir en fonction de votre configuration).
PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
LOCATION=us-<GOOGLE_CLOUD_REGION_NAME>
GEMINI_MODEL_NAME=gemini-1.5-flash-002
EMBEDDING_MODEL_NAME=text-embedding-004
IMAGE_GENERATION_MODEL_NAME=imagen-3.0-fast-generate-001
DATABASE=(default)
COLLECTION=poses
TEST_COLLECTION=test-poses
TOP_K=3
Veuillez enregistrer ce fichier sous le nom .env
dans le même dossier que le fichier env-template
.
Accédez au menu principal en haut à gauche de l'IDE Cloud Shell, puis à Terminal → New Terminal
.
Accédez au dossier racine du dépôt que vous avez cloné à l'aide de la commande suivante:
cd yoga-poses-recommender-nodejs
Installez les dépendances Node.js à l'aide de la commande suivante:
npm install
Parfait ! Nous sommes maintenant prêts à passer à la configuration de la base de données Firestore.
3. Configurer Firestore
Cloud Firestore est une base de données de documents sans serveur entièrement gérée que nous utiliserons comme backend pour les données de notre application. Les données de Cloud Firestore sont structurées en collections de documents.
Initialisation de la base de données Firestore
Accédez à la page Firestore de Cloud Console.
Si vous n'avez jamais initialisé de base de données Firestore dans le projet, créez la base de données default
en cliquant sur Create Database
. Lors de la création de la base de données, utilisez les valeurs suivantes:
- Mode Firestore:
Native.
- Position: utilisez les paramètres de localisation par défaut.
- Pour les règles de sécurité, sélectionnez
Test rules
. - Créez la base de données.
Dans la section suivante, nous allons préparer la création d'une collection nommée poses
dans notre base de données Firestore par défaut. Cette collection contiendra des exemples de données (documents) ou des informations sur les postures de yoga, que nous utiliserons ensuite dans notre application.
Vous avez terminé la section sur la configuration de la base de données Firestore.
4. Préparer l'ensemble de données sur les postures de yoga
Notre première tâche consiste à préparer l'ensemble de données sur les postures de yoga que nous utiliserons pour l'application. Nous allons commencer par un ensemble de données Hugging Face existant, puis l'enrichir avec des informations supplémentaires.
Consultez l'ensemble de données Hugging Face pour les postures de yoga. Notez que cet atelier de programmation utilise l'un des ensembles de données, mais que vous pouvez utiliser n'importe quel autre ensemble de données et suivre les mêmes techniques pour l'améliorer.
Si nous accédons à la section Files and versions
, nous pouvons obtenir le fichier de données JSON pour toutes les poses.
Nous avons téléchargé le fichier yoga_poses.json
et vous l'avons fourni. Ce fichier est nommé yoga_poses_alldata.json
et se trouve dans le dossier /data
.
Accédez au fichier data/yoga_poses.json
dans l'éditeur Cloud Shell et examinez la liste des objets JSON, où chaque objet JSON représente une posture de yoga. Il y a un total de trois enregistrements, et un exemple d'enregistrement est présenté ci-dessous:
{
"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"]
}
C'est l'occasion de vous présenter Gemini et de vous expliquer comment utiliser le modèle par défaut pour générer un champ description
.
Dans l'éditeur Cloud Shell, accédez au fichier generate-descriptions.js
. Le contenu de ce fichier est affiché ci-dessous:
import { VertexAI } from "@langchain/google-vertexai";
import fs from 'fs/promises'; // Use fs/promises for async file operations
import dotenv from 'dotenv';
import pRetry from 'p-retry';
import { promisify } from 'util';
const sleep = promisify(setTimeout);
// Load environment variables
dotenv.config();
async function callGemini(poseName, sanskritName, expertiseLevel, poseTypes) {
const prompt = `
Generate a concise description (max 50 words) for the yoga pose: ${poseName}
Also known as: ${sanskritName}
Expertise Level: ${expertiseLevel}
Pose Type: ${poseTypes.join(', ')}
Include key benefits and any important alignment cues.
`;
try {
// Initialize Vertex AI Gemini model
const model = new VertexAI({
model: process.env.GEMINI_MODEL_NAME,
location: process.env.LOCATION,
project: process.env.PROJECT_ID,
});
// Invoke the model
const response = await model.invoke(prompt);
// Return the response
return response;
} catch (error) {
console.error("Error calling Gemini:", error);
throw error; // Re-throw the error for handling in the calling function
}
}
// Configure logging (you can use a library like 'winston' for more advanced logging)
const logger = {
info: (message) => console.log(`INFO - ${new Date().toISOString()} - ${message}`),
error: (message) => console.error(`ERROR - ${new Date().toISOString()} - ${message}`),
};
async function generateDescription(poseName, sanskritName, expertiseLevel, poseTypes) {
const prompt = `
Generate a concise description (max 50 words) for the yoga pose: ${poseName}
Also known as: ${sanskritName}
Expertise Level: ${expertiseLevel}
Pose Type: ${poseTypes.join(', ')}
Include key benefits and any important alignment cues.
`;
const req = {
contents: [{ role: 'user', parts: [{ text: prompt }] }],
};
const runWithRetry = async () => {
const resp = await generativeModel.generateContent(req);
const response = await resp.response;
const text = response.candidates[0].content.parts[0].text;
return text;
};
try {
const text = await pRetry(runWithRetry, {
retries: 5,
onFailedAttempt: (error) => {
logger.info(
`Attempt ${error.attemptNumber} failed. There are ${error.retriesLeft} retries left. Waiting ${error.retryDelay}ms...`
);
},
minTimeout: 4000, // 4 seconds (exponential backoff will adjust this)
factor: 2, // Exponential factor
});
return text;
} catch (error) {
logger.error(`Error generating description for ${poseName}: ${error}`);
return '';
}
}
async function addDescriptionsToJSON(inputFile, outputFile) {
try {
const data = await fs.readFile(inputFile, 'utf-8');
const yogaPoses = JSON.parse(data);
const totalPoses = yogaPoses.length;
let processedCount = 0;
for (const pose of yogaPoses) {
if (pose.name !== ' Pose') {
const startTime = Date.now();
pose.description = await callGemini(
pose.name,
pose.sanskrit_name,
pose.expertise_level,
pose.pose_type
);
const endTime = Date.now();
const timeTaken = (endTime - startTime) / 1000;
processedCount++;
logger.info(`Processed: ${processedCount}/${totalPoses} - ${pose.name} (${timeTaken.toFixed(2)} seconds)`);
} else {
pose.description = '';
processedCount++;
logger.info(`Processed: ${processedCount}/${totalPoses} - ${pose.name} (${timeTaken.toFixed(2)} seconds)`);
}
// Add a delay to avoid rate limit
await sleep(30000); // 30 seconds
}
await fs.writeFile(outputFile, JSON.stringify(yogaPoses, null, 2));
logger.info(`Descriptions added and saved to ${outputFile}`);
} catch (error) {
logger.error(`Error processing JSON file: ${error}`);
}
}
async function main() {
const inputFile = './data/yoga_poses.json';
const outputFile = './data/yoga_poses_with_descriptions.json';
await addDescriptionsToJSON(inputFile, outputFile);
}
main();
Cette application ajoutera un nouveau champ description
à chaque enregistrement JSON de la pose de yoga. Il obtiendra la description via un appel au modèle Gemini, auquel nous lui fournirons l'invite nécessaire. Le champ est ajouté au fichier JSON, et le nouveau fichier est écrit dans le fichier data/yoga_poses_with_descriptions.json
.
Passons en revue les principales étapes:
- Dans la fonction
main()
, vous constaterez qu'elle appelle la fonctionadd_descriptions_to_json
et fournit le fichier d'entrée et le fichier de sortie attendus. - La fonction
add_descriptions_to_json
effectue les opérations suivantes pour chaque enregistrement JSON, c'est-à-dire les informations sur le post sur le yoga: - Il extrait les
pose_name
,sanskrit_name
,expertise_level
etpose_types
. - Elle appelle la fonction
callGemini
qui construit une requête, puis appelle la classe de modèle LangchainVertexAI pour obtenir le texte de la réponse. - Ce texte de réponse est ensuite ajouté à l'objet JSON.
- La liste d'objets JSON mise à jour est ensuite écrite dans le fichier de destination.
Exécutons cette application. Ouvrez une nouvelle fenêtre de terminal (Ctrl+Maj+C) et exécutez la commande suivante:
npm run generate-descriptions
Si une autorisation vous est demandée, veuillez la fournir.
Vous constaterez que l'application commence à s'exécuter. Nous avons ajouté un délai de 30 secondes entre les enregistrements pour éviter tout quota de limite de débit qui pourrait s'appliquer aux nouveaux comptes Google Cloud. Veuillez donc patienter.
Voici un exemple d'exécution en cours:
Une fois les trois enregistrements améliorés avec l'appel Gemini, un fichier data/yoga_poses_with_description.json
est généré. Vous pouvez y jeter un coup d'œil.
Notre fichier de données est maintenant prêt. L'étape suivante consiste à comprendre comment le renseigner dans une base de données Firestore, ainsi que la génération d'embeddings.
5. Importer des données dans Firestore et générer des représentations vectorielles continues
Nous disposons du fichier data/yoga_poses_with_description.json
. Nous devons maintenant l'insérer dans la base de données Firestore et, surtout, générer les représentations vectorielles continues pour chacun des enregistrements. Les embeddings vectoriels seront utiles plus tard, lorsque nous devrons effectuer une recherche de similarité avec la requête utilisateur fournie en langage naturel.
Pour ce faire, procédez comme suit:
- Nous allons convertir la liste d'objets JSON en une liste d'objets. Chaque document comporte deux attributs:
content
etmetadata
. L'objet de métadonnées contient l'intégralité de l'objet JSON qui comporte des attributs tels quename
,description
,sanskrit_name
, etc.content
est une chaîne de texte qui est une concaténation de quelques champs. - Une fois que nous aurons une liste de documents, nous utiliserons la classe Vertex AI Embeddings pour générer l'embedding du champ de contenu. Cet imbrication sera ajoutée à chaque enregistrement de document, puis nous utiliserons l'API Firestore pour enregistrer cette liste d'objets de document dans la collection (nous utilisons la variable
TEST_COLLECTION
qui pointe verstest-poses
).
Le code de import-data.js
est donné ci-dessous (certaines parties du code ont été tronquées par souci de concision):
import { Firestore,
FieldValue,
} from '@google-cloud/firestore';
import { VertexAIEmbeddings } from "@langchain/google-vertexai";
import * as dotenv from 'dotenv';
import fs from 'fs/promises';
// Load environment variables
dotenv.config();
// Configure logging
const logger = {
info: (message) => console.log(`INFO - ${new Date().toISOString()} - ${message}`),
error: (message) => console.error(`ERROR - ${new Date().toISOString()} - ${message}`),
};
async function loadYogaPosesDataFromLocalFile(filename) {
try {
const data = await fs.readFile(filename, 'utf-8');
const poses = JSON.parse(data);
logger.info(`Loaded ${poses.length} poses.`);
return poses;
} catch (error) {
logger.error(`Error loading dataset: ${error}`);
return null;
}
}
function createFirestoreDocuments(poses) {
const documents = [];
for (const pose of poses) {
// Convert the pose to a string representation for pageContent
const pageContent = `
name: ${pose.name || ''}
description: ${pose.description || ''}
sanskrit_name: ${pose.sanskrit_name || ''}
expertise_level: ${pose.expertise_level || 'N/A'}
pose_type: ${pose.pose_type || 'N/A'}
`.trim();
// The metadata will be the whole pose
const metadata = pose;
documents.push({ pageContent, metadata });
}
logger.info(`Created ${documents.length} Langchain documents.`);
return documents;
}
async function main() {
const allPoses = await loadYogaPosesDataFromLocalFile('./data/yoga_poses_with_descriptions.json');
const documents = createFirestoreDocuments(allPoses);
logger.info(`Successfully created Firestore documents. Total documents: ${documents.length}`);
const embeddings = new VertexAIEmbeddings({
model: process.env.EMBEDDING_MODEL_NAME,
});
// Initialize Firestore
const firestore = new Firestore({
projectId: process.env.PROJECT_ID,
databaseId: process.env.DATABASE,
});
const collectionName = process.env.TEST_COLLECTION;
for (const doc of documents) {
try {
// 1. Generate Embeddings
const singleVector = await embeddings.embedQuery(doc.pageContent);
// 2. Store in Firestore with Embeddings
const firestoreDoc = {
content: doc.pageContent,
metadata: doc.metadata, // Store the original data as metadata
embedding: FieldValue.vector(singleVector), // Add the embedding vector
};
const docRef = firestore.collection(collectionName).doc();
await docRef.set(firestoreDoc);
logger.info(`Document ${docRef.id} added to Firestore with embedding.`);
} catch (error) {
logger.error(`Error processing document: ${error}`);
}
}
logger.info('Finished adding documents to Firestore.');
}
main();
Exécutons cette application. Ouvrez une nouvelle fenêtre de terminal (Ctrl+Maj+C) et exécutez la commande suivante:
npm run import-data
Si tout se passe bien, un message semblable à celui-ci doit s'afficher:
INFO - 2025-01-28T07:01:14.463Z - Loaded 3 poses.
INFO - 2025-01-28T07:01:14.464Z - Created 3 Langchain documents.
INFO - 2025-01-28T07:01:14.464Z - Successfully created Firestore documents. Total documents: 3
INFO - 2025-01-28T07:01:17.623Z - Document P46d5F92z9FsIhVVYgkd added to Firestore with embedding.
INFO - 2025-01-28T07:01:18.265Z - Document bjXXISctkXl2ZRSjUYVR added to Firestore with embedding.
INFO - 2025-01-28T07:01:19.285Z - Document GwzZMZyPfTLtiX6qBFFz added to Firestore with embedding.
INFO - 2025-01-28T07:01:19.286Z - Finished adding documents to Firestore.
Pour vérifier si les enregistrements ont bien été insérés et si les représentations vectorielles continues ont été générées, accédez à la page Firestore de la console Cloud.
Cliquez sur la base de données (par défaut). La collection test-poses
et plusieurs documents sous cette collection devraient s'afficher. Chaque document correspond à une posture de yoga.
Cliquez sur l'un des documents pour examiner les champs. En plus des champs que nous avons importés, vous trouverez également le champ embedding
, qui est un champ Vector, dont nous avons généré la valeur via le modèle d'embedding Vertex AI text-embedding-004
.
Maintenant que les enregistrements ont été importés dans la base de données Firestore avec les représentations vectorielles continues en place, nous pouvons passer à l'étape suivante et voir comment effectuer une recherche de similarité vectorielle dans Firestore.
6. Importer des poses de yoga complètes dans une collection de base de données Firestore
Nous allons maintenant créer la collection poses
, qui est une liste complète de 160 postures de yoga, pour laquelle nous avons généré un fichier d'importation de base de données que vous pouvez importer directement. Cela permet de gagner du temps pendant l'atelier. Le processus de génération de la base de données contenant la description et les représentations vectorielles continues est le même que celui que nous avons vu dans la section précédente.
Importez la base de données en suivant les étapes ci-dessous:
- Créez un bucket dans votre projet à l'aide de la commande
gsutil
ci-dessous. Remplacez la variable<PROJECT_ID>
dans la commande ci-dessous par l'ID de votre projet Google Cloud.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
- Maintenant que le bucket est créé, nous devons y copier l'exportation de la base de données que nous avons préparée avant de pouvoir l'importer dans la base de données Firebase. Utilisez la commande ci-dessous:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615 gs://<PROJECT_ID>-my-bucket
Maintenant que nous avons les données à importer, nous pouvons passer à l'étape finale d'importation des données dans la base de données Firebase (default
) que nous avons créée.
- Utilisez la commande gcloud ci-dessous:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615
L'importation prend quelques secondes. Une fois qu'elle est terminée, vous pouvez valider votre base de données Firestore et la collection en accédant à https://console.cloud.google.com/firestore/databases, en sélectionnant la base de données default
et la collection poses
, comme indiqué ci-dessous:
La création de la collection Firestore que nous utiliserons dans notre application est terminée.
7. Effectuer une recherche de similarité vectorielle dans Firestore
Pour effectuer une recherche de similarité vectorielle, nous allons saisir la requête de l'utilisateur. Par exemple, "Suggest me some exercises to relieve back pain"
.
Examinez le fichier search-data.js
. La fonction clé à examiner est la fonction search
, qui est illustrée ci-dessous. De manière générale, il crée une classe d'embedding qui doit être utilisée pour générer l'embedding de la requête utilisateur. Il établit ensuite une connexion à la base de données et à la collection Firestore. Ensuite, sur la collection, il appelle la méthode findNearest, qui effectue une recherche de similarité vectorielle.
async function search(query) {
try {
const embeddings = new VertexAIEmbeddings({
model: process.env.EMBEDDING_MODEL_NAME,
});
// Initialize Firestore
const firestore = new Firestore({
projectId: process.env.PROJECT_ID,
databaseId: process.env.DATABASE,
});
log.info(`Now executing query: ${query}`);
const singleVector = await embeddings.embedQuery(query);
const collectionRef = firestore.collection(process.env.COLLECTION);
let vectorQuery = collectionRef.findNearest(
"embedding",
FieldValue.vector(singleVector), // a vector with 768 dimensions
{
limit: process.env.TOP_K,
distanceMeasure: "COSINE",
}
);
const vectorQuerySnapshot = await vectorQuery.get();
for (const result of vectorQuerySnapshot.docs) {
console.log(result.data().content);
}
} catch (error) {
log.error(`Error during search: ${error.message}`);
}
}
Avant d'exécuter cette requête avec quelques exemples, vous devez d'abord générer un index composite Firestore, qui est nécessaire pour que vos requêtes de recherche aboutissent. Si vous exécutez l'application sans créer l'index, un message d'erreur indiquant que vous devez d'abord créer l'index s'affiche, avec la commande à exécuter pour le créer.
La commande gcloud
permettant de créer l'index composite est indiquée ci-dessous:
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
L'indexation prend quelques minutes, car la base de données contient plus de 150 enregistrements. Une fois l'indexation terminée, vous pouvez afficher l'index à l'aide de la commande ci-dessous:
gcloud firestore indexes composite list
L'index que vous venez de créer doit s'afficher dans la liste.
Essayez maintenant la commande suivante:
node search-data.js --prompt "Recommend me some exercises for back pain relief"
Vous devriez recevoir quelques recommandations. Voici un exemple d'exécution:
2025-01-28T07:09:05.250Z - INFO - Now executing query: Recommend me some exercises for back pain relief
name: Sphinx Pose
description: A gentle backbend, Sphinx Pose (Salamba Bhujangasana) strengthens the spine and opens the chest. Keep shoulders relaxed, lengthen the tailbone, and engage the core for optimal alignment. Beginner-friendly.
sanskrit_name: Salamba Bhujangasana
expertise_level: Beginner
pose_type: ['Prone']
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 your spine throughout the twist.
sanskrit_name: Supta Matsyendrasana
expertise_level: Beginner
pose_type: ['Supine', 'Twist']
name: Reverse Corpse Pose
description: Reverse Corpse Pose (Advasana) is a beginner prone pose. Lie on your belly, arms at your sides, relaxing completely. Benefits include stress release and spinal decompression. Ensure your forehead rests comfortably on the mat.
sanskrit_name: Advasana
expertise_level: Beginner
pose_type: ['Prone']
Une fois que vous avez terminé, vous savez maintenant comment utiliser la base de données vectorielle Firestore pour importer des enregistrements, générer des représentations vectorielles continues et effectuer une recherche de similarité vectorielle. Nous pouvons maintenant créer une application Web qui intégrera la recherche vectorielle dans un front-end Web.
8. L'application Web
L'application Web Python Flask est disponible dans le fichier app.js
, et le fichier HTML du front-end est présent dans le fichier views/index.html.
.
Nous vous recommandons de consulter les deux fichiers. Commencez par le fichier app.js
qui contient le gestionnaire /search
, qui récupère l'invite transmise à partir du fichier HTML index.html
du front-end. La méthode de recherche est ensuite appelée, ce qui effectue la recherche de similarité vectorielle que nous avons examinée dans la section précédente.
La réponse est ensuite renvoyée à index.html
avec la liste des recommandations. index.html
affiche ensuite les recommandations sous forme de fiches différentes.
Exécuter l'application en local
Ouvrez une nouvelle fenêtre de terminal (Ctrl+Maj+C) ou une fenêtre de terminal existante, puis exécutez la commande suivante:
npm run start
Voici un exemple d'exécution:
...
Server listening on port 8080
Une fois l'application opérationnelle, accédez à son URL d'accueil en cliquant sur le bouton "Aperçu sur le Web" ci-dessous:
Le fichier index.html
diffusé doit s'afficher, comme illustré ci-dessous:
Fournissez un exemple de requête (par exemple, Provide me some exercises for back pain relief
) et cliquez sur le bouton Search
. Vous devriez ainsi récupérer certaines recommandations dans la base de données. Vous verrez également un bouton Play Audio
, qui génère un flux audio basé sur la description, que vous pouvez écouter directement.
9. (Facultatif) Déployer sur Google Cloud Run
La dernière étape consiste à déployer cette application sur Google Cloud Run. La commande de déploiement est indiquée ci-dessous. Avant de la déployer, assurez-vous de remplacer les valeurs affichées en gras ci-dessous. Vous pourrez récupérer ces valeurs dans le fichier .env
.
gcloud run deploy yogaposes --source . \
--port=8080 \
--allow-unauthenticated \
--region=<<YOUR_LOCATION>> \
--platform=managed \
--project=<<YOUR_PROJECT_ID>> \
--set-env-vars=PROJECT_ID="<<YOUR_PROJECT_ID>>",LOCATION="<<YOUR_LOCATION>>",EMBEDDING_MODEL_NAME="<<EMBEDDING_MODEL_NAME>>",DATABASE="<<FIRESTORE_DATABASE_NAME>>",COLLECTION="<<FIRESTORE_COLLECTION_NAME>>",TOP_K=<<YOUR_TOP_K_VALUE>>
Exécutez la commande ci-dessus à partir du dossier racine de l'application. Vous serez peut-être également invité à activer les API Google Cloud et à accepter diverses autorisations. Veuillez le faire.
Le processus de déploiement prend environ cinq à sept minutes. Veuillez donc patienter.
Une fois le déploiement terminé, l'URL du service Cloud Run s'affiche dans la sortie du déploiement. Il se présente sous la forme suivante:
Service URL: https://yogaposes-<UNIQUEID>.us-central1.run.app
Accédez à cette URL publique. Vous devriez voir la même application Web déployée et en cours d'exécution.
Vous pouvez également accéder à Cloud Run depuis la console Google Cloud pour afficher la liste des services dans Cloud Run. Le service yogaposes
doit figurer dans la liste (s'il n'est pas le seul).
Vous pouvez afficher les détails du service, tels que l'URL, les configurations, les journaux, etc., en cliquant sur le nom du service spécifique (yogaposes
dans notre cas).
Vous avez terminé le développement et le déploiement de notre application Web de recommandation de postures de yoga sur Cloud Run.
10. Félicitations
Félicitations ! Vous avez créé une application qui importe un ensemble de données dans Firestore, génère des représentations vectorielles continues et effectue une recherche de similarité vectorielle en fonction de la requête de l'utilisateur.