1. Giới thiệu
Trong lớp học lập trình này, bạn sẽ xây dựng một ứng dụng sử dụng tính năng tìm kiếm vectơ để đề xuất các tư thế Yoga.
Trong lớp học lập trình này, bạn sẽ sử dụng phương pháp từng bước như sau:
- Sử dụng một Tập dữ liệu hiện có của Hugging Face về các tư thế Yoga (định dạng JSON).
- Nâng cao tập dữ liệu bằng nội dung mô tả trường bổ sung sử dụng Gemini để tạo nội dung mô tả cho từng tư thế.
- Sử dụng Langchain để tạo một Tài liệu, sử dụng tính năng tích hợp Firestore Langchain để tạo bộ sưu tập và các mục nhúng trong Firestore.
- Tạo một chỉ mục kết hợp trong Firestore để cho phép tìm kiếm vectơ.
- Sử dụng tính năng Tìm kiếm vectơ trong một Ứng dụng Flask để kết hợp mọi thứ như minh hoạ dưới đây:

Bạn sẽ thực hiện
- Thiết kế, xây dựng và triển khai một ứng dụng web sử dụng tính năng Tìm kiếm vectơ để đề xuất các tư thế Yoga.
Kiến thức bạn sẽ học được
- Cách dùng Gemini để tạo nội dung văn bản và trong bối cảnh của lớp học lập trình này, hãy tạo nội dung mô tả cho các tư thế yoga
- Cách sử dụng Langchain Document Loader for Firestore để tải các bản ghi từ một tập dữ liệu nâng cao từ Hugging Face vào Firestore cùng với Vector Embeddings
- Cách sử dụng Langchain Vector Store cho Firestore để tìm kiếm dữ liệu dựa trên một cụm từ tìm kiếm bằng ngôn ngữ tự nhiên
- Cách sử dụng API Chuyển văn bản sang lời nói của Google Cloud để tạo nội dung âm thanh
Bạn cần có
- Trình duyệt web Chrome
- Tài khoản Gmail
- Một Dự án trên đám mây đã bật tính năng thanh toán
Lớp học lập trình này được thiết kế cho nhà phát triển ở mọi cấp độ (kể cả người mới bắt đầu), sử dụng Python trong ứng dụng mẫu. Tuy nhiên, bạn không cần có kiến thức về Python để hiểu các khái niệm được trình bày.
2. Trước khi bắt đầu
Tạo dự án
- Trong Google Cloud Console, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
- Đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên đám mây của bạn. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trong một dự án hay không .
- Bạn sẽ sử dụng Cloud Shell, một môi trường dòng lệnh chạy trong Google Cloud và được tải sẵn bằng bq. Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Google Cloud.

- Sau khi kết nối với Cloud Shell, bạn có thể kiểm tra để đảm bảo rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:
gcloud auth list
- Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn.
gcloud config list project
- Nếu bạn chưa đặt dự án, hãy dùng lệnh sau để đặt:
gcloud config set project <YOUR_PROJECT_ID>
- Bật các API bắt buộc thông qua lệnh bên dưới. Quá trình này có thể mất vài phút, vì vậy, vui lòng kiên nhẫn chờ đợi.
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
Khi thực thi lệnh thành công, bạn sẽ thấy một thông báo tương tự như thông báo dưới đây:
Operation "operations/..." finished successfully.
Bạn có thể thay thế lệnh gcloud bằng cách tìm kiếm từng sản phẩm trên bảng điều khiển hoặc sử dụng đường liên kết này.
Nếu bỏ lỡ API nào, bạn luôn có thể bật API đó trong quá trình triển khai.
Tham khảo tài liệu để biết các lệnh và cách sử dụng gcloud.
Sao chép kho lưu trữ và thiết lập chế độ cài đặt môi trường
Bước tiếp theo là sao chép kho lưu trữ mẫu mà chúng ta sẽ tham chiếu trong phần còn lại của lớp học lập trình. Giả sử bạn đang ở trong Cloud Shell, hãy đưa ra lệnh sau từ thư mục chính của bạn:
git clone https://github.com/rominirani/yoga-poses-recommender-python
Để khởi chạy trình chỉnh sửa, hãy nhấp vào Open Editor (Mở trình chỉnh sửa) trên thanh công cụ của cửa sổ Cloud Shell. Nhấp vào thanh trình đơn ở góc trên cùng bên trái rồi chọn Tệp → Mở thư mục như minh hoạ dưới đây:

Chọn thư mục yoga-poses-recommender-python. Bạn sẽ thấy thư mục này mở ra với các tệp sau đây như minh hoạ bên dưới:

Bây giờ, chúng ta cần thiết lập các biến môi trường mà chúng ta sẽ sử dụng. Nhấp vào tệp config.template.yaml, bạn sẽ thấy nội dung như hình bên dưới:
project_id: your-project-id
location: us-central1
gemini_model_name: gemini-1.5-flash-002
embedding_model_name: text-embedding-004
image_generation_model_name: imagen-3.0-fast-generate-002
database: (default)
collection: poses
test_collection: test-poses
top_k: "3"
Vui lòng cập nhật các giá trị cho project_id và location theo những gì bạn đã chọn khi tạo Dự án trên Google Cloud và khu vực Cơ sở dữ liệu Firestore. Lý tưởng nhất là các giá trị của location phải giống nhau đối với Dự án Google Cloud và Cơ sở dữ liệu Firestore, ví dụ: us-central1.
Trong lớp học lập trình này, chúng ta sẽ sử dụng các giá trị được định cấu hình sẵn (ngoại trừ project_id và location, bạn cần đặt theo cấu hình của mình.
Vui lòng lưu tệp này dưới dạng config.yaml trong cùng thư mục với tệp config.template.yaml.
Bước cuối cùng là tạo một môi trường Python mà chúng ta sẽ sử dụng cục bộ với tất cả các phần phụ thuộc Python được thiết lập cho chúng ta. Hãy xem tệp pyproject.toml chứa thông tin chi tiết về tệp này. Nội dung của tệp được trình bày dưới đây:
dependencies = [
"datasets>=3.2.0",
"flask>=3.1.0",
"google-cloud-aiplatform>=1.78.0",
"google-cloud-texttospeech>=2.24.0",
"langchain-community>=0.3.15",
"langchain-core>=0.3.31",
"langchain-google-community>=2.0.4",
"langchain-google-firestore>=0.5.0",
"langchain-google-vertexai>=2.0.7",
"pydantic-settings>=2.7.1",
"pyyaml>=6.0.2",
"tenacity>=9.0.0",
]
Các phần phụ thuộc này đã được khoá phiên bản trong requirements.txt. Tóm lại, chúng ta cần tạo một môi trường Python ảo với các phần phụ thuộc gói Python trong requirements.txt để cài đặt trong môi trường ảo. Để thực hiện việc này, hãy chuyển đến biểu tượng Command Palette (Ctrl+Shift+P) trong Cloud Shell IDE rồi nhập Python: Create Environment. Thực hiện một vài bước tiếp theo để chọn tệp Virtual Environment(venv), Python 3.x interpreter và requirements.txt.
Sau khi tạo môi trường, chúng ta sẽ cần kích hoạt môi trường đã tạo bằng lệnh sau
source .venv/bin/activate
Bạn sẽ thấy (.venv) trong bảng điều khiển. Ví dụ: -> (.venv) yourusername@cloudshell:
Tuyệt vời! Giờ đây, chúng ta đã sẵn sàng chuyển sang nhiệm vụ thiết lập cơ sở dữ liệu Firestore.
3. Thiết lập Firestore
Cloud Firestore là một cơ sở dữ liệu tài liệu không máy chủ, được quản lý toàn diện mà chúng ta sẽ dùng làm phần phụ trợ cho dữ liệu ứng dụng. Dữ liệu trong Cloud Firestore được cấu trúc thành tập hợp gồm tài liệu.
Khởi chạy cơ sở dữ liệu Firestore
Truy cập vào trang Firestore trong bảng điều khiển Cloud.
Nếu trước đây bạn chưa khởi tạo cơ sở dữ liệu Firestore trong dự án, hãy tạo cơ sở dữ liệu default bằng cách nhấp vào Create Database. Trong quá trình tạo cơ sở dữ liệu, hãy sử dụng các giá trị sau:
- Chế độ Firestore:
Native. - Chọn Loại địa điểm là
Regionrồi chọn địa điểmus-central1cho khu vực. - Đối với Quy tắc bảo mật, hãy chọn
Test rules. - Tạo cơ sở dữ liệu.

Trong phần tiếp theo, chúng ta sẽ đặt nền tảng để tạo một tập hợp có tên là poses trong cơ sở dữ liệu Firestore mặc định. Tập hợp này sẽ chứa dữ liệu mẫu (tài liệu) hoặc thông tin về các tư thế Yoga mà chúng ta sẽ sử dụng trong ứng dụng.
Đến đây là kết thúc phần thiết lập cơ sở dữ liệu Firestore.
4. Chuẩn bị tập dữ liệu tư thế Yoga
Nhiệm vụ đầu tiên của chúng ta là chuẩn bị tập dữ liệu Tư thế yoga mà chúng ta sẽ sử dụng cho ứng dụng. Chúng tôi sẽ bắt đầu với một tập dữ liệu hiện có của Hugging Face, sau đó cải thiện tập dữ liệu đó bằng thông tin bổ sung.
Hãy xem Tập dữ liệu Hugging Face cho các tư thế yoga. Xin lưu ý rằng mặc dù lớp học lập trình này sử dụng một trong các tập dữ liệu, nhưng trên thực tế, bạn có thể sử dụng bất kỳ tập dữ liệu nào khác và làm theo các kỹ thuật tương tự được minh hoạ để cải thiện tập dữ liệu.

Nếu chuyển đến phần Files and versions, chúng ta có thể lấy tệp dữ liệu JSON cho tất cả các tư thế.

Chúng tôi đã tải yoga_poses.json xuống và cung cấp tệp đó cho bạn. Tệp này có tên là yoga_poses_alldata.json và nằm trong thư mục /data.
Chuyển đến tệp data/yoga_poses.json trong Cloud Shell Editor rồi xem danh sách các đối tượng JSON, trong đó mỗi đối tượng JSON đại diện cho một tư thế Yoga. Chúng ta có tổng cộng 3 bản ghi và một bản ghi mẫu được trình bày bên dưới:
{
"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"]
}
Đây là cơ hội tuyệt vời để chúng ta giới thiệu Gemini và cách sử dụng chính mô hình mặc định để tạo trường description cho mô hình này.
Trong Trình chỉnh sửa Cloud Shell, hãy chuyển đến tệp generate-descriptions.py. Dưới đây là nội dung của tệp này:
import json
import time
import logging
import vertexai
from langchain_google_vertexai import VertexAI
from tenacity import retry, stop_after_attempt, wait_exponential
from settings import get_settings
settings = get_settings()
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
# Initialize Vertex AI SDK
vertexai.init(project=settings.project_id, location=settings.location)
logging.info("Done Initializing Vertex AI SDK")
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=4, max=10),
)
def generate_description(pose_name, sanskrit_name, expertise_level, pose_types):
"""Generates a description for a yoga pose using the Gemini API."""
prompt = f"""
Generate a concise description (max 50 words) for the yoga pose: {pose_name}
Also known as: {sanskrit_name}
Expertise Level: {expertise_level}
Pose Type: {", ".join(pose_types)}
Include key benefits and any important alignment cues.
"""
try:
model = VertexAI(model_name=settings.gemini_model_name, verbose=True)
response = model.invoke(prompt)
return response
except Exception as e:
logging.info(f"Error generating description for {pose_name}: {e}")
return ""
def add_descriptions_to_json(input_file, output_file):
"""Loads JSON data, adds descriptions, and saves the updated data."""
with open(input_file, "r") as f:
yoga_poses = json.load(f)
total_poses = len(yoga_poses)
processed_count = 0
for pose in yoga_poses:
if pose["name"] != " Pose":
start_time = time.time() # Record start time
pose["description"] = generate_description(
pose["name"],
pose["sanskrit_name"],
pose["expertise_level"],
pose["pose_type"],
)
end_time = time.time() # Record end time
processed_count += 1
end_time = time.time() # Record end time
time_taken = end_time - start_time
logging.info(
f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
)
else:
pose["description"] = ""
processed_count += 1
logging.info(
f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
)
# Adding a delay to avoid rate limit
time.sleep(30)
with open(output_file, "w") as f:
json.dump(yoga_poses, f, indent=2)
def main():
# File paths
input_file = "./data/yoga_poses.json"
output_file = "./data/yoga_poses_with_descriptions.json"
# Add descriptions and save the updated JSON
add_descriptions_to_json(input_file, output_file)
if __name__ == "__main__":
main()
Ứng dụng này sẽ thêm một trường description mới vào mỗi bản ghi JSON về tư thế Yoga. Ứng dụng sẽ lấy nội dung mô tả thông qua một lệnh gọi đến mô hình Gemini, trong đó chúng tôi sẽ cung cấp cho mô hình này câu lệnh cần thiết. Trường này sẽ được thêm vào tệp JSON và tệp mới sẽ được ghi vào tệp data/yoga_poses_with_descriptions.json.
Hãy cùng tìm hiểu các bước chính:
- Trong hàm
main(), bạn sẽ thấy rằng hàm này gọi hàmadd_descriptions_to_jsonvà cung cấp tệp đầu vào cũng như tệp đầu ra dự kiến. - Hàm
add_descriptions_to_jsonsẽ thực hiện những việc sau cho mỗi bản ghi JSON, tức là thông tin về bài đăng trên Yoga: - Thao tác này sẽ trích xuất
pose_name,sanskrit_name,expertise_levelvàpose_types. - Thao tác này sẽ gọi hàm generate_description để tạo một câu lệnh, sau đó gọi lớp mô hình Langchain VertexAI để nhận văn bản phản hồi.
- Sau đó, văn bản phản hồi này sẽ được thêm vào đối tượng JSON.
- Sau đó, danh sách đối tượng JSON đã cập nhật sẽ được ghi vào tệp đích.
Hãy chạy ứng dụng này. Khởi chạy một cửa sổ dòng lệnh mới (Ctrl+Shift+C) và đưa ra lệnh sau:
python generate-descriptions.py
Nếu bạn được yêu cầu uỷ quyền, vui lòng cung cấp thông tin đó.
Bạn sẽ thấy ứng dụng bắt đầu thực thi. Chúng tôi đã thêm độ trễ 30 giây giữa các bản ghi để tránh mọi hạn mức giới hạn tốc độ có thể có trên tài khoản Google Cloud mới, vì vậy, vui lòng kiên nhẫn chờ đợi.
Dưới đây là ví dụ về một lượt chạy đang diễn ra:

Sau khi cả 3 bản ghi được tăng cường bằng lệnh gọi Gemini, một tệp data/yoga_poses_with_description.json sẽ được tạo. Bạn có thể xem thông tin đó.
Chúng ta đã chuẩn bị xong tệp dữ liệu và bước tiếp theo là tìm hiểu cách điền dữ liệu vào Cơ sở dữ liệu Firestore, cùng với việc tạo các mục nhúng.
5. Nhập dữ liệu vào Firestore và tạo các vectơ nhúng
Chúng ta có tệp data/yoga_poses_with_description.json và giờ cần điền dữ liệu vào Cơ sở dữ liệu Firestore, đồng thời tạo Vector Embeddings cho từng bản ghi. Vector Embeddings sẽ hữu ích sau này khi chúng ta phải thực hiện tìm kiếm tương tự trên các Vector Embeddings đó bằng truy vấn của người dùng được cung cấp bằng ngôn ngữ tự nhiên.
Chúng ta sẽ sử dụng các thành phần Langchain Firestore để triển khai quy trình nêu trên.
Các bước thực hiện như sau:
- Chúng ta sẽ chuyển đổi danh sách đối tượng JSON thành danh sách đối tượng Langchain Document. Mỗi tài liệu sẽ có 2 thuộc tính:
page_contentvàmetadata. Đối tượng siêu dữ liệu sẽ chứa toàn bộ đối tượng JSON có các thuộc tính nhưname,description,sanskrit_name, v.v.page_contentsẽ là một văn bản dạng chuỗi, là chuỗi nối của một số trường. - Sau khi có danh sách các đối tượng
Document, chúng ta sẽ sử dụng lớpFirestoreVectorStoreLangchain và cụ thể là phương thứcfrom_documentsvới danh sách tài liệu này, tên bộ sưu tập (chúng ta đang sử dụng biếnTEST_COLLECTIONtrỏ đếntest-poses), một lớp Vertex AI Embedding và thông tin chi tiết về kết nối Firestore (tênPROJECT_IDvàDATABASE). Thao tác này sẽ tạo bộ sưu tập và cũng sẽ tạo một trườngembeddingcho từng thuộc tính.
Mã cho import-data.py được cung cấp bên dưới (một số phần của mã đã bị cắt bớt để ngắn gọn):
...
def create_langchain_documents(poses):
"""Creates a list of Langchain Documents from a list of poses."""
documents = []
for pose in poses:
# Convert the pose to a string representation for page_content
page_content = (
f"name: {pose.get('name', '')}\n"
f"description: {pose.get('description', '')}\n"
f"sanskrit_name: {pose.get('sanskrit_name', '')}\n"
f"expertise_level: {pose.get('expertise_level', 'N/A')}\n"
f"pose_type: {pose.get('pose_type', 'N/A')}\n"
).strip()
# The metadata will be the whole pose
metadata = pose
document = Document(page_content=page_content, metadata=metadata)
documents.append(document)
logging.info(f"Created {len(documents)} Langchain documents.")
return documents
def main():
all_poses = load_yoga_poses_data_from_local_file(
"./data/yoga_poses_with_descriptions.json"
)
documents = create_langchain_documents(all_poses)
logging.info(
f"Successfully created langchain documents. Total documents: {len(documents)}"
)
embedding = VertexAIEmbeddings(
model_name=settings.embedding_model_name,
project=settings.project_id,
location=settings.location,
)
client = firestore.Client(project=settings.project_id, database=settings.database)
vector_store = FirestoreVectorStore.from_documents(
client=client,
collection=settings.test_collection,
documents=documents,
embedding=embedding,
)
logging.info("Added documents to the vector store.")
if __name__ == "__main__":
main()
Hãy chạy ứng dụng này. Khởi chạy một cửa sổ dòng lệnh mới (Ctrl+Shift+C) và đưa ra lệnh sau:
python import-data.py
Nếu mọi thứ diễn ra suôn sẻ, bạn sẽ thấy một thông báo tương tự như thông báo dưới đây:
2025-01-21 14:50:06,479 - INFO - Added documents to the vector store.
Để kiểm tra xem các bản ghi đã được chèn thành công và các embeddings đã được tạo hay chưa, hãy truy cập vào trang Firestore trong bảng điều khiển Cloud.

Nhấp vào cơ sở dữ liệu (mặc định), thao tác này sẽ cho thấy bộ sưu tập test-poses và nhiều tài liệu trong bộ sưu tập đó. Mỗi tài liệu là một tư thế Yoga.

Nhấp vào một tài liệu bất kỳ để xem xét các trường. Ngoài các trường mà chúng ta đã nhập, bạn cũng sẽ thấy trường embedding. Đây là một trường Vector được tạo tự động cho bạn thông qua lớp Langchain VertexAIEmbeddings mà chúng ta đã sử dụng, trong đó chúng ta cung cấp mô hình Nhúng text-embedding-004 Vertex AI.

Giờ đây, sau khi tải các bản ghi lên Cơ sở dữ liệu Firestore cùng với các mục nhúng, chúng ta có thể chuyển sang bước tiếp theo và xem cách thực hiện Tìm kiếm tương tự theo vectơ trong Firestore.
6. Nhập toàn bộ tư thế Yoga vào bộ sưu tập Cơ sở dữ liệu Firestore
Bây giờ, chúng ta sẽ tạo bộ sưu tập poses. Đây là danh sách đầy đủ gồm 160 tư thế Yoga. Chúng ta đã tạo một tệp nhập cơ sở dữ liệu mà bạn có thể nhập trực tiếp. Việc này giúp tiết kiệm thời gian trong phòng thí nghiệm. Quy trình tạo cơ sở dữ liệu chứa nội dung mô tả và các vectơ nhúng cũng giống như quy trình mà chúng ta đã thấy trong phần trước.
Nhập cơ sở dữ liệu bằng cách làm theo các bước dưới đây:
- Tạo một bộ chứa trong dự án bằng lệnh
gsutilđược cung cấp bên dưới. Thay thế biến<PROJECT_ID>trong lệnh bên dưới bằng mã dự án của bạn trên Google Cloud.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
- Sau khi tạo vùng chứa, chúng ta cần sao chép dữ liệu xuất của cơ sở dữ liệu mà chúng ta đã chuẩn bị vào vùng chứa này, trước khi có thể nhập dữ liệu đó vào cơ sở dữ liệu Firebase. Sử dụng lệnh bên dưới:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615 gs://<PROJECT_ID>-my-bucket
Bây giờ, khi đã có dữ liệu để nhập, chúng ta có thể chuyển sang bước cuối cùng là nhập dữ liệu vào cơ sở dữ liệu Firebase (default) mà chúng ta đã tạo.
- Sử dụng lệnh gcloud bên dưới:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615
Quá trình nhập sẽ mất vài giây và sau khi hoàn tất, bạn có thể xác thực cơ sở dữ liệu Firestore và tập hợp bằng cách truy cập vào https://console.cloud.google.com/firestore/databases, chọn cơ sở dữ liệu default và tập hợp poses như minh hoạ bên dưới:

Thao tác này sẽ hoàn tất việc tạo bộ sưu tập Firestore mà chúng ta sẽ sử dụng trong ứng dụng.
7. Thực hiện tìm kiếm mức độ tương tự của vectơ trong Firestore
Để thực hiện tìm kiếm Mức độ tương đồng của vectơ, chúng ta sẽ lấy truy vấn từ người dùng. Ví dụ về truy vấn này có thể là "Suggest me some exercises to relieve back pain".
Hãy xem tệp search-data.py. Hàm chính cần xem xét là hàm tìm kiếm, được minh hoạ bên dưới. Nhìn chung, lớp này tạo ra một lớp nhúng sẽ được dùng để tạo lớp nhúng cho truy vấn của người dùng. Sau đó, lớp này sẽ dùng lớp FirestoreVectorStore để gọi hàm similarity_search.
def search(query: str):
"""Executes Firestore Vector Similarity Search"""
embedding = VertexAIEmbeddings(
model_name=settings.embedding_model_name,
project=settings.project_id,
location=settings.location,
)
client = firestore.Client(project=settings.project_id, database=settings.database)
vector_store = FirestoreVectorStore(
client=client, collection=settings.collection, embedding_service=embedding
)
logging.info(f"Now executing query: {query}")
results: list[Document] = vector_store.similarity_search(
query=query, k=int(settings.top_k), include_metadata=True
)
for result in results:
print(result.page_content)
Trước khi chạy thao tác này với một vài ví dụ về truy vấn, trước tiên, bạn phải tạo một chỉ mục kết hợp Firestore. Chỉ mục này là cần thiết để các truy vấn tìm kiếm của bạn thành công. Nếu bạn chạy ứng dụng mà không tạo chỉ mục, thì một lỗi cho biết bạn cần tạo chỉ mục trước sẽ xuất hiện cùng với lệnh tạo chỉ mục trước.
Lệnh gcloud để tạo chỉ mục kết hợp được trình bày dưới đây:
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
Quá trình lập chỉ mục sẽ mất vài phút để hoàn tất vì có hơn 150 bản ghi trong cơ sở dữ liệu. Sau khi hoàn tất, bạn có thể xem chỉ mục thông qua lệnh bên dưới:
gcloud firestore indexes composite list
Bạn sẽ thấy chỉ mục mà mình vừa tạo trong danh sách.
Hãy thử lệnh sau ngay bây giờ:
python search-data.py --prompt "Recommend me some exercises for back pain relief"
Bạn sẽ nhận được một số đề xuất. Sau đây là ví dụ về một lần chạy:
2025-01-21 15:48:51,282 - INFO - Now executing query: Recommend me some exercises for back pain relief
name: Supine Spinal Twist Pose
description: A gentle supine twist (Supta Matsyendrasana), great for beginners. Releases spinal tension, improves digestion, and calms the nervous system. Keep shoulders flat on the floor and lengthen the spine.
sanskrit_name: Supta Matsyendrasana
expertise_level: Beginner
pose_type: ['Supine', 'Twist']
name: Cow Pose
description: Cow Pose (Bitilasana) is a gentle backbend, stretching the chest, shoulders, and abdomen. Maintain a neutral spine, lengthen the tailbone, and avoid hyperextension. Benefits include improved posture and stress relief.
sanskrit_name: Bitilasana
expertise_level: Beginner
pose_type: ['Arm Leg Support', 'Back Bend']
name: Locust I Pose
description: Locust Pose I (Shalabhasana A) strengthens the back, glutes, and shoulders. Lie prone, lift chest and legs simultaneously, engaging back muscles. Keep hips grounded and gaze slightly forward.
sanskrit_name: Shalabhasana A
expertise_level: Intermediate
pose_type: ['Prone', 'Back Bend']
Sau khi bạn hoàn tất bước này, bạn sẽ hiểu cách sử dụng Cơ sở dữ liệu vectơ Firestore để tải bản ghi lên, tạo mục nhúng và thực hiện Tìm kiếm độ tương đồng của vectơ. Giờ đây, chúng ta có thể tạo một ứng dụng web tích hợp tính năng tìm kiếm vectơ vào giao diện người dùng web.
8. Ứng dụng web
Ứng dụng web Python Flask có trong tệp main.py và tệp HTML giao diện người dùng có trong templates/index.html.
Bạn nên xem cả hai tệp này. Bắt đầu bằng tệp main.py chứa trình xử lý /search. Trình xử lý này sẽ lấy câu lệnh đã được truyền từ tệp index.html HTML của giao diện người dùng. Sau đó, thao tác này sẽ gọi phương thức tìm kiếm, thực hiện tìm kiếm Tương đồng vectơ mà chúng ta đã xem xét ở phần trước.
Sau đó, phản hồi sẽ được gửi lại đến index.html cùng với danh sách đề xuất. Sau đó, index.html sẽ hiển thị các đề xuất dưới dạng các thẻ riêng biệt.
Chạy ứng dụng cục bộ
Khởi chạy một cửa sổ dòng lệnh mới (Ctrl+Shift+C) hoặc bất kỳ cửa sổ dòng lệnh hiện có nào và đưa ra lệnh sau:
python main.py
Dưới đây là một ví dụ về quá trình thực thi:
* Serving Flask app 'main'
* Debug mode: on
2025-01-21 16:02:37,473 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
* Running on http://10.88.0.4:8080
2025-01-21 16:02:37,473 - INFO - Press CTRL+C to quit
2025-01-21 16:02:37,474 - INFO - * Restarting with stat
2025-01-21 16:02:41,462 - WARNING - * Debugger is active!
2025-01-21 16:02:41,484 - INFO - * Debugger PIN: 440-653-555
Sau khi ứng dụng chạy, hãy truy cập vào URL trang chủ của ứng dụng bằng cách nhấp vào nút Web Preview (Xem trước trên web) như minh hoạ bên dưới:

Thao tác này sẽ cho bạn thấy tệp index.html được phân phát như minh hoạ dưới đây:

Cung cấp một cụm từ tìm kiếm mẫu (Ví dụ : Provide me some exercises for back pain relief) rồi nhấp vào nút Search. Thao tác này sẽ truy xuất một số đề xuất từ cơ sở dữ liệu. Bạn cũng sẽ thấy nút Play Audio. Nút này sẽ tạo một luồng âm thanh dựa trên nội dung mô tả mà bạn có thể nghe trực tiếp.

9. (Không bắt buộc) Triển khai lên Google Cloud Run
Bước cuối cùng là triển khai ứng dụng này lên Google Cloud Run. Lệnh triển khai xuất hiện bên dưới. Hãy đảm bảo rằng trước khi triển khai, bạn sẽ thay thế các giá trị cho biến (<<YOUR_PROJECT_ID>>) bằng các giá trị dành riêng cho dự án của bạn. Đây là những giá trị mà bạn có thể truy xuất từ tệp config.yaml.
gcloud run deploy yogaposes --source . \
--port=8080 \
--allow-unauthenticated \
--region=us-central1 \
--platform=managed \
--project=<<YOUR_PROJECT_ID>> \
--env-vars-file=config.yaml
Thực thi lệnh trên từ thư mục gốc của ứng dụng. Bạn cũng có thể được yêu cầu bật Google Cloud API và xác nhận cấp nhiều quyền. Vui lòng thực hiện việc này.
Quá trình triển khai sẽ mất khoảng 5 đến 7 phút để hoàn tất, vì vậy, vui lòng kiên nhẫn chờ đợi.

Sau khi triển khai thành công, đầu ra triển khai sẽ cung cấp URL dịch vụ Cloud Run. Nội dung này sẽ có dạng:
Service URL: https://yogaposes-<<UNIQUEID>.us-central1.run.app
Truy cập vào URL công khai đó và bạn sẽ thấy ứng dụng web tương tự được triển khai và chạy thành công.

Bạn cũng có thể truy cập vào Cloud Run từ bảng điều khiển Cloud của Google và bạn sẽ thấy danh sách các dịch vụ trong Cloud Run. Dịch vụ yogaposes phải là một trong các dịch vụ (nếu không phải là dịch vụ duy nhất) được liệt kê ở đó.

Bạn có thể xem thông tin chi tiết về dịch vụ như URL, cấu hình, nhật ký và nhiều thông tin khác bằng cách nhấp vào tên dịch vụ cụ thể (yogaposes trong trường hợp này).

Như vậy là chúng ta đã hoàn tất việc phát triển và triển khai ứng dụng web đề xuất tư thế Yoga trên Cloud Run.
10. Xin chúc mừng
Xin chúc mừng! Bạn đã tạo thành công một ứng dụng tải một tập dữ liệu lên Firestore, tạo các mục nhúng và thực hiện một Tìm kiếm tương tự theo vectơ dựa trên truy vấn của người dùng.