1. Pengantar
Dalam codelab ini, Anda akan mem-build aplikasi yang menggunakan penelusuran vektor untuk merekomendasikan pose Yoga.
Melalui codelab ini, Anda akan menggunakan pendekatan langkah demi langkah sebagai berikut:
- Manfaatkan Set Data Hugging Face yang ada untuk pose Yoga (format JSON).
- Tingkatkan kualitas set data dengan deskripsi kolom tambahan yang menggunakan Gemini untuk membuat deskripsi setiap pose.
- Muat data postur Yoga sebagai kumpulan Dokumen dalam koleksi Firestore dengan penyematan yang dihasilkan.
- Buat indeks gabungan di Firestore untuk mengaktifkan penelusuran Vektor.
- Gunakan Vector Search di Aplikasi Node.js yang menggabungkan semuanya seperti yang ditunjukkan di bawah:
Yang akan Anda lakukan
- Buat Desain, Build, dan Deploy aplikasi web yang menggunakan Vector Search untuk merekomendasikan pose Yoga.
Yang akan Anda pelajari
- Cara menggunakan Gemini untuk membuat konten teks dan dalam konteks codelab ini, membuat deskripsi untuk pose yoga
- Cara memuat data dari set data yang ditingkatkan dari Hugging Face ke Firestore beserta Vector Embedding
- Cara menggunakan Firestore Vector Search untuk menelusuri data berdasarkan kueri bahasa alami
- Cara menggunakan Google Cloud Text to Speech API untuk membuat konten Audio
Yang Anda butuhkan
- Browser web Chrome
- Akun Gmail
- Project Cloud dengan penagihan diaktifkan
Codelab ini, yang dirancang untuk developer dari semua tingkat (termasuk pemula), menggunakan JavaScript dan Node.js dalam aplikasi contohnya. Namun, pengetahuan JavaScript dan Node.js tidak diperlukan untuk memahami konsep yang disajikan.
2. Sebelum memulai
Membuat project
- Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
- Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project .
- Anda akan menggunakan Cloud Shell, lingkungan command line yang berjalan di Google Cloud yang telah dilengkapi dengan bq. Klik Aktifkan Cloud Shell di bagian atas konsol Google Cloud.
- Setelah terhubung ke Cloud Shell, Anda akan memeriksa bahwa Anda sudah diautentikasi dan project ditetapkan ke project ID Anda menggunakan perintah berikut:
gcloud auth list
- Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda.
gcloud config list project
- Jika project Anda belum ditetapkan, gunakan perintah berikut untuk menetapkannya:
gcloud config set project <YOUR_PROJECT_ID>
- Aktifkan API yang diperlukan melalui perintah yang ditampilkan di bawah. Tindakan ini mungkin memerlukan waktu beberapa menit, jadi harap bersabar.
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
Setelah perintah berhasil dieksekusi, Anda akan melihat pesan yang mirip dengan yang ditampilkan di bawah ini:
Operation "operations/..." finished successfully.
Alternatif untuk perintah gcloud adalah melalui konsol dengan menelusuri setiap produk atau menggunakan link ini.
Jika ada API yang terlewat, Anda dapat mengaktifkannya kapan saja selama proses penerapan.
Baca dokumentasi untuk mempelajari perintah gcloud dan penggunaannya.
Meng-clone repositori dan menyiapkan setelan lingkungan
Langkah berikutnya adalah meng-clone repositori contoh yang akan kita referensikan di bagian codelab lainnya. Dengan asumsi bahwa Anda berada di Cloud Shell, berikan perintah berikut dari direktori utama:
git clone https://github.com/rominirani/yoga-poses-recommender-nodejs
Untuk meluncurkan editor, klik Buka Editor di toolbar jendela Cloud Shell. Klik panel menu di sudut kiri atas, lalu pilih File → Buka Folder seperti yang ditunjukkan di bawah:
Pilih folder yoga-poses-recommender-nodejs
dan Anda akan melihat folder terbuka dengan file berikut seperti yang ditunjukkan di bawah ini:
Sekarang kita perlu menyiapkan variabel lingkungan yang akan digunakan. Klik file env-template
dan Anda akan melihat konten seperti yang ditunjukkan di bawah ini:
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
Perbarui nilai untuk PROJECT_ID
dan LOCATION
sesuai dengan yang Anda pilih saat membuat Project Google Cloud dan wilayah Database Firestore. Idealnya, kita ingin nilai LOCATION
sama untuk Project Google Cloud dan Database Firestore, misalnya us-central1
.
Untuk tujuan codelab ini, kita akan menggunakan nilai berikut (kecuali tentu saja untuk PROJECT_ID
dan LOCATION
, yang perlu Anda tetapkan sesuai konfigurasi Anda.
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
Simpan file ini sebagai .env
di folder yang sama dengan file env-template
.
Buka menu utama di kiri atas di Cloud Shell IDE, lalu Terminal → New Terminal
.
Buka folder root repositori yang Anda clone melalui perintah berikut:
cd yoga-poses-recommender-nodejs
Instal dependensi Node.js melalui perintah:
npm install
Bagus! Sekarang kita siap untuk melanjutkan ke tugas menyiapkan database Firestore.
3. Menyiapkan Firestore
Cloud Firestore adalah database dokumen serverless yang terkelola sepenuhnya yang akan kita gunakan sebagai backend untuk data aplikasi. Data di Cloud Firestore disusun dalam koleksi dokumen.
Inisialisasi Database Firestore
Buka halaman Firestore di konsol Cloud.
Jika Anda belum menginisialisasi database Firestore sebelumnya dalam project, buat database default
dengan mengklik Create Database
. Selama pembuatan database, gunakan nilai berikut:
- Mode Firestore:
Native.
- Lokasi: Gunakan setelan lokasi default.
- Untuk Aturan Keamanan, pilih
Test rules
. - Buat Database.
Di bagian berikutnya, kita akan menyiapkan dasar-dasar untuk membuat koleksi bernama poses
di database Firestore default. Koleksi ini akan menyimpan data sampel (dokumen) atau informasi pose Yoga, yang kemudian akan kita gunakan dalam aplikasi.
Dengan ini, bagian untuk menyiapkan database Firestore telah selesai.
4. Menyiapkan set data Pose yoga
Tugas pertama kita adalah menyiapkan set data Pose Yoga yang akan kita gunakan untuk aplikasi. Kita akan memulai dengan set data Hugging Face yang ada, lalu meningkatkannya dengan informasi tambahan.
Lihat Set Data Hugging Face untuk Pose Yoga. Perhatikan bahwa meskipun codelab ini menggunakan salah satu set data, Anda sebenarnya dapat menggunakan set data lain dan mengikuti teknik yang sama yang ditunjukkan untuk meningkatkan kualitas set data.
Jika membuka bagian Files and versions
, kita bisa mendapatkan file data JSON untuk semua pose.
Kami telah mendownload yoga_poses.json
dan memberikan file tersebut kepada Anda. File ini diberi nama yoga_poses_alldata.json
dan ada di folder /data
.
Buka file data/yoga_poses.json
di Cloud Shell Editor dan lihat daftar objek JSON, dengan setiap objek JSON mewakili postur Yoga. Kita memiliki total 3 data dan contoh data ditampilkan di bawah:
{
"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"]
}
Sekarang adalah kesempatan yang bagus bagi kita untuk memperkenalkan Gemini dan cara menggunakan model default itu sendiri untuk membuat kolom description
untuknya.
Di Cloud Shell Editor, buka file generate-descriptions.js
. Isi file ini ditampilkan di bawah:
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();
Aplikasi ini akan menambahkan kolom description
baru ke setiap kumpulan data JSON postur Yoga. Model ini akan mendapatkan deskripsi melalui panggilan ke model Gemini, tempat kami akan memberikan perintah yang diperlukan. Kolom ditambahkan ke file JSON dan file baru ditulis ke file data/yoga_poses_with_descriptions.json
.
Mari kita bahas langkah-langkah utamanya:
- Dalam fungsi
main()
, Anda akan menemukan bahwa fungsi tersebut memanggil fungsiadd_descriptions_to_json
dan menyediakan file input dan file output yang diharapkan. - Fungsi
add_descriptions_to_json
melakukan hal berikut untuk setiap data JSON, yaitu informasi postingan Yoga: - Fungsi ini mengekstrak
pose_name
,sanskrit_name
,expertise_level
, danpose_types
. - Fungsi ini memanggil fungsi
callGemini
yang membuat perintah, lalu memanggil class model LangchainVertexAI untuk mendapatkan teks respons. - Teks respons ini kemudian ditambahkan ke objek JSON.
- Daftar objek JSON yang diperbarui kemudian ditulis ke file tujuan.
Mari kita jalankan aplikasi ini. Luncurkan jendela terminal baru (Ctrl+Shift+C) dan berikan perintah berikut:
npm run generate-descriptions
Jika Anda dimintai otorisasi, harap berikan otorisasi tersebut.
Anda akan melihat bahwa aplikasi mulai dieksekusi. Kami telah menambahkan penundaan 30 detik di antara data untuk menghindari kuota batas kapasitas yang mungkin ada di akun Google Cloud baru, jadi harap bersabar.
Contoh operasi yang sedang berlangsung ditampilkan di bawah ini:
Setelah ketiga data tersebut ditingkatkan dengan panggilan Gemini, file data/yoga_poses_with_description.json
akan dibuat. Anda dapat melihatnya.
Sekarang kita siap dengan file data dan langkah selanjutnya adalah memahami cara mengisi Database Firestore dengan file tersebut, beserta pembuatan penyematan.
5. Mengimpor Data ke Firestore dan membuat Embedding Vektor
Kita memiliki file data/yoga_poses_with_description.json
dan sekarang perlu mengisi Database Firestore dengan file tersebut dan yang terpenting, membuat Penyematan Vektor untuk setiap kumpulan data. Embedding Vektor akan berguna nanti saat kita harus melakukan penelusuran kemiripan pada embedding tersebut dengan kueri pengguna yang telah diberikan dalam bahasa alami.
Langkah-langkah untuk melakukannya adalah sebagai berikut:
- Kita akan mengonversi daftar objek JSON menjadi daftar objek. Setiap dokumen akan memiliki dua atribut:
content
danmetadata
. Objek metadata akan berisi seluruh objek JSON yang memiliki atribut sepertiname
,description
,sanskrit_name
, dll.content
akan berupa teks string yang akan menjadi gabungan dari beberapa kolom. - Setelah memiliki daftar dokumen, kita akan menggunakan class Vertex AI Embeddings untuk membuat embedding kolom konten. Penyematan ini akan ditambahkan ke setiap data dokumen, lalu kita akan menggunakan Firestore API untuk menyimpan daftar objek dokumen ini dalam koleksi (kita menggunakan variabel
TEST_COLLECTION
yang mengarah ketest-poses
).
Kode untuk import-data.js
diberikan di bawah (bagian kode telah dipotong agar lebih ringkas):
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();
Mari kita jalankan aplikasi ini. Luncurkan jendela terminal baru (Ctrl+Shift+C) dan berikan perintah berikut:
npm run import-data
Jika semuanya berjalan lancar, Anda akan melihat pesan yang mirip dengan pesan di bawah ini:
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.
Untuk memeriksa apakah data telah berhasil disisipkan dan penyematan telah dibuat, buka halaman Firestore di konsol Cloud.
Klik database (default), tindakan ini akan menampilkan koleksi test-poses
dan beberapa dokumen dalam koleksi tersebut. Setiap dokumen adalah satu pose Yoga.
Klik salah satu dokumen untuk menyelidiki kolom. Selain kolom yang kami impor, Anda juga akan menemukan kolom embedding
, yang merupakan kolom Vektor, yang nilainya kami buat melalui model Vertex AI Embedding text-embedding-004
.
Setelah memiliki data yang diupload ke Database Firestore dengan penyematan yang sudah diterapkan, kita dapat melanjutkan ke langkah berikutnya dan melihat cara melakukan Penelusuran Kemiripan Vektor di Firestore.
6. Mengimpor pose Yoga lengkap ke dalam koleksi Database Firestore
Sekarang kita akan membuat koleksi poses
, yang merupakan daftar lengkap dari 160 pose Yoga, yang file impor database-nya telah kita buat dan dapat Anda impor secara langsung. Hal ini dilakukan untuk menghemat waktu di lab. Proses untuk membuat database yang berisi deskripsi dan penyematan sama dengan yang kita lihat di bagian sebelumnya.
Impor database dengan mengikuti langkah-langkah berikut:
- Buat bucket di project Anda dengan perintah
gsutil
yang diberikan di bawah. Ganti variabel<PROJECT_ID>
dalam perintah di bawah dengan Project ID Google Cloud Anda.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
- Setelah bucket dibuat, kita perlu menyalin ekspor database yang telah kita siapkan ke bucket ini, sebelum dapat mengimpornya ke database Firebase. Gunakan perintah yang diberikan di bawah:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615 gs://<PROJECT_ID>-my-bucket
Setelah memiliki data yang akan diimpor, kita dapat melanjutkan ke langkah terakhir untuk mengimpor data ke database Firebase (default
) yang telah kita buat.
- Gunakan perintah gcloud yang diberikan di bawah ini:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615
Pengimporan akan memerlukan waktu beberapa detik dan setelah siap, Anda dapat memvalidasi database Firestore dan koleksi dengan membuka https://console.cloud.google.com/firestore/databases, memilih database default
dan koleksi poses
seperti yang ditunjukkan di bawah:
Tindakan ini akan menyelesaikan pembuatan koleksi Firestore yang akan kita gunakan di aplikasi.
7. Melakukan Penelusuran Kemiripan Vektor di Firestore
Untuk melakukan Penelusuran Kemiripan Vektor, kita akan mengambil kueri dari pengguna. Contoh kueri ini dapat berupa "Suggest me some exercises to relieve back pain"
.
Lihat file search-data.js
. Fungsi utama yang perlu dilihat adalah fungsi search
, yang ditampilkan di bawah. Pada tingkat tinggi, class ini membuat class penyematan yang akan digunakan untuk membuat penyematan untuk kueri pengguna. Kemudian, aplikasi akan membuat koneksi ke database dan koleksi Firestore. Kemudian, pada koleksi, metode ini memanggil metode findNearest, yang melakukan Penelusuran Kemiripan Vektor.
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}`);
}
}
Sebelum menjalankannya dengan beberapa contoh kueri, Anda harus membuat indeks komposit Firestore terlebih dahulu, yang diperlukan agar kueri penelusuran berhasil. Jika Anda menjalankan aplikasi tanpa membuat indeks, error yang menunjukkan bahwa Anda perlu membuat indeks terlebih dahulu akan ditampilkan dengan perintah untuk membuat indeks terlebih dahulu.
Perintah gcloud
untuk membuat indeks gabungan ditampilkan di bawah:
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
Indeks akan memerlukan waktu beberapa menit untuk selesai karena ada lebih dari 150 data yang ada di database. Setelah selesai, Anda dapat melihat indeks melalui perintah yang ditampilkan di bawah ini:
gcloud firestore indexes composite list
Anda akan melihat indeks yang baru saja dibuat dalam daftar.
Coba perintah berikut sekarang:
node search-data.js --prompt "Recommend me some exercises for back pain relief"
Anda akan mendapatkan beberapa rekomendasi. Contoh operasi ditampilkan di bawah ini:
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']
Setelah berhasil melakukannya, sekarang kita telah memahami cara menggunakan Database Vektor Firestore untuk mengupload data, membuat penyematan, dan melakukan Penelusuran Kemiripan Vektor. Sekarang kita dapat membuat aplikasi web yang akan mengintegrasikan penelusuran vektor ke frontend web.
8. Aplikasi Web
Aplikasi web Python Flask tersedia dalam file app.js
dan file HTML frontend ada di views/index.html.
Sebaiknya Anda melihat kedua file tersebut. Mulailah terlebih dahulu dengan file app.js
yang berisi pengendali /search
, yang mengambil perintah yang telah diteruskan dari file index.html
HTML frontend. Tindakan ini kemudian akan memanggil metode penelusuran, yang melakukan penelusuran Kesamaan Vektor yang kita lihat di bagian sebelumnya.
Respons kemudian dikirim kembali ke index.html
dengan daftar rekomendasi. index.html
kemudian menampilkan rekomendasi sebagai kartu yang berbeda.
Menjalankan aplikasi secara lokal
Luncurkan jendela terminal baru (Ctrl+Shift+C) atau jendela terminal yang ada, lalu berikan perintah berikut:
npm run start
Contoh eksekusi ditampilkan di bawah ini:
...
Server listening on port 8080
Setelah siap dan berjalan, buka URL beranda aplikasi, dengan mengklik tombol Pratinjau Web yang ditampilkan di bawah:
Tindakan ini akan menampilkan file index.html
yang ditayangkan seperti yang ditunjukkan di bawah ini:
Berikan contoh kueri (Contoh : Provide me some exercises for back pain relief
) dan klik tombol Search
. Tindakan ini akan mengambil beberapa rekomendasi dari database. Anda juga akan melihat tombol Play Audio
, yang akan menghasilkan streaming audio berdasarkan deskripsi, yang dapat Anda dengar secara langsung.
9. (Opsional) Men-deploy ke Google Cloud Run
Langkah terakhir kita adalah men-deploy aplikasi ini ke Google Cloud Run. Perintah deployment ditampilkan di bawah. Pastikan sebelum men-deploy-nya, Anda mengganti nilai yang ditampilkan dalam cetak tebal di bawah. Ini adalah nilai yang dapat Anda ambil dari file .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>>
Jalankan perintah di atas dari folder root aplikasi. Anda mungkin juga diminta untuk mengaktifkan Google Cloud API, berikan konfirmasi Anda untuk berbagai izin.
Proses deployment akan memerlukan waktu sekitar 5-7 menit, jadi harap bersabar.
Setelah berhasil di-deploy, output deployment akan memberikan URL layanan Cloud Run. URL tersebut akan memiliki format:
Service URL: https://yogaposes-<UNIQUEID>.us-central1.run.app
Buka URL publik tersebut dan Anda akan melihat aplikasi web yang sama di-deploy dan berhasil berjalan.
Anda juga dapat membuka Cloud Run dari konsol Google Cloud dan akan melihat daftar layanan di Cloud Run. Layanan yogaposes
harus menjadi salah satu layanan (jika bukan satu-satunya) yang tercantum di sana.
Anda dapat melihat detail layanan seperti URL, konfigurasi, log, dan lainnya dengan mengklik nama layanan tertentu (yogaposes
dalam kasus kami).
Dengan demikian, pengembangan dan deployment aplikasi web perekomendasikan postur Yoga di Cloud Run telah selesai.
10. Selamat
Selamat, Anda telah berhasil mem-build aplikasi yang mengupload set data ke Firestore, membuat penyematan, dan melakukan Penelusuran Kemiripan Vektor berdasarkan kueri pengguna.