Cloud Run サービスから Cloud Storage 内の PDF(非構造化データ)に対して Vertex AI Search を使用する

1. はじめに

概要

Vertex AI Search and Conversation(旧称: Generative AI App Builder)を使用すると、デベロッパーは Google の基盤モデル、検索技術、会話型 AI テクノロジーの力を活用して、エンタープライズ グレードの生成 AI アプリケーションを作成できます。この Codelab では、Vertex AI Search の使用に焦点を当てます。Vertex AI Search を使用すると、独自のデータに基づいて Google 品質の検索アプリケーションを構築し、ウェブページやアプリケーションに検索バーを埋め込むことができます。

Cloud Run は、Google のスケーラブルなインフラストラクチャ上でコンテナを直接実行できるマネージド コンピューティング プラットフォームです。ソースベースのデプロイ オプションを使用すると、コンテナに配置できる任意のプログラミング言語で記述されたコードを Cloud Run にデプロイできます。

この Codelab では、ソースベースのデプロイを使用して Cloud Run サービスを作成し、Cloud Storage バケット内の PDF ファイルの非構造化コンテンツの検索結果を取得します。非構造化コンテンツの取り込みの詳細については、こちらをご覧ください

学習内容

  • Cloud Storage バケットから取り込まれた PDF 形式の非構造化データに対して Vertex AI Search アプリを作成する方法
  • Cloud Run でソースベースのデプロイを使用して HTTP エンドポイントを作成する方法
  • Cloud Run サービスが Vertex AI Search アプリにクエリを実行するために使用する、最小権限の原則に沿ったサービス アカウントを作成する方法
  • Cloud Run サービスを呼び出して Vertex AI Search アプリにクエリを実行する方法

2. 設定と要件

前提条件

Cloud Shell をアクティブにする

  1. Cloud Console で、[Cloud Shell をアクティブにする ]d1264ca30785e435.png をクリックします。

cb81e7c8e34bc8d.png

Cloud Shell を初めて起動した場合は、その内容を説明する画面が表示されます。その場合は、[続行] をクリックしてください。

d95252b003979716.png

すぐにプロビジョニングが実行され、Cloud Shell に接続されます。

7833d5e1c5d18f54.png

この仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。 この Codelab で行う作業のほとんどはブラウザから実行できます。

Cloud Shell に接続すると、認証が完了し、プロジェクトにプロジェクト ID が設定されていることがわかります。

  1. Cloud Shell で次のコマンドを実行して、認証されたことを確認します。
gcloud auth list

コマンド出力

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project

コマンド出力

[core]
project = <PROJECT_ID>

上記のようになっていない場合は、次のコマンドで設定できます。

gcloud config set project <PROJECT_ID>

コマンド出力

Updated property [core/project].

3. API の有効化

Vertex AI Search の使用を開始する前に、いくつかの API を有効にする必要があります。

まず、この Codelab では、Vertex AI Search and Conversation、BigQuery、Cloud Storage API を使用する必要があります。これらの API はこちらで有効にできます

次に、次の手順に沿って Vertex AI Search and Conversation API を有効にします。

  1. Google Cloud コンソールで、Vertex AI Search and Conversation コンソールに移動します。
  2. 利用規約を読んで同意し、[続行して API を有効にする] をクリックします。

4. Cloud Storage から非構造化データを検索するアプリを作成する

  1. Google Cloud コンソールで、[検索と会話] ページに移動します。[新しいアプリ] をクリックします。
  2. [アプリの種類の選択] ペインで、[検索] を選択します。
  3. ドキュメントからそのまま抜粋された回答を受け取るには、[Enterprise 機能] が有効 になっていることを確認します。
  4. 検索の要約を受け取るには、[高度な LLM 機能] オプションが有効 になっていることを確認します。
  5. [アプリ名] フィールドに、アプリの名前を入力します。アプリ名の下にアプリ ID が表示されます。
  6. アプリのロケーションとして [global (Global)] を選択し、[続行] をクリックします。
  7. [データストア] ペインで、[新しいデータストアの作成] をクリックします。
  8. [データソースを選択] ペインで [Cloud Storage] を選択します。
  9. [GCS からデータをインポートする] ペインで [フォルダ] が選択されていることを確認します。
  10. [gs://] フィールドに、値 cloud-samples-data/gen-app-builder/search/stanford-cs-224 を入力します。この Cloud Storage バケットには、テスト用に一般公開されている Cloud Storage フォルダの PDF ファイルが含まれています。
  11. [**非構造化ドキュメント**] を選択してから、[**続行**] をクリックします。
  12. [データストアの構成] ペインで、データストアのロケーションとして [global (Global)] を選択します。
  13. データストアの名前 を入力します。この名前は、この Codelab で Cloud Run サービスをデプロイするときに使用します。[作成] をクリックします。
  14. [データストア] ペインで新しいデータストアを選択してから、[作成] をクリックします。
  15. データストアの [データ] ページで、[アクティビティ] タブをクリックして、データの取り込みのステータスを確認します。インポート プロセスが完了すると、[ステータス] 列に [インポートが完了しました] と表示されます。
  16. [ドキュメント] タブをクリックして、インポートされたドキュメントの数を確認します。
  17. ナビゲーション メニューで [プレビュー] をクリックし、検索アプリをテストします。
  18. 検索バーに「final lab due date」と入力し、Enter キーを押して結果を確認します。

5. Cloud Run サービスを作成する

このセクションでは、検索語句のクエリ文字列を受け入れる Cloud Run サービスを作成します。このサービスでは、Discovery Engine API の Python クライアント ライブラリを使用します。サポートされている他のランタイムについては、こちらでリストを確認できます

関数のソースコードを作成する

まず、ディレクトリを作成し、そのディレクトリに移動します。

mkdir docs-search-service-python && cd $_

次に、次の内容で requirements.txt ファイルを作成します。

blinker==1.6.3
cachetools==5.3.1
certifi==2023.7.22
charset-normalizer==3.3.0
click==8.1.7
Flask==3.0.0
google-api-core==2.12.0
google-auth==2.23.3
google-cloud-discoveryengine==0.11.2
googleapis-common-protos==1.61.0
grpcio==1.59.0
grpcio-status==1.59.0
idna==3.4
importlib-metadata==6.8.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
numpy==1.26.1
proto-plus==1.22.3
protobuf==4.24.4
pyasn1==0.5.0
pyasn1-modules==0.3.0
requests==2.31.0
rsa==4.9
urllib3==2.0.7
Werkzeug==3.0.1
zipp==3.17.0

次に、次の内容で main.py ソースファイルを作成します。

from typing import List
import json
import os
from flask import Flask
from flask import request

app = Flask(__name__)

from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine_v1 as discoveryengine

project_id = os.environ.get('PROJECT_ID')
location = "global"  # Values: "global", "us", "eu"
data_store_id = os.environ.get('SEARCH_ENGINE_ID')

print(project_id)
print(data_store_id)

@app.route("/")
def search_storage():

    search_query = request.args.get("searchQuery")

    result = search_sample(project_id, location, data_store_id, search_query)
    return result

def search_sample(
    project_id: str,
    location: str,
    data_store_id: str,
    search_query: str,
) -> str:
    #  For more information, refer to:
    # https://cloud.google.com/generative-ai-app-builder/docs/locations#specify_a_multi-region_for_your_data_store
    client_options = (
        ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
        if location != "global"
        else None
    )

    # Create a client
    client = discoveryengine.SearchServiceClient(client_options=client_options)

    # The full resource name of the search engine serving config
    # e.g. projects/{project_id}/locations/{location}/dataStores/{data_store_id}/servingConfigs/{serving_config_id}
    serving_config = client.serving_config_path(
        project=project_id,
        location=location,
        data_store=data_store_id,
        serving_config="default_config",
    )

    # Optional: Configuration options for search
    # Refer to the `ContentSearchSpec` reference for all supported fields:
    # https://cloud.google.com/python/docs/reference/discoveryengine/latest/google.cloud.discoveryengine_v1.types.SearchRequest.ContentSearchSpec
    content_search_spec = discoveryengine.SearchRequest.ContentSearchSpec(
        # For information about snippets, refer to:
        # https://cloud.google.com/generative-ai-app-builder/docs/snippets
        snippet_spec=discoveryengine.SearchRequest.ContentSearchSpec.SnippetSpec(
            return_snippet=True
        ),
        # For information about search summaries, refer to:
        # https://cloud.google.com/generative-ai-app-builder/docs/get-search-summaries
        summary_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec(
            summary_result_count=5,
            include_citations=True,
            ignore_adversarial_query=True,
            ignore_non_summary_seeking_query=True,
        ),
    )


    # Refer to the `SearchRequest` reference for all supported fields:
    # https://cloud.google.com/python/docs/reference/discoveryengine/latest/google.cloud.discoveryengine_v1.types.SearchRequest
    request = discoveryengine.SearchRequest(
        serving_config=serving_config,
        query=search_query,
        page_size=10,
        content_search_spec=content_search_spec,
        query_expansion_spec=discoveryengine.SearchRequest.QueryExpansionSpec(
            condition=discoveryengine.SearchRequest.QueryExpansionSpec.Condition.AUTO,
        ),
        spell_correction_spec=discoveryengine.SearchRequest.SpellCorrectionSpec(
            mode=discoveryengine.SearchRequest.SpellCorrectionSpec.Mode.AUTO
        ),
    )

    response = client.search(request)

    return response.summary.summary_text

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

環境変数を設定する

このコードでは、この Codelab で使用する gcloud コマンドの可読性を高めるために、いくつかの環境変数を作成します。

PROJECT_ID=$(gcloud config get-value project)

SERVICE_NAME="search-storage-pdfs-python"
SERVICE_REGION="us-central1"

# update with your data store name
SEARCH_ENGINE_ID=<your-data-store-name>

サービス アカウントを作成する

この Codelab では、Cloud Run サービスが Vertex AI Search API にアクセスするために使用するサービス アカウントを作成する方法について説明します。

SERVICE_ACCOUNT="cloud-run-vertex-ai-search"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run Vertex AI Search service account"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/discoveryengine.editor'

Cloud Run サービスをデプロイする

ソースベースのデプロイを使用して、Cloud Run サービスを自動的にコンテナ化できるようになりました。

gcloud run deploy $SERVICE_NAME \
--region=$SERVICE_REGION \
--source=. \
--service-account $SERVICE_ACCOUNT \
--update-env-vars SEARCH_ENGINE_ID=$SEARCH_ENGINE_ID,PROJECT_ID=$PROJECT_ID \
--no-allow-unauthenticated

Cloud Run URL を環境変数として保存して、後で使用できます。

ENDPOINT_URL="$(gcloud run services describe $SERVICE_NAME --region=$SERVICE_REGION --format='value(status.url)')"

6. Cloud Run サービスを呼び出す

クエリ文字列を使用して Cloud Run サービスを呼び出し、What is the final lab due date? と尋ねることができます。

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "$ENDPOINT_URL?searchQuery=what+is+the+final+lab+due+date"

結果は、次の出力例のようになります。

The final lab is due on Tuesday, March 21 at 4:30 PM [1].

7. 完了

以上で、この Codelab は完了です。

Vertex AI SearchCloud Run のドキュメントを確認することをおすすめします。

学習した内容

  • Cloud Storage バケットから取り込まれた PDF 形式の非構造化データに対して Vertex AI Search アプリを作成する方法
  • Cloud Run でソースベースのデプロイを使用して HTTP エンドポイントを作成する方法
  • Cloud Run サービスが Vertex AI Search アプリにクエリを実行するために使用する、最小権限の原則に沿ったサービス アカウントを作成する方法。
  • Cloud Run サービスを呼び出して Vertex AI Search アプリにクエリを実行する方法

8. クリーンアップ

意図しない課金を回避するには(たとえば、この Cloud Functions が無料枠の月間 Cloud Functions 呼び出し割り当てよりも多く呼び出された場合)、Cloud Functions を削除するか、ステップ 2 で作成したプロジェクトを削除します。

Cloud Functions を削除するには、https://console.cloud.google.com/functions/ で Cloud Functions Cloud コンソールに移動し、imagen_vqa 関数(別の名前を使用した場合は $FUNCTION_NAME)を削除します。

プロジェクト全体を削除する場合は、https://console.cloud.google.com/cloud-resource-manager に移動し、ステップ 2 で作成したプロジェクトを選択して、[削除] を選択します。プロジェクトを削除する場合は、Cloud SDK でプロジェクトを変更する必要があります。gcloud projects list を実行すると、使用可能なすべてのプロジェクトのリストが表示されます。