1. はじめに
この Codelab では、ベクトル検索を使用してヨガのポーズを推奨するアプリケーションを作成します。
この Codelab では、次の手順でアプローチします。
- ヨガのポーズの既存の Hugging Face データセット(JSON 形式)を利用します。
- Gemini を使用して各ポーズの説明を生成する追加のフィールドの説明でデータセットを強化します。
- Langchain を使用してドキュメントを作成し、Firestore Langchain 統合を使用して Firestore にコレクションとエンベディングを作成します。
- Firestore に複合インデックスを作成して、ベクトル検索を可能にします。
- 以下に示すように、すべてをまとめた Flask アプリケーションでベクトル検索を利用します。

演習内容
- ベクトル検索を使用してヨガのポーズを推奨するウェブ アプリケーションを設計、構築、デプロイします。
学習内容
- Gemini を使用してテキスト コンテンツを生成する方法と、この Codelab のコンテキスト内でヨガのポーズの説明を生成する方法
- Langchain Document Loader for Firestore を使用して、Hugging Face の拡張データセットから Firestore にレコードをベクトル エンベディングとともに読み込む方法
- Langchain Vector Store for Firestore を使用して自然言語クエリに基づいてデータを検索する方法
- Google Cloud Text to Speech API を使用して音声コンテンツを生成する方法
必要なもの
- Chrome ウェブブラウザ
- Gmail アカウント
- 課金が有効になっている Cloud プロジェクト
この Codelab は、初心者を含むあらゆるレベルのデベロッパーを対象としており、サンプル アプリケーションで Python を使用します。ただし、ここで説明するコンセプトを理解するために Python の知識は必要ありません。
2. 始める前に
プロジェクトを作成する
- Google Cloud コンソールのプロジェクト選択ページで、Google Cloud プロジェクトを選択または作成します。
- Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。
- Cloud Shell(Google Cloud で動作するコマンドライン環境)を使用します。この環境には bq がプリロードされています。Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします。
![[Cloud Shell をアクティブにする] ボタンの画像](https://codelabs.developers.google.com/static/yoga-pose-firestore-vectorsearch-python/img/7875ca05ca6f7cab.png?hl=ja)
- Cloud Shell に接続したら、次のコマンドを使用して、すでに認証済みであることと、プロジェクトがプロジェクト ID に設定されていることを確認します。
gcloud auth list
- Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
- プロジェクトが設定されていない場合は、次のコマンドを使用して設定します。
gcloud config set project <YOUR_PROJECT_ID>
- 次のコマンドを使用して、必要な API を有効にします。これには数分かかることがあります。
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 コマンドの代わりに、コンソールで各プロダクトを検索するか、こちらのリンクを使用することもできます。
API が見つからない場合は、実装中にいつでも有効にできます。
gcloud コマンドとその使用方法については、ドキュメントをご覧ください。
リポジトリのクローンを作成して環境設定を行う
次のステップでは、Codelab の残りの部分で参照するサンプル リポジトリのクローンを作成します。Cloud Shell にいると仮定して、ホーム ディレクトリから次のコマンドを実行します。
git clone https://github.com/rominirani/yoga-poses-recommender-python
エディタを起動するには、Cloud Shell ウィンドウのツールバーにある [エディタを開く] をクリックします。左上のメニューバーをクリックし、[ファイル] → [フォルダを開く] を選択します。

yoga-poses-recommender-python フォルダを選択すると、次のようにフォルダが開き、次のファイルが表示されます。

ここで、使用する環境変数を設定する必要があります。config.template.yaml ファイルをクリックすると、次のような内容が表示されます。
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"
Google Cloud プロジェクトと Firestore データベースのリージョンを作成する際に選択した内容に従って、project_id と location の値を更新してください。理想的には、Google Cloud プロジェクトと Firestore データベースの location の値が同じ(us-central1 など)であることが望ましいです。
この Codelab では、事前構成済みの値を使用します(ただし、project_id と location は構成に合わせて設定する必要があります)。
このファイルを config.template.yaml ファイルと同じフォルダに config.yaml として保存してください。
最後のステップは、すべての Python 依存関係が設定された状態でローカルで使用する Python 環境を作成することです。同じ詳細を含む pyproject.toml ファイルを見てみましょう。その内容は次のとおりです。
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",
]
これらの依存関係は requirements.txt. でバージョン ロックされています。要約すると、requirements.txt の Python パッケージの依存関係を含む仮想 Python 環境を作成し、仮想環境にインストールする必要があります。これを行うには、Cloud Shell IDE の Command Palette(Ctrl+Shift+P)に移動して、「Python: Create Environment」と入力します。次の手順に沿って、Virtual Environment(venv)、Python 3.x interpreter、requirements.txt ファイルを選択します。
環境が作成されたら、次のコマンドを使用して作成した環境を有効にする必要があります。
source .venv/bin/activate
コンソールに (.venv) が表示されます。例: -> (.venv) yourusername@cloudshell:
これで準備が整いました。これで、Firestore データベースの設定タスクに進む準備が整いました。
3. Firestore を設定する
Cloud Firestore は、アプリケーション データのバックエンドとして使用するフルマネージドのサーバーレス ドキュメント データベースです。Cloud Firestore のデータは、ドキュメントのコレクションに構造化されています。
Firestore データベースの初期化
Cloud コンソールの Firestore ページに移動します。
プロジェクトで Firestore データベースを初期化したことがない場合は、Create Database をクリックして default データベースを作成します。データベースの作成時に、次の値を使用します。
- Firestore モード:
Native. - [ロケーション タイプ] で
Regionを選択し、リージョンのロケーションとしてus-central1を選択します。 - セキュリティ ルールには
Test rulesを使用します。 - データベースを作成します。

次のセクションでは、デフォルトの Firestore データベースに poses という名前のコレクションを作成するための準備を行います。このコレクションには、アプリケーションで使用するサンプルデータ(ドキュメント)またはヨガポーズの情報が格納されます。
これで、Firestore データベースの設定セクションは完了です。
4. ヨガのポーズのデータセットを準備する
最初のタスクは、アプリケーションで使用するヨガポーズのデータセットを準備することです。既存の Hugging Face データセットから始め、追加情報で強化します。
ヨガのポーズの Hugging Face データセットをご覧ください。この Codelab ではデータセットの 1 つを使用しますが、実際には他のデータセットを使用することもできます。その場合も、ここで説明した手法に沿ってデータセットを強化できます。

Files and versions セクションに移動すると、すべてのポーズの JSON データファイルを取得できます。

yoga_poses.json をダウンロードして、そのファイルを提供しました。このファイルの名前は yoga_poses_alldata.json で、/data フォルダにあります。
Cloud Shell エディタで data/yoga_poses.json ファイルに移動し、JSON オブジェクトのリストを確認します。各 JSON オブジェクトはヨガのポーズを表しています。合計 3 件のレコードがあり、サンプル レコードを以下に示します。
{
"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 エディタで、generate-descriptions.py ファイルに移動します。このファイルの内容は次のとおりです。
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()
このアプリケーションは、各ヨガのポーズの 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を抽出します。- generate_description 関数を呼び出してプロンプトを作成し、Langchain VertexAI モデルクラスを呼び出してレスポンス テキストを取得します。
- このレスポンス テキストは、JSON オブジェクトに追加されます。
- 更新された JSON オブジェクトのリストが宛先ファイルに書き込まれます。
このアプリケーションを実行してみましょう。新しいターミナル ウィンドウ(Ctrl+Shift+C)を起動し、次のコマンドを入力します。
python generate-descriptions.py
承認を求められた場合は、承認を行ってください。
アプリケーションの実行が開始されます。新しい Google Cloud アカウントにレート上限の割り当てがある場合に備えて、レコード間に 30 秒の遅延を追加しました。しばらくお待ちください。
以下は実行中のサンプルの例です。

3 つのレコードすべてが Gemini 呼び出しで拡張されると、ファイル data/yoga_poses_with_description.json が生成されます。そちらをご覧ください。
データファイルの準備が整いました。次のステップでは、エンベディングの生成とともに、Firestore データベースにデータを入力する方法について説明します。
5. Firestore にデータをインポートしてベクトル エンベディングを生成する
data/yoga_poses_with_description.json ファイルがあるので、これを使用して Firestore データベースにデータを入力し、各レコードのベクトル エンベディングを生成する必要があります。ベクトル エンベディングは、自然言語で指定されたユーザー クエリを使用して類似性検索を行う場合に役立ちます。
上記のプロセスを実装するには、Langchain Firestore コンポーネントを使用します。
手順は次のとおりです。
- JSON オブジェクトのリストを Langchain Document オブジェクトのリストに変換します。各ドキュメントには、
page_contentとmetadataの 2 つの属性があります。メタデータ オブジェクトには、name、description、sanskrit_nameなどの属性を持つ JSON オブジェクト全体が含まれます。page_contentは、いくつかのフィールドを連結した文字列テキストになります。 Documentオブジェクトのリストを取得したら、FirestoreVectorStoreLangchain クラスと、このドキュメントのリスト、コレクション名(test-posesを指すTEST_COLLECTION変数を使用)、Vertex AI エンベディング クラス、Firestore 接続の詳細(PROJECT_IDとDATABASEの名前)でfrom_documentsメソッドを使用します。これにより、コレクションが作成され、各属性のembeddingフィールドも生成されます。
import-data.py のコードは次のとおりです(コードの一部は簡潔にするために省略されています)。
...
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()
このアプリケーションを実行してみましょう。新しいターミナル ウィンドウ(Ctrl+Shift+C)を起動し、次のコマンドを入力します。
python import-data.py
すべてが正常に完了すると、次のようなメッセージが表示されます。
2025-01-21 14:50:06,479 - INFO - Added documents to the vector store.
レコードが正常に挿入され、エンベディングが生成されたかどうかを確認するには、Cloud コンソールの Firestore ページにアクセスします。

(デフォルトの)データベースをクリックします。これにより、test-poses コレクションと、そのコレクションの下にある複数のドキュメントが表示されます。各ドキュメントは 1 つのヨガのポーズです。

いずれかのドキュメントをクリックして、フィールドを調べます。インポートしたフィールドに加えて、使用した Langchain VertexAIEmbeddings クラスを介して自動的に生成されたベクトル フィールドである embedding フィールドもあります。このクラスでは、text-embedding-004 Vertex AI エンベディング モデルを指定しました。

エンベディングを含むレコードが Firestore データベースにアップロードされたので、次のステップに進み、Firestore でベクトル類似度検索を行う方法を確認します。
6. 完全なヨガのポーズを Firestore データベース コレクションにインポートします。
次に、160 個のヨガポーズの完全なリストである poses コレクションを作成します。このコレクションについては、直接インポートできるデータベース インポート ファイルを生成しました。これは、ラボでの時間を節約するために行います。説明とエンベディングを含むデータベースを生成するプロセスは、前のセクションで説明したプロセスと同じです。
以下の手順に沿ってデータベースをインポートします。
- 次の
gsutilコマンドを使用して、プロジェクトにバケットを作成します。次のコマンドの<PROJECT_ID>変数を、Google Cloud プロジェクト ID に置き換えます。
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.py ファイルを確認します。注目すべき主な関数は、以下の検索関数です。大まかに言うと、ユーザー クエリのエンベディングの生成に使用されるエンベディング クラスを作成します。次に、FirestoreVectorStore クラスを使用して 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)
いくつかのクエリの例でこのコードを実行する前に、検索クエリを成功させるために必要な 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
先ほど作成したインデックスがリストに表示されます。
次のコマンドを試してみましょう。
python search-data.py --prompt "Recommend me some exercises for back pain relief"
いくつかの推奨事項が表示されます。実行例を以下に示します。
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']
これで、Firestore ベクトル データベースを使用してレコードをアップロードし、エンベディングを生成してベクトル類似性検索を行う方法を理解できました。これで、ベクトル検索をウェブ フロントエンドに統合するウェブ アプリケーションを作成できます。
8. ウェブ アプリケーション
Python Flask ウェブ アプリケーションは main.py ファイルにあり、フロントエンドの HTML ファイルは templates/index.html. にあります。
両方のファイルを確認することをおすすめします。まず、フロントエンドの HTML index.html ファイルから渡されたプロンプトを受け取る /search ハンドラを含む main.py ファイルから始めます。これにより、検索メソッドが呼び出され、前のセクションで説明したベクトル類似度検索が実行されます。
その後、レスポンスがおすすめのリストとともに index.html に返されます。index.html は、推奨事項をさまざまなカードとして表示します。
アプリケーションをローカルで実行する
新しいターミナル ウィンドウ(Ctrl+Shift+C)または既存のターミナル ウィンドウを開き、次のコマンドを入力します。
python main.py
以下に実行例を示します。
* 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
起動したら、次のウェブ プレビュー ボタンをクリックして、アプリケーションのホーム URL にアクセスします。

次のように、提供された index.html ファイルが表示されます。

サンプルクエリ(例 : Provide me some exercises for back pain relief)を入力し、[Search] ボタンをクリックします。これにより、データベースからいくつかの推奨事項が取得されます。また、Play Audio ボタンも表示されます。このボタンをクリックすると、説明に基づいて音声ストリームが生成され、直接聞くことができます。

9. (省略可)Google Cloud Run へのデプロイ
最後のステップでは、このアプリケーションを Google Cloud Run にデプロイします。デプロイ コマンドは次のとおりです。デプロイする前に、変数(<<YOUR_PROJECT_ID>>)の値をプロジェクト固有の値に置き換えてください。これらの値は、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
上記のコマンドは、アプリケーションのルートフォルダから実行します。Google Cloud APIs を有効にするよう求められたり、さまざまな権限について確認を求められたりすることがあります。その場合は、指示に従ってください。
デプロイ プロセスが完了するまでに 5 ~ 7 分ほどかかりますので、しばらくお待ちください。

デプロイが正常に完了すると、デプロイの出力に Cloud Run サービスの URL が表示されます。形式は次のようになります。
Service URL: https://yogaposes-<<UNIQUEID>.us-central1.run.app
そのパブリック URL にアクセスすると、同じウェブ アプリケーションがデプロイされ、正常に実行されていることがわかります。

Google Cloud コンソールから Cloud Run にアクセスして、Cloud Run のサービスリストを表示することもできます。yogaposes サービスは、そこにリストされているサービス(唯一のサービスではない場合)の 1 つである必要があります。

特定のサービス名(この例では yogaposes)をクリックすると、URL、構成、ログなどのサービスの詳細を表示できます。

これで、Cloud Run でのヨガのポーズの推奨ウェブ アプリケーションの開発とデプロイが完了しました。
10. 完了
おめでとうございます。データセットを Firestore にアップロードし、エンベディングを生成して、ユーザーのクエリに基づいてベクトル類似度検索を行うアプリケーションを構築できました。