更新和重建活跃索引

概览

对于大型搜索查询,更新索引对于始终拥有最准确的信息非常重要。现在,您可以使用批量更新或流式更新来更新 Vector Search 索引,前者使您可以通过批量时间表插入和删除数据点,后者则使您可以在几秒钟内更新和查询索引。

此外,您还可以使用 UpdateIndex 更新重要的元数据字段,例如 display_namedescriptionlabels。您还可以向索引中添加可选标记,以使结果多样化或过滤预索引查询。

更新批量索引

如需更新现有 Index 的内容,请使用 IndexService.UpdateIndex 方法。

如需替换现有 Index 的内容,请执行以下操作:

  • Index.metadata.contentsDeltaUri 设置为包含要更新的向量的 Cloud Storage URI。
  • isCompleteOverwrite 设置为 true。设置为 true 时,整个索引会完全被您提供的新元数据文件覆盖。

如果您在调用 IndexService.UpdateIndex 时设置了 contentsDeltaUri 字段,则无法在同一调用中更新其他索引字段(例如 displayNamedescriptionuserLabels)。

gcloud

  1. 更新索引元数据文件
  2. 使用 gcloud ai indexes update 命令

在使用下面的命令数据之前,请先进行以下替换:

  • 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 方法和网址:

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"
   }
 }
}

控制台

使用以下说明更新批量索引内容。

  1. 在 Google Cloud 控制台的 Vertex AI 部分中,前往部署和使用部分。选择 Vector Search

    前往 Vector Search

  2. 选择要更新的索引。此时会打开索引信息页面。
  3. 选择修改索引。此时会打开修改索引窗格。
  4. 在 Cloud Storage 字段中,搜索并选择存储向量数据的 Cloud Storage 文件夹。
  5. (可选)如果要覆盖所有现有数据,请选中“完全覆盖”复选框。
  6. 点击更新
  7. 点击完成以关闭面板。

如果 Index 具有任何关联的部署(请参阅 Index.deployed_indexes 字段),那么对原始 Index 进行某些更改后,DeployedIndex 会在后台中自动异步进行更新以反映这些更改。

如需检查更改是否已传播,请比较更新索引操作的完成时间和 DeployedIndex.index_sync_time

更新流式索引

利用流式更新,您可以在几秒钟内更新和查询索引。目前,您不能对现有批量更新索引使用流式更新,必须创建新索引。 如需了解详情,请参阅为流式更新创建索引

流式更新按 0.45 美元/GB 收费。如需详细了解价格,请参阅 Vertex AI 价格页面。 流式更新会直接应用于内存中已部署的索引,然后在短暂延迟后体现在查询结果中。

更新/插入数据点

通过这些示例了解如何更新/插入数据点。请注意,upsert-datapoints 仅接受数组格式的 JSON。

Python

Python

def stream_update_vector_search_index(
    project: str, location: str, index_name: str, datapoints: Sequence[dict]
) -> None:
    """Stream update an existing vector search index

    Args:
      project (str): Required. The Project ID
      location (str): Required. The region name, e.g. "us-central1"
      index_name (str): Required. The index to update. A fully-qualified index
        resource name or a index ID.  Example:
        "projects/123/locations/us-central1/indexes/my_index_id" or
        "my_index_id".
      datapoints: Sequence[dict]: Required. The datapoints to be updated. The dict
        element should be of the IndexDatapoint type.
    """
    # Initialize the Vertex AI client
    aiplatform.init(project=project, location=location)

    # Create the index instance from an existing index with stream_update
    # enabled
    my_index = aiplatform.MatchingEngineIndex(index_name=index_name)

    # Upsert the datapoints to the index
    my_index.upsert_datapoints(datapoints=datapoints)

Curl

吞吐量配额限制与更新/插入操作包含的数据量有关。 如果索引中存在数据点 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]}}]}'
    
  

控制台

控制台

按照以下说明将内容更新为流式索引。

  1. 在 Google Cloud 控制台中,前往向量搜索页面。

    前往 Vector Search

  2. 选择要更新的索引。此时会打开索引信息页面。
  3. 点击修改索引。此时会打开修改索引窗格。
  4. 在该窗格中,选择更新/插入数据点标签页以添加内容。
  5. 输入数据点 ID。
  6. 请至少输入一种嵌入类型:
    • 密集嵌入:输入以英文逗号分隔的浮点值数组。值的数量必须与索引的维度相匹配。
    • 稀疏嵌入(公开预览):
      1. 以英文逗号分隔的整数数组的形式输入稀疏嵌入维度。值的数量不必与索引的维度数量相匹配。
      2. 以英文逗号分隔的浮点值数组的形式输入值。值的数量必须与稀疏嵌入维度的数量相匹配。
  7. 可选:如需启用对此数据点的令牌限制过滤,请点击添加令牌限制,然后输入命名空间和以英文逗号分隔的字符串作为令牌。
  8. 可选:如要启用按此数据点的数字限制进行过滤,请点击添加数字限制,输入命名空间,选择数字类型,然后输入值。
  9. 可选:为避免出现许多类似结果,请输入拥挤标记字符串。
  10. 点击 Upsert
  11. 点击完成以关闭面板。

吞吐量配额限制与更新/插入操作包含的数据量有关。如果索引中存在数据点 ID,则会更新嵌入,否则将添加新嵌入。

更新动态元数据

您可能出于各种各样的原因而需要更新流式传输限制或数字限制。例如,在处理大量快速变化的数据时,您可能需要优先处理某些数据流。直接更新限制或数字限制可让您实时优化焦点,确保立即处理或突出显示最重要的数据。

您可以直接更新流式索引中的数据点限制和数字限制,而无需进行完整更新的压缩。

如需执行这些仅涉及元数据的更新,您需要向请求添加 update_mask 字段。update_mask 的值必须设置为 all_restricts。在数据点中设置的限制和数值限制值应为您要在更新中应用的新值。

以下示例展示了如何对两个现有数据点添加限制。

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}'"]}'

控制台

控制台

按照以下说明从流式索引中删除数据点。

  1. 在 Google Cloud 控制台的 Vertex AI 部分中,前往部署和使用部分。选择 Vector Search

    前往 Vector Search

  2. 选择要更新的流式索引。此时会打开索引信息页面。
  3. 选择修改索引。此时会打开修改索引窗格。
  4. 在该窗格中,选择移除数据点标签页。
  5. 通过提供数据点 ID 的逗号分隔列表,最多可以添加 20 个数据点
  6. 点击移除
  7. 点击完成以关闭面板。

压缩

索引会定期重建,以将自上次重建以来的所有新更新纳入在内。这种重建(也称为“压缩”)可以提高查询性能和可靠性。流式更新和批量更新均执行压缩操作。

  • 流式更新:Vector Search 使用基于启发法的指标来确定何时触发压缩。如果最早的未压缩数据存在时间超过 5 天,则始终会触发压缩。除了流式更新费用外,您还需要按与批量更新相同的费率支付重建索引的费用。

  • 批量更新:当增量数据集大小超过基本数据集大小的 20% 时进行压缩。

重新构建和查询索引

您可以使用 grpc cli、客户端库或 Vertex AI SDK for Python 照常发送匹配或批量匹配请求。重新构建查询时,您应该会在几秒钟内看到更新。如需了解如何查询索引,请参阅查询索引以获取最近邻

可选字段

创建索引时,您可以使用一些可选字段来微调查询。

包含限制的更新/插入

更新/插入索引并添加限制是标记数据点的方法,以便在查询时标识它们进行过滤。建议您添加限制标记,以在发送查询之前限制数据中显示的结果。例如,一位客户想要对索引运行查询,但希望确保结果在搜索鞋类时仅显示与“red”匹配的项。在以下示例中,索引正在更新/插入,并且正在过滤所有红色鞋子,但拒绝蓝色鞋子。这可确保搜索在运行前从一个多元化的大型索引中筛选出最佳特定选项。

除了词元限制之外,示例还使用数值限制。在本例中,数据点关联的价格 20,长度为 0.3,宽度为 0.5。在查询时,您可以使用这些数值限制来过滤结果,以按照价格、长度和宽度的值来限制查询结果。例如,此数据点会出现在按以下条件过滤的查询中:价格 > 25、长度 < 1 且宽度 < 1。

如需详细了解过滤,请参阅使用 Vector Search 进行索引

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 值。例如,假设您重新上线购买鞋子。您希望在结果中看到各种颜色,但希望它们属于单一款式,例如足球鞋。您可以通过在查询中设置 per_crowding_attribute_num_neighbors = 3 来要求返回不超过 3 双相同颜色的鞋子(假设您在插入数据点时将 crowding_attribute 设置为鞋子的颜色)。

此字段表示允许的具有相同拥挤标记的匹配数量上限。

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"},
  }
]}'

后续步骤