本部分介绍了如何使用 pgvector 扩展程序调用预测、查询和索引嵌入。这些由机器学习技术提供支持的 AI 函数可通过 AlloyDB AI 使用,后者是一套 AlloyDB for PostgreSQL 功能,可让您将机器学习 (ML) 模型的语义和预测能力应用于您的数据。
如需详细了解 AlloyDB AI,请访问 https://cloud.google.com//alloydb/docs/ai。
调用预测
如需将 Vertex AI 与 AlloyDB Omni 集成,并对 Vertex AI 存储的模型运行预测,请按照以下步骤操作。
准备工作
- 在 GDC 中启用 Vertex AI 在线预测。
- 运行以下命令,根据上述步骤中下载的服务账号密钥创建 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:数据库集群的命名空间。
 
- 按照选择数据库引擎类型并创建数据库集群中列出的步骤安装 AlloyDB Omni 操作器。 
- 使用 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。
 
- 安装 - 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 数据库中的表。 
- 安装了基于 - pgvector的- vector扩展程序版本- 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 | 对索引执行的更新操作的次数。此指标不会考虑任何热更新。 | 
| deletecount | BIGINT | 对索引执行的删除操作的次数。 | 
| distribution | JSONB | 索引的所有分区中的向量分布。 以下字段展示了分布情况: 
 注意:由于 K-means 聚类算法固有的特性,即使在最初创建索引时,向量在各个分区之间的分布也始终会存在一定程度的差异。 | 
基于指标的调优建议
- Mutation
- insertcount、- updatecount和- deletecount指标一起展示了索引向量中的更改或变更。
- 系统会使用特定数量的向量和分区来创建索引。对向量索引执行插入、更新或删除等操作时,它仅会影响向量所在的初始分区集。因此,每个分区中的向量数量会随时间推移而波动,这可能会影响召回率、QPS 或者同时影响两者。
- 如果您在一段时间内遇到 ANN 搜索查询速度较慢或准确性问题(例如 QPS 较低或召回率较差),请考虑查看这些指标。相对于向量总数,变更次数较多可能表示需要重新编制索引。
- 分布
-  distribution指标展示所有分区中的向量分布。
- 当您创建索引时,系统会使用特定数量的向量和固定分区来创建索引。分区过程和后续分布过程会根据此考虑因素进行。如果添加了其他向量,则系统会在现有分区之间对其进行分区,导致分布与创建索引时的分布不同。由于最终分布不会同时考虑所有向量,因此召回率、QPS 或两者都可能会受到影响。
- 如果您发现 ANN 搜索查询的性能逐渐下降,例如响应时间变慢或结果准确性降低(按 QPS 或召回率衡量),请考虑检查此指标并重新编制索引。