使用分区 DML 为文本数据批量生成向量嵌入

本文档介绍了如何批量生成和回填矢量嵌入 文本数据(STRINGJSON),存储在 使用 SQL 和 Vertex AI textembedding-gecko 的 Spanner model.

前提条件

您的 Spanner 数据库中必须有一个表,并且其中包含 文本数据(STRINGJSON)。如需详细了解如何导入数据, 请参阅 Spanner 导入和导出概览

用例示例

假设您在 Spanner 中有一个具有以下架构的表。 此表包含数百万条记录。

GoogleSQL

CREATE TABLE Products (
  product_id INT64 NOT NULL,
  name STRING(MAX),
  description STRING(MAX)
) PRIMARY KEY(product_id);

PostgreSQL

CREATE TABLE Products (
  product_id INT8 NOT NULL,
  name TEXT,
  description TEXT,
  PRIMARY KEY(product_id)
);

您的目标是为此示例中的 description 列生成向量嵌入, 以查找类似商品并向客户推荐,从而改善他们的购物体验 使用矢量搜索获得更棒的体验。

注册嵌入模型

GoogleSQL

向 Vertex AI 注册嵌入模型 textembedding-gecko 端点:

CREATE MODEL MODEL_NAME
INPUT(
  content STRING(MAX)
)
OUTPUT(
  embeddings STRUCT<values ARRAY<FLOAT32>>
)
REMOTE OPTIONS(
    endpoint = '//aiplatform.googleapis.com/projects/PROJECT/locations/LOCATION/publishers/google/models/textembedding-gecko$MODEL_VERSION',
  default_batch_size = 5
)

请替换以下内容:

  • MODEL_NAME:嵌入模型的名称
  • PROJECT:托管 Vertex AI 端点的项目
  • LOCATION:Vertex AI 端点的位置
  • MODEL_VERSIONtextembedding-gecko 嵌入模型的版本

PostgreSQL

在 PostgreSQL 方言中,无需注册模型。 您可以直接将端点名称传递给 spanner.ML_PREDICT_ROW 函数调用。

有关最佳实践,请考虑以下事项:

  • 要保持配额的隔离,请使用其他项目中的端点 生成和回填嵌入会比生产端点更高。预留 生产端点来传送生产流量。
  • 确保模型端点支持 default_batch_size 的值。 您可以使用查询提示替换 default_batch_size @{remote_udf_max_rows_per_rpc=NEW_NUMBER}.有关 每个区域的default_batch_size上限,请参阅 获取文本片段的文本嵌入
  • 使用特定的模型版本(例如 @003)定义端点,而不是定义端点 @latest.这是因为为同一段生成的嵌入矢量 可能因您使用的模型版本而异;哪个 是希望避免使用不同模型版本来生成嵌入的原因 模型。此外,更新模型中的模型版本 定义语句不会更新已生成的嵌入 模型生成文本。管理嵌入的模型版本的一种方法是 在表中额外创建一个列来存储模型版本。
  • 自定义经调参的 textembedding-gecko 模型不支持 GoogleSQL ML.PREDICT 和 PostgreSQL spanner.ML_PREDICT_ROW 函数。

测试嵌入模型的端到端集成

您可以执行查询来测试是否已成功配置嵌入模型, 检索嵌入和嵌入。例如,运行以下查询:

GoogleSQL

SELECT embeddings.values
FROM SAFE.ML.PREDICT(
  MODEL MODEL_NAME,
  (SELECT description AS content FROM products LIMIT 10)
);

请替换以下内容:

  • MODEL_NAME:嵌入模型的名称

PostgreSQL

SELECT spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/textembedding-gecko$MODEL_VERSION',
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', description))))
FROM Products
LIMIT 10;

请替换以下内容:

  • PROJECT:托管 Vertex AI 端点的项目
  • LOCATION:Vertex AI 端点的位置
  • MODEL_VERSIONtextembedding-gecko 嵌入模型的版本

更新源表以包含用于存储嵌入的其他列

接下来,更新源表架构以包含 数据类型 ARRAY<FLOAT32>,用于存储生成的嵌入:

GoogleSQL

ALTER TABLE TABLE_NAME
ADD COLUMN EMBEDDING_COLUMN_NAME ARRAY<FLOAT32>;

请替换以下内容:

  • TABLE_NAME:源表的名称
  • EMBEDDING_COLUMN_NAME:要在其中添加生成的嵌入的列的名称

PostgreSQL

ALTER TABLE TABLE_NAME
ADD COLUMN EMBEDDING_COLUMN_NAME real[];

请替换以下内容:

  • TABLE_NAME:源表的名称
  • EMBEDDING_COLUMN_NAME:要在其中添加生成的嵌入的列的名称

例如,使用 products 表示例,运行以下命令:

GoogleSQL

ALTER TABLE Products
ADD COLUMN desc_embed ARRAY<FLOAT32>;

PostgreSQL

ALTER TABLE Products
ADD COLUMN desc_embed real[];

您可以再添加一列来管理嵌入模型的版本。

GoogleSQL

ALTER TABLE Products
ADD COLUMN desc_embed_model_version INT64;

PostgreSQL

ALTER TABLE Products
ADD COLUMN desc_embed_model_version INT8;

增加 Vertex AI 的配额

您可能需要增加 Vertex AI API 配额, 在使用模型的区域中 textembedding-gecko。接收者 申请增加配额,请参阅 Vertex AI 增加配额

如需了解详情,请参阅 Vertex AI 配额和限制

回填嵌入

最后,使用分区 DML 执行以下 UPDATE 语句 为文本数据列生成嵌入并存储嵌入 存储数据您可以将模型版本与嵌入一起存储。周三 建议您在所在区域的低流量时段执行此查询 数据库。

GoogleSQL

UPDATE TABLE_NAME
SET 
  TABLE_NAME.EMBEDDING_COLUMN_NAME = (
    SELECT embeddings.values
    FROM SAFE.ML.PREDICT(
      MODEL MODEL_NAME,
      (SELECT TABLE_NAME.DATA_COLUMN_NAME AS content)
    ) @{remote_udf_max_rows_per_rpc=MAX_ROWS}
  ),
  TABLE_NAME.EMBEDDING_VERSION_COLUMN = MODEL_VERSION
WHERE FILTER_CONDITION;

请替换以下内容:

  • TABLE_NAME:包含文本数据的表的名称
  • EMBEDDING_COLUMN_NAME:要在其中添加生成的嵌入的列的名称
  • DATA_COLUMN_NAME:包含文本数据的列的名称
  • MODEL_NAME:嵌入模型的名称
  • MAX_ROWS:每个 RPC 的最大行数
  • EMBEDDING_VERSION_COLUMN:用于管理用于回填嵌入的 textembedding-gecko 嵌入模型版本的列
  • MODEL_VERSIONtextembedding-gecko 嵌入模型的版本
  • FILTER_CONDITION:要应用的可分区过滤条件

使用 SAFE.ML.PREDICT 会针对失败的请求返回 NULL。您还可以使用 将 SAFE.ML.PREDICTWHERE embedding_column IS NULL 组合使用 过滤器来重新运行查询,而不计算字段的嵌入 已经计算好的模型。

PostgreSQL

UPDATE TABLE_NAME
SET 
  EMBEDDING_COLUMN_NAME = spanner.FLOAT32_ARRAY(spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/textembedding-gecko$MODEL_VERSION', 
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', DATA_COLUMN_NAME)))
  ) /*@ remote_udf_max_rows_per_rpc=MAX_ROWS */ ->'predictions'->0->'embeddings'->'values'),
  EMBEDDING_VERSION_COLUMN = MODEL_VERSION
WHERE FILTER_CONDITION;

请替换以下内容:

  • TABLE_NAME:包含文本数据的表的名称
  • EMBEDDING_COLUMN_NAME:要在其中添加生成的嵌入的列的名称
  • DATA_COLUMN_NAME:包含文本数据的列的名称
  • PROJECT:托管 Vertex AI 端点的项目
  • LOCATION:Vertex AI 端点的位置
  • MODEL_VERSIONtextembedding-gecko 嵌入模型的版本
  • MAX_ROWS:每个 RPC 的最大行数
  • EMBEDDING_VERSION_COLUMN:用于管理用于回填嵌入的 textembedding-gecko 嵌入模型版本的列
  • FILTER_CONDITION:要应用的可分区过滤条件

products 表的回填查询示例:

GoogleSQL

UPDATE products
SET
  products.desc_embed = (
    SELECT embeddings.values
    FROM SAFE.ML.PREDICT(
      MODEL gecko_model,
      (SELECT products.description AS content)
    ) @{remote_udf_max_rows_per_rpc=200}
  ),
  products.desc_embed_model_version = 3
WHERE products.desc_embed IS NULL;

PostgreSQL

UPDATE products
SET
  desc_embed = spanner.FLOAT32_ARRAY(spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/textembedding-gecko@003', 
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', description)))
  ) /*@ remote_udf_max_rows_per_rpc=200 */ ->'predictions'->0->'embeddings'->'values'),
  desc_embed_model_version = 3
WHERE desc_embed IS NULL;

有关最佳实践,请考虑以下事项:

  • Spanner API 的默认 gRPC 超时为一小时。 根据要回填的嵌入数量,您可能需要 请延长此超时时间,以确保 UPDATE 分区 DML 需要足够的时间来完成。如需了解详情,请参阅 配置自定义超时和重试

性能和其他注意事项

在回填嵌入时,请考虑以下因素来优化性能 数据。

节点数

分区 DML 在不同的分区上执行指定的 DML 语句, 并行运行。对于具有大量节点的实例,您可能会观察到配额问题 错误。如果 Vertex AI API 请求因 Vertex AI API 配额限制而受到限制, 然后 Spanner 会在 分区 DML 事务模式 最多 20 次如果您发现 Vertex AI,然后增加 Vertex AI 的配额。 您还可以使用语句级提示来调整并行处理 @{pdml_max_parallelism=DESIRED_NUMBER}。以下 示例将并行处理设置为“5”:

GoogleSQL

@{pdml_max_parallelism=5} UPDATE products
SET products.desc_embed =(
  SELECT embeddings.values
  FROM SAFE.ML.PREDICT(MODEL gecko_model, (
        SELECT products.value AS CONTENT
        )
  )
      @{remote_udf_max_rows_per_rpc=200}
),
products.desc_embed_model_version = 003
WHERE products.desc_embed IS NULL;

数据列中文字的大小

Vertex AI 嵌入模型对 词元。不同的模型版本具有不同的令牌 限制。每个 Vertex AI 请求可以有多个输入文本 字段中,但存在的令牌数量上限有限制 处理一个单独的请求对于 GoogleSQL 数据库,如果您遇到 INVALID_ARGUMENT 错误,显示“请求过大”请尝试减少 来避免错误为此,您可以配置default_batch_size 或者在注册模型时使用 @{remote_udf_max_outstanding_rpcs} 查询提示。

发送到 Vertex AI 的 API 请求数量

您可以使用查询提示 @{remote_udf_max_outstanding_rpcs} 来增加或 减少发送到 Vertex AI 的请求数, Spanner。请注意,提高此上限可以提高 Spanner 实例的内存用量和内存用量,适用于 GoogleSQL 使用此查询提示会替换已配置的 default_batch_size 进行微调。

监控回填进度

您可以监控发送到 Vertex AI 使用 系统数据分析信息中心

后续步骤