8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NTTコムウェアAdvent Calendar 2023

Day 24

Vertex AI Searchと オセロアプリを連携してみた

Last updated at Posted at 2023-12-23

この記事はNTTコムウェア Advent Calendar 2023の24日目の記事です。

はじめに

みなさ~~~~ん!!!
Vertex AI Search、使ってますか!?

こんにちは。NTTコムウェア2年目の石川です。
みなさん、Vertex AI Search、使ってますか?

Vertex AI SearchとはGoogle Cloudが提供するマネージドサービスです。大規模言語モデル(LLM)に対し、情報を外部からインプットすることで、LLMが学習していない知識を回答させることができるアーキテクチャをRAG(Retrieval Augmented Model)と言いますが、Vertex AI Searchを使うとRAGを簡単に実現することができます。
以下にVertex AI Searchの簡単なイメージを示します。

vertex_ai_search概要2.png

通常、RAGを実現させるためには「embedding」と呼ばれる、自然言語をベクトル化する工程や、ベクトル化した文章とインプットした文章を比較し類似した文章を検索する「ベクトル検索」が必要です。Vertex AI Searchではこれらの要素技術が隠蔽されているので、簡単なRAG構築が可能になります。

私は最近業務でVertex AI Searchを少々触っており、今回は簡単なオセロのWebアプリケーションとVertex AI Searchを連携してみましたので、みなさんにVertex AI Searchの機能や使い方の一端をご紹介できればと思います。

オセロアプリとVertex AI Searchの連携

ではやっていきましょう。
まずはReactで簡単なオセロのWebアプリケーションを用意します。オセロアプリはこちらのGitHubを大変参考にさせていただきました。ありがとうございます。

現時点ではオセロアプリは以下のような画面になっています。2人のプレイヤーが交互に石を置いていくと、各色の数が右に表示される仕様です。リセットボタンを押すと最初の盤面に戻ります。
ocello1.png

次にVertex AI Searchのアプリケーションを作成します。使用するドキュメントはGCS(Google Cloud Storage)に保存しておき、アプリにインポートすることで使用可能になります。今回はWikipediaのオセロの記事をPDF化し、読み込ませてあります。

さて、ここからどうオセロアプリに連携させるかですが、2つ方法があります。

Widgetによるオセロアプリ連携

1つはWidgetを使う方法です。左のメニューから「統合」を選択し、さらに「WIDGET」タブをクリックします。認証タイプは「公開アクセス」を選択します。ドメインは、今回ローカルでしか実行しないのでlocalhostと入力して保存しておきます。
vertex_ai_search_widget1.png

次に、JavaScriptのコードスニペットが生成されるので、コピーしてオセロアプリのindex.htmlの一番下に貼り付けます。
vertex_ai_search_widget2.png

オセロアプリを実行してみると、以下のように画面の最下部に検索窓が表示されます。
vertex_ai_search_widget3.png

この検索窓をクリックし、適当に「オセロについて教えて」と入力してみると回答が返ってきました。事前にインプットしたWikipediaを確認すると、しっかりと回答がインプット文書から生成されていることがわかります。
vertex_ai_search_widge4.png

このように、最低限で良いのであれば、たったこれだけでアプリとVertex AI Searchを連携することができます。
ただ、これだけでは柔軟性に欠けるかと思います。そこで、もう一つの連携方法も試してみましょう。

APIを用いたオセロアプリ連携

もう一つの連携方法はAPIを叩くことです。「API」タブを選択し、検索クエリを入力すると、Cloud ShellでAPIを叩くためのcurlコマンドが自動生成されます。「CLOUD SHELLで実行」ボタンを押すとCloud Shellが起動するので、コピーしておいたcurlコマンドを実行します。
vertex_ai_search_api1.PNG

すると、以下のようにレスポンスが返ってきます。

{
  "summary": {
    "summaryText": "オセロは、1890年に...",
  ...

  "results": [
    {
      "id": "xxxxxxxxxxxxxxx",
      "document": {
        "name": "projects/xxxxxxxxx/locations/global/collections/default_collection/dataStores/xxxxxxxxxxx/branches/0/documents/xxxxxxxxxx",
        "id": "xxxxxxxxxxx",
        "derivedStructData": {
          "snippets": [
            {
              "snippet": "... \u003cb\u003eについて\u003c/b\u003eも特許権や...",
              "snippet_status": "SUCCESS"
            }
          ],
          "extractive_answers": [
            {
              "content": "ロ』に由来する[18]。緑の平原が...",
              "pageNumber": "13"
            }
          ],
          "title": "オセロ_(ボードゲーム)",
          "link": "gs://xxxx-bucket/オセロ_(ボードゲーム).pdf"
        }
      }
    },
    ...
  ]
}

ReactからAPIを呼び出す

しかしながら、勿論オセロアプリと連携させるのであれば、curlではなくReactからAPIを呼び出すことになると思いますので、今回はこの方法をご紹介します。

Googleのサービスアカウント作成

まずGoogleのサービスアカウントを作成する必要があります。今回は公式ドキュメントを参考に作成しました。途中、IAMロールを指定する必要がありますが、「AI Platform サービス エージェント」と「Vertex AI サービス エージェント」の2つを指定しました。どのロールを指定すればよいかは、先ほど立ち上げたCloud Shellで、組織の IAM Policy 情報を取得する以下のコマンドを実行すれば確認できるかと思います。(筆者はここで数時間躓きました)
gcloud projects get-iam-policy [Project ID or Number]

割り当てたIAMロールは以下のように、「権限」タブで確認できます。
vertex_ai_role.PNG

アクセストークンの取得

次にアクセストークンを取得します。上の手順の最後で保存した秘密鍵を用いて署名済みJWTを作り、Google OAuth2.0 AuthorizationServerへリクエストを送信します。
(この手順はこちらの記事を参考にさせていただきました)
詳しい手順は上記URLを参考にしていただければと思いますが、手順のうちJWTの作成と署名は手動で実施するうえ、認証アサーションの有効期限を1時間以内に設定する必要があります。いちいち1時間ごとに手動でポチポチ生成するのは現実的ではないので、実際に導入するのであれば自動生成できるように工夫しましょう。(今回はめんどくさい時間がないのでやりませんでした)

署名済JWTが作成できたら、以下のパラメータをbodyに含めてhttps://oauth2.googleapis.com/token
にPOSTリクエストを送り、アクセストークンを取得します。

パラメータ名
assertion 署名済JWT
grant_type urn:ietf:params:oauth:grant-type:jwt-bearer

Vertex AI Search APIを実行

アクセストークンが取得出来たら、いよいよVertex AI SearchのAPIを呼び出します。今回はJavaScriptのaxiosを使ったので、axiosを使った場合のコード例を載せておきます。

  const response = await axios.post(
    "https://discoveryengine.googleapis.com/v1alpha/projects/xxxxxxxxx/locations/global/collections/default_collection/dataStores/xxxxxxxxxxx/servingConfigs/default_search:search",
    {
      query: message,
      pageSize: 10,
      queryExpansionSpec: { condition: "AUTO" },
      spellCorrectionSpec: { mode: "AUTO" },
      contentSearchSpec: {
        summarySpec: {
          summaryResultCount: 5,
          ignoreAdversarialQuery: true,
          includeCitations: true,
        },
        snippetSpec: { returnSnippet: true },
        extractiveContentSpec: { maxExtractiveAnswerCount: 1 },
      },
    },
    {
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
    }
  );

一部マスキングしてしまっていますが、Vertex AI SearchのAPI画面で自動生成されるcurlコマンドを確認すれば、リクエスト先のURIやbodyの値が確認できるかと思います。

オセロアプリとVertex AI Search連携結果

これでようやくオセロアプリからVertex AI SearchのAPIを呼び出す準備ができました!

以下が実際に連携させてみた結果です。
ocello3_pettern3.PNG

質問文を入力して黄色いボタンを押すと、Vertex AI Searchから答えが返ってきます。オセロのWikipediaを確認していただければ分かりますが、しっかりとインプットした文書から答えが生成されていることがわかるかと思います。
ocello4_pettern3.PNG

精度

上述の通り、答えはインプット文書から生成されていますが、正確とは限りません。例えば、今回の「オセロの歴史を教えてください」という質問に対し、「1974年に水戸で自身のゲームであるオセロを発売した」と書かれていますが、実際にはオセロの発売日は1973年であり、水戸で発売したとはインプット文書に書かれていません。
(もちろん質問の表現を変えれば正答する場合もあります)

また、表から回答させる場合も、正答したり誤答したりとまちまちです。

表から正確に回答を生成した例
ocello_正答例_pettern3.PNG

表から回答させる質問を誤答した例
ocello_誤答例_pettern3.PNG

(正誤はWikipediaでご確認ください)

このように回答の精度は全て信用できるものではないので、インプット文書に対し前処理を施すなどの工夫が必要です。

終わりに

皆様お気づきかと思いますが、今回実装したオセロアプリは単にウィジェットを組み込んだ場合とほとんど機能は変わりません・・・。本当は盤面の状態をうまく自然言語に変換し、検索クエリに投げることで、次の一手のアドバイスができるオセロアプリを開発したかったのですが、時間がありませんでした。悔しいので次の機会にチャレンジして、オセロの「神の一手」を極めていきたいと思います。

この記事がこれからVertex AI Searchを始める方々のお力に少しでもなれたら幸いです。
引き続きNTTコムウェアのアドベントカレンダーをお楽しみください!

※記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?