概要
大規模な検索クエリでは、情報を常に最も正確に維持するため、インデックスの更新が重要です。現在、ベクトル検索インデックスは、バッチ アップデートを使用して更新できます。これにより、バッチ スケジュールに従って、またはストリーミング アップデートによってデータポイントの挿入と削除を行い、わずか数秒間でインデックスの更新とクエリを実行できます。
また、UpdateIndex
を使用して、display_name
、description
、labels
などの重要なメタデータ フィールドを更新することもできます。オプションのタグをインデックスに追加して、結果の多様化やインデックス前のクエリのフィルタリングを行うこともできます。
バッチ インデックスの更新
既存の Index
の内容を更新するには、IndexService.UpdateIndex
メソッドを使用します。
既存の Index
のコンテンツを置き換えるには:
Index.metadata.contentsDeltaUri
を、更新するベクトルを含む Cloud Storage URI に設定します。isCompleteOverwrite
を true に設定します。true に設定すると、インデックス全体が、指定した新しいメタデータ ファイルで完全に上書きされます。
IndexService.UpdateIndex
の呼び出し時に contentsDeltaUri
フィールドを設定するなら、同じ呼び出しで他のインデックス フィールド(displayName
、description
、userLabels
など)は更新できません。
gcloud
後述のコマンドデータを使用する前に、次のように置き換えます。
- LOCAL_PATH_TO_METADATA_FILE: メタデータ ファイルのローカルパス。
- INDEX_ID: インデックスの ID。
- LOCATION: Vertex AI を使用するリージョン。
- PROJECT_ID: Google Cloud プロジェクト ID。
次のコマンドを実行します。
Linux、macOS、Cloud Shell
gcloud ai indexes update INDEX_ID \ --metadata-file=LOCAL_PATH_TO_METADATA_FILE \ --region=LOCATION \ --project=PROJECT_ID
Windows(PowerShell)
gcloud ai indexes update INDEX_ID ` --metadata-file=LOCAL_PATH_TO_METADATA_FILE ` --region=LOCATION ` --project=PROJECT_ID
Windows(cmd.exe)
gcloud ai indexes update INDEX_ID ^ --metadata-file=LOCAL_PATH_TO_METADATA_FILE ^ --region=LOCATION ^ --project=PROJECT_ID
REST
リクエストのデータを使用する前に、次のように置き換えます。
- INPUT_DIR: インデックス コンテンツの Cloud Storage ディレクトリ パス。
- INDEX_ID: インデックスの ID。
- LOCATION: Vertex AI を使用するリージョン。
- PROJECT_ID: Google Cloud プロジェクト ID。
- PROJECT_NUMBER: プロジェクトに自動生成されたプロジェクト番号。
HTTP メソッドと URL:
PATCH https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/indexes/INDEX_ID
リクエストの本文(JSON):
{ "metadata": { "contentsDeltaUri": "INPUT_DIR", "isCompleteOverwrite": true } }
リクエストを送信するには、次のいずれかのオプションを開きます。
次のような JSON レスポンスが返されます。
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/indexes/INDEX_ID/operations/OPERATION_ID", "metadata": { "@type": "type.googleapis.com/google.cloud.aiplatform.v1.UpdateIndexOperationMetadata", "genericMetadata": { "createTime": "2022-01-12T23:56:14.480948Z", "updateTime": "2022-01-12T23:56:14.480948Z" } } }
コンソール
バッチ インデックスのコンテンツを更新するには、次の手順で操作します。
- Google Cloud コンソールの [Vertex AI] セクションで、[Deploy and Use] セクションに移動します。[ベクトル検索] を選択します。
- 更新するインデックスを選択します。[インデックスの情報] ページが開きます。
- [インデックスを編集] を選択します。インデックスの編集ペインが開きます。
- [Cloud Storage] フィールドで、ベクトルデータが保存されている Cloud Storage フォルダを検索して選択します。
- (省略可)既存のデータをすべて上書きする場合は、[完全な上書き] チェックボックスをオンにします。
- [更新] をクリックします。
- [完了] をクリックしてパネルを閉じます。
Index
に関連するデプロイがある場合(Index.deployed_indexes
フィールドを参照)、元の Index
への特定の変更が完了すると、その変更を反映するため、バックグラウンドで非同期的に DeployedIndex
が自動更新されます。
変更が伝播されたかどうかを確認するには、更新インデックス オペレーションの終了時間と DeployedIndex.index_sync_time
を比較します。
ストリーミング インデックスの更新
ストリーミング アップデートにより、数秒以内にインデックスを更新してクエリを実行できます。現時点では、既存のバッチ アップデート インデックスに対してストリーミング アップデートは使用できません。新しいインデックスを作成する必要があります。詳細については、ストリーミング アップデートのインデックスを作成するをご覧ください。
ストリーミング アップデートに使用される 1 GB あたり $0.45 が課金されます。料金の詳細については、Vertex AI の料金ページをご覧ください。ストリーミング アップデートは、メモリ内にデプロイされたインデックスに直接適用され、その後少し遅延してクエリ結果に反映されます。
データポイントの upsert
これらのサンプルを使用して、データポイントを upsert する方法を説明します。upsert-datapoints
は配列形式の JSON のみを受け入れます。
Python
Python
Curl
スループットの割り当て上限は、upsert に含まれるデータの量に関連します。データポイント ID がインデックスにある場合、エンベディングが更新されます。それ以外の場合は、新しいエンベディングが追加されます。
DATAPOINT_ID_1=
DATAPOINT_ID_2=
curl -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/indexes/${INDEX_ID}:upsertDatapoints \
-d '{datapoints: [{datapoint_id: "'${DATAPOINT_ID_1}'", feature_vector: [...]},
{datapoint_id: "'${DATAPOINT_ID_2}'", feature_vector: [...]}]}'
公開プレビュー版のハイブリッド検索では、データポイントのスパースなエンベディング表現と密なエンベディング表現がサポートされています。upsert オペレーションで密エンベディングを省略すると密表現が削除され、スパース エンベディングを省略するとスパース表現が削除されます。
この例では、密エンベディングとスパース エンベディングの両方を更新します。
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/indexes/${INDEX_ID}:upsertDatapoints -d '{datapoints: [{datapoint_id: "111", feature_vector: [0.111, 0.111], "sparse_embedding": {"values": [111.0,111.1,111.2], "dimensions": [10,20,30]}}]}'
この例では、密エンベディングを更新し、スパース エンベディングを削除します。
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/indexes/${INDEX_ID}:upsertDatapoints -d '{datapoints: [{datapoint_id: "111", feature_vector: [0.111, 0.111]}]}'
この例では、スパース エンベディングを更新し、密エンベディングを削除します。
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/indexes/${INDEX_ID}:upsertDatapoints -d '{datapoints: [{datapoint_id: "111", "sparse_embedding": {"values": [111.0,111.1,111.2], "dimensions": [10,20,30]}}]}'
コンソール
コンソール
ストリーミング インデックスのコンテンツを更新するには、次の手順で操作します。
- Google Cloud コンソールで、[ベクトル検索] ページに移動します。
- 更新するインデックスを選択します。[インデックスの情報] ページが開きます。
- [インデックスを編集] をクリックします。インデックスの編集ペインが開きます。
- このペインで [データポイントの Upsert] タブを選択して、コンテンツを追加します。
- データポイント ID を入力します。
- エンベディングのタイプを 1 つ以上入力します。
- 密エンベディング: カンマ区切りの浮動小数点値の配列を入力します。値の数は、インデックスのディメンションと一致している必要があります。
- スパース エンベディング(公開プレビュー):
- スパース エンベディングのディメンションを、カンマ区切りの整数の配列として入力します。値の数はインデックスのディメンションと一致している必要はありません。
- 値は、カンマ区切りの浮動小数点値の配列として入力します。値の数は、スパース エンベディングのディメンションの数と一致している必要があります。
- 省略可: このデータポイントでトークン制限によるフィルタリングを有効にするには、[トークン制限を追加] をクリックし、名前空間とトークンとしてカンマ区切りの文字列を入力します。
- 省略可: このデータポイントで数値制限によるフィルタリングを有効にするには、[数値制限を追加] をクリックして名前空間を入力し、数値型を選択して値を入力します。
- 省略可: 類似する結果が多数表示されるのを防ぐには、クラウディング タグ文字列を入力します。
- [Upsert] をクリックします。
- [完了] をクリックしてパネルを閉じます。
スループットの割り当て上限は、upsert に含まれるデータの量に関連します。データポイント ID がインデックスにある場合、エンベディングが更新されます。それ以外の場合は、新しいエンベディングが追加されます。
動的なメタデータの更新
ストリーミング制限や数値制限の更新が必要になる理由はさまざまです。たとえば、大容量で急速に変化するデータを処理する場合に、特定のデータ ストリームを優先したい場合です。制限または数値制限を直接更新すると、リアルタイムでフォーカスを絞り込み、最も重要なデータをすぐに処理またはハイライト表示できます。
完全に更新する場合の圧縮コストがかかることはなく、ストリーミング インデックス内のデータポイント制限と数値制限を直接更新できます。
これらのメタデータのみの更新を実行するには、リクエストに update_mask
フィールドを追加する必要があります。update_mask
の値は all_restricts
に設定する必要があります。データポイントに設定された制限値と数値制限値は、更新で適用する新しい値にする必要があります。
次の例は、既存の 2 つのデータポイントに制限を追加する方法を示しています。
DATAPOINT_ID_1=
DATAPOINT_ID_2=
curl -H "Content-Type: application/json" -H "Authorization: Bearer gcloud auth print-access-token" https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/indexes/${INDEX_ID}:upsertDatapoints \
-d '{datapoints:
[{datapoint_id: "'${DATAPOINT_ID_1}'", feature_vector: [...], restricts:[{namespace: "color", allow_list: ["red"]}]},
{datapoint_id: "'${DATAPOINT_ID_2}'", feature_vector: [...], restricts:[{namespace: "color", allow_list: ["red"]}]}
], update_mask: "all_restricts"}'
データポイントの削除
ストリーミング インデックスからデータポイントの削除が必要になる場合があります。これを行うには、curl または Google Cloud コンソールを使用します。
インデックスからデータポイントを削除する主なユースケースとして、インデックスと実際のソースの間の整合性の維持が挙げられます。ベクトル エンベディングを使用して検索やおすすめのために書籍の在庫を表示する、書籍販売業者の場合を考えてみましょう。書籍が売り切れた場合や、在庫から削除した場合は、関連するデータポイントをインデックスから削除することで、検索結果とおすすめを正確かつ最新の状態に保てます。
Curl
curl -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://{LOCATION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/indexes/{INDEX_ID}:removeDatapoints -d '{datapoint_ids: ["'{DATAPOINT_ID_1}'", "'{DATAPOINT_ID_2}'"]}'
コンソール
コンソール
ストリーミング インデックスからデータポイントを削除するには、次の手順で操作します。
- Google Cloud コンソールの [Vertex AI] セクションで、[Deploy and Use] セクションに移動します。[ベクトル検索] を選択します。
- 更新するストリーミング インデックスを選択します。[インデックスの情報] ページが開きます。
- [インデックスを編集] を選択します。インデックスの編集ペインが開きます。
- このペインで [データポイントの削除] タブを選択します。
- データポイント ID のカンマ区切りリストを指定すれば、最大 20 個のデータポイントを追加できます
- [削除] をクリックします。
- [完了] をクリックしてパネルを閉じます。
圧縮
インデックスは、前回の再構築以降に行われたすべての更新を反映して、定期的に再構築されます。この再構築(圧縮)により、クエリのパフォーマンスと信頼性が向上します。圧縮は、ストリーミング アップデートとバッチ アップデートの両方で行われます。
ストリーミング アップデート: ベクトル検索では、ヒューリスティック ベースの指標を使用して圧縮をトリガーするタイミングを決定します。最も古いものが 5 日以上前の未圧縮データである場合、圧縮は常にトリガーされます。ストリーミング アップデートの費用に加えて、バッチ アップデートと同じ頻度でインデックスを再構築する費用も課金されます。
バッチ アップデート: 増分データセット サイズが基本データセット サイズの 20% を超えるときに行われます。
インデックスの再構築とクエリ
gRPC CLI、クライアント ライブラリ、または Vertex AI SDK for Python を使用して、通常どおりに一致リクエストまたはバッチ一致リクエストを送信できます。クエリを再構築すると、数秒以内に更新が反映されます。インデックスをクエリする方法については、インデックスをクエリして最近傍を取得するをご覧ください。
省略可能フィールド
インデックスを作成するとき、クエリの微調整に使用できる省略可能フィールドがいくつかあります。
制限付きのアップサート
インデックスをアップサートして制限を追加するのは、データポイントにタグを付けて、クエリ時にフィルタリング対象として識別されるようにする方法です。クエリを送信する前に、データに表示される結果を制限するため、制限タグを追加するのが望ましいこともあります。たとえば、インデックスでクエリを実行するとき、「フットウェア」の検索で「赤」に一致するアイテムのみが結果に表示されるようにすることを考えます。以下の例では、インデックスが upsert され、すべての赤い靴でフィルタリングが行われていますが、青い靴は拒否されています。これにより、実行前に大規模で多様なインデックスから、最適な特定のオプションで検索をフィルタリングできます。
この例では、トークン制限に加えて数値制限も使用しています。この場合、データポイントは価格 20、長さ 0.3、幅 0.5 に関連付けられます。クエリの実行時に、これらの数値制限を使用して結果をフィルタリングし、クエリの結果を価格、長さ、幅の値に制限できます。たとえば、このデータポイントは、価格が 25 より大きい、長さが 1 より小さい、幅が 1 より小さい、というフィルタのクエリで表示されます。
フィルタリングの詳細については、インデックス作成用のベクトル検索をご覧ください。
Python
# Upsert datapoints
_TEST_DATAPOINT_1 = aiplatform_v1.types.index.IndexDatapoint(
datapoint_id="3",
feature_vector=[0.00526886899, -0.0198396724],
restricts=[
aiplatform_v1.types.index.IndexDatapoint.Restriction(namespace="Color", allow_list=["red"])
],
numeric_restricts=[
aiplatform_v1.types.index.IndexDatapoint.NumericRestriction(
namespace="cost",
value_int=1,
)
],
)
_TEST_DATAPOINT_2 = aiplatform_v1.types.index.IndexDatapoint(
datapoint_id="4",
feature_vector=[0.00526886899, -0.0198396724],
numeric_restricts=[
aiplatform_v1.types.index.IndexDatapoint.NumericRestriction(
namespace="cost",
value_double=0.1,
)
],
crowding_tag=aiplatform_v1.types.index.IndexDatapoint.CrowdingTag(crowding_attribute="crowding"),
)
_TEST_DATAPOINT_3 = aiplatform_v1.types.index.IndexDatapoint(
datapoint_id="5",
feature_vector=[0.00526886899, -0.0198396724],
numeric_restricts=[
aiplatform_v1.types.index.IndexDatapoint.NumericRestriction(
namespace="cost",
value_float=1.1,
)
],
)
_TEST_DATAPOINTS = [_TEST_DATAPOINT_1, _TEST_DATAPOINT_2, _TEST_DATAPOINT_3]
my_streaming_index = my_streaming_index.upsert_datapoints(datapoints=_TEST_DATAPOINTS)
# Dynamic metadata update
_TEST_DATAPOINT_4 = aiplatform_v1.types.index.IndexDatapoint(
datapoint_id="-2",
numeric_restricts=[
aiplatform_v1.types.index.IndexDatapoint.NumericRestriction(
namespace="cost",
value_float=1.1,
)
],
)
my_streaming_index = my_streaming_index.upsert_datapoints(datapoints=[_TEST_DATAPOINT4], update_mask=["all_restricts"])
curl
curl -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${ENDPOINT}/v1/projects/${PROJECT_ID}/locations/us-central1/indexes/${INDEX_ID}:upsertDatapoints \
-d '{
datapoints: [
{
datapoint_id: "'${DATAPOINT_ID_1}'",
feature_vector: [...],
restricts: { namespace: "color", allow_list: ["red"], deny_list: ["blue"]},
numeric_restricts: [{namespace: "price", value_int: 20}, {namespace: "length", value_float: 0.3}, {namespace: "width", value_double: 0.5}]
}
]}'
クラウディングでのアップサート
クラウディング タグは、検索結果の多様性を改善することで、類似の結果を制限します。クラウディングは、最近傍検索によって生成される近傍リストに対する制約で、同じ crowding_attribute
の値について、少数の値、または結果のグループしか返されないようにします。たとえば、オンラインで靴を購入することを考えます。結果において、さまざまな色の靴を含め、しかしスタイルについてはサッカー用スパイクのように 1 つのスタイルに限ることが望まれる場合があります。データポイントを挿入するとき、crowding_attribute を靴の色に設定したと想定すると、クエリで per_crowding_attribute_num_neighbors
= 3 を設定すると、返される結果で同じ色の靴を 3 足以下にするよう指定できます。
このフィールドは、同じクラウディング タグで許容される最大一致数を表します。
curl -H "Content-Type: application/json" -H "Authorization: Bearer `gcloud auth print-access-token`" https://${ENDPOINT}/v1/projects/${PROJECT_ID}/locations/us-central1/indexes/${INDEX_ID}:upsertDatapoints \
-d '{
datapoints: [
{
datapoint_id: "'${DATAPOINT_ID_1}'",
feature_vector: [...],
restricts: { namespace: "type", allow_list: ["cleats"]}
crowding_tag: { crowding_attribute: "red-shoe"},
}
]}'
次のステップ
- インデックス構成パラメータについて学習する
- インデックスのモニタリング方法について学習する