ベクトル検索のクイックスタート

Vertex AI Vector Search クイックスタートでは、架空の衣料品 e コマースサイトのサンプル データセットを例として取り上げ、インデックスを作成する方法について説明します。このクイックスタートは、エンベディングが作成済みの状態で開始します。このクイックスタートでは、30 分未満でインデックスの作成とデプロイを開始する方法について説明します。

前提条件

このチュートリアルには、請求先アカウントとリンクされた Google Cloud プロジェクトが必要です。新しいプロジェクトを作成するには、プロジェクトと開発環境を設定するをご覧ください。プロジェクトを作成し、請求先アカウントを設定する必要があります。

ランタイム環境を選択する

このチュートリアルは、Colab または Vertex AI Workbench で実行できます。

  • Colab: このチュートリアルを Colab で開きます。
  • Vertex AI Workbench: このチュートリアルを Vertex AI Workbench で開きます。Google Cloud プロジェクトで Vertex AI Workbench を初めて使用する場合は、Google Cloud コンソールの [Vertex AI Workbench] セクションに移動し、[有効にする] をクリックして Notebooks API を有効にします。

このノートブックを GitHub で表示するには、GitHub をご覧ください。

このクイックスタートを完了するためにかかる費用

このチュートリアルを完了するには、数米ドルほどかかります。このチュートリアルで使用する Google Cloud サービスの料金については、次の各ページをご覧ください。

また、料金計算ツールを使用して、予測される使用量に基づいた費用の見積もりを算出することもできます。

設定

Vertex AI を使い始める前に、以下の設定を行う必要があります。

Vertex AI SDK for Python をインストールする

Vertex AI と Cloud Storage API には、REST API や Vertex AI SDK for Python など、複数の方法でアクセスできます。このチュートリアルでは、Vertex AI SDK for Python を使用します。

!pip install --upgrade --user google-cloud-aiplatform>=1.29.0 google-cloud-storage

この Jupyter ランタイムで新しくインストールされたパッケージを使用するには、次のコード スニペットに示すように、ランタイムを再起動する必要があります。

# Restart kernel after installs so that your environment can access the new packages
import IPython

app = IPython.Application.instance()
app.kernel.do_shutdown(True)

環境変数

環境変数を設定します。プロンプトが表示されたら、your-project-id をプロジェクト ID に置き換えてセルを実行します。

# get project ID
PROJECT_ID = ! gcloud config get-value project
PROJECT_ID = PROJECT_ID[0]
LOCATION = "us-central1"
if PROJECT_ID == "(unset)":
    print(f"Please set the project ID manually below")
# define project information
if PROJECT_ID == "(unset)":
  PROJECT_ID = "[your-project-id]"

# generate a unique id for this session
from datetime import datetime
UID = datetime.now().strftime("%m%d%H%M")

認証(Colab のみ)

このノートブックを Colab で実行している場合は、次のセルの認証を実行する必要があります。Vertex AI Workbench を使用している場合は、事前に認証されているため、この手順は必要ありません。

import sys

# if it's Colab runtime, authenticate the user with Google Cloud
if 'google.colab' in sys.modules:
    from google.colab import auth
    auth.authenticate_user()

IAM 権限を設定する

サービスを使用するには、デフォルトのサービス アカウントにアクセス権限を追加する必要があります。

  1. Google Cloud コンソールで [IAM] ページに移動します。
  2. デフォルトのコンピューティング サービス アカウントのプリンシパルを特定します。次のようになります: compute@developer.gserviceaccount.com
  3. 編集ボタンをクリックして、デフォルトのコンピューティング サービス アカウントに Vertex AI ユーザーとストレージ管理者、Service Usage 管理者のロールを付与します。

API を有効にする

次のコマンドを実行して、この Google Cloud プロジェクトで Compute Engine、Vertex AI、Cloud Storage の API を有効にします。

! gcloud services enable compute.googleapis.com aiplatform.googleapis.com storage.googleapis.com --project {PROJECT_ID}

サンプルデータを準備する

このチュートリアルでは、架空の衣料品 e コマースサイトの合成商品データが約 30,000 行含まれた商品テーブルで構成された TheLook データセットを使用します。

サンプル データセット

このテーブルから product-embs.json ファイルが作成されました。

サンプルの商品エンベディング

このファイルは JSONL 形式です。各行には、商品 ID を表す id、商品名を表す name、テキスト用の Vertex AI エンベディングで以前に生成された 768 ディメンションの商品名のエンベディングを表す embedding があります。

テキスト エンベディングは、衣料品の商品名の意味を表します。このチュートリアルでは、ベクトル検索を使用してアイテムのセマンティック検索を行います。このサンプルコードは、「これに似た他の商品」をすばやく見つけてくれるクイック レコメンデーション システムの基礎として使用できます。

BigQuery テーブルのデータからエンベディングを作成して JSON ファイルに保存する方法の詳細については、Getting Started with Text Embeddings + Vertex AI Vector Search をご覧ください。

Cloud Storage 上でデータを準備する

Vertex AI を使用してインデックスを作成するには、エンベディング ファイルを Cloud Storage バケットに配置します。このコードを実行すると、次の 2 つのタスクが実行されます。

  1. Cloud Storage バケットを作成する。
  2. サンプル ファイルを Cloud Storage バケットにコピーする。
BUCKET_URI = f"gs://{PROJECT_ID}-vs-quickstart-{UID}"
! gcloud storage buckets create $BUCKET_URI --location=$LOCATION --project=$PROJECT_ID
! gcloud storage cp "gs://github-repo/data/vs-quickstart/product-embs.json" $BUCKET_URI

ベクトル検索を使用してクエリを実行するには、エンベディング ファイルをローカル ディレクトリにコピーする必要もあります。

! gcloud storage cp "gs://github-repo/data/vs-quickstart/product-embs.json" . # for query tests

ベクトル検索インデックスの作成とデプロイ

インデックスとインデックス エンドポイントを作成して、インデックスをエンドポイントにデプロイする方法を説明します。

インデックスを作成する

次に、エンベディングをベクトル検索に読み込みます。API は SDK の aiplatform パッケージで使用できます。

# init the aiplatform package
from google.cloud import aiplatform
aiplatform.init(project=PROJECT_ID, location=LOCATION)

create_tree_ah_index 関数を使用して MatchingEngineIndex を作成します(Matching Engine とは、ベクトル検索の以前の名称です)。

# create Index
my_index = aiplatform.MatchingEngineIndex.create_tree_ah_index(
    display_name = f"vs-quickstart-index-{UID}",
    contents_delta_uri = BUCKET_URI,
    dimensions = 768,
    approximate_neighbors_count = 10,
)

MatchingEngineIndex.create_tree_ah_index() メソッドはインデックスを作成します。所要時間はデータセットのサイズによって異なり、小さい場合は 10 分未満で完了する場合もありますが、60 分以上かかる場合もあります。インデックス作成のステータスは、Google Cloud コンソールの [ベクトル検索] で確認できます。

インデックスを確認する

インデックスを作成するためのパラメータ:

  • contents_delta_uri: エンベディング JSON ファイルを保存した Cloud Storage ディレクトリの URI
  • dimensions: 各エンベディングのディメンション サイズ。この例では、Text Embeddings API のエンベディングを使用しているため、768 です。
  • approximate_neighbors_count: 一般的なケースで取得する類似アイテムの数

インデックスの作成と使用可能なパラメータの詳細については、インデックスを作成して管理するをご覧ください。

インデックス エンドポイントの作成とインデックスのデプロイ

インデックスを使用するには、インデックス エンドポイントを作成する必要があります。これは、インデックスに対するクエリ リクエストを受け入れるサーバー インスタンスとして機能します。

## create `IndexEndpoint`
my_index_endpoint = aiplatform.MatchingEngineIndexEndpoint.create(
    display_name = f"vs-quickstart-index-endpoint-{UID}",
    public_endpoint_enabled = True
)

インデックス エンドポイントでは、デプロイされる一意のインデックス ID を指定してインデックスをデプロイします。

DEPLOYED_INDEX_ID = f"vs_quickstart_deployed_{UID}"
# deploy the Index to the Index Endpoint
my_index_endpoint.deploy_index(
    index = my_index, deployed_index_id = DEPLOYED_INDEX_ID
)

インデックスをインデックス エンドポイントに初めてデプロイする場合は、バックエンドを自動的にビルドして起動するまでに 30 分ほどかかります。インデックスのデプロイのステータスを確認するには、Google Cloud コンソールの Vertex AI セクションで、[Deploy and Use] セクションに移動します。[インデックス] を選択します。

インデックスを確認する

ベクトル検索を使用してクエリを実行する

次のコードでは、指定された商品名のエンベディングを検索し、ベクトル検索を使用して類似した商品名を探します。

クエリを実行するエンベディングを取得する

まず、エンベディング JSON ファイルを読み込み、商品名とエンベディングの dict を構築します。

import json

# build dicts for product names and embs
product_names = {}
product_embs = {}
with open('product-embs.json') as f:
    for l in f.readlines():
        p = json.loads(l)
        id = p['id']
        product_names[id] = p['name']
        product_embs[id] = p['embedding']

product_embs ディクショナリでは、商品 ID を指定してエンベディングを取得できます。

 # Get the embedding for ID 6523 "cloudveil women's excursion short"
 # You can also try with other IDs such as 12711, 18090, 19536 and 11863
query_emb = product_embs['6523']

クエリを実行する

エンベディングを Endpoint.find_neighbors() メソッドに渡して、類似する商品名を探します。

# run query
response = my_index_endpoint.find_neighbors(
    deployed_index_id = DEPLOYED_INDEX_ID,
    queries = [query_emb],
    num_neighbors = 10
)

# show the results
for idx, neighbor in enumerate(response[0]):
    print(f"{neighbor.distance:.2f} {product_names[neighbor.id]}")

ScaNN アルゴリズムにより、インデックスに数十億のアイテムがある場合でも、find_neighbors() メソッドは類似のアイテムをわずか数ミリ秒で取得します。ベクトル検索は自動スケーリングもサポートしており、ワークロードの需要に応じてノード数を自動的に変更できます。

クリーンアップ

Qwiklab の一時プロジェクトではなく、独自の Cloud プロジェクトを使用している場合は、このチュートリアルの終了後に、インデックス、インデックス エンドポイント、Cloud Storage バケットをすべて削除してください。そうしないと、残りのリソースで予期しない費用が発生する可能性があります。

Workbench を使用した場合は、コンソールからノートブックを削除しなければならない場合もあります。


# wait for a confirmation
input("Press Enter to delete Index Endpoint, Index and Cloud Storage bucket:")

# delete Index Endpoint
my_index_endpoint.undeploy_all()
my_index_endpoint.delete(force = True)

# delete Index
my_index.delete()

# delete Cloud Storage bucket
! gcloud storage rm {BUCKET_URI} --recursive

ユーティリティ

インデックスの作成またはデプロイには時間がかかることがあり、その間に Colab ランタイムとの接続が失われる可能性があります。接続が失われた場合は、新しいインデックスを再作成またはデプロイしなくても、Google Cloud コンソールの [ベクトル検索] を確認し、既存のインデックスを使用して続行できます。

既存のインデックスを取得する

既存のインデックス オブジェクトを取得するには、次の your-index-id の部分をインデックス ID に置き換えて、セルを実行します。インデックス ID は、Google Cloud コンソールの [ベクトル検索] で確認できます。Google Cloud コンソールの [Vertex AI] セクションで、[Deploy and Use] セクションに移動します。[インデックス] を選択します。

インデックスを確認する

my_index_id = "[your-index-id]"
my_index = aiplatform.MatchingEngineIndex(my_index_id)

既存のインデックス エンドポイントを取得する

既存のインデックス エンドポイント オブジェクトを取得するには、次の your-index-endpoint-id の部分をインデックス エンドポイント ID に置き換えて、セルを実行します。インデックス エンドポイントは、Google Cloud コンソールの [ベクトル検索] で確認できます。Google Cloud コンソールの [Vertex AI] セクションで、[Deploy and Use] セクションに移動します。[インデックス エンドポイント] を選択します。

[インデックス エンドポイント] を確認する

my_index_endpoint_id = "[your-index-endpoint-id]"
my_index_endpoint = aiplatform.MatchingEngineIndexEndpoint(my_index_endpoint_id)