ADK、AlloyDB、Gemini を使用して、Java で強力なステートフル E2E AI エージェント アプリを構築する

ADK、AlloyDB、Gemini を使用して、Java で強力なステートフル E2E AI エージェント アプリを構築する

この Codelab について

subject最終更新: 5月 28, 2025
account_circle作成者: Author: Abirami Sukumaran

1. 概要

さまざまな業界において、コンテキスト検索はアプリケーションの中核をなす重要な機能です。検索拡張生成は、生成 AI を活用した検索メカニズムによって、この重要な技術革新の重要な推進力となってきました。生成モデルは、広範なコンテキスト ウィンドウと優れた出力品質を備え、AI を変革しています。RAG は、AI アプリケーションとエージェントにコンテキストを挿入するための体系的な方法を提供し、さまざまなメディアの構造化データや情報に基づいて AI アプリケーションとエージェントを構築します。このコンテキスト データは、真実の明確さと出力の精度にとって重要ですが、結果の精度はどの程度でしょうか。ビジネスは、こうしたコンテキスト マッチと関連性の精度に大きく依存していますか?このプロジェクトは、そんなあなたにぴったりです。

生成モデルの力を活用して、このようなコンテキストに重要な情報に基づいて、真実に基づいて自律的に意思決定できるインタラクティブ エージェントを構築できるとしたらどうでしょうか。これが、今日構築するものです。AlloyDB の高度な RAG を活用したエージェント開発キットを使用して、特許分析アプリケーションのエンドツーエンドの AI エージェント アプリを構築します。

特許分析エージェントは、検索テキストにコンテキスト的に関連する特許を見つける際にユーザーをサポートします。また、ユーザーからのリクエストに応じて、選択した特許について明確で簡潔な説明と、必要に応じて追加の詳細情報を提供します。では、その方法を見てみましょう。それでは詳しく見ていきましょう。

目標

目標はシンプルです。ユーザーがテキストの説明に基づいて特許を検索し、検索結果から特定の特許の詳細な説明を取得できるようにします。このすべてを、Java ADK、AlloyDB、ベクトル検索(高度なインデックスを使用)、Gemini で構築された AI エージェントを使用して、Cloud Run にサーバーレスでデプロイされたアプリケーション全体で実現します。

作成するアプリの概要

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

  1. AlloyDB インスタンスを作成して、特許公開データセットのデータを読み込む
  2. ScaNN と再現率評価機能を使用して AlloyDB に高度なベクトル検索を実装する
  3. Java ADK を使用してエージェントを作成する
  4. Java サーバーレス Cloud Functions でデータベース サーバーサイド ロジックを実装する
  5. Cloud Run でエージェントをデプロイしてテストする

次の図は、実装に関連するデータフローと手順を示しています。

c22563ace65a6930.png

High level diagram representing the flow of the Patent Search Agent with AlloyDB & ADK

要件

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

2. 始める前に

プロジェクトを作成する

  1. Google Cloud コンソールのプロジェクト選択ページで、Google Cloud プロジェクトを選択または作成します。
  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。
  3. Google Cloud 上で動作するコマンドライン環境の Cloud Shell を使用します。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 を有効にします。Cloud Shell ターミナルで gcloud コマンドを使用できます。
gcloud services enable alloydb.googleapis.com compute.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com run.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com aiplatform.googleapis.com

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

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

3. データベースの設定

このラボでは、特許データのデータベースとして AlloyDB を使用します。クラスタを使用して、データベースやログなどのすべてのリソースを保持します。各クラスタには、データへのアクセス ポイントを提供するプライマリ インスタンスがあります。テーブルには実際のデータが保持されます。

特許データセットを読み込む AlloyDB クラスタ、インスタンス、テーブルを作成しましょう。

クラスタとインスタンスを作成する

  1. Cloud コンソールの AlloyDB ページに移動します。Cloud コンソールのほとんどのページは、コンソールの検索バーを使用して簡単に見つけることができます。
  2. そのページで [クラスタを作成] を選択します。

f76ff480c8c889aa.png

  1. 次のような画面が表示されます。次の値を使用してクラスタとインスタンスを作成します(リポジトリからアプリケーション コードをクローンする場合は、値が一致していることを確認してください)。
  • クラスタ ID: "vector-cluster"
  • password: "alloydb"
  • PostgreSQL 15 / 最新バージョンを推奨
  • Region: "us-central1"
  • ネットワーキング: 「default

538dba58908162fb.png

  1. デフォルトのネットワークを選択すると、次のような画面が表示されます。

[接続の設定] を選択します。
7939bbb6802a91bf.png

  1. [自動的に割り振られた IP 範囲を使用する] を選択し、[続行] をクリックします。情報を確認したら、[CREATE CONNECTION] を選択します。768ff5210e79676f.png
  2. ネットワークが設定されたら、クラスタの作成を続行できます。[CREATE CLUSTER] をクリックして、クラスタの設定を完了します。

e06623e55195e16e.png

インスタンス ID(クラスタまたはインスタンスの構成時に確認できます)を

vector-instance。変更できない場合は、今後のすべての参照でインスタンス ID を使用してください。

クラスタの作成には 10 分ほどかかります。正常に完了すると、作成したクラスタの概要を示す画面が表示されます。

4. データの取り込み

次は、店舗に関するデータを含むテーブルを追加します。AlloyDB に移動し、プライマリ クラスタと AlloyDB Studio を選択します。

847e35f1bf8a8bd8.png

インスタンスの作成が完了するまで待つ必要があります。完了したら、クラスタの作成時に作成した認証情報を使用して AlloyDB にログインします。PostgreSQL の認証には、次のデータを使用します。

  • ユーザー名: 「postgres
  • データベース: 「postgres
  • パスワード: 「alloydb

AlloyDB Studio で認証が正常に完了すると、エディタに SQL コマンドが入力されます。最後のウィンドウの右側にあるプラス記号を使用して、複数のエディタ ウィンドウを追加できます。

91a86d9469d499c4.png

必要に応じて、実行、フォーマット、クリアのオプションを使用して、エディタ ウィンドウに AlloyDB のコマンドを入力します。

拡張機能を有効にする

このアプリの作成では、拡張機能 pgvectorgoogle_ml_integration を使用します。pgvector 拡張機能を使用すると、ベクトル エンベディングを保存して検索できます。google_ml_integration 拡張機能は、Vertex AI 予測エンドポイントにアクセスして SQL で予測を取得するために使用する関数を提供します。次の DDL を実行して、これらの拡張機能を有効にします。

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

データベースで有効になっている拡張機能を確認するには、次の SQL コマンドを実行します。

select extname, extversion from pg_extension;

テーブルを作成する

AlloyDB Studio で次の DDL ステートメントを使用してテーブルを作成できます。

CREATE TABLE patents_data ( id VARCHAR(25), type VARCHAR(25), number VARCHAR(20), country VARCHAR(2), date VARCHAR(20), abstract VARCHAR(300000), title VARCHAR(100000), kind VARCHAR(5), num_claims BIGINT, filename VARCHAR(100), withdrawn BIGINT, abstract_embeddings vector(768)) ;

abstract_embeddings 列には、テキストのベクトル値を保存できます。

権限を付与

次のステートメントを実行して、「embedding」関数に対する実行権限を付与します。

GRANT EXECUTE ON FUNCTION embedding TO postgres;

AlloyDB サービス アカウントに Vertex AI ユーザーロールを付与する

Google Cloud IAM コンソールで、AlloyDB サービス アカウント(service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com の形式)に「Vertex AI ユーザー」ロールへのアクセス権を付与します。PROJECT_NUMBER にはプロジェクト番号を指定します。

または、Cloud Shell ターミナルから次のコマンドを実行します。

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

特許データをデータベースに読み込む

データセットとして、BigQuery の Google Patents Public Datasets を使用します。AlloyDB Studio を使用してクエリを実行します。データは、この insert_scripts.sql ファイルにソースされます。このファイルを実行して、特許データを読み込みます。

  1. Google Cloud コンソールで、AlloyDB ページを開きます。
  2. 新しく作成したクラスタを選択し、インスタンスをクリックします。
  3. AlloyDB ナビゲーション メニューで [AlloyDB Studio] をクリックします。自分の認証情報でログインします。
  4. 右側の [新しいタブ] アイコンをクリックして、新しいタブを開きます。
  5. 上記の insert_scripts.sql スクリプトから insert クエリ ステートメントをエディタにコピーします。このユースケースのクイックデモでは、10 ~ 50 個の挿入ステートメントをコピーします。
  6. [実行] をクリックします。クエリの結果が [結果] テーブルに表示されます。

5. 特許データのエンベディングを作成する

まず、次のサンプルクエリを実行して、エンベディング関数をテストします。

SELECT embedding('text-embedding-005', 'AlloyDB is a managed, cloud-hosted SQL database service.');

これにより、クエリのサンプルテキストのエンベディング ベクトルが返されます。これは浮動小数点数の配列のように見えます。次のように表示されます。

25a1d7ef0e49e91e.png

abstract_embeddings ベクトル フィールドを更新する

次の DML を実行して、テーブル内の特許要約を対応するエンベディングで更新します。

UPDATE patents_data set abstract_embeddings = embedding( 'text-embedding-005', abstract);

6. ベクトル検索を実行する

テーブル、データ、エンベディングがすべて準備できたので、ユーザーの検索テキストに対してリアルタイム ベクトル検索を実行します。これをテストするには、次のクエリを実行します。

SELECT id || ' - ' || title as title FROM patents_data ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;

このクエリでは、

  1. ユーザーが検索したテキストは「Sentiment Analysis」です。
  2. モデル text-embedding-005 を使用して、embedding() メソッドでエンベディングに変換しています。
  3. "<=>" は、COSINE SIMILARITY 距離メソッドの使用を表します。
  4. エンベディング方法の結果をベクトル型に変換し、データベースに保存されているベクトルと互換性を持たせています。
  5. LIMIT 10 は、検索テキストに最も近い 10 件の一致を選択することを表します。

AlloyDB は、ベクトル検索 RAG を次のレベルに引き上げます。

新機能は多数あります。デベロッパー向けの機能には次の 2 つがあります。

  1. インライン フィルタリング
  2. 再現率評価ツール

インライン フィルタリング

以前は、デベロッパーはベクトル検索クエリを実行し、フィルタリングと再現率を処理する必要がありました。AlloyDB クエリ オプティマイザーは、フィルタ付きクエリの実行方法を最適化します。インライン フィルタリングは新しいクエリ最適化手法であり、これにより AlloyDB クエリ オプティマイザーは、ベクトル インデックスとメタデータ列のインデックスの両方を活用して、メタデータのフィルタ条件とベクトル検索の両方を同時に評価できます。これにより、リコール パフォーマンスが向上し、デベロッパーは AlloyDB の機能をすぐに利用できるようになります。

インライン フィルタリングは、選択性が中程度の場合に最適です。AlloyDB はベクトル インデックスを検索する際に、メタデータのフィルタ条件(通常は WHERE 句で処理されるクエリの関数フィルタ)に一致するベクトルの距離のみを計算します。これにより、ポストフィルタやプレフィルタの利点を補完し、クエリのパフォーマンスを大幅に向上させます。

  1. pgvector 拡張機能をインストールまたは更新する
CREATE EXTENSION IF NOT EXISTS vector WITH VERSION '0.8.0.google-3';

pgvector 拡張機能がすでにインストールされている場合は、ベクトル拡張機能をバージョン 0.8.0.google-3 以降にアップグレードして、再現率評価ツールを利用できるようにします。

ALTER EXTENSION vector UPDATE TO '0.8.0.google-3';

この手順は、ベクトル拡張機能が 0.8.0.google-3 未満の場合にのみ実行する必要があります。

重要な注意事項: 行数が 100 未満の場合は、行数が少ないため ScaNN インデックスは適用されないため、最初から ScaNN インデックスを作成する必要はありません。その場合は、次の手順をスキップしてください。

  1. ScaNN インデックスを作成するには、alloydb_scann 拡張機能をインストールします。
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
  1. まず、インデックスなしで、インライン フィルタを有効にせずにベクトル検索クエリを実行します。
SELECT id || ' - ' || title as title FROM patents_data 
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;

結果は次のようになります。

6989de0fc3f0f753.png

  1. Explain Analyze を実行します(インデックスとインライン フィルタなし)。

908dcf87c7f00ed4.png

実行時間は 2.4 ms

  1. num_claims フィールドに通常のインデックスを作成して、このフィールドでフィルタできるようにしましょう。
CREATE INDEX idx_patents_data_num_claims ON patents_data (num_claims);
  1. 特許検索アプリケーションの ScaNN インデックスを作成しましょう。AlloyDB Studio から次のコマンドを実行します。
CREATE INDEX patent_index ON patents_data 
USING scann (abstract_embeddings cosine)
WITH (num_leaves=32);

重要な注意事項: (num_leaves=32) は、1,000 行を超える合計データセットに適用されます。行数が 100 未満の場合は、インデックスは適用されないため、インデックスを作成する必要はありません。

  1. ScaNN インデックスでインライン フィルタリングを有効にします。
SET scann.enable_inline_filtering = on
  1. 次に、フィルタとベクトル検索を含む同じクエリを実行します。
SELECT id || ' - ' || title as title FROM patents_data 
WHERE num_claims >= 15
ORDER BY abstract_embeddings <=> embedding('text-embedding-005', 'Sentiment Analysis')::vector LIMIT 10;

aa54cba2b2ada2cb.png

ご覧のとおり、同じベクトル検索で実行時間が大幅に短縮されています。ベクトル検索にインライン フィルタリングを組み込んだ ScaNN インデックスによって、これが可能になりました。

次に、この ScaNN 対応ベクトル検索の再現率を評価しましょう。

再現率評価ツール

類似検索における再現率は、検索から取得された関連インスタンスの割合(真陽性のインスタンスの数)です。これは、検索品質の測定に使用される最も一般的な指標です。再現率低下の一因は、近似最近傍検索(aNN)と K 最近傍検索(kNN)の違いにあります。AlloyDB の ScaNN のようなベクトル インデックスは aNN アルゴリズムを実装しており、再現率のわずかなトレードオフと引き換えに、大規模データセットでのベクトル検索を高速化できます。AlloyDB では、個々のクエリのトレードオフをデータベース内で直接測定し、経時的な安定性を確認できるようになりました。この情報に応じてクエリやインデックスのパラメータを更新すれば、より良い検索結果とパフォーマンスを実現できます。

特定の構成のベクトル インデックスに対するベクトルクエリの再現率は、evaluate_query_recall 関数で確認できます。この関数を使用すると、目的のベクトルクエリの再現率を達成するようにパラメータをチューニングできます。再現率は検索品質に使用される指標で、クエリベクトルに客観的に最も近い結果が返された割合として定義されます。evaluate_query_recall 関数はデフォルトでオンになっています。

注意事項:

次の手順で HNSW インデックスで権限拒否エラーが発生した場合は、この再現率評価セクション全体をスキップしてください。この Codelab のドキュメント作成時点でリリースされたばかりであるため、この時点ではアクセス制限が関係している可能性があります。

  1. ScaNN インデックスと HNSW インデックスで、インデックス スキャンの有効化フラグを設定します。
SET scann.enable_indexscan = on
SET hnsw.enable_index_scan = on
  1. AlloyDB Studio で次のクエリを実行します。
SELECT
  *
FROM
  evaluate_query_recall($$
  SELECT
    id || ' - ' || title AS title,
    abstract
  FROM
    patents_data
    where num_claims >= 15
  ORDER BY
    abstract_embeddings <=> embedding('text-embedding-005',
      'sentiment analysis')::vector
  LIMIT 25 $$,
    '{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10}',
    ARRAY['scann']);

evaluate_query_recall 関数は、クエリをパラメータとして受け取り、その再現率を返します。関数の入力クエリとして、パフォーマンスの確認に使用したクエリを使用しています。インデックス メソッドとして SCaNN を追加しました。その他のパラメータ オプションについては、ドキュメントをご覧ください。

これまで使用してきたこのベクトル検索クエリの再現率は次のとおりです。

c98f38fbe6a0b6c5.png

リコール率は 70% ですね。この情報を使用して、インデックス パラメータ、メソッド、クエリ パラメータを変更し、このベクトル検索のレコード数を増やすことができます。

結果セット内の行数を 7 に変更しました(以前は 10)。すると、RECALL がわずかに改善され、86% になりました。

c12f7b92b8481ceb.png

つまり、ユーザーに表示する一致数をリアルタイムで変更し、ユーザーの検索コンテキストに応じて一致の関連性を高めることができます。

では、データベース ロジックをデプロイして、エージェントに移行しましょう。

7. サーバーレスでデータベース ロジックをウェブに移行する

このアプリをウェブに移行する準備はできていますか?手順は次のとおりです。

  1. Google Cloud コンソールの Cloud Run Functions に移動して、新しい Cloud Run 関数を作成するか、リンク https://console.cloud.google.com/functions/add を使用します。
  2. 環境として [Cloud Run 関数] を選択します。関数名に「patent-search」を指定し、リージョンとして「us-central1」を選択します。[認証] を [未認証の呼び出しを許可する] に設定し、[次へ] をクリックします。ランタイムとして Java 17 を選択し、ソースコードのインライン エディタを選択します。
  3. デフォルトでは、エントリ ポイントは「gcfv2.HelloHttpFunction」に設定されます。Cloud Run Functions の関数の HelloHttpFunction.java と pom.xml のプレースホルダ コードを、それぞれ「PatentSearch.java」と「pom.xml」のコードに置き換えます。クラスファイルの名前を PatentSearch.java に変更します。
  4. Java ファイルで、************* プレースホルダと AlloyDB 接続認証情報を自分の値に変更してください。AlloyDB の認証情報は、この Codelab の開始時に使用したものと同じです。異なる値を使用している場合は、Java ファイルで同じ値を変更してください。
  5. [デプロイ] をクリックします。

重要なステップ:

デプロイしたら、Cloud Functions が AlloyDB データベース インスタンスにアクセスできるように VPC コネクタを作成します。

デプロイの準備が整うと、Google Cloud Run Functions コンソールに関数が表示されます。新しく作成した関数(patent-search)を検索してクリックし、[新しいリビジョンの編集とデプロイ](Cloud Run Functions コンソールの上部にある編集アイコン(ペン))をクリックして、次のように変更します。

  1. [ネットワーキング] タブに移動します。

828cd861864d99ea.png

  1. [アウトバウンド トラフィック用の VPC に接続する] を選択し、[サーバーレス VPC アクセス コネクタを使用する] を選択します。
  2. [ネットワーク] プルダウンの設定で、[ネットワーク] プルダウンをクリックし、[新しい VPC コネクタを追加] オプションを選択します(デフォルトの VPC コネクタをまだ構成していない場合)。ポップアップ ダイアログに表示される手順に沿って操作します。

6559ccfd10e597f2.png

  1. VPC コネクタの名前を指定し、リージョンがインスタンスと同じであることを確認します。[ネットワーク] の値はデフォルトのままにして、[サブネット] を [カスタム IP 範囲] に設定し、IP 範囲を 10.8.0.0 または使用可能な類似の値に設定します。
  2. [スケーリング設定を表示] を開き、構成が次のように正確に設定されていることを確認します。

199b0ccd80215004.png

  1. [作成] をクリックすると、このコネクタが下り(外向き)設定に表示されます。
  2. 新しく作成したコネクタを選択します。
  3. すべてのトラフィックをこの VPC コネクタ経由でルーティングするように選択します。
  4. [次へ]、[デプロイ] の順にクリックします。
  5. 更新された Cloud Functions 関数がデプロイされると、生成されたエンドポイントが表示されます。コピーして、次のコマンドで置き換えます。
PROJECT_ID=$(gcloud config get-value project)

curl -X POST <<YOUR_ENDPOINT>> \
  -H 'Content-Type: application/json' \
  -d '{"search":"Sentiment Analysis"}'

これで、AlloyDB データでエンベディング モデルを使用して高度なコンテキスト シナリオ ベクトル検索を実行するのは、これほど簡単です。

8. Java ADK を使用してエージェントを構築する

まず、エディタで Java プロジェクトを作成しましょう。

  1. Cloud Shell ターミナルに移動します。

https://shell.cloud.google.com/?fromcloudshell=true&show=ide%2Cterminal

  1. プロンプトが表示されたら承認する
  2. Cloud Shell コンソールの上部にあるエディタ アイコンをクリックして、Cloud Shell エディタに切り替えます。

f913b886324e5196.png

  1. ランディング ページの Cloud Shell エディタ コンソールで、新しいフォルダを作成し、adk-agents という名前を付けます。

次のように、Cloud Shell のルート ディレクトリで [新しいフォルダを作成] をクリックします。

94c9804697614a94.png

名前を「adk-agents」にします。

37445dc1fe08f74c.png

  1. 次のフォルダ構造と、次の構造に一致するファイル名の空のファイルを作成します。
adk-agents/
 └—— pom.xml
 └—— src/
     └—— main/
         └—— java/
             └—— agents/
                 └—— App.java
  1. 別のタブで GitHub リポジトリを開き、App.java ファイルと pom.xml ファイルのソースコードをコピーします。
  2. 右上の [新しいタブで開く] アイコンを使用してエディタを新しいタブで開いた場合は、ページの下部にターミナルを開くことができます。エディタとターミナルの両方を同時に開いて、自由に操作できます。
  3. クローンを作成したら、Cloud Shell エディタ コンソールに戻ります。
  4. Cloud Run 関数はすでに作成されているため、リポジトリ フォルダから Cloud Run 関数ファイルをコピーする必要はありません。

ADK Java SDK のスタートガイド

手順は簡単です。主に、クローン作成ステップで次のことがカバーされていることを確認する必要があります。

  1. 依存関係を追加する:

google-adk と google-adk-dev(ウェブ UI 用)のアーティファクトを pom.xml に含めます。

<!-- The ADK core dependency -->
        <dependency>
            <groupId>com.google.adk</groupId>
            <artifactId>google-adk</artifactId>
            <version>0.1.0</version>
        </dependency>
        <!-- The ADK dev web UI to debug your agent -->
        <dependency>
            <groupId>com.google.adk</groupId>
            <artifactId>google-adk-dev</artifactId>
            <version>0.1.0</version>
        </dependency>

アプリケーションを実行するために必要な他の依存関係と構成があるため、ソース リポジトリの pom.xml を参照してください。

  1. プロジェクトを構成する:

pom.xml で Java バージョン(17 以降推奨)と Maven コンパイラ設定が正しく構成されていることを確認します。プロジェクトを次のような構造に設定できます。

adk-agents/
 └—— pom.xml
 └—— src/
     └—— main/
         └—— java/
             └—— agents/
                 └—— App.java
  1. エージェントとそのツールの定義(App.java):

ここで ADK Java SDK の真価を発揮します。エージェント、その機能(指示)、使用できるツールを定義します。

メイン エージェント クラスのコード スニペットの簡略版を以下に示します。プロジェクト全体については、こちらのプロジェクト リポジトリをご覧ください。

// App.java (Simplified Snippets)
package agents;

import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.BaseAgent;
import com.google.adk.agents.InvocationContext;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
// ... other imports

public class App {

    static FunctionTool searchTool = FunctionTool.create(App.class, "getPatents");
    static FunctionTool explainTool = FunctionTool.create(App.class, "explainPatent");

    public static BaseAgent ROOT_AGENT = initAgent();

    public static BaseAgent initAgent() {
        return LlmAgent.builder()
            .name("patent-search-agent")
            .description("Patent Search agent")
            .model("gemini-2.0-flash-001") // Specify your desired Gemini model
            .instruction(
                """
                You are a helpful patent search assistant capable of 2 things:
                // ... complete instructions ...
                """)
            .tools(searchTool, explainTool)
            .outputKey("patents") // Key to store tool output in session state
            .build();
    }

    // --- Tool: Get Patents ---
    public static Map<String, String> getPatents(
        @Schema(name="searchText",description = "The search text for which the user wants to find matching patents")
        String searchText) {
        try {
            String patentsJson = vectorSearch(searchText); // Calls our Cloud Run Function
            return Map.of("status", "success", "report", patentsJson);
        } catch (Exception e) {
            // Log error
            return Map.of("status", "error", "report", "Error fetching patents.");
        }
    }

    // --- Tool: Explain Patent (Leveraging InvocationContext) ---
    public static Map<String, String> explainPatent(
        @Schema(name="patentId",description = "The patent id for which the user wants to get more explanation for, from the database")
    String patentId,
    @Schema(name="ctx",description = "The list of patent abstracts from the database from which the user can pick the one to get more explanation for")
    InvocationContext ctx) { // Note the InvocationContext
        try {
            // Retrieve previous patent search results from session state
            String previousResults = (String) ctx.session().state().get("patents");
            if (previousResults != null && !previousResults.isEmpty()) {
// Logic to find the specific patent abstract from 'previousResults' by 'patentId'
                String[] patentEntries = previousResults.split("\n\n\n\n");
                for (String entry : patentEntries) {
                    if (entry.contains(patentId)) { // Simplified check
       // The agent will then use its instructions to summarize this 'report'
                        return Map.of("status", "success", "report", entry);
                    }
                }
            }
            return Map.of("status", "error", "report", "Patent ID not found in previous search.");
        } catch (Exception e) {
            // Log error
            return Map.of("status", "error", "report", "Error explaining patent.");
        }
    }

    public static void main(String[] args) throws Exception {
        InMemoryRunner runner = new InMemoryRunner(ROOT_AGENT);
        // ... (Session creation and main input loop - shown in your source)
    }
}

ハイライト表示された主要な ADK Java コード コンポーネント:

  1. LlmAgent.builder(): エージェントを構成するための Fluent API。
  2. .instruction(...): LLM のコア プロンプトとガイドライン(どのツールを使用するかなど)を提供します。
  3. FunctionTool.create(App.class, "methodName"): エージェントが呼び出せるツールとして Java メソッドを簡単に登録します。メソッド名の文字列は、実際の公開静的メソッドと一致している必要があります。
  4. @Schema(description = ...): ツール パラメータにアノテーションを付け、各ツールが想定する入力を LLM が理解できるようにします。この説明は、正確なツールの選択とパラメータの入力に不可欠です。
  5. InvocationContext ctx: ツールメソッドに自動的に渡され、セッション状態(ctx.session().state())やユーザー情報などにアクセスできます。
  6. .outputKey("patents"): ツールがデータを返すと、ADK はデータをこのキーのセッション状態に自動的に保存できます。これにより、explainPatent は getPatents の結果にアクセスできます。
  7. VECTOR_SEARCH_ENDPOINT: 特許検索のユースケースで、ユーザー向けのコンテキスト対応 Q&A のコア機能ロジックを保持する変数です。
  8. 次のアクション: 前のセクションの Java Cloud Run 関数ステップを実装したら、更新されたデプロイ済みエンドポイント値を設定する必要があります。
  9. searchTool: ユーザーの検索テキストにコンテキスト的に関連する特許を特許データベースから検索します。
  10. explainTool: 詳細を確認する特定の特許をユーザーに尋ねます。次に、特許の概要を要約し、取得した特許の詳細に基づいてユーザーからの追加の質問に回答します。

重要な注意事項: VECTOR_SEARCH_ENDPOINT 変数は、デプロイした CRF エンドポイントに置き換えてください。

InvocationContext をステートフル インタラクションに活用する

有用なエージェントを構築するための重要な機能の 1 つは、会話の複数のターンにわたる状態を管理することです。ADK の InvocationContext を使用すると、この処理を簡単に行えます。

App.java で、次のようにします。

  1. initAgent() が定義されている場合は、.outputKey("patents") を使用します。これは、ツール(getPatents など)がレポート フィールドでデータを返すときに、そのデータをセッション状態のキー「patents」に保存するように ADK に指示します。
  2. explainPatent ツールメソッドで、InvocationContext ctx を挿入します。
public static Map<String, String> explainPatent(
    @Schema(description = "...") String patentId, InvocationContext ctx) {
    String previousResults = (String) ctx.session().state().get("patents");
    // ... use previousResults ...
}

これにより、explainPatent ツールは、前のターンで getPatents ツールによって取得された特許リストにアクセスできるため、会話がステートフルで整合性のあるものになります。

9. ローカル CLI テスト

環境変数を定義する

次の 2 つの環境変数をエクスポートする必要があります。

  1. AI Studio から取得できる Gemini キー:

これを行うには、https://aistudio.google.com/apikey に移動し、このアプリケーションを実装しているアクティブな Google Cloud プロジェクトの API キーを取得して、キーをどこかに保存します。

ae2db169e6a94e4a.png

  1. キーを取得したら、Cloud Shell ターミナルを開き、次のコマンドを実行して、先ほど作成した adk-agents の新しいディレクトリに移動します。
cd adk-agents
  1. 今回は Vertex AI を使用しないことを指定する変数。
export GOOGLE_GENAI_USE_VERTEXAI=FALSE
export GOOGLE_API_KEY=AIzaSyDF...
  1. CLI で最初のエージェントを実行する

この最初のエージェントを起動するには、ターミナルで次の Maven コマンドを使用します。

mvn compile exec:java -DmainClass="agents.App"

エージェントからのインタラクティブなレスポンスがターミナルに表示されます。

10. Cloud Run へのデプロイ

ADK Java エージェントを Cloud Run にデプロイする方法は、他の Java アプリケーションのデプロイ方法と同様です。

  1. Dockerfile: Dockerfile を作成して Java アプリケーションをパッケージ化します。
  2. Docker イメージのビルドと push: Google Cloud Build と Artifact Registry を使用します。
  3. 上記の手順を実行し、Cloud Run にデプロイするには、次の 1 つのコマンドを使用します。
gcloud run deploy --source . --set-env-vars GOOGLE_API_KEY=<<Your_Gemini_Key>>

同様に、Java Cloud Run 関数(gcfv2.PatentSearch)をデプロイします。または、Cloud Run Functions コンソールから直接、データベース ロジック用の Java Cloud Run Functions の関数を作成してデプロイすることもできます。

11. ウェブ UI を使用したテスト

ADK には、エージェントのローカルテストとデバッグに便利なウェブ UI が付属しています。App.java をローカルで実行すると(例: mvn exec:java -Dexec.mainClass="agents.App"(構成されている場合)または main メソッドを実行するだけ)、通常 ADK はローカル ウェブサーバーを起動します。

ADK ウェブ UI では、次のことができます。

  1. エージェントにメッセージを送信します。
  2. イベント(ユーザー メッセージ、ツール呼び出し、ツールの応答、LLM の応答)を確認します。
  3. セッションの状態を検査します。
  4. ログとトレースを表示します。

これは、エージェントがリクエストを処理し、ツールを使用する方法を理解するために、開発中に非常に役立ちます。これは、pom.xml の mainClass が com.google.adk.web.AdkWebServer に設定され、エージェントがそれに登録されているか、これを公開するローカル テストランナーを実行していることを前提としています。

InMemoryRunner とコンソール入力用の Scanner を使用して App.java を実行すると、コア エージェント ロジックをテストできます。ウェブ UI は、より視覚的なデバッグ エクスペリエンスのための個別のコンポーネントです。ADK が HTTP 経由でエージェントを提供する場合によく使用されます。

ルート ディレクトリから次の Maven コマンドを使用して、SpringBoot ローカル サーバーを起動できます。

mvn compile exec:java -Dexec.args="--adk.agents.source-dir=src/main/java/ --logging.level.com.google.adk.dev=TRACE --logging.level.com.google.adk.demo.agents=TRACE"

多くの場合、このインターフェースには、上記のコマンドが出力した URL からアクセスできます。Cloud Run にデプロイされている場合は、Cloud Run にデプロイされたリンクからアクセスできます。

結果はインタラクティブなインターフェースで確認できます。

配備された特許エージェントについては、以下の動画をご覧ください。

AlloyDB インライン検索と再現率評価による品質管理された特許エージェントのデモ

ca7b0fc4fe571dd6.png

12. クリーンアップ

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

  1. Google Cloud コンソールで、https://console.cloud.google.com/cloud-resource-manager?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog に移動します。
  2. https://console.cloud.google.com/cloud-resource-manager?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog ページ。
  3. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  4. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

13. 完了

これで、ADK、https://cloud.google.com/alloydb/docs?utm_campaign=CDR_0x1d2a42f5_default_b419133749&utm_medium=external&utm_source=blog、Vertex AI、ベクトル検索の機能を組み合わせて、Java で特許分析エージェントを正常に構築しました。また、コンテキスト ベースの類似性検索を変革的で効率的で真に意味に基づくものにする大きな一歩を踏み出しました。

ぜひご登録ください

ADK ドキュメント: [公式 ADK Java ドキュメントへのリンク]

特許分析エージェントのソースコード: [(公開されている)GitHub リポジトリへのリンク]

Java サンプル エージェント: [adk-samples リポジトリへのリンク]

ADK コミュニティに参加する: https://www.reddit.com/r/agentdevelopmentkit/

エージェントの作成を楽しんでください。