使用 ONNX 格式的 Transformer 模型生成嵌入

本教程介绍了如何将 Transformer 模型导出为开放神经网络交换 (ONNX) 格式,将 ONNX 模型导入 BigQuery 数据集,然后使用该模型通过 SQL 查询生成嵌入。

本教程使用 sentence-transformers/all-MiniLM-L6-v2 模型。此句子转换器模型以其在生成句子嵌入方面的快速高效而闻名。通过捕获文本的潜在含义,句子嵌入可实现语义搜索、聚类和句子相似度等任务。

ONNX 提供了一种用于表示任何机器学习 (ML) 框架的统一格式。BigQuery ML 对 ONNX 的支持让您可以执行以下操作:

  • 使用您偏好的框架训练模型。
  • 将模型转换为 ONNX 模型格式。
  • 将 ONNX 模型导入 BigQuery 并使用 BigQuery ML 进行预测。

目标

费用

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

如需根据您的预计使用量来估算费用,请使用价格计算器

新 Google Cloud 用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the BigQuery and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  6. 确保您拥有必要的权限,以便执行本文档中的任务。
  7. 所需的角色

    如果您创建新项目,则您是该项目的所有者,并且会获得完成本教程所需的所有 Identity and Access Management (IAM) 权限。

    如果您使用的是现有项目,请执行以下操作。

    Make sure that you have the following role or roles on the project:

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      前往 IAM
    2. 选择项目。
    3. 点击 授予访问权限
    4. 新的主账号字段中,输入您的用户标识符。 这通常是 Google 账号的电子邮件地址。

    5. 选择角色列表中,选择一个角色。
    6. 如需授予其他角色,请点击 添加其他角色,然后添加其他各个角色。
    7. 点击 Save(保存)。
    8. 如需详细了解 BigQuery 中的 IAM 权限,请参阅 IAM 权限

      将 Transformer 模型文件转换为 ONNX

      您可以选择按照本部分中的步骤将 sentence-transformers/all-MiniLM-L6-v2 模型和分词器手动转换为 ONNX。 否则,您可以使用公共 gs://cloud-samples-data Cloud Storage 存储分区中已转换的示例文件。

      如果您选择手动转换文件,则必须拥有已安装 Python 的本地命令行环境。如需详细了解如何安装 Python,请参阅 Python 下载

      将 Transformer 模型导出为 ONNX

      使用 Hugging Face Optimum CLI 将 sentence-transformers/all-MiniLM-L6-v2 模型导出到 ONNX。 如需详细了解如何使用 Optimum CLI 导出模型,请参阅使用 optimum.exporters.onnx 将模型导出为 ONNX

      如需导出模型,请打开命令行环境并按以下步骤操作:

      1. 安装 Optimum CLI:

        pip install optimum[onnx]
        
      2. 导出模型。 --model 实参用于指定 Hugging Face 模型 ID。 --opset 实参用于指定 ONNXRuntime 库版本,并设置为 17 以保持与 BigQuery 支持的 ONNXRuntime 库的兼容性。

        optimum-cli export onnx \
          --model sentence-transformers/all-MiniLM-L6-v2 \
          --task sentence-similarity \
          --opset 17 all-MiniLM-L6-v2/
        

      模型文件会导出到 all-MiniLM-L6-v2 目录,并命名为 model.onnx

      对 Transformer 模型应用量化

      使用 Optimum CLI 对导出的 Transformer 模型应用量化,以减小模型大小并加快推理速度。如需了解详情,请参阅量化

      如需对模型应用量化,请在命令行中运行以下命令:

      optimum-cli onnxruntime quantize \
        --onnx_model all-MiniLM-L6-v2/ \
        --avx512_vnni -o all-MiniLM-L6-v2_quantized
      

      量化模型文件将导出到 all-MiniLM-L6-v2_quantized 目录,并命名为 model_quantized.onnx

      将分词器转换为 ONNX

      如需使用 ONNX 格式的 Transformer 模型生成嵌入,您通常会使用分词器生成模型的两个输入,即 input_idsattention_mask

      如需生成这些输入,请使用 onnxruntime-extensions 库将 sentence-transformers/all-MiniLM-L6-v2 模型的分词器转换为 ONNX 格式。转换分词器后,您可以直接对原始文本输入执行分词,以生成 ONNX 预测。

      如需转换分词器,请在命令行中按以下步骤操作:

      1. 安装 Optimum CLI:

        pip install optimum[onnx]
        
      2. 使用您选择的文本编辑器,创建一个名为 convert-tokenizer.py 的文件。以下示例使用 nano 文本编辑器:

        nano convert-tokenizer.py
        
      3. 将如下Python脚本复制并粘贴到convert-tokenizer.py文件中:

        from onnxruntime_extensions import gen_processing_models
        
        # Load the Huggingface tokenizer
        tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
        
        # Export the tokenizer to ONNX using gen_processing_models
        onnx_tokenizer_path = "tokenizer.onnx"
        
        # Generate the tokenizer ONNX model, and set the maximum token length.
        # Ensure 'max_length' is set to a value less than the model's maximum sequence length, failing to do so will result in error during inference.
        tokenizer_onnx_model = gen_processing_models(tokenizer, pre_kwargs={'max_length': 256})[0]
        
        # Modify the tokenizer ONNX model signature.
        # This is because certain tokenizers don't support batch inference.
        tokenizer_onnx_model.graph.input[0].type.tensor_type.shape.dim[0].dim_value = 1
        
        # Save the tokenizer ONNX model
        with open(onnx_tokenizer_path, "wb") as f:
          f.write(tokenizer_onnx_model.SerializeToString())
        
      4. 保存 convert-tokenizer.py 文件。

      5. 运行 Python 脚本以转换分词器:

        python convert-tokenizer.py
        

      转换后的分词器将导出到 all-MiniLM-L6-v2_quantized 目录,并命名为 tokenizer.onnx

      将转换后的模型文件上传到 Cloud Storage

      转换 Transformer 模型和分词器后,请执行以下操作:

      创建数据集

      创建 BigQuery 数据集以存储机器学习模型。

      控制台

      1. 在 Google Cloud 控制台中,前往 BigQuery 页面。

        转到 BigQuery 页面

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

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

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

        • 数据集 ID 部分,输入 bqml_tutorial

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

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

      bq

      如需创建新数据集,请使用带有 --location 标志的 bq mk 命令。 如需查看完整的潜在参数列表,请参阅 bq mk --dataset 命令参考文档。

      1. 创建一个名为 bqml_tutorial 的数据集,并将数据位置设置为 US,说明为 BigQuery ML tutorial dataset

        bq --location=US mk -d \
         --description "BigQuery ML tutorial dataset." \
         bqml_tutorial

        该命令使用的不是 --dataset 标志,而是 -d 快捷方式。如果省略 -d--dataset,该命令会默认创建一个数据集。

      2. 确认已创建数据集:

        bq ls

      API

      使用已定义的数据集资源调用 datasets.insert 方法。

      {
        "datasetReference": {
           "datasetId": "bqml_tutorial"
        }
      }

      BigQuery DataFrame

      在尝试此示例之前,请按照《BigQuery 快速入门:使用 BigQuery DataFrames》中的 BigQuery DataFrames 设置说明进行操作。如需了解详情,请参阅 BigQuery DataFrames 参考文档

      如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为本地开发环境设置 ADC

      import google.cloud.bigquery
      
      bqclient = google.cloud.bigquery.Client()
      bqclient.create_dataset("bqml_tutorial", exists_ok=True)

      将 ONNX 模型导入 BigQuery

      将转换后的分词器和句子转换器模型作为 BigQuery ML 模型导入。

      从下列选项中选择一项:

      控制台

      1. 在 Google Cloud 控制台中,打开 BigQuery Studio。

        进入 BigQuery Studio

      2. 在查询编辑器中,运行以下 CREATE MODEL 语句以创建 tokenizer 模型。

         CREATE OR REPLACE MODEL `bqml_tutorial.tokenizer`
          OPTIONS (MODEL_TYPE='ONNX',
           MODEL_PATH='TOKENIZER_BUCKET_PATH')

        TOKENIZER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TOKENIZER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/tokenizer.onnx

        操作完成后,您会在查询结果窗格中看到类似于以下内容的消息:Successfully created model named tokenizer

      3. 点击前往模型以打开详细信息窗格。

      4. 查看特征列部分可了解模型输入,查看标签列可了解模型输出。

        分词器模型的 **详细信息** 窗格

      5. 在查询编辑器中,运行以下 CREATE MODEL 语句以创建 all-MiniLM-L6-v2 模型。

         CREATE OR REPLACE MODEL `bqml_tutorial.all-MiniLM-L6-v2`
          OPTIONS (MODEL_TYPE='ONNX',
           MODEL_PATH='TRANSFORMER_BUCKET_PATH')

        TRANSFORMER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TRANSFORMER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/model_quantized.onnx

        操作完成后,您会在查询结果窗格中看到类似于以下内容的消息:Successfully created model named all-MiniLM-L6-v2

      6. 点击前往模型以打开详细信息窗格。

      7. 查看特征列部分可了解模型输入,查看标签列可了解模型输出。

        `all-MiniLM-L6-v2` 模型的 **详细信息** 窗格

      bq

      使用 bq 命令行工具 query 命令运行 CREATE MODEL 语句。

      1. 在命令行中,运行以下命令以创建 tokenizer 模型。

        bq query --use_legacy_sql=false \
        "CREATE OR REPLACE MODEL
        `bqml_tutorial.tokenizer`
        OPTIONS
        (MODEL_TYPE='ONNX',
        MODEL_PATH='TOKENIZER_BUCKET_PATH')"

        TOKENIZER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TOKENIZER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/tokenizer.onnx

        操作完成后,您会看到类似于以下内容的消息:Successfully created model named tokenizer

      2. 在命令行中,运行以下命令以创建 all-MiniLM-L6-v2 模型。

        bq query --use_legacy_sql=false \
        "CREATE OR REPLACE MODEL
        `bqml_tutorial.all-MiniLM-L6-v2`
        OPTIONS
        (MODEL_TYPE='ONNX',
          MODEL_PATH='TRANSFORMER_BUCKET_PATH')"

        TRANSFORMER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TRANSFORMER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/model_quantized.onnx

        操作完成后,您会看到类似于以下内容的消息:Successfully created model named all-MiniLM-L6-v2

      3. 导入模型后,请验证这些模型是否显示在数据集中。

        bq ls -m bqml_tutorial

        输出类似于以下内容:

        tableId            Type
        ------------------------
        tokenizer          MODEL
        all-MiniLM-L6-v2   MODEL

      API

      使用 jobs.insert 方法导入模型。在请求正文中,使用 CREATE MODEL 语句填充 QueryRequest 资源query 参数。

      1. 使用以下 query 参数值创建 tokenizer 模型。

        {
        "query": "CREATE MODEL `PROJECT_ID :bqml_tutorial.tokenizer` OPTIONS(MODEL_TYPE='ONNX' MODEL_PATH='TOKENIZER_BUCKET_PATH')"
        }

        替换以下内容:

        • PROJECT_ID 替换为您的项目 ID。
        • TOKENIZER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TOKENIZER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/tokenizer.onnx
      2. 使用以下 query 参数值创建 all-MiniLM-L6-v2 模型。

        {
        "query": "CREATE MODEL `PROJECT_ID :bqml_tutorial.all-MiniLM-L6-v2` OPTIONS(MODEL_TYPE='ONNX' MODEL_PATH='TRANSFORMER_BUCKET_PATH')"
        }

        替换以下内容:

        • PROJECT_ID 替换为您的项目 ID。
        • TRANSFORMER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TRANSFORMER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/model_quantized.onnx

      BigQuery DataFrame

      在尝试此示例之前,请按照《BigQuery 快速入门:使用 BigQuery DataFrames》中的 BigQuery DataFrames 设置说明进行操作。如需了解详情,请参阅 BigQuery DataFrames 参考文档

      如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为本地开发环境设置 ADC

      使用 ONNXModel 对象导入分词器和句子转换器模型。

      import bigframes
      from bigframes.ml.imported import ONNXModel
      
      bigframes.options.bigquery.project = PROJECT_ID
      
      bigframes.options.bigquery.location = "US"
      
      tokenizer = ONNXModel(
        model_path= "TOKENIZER_BUCKET_PATH"
      )
      imported_onnx_model = ONNXModel(
        model_path="TRANSFORMER_BUCKET_PATH"
      )

      替换以下内容:

      • PROJECT_ID 替换为您的项目 ID。
      • TOKENIZER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TOKENIZER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/tokenizer.onnx
      • TRANSFORMER_BUCKET_PATH 替换为您上传到 Cloud Storage 的模型的路径。如果您使用的是示例模型,请将 TRANSFORMER_BUCKET_PATH 替换为以下值:gs://cloud-samples-data/bigquery/ml/onnx/all-MiniLM-L6-v2/model_quantized.onnx

      使用导入的 ONNX 模型生成嵌入

      使用导入的分词器和句子转换器模型,根据 bigquery-public-data.imdb.reviews 公共数据集中的数据生成嵌入。

      从下列选项中选择一项:

      控制台

      使用 ML.PREDICT 函数通过模型生成嵌入。

      该查询使用嵌套的 ML.PREDICT 调用,通过分词器和嵌入模型直接处理原始文本,如下所示:

      • 分词(内部查询):内部 ML.PREDICT 调用使用 bqml_tutorial.tokenizer 模型。它将 bigquery-public-data.imdb.reviews 公共数据集中的 title 列作为其 text 输入。 tokenizer 模型将原始文本字符串转换为主模型所需的数字令牌输入,包括 input_idsattention_mask 输入。
      • 嵌入生成(外部查询):外部 ML.PREDICT 调用使用 bqml_tutorial.all-MiniLM-L6-v2 模型。该查询将内部查询输出中的 input_idsattention_mask 列作为输入。

      SELECT 语句会检索 sentence_embedding 列,该列是一个 FLOAT 值数组,表示文本的语义嵌入。

      1. 在 Google Cloud 控制台中,打开 BigQuery Studio。

        进入 BigQuery Studio

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

        SELECT
        sentence_embedding
        FROM
        ML.PREDICT (MODEL `bqml_tutorial.all-MiniLM-L6-v2`,
          (
          SELECT
            input_ids, attention_mask
          FROM
            ML.PREDICT(MODEL `bqml_tutorial.tokenizer`,
              (
              SELECT
                title AS text
              FROM
                `bigquery-public-data.imdb.reviews` limit 10))))

        结果类似于以下内容:

        +-----------------------+
        | sentence_embedding    |
        +-----------------------+
        | -0.02361682802438736  |
        | 0.02025664784014225   |
        | 0.005168713629245758  |
        | -0.026361213997006416 |
        | 0.0655381828546524    |
        | ...                   |
        +-----------------------+
        

      bq

      使用 bq 命令行工具的 query 命令运行查询。该查询使用 ML.PREDICT 函数通过模型生成嵌入。

      该查询使用嵌套的 ML.PREDICT 调用,通过分词器和嵌入模型直接处理原始文本,如下所示:

      • 分词(内部查询):内部 ML.PREDICT 调用使用 bqml_tutorial.tokenizer 模型。它将 bigquery-public-data.imdb.reviews 公共数据集中的 title 列作为其 text 输入。 tokenizer 模型将原始文本字符串转换为主模型所需的数字令牌输入,包括 input_idsattention_mask 输入。
      • 嵌入生成(外部查询):外部 ML.PREDICT 调用使用 bqml_tutorial.all-MiniLM-L6-v2 模型。该查询将内部查询输出中的 input_idsattention_mask 列作为输入。

      SELECT 语句会检索 sentence_embedding 列,该列是一个 FLOAT 值数组,表示文本的语义嵌入。

      在命令行中,运行以下命令以运行查询。

      bq query --use_legacy_sql=false \
      'SELECT
      sentence_embedding
      FROM
      ML.PREDICT (MODEL `bqml_tutorial.all-MiniLM-L6-v2`,
        (
        SELECT
          input_ids, attention_mask
        FROM
          ML.PREDICT(MODEL `bqml_tutorial.tokenizer`,
            (
            SELECT
              title AS text
            FROM
              `bigquery-public-data.imdb.reviews` limit 10))))'

      结果类似于以下内容:

      +-----------------------+
      | sentence_embedding    |
      +-----------------------+
      | -0.02361682802438736  |
      | 0.02025664784014225   |
      | 0.005168713629245758  |
      | -0.026361213997006416 |
      | 0.0655381828546524    |
      | ...                   |
      +-----------------------+
      

      BigQuery DataFrame

      在尝试此示例之前,请按照《BigQuery 快速入门:使用 BigQuery DataFrames》中的 BigQuery DataFrames 设置说明进行操作。如需了解详情,请参阅 BigQuery DataFrames 参考文档

      如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为本地开发环境设置 ADC

      使用 predict 方法通过 ONNX 模型生成嵌入。

      import bigframes.pandas as bpd
      
      df = bpd.read_gbq("bigquery-public-data.imdb.reviews", max_results=10)
      df_pred = df.rename(columns={"title": "text"})
      tokens = tokenizer.predict(df_pred)
      predictions = imported_onnx_model.predict(tokens)
      predictions.peek(5)
      

      输出类似于以下内容:

      Transformer 模型的输出。

      清理

      为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

      删除项目

      控制台

      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.

      gcloud

      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.

      删除各个资源

      或者,如需移除本教程中使用的各个资源,请执行以下操作:

      1. 删除导入的模型

      2. 可选:删除数据集

      后续步骤