生成和搜索多模态嵌入

本教程将指导您完成一个端到端流程,该流程是为图片和文字创建多模态嵌入,然后执行跨模态文本到图片搜索。

本教程介绍了以下任务:

本教程使用大都会艺术博物馆中的公共领域艺术图片,您可以在公共 Cloud Storage gcs-public-data--met 存储桶中找到这些图片。

所需权限

如需运行本教程,您需要拥有以下 Identity and Access Management (IAM) 权限:

  • 如需创建连接,您需要拥有 BigQuery Connection Admin (roles/bigquery.connectionAdmin) 角色的成员资格。

  • 如需向连接的服务账号授予权限,您需要 resourcemanager.projects.setIamPolicy 权限。

  • 如需创建和运行笔记本,您需要以下 IAM 权限:

    • resourcemanager.projects.get
    • resourcemanager.projects.list
    • bigquery.config.get
    • bigquery.jobs.create
    • bigquery.readsessions.create
    • bigquery.readsessions.getData
    • bigquery.readsessions.update
    • resourcemanager.projects.get
    • resourcemanager.projects.list
    • dataform.locations.get
    • dataform.locations.list
    • dataform.repositories.create

    • dataform.repositories.list

    • dataform.collections.create

    • dataform.collections.list

    • aiplatform.notebookRuntimeTemplates.apply

    • aiplatform.notebookRuntimeTemplates.get

    • aiplatform.notebookRuntimeTemplates.list

    • aiplatform.notebookRuntimeTemplates.getIamPolicy

    • aiplatform.notebookRuntimes.assign

    • aiplatform.notebookRuntimes.get

    • aiplatform.notebookRuntimes.list

    • aiplatform.operations.list

    您可以从以下 IAM 角色获取这些权限:

    • BigQuery Read Session User (roles/bigquery.readSessionUser)
    • BigQuery Studio User (roles/bigquery.studioUser)
  • 以下两个角色提供本教程中的其余 BigQuery 操作所需的 IAM 权限:

    • BigQuery Data Editor (roles/bigquery.dataEditor),用于创建模型、表和索引。
    • BigQuery User (roles/bigquery.user),用于运行 BigQuery 作业。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

  • BigQuery ML: You incur costs for the data that you process in BigQuery.
  • Vertex AI: You incur costs for calls to the Vertex AI service that's represented by the remote model.

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

如需详细了解 BigQuery 价格,请参阅 BigQuery 文档中的 BigQuery 价格

如需详细了解 Vertex AI 价格,请参阅 Vertex AI 价格页面。

准备工作

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. Enable the BigQuery, BigQuery Connection, and Vertex AI APIs.

    Enable the APIs

  4. 启用 BigQuery Studio

创建数据集

创建 BigQuery 数据集以存储您的机器学习模型:

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery 页面

  2. 探索器窗格中,点击您的项目名称。

  3. 点击 查看操作 > 创建数据集

    创建数据集。

  4. 创建数据集页面上,执行以下操作:

    • 数据集 ID 部分,输入 bqml_tutorial

    • 位置类型部分,选择多区域,然后选择 US (multiple regions in United States)(美国[美国的多个区域])。

      公共数据集存储在 US 多区域中。为简单起见,请将数据集存储在同一位置。

    • 保持其余默认设置不变,然后点击创建数据集

      创建数据集页面。

创建连接

创建 Cloud 资源连接并获取连接的服务账号。在上一步中创建的数据集所在的位置创建连接。

从下列选项中选择一项:

控制台

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 如需创建连接,请点击 添加,然后点击与外部数据源的连接

  3. 连接类型列表中,选择 Vertex AI 远程模型、远程函数和 BigLake(Cloud 资源)

  4. 连接 ID 字段中,输入连接的名称。

  5. 点击创建连接

  6. 点击转到连接

  7. 连接信息窗格中,复制服务账号 ID 以在后续步骤中使用。

bq

  1. 在命令行环境中,创建连接:

    bq mk --connection --location=REGION --project_id=PROJECT_ID \
        --connection_type=CLOUD_RESOURCE CONNECTION_ID

    --project_id 参数会替换默认项目。

    替换以下内容:

    • REGION:您的连接区域
    • PROJECT_ID:您的 Google Cloud 项目 ID
    • CONNECTION_ID:您的连接的 ID

    当您创建连接资源时,BigQuery 会创建一个唯一的系统服务账号,并将其与该连接相关联。

    问题排查:如果您收到以下连接错误,请更新 Google Cloud SDK

    Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
    
  2. 检索并复制服务账号 ID 以在后续步骤中使用:

    bq show --connection PROJECT_ID.REGION.CONNECTION_ID

    输出类似于以下内容:

    name                          properties
    1234.REGION.CONNECTION_ID     {"serviceAccountId": "connection-1234-9u56h9@gcp-sa-bigquery-condel.iam.gserviceaccount.com"}
    

Terraform

使用 google_bigquery_connection 资源。

如需向 BigQuery 进行身份验证,请设置应用默认凭据。如需了解详情,请参阅为客户端库设置身份验证

以下示例会在 US 区域中创建一个名为 my_cloud_resource_connection 的 Cloud 资源连接:


# This queries the provider for project information.
data "google_project" "default" {}

# This creates a cloud resource connection in the US region named my_cloud_resource_connection.
# Note: The cloud resource nested object has only one output field - serviceAccountId.
resource "google_bigquery_connection" "default" {
  connection_id = "my_cloud_resource_connection"
  project       = data.google_project.default.project_id
  location      = "US"
  cloud_resource {}
}

如需在 Google Cloud 项目中应用 Terraform 配置,请完成以下部分中的步骤。

准备 Cloud Shell

  1. 启动 Cloud Shell
  2. 设置要在其中应用 Terraform 配置的默认 Google Cloud 项目。

    您只需为每个项目运行一次以下命令,即可在任何目录中运行它。

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    如果您在 Terraform 配置文件中设置显式值,则环境变量会被替换。

准备目录

每个 Terraform 配置文件都必须有自己的目录(也称为“根模块”)。

  1. Cloud Shell 中,创建一个目录,并在该目录中创建一个新文件。文件名必须具有 .tf 扩展名,例如 main.tf。在本教程中,该文件称为 main.tf
    mkdir DIRECTORY && cd DIRECTORY && touch main.tf
  2. 如果您按照教程进行操作,可以在每个部分或步骤中复制示例代码。

    将示例代码复制到新创建的 main.tf 中。

    (可选)从 GitHub 中复制代码。如果端到端解决方案包含 Terraform 代码段,则建议这样做。

  3. 查看和修改要应用到您的环境的示例参数。
  4. 保存更改。
  5. 初始化 Terraform。您只需为每个目录执行一次此操作。
    terraform init

    (可选)如需使用最新的 Google 提供程序版本,请添加 -upgrade 选项:

    terraform init -upgrade

应用更改

  1. 查看配置并验证 Terraform 将创建或更新的资源是否符合您的预期:
    terraform plan

    根据需要更正配置。

  2. 通过运行以下命令并在提示符处输入 yes 来应用 Terraform 配置:
    terraform apply

    等待 Terraform 显示“应用完成!”消息。

  3. 打开您的 Google Cloud 项目以查看结果。在 Google Cloud 控制台的界面中找到资源,以确保 Terraform 已创建或更新它们。

向连接的服务账号授予权限

向连接的服务账号授予适当的角色以访问 Cloud Storage 和 Vertex AI 服务。您必须在您在准备工作部分创建或选择的项目中授予这些角色。在其他项目中授予这些角色会导致错误 bqcx-1234567890-xxxx@gcp-sa-bigquery-condel.iam.gserviceaccount.com does not have the permission to access resource

如需授予适当的角色,请按照以下步骤操作:

  1. 前往 IAM 和管理页面。

    转到“IAM 和管理”

  2. 点击 授予访问权限

  3. 新的主账号字段中,输入您之前复制的服务账号 ID。

  4. 选择角色字段中,选择 Vertex AI,然后选择 Vertex AI User

  5. 点击添加其他角色

  6. 选择角色字段中,选择 Cloud Storage,然后选择 Storage Object Viewer

  7. 点击保存

创建对象表

基于公共 Cloud Storage gcs-public-data--met 存储桶中的艺术图片创建对象表。对象表让您无需从 Cloud Storage 中移动图片即可分析图片。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE EXTERNAL TABLE `bqml_tutorial.met_images`
    WITH CONNECTION `LOCATION.CONNECTION_ID`
    OPTIONS
      ( object_metadata = 'SIMPLE',
        uris = ['gs://gcs-public-data--met/*']
      );

    替换以下内容:

    • LOCATION:连接位置。
    • CONNECTION_ID:BigQuery 连接的 ID。

      当您在 Google Cloud 控制台中查看连接详情时,它是连接 ID 中显示的完全限定连接 ID 的最后一部分中的值,例如 projects/myproject/locations/connection_location/connections/myconnection

探索图片数据

在 BigQuery 中创建 Colab Enterprise 笔记本来探索图片数据。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 使用 BigQuery 编辑器创建笔记本

  3. 将笔记本连接到默认运行时

  4. 设置笔记本:

    1. 向笔记本添加一个代码单元。
    2. 将以下代码复制并粘贴到该代码单元中:

      #@title Set up credentials
      
      from google.colab import auth
      auth.authenticate_user()
      print('Authenticated')
      
      PROJECT_ID='PROJECT_ID'
      from google.cloud import bigquery
      client = bigquery.Client(PROJECT_ID)
      

      PROJECT_ID 替换为您在本教程中使用的项目名称。

    3. 运行该代码单元。

  5. 启用表显示:

    1. 向笔记本添加一个代码单元。
    2. 将以下代码复制并粘贴到该代码单元中:

      #@title Enable data table display
      %load_ext google.colab.data_table
      
    3. 运行该代码单元。

  6. 创建一个用于显示图片的函数:

    1. 向笔记本添加一个代码单元。
    2. 将以下代码复制并粘贴到该代码单元中:

      #@title Util function to display images
      import io
      from PIL import Image
      import matplotlib.pyplot as plt
      import tensorflow as tf
      
      def printImages(results):
       image_results_list = list(results)
       amt_of_images = len(image_results_list)
      
       fig, axes = plt.subplots(nrows=amt_of_images, ncols=2, figsize=(20, 20))
       fig.tight_layout()
       fig.subplots_adjust(hspace=0.5)
       for i in range(amt_of_images):
         gcs_uri = image_results_list[i][0]
         text = image_results_list[i][1]
         f = tf.io.gfile.GFile(gcs_uri, 'rb')
         stream = io.BytesIO(f.read())
         img = Image.open(stream)
         axes[i, 0].axis('off')
         axes[i, 0].imshow(img)
         axes[i, 1].axis('off')
         axes[i, 1].text(0, 0, text, fontsize=10)
       plt.show()
      
    3. 运行该代码单元。

  7. 显示图片:

    1. 向笔记本添加一个代码单元。
    2. 将以下代码复制并粘贴到该代码单元中:

      #@title Display Met images
      
      inspect_obj_table_query = """
      SELECT uri, content_type
      FROM bqml_tutorial.met_images
      WHERE content_type = 'image/jpeg'
      Order by uri
      LIMIT 10;
      """
      printImages(client.query(inspect_obj_table_query))
      
    3. 运行该代码单元。

      结果应如下所示:

      显示大都会艺术博物馆的图片。

  8. 将笔记本保存为 met-image-analysis

创建远程模型

创建表示托管 Vertex AI 多模态嵌入模型的远程模型:

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE MODEL `bqml_tutorial.multimodal_embedding_model`
      REMOTE WITH CONNECTION `LOCATION.CONNECTION_ID`
      OPTIONS (ENDPOINT = 'multimodalembedding@001');

    替换以下内容:

    • LOCATION:连接位置。
    • CONNECTION_ID:BigQuery 连接的 ID。

      当您在 Google Cloud 控制台中查看连接详情时,它是连接 ID 中显示的完全限定连接 ID 的最后一部分中的值,例如 projects/myproject/locations/connection_location/connections/myconnection

    查询需要几秒钟才能完成,之后 multimodal_embedding_model 模型会显示在探索器窗格的 bqml_tutorial 数据集中。由于查询使用 CREATE MODEL 语句来创建模型,因此没有查询结果。

生成嵌入图片

使用 ML.GENERATE_EMBEDDING 函数根据对象表中的图片生成嵌入,然后将其写入表中以供下一步使用。嵌入生成是一项费用高昂的操作,因此查询使用子查询(包括 LIMIT 子句)将嵌入生成限制为 10,000 张图片,而不是嵌入包含 601,294 张图片的完整数据集。这也有助于将 ML.GENERATE_EMBEDDING 函数的图片数量保持在 25,000 的限制以下。此查询大约需要 40 分钟才能完成运行。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE TABLE `bqml_tutorial.met_image_embeddings`
    AS
    SELECT *
    FROM
      ML.GENERATE_EMBEDDING(
        MODEL `bqml_tutorial.multimodal_embedding_model`,
        (SELECT * FROM `bqml_tutorial.met_images` WHERE content_type = 'image/jpeg' LIMIT 10000))

更正所有嵌入生成错误

检查并更正任何嵌入生成错误。由于 Vertex AI 上的生成式 AI 配额或服务不可用,嵌入生成可能会失败。

ML.GENERATE_EMBEDDING 函数在 ml_generate_embedding_status 列中返回错误详细信息。如果成功生成嵌入,此列为空;如果嵌入生成失败,此列会包含错误消息。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询以查看是否存在任何嵌入生成失败:

    SELECT DISTINCT(ml_generate_embedding_status),
      COUNT(uri) AS num_rows
    FROM bqml_tutorial.met_image_embeddings
    GROUP BY 1;
  3. 如果返回存在错误的行,请丢弃无法生成嵌入的行:

    DELETE FROM `bqml_tutorial.met_image_embeddings`
    WHERE ml_generate_embedding_status = 'A retryable error occurred: RESOURCE_EXHAUSTED error from remote service/endpoint.';

创建矢量索引

您可以选择使用 CREATE VECTOR INDEX 语句met_images_embeddings 表的 ml_generate_embedding_result 列上创建 met_images_index 矢量索引。矢量索引可让您更快地执行矢量搜索,同时需要降低召回率并返回更多近似结果。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE
      VECTOR INDEX `met_images_index`
    ON
      bqml_tutorial.met_image_embeddings(ml_generate_embedding_result)
      OPTIONS (
        index_type = 'IVF',
        distance_type = 'COSINE');
  3. 矢量索引是异步创建的。如需检查是否已创建矢量索引,请查询 INFORMATION_SCHEMA.VECTOR_INDEXES 视图并确认 coverage_percentage 值大于 0,并且 last_refresh_time 值不是 NULL

    SELECT table_name, index_name, index_status,
      coverage_percentage, last_refresh_time, disable_reason
    FROM bqml_tutorial.INFORMATION_SCHEMA.VECTOR_INDEXES
    WHERE index_name = 'met_images_index';

为搜索文本生成嵌入

如需搜索与指定文本搜索字符串对应的图片,您必须先为该字符串创建文本嵌入。使用同一远程模型创建用于创建图片嵌入的文本嵌入,然后将文本嵌入写入表中以供下一步使用。搜索字符串为 pictures of white or cream colored dress from victorian era

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE TABLE `bqml_tutorial.search_embedding`
    AS
    SELECT * FROM ML.GENERATE_EMBEDDING(
      MODEL `bqml_tutorial.multimodal_embedding_model`,
      (
        SELECT 'pictures of white or cream colored dress from victorian era' AS content
      )
    );

请使用 VECTOR_SEARCH 函数搜索与文本嵌入表示的搜索字符串最匹配的图片,然后将其写入表中以供下一步使用。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中,运行以下查询:

    CREATE OR REPLACE TABLE `bqml_tutorial.vector_search_results` AS
    SELECT base.uri AS gcs_uri, distance
    FROM
      VECTOR_SEARCH(
        TABLE `bqml_tutorial.met_image_embeddings`,
        'ml_generate_embedding_result',
        TABLE `bqml_tutorial.search_embedding`,
        'ml_generate_embedding_result',
        top_k => 3);

直观呈现矢量搜索结果

使用笔记本直观呈现矢量搜索结果。

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    转到 BigQuery

  2. 打开您之前创建的 met-image-analysis 笔记本。

  3. 直观呈现矢量搜索结果:

    1. 向笔记本添加一个代码单元。
    2. 将以下代码复制并粘贴到该代码单元中:

      query = """
        SELECT * FROM `bqml_tutorial.vector_search_results`
        ORDER BY distance;
      """
      
      printImages(client.query(query))
      
    3. 运行该代码单元。

      结果应如下所示:

      从多模态矢量搜索查询返回的图片。

清理

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.