1. परिचय
इस कोडलैब में, आपको एक ऐसा ऐप्लिकेशन बनाने का तरीका बताया जाएगा जो योग के आसन सुझाने के लिए, वेक्टर सर्च का इस्तेमाल करता है.
कोडलैब के ज़रिए, आपको यहां दिया गया तरीका अपनाना होगा:
- योग की मुद्राओं के लिए, Hugging Face के मौजूदा डेटासेट (JSON फ़ॉर्मैट) का इस्तेमाल करो.
- डेटासेट को बेहतर बनाने के लिए, फ़ील्ड के बारे में अतिरिक्त जानकारी जोड़ें. इसमें Gemini का इस्तेमाल करके, हर पोज़ के लिए जानकारी जनरेट की जाती है.
- जनरेट की गई एम्बेडिंग के साथ, योग की मुद्राओं के डेटा को Firestore कलेक्शन में दस्तावेज़ों के कलेक्शन के तौर पर लोड करें.
- वेक्टर सर्च की सुविधा इस्तेमाल करने के लिए, Firestore में कंपोज़िट इंडेक्स बनाएं.
- Node.js ऐप्लिकेशन में वेक्टर सर्च का इस्तेमाल करें. इससे आपको नीचे दी गई जानकारी मिलेगी:

आपको क्या करना होगा
- एक ऐसा वेब ऐप्लिकेशन डिज़ाइन करें, बनाएं, और डिप्लॉय करें जो योग के आसन सुझाने के लिए वेक्टर सर्च का इस्तेमाल करता हो.
आपको क्या सीखने को मिलेगा
- टेक्स्ट कॉन्टेंट जनरेट करने के लिए Gemini का इस्तेमाल कैसे करें. साथ ही, इस कोडलैब के संदर्भ में, योगा पोज़ के लिए ब्यौरे जनरेट करने का तरीका
- Hugging Face के बेहतर डेटासेट से रिकॉर्ड को Firestore में, वेक्टर एम्बेडिंग के साथ लोड करने का तरीका
- नैचुरल लैंग्वेज क्वेरी के आधार पर डेटा खोजने के लिए, Firestore Vector Search का इस्तेमाल कैसे करें
- ऑडियो कॉन्टेंट जनरेट करने के लिए, Google Cloud Text to Speech API का इस्तेमाल कैसे करें
आपको इन चीज़ों की ज़रूरत होगी
- Chrome वेब ब्राउज़र
- Gmail खाता
- बिलिंग की सुविधा वाला Cloud प्रोजेक्ट
यह कोडलैब, सभी लेवल के डेवलपर (शुरुआती डेवलपर भी शामिल हैं) के लिए बनाया गया है. इसमें सैंपल ऐप्लिकेशन में JavaScript और Node.js का इस्तेमाल किया गया है. हालांकि, यहां बताए गए कॉन्सेप्ट को समझने के लिए, JavaScript और Node.js के बारे में जानकारी होना ज़रूरी नहीं है.
2. शुरू करने से पहले
प्रोजेक्ट बनाना
- Google Cloud Console में, प्रोजेक्ट चुनने वाले पेज पर, Google Cloud प्रोजेक्ट चुनें या बनाएं.
- पक्का करें कि आपके Cloud प्रोजेक्ट के लिए बिलिंग चालू हो. किसी प्रोजेक्ट के लिए बिलिंग चालू है या नहीं, यह देखने का तरीका जानें .
- आपको Cloud Shell का इस्तेमाल करना होगा. यह Google Cloud में चलने वाला कमांड-लाइन एनवायरमेंट है. इसमें bq पहले से लोड होता है. Google Cloud Console में सबसे ऊपर मौजूद, Cloud Shell चालू करें पर क्लिक करें.

- Cloud Shell से कनेक्ट होने के बाद, यह देखने के लिए कि आपकी पुष्टि हो चुकी है और प्रोजेक्ट को आपके प्रोजेक्ट आईडी पर सेट किया गया है, इस कमांड का इस्तेमाल करें:
gcloud auth list
- यह पुष्टि करने के लिए कि gcloud कमांड को आपके प्रोजेक्ट के बारे में पता है, Cloud Shell में यह कमांड चलाएं.
gcloud config list project
- अगर आपका प्रोजेक्ट सेट नहीं है, तो इसे सेट करने के लिए इस निर्देश का इस्तेमाल करें:
gcloud config set project <YOUR_PROJECT_ID>
- नीचे दिए गए निर्देश का इस्तेमाल करके, ज़रूरी एपीआई चालू करें. इसमें कुछ मिनट लग सकते हैं. इसलिए, कृपया इंतज़ार करें.
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
कमांड के सही तरीके से लागू होने पर, आपको यहां दिखाए गए मैसेज जैसा मैसेज दिखेगा:
Operation "operations/..." finished successfully.
gcloud कमांड के बजाय, कंसोल का इस्तेमाल करके भी ऐसा किया जा सकता है. इसके लिए, हर प्रॉडक्ट को खोजें या इस लिंक का इस्तेमाल करें.
अगर कोई एपीआई छूट जाता है, तो उसे लागू करने के दौरान कभी भी चालू किया जा सकता है.
gcloud कमांड और उनके इस्तेमाल के बारे में जानने के लिए, दस्तावेज़ देखें.
रिपॉज़िटरी को क्लोन करना और एनवायरमेंट की सेटिंग सेटअप करना
अगला चरण, उस सैंपल रिपॉज़िटरी को क्लोन करना है जिसे हम कोडलैब के बाकी हिस्से में रेफ़र करेंगे. मान लें कि आप Cloud Shell में हैं. अपनी होम डायरेक्ट्री से यह कमांड दें:
git clone https://github.com/rominirani/yoga-poses-recommender-nodejs
एडिटर लॉन्च करने के लिए, Cloud Shell विंडो के टूलबार पर मौजूद, एडिटर खोलें पर क्लिक करें. सबसे ऊपर बाएं कोने में मौजूद मेन्यू बार पर क्लिक करें. इसके बाद, नीचे दिए गए तरीके से फ़ाइल → फ़ोल्डर खोलें को चुनें:

yoga-poses-recommender-nodejs फ़ोल्डर चुनें. इसके बाद, आपको फ़ोल्डर में ये फ़ाइलें दिखेंगी, जैसा कि यहां दिखाया गया है:

अब हमें उन एनवायरमेंट वैरिएबल को सेट अप करना होगा जिनका हम इस्तेमाल करेंगे. env-template फ़ाइल पर क्लिक करें. इसके बाद, आपको कॉन्टेंट इस तरह दिखेगा:
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
कृपया PROJECT_ID और LOCATION के लिए, वे वैल्यू अपडेट करें जो आपने Google Cloud प्रोजेक्ट और Firestore डेटाबेस क्षेत्र बनाते समय चुनी थीं. हम चाहते हैं कि Google Cloud प्रोजेक्ट और Firestore डेटाबेस, दोनों के लिए LOCATION की वैल्यू एक जैसी हो. उदाहरण के लिए, us-central1.
इस कोडलैब के लिए, हम यहां दी गई वैल्यू का इस्तेमाल करेंगे. हालांकि, PROJECT_ID और LOCATION को आपको अपने कॉन्फ़िगरेशन के हिसाब से सेट करना होगा.
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
कृपया इस फ़ाइल को .env के तौर पर उसी फ़ोल्डर में सेव करें जिसमें env-template फ़ाइल है.
Cloud Shell IDE में सबसे ऊपर बाईं ओर मौजूद मुख्य मेन्यू पर जाएं. इसके बाद, Terminal → New Terminal पर क्लिक करें.
उस रिपॉज़िटरी के रूट फ़ोल्डर पर जाएं जिसे आपने इस कमांड का इस्तेमाल करके क्लोन किया है:
cd yoga-poses-recommender-nodejs
इस कमांड का इस्तेमाल करके, Node.js की डिपेंडेंसी इंस्टॉल करें:
npm install
बहुत बढ़िया ! अब हम Firestore डेटाबेस सेट अप करने के लिए तैयार हैं.
3. Firestore सेटअप करना
Cloud Firestore, पूरी तरह से मैनेज किया जाने वाला सर्वरलेस दस्तावेज़ डेटाबेस है. इसका इस्तेमाल हम अपने ऐप्लिकेशन के डेटा के बैकएंड के तौर पर करेंगे. Cloud Firestore में डेटा को दस्तावेज़ों के संग्रहों में व्यवस्थित किया जाता है.
Firestore डेटाबेस शुरू करना
Cloud Console में Firestore पेज पर जाएं.
अगर आपने प्रोजेक्ट में पहले कभी Firestore डेटाबेस शुरू नहीं किया है, तो Create Database पर क्लिक करके default डेटाबेस बनाएं. डेटाबेस बनाते समय, इन वैल्यू का इस्तेमाल करें:
- Firestore मोड:
Native. - जगह के टाइप के तौर पर
Regionचुनें. इसके बाद, इलाके के लिएus-central1लोकेशन चुनें. - सुरक्षा नियमों के लिए,
Test rulesपर जाएं. - डेटाबेस बनाएं.

अगले सेक्शन में, हम अपने डिफ़ॉल्ट Firestore डेटाबेस में poses नाम का कलेक्शन बनाने के लिए, बुनियादी सेटअप करेंगे. इस कलेक्शन में सैंपल डेटा (दस्तावेज़) या योग की पोज़ के बारे में जानकारी होगी. इसका इस्तेमाल हम अपने ऐप्लिकेशन में करेंगे.
इससे Firestore डेटाबेस को सेट अप करने का सेक्शन पूरा हो जाता है.
4. योग की मुद्राओं का डेटासेट तैयार करना
हमारा पहला काम, योगा पोज़ का डेटासेट तैयार करना है. इसका इस्तेमाल हम ऐप्लिकेशन के लिए करेंगे. हम Hugging Face के मौजूदा डेटासेट से शुरुआत करेंगे. इसके बाद, इसमें ज़्यादा जानकारी जोड़ेंगे.
योग की मुद्राओं के लिए Hugging Face डेटासेट देखें. ध्यान दें कि इस कोडलैब में एक डेटासेट का इस्तेमाल किया गया है. हालांकि, आपके पास किसी दूसरे डेटासेट का इस्तेमाल करने का विकल्प होता है. साथ ही, डेटासेट को बेहतर बनाने के लिए, दिखाई गई तकनीकों का इस्तेमाल किया जा सकता है.

Files and versions सेक्शन में जाकर, सभी पोज़ के लिए JSON डेटा फ़ाइल हासिल की जा सकती है.

हमने yoga_poses.json डाउनलोड कर लिया है और आपको वह फ़ाइल भेज दी है. इस फ़ाइल का नाम yoga_poses_alldata.json है और यह /data फ़ोल्डर में मौजूद है.
Cloud Shell Editor में data/yoga_poses.json फ़ाइल पर जाएं और JSON ऑब्जेक्ट की सूची देखें. इसमें हर JSON ऑब्जेक्ट, योगा पोज़ के बारे में बताता है. हमारे पास कुल तीन रिकॉर्ड हैं. यहां एक सैंपल रिकॉर्ड दिखाया गया है:
{
"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"]
}
अब हमारे पास Gemini को पेश करने का एक शानदार मौका है. साथ ही, हम यह भी बता सकते हैं कि इसके लिए description फ़ील्ड जनरेट करने के लिए, डिफ़ॉल्ट मॉडल का इस्तेमाल कैसे किया जा सकता है.
Cloud Shell Editor में, generate-descriptions.js फ़ाइल पर जाएं. इस फ़ाइल का कॉन्टेंट यहां दिया गया है:
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();
यह ऐप्लिकेशन, योगा पोज़ के हर JSON रिकॉर्ड में एक नया description फ़ील्ड जोड़ेगा. यह Gemini मॉडल को कॉल करके, इमेज के बारे में जानकारी हासिल करेगा. इसके लिए, हम उसे ज़रूरी प्रॉम्प्ट देंगे. यह फ़ील्ड, JSON फ़ाइल में जोड़ दिया जाता है. साथ ही, नई फ़ाइल को data/yoga_poses_with_descriptions.json फ़ाइल में लिख दिया जाता है.
आइए, मुख्य चरणों के बारे में जानते हैं:
- आपको
main()फ़ंक्शन में दिखेगा कि यहadd_descriptions_to_jsonफ़ंक्शन को चालू करता है. साथ ही, इनपुट फ़ाइल और उम्मीद के मुताबिक आउटपुट फ़ाइल उपलब्ध कराता है. add_descriptions_to_jsonफ़ंक्शन, हर JSON रिकॉर्ड के लिए यह काम करता है. जैसे, योग पोस्ट की जानकारी:- यह
pose_name,sanskrit_name,expertise_level, औरpose_typesको अलग करता है. - यह
callGeminiफ़ंक्शन को शुरू करता है, जो एक प्रॉम्प्ट बनाता है. इसके बाद, यह LangchainVertexAI मॉडल क्लास को शुरू करता है, ताकि जवाब का टेक्स्ट मिल सके. - इसके बाद, इस जवाब के टेक्स्ट को JSON ऑब्जेक्ट में जोड़ दिया जाता है.
- इसके बाद, अपडेट की गई ऑब्जेक्ट की JSON सूची को डेस्टिनेशन फ़ाइल में लिखा जाता है.
हमें इस ऐप्लिकेशन को चलाने की अनुमति दें. नई टर्मिनल विंडो (Ctrl+Shift+C) लॉन्च करें और यह कमांड दें:
npm run generate-descriptions
अगर आपसे कोई अनुमति मांगी जाती है, तो कृपया उसे दें.
आपको दिखेगा कि ऐप्लिकेशन काम करना शुरू कर देगा. हमने रिकॉर्ड के बीच 30 सेकंड का समय जोड़ा है, ताकि Google Cloud के नए खातों पर दर की सीमा से जुड़े किसी भी कोटे से बचा जा सके. इसलिए, कृपया इंतज़ार करें.
यहां, प्रोसेस में चल रहे सैंपल का उदाहरण दिया गया है:

Gemini की मदद से तीनों रिकॉर्ड बेहतर बनाने के बाद, एक फ़ाइल data/yoga_poses_with_description.json जनरेट होगी. इसे देखा जा सकता है.
अब हमारी डेटा फ़ाइल तैयार है. अगला चरण यह समझना है कि इसे Firestore डेटाबेस में कैसे भरा जाए. साथ ही, एम्बेडिंग कैसे जनरेट की जाए.
5. Firestore में डेटा इंपोर्ट करना और वेक्टर एम्बेडिंग जनरेट करना
हमारे पास data/yoga_poses_with_description.json फ़ाइल है. अब हमें इसे Firestore डेटाबेस में डालना है. साथ ही, हर रिकॉर्ड के लिए वेक्टर एम्बेडिंग जनरेट करनी है. वेक्टर एम्बेडिंग, बाद में तब काम आएंगी, जब हमें उपयोगकर्ता की क्वेरी के आधार पर मिलती-जुलती खोज करनी होगी. यह क्वेरी, सामान्य भाषा में दी गई है.
इसके लिए, यह तरीका अपनाएं:
- हम JSON ऑब्जेक्ट की सूची को ऑब्जेक्ट की सूची में बदल देंगे. हर दस्तावेज़ में दो एट्रिब्यूट होंगे:
contentऔरmetadata. मेटाडेटा ऑब्जेक्ट में पूरा JSON ऑब्जेक्ट शामिल होगा. इसमेंname,description,sanskrit_nameजैसे एट्रिब्यूट होंगे.contentएक स्ट्रिंग टेक्स्ट होगा, जो कुछ फ़ील्ड को जोड़कर बनाया जाएगा. - दस्तावेज़ों की सूची मिलने के बाद, हम कॉन्टेंट फ़ील्ड के लिए एम्बेडिंग जनरेट करने के लिए, Vertex AI Embeddings क्लास का इस्तेमाल करेंगे. इस एम्बेडिंग को हर दस्तावेज़ रिकॉर्ड में जोड़ा जाएगा. इसके बाद, हम Firestore API का इस्तेमाल करके, दस्तावेज़ ऑब्जेक्ट की इस सूची को कलेक्शन में सेव करेंगे. हम
TEST_COLLECTIONवैरिएबल का इस्तेमाल कर रहे हैं, जोtest-posesकी ओर इशारा करता है.
import-data.js का कोड यहां दिया गया है. कोड के कुछ हिस्सों को छोटा कर दिया गया है, ताकि इसे आसानी से समझा जा सके:
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();
हमें इस ऐप्लिकेशन को चलाने की अनुमति दें. नई टर्मिनल विंडो (Ctrl+Shift+C) लॉन्च करें और यह कमांड दें:
npm run import-data
अगर सब कुछ ठीक रहा, तो आपको यहां दिया गया मैसेज दिखेगा:
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.
यह देखने के लिए कि रिकॉर्ड सही तरीके से डाले गए हैं और एम्बेडिंग जनरेट की गई हैं, Cloud Console में Firestore पेज पर जाएं.

(डिफ़ॉल्ट) डेटाबेस पर क्लिक करें. इससे आपको test-poses कलेक्शन और उस कलेक्शन में मौजूद कई दस्तावेज़ दिखेंगे. हर दस्तावेज़ में एक योगा पोज़ है.

फ़ील्ड की जांच करने के लिए, किसी भी दस्तावेज़ पर क्लिक करें. हमने जिन फ़ील्ड को इंपोर्ट किया है उनके अलावा, आपको embedding फ़ील्ड भी दिखेगा. यह एक वेक्टर फ़ील्ड है. इसकी वैल्यू हमने text-embedding-004 Vertex AI Embedding मॉडल की मदद से जनरेट की है.

अब हमने एम्बेडिंग के साथ रिकॉर्ड को Firestore डेटाबेस में अपलोड कर दिया है. इसलिए, हम अगले चरण पर जा सकते हैं और देख सकते हैं कि Firestore में वेक्टर सिमिलैरिटी सर्च कैसे की जाती है.
6. Firestore डेटाबेस कलेक्शन में, योग की सभी मुद्राएं इंपोर्ट करना
अब हम poses कलेक्शन बनाएंगे. इसमें योग के 160 आसनों की पूरी सूची होगी. इसके लिए, हमने डेटाबेस इंपोर्ट करने वाली फ़ाइल जनरेट की है. इसे सीधे तौर पर इंपोर्ट किया जा सकता है. ऐसा लैब में समय बचाने के लिए किया जाता है. ब्यौरा और एम्बेडिंग शामिल करने वाला डेटाबेस जनरेट करने की प्रोसेस वही है जो हमने पिछले सेक्शन में देखी थी.
नीचे दिया गया तरीका अपनाकर, डेटाबेस इंपोर्ट करें:
- नीचे दी गई
gsutilकमांड का इस्तेमाल करके, अपने प्रोजेक्ट में एक बकेट बनाएं. नीचे दिए गए कमांड में,<PROJECT_ID>वैरिएबल की जगह अपना Google Cloud प्रोजेक्ट आईडी डालें.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
- बकेट बन जाने के बाद, हमें डेटाबेस के उस एक्सपोर्ट को इस बकेट में कॉपी करना होगा जिसे हमने तैयार किया है. ऐसा करने के बाद ही, हम इसे Firebase डेटाबेस में इंपोर्ट कर पाएंगे. नीचे दिए गए निर्देश का इस्तेमाल करें:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615 gs://<PROJECT_ID>-my-bucket
अब हमारे पास इंपोर्ट करने के लिए डेटा है. इसलिए, हम बनाए गए Firebase डेटाबेस (default) में डेटा इंपोर्ट करने के आखिरी चरण पर जा सकते हैं.
- नीचे दिए गए gcloud कमांड का इस्तेमाल करें:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615
इंपोर्ट होने में कुछ सेकंड लगेंगे. इसके बाद, https://console.cloud.google.com/firestore/databases पर जाकर, अपने Firestore डेटाबेस और कलेक्शन की पुष्टि की जा सकती है. इसके लिए, नीचे दिखाए गए तरीके से default डेटाबेस और poses कलेक्शन चुनें:

इससे, Firestore कलेक्शन बनाने की प्रोसेस पूरी हो जाती है. इसका इस्तेमाल हम अपने ऐप्लिकेशन में करेंगे.
7. Firestore में वेक्टर सिमिलैरिटी सर्च करना
वेक्टर सिमिलैरिटी सर्च करने के लिए, हम उपयोगकर्ता से क्वेरी लेंगे. इस क्वेरी का एक उदाहरण "Suggest me some exercises to relieve back pain" हो सकता है.
search-data.js फ़ाइल देखें. यहाँ search फ़ंक्शन के बारे में बताया गया है. यह एक एम्बेडिंग क्लास बनाता है. इसका इस्तेमाल, उपयोगकर्ता की क्वेरी के लिए एम्बेडिंग जनरेट करने के लिए किया जाता है. इसके बाद, यह Firestore डेटाबेस और कलेक्शन से कनेक्ट हो जाता है. इसके बाद, यह कलेक्शन पर findNearest तरीके को लागू करता है. यह वेक्टर सिमिलैरिटी सर्च करता है.
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}`);
}
}
क्वेरी के कुछ उदाहरणों के साथ इसे चलाने से पहले, आपको सबसे पहले Firestore कंपोज़िट इंडेक्स जनरेट करना होगा. यह आपकी खोज क्वेरी के लिए ज़रूरी है. अगर इंडेक्स बनाए बिना ऐप्लिकेशन चलाया जाता है, तो एक गड़बड़ी का मैसेज दिखेगा. इसमें बताया जाएगा कि आपको पहले इंडेक्स बनाना होगा. साथ ही, इंडेक्स बनाने के लिए कमांड भी दी जाएगी.
कंपोज़िट इंडेक्स बनाने के लिए, gcloud कमांड यहां दी गई है:
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
डेटाबेस में 150 से ज़्यादा रिकॉर्ड मौजूद हैं. इसलिए, इंडेक्स बनने में कुछ मिनट लगेंगे. यह प्रोसेस पूरी होने के बाद, नीचे दिए गए कमांड का इस्तेमाल करके इंडेक्स देखा जा सकता है:
gcloud firestore indexes composite list
आपको सूची में, अभी-अभी बनाया गया इंडेक्स दिखेगा.
अब यह निर्देश आज़माएँ:
node search-data.js --prompt "Recommend me some exercises for back pain relief"
आपको कुछ सुझाव दिए गए होंगे. यहां सैंपल रन दिखाया गया है:
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']
इस सुविधा के काम करने के बाद, हमें यह समझ आ गया है कि रिकॉर्ड अपलोड करने, एम्बेडिंग जनरेट करने, और वेक्टर समानता खोज करने के लिए, Firestore Vector Database का इस्तेमाल कैसे किया जाता है. अब हम एक वेब ऐप्लिकेशन बना सकते हैं, जो वेक्टर सर्च को वेब फ़्रंट-एंड में इंटिग्रेट करेगा.
8. वेब ऐप्लिकेशन
Python Flask वेब ऐप्लिकेशन, app.js फ़ाइल में उपलब्ध है. साथ ही, फ़्रंट-एंड एचटीएमएल फ़ाइल, views/index.html. में मौजूद है
हमारा सुझाव है कि आप दोनों फ़ाइलों को देख लें. सबसे पहले, app.js फ़ाइल से शुरू करें. इसमें /search हैंडलर होता है. यह फ़्रंट-एंड एचटीएमएल index.html फ़ाइल से पास किए गए प्रॉम्प्ट को लेता है. इसके बाद, खोज के तरीके को लागू किया जाता है. यह वेक्टर सिमिलैरिटी सर्च करता है, जिसके बारे में हमने पिछले सेक्शन में देखा था.
इसके बाद, सुझावों की सूची के साथ रिस्पॉन्स को index.html पर वापस भेज दिया जाता है. इसके बाद, index.html, सुझावों को अलग-अलग कार्ड के तौर पर दिखाता है.
ऐप्लिकेशन को स्थानीय तौर पर चलाना
नई टर्मिनल विंडो (Ctrl+Shift+C) या किसी मौजूदा टर्मिनल विंडो को लॉन्च करें और यह कमांड दें:
npm run start
यहां एक सैंपल दिखाया गया है:
...
Server listening on port 8080
सेट अप हो जाने के बाद, ऐप्लिकेशन के होम यूआरएल पर जाएं. इसके लिए, यहां दिया गया 'वेब की झलक देखें' बटन पर क्लिक करें:

इसमें आपको नीचे दिखाई गई index.html फ़ाइल दिखनी चाहिए:

कोई सैंपल क्वेरी (उदाहरण : Provide me some exercises for back pain relief) डालें और Search बटन पर क्लिक करें. इससे डेटाबेस से कुछ सुझाव वापस मिल जाने चाहिए. आपको Play Audio बटन भी दिखेगा. इससे, ब्यौरे के आधार पर एक ऑडियो स्ट्रीम जनरेट होगी. इसे सीधे तौर पर सुना जा सकता है.

9. (ज़रूरी नहीं) Google Cloud Run पर डिप्लॉय करना
आखिरी चरण में, हम इस ऐप्लिकेशन को Google Cloud Run पर डिप्लॉय करेंगे. डप्लॉयमेंट कमांड यहां दिखाई गई है. इसे डिप्लॉय करने से पहले, यहां दिखाई गई ब्रैकेट (<<>>) में मौजूद अलग-अलग वैल्यू बदलें. ये ऐसी वैल्यू हैं जिन्हें .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>>
ऊपर दिए गए कमांड को ऐप्लिकेशन के रूट फ़ोल्डर से चलाएं. आपको Google Cloud API चालू करने के लिए भी कहा जा सकता है. साथ ही, अलग-अलग अनुमतियों के लिए अपनी सहमति देने के लिए कहा जा सकता है. कृपया ऐसा करें.
डेटा डिप्लॉय होने में करीब 5 से 7 मिनट लगेंगे. इसलिए, कृपया इंतज़ार करें.

डिप्लॉयमेंट पूरा होने के बाद, डिप्लॉयमेंट आउटपुट में Cloud Run सेवा का यूआरएल दिखेगा. यह इस फ़ॉर्म में होगा:
Service URL: https://yogaposes-<UNIQUEID>.us-central1.run.app
उस सार्वजनिक यूआरएल पर जाएं. आपको दिखेगा कि वही वेब ऐप्लिकेशन डिप्लॉय किया गया है और वह सही तरीके से काम कर रहा है.

Google Cloud Console में जाकर भी Cloud Run पर जाया जा सकता है. यहां आपको Cloud Run में मौजूद सेवाओं की सूची दिखेगी. yogaposes सेवा, वहां दी गई सेवाओं में से एक होनी चाहिए. अगर वहां सिर्फ़ एक सेवा दी गई है, तो वह yogaposes सेवा होनी चाहिए.

सेवा के नाम (हमारे मामले में yogaposes) पर क्लिक करके, सेवा के बारे में ज़्यादा जानकारी देखी जा सकती है. जैसे, यूआरएल, कॉन्फ़िगरेशन, लॉग वगैरह.

इससे Cloud Run पर, योगा पोज़ के सुझाव देने वाले वेब ऐप्लिकेशन को डेवलप और डिप्लॉय करने की प्रोसेस पूरी हो जाती है.
10. बधाई हो
बधाई हो, आपने एक ऐसा ऐप्लिकेशन बना लिया है जो डेटासेट को Firestore में अपलोड करता है, एम्बेडिंग जनरेट करता है, और उपयोगकर्ताओं की क्वेरी के आधार पर वेक्टर सिमिलैरिटी सर्च करता है.