使用 Vertex AI 执行向量相似度搜索

欢迎使用 Firebase Data Connect 的向量相似度搜索功能。这是 Firebase 实现的语义搜索功能,可与 Google Vertex AI 集成。

此功能的核心是向量嵌入,它们是表示文本或媒体的语义含义的浮点数数组。通过使用输入向量嵌入运行最近邻搜索,您可以找到所有语义相似的内容。Data Connect 使用 PostgreSQL 的 pgvector 扩展程序实现此功能。

这种强大的语义搜索功能可支持商品推荐引擎和搜索引擎等应用场景。它也是生成式 AI 流程中检索增强生成的关键组成部分。如需了解详情,请参阅 Vertex AI 文档。

您可以依赖 Data Connect 的内置支持,使用 Vertex AI 的 Embeddings API 自动生成向量嵌入,也可以使用该 API 手动生成向量嵌入。

前提条件

  • 为您的项目设置 Data Connect

  • 启用 Vertex AI API

设置

您可以选择本地开发流程(如果您是 Web、Kotlin Android 或 iOS 开发者)或 IDX 流程(适用于 Web 开发者)。您可以使用本地数据库或生产 Data Connect 项目及其 Cloud SQL for PostgreSQL 实例进行开发。

以下说明假定您已按照快速入门指南创建 Data Connect 项目。

与本地 PostgreSQL 集成

  1. 设置本地 PostgreSQL 实例。
  2. 为自己授予 Vertex AI User IAM 角色
  3. 在您的环境中设置 Google Cloud 应用默认凭据
  4. 在本地 PostgreSQL 实例中安装 pgvector 扩展程序
  5. 按照 pgvector 代码库中的说明使用 CREATE EXTENSION vector 启用该扩展程序。

与 IDX 集成

  1. 使用 Data Connect 模板设置 IDX 工作区。
  2. 为自己授予 Vertex AI User IAM 角色
  3. 按照 pgvector 代码库中的说明使用 CREATE EXTENSION vector 启用该扩展程序。

设计架构

如需执行矢量搜索,请在架构中添加一个 Vector 类型的新字段。例如,如果您想使用电影说明进行语义搜索,请添加一个字段来存储与电影说明关联的矢量嵌入。在此架构中,添加了 descriptionEmbedding 以存储 description 字段的向量嵌入。

type Movie @table {
 id: ID! @col(name: "movie_id") @default(id: ID! @col(name: "movie_id") @default(expr: "uuidV4()")
 title: String!
 description: String
 descriptionEmbedding: Vector! @col(size:768)
 // ...
}

生成和检索嵌入

Data Connect 通过 _embed 服务器值为矢量嵌入提供了集成支持。这会指示 Data Connect 通过在内部调用 Vertex AI 的嵌入 API 来生成向量嵌入。_embed 服务器值可用于更改和查询。

变更

通过 Data Connect 生成并存储嵌入

在向量搜索应用中,您可能希望在向数据库添加记录后立即请求生成嵌入。下面的 createMovie 更改会向 Movie 表添加电影记录,同时传递带有指定嵌入 model 的电影说明。

mutation createMovie($movieData: Movie_Data! @pick(fields: ["title", "genre", "description"])) {
  movie_insert(data: {
    ...movieData,
    descriptionEmbedding_embed: {model: "textembedding-gecko@003", text: $movieData.description}
  })
}

在某些情况下,您可能需要更新电影说明和嵌入。

mutation updateDescription($id: String!, $description: String!) {
  movie_update(id: $id, data: {
    description: $description,
    descriptionEmbedding_embed: {model: "textembedding-gecko@003", text: $description}
  })
}

如需从客户端调用后者更改,请执行以下操作:

import { updateMovieDescriptionWithEmbed } from 'lib/dataconnect-sdk/';

await updateMovieDescriptionWithEmbed({ id: movieId, description: description});

// Use the response

查询

使用如下所示的查询提取向量嵌入。请注意,查询返回的 descriptionEmbedding 是一个浮点数数组,通常不可读。因此,Data Connect 生成的 SDK 不支持直接返回它。

您可以使用返回的向量嵌入进行相似度搜索,如下一部分所述。

query getMovieDescription($id: String!) @auth(is: PUBLIC) {
 movie(id: $id)
   id
   description
   descriptionEmbedding
}

执行相似度搜索

现在,我们可以执行相似搜索了。

对于每个 Vector 字段,Data Connect 都会生成一个用于实现相似性搜索的 GraphQL 函数。此生成函数的名称为 ${pluralType}_${vectorFieldName}_similarity。它支持一些参数,如以下示例和参考列表所示。

您可以定义用于调用相似性搜索的 GraphQL 函数。如上所述,_embed 服务器值会指示 Data Connect 使用 Vertex AI 的 Embedding API 生成矢量嵌入,在本例中,为搜索字符串创建嵌入,以便与电影说明嵌入进行比较。

在此示例中,相似度搜索最多会返回 5 部电影,这些电影的说明在语义上与输入查询最接近。结果集按距离(从最近到最远)的升序排列。

query searchMovieDescriptionUsingL2Similarity ($query: String!) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare_embed: {model: "textembedding-gecko@003", text: $query},
      method: L2,
      within: 2,
      where: {content: {ne: "No info available for this movie."}}, limit: 5)
      {
        id
        title
        description
      }
  }

调用相似度查询

如需从客户端代码调用相似度搜索,请执行以下操作:

import { searchMovieDescriptionUsingL2similarity} from 'lib/dataconnect-sdk';

const response = await searchMovieDescriptionUsingL2similarity({ query });

// Use the response

使用自定义嵌入

借助 Data Connect,您还可以直接将嵌入作为 Vector 进行处理,而无需使用 _embed 服务器值来生成嵌入。

存储自定义嵌入

使用 Vertex Embeddings API 指定匹配模型,并请求正确维度的嵌入结果。

然后,将返回的浮点数组转换为 Vector,以便传递给更新操作进行存储。

mutation updateDescription($id: String!, $description: String!, $descriptionEmbedding: Vector!) {
  movie_update(id: $id, data: {
    // title, genre...
    description: $description,
    descriptionEmbedding: $descriptionEmbedding
  })
}

使用自定义嵌入执行相似度搜索

执行相同的操作以检索搜索字词的嵌入,并将其转换为 Vectors

然后,调用 _similarity 查询以执行每次搜索。

query searchMovieDescriptionUsingL2Similarity($compare: Vector!, $within: Float, $excludesContent: String, $limit: Int) @auth(level: PUBLIC) {
    movies_descriptionEmbedding_similarity(
      compare: $compare,
      method: L2,
      within: $within,
      where: {content: {ne: $excludesContent}}, limit: $limit)
      {
        id
        title
        description
      }
  }

部署到生产环境

部署架构和连接器

典型 Data Connect 迭代的最后一步是将资源部署到生产环境。

使用 firebase deploy 命令将包含 Vector 类型的架构部署到 CloudSQL 时,Firebase CLI 会执行必要的步骤,以便在 CloudSQL 实例上启用基于 Vertex AI 的嵌入生成。

firebase deploy --only dataconnect

如果您想在 CloudSQL 实例中手动启用嵌入支持,或者遇到 CLI 错误,请按照这些说明操作。

矢量搜索语法

架构扩展

Data ConnectVector 数据类型会映射到 PostgreSQL 的 vector 类型(如 pgvector 扩展所定义)。pgvector 的 vector 类型在 PostgreSQL 中存储为单精度浮点数的数组。

Data Connect 中,Vector 类型表示为 JSON 数字数组。输入会强制转换为 float32 值数组。如果强制转换失败,则会引发错误。

使用 @col 指令的 size 参数设置向量的维度。

type Question @table {
    text: String!
    category: String!
    textEmbedding: Vector! @col(size: 768)
}

Vector 类型支持 sizeVector 运算(例如相似搜索)需要所有 Vector 具有相同的维数。

directive @col(
  # … existing args
  """
  Defines a fixed column size for certain scalar types.

  - For Vector, size is required.
  - For all other types, size is currently unsupported and hence supplying it will result in a schema error.
  """
  size: Int
) on FIELD_DEFINITION

适用于查询和更改的 _embed 服务器值

_embed

此服务器值会指示 Data Connect 服务使用 Vertex AI 的嵌入 API 生成和存储嵌入。此服务器值可用于查询和更改。

用于相似性搜索的参数

method: COSINE|INNER_PRODUCT|L2

用于搜索附近邻居的距离函数。目前支持的算法是 pgvector 搜索算法的子集。

within: float

对执行最近邻搜索的距离范围的约束条件。

where: FDC filter condition

请参阅架构、查询和变更指南

limit: int

要返回的结果数。