Agent Search(旧Vertex AI Search)をAPI経由で使用する方法

Agent Search(旧Vertex AI Search)は、Googleが提供するAI検索エンジン構築サービスで、高度な自然言語処理や生成AI技術を活用した検索システムを簡単に構築できます。

Agent SearchをWebサイトに組み込む際にはウィジェット方式とAPI方式の2つの方式があります。ウィジェット方式は実装は極めて簡単な一方で、カラーや配置以外は変更できないというデザイン上の大きな制約があります。一方でAPI方式はデザインを自由に変えることが出来ますが、APIの呼び出しと受け取った結果の表示を自前で実装する必要があります。

この記事ではAgent Searchの結果をAPIを使って取得する方法を解説します。

目次

Google CloudでAgent Searchのアプリを作成する

まずは、Google Cloud上からAgent Searchのアプリケーションを作成する必要があります。アプリの作り方についてはこちらの記事で解説しているので、今回は割愛させていただきます。

アプリを作成したら、プレビューを実行して結果が返ってくることを確認しておきましょう。

REST APIを実行してみる

次に、REST APIを使用して検索結果やAIによる回答を取得してみます。

Google Cloud上で先ほど作成したアプリを選択して、左側のメニューから「統合」を選び「API」タブを開くと、REST APIを使用するためのコマンドが案内されています。なお、このコマンドを実行するには、Google Cloud CLIをインストールしたうえで、「gcloud auth login」コマンドでGoogle Cloudにログインしておく必要があります。

案内されている手順に沿って検索と回答の生成を実行してみます。

以下のコマンドは一部を伏字に変えています。お手元で実行される際はGoogle Cloud上に表示されるコマンドをご使用ください。

まずは検索です。以下のコマンドをターミナルから実行します。

curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
"https://discoveryengine.googleapis.com/v1alpha/projects/xxxxxxx/locations/global/collections/default_collection/engines/xxxxxxx/servingConfigs/default_search:search" \
  -d '{
    "query": "多摩川でおすすめのスポットは?",
    "pageSize": 10,
    "queryExpansionSpec": {
      "condition": "AUTO"
    },
    "spellCorrectionSpec": {
      "mode": "AUTO"
    },
    "languageCode": "ja",
    "contentSearchSpec": {
      "summarySpec": {
        "summaryResultCount": 1
      }
    },
    "userInfo": {
      "timeZone": "Asia/Tokyo"
    },
    "session": "projects/xxxxxxx/locations/global/collections/default_collection/engines/xxxxxxx/sessions/-"
  }'

レスポンスは以下になります(一部抜粋)。resultsというフィールドに、質問に対する検索結果のランキングが配列で格納されています。タイトルやHTML、ページの抜粋が取得できます。

{
  "results": [
    {
      "document": {
        "derivedStructData": {
          "extractive_answers": [
            {
              "content": "サイクリングコース・<b>スポット</b>一覧 | <b>多摩川</b>...(以下略)"
            }
          ],
          "title": "サイクリングコース・スポット一覧 | 多摩川レンタサイクル | RIDEAWAY",
          "link": "https://www.rideaway.bike/course-spot",
        }
      },
    },
    {
      "document": {
        "derivedStructData": {
          "extractive_answers": [
            {
              "content": "\u003cb\u003e多摩川\u003c/b\u003e沿いの\u003cb\u003eおすすめ...(以下略)"
            }
          ],
          "title": "多摩川沿いのおすすめピクニックスポット - 自然と健康とサイクリングのブログ",
          "link": "https://fun2ride.rideaway.bike/tamagawa-picnic/",
        }
      },
    },
    // ,{ ... }
  ],
  "sessionInfo": {
    "name": "projects/xxxxxxxx/locations/global/collections/default_collection/engines/xxxxxxxx/sessions/xxxxxxxx",
    "queryId": "projects/xxxxxxxx/locations/global/questions/xxxxxxxx"
  },
}

次にAIによって生成された回答を取得します。今のレスポンスからセッション名とクエリIDをコピーして、以下のコマンドを実行します。

セッション名やクエリIDは指定しなくても実行できますが、セッション名を指定することで、そのセッション内の会話の文脈を記憶したまま回答を生成することができます。

curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://discoveryengine.googleapis.com/v1alpha/projects/xxxxxxxx/locations/global/collections/default_collection/engines/xxxxxxxx/servingConfigs/default_search:answer" \
-d '{
  "query":{
    "text":"多摩川でおすすめのスポットは?",
    "queryId":"projects/xxxxxxxx/locations/global/questions/xxxxxxxx"
  },
  "session":"projects/xxxxxxxx/locations/global/collections/default_collection/engines/xxxxxxxx/sessions/xxxxxxxx",
  "relatedQuestionsSpec":{
    "enable":true
  },
  "answerGenerationSpec":{
    "ignoreAdversarialQuery":true,
    "ignoreNonAnswerSeekingQuery":false,
    "ignoreLowRelevantContent":true,
    "multimodalSpec":{},
    "includeCitations":true,
    "modelSpec":{
    "modelVersion":"stable"
    }
  }
}'

回答はこのようになります(一部抜粋)。生成された回答(answerText)と引用箇所(citations)、引用箇所の参照元(references)や関連する質問(relatedQuestions)などのフィールドが取得できます。

{
  "answer": {
    "answerText": "多摩川でおすすめのスポットは以下の通りです。\n\n**休憩スポット**\n*   **多摩川台公園** 中野島から下流方面に約13kmの位置にあり、古墳のある公園として有名です。古墳の周りの小道は森林で覆われているため日陰が多く、四季の野草園や水生植物園もあり、涼しさを感じられる休憩スポットとしておすすめです。サイクリングの休憩スポットとしても紹介されています...(以下略)",
    "citations": [], // 中身は省略
    "references": [], // 中身は省略
    "relatedQuestions": ["サイクリング以外で楽しめるスポットは?", "家族向けのおすすめスポットはありますか?",// 以下略],
}		

SDKを使用してAPIを実行する

Agent SearchにはREST APIを使うよりも実装が簡単なSDKが用意されています。SDKを使ってAgent Searchの結果を取得する手順を紹介します。

SDKはJavaやPHP、Pythonなどいくつかの言語で提供されていますが、ここではNode.jsのSDKを使用します。

API用の認証情報を用意する

まずは、Agent SearchのAPIを実行するのに必要な認証情報を作成する必要があります。認証方法はいくつかありますが、この記事ではサービスアカウントキーを使った認証方法で進めます。

サービスアカウントキーが流出すると第三者の不正利用による高額請求のリスクがあります。サービスアカウントキーの取り扱いには十分にご注意ください。
この記事では再現性を重視してサービスアカウントキーによる認証方法を使用していますが、実運用では、環境に合わせてキーレスな方式での認証を推奨します。

Google Cloudの「サービス アカウント」メニューから、サービスアカウントを作成します。Agent Searchを実行するには「ディスカバリー エンジン ユーザー」の権限が必要です。

サービスアカウントを作成したら、該当のサービスアカウントで鍵を作成します。「キーのタイプ」はJSONを指定します。作成が完了するとJSONファイルがダウンロードされます。

Node.jsのプロジェクトでSDKをインストールする

次に、プロジェクトを用意していきます。Node.jsのプロジェクトを作成し、SDKをインストールします。

npm install @google-cloud/discoveryengine

Node.jsのSDK経由で検索結果を取得する

まずは、検索結果の取得から実行してみます。検索結果の取得にはSearchServiceClientクラスのsearchメソッドを使用します。

以下の内容でindex.jsを作成します。<project number>、<engine>にはお手元のアプリの実際の値を入れてください。細かいオプションは先ほどのREST APIを使用した場合に合わせてあります。

プロジェクト番号、エンジンIDは、アプリをGoogle Cloudで開いた時のURLから取得可能です。

import "dotenv/config";
import { v1 } from "@google-cloud/discoveryengine";

const client = new v1.SearchServiceClient();

const search = async (projectNumber, engine, query) => {
  const servingConfig = client.projectLocationCollectionEngineServingConfigPath(
    projectNumber,
    "global",
    "default_collection",
    engine,
    "default_search",
  );

  const [, , response] = await client.search(
    {
      servingConfig: servingConfig,
      query: query,
      pageSize: 10,
      languageCode: "ja",
      queryExpansionSpec: {
        condition: "AUTO",
      },
      spellCorrectionSpec: {
        mode: "AUTO",
      },
      contentSearchSpec: {
        extractiveContentSpec: {
          maxExtractiveAnswerCount: 1,
        },
      },
      userInfo: {
        timeZone: "Asia/Tokyo",
      },
      session: `projects/${projectNumber}/locations/global/collections/default_collection/engines/${engine}/sessions/-`,
    },
    { autoPaginate: false },
  );
  return response;
};

const response = await search(
  <project number>,
  <engine>,
  "多摩川でおすすめのスポットは?",
);
console.log(JSON.stringify(response, null, 2));

SDKを利用するには、先ほど取得したサービスアカウントキー(JSONファイル)のパスがGOOGLE_APPLICATION_CREDENTIALSという環境変数に登録してある必要があります。上記のコード例では、.envを使って環境変数を設定しています。

またsearchメソッドの戻り値は配列の形を取っていますが、後の工程でセッション名やクエリIDを使用するため、ここでは配列の3番目の値を取得しています。

結果は以下になりました(抜粋)。SDKのバージョンで安定版の「v1」を指定しているため、REST APIの時と若干形式が異なりますが、ページのリンクやタイトル、ページの抜粋などが取得できました。

{
  "results": [
    {
      "document": {
        "derivedStructData": {
          "fields": {
            "link": {
              "stringValue": "https://www.rideaway.bike/course-spot",
            },
            "htmlTitle": {
              "stringValue": "サイクリングコース・スポット一覧 | 多摩川レンタサイクル | RIDEAWAY",
            },
            "extractive_answers": {
              "listValue": {
                "values": [
                  {
                    "structValue": {
                      "fields": {
                        "content": {
                          "stringValue": "サイクリングコース・<b>スポット</b>一覧 | <b>多摩川</b>レンタサイクル...(以下略)",
                        }
                      }
                    },
                  }
                ]
              },
            },
            "displayLink": {
              "stringValue": "www.rideaway.bike",
            }
          }
        },
      },
  // ,{ ... }
  ],
  "sessionInfo": {
    "name": "projects/xxxxxxxx/locations/global/collections/default_collection/engines/xxxxxxxx/sessions/xxxxxxxx",
    "queryId": "projects/xxxxxxxx/locations/global/questions/xxxxxxxx"
  },
}

Node.jsのSDK経由で回答を生成する

さらにAI生成による回答の取得も実行してみます。REST APIの時と同様、searchメソッドの戻り値からセッション名とクエリIDをコピーして使用します。回答の取得にはConversationalSearchServiceClientクラスのanswerQueryメソッドを使用します。

import "dotenv/config";
import { v1 } from "@google-cloud/discoveryengine";

const client = new v1.ConversationalSearchServiceClient();

const answer = async (projectNumber, engine, query, queryId, session) => {
  const servingConfig = client.projectLocationCollectionEngineServingConfigPath(
    projectNumber,
    "global",
    "default_collection",
    engine,
    "default_search",
  );

  const [response] = await client.answerQuery(
    {
      servingConfig: servingConfig,
      query: {
        text: query,
        queryId: queryId,
      },
      relatedQuestionsSpec: {
        enable: true,
      },
      answerGenerationSpec: {
        ignoreAdversarialQuery: true,
        ignoreNonAnswerSeekingQuery: false,
        ignoreLowRelevantContent: true,
        multimodalSpec: {},
        includeCitations: true,
        modelSpec: {
          modelVersion: "stable",
        },
      },
      session: session,
    },
    { autoPaginate: false },
  );
  return response;
};

const response = await answer(
  <project number>,
  <engine>,
  "多摩川でおすすめのスポットは?",
  <query id>,
  <session>,
);

console.log(JSON.stringify(response, null, 2));

以下が回答の抜粋になります。REST APIの時と同様の回答が得られました。

{
  "answer": {
    "answerText": "多摩川でおすすめのスポットは以下の通りです。\n\n**休憩スポット**\n*   **多摩川台公園** 中野島から下流方面に約13kmの位置にあり、古墳のある公園として有名です。古墳の周りの小道は森林で覆われているため日陰が多く、四季の野草園や水生植物園もあり、涼しさを感じられる休憩スポットとしておすすめです。サイクリングの休憩スポットとしても紹介されています...(以下略)",
    "citations": [], // 中身は省略
    "references": [], // 中身は省略
    "relatedQuestions": ["サイクリング以外で楽しめるスポットは?", "家族向けのおすすめスポットはありますか?",// 以下略],
}	

APIを実行する際のパラメータによって、検索や回答生成の際の動作を指定することができます。パラメータによる動作の指定については以下の公式ドキュメントに記載されているので、ご参照ください。

検索結果を取得する  |  Agent Search  |  Google Cloud Documentation
回答とフォローアップを取得する  |  Agent Search  |  Google Cloud Documentation

まとめ

この記事ではAPIを使ってAgent Search(旧Vertex AI Search)の検索結果やAIによる回答を取得する手順を説明しました。

ウィジェット方式は手軽に導入できる反面、デザインに大きな制約があります。自社のWebサイトのブランドカラーに合わせたUIや、ユーザー体験にこだわった独自のレイアウトを構築したい場合には、今回ご紹介したAPI方式が強力な選択肢となるでしょう。

Agent Searchを活用したAIサイト内検索を手軽に導入「SiteAsk(サイトアスク)」

Agent Searchを活用したAIサイト内検索を手軽かつ安全に導入できるサービスが、弊社が提供する「SiteAsk(サイトアスク)」です。

  • Agent Searchを採用、回答データの作成や保守が不要

Agent SearchがWebサイトのデータから自動的にRAGを構築するため、面倒なデータ処理は不要です。Webサイトの更新と共にデータは更新されるので、運用中のデータ保守も不要です。

  • 強力なハルシネーション防止機能

Agent Searchの安全構造に加え、SiteAsk独自の「3層AIガードレール」を搭載。悪意のある質問による不適切な回答やブランドを毀損する回答をブロックします。

  • システム改修不要で導入可能

JavaScriptを読み込むコードを追加するだけで導入できます。Googleタグマネージャー(GTM)を利用した導入も可能なため、既存のシステムやサイトのソースコードを改修する必要がありません。

Agent Searchを活用したAIサイト内検索を手軽にWebサイトに導入したい方は、ぜひSiteAskの導入をご検討ください。

よかったらシェアしてね!
  • URLをコピーしました!
目次