使用 AlloyDB AI 构建生成式 AI 应用

本部分介绍了如何使用 pgvector 扩展程序调用预测、查询和索引嵌入。这些由机器学习提供支持的 AI 函数可通过 AlloyDB AI 使用,后者是一套 AlloyDB for PostgreSQL 功能,可让您将机器学习 (ML) 模型的语义和预测能力应用于您的数据。

如需详细了解 AlloyDB AI,请访问 https://cloud.google.com//alloydb/docs/ai

调用预测

如需将 Vertex AI 与 AlloyDB Omni 集成,并对 Vertex AI 存储的模型运行预测,请按照以下步骤操作。

准备工作

  1. 在 GDC 中启用 Vertex AI 在线预测
  2. 运行以下命令,根据上述步骤中下载的服务账号密钥创建 Kubernetes Secret。请确保在与 DBCluster 资源相同的命名空间中创建 Kubernetes Secret。

    kubectl create secret generic SECRET_NAME \
    --from-file=PATH_TO_SERVICE_ACCOUNT_KEY/private-key.json \
    -n NAMESPACE

    替换以下内容:

    • SECRET_NAME:创建 DBCluster 清单以让 AlloyDB Omni 可以访问 Distributed Cloud AI 功能时使用的 Secret 的名称。例如 vertex-ai-key-alloydb

    • PATH_TO_SERVICE_ACCOUNT_KEY:您下载 private-key.json 服务账号密钥的位置的路径。

    • NAMESPACE:数据库集群的命名空间。

  3. 按照选择数据库引擎类型并创建数据库集群中列出的步骤安装 AlloyDB Omni 操作器。

  4. 使用 AlloyDB AI 创建数据库集群,并将 vertexAIKeyRef 设置为上述步骤中在 DBCluster 清单的 googleMLExtension 字段下创建的 Kubernetes Secret。

    apiVersion: v1
    kind: Secret
    metadata:
      name: db-pw-DBCLUSTER_NAME
      namespace: USER_PROJECT
    type: Opaque
    data:
      DBCLUSTER_NAME: "BASE64_PASSWORD"
    ---
    apiVersion: DBENGINE_NAME.dbadmin.gdc.goog/v1
    kind: DBCluster
    metadata:
      name: DBCLUSTER_NAME
      namespace: USER_PROJECT
    spec:
      primarySpec:
        adminUser:
          passwordRef:
            name: db-pw-DBCLUSTER_NAME
        features:
          googleMLExtension:
            config:
              vertexAIKeyRef: SECRET_NAME
        version: "DB_VERSION"
        resources:
          memory: DB_MEMORY
          cpu: DB_CPU
          disks:
          - name: DataDisk
            size: DB_DATA_DISK
    

    执行以下变量替换操作:

    • DBCLUSTER_NAME:数据库集群的名称。
    • USER_PROJECT:要在其中创建数据库集群的用户项目的名称。
    • BASE64_PASSWORD:数据库管理员密码的 base64 编码。
    • DBENGINE_NAME:数据库引擎的名称。设置为 alloydbomni
    • DB_VERSION:数据库引擎的版本。
    • DB_MEMORY:分配给数据库集群的内存量,例如 5Gi
    • DB_CPU:分配给数据库集群的 CPU 数量,例如 2
    • DB_DATA_DISK:分配给数据库集群的空间量,例如 10 Gi

    应用清单。

    kubectl apply -f DB_CLUSTER_YAML

    替换以下内容:

    • DB_CLUSTER_YAML:此数据库集群清单文件的名称,例如 alloydb-omni-db-cluster.yaml
  5. 安装 google_ml_integration 扩展程序。

    CREATE EXTENSION google_ml_integration CASCADE;
    

调用预测

通过运行以下 ml_predict_row() SQL 函数,使用 Vertex AI 模型端点调用在线预测:

  SELECT ml_predict_row('PREDICTION_ENDPOINT/PROJECT_NAMESPACE/ORGANIZATION/ZONE/DNS/DNS_SUFFIX', '{ "instances": [ INSTANCES ], "parameters":
  PARAMETERS');

替换以下内容:

  • PREDICTION_ENDPOINT:Vertex AI 端点的限定名称

  • PROJECT_NAMESPACE:部署 Vertex AI 端点的命名空间

  • ORGANIZATION:部署 Vertex AI 端点的组织的名称

  • ZONE:Vertex AI 端点部署到的可用区

  • DNS:组织的 DNS

  • DNS_SUFFIX:DNS 对象的后缀

  • INSTANCES:预测调用的输入,采用 JSON 格式

  • PARAMETERS:预测调用的参数,采用 JSON 格式

使用 pgvector 查询嵌入并编入索引

借助 pgvector PostgreSQL 扩展程序,您可以在数据库中存储、编入索引和查询文本嵌入时使用向量专用运算符和函数。AlloyDB 针对使用 pgvector 进行了优化,可让您创建索引,以加快涉及嵌入的某些查询速度。

如需详细了解如何将 AlloyDB 用作 LLM,以及如何根据 LLM 生成和存储向量嵌入,请访问 https://cloud.google.com/alloydb/docs/ai/work-with-embeddings#index

使用 ScaNN 创建索引和查询向量

本部分介绍了如何使用存储的嵌入生成索引和查询嵌入。您可以使用 AlloyDB 创建 ScaNN 索引。

准备工作

在开始创建索引之前,您必须完成以下前提条件。

  • 嵌入向量已添加到 AlloyDB 数据库中的表。

  • 安装了基于 pgvectorvector 扩展程序版本 0.5.0 或更高版本(由 Google 针对 AlloyDB 进行扩展)。

    CREATE EXTENSION IF NOT EXISTS vector;
    
  • 如需生成 ScaNN 索引,请安装 postgres_ann 扩展程序以及 vector 扩展程序。

    CREATE EXTENSION IF NOT EXISTS postgres_ann;
    

创建 ScaNN 索引

您可以为数据库中的表创建 ScaNN 索引。

AlloyDB postgres_ann 是由 Google 开发的 PostgreSQL 扩展程序,可实现依托 ScaNN 算法的高效最近邻索引。

ScaNN 索引是一种基于树的量化索引,用于近似最近邻搜索。它可以缩短索引构建时间并减少内存占用。此外,它可根据工作负载提供快速 QPS。

二级树 ScaNN 索引

如需将使用 ScaNN 算法的二级树索引应用于包含存储的向量嵌入的列,请运行以下 DDL 查询:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE);

替换以下内容:

  • INDEX_NAME:要创建的索引的名称,例如 my-scann-index。索引名称会在整个数据库中共享。确保每个索引名称对数据库中的每个表中都是唯一的。

  • TABLE:要向其中添加索引的表。

  • EMBEDDING_COLUMN:用于存储 vector 数据的列。

  • DISTANCE_FUNCTION:要与此索引一起使用的距离函数。请按以下方式之一操作:

    • L2 距离:l2

    • 点积:dot_product

    • 余弦距离:cosine

  • NUM_LEAVES_VALUE:要应用于此索引的分区数量。设置为介于 1 到 1048576 之间的任意值。

三级树 ScaNN 索引

如需对包含存储的向量嵌入的列创建使用 ScaNN 算法的三级树索引,请运行以下 DDL 查询:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

替换以下内容:

  • MAX_NUM_LEVELS:K-means 聚类树的级别数量上限。对于基于二级树的量化,设置为 1(默认值);对于基于三级树的量化,设置为 2

创建索引后,您可以按照使用给定文本执行最近邻查询中的说明,运行利用该索引的最近邻搜索查询。

索引参数必须设置为可在 QPS 和召回率之间取得适当的平衡。

如需在使用 real[] 数据类型(而非 vector)的嵌入列上创建此索引,请将该列转换为 vector 数据类型:

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

DIMENSIONS 替换为嵌入列的维度宽度。

如需查看索引编制进度,请使用 pg_stat_progress_create_index 视图:

SELECT * FROM pg_stat_progress_create_index;

phase 列会显示索引创建的当前状态,building index: tree training 阶段会在索引创建后消失。

运行查询

在将嵌入存储到数据库中并为其编制索引后,您可以开始使用 pgvector 查询功能进行查询。您无法使用 postgres_ann 扩展程序运行批量搜索查询。

如需查找嵌入向量的语义最近邻,您可以运行以下示例查询,其中设置了在创建索引期间使用的相同距离函数。

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
    LIMIT ROW_COUNT

替换以下内容:

  • TABLE:包含要与文本进行比较的嵌入的表。

  • INDEX_NAME:要使用的索引的名称,例如 my-scann-index

  • EMBEDDING_COLUMN:包含存储的嵌入的列。

  • DISTANCE_FUNCTION_QUERY:要用于此查询的距离函数。根据创建索引时使用的距离函数,选择以下各项之一:

    • L2 距离:<->

    • 内积:<#>

    • 余弦距离:<=>

  • EMBEDDING:您要为其查找存储的语义最近邻的嵌入向量。

  • ROW_COUNT:要返回的行数。

    如果您只想获得单个最佳匹配项,请指定 1

您还可以使用 embedding() 函数将文本转换为向量。您可以将向量应用于某个pgvector最近邻运算符(适用于 L2 距离的 <->),以查找具有语义最相似的嵌入的数据库行。请注意,您必须先注册文本嵌入 Gecko 模型,才能使用此函数。

由于 embedding() 会返回 real 数组,因此您必须明确将 embedding() 调用转换为 vector,以便将这些值与 pgvector 运算符结合使用。

  CREATE EXTENSION google_ml_integration;
  CREATE EXTENSION IF NOT EXISTS vector;

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN::vector
    <-> embedding('MODEL_IDVERSION_TAG', 'TEXT')
    LIMIT ROW_COUNT

替换以下内容:

  • MODEL_ID:要查询的模型的 ID。

    如果您使用的是 Vertex AI Model Garden,请将 textembedding-gecko@003 指定为模型 ID。这些是 Distributed Cloud 可用于文本嵌入的云端模型。

  • 可选:VERSION_TAG:要查询的模型的版本标记。在标记前面添加 @

    如果您将某个 textembedding-gecko 英语模型与 Vertex AI 搭配使用,请指定某个版本标记,例如 textembedding-gecko@003

    Google 强烈建议您始终指定版本标记。如果您未指定版本标记,AlloyDB 会始终使用最新的模型版本,这可能会导致意外结果。

  • TEXT:要转换为向量嵌入的文本。

向量索引指标

本部分列出了与您在 AlloyDB 中生成的向量索引相关的指标。您可以使用安装 postgres_ann 扩展程序时可用的 pg_stat_ann_indexes 视图查看这些指标。

易用性指标

易用性指标包括一些指标,这些指标可帮助您通过指标(例如索引配置和索引扫描次数)了解索引利用率的状态。

指标名称 数据类型 说明
relid OID 包含向量索引的表的唯一标识符。
indexrelid OID 向量索引的唯一标识符。
schemaname NAME 索引所属架构的名称。
relname NAME 包含索引的表的名称。
indexrelname NAME 指数的名称。
indextype NAME 索引的类型。此值始终设置为 postgres_ann
indexconfig TEXT[] 在创建索引时为其定义的配置,例如叶数量和量化器。
indexsize TEXT 索引的大小。
indexscan BIGINT 对索引启动的索引扫描的次数。

调优指标

调优指标可让您深入了解当前索引优化,从而应用建议以提高查询性能。

指标名称 数据类型 说明
insertcount BIGINT 对索引执行的插入操作的次数。此指标还包括在创建索引之前存在的任何行数。
updatecount BIGINT 对索引执行的更新操作的次数。此指标不考虑任何 HOT 更新。
deletecount BIGINT 对索引执行的删除操作的次数。
distribution JSONB 索引的所有分区中的向量分布。

以下字段展示了分布情况:
  • maximum (INT8):所有分区中的向量数上限。
  • minimum (INT8):所有分区中的向量数下限。
  • average (FLOAT):所有分区中的向量平均数。
  • outliers (INT8[]):所有分区中排名靠前的离群值。此值显示了前 20 个离群值。

注意:由于 K-means 聚类算法固有的特性,即使在最初创建索引时,向量在各个分区之间的分布也始终会存在一定程度的差异。

基于指标的调整建议

Mutation
insertcountupdatecountdeletecount 指标一起展示了索引向量中的更改或变更。
系统会使用特定数量的向量和分区来创建索引。对向量索引执行插入、更新或删除等操作时,它仅会影响向量所在的初始分区集。因此,每个分区中的向量数量会随时间推移而波动,这可能会影响召回率、QPS 或者同时影响两者。
如果您在一段时间内遇到 ANN 搜索查询速度较慢或准确性问题(例如 QPS 较低或召回率较差),请考虑查看这些指标。相对于向量总数,变更次数较多可能表示需要重新编制索引。
分布
distribution 指标展示所有分区中的向量分布。
当您创建索引时,系统会使用特定数量的向量和固定分区来创建索引。分区过程和后续分布过程会根据此考虑因素进行。如果添加了其他向量,则系统会在现有分区之间对其进行分区,导致分布与创建索引时的分布不同。由于最终分布不会同时考虑所有向量,因此召回率、QPS 或两者都可能会受到影响。
如果您发现 ANN 搜索查询的性能逐渐下降,例如响应时间变慢或结果准确性降低(按 QPS 或召回率衡量),请考虑检查此指标并重新编制索引。