Firestore、ベクトル検索、Gemini 2.0 を使用して、コンテキストに応じたヨガのポーズ レコメンダー アプリを構築しましょう。

1. 概要

ウェルネス アプリやフィットネス アプリの世界では、ユーザーに豊かで魅力的なエクスペリエンスを提供することが重要です。たとえば、ヨガアプリでは、ポーズの簡単なテキスト記述を超えて、包括的な情報、マルチメディア コンテンツ、インテリジェントな検索機能を提供します。このブログでは、Google Cloud の Firestore を使用して堅牢なヨガのポーズ データベースを作成し、ベクトル検索拡張機能を使用してコンテキスト マッチングを行い、Gemini 2.0 Flash(試験運用版)を統合してマルチモーダル コンテンツを操作する方法について説明します。

Firestore を選ぶ理由

Google Cloud のサーバーレス NoSQL ドキュメント データベースである Firestore は、スケーラブルで動的アプリケーションを構築するのに最適です。ヨガアプリに最適な理由は次のとおりです。

  • スケーラビリティとパフォーマンス: Firestore は、数百万人のユーザーと大規模なデータセットを処理するように自動的にスケーリングし、アプリの成長に伴って応答性が低下しないようにします。
  • リアルタイム更新: リアルタイム同期が組み込まれているため、接続されているすべてのクライアント間でデータの整合性が維持されます。ライブ クラスや共同練習などの機能に最適です。
  • 柔軟なデータモデル: Firestore のドキュメント ベースの構造では、テキスト、画像、エンベディングなど、さまざまなデータ型を保存できるため、複雑なヨガのポーズ情報を表すのに最適です。
  • 強力なクエリ: Firestore は、等式、不等式などの複雑なクエリをサポートしています。また、新しい拡張機能により、ベクトル類似性検索もサポートされています。
  • オフライン サポート: Firestore はデータをローカルにキャッシュに保存するため、ユーザーがオフラインの場合でもアプリを機能させることができます。

Firestore ベクトル検索拡張機能による検索の強化

ヨガのポーズなど複雑なコンセプトに対応する場合、従来のキーワード ベースの検索では制限が生じる可能性があります。ユーザーは、特定のポーズ名を知らなくても、「腰を開く」ポーズや「バランスを改善する」ポーズを検索する場合があります。そこで役立つのがベクトル検索です。

Firestore のベクトル検索を使用すると、次のことができます。

  • エンベディングの生成: テキストの説明、将来的には画像や音声を、Vertex AI で利用可能なモデルやカスタムモデルを使用して、セマンティックな意味をキャプチャする数値ベクトル表現(エンベディング)に変換します。
  • エンベディングを保存する: これらのエンベディングを Firestore ドキュメントに直接保存します。
  • 類似検索を実行する: データベースに対してクエリを実行し、指定されたクエリベクトルと意味的に類似するドキュメントを見つけて、コンテキスト マッチングを可能にします。

Gemini 2.0 Flash の統合(試験運用版)

Gemini 2.0 Flash は、Google の最先端のマルチモーダル AI モデルです。まだ試験運用中ですが、YouTube のヨガアプリを充実させる可能性を秘めています。

  • テキスト生成: Gemini 2.0 Flash を使用して、ヨガのポーズに関する詳細な説明(効果、修正、禁忌など)を生成します。
  • 画像生成(模倣): Gemini による直接的な画像生成はまだ一般公開されていませんが、Google の Imagen を使用してこれをシミュレートし、ポーズを視覚的に表す画像を生成しました。
  • 音声生成(模倣): 同様に、テキスト読み上げ(TTS)サービスを使用して、各ポーズの音声指示を作成し、ユーザーに練習を案内することもできます。

モデルの次の機能を使用するようにアプリを強化するための統合を提案することを検討しています。

  • Multimodal Live API: この新しい API を使用すると、ツールを使用してリアルタイムのビジョンと音声ストリーミング アプリケーションを作成できます。
  • 速度とパフォーマンス: Gemini 2.0 Flash では、Gemini 1.5 Flash と比較して最初のトークンまでの時間(TTFT)が大幅に短縮されています。
  • エージェント エクスペリエンスの改善: Gemini 2.0 では、マルチモーダル理解、コーディング、複雑な指示の実行、関数呼び出しが改善されています。これらの改善は相互に連携して、エージェント エクスペリエンスの向上をサポートします。

詳しくは、こちらのドキュメントの Gemini 1.5 フラッシュに関するページをご覧ください。

信頼性を高め、より多くのリソースを提供するために、Google 検索を統合してアプリから提供される情報をグラウンディングできます。つまり、次のようなメリットがあります。

  • コンテキスト検索: 管理ユーザーがポーズの詳細を入力すると、ポーズ名を使用して Google 検索を実行できます。
  • URL の抽出: 検索結果から、関連する URL(記事、動画、信頼できるヨガのウェブサイトなど)を抽出し、アプリ内に表示できます。

作成するアプリの概要

このラボでは、次の作業を行います。

  1. Firestore コレクションを作成し、Yoga ドキュメントを読み込む
  2. Firestore で CRUD アプリケーションを作成する方法を学習する
  3. Gemini 2.0 Flash でヨガのポーズ説明を生成する
  4. Firestore 統合による Firebase ベクトル検索を有効にする
  5. ヨガの説明からエンベディングを生成する
  6. ユーザーの検索テキストの類似度検索を行う

要件

  • ブラウザ(ChromeFirefox など)
  • 課金を有効にした Google Cloud プロジェクト

2. 始める前に

プロジェクトを作成する

  1. Google Cloud コンソールのプロジェクト選択ページで、Google Cloud プロジェクトを選択または作成します。
  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。
  3. Cloud Shell(Google Cloud で動作するコマンドライン環境)を使用します。この環境には bq がプリロードされています。Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします。

Cloud Shell を有効にするボタンの画像

  1. Cloud Shell に接続したら、次のコマンドを使用して、認証が完了していることと、プロジェクトがプロジェクト ID に設定されていることを確認します。
gcloud auth list
  1. Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
  1. プロジェクトが設定されていない場合は、次のコマンドを使用して設定します。
gcloud config set project <YOUR_PROJECT_ID>
  1. 必要な 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 \
                       storage.googleapis.com \ 
                       secretmanager.googleapis.com \ 
                       texttospeech.googleapis.com

gcloud コマンドの代わりに、コンソールで各プロダクトを検索するか、このリンクを使用します。

いずれかの API が不足している場合は、実装中にいつでも有効にできます。

gcloud コマンドとその使用方法については、ドキュメントをご覧ください。

3. データベースの設定

Firestore インスタンスの設定方法については、ドキュメントの手順をご覧ください。大まかな手順は次のとおりです。

1. Firestore ビューアに移動し、[データベース サービスの選択] 画面で、ネイティブ モードの Firestore を選択します。

  1. Firestore のロケーションを選択する
  2. [Create Database] をクリックします(初めて作成する場合は、データベースを「(default)」のままにします)。

Firestore プロジェクトを作成すると、Cloud API Manager で API も有効になります。

  1. 重要: データにアクセスできるように、セキュリティ ルールのテスト版(本番環境版ではない)を選択します。
  2. 設定が完了すると、下図のように、ネイティブ モードの Firestore データベース、コレクション、ドキュメントのビューが表示されます。

f7136d53253c59a.png

  1. この手順はまだ行いませんが、記録のために説明します。[コレクションを開始] をクリックして、新しいコレクションを作成できます。コレクション ID を「poses」に設定します。[保存] ボタンをクリックします。

a26eb470aa9bfda9.png

本番環境アプリケーション向けのおすすめの方法:

  1. データモデルを確定させ、さまざまな種類のドキュメントにアクセスできるユーザーを特定したら、Firebase インターフェースからセキュリティ ルールを作成、編集、モニタリングできます。セキュリティ ルールには、https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules からアクセスできます。
  2. アプリの動作が想定と異なる場合、セキュリティ ルールが原因であることが多いため、開発フェーズからプロジェクトをデプロイ / ロールアウトする前に、セキュリティ ルールを編集、モニタリング、テストしてください。

このデモでは、TEST モードで使用します。

4. Firestore REST API

  1. REST API は、次のような場合に役立ちます。完全なクライアント ライブラリを実行できないリソースが制約された環境から Firestore にアクセスする場合。データベース管理の自動化を行ったり、詳細なデータベース メタデータを取得したりする場合
  2. Firestore を使用する場合、ネイティブのクライアント ライブラリを使用するのが最も簡単な方法ですが、REST API を直接呼び出すと便利な場合もあります。
  3. このブログでは、ネイティブ クライアント ライブラリではなく、Firestore REST API の使用方法とデモについて説明します。
  4. 認証では、Firestore REST API は Firebase Authentication ID トークンまたは Google Identity OAuth 2.0 トークンのいずれかを受け取ります。認証と承認のトピックの詳細については、ドキュメントをご覧ください。
  5. すべての REST API エンドポイントは、ベース URL https://firestore.googleapis.com/v1/ の下にあります。

Spring Boot と Firestore API

Spring Boot フレームワークのこのソリューションは、Firestore API を使用して、ユーザーのインタラクティブな操作でヨガのポーズと呼吸の詳細を収集、変更するクライアント アプリケーションを示しています。

ヨガのポーズアプリの Firestore CRUD ソリューションの部分について詳しくは、ブログのリンクをご覧ください。

現在のソリューションに焦点を当て、外出先で CRUD 部分を学習するには、Cloud Shell ターミナルからこのブログに焦点を当てたソリューション全体を以下のリポジトリからクローンを作成し、コードベースのコピーを取得します。

git clone https://github.com/AbiramiSukumaran/firestore-poserecommender

注意:

  1. このリポジトリをクローンしたら、プロジェクト ID や API などにいくつか変更を加えるだけで、アプリケーションを稼働させることができます。以降のセクションでは、アプリケーションの各コンポーネントについて説明します。変更内容は次のとおりです。
  2. src/main/java/com/example/demo/GenerateImageSample.java ファイルで、「<<YOUR_PROJECT_ID>>" をプロジェクト ID に置き換えます。
  3. src/main/java/com/example/demo/GenerateEmbeddings.java ファイルで、「<<YOUR_PROJECT_ID>>" をプロジェクト ID に置き換えます。
  4. src/main/java/com/example/demo/PoseController.java で、<<YOUR_PROJECT_ID>>" とデータベース名 ,(この場合は "(default)",)のすべてのインスタンスを、構成の適切な値に置き換えます。
  5. src/main/java/com/example/demo/PoseController.java で、「[YOUR_API_KEY]」を Gemini 2.0 Flash の API キーに置き換えます。これは AI Studio から入手できます。
  6. ローカルでテストする場合は、Cloud Shell ターミナルのプロジェクト フォルダから次のコマンドを実行します。
mvn package

mvn spring-boot:run

現在、Cloud Shell ターミナルで [ウェブでプレビュー] オプションをクリックすると、実行中のアプリケーションを表示できます。現時点では、テストを実施してアプリケーションを試す準備ができていません。

  1. 省略可: Cloud Run にアプリをデプロイする場合は、Cloud Shell エディタから新しい Java Cloud Run アプリケーションをゼロからブートストラップし、repoの src ファイルとテンプレート ファイルを、新しいプロジェクトの対応するフォルダに追加する必要があります(現在の GitHub リポジトリ プロジェクトは、Cloud Run のデプロイ構成用にデフォルトで設定されていないため)。その場合は、既存のリポジトリのクローンを作成するのではなく、次の手順に沿って操作します。
  2. Cloud Shell エディタに移動し(ターミナルではなくエディタが開いていることを確認してください)、ステータスバーの左側にある Google Cloud プロジェクト名アイコン(下のスクリーンショットのブロックされた部分)をクリックします。

d3f0de417094237d.png

  1. 選択肢のリストから [New application] -> [Cloud Run Application] -> [Java: Cloud Run] を選択し、名前を「firestore-poserecommender」にします。

d5ef8b4ca8bf3f85.png

  1. これで、Java Cloud Run アプリケーションのフルスタック テンプレートが事前構成され、使用できる状態になります。
  2. 既存の Controller クラスを削除し、次のファイルをプロジェクト構造のそれぞれのフォルダにコピーします。

firestore-poserecommender/src/main/java/com/example/demo/

  1. FirestoreSampleApplication.java
  2. GenerateEmbeddings.java
  3. GenerateImageSample.java
  4. Pose.java
  5. PoseController.java
  6. ServletInitializer.java
             firestore-poserecommender/src/main/resources/static/
    
  7. Index.html

firestore-poserecommender/src/main/resources/templates/

  1. contextsearch.html
  2. createpose.html
  3. errmessage.html
  4. pose.html
  5. ryoq.html
  6. searchpose.html
  7. showmessage.html

firestore-poserecommender/

  1. Dockerfile
  2. 対応するファイルで変更を加えて、PROJECT ID と API KEY をそれぞれの値に置き換える必要があります。(上記のステップ 1 a、b、c、d)。

5. データの取り込み

アプリのデータは、https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json の data.json ファイルで入手できます。

事前定義されたデータから始める場合は、JSON をコピーして、"<<YOUR_PROJECT_ID>>" が含まれるすべての箇所を自分の値に置き換えます。

  • Firestore Studio に移動します。
  • 「poses」という名前のコレクションが作成されていることを確認します。
  • 上記のリポジトリ ファイルからドキュメントを手動で 1 つずつ追加する

または、Google が作成した事前定義済みセットからデータを一括インポートすることもできます。手順は次のとおりです。

  1. Cloud Shell ターミナルに移動し、アクティブな Google Cloud プロジェクトが設定されていること、および認可されていることを確認します。次の gsutil コマンドを使用して、プロジェクトにバケットを作成します。次のコマンドの <PROJECT_ID> 変数は、Google Cloud プロジェクト ID に置き換えます。

gsutil mb -l us gs://<PROJECT_ID>-yoga-poses-bucket

  1. バケットが作成されたので、Firebase データベースにインポートする前に、準備したデータベース エクスポートをこのバケットにコピーする必要があります。次のコマンドを使用します。

gsutil cp -r gs://demo-bq-gemini-public/yoga_poses gs://<PROJECT_ID>-yoga-poses-bucket

読み込むデータが用意できたので、作成した Firebase データベース(デフォルト)にデータを読み込む最終ステップに進みます。

  1. Firestore コンソールに移動し、左側のナビゲーション メニューから [インポート/エクスポート] をクリックします。

[インポート] を選択し、作成した Cloud Storage パスを選択して、ファイル「yoga_poses.overall_export_metadata」を選択できるまで移動します。

f5c1d16df7d5a64a.png

  1. [インポート] をクリックします。

インポートには数秒かかります。準備ができたら、https://console.cloud.google.com/firestore/databases にアクセスして、以下の手順で Firestore データベースとコレクションを検証します。デフォルトのデータベースと poses コレクションを選択します。

  1. 別の方法として、デプロイ後に [Create a New Pose] アクションを使用して、アプリケーションでレコードを手動で作成することもできます。

6. ベクトル検索

Firestore ベクトル検索拡張機能を有効にする

この拡張機能を使用して、新しいベクトル検索機能で Firestore ドキュメントを自動的に埋め込み、クエリを実行しましょう。Firebase Extensions Hub が表示されます。

ベクトル検索拡張機能をインストールするときに、コレクションとドキュメント フィールド名を指定します。このフィールドを含むドキュメントを追加または更新すると、この拡張機能がトリガーされ、ドキュメントのベクトル エンベディングが計算されます。このベクトル エンベディングは同じドキュメントに書き戻され、ドキュメントはベクトルストアでインデックスに登録され、クエリの対象になります。

手順は次のとおりです。

拡張機能をインストールする:

Firebase Extensions Marketplace で [Firebase コンソールでインストール] をクリックして、[Firestore を使用したベクター検索] 拡張機能をインストールします。

重要:

この拡張機能ページに初めて移動する場合は、Firebase コンソールに表示されている Google Cloud コンソールで作業しているプロジェクトを選択する必要があります。

715426b97c732649.png

プロジェクトが表示されない場合は、Firebase でプロジェクトを追加します(リストから既存の Google Cloud プロジェクトを選択します)。

拡張機能を設定する:

コレクション(「poses」)、エンベディングするテキストを含むフィールド(「posture」)、エンベディング ディメンションなどのその他のパラメータを指定します。

この手順で有効にする必要がある API がある場合は、構成ページで有効にできます。手順に沿って操作します。

API を有効にしてもしばらくページが応答しない場合は、更新すると有効になった API が表示されます。

5ba59b45710c567b.png

次のいずれかの手順で、任意の LLM を使用してエンベディングを生成できます。[Vertex AI] を選択します。

bb528a04ebb5f976.png

次の設定は、コレクションと埋め込むフィールドに関連しています。

LLM: Vertex AI

コレクションのパス: poses

デフォルトのクエリの上限: 3

距離測定: コサイン

入力フィールド名: posture

出力フィールド名: embedding

ステータス フィールド名: status

既存のドキュメントを埋め込む: はい

既存のエンベディングを更新する: はい

Cloud Functions のロケーション: us-central1

Enable Events(イベントを有効にする): オフ

fb8cdf1163fac7cb.png

すべての設定が完了したら、[拡張機能をインストール] ボタンをクリックします。所要時間は 3 ~ 5 分です。

エンベディングを生成:

[poses] コレクションにドキュメントを追加または更新すると、拡張機能は、事前トレーニング済みモデルまたは API エンドポイントを介して選択したモデルを使用してエンベディングを自動的に生成します。この例では、拡張機能の構成で Vertex AI を選択しています。

インデックスの作成

アプリケーションでエンベディングを使用するときに、エンベディング フィールドのインデックスの作成が義務付けられます。

Firestore は基本的なクエリのインデックスを自動的に作成しますが、インデックスのないクエリを実行して、Firestore にインデックス構文を生成させることができます。生成されたインデックスへのリンクは、アプリケーション側のエラー メッセージに表示されます。ベクトル インデックスを作成する手順は次のとおりです。

  1. Cloud Shell ターミナルに移動する
  2. 次のコマンドを実行します。
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

詳しくは、こちらをご覧ください。

ベクトル インデックスが作成されたら、ベクトル エンベディングを使用して最近傍検索を実行できます。

注意事項:

この時点で、ソースに変更を加える必要はありません。手順に沿って、アプリが何をしているかを理解してください。

新しく構築したアプリケーションがベクトル検索にどのようにアプローチするかを見てみましょう。エンベディングを保存したら、Firestore Java SDK の VectorQuery クラスを使用してベクトル検索を行い、最近傍の結果を取得できます。

CollectionReference coll = firestore.collection("poses");
    VectorQuery vectorQuery = coll.findNearest(
        "embedding",
        userSearchTextEmbedding, 
        /* limit */ 3,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance")
         .setDistanceThreshold(2.0)
          .build());
ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();
List<Pose> posesList = new ArrayList<Pose>();
// Get the ID of the closest document (assuming results are sorted by distance)
String closestDocumentId = vectorQuerySnapshot.getDocuments().get(0).getId();

このスニペットは、ユーザーが検索したテキストのエンベディングと Firestore 内のドキュメントのエンベディングを比較し、コンテキスト的に最も近いものを抽出します。

7. Gemini 2.0 Flash

Gemini 2.0 Flash の統合(説明の生成用)

新しく作成したアプリが、説明の生成のために Gemini 2.0 Flash の統合をどのように処理するかを見てみましょう。

管理者ユーザーまたはヨガ インストラクターが Gemini 2.0 Flash を使用してポーズの詳細を入力し、検索を実行して最も近い一致を表示したいとします。これにより、結果をサポートするマルチモーダル オブジェクトとともに、一致するポーズの詳細が抽出されます。

String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=[YOUR_API_KEY]";
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> contents = new ArrayList<>();
List<Map<String, Object>> tools = new ArrayList<>();
Map<String, Object> content = new HashMap<>();
List<Map<String, Object>> parts = new ArrayList<>();
Map<String, Object> part = new HashMap<>();
part.put("text", prompt);
parts.add(part);
content.put("parts", parts);
contents.add(content);
requestBody.put("contents", contents);
/**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, String.class);
System.out.println("Generated response: " + response);
String responseBody = response.getBody();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray candidates = jsonObject.getJSONArray("candidates");
JSONObject candidate = candidates.getJSONObject(0);
JSONObject contentResponse = candidate.getJSONObject("content");
JSONArray partsResponse = contentResponse.getJSONArray("parts");
JSONObject partResponse = partsResponse.getJSONObject(0);
String generatedText = partResponse.getString("text");
System.out.println("Generated Text: " + generatedText);

a. 画像と音声の生成の模倣

Gemini 2.0 Flash 試験運用版はマルチモーダルの結果を生成できますが、私はまだ早期アクセスに登録していないため、Imagen API と TTS API で画像出力と音声出力をそれぞれ模倣しました。Gemini 2.0 Flash への 1 回の API 呼び出しで、これらすべてを生成できるとしたら、どれほど便利でしょうか。

try (PredictionServiceClient predictionServiceClient =
          PredictionServiceClient.create(predictionServiceSettings)) {
  
        final EndpointName endpointName =
            EndpointName.ofProjectLocationPublisherModelName(
                projectId, location, "google", "imagen-3.0-generate-001");
  
        Map<String, Object> instancesMap = new HashMap<>();
        instancesMap.put("prompt", prompt);
        Value instances = mapToValue(instancesMap);
  
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("sampleCount", 1);
        paramsMap.put("aspectRatio", "1:1");
        paramsMap.put("safetyFilterLevel", "block_few");
        paramsMap.put("personGeneration", "allow_adult");
        Value parameters = mapToValue(paramsMap);
  
        PredictResponse predictResponse =
            predictionServiceClient.predict(
                endpointName, Collections.singletonList(instances), parameters);
  
        for (Value prediction : predictResponse.getPredictionsList()) {
          Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
          if (fieldsMap.containsKey("bytesBase64Encoded")) {
            bytesBase64Encoded = fieldsMap.get("bytesBase64Encoded").getStringValue();
       }
      }
      return bytesBase64Encoded;
    }
 try {
            // Create a Text-to-Speech client
            try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
                // Set the text input to be synthesized
                SynthesisInput input = SynthesisInput.newBuilder().setText(postureString).build();

                // Build the voice request, select the language code ("en-US") and the ssml
                // voice gender
                // ("neutral")
                VoiceSelectionParams voice =
                        VoiceSelectionParams.newBuilder()
                                .setLanguageCode("en-US")
                                .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                                .build();

                // Select the type of audio file you want returned
                AudioConfig audioConfig =
                        AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

                // Perform the text-to-speech request on the text input with the selected voice
                // parameters and audio file type
                SynthesizeSpeechResponse response =
                        textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

                // Get the audio contents from the response
                ByteString audioContents = response.getAudioContent();

                // Convert to Base64 string
                String base64Audio = Base64.getEncoder().encodeToString(audioContents.toByteArray());

                // Add the Base64 encoded audio to the Pose object
               return base64Audio;
            }

        } catch (Exception e) {
            e.printStackTrace(); // Handle exceptions appropriately. For a real app, log and provide user feedback.
            return "Error in Audio Generation";
        }
}

b. Google 検索によるグラウンディング:

ステップ 6 の Gemini 呼び出しコードを確認すると、LLM レスポンスの Google 検索グラウンディングを有効にする次のコード スニペットがあります。

 /**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

これは、次のことを確実にするためです。

  • モデルを実際の検索結果に適用する
  • 検索で参照された関連 URL を抽出する

8. アプリケーションを実行する

シンプルな Thymeleaf ウェブ インターフェースを備えた新しく構築した Java Spring Boot アプリケーションのすべての機能を見てみましょう。

  1. Firestore の CRUD オペレーション(作成、読み取り、更新、削除)
  2. キーワード検索
  3. 生成 AI ベースのコンテキスト作成
  4. コンテキスト検索(ベクトル検索)
  5. 検索に関連するマルチモーダル出力
  6. 独自のクエリを実行する(structuredQuery 形式のクエリ)

例: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

ここまで説明した機能はすべて、リポジトリから作成したアプリケーションの一部です。https://github.com/AbiramiSukumaran/firestore-poserecommender

ビルド、実行、デプロイするには、Cloud Shell ターミナルから次のコマンドを実行します。

mvn package

mvn spring-boot:run

結果が表示され、アプリの機能を試すことができます。出力のデモについては、以下の動画をご覧ください。

Firestore、ベクトル検索、Gemini 2.0 Flash を使用したポーズ レコメンダー

省略可能な手順:

Cloud Run にデプロイするには(Dockerfile を使用して新しいアプリケーションをブートストラップし、必要に応じてファイルをコピーしたと仮定します)、プロジェクト ディレクトリ内の Cloud Shell ターミナルから次のコマンドを実行します。

gcloud run deploy --source .

アプリケーション名、リージョン コード(us-central1 のコードを選択)を指定し、プロンプトが表示されたら未認証の呼び出し「Y」を選択します。デプロイが正常に完了すると、ターミナルにアプリケーション エンドポイントが表示されます。

9. クリーンアップ

この投稿で使用したリソースについて、Google Cloud アカウントに課金されないようにするには、次の操作を行います。

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。
  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

10.完了

これで、Firestore を使用して、堅牢でインテリジェントなヨガのポーズ管理アプリケーションを作成できました。Firestore、ベクトル検索拡張機能、Gemini 2.0 Flash の機能を組み合わせることで、CRUD オペレーションの実装、キーワードベースの検索、コンテキスト ベクトル検索、マルチメディア コンテンツの生成を行う、魅力的で有益なヨガアプリを作成しました。

このアプローチはヨガアプリに限定されません。Gemini などの AI モデルが進化を続けるにつれ、没入感とパーソナライズをさらに高めたユーザー エクスペリエンスを実現できる可能性はますます高まっています。Google Cloud と Firebase の最新の開発情報とドキュメントを常に確認し、これらのテクノロジーの可能性を最大限に引き出してください。

このアプリを拡張する場合は、Gemini 2.0 Flash で次の 2 つのことを試します。

  1. ユースケースにリアルタイムのビジョンと音声ストリーミングを作成して、Multimodal Live API を使用します。
  2. 思考モードを有効にして、リアルタイム データとのやり取りに対する回答の背後にある思考を生成することで、よりリアルなエクスペリエンスを実現します。

ぜひお試しいただき、プル リクエストをお送りください :>D