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

本教學課程說明如何將 Transformer 模型匯出為開放式神經網路交換 (ONNX) 格式、將 ONNX 模型匯入 BigQuery 資料集,然後使用該模型透過 SQL 查詢產生嵌入。

本教學課程使用 sentence-transformers/all-MiniLM-L6-v2 模型。這個句子 Transformer 模型以快速且有效率地生成句子嵌入而聞名。句子嵌入可擷取文字的深層含義,因此能執行語意搜尋、叢集和句子相似度等工作。

ONNX 提供統一格式,可用於表示任何機器學習 (ML) 架構。BigQuery ML 支援 ONNX,因此您可以執行下列操作:

  • 使用您偏好的架構訓練模型。
  • 將模型轉換為 ONNX 模型格式。
  • 將 ONNX 模型匯入 BigQuery,並使用 BigQuery ML 進行預測。

將 Transformer 模型檔案轉換為 ONNX

您也可以選擇按照本節的步驟,手動將 sentence-transformers/all-MiniLM-L6-v2 模型和權杖化工具轉換為 ONNX。否則,您可以使用公開 gs://cloud-samples-dataCloud 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. 在「Explorer」窗格中,按一下專案名稱。

  3. 依序點按 「View actions」(查看動作) >「Create dataset」(建立資料集)

  4. 在「建立資料集」頁面中,執行下列操作:

    • 在「Dataset ID」(資料集 ID) 中輸入 bqml_tutorial

    • 針對「Location type」(位置類型) 選取「Multi-region」(多區域),然後選取「US (multiple regions in United States)」(us (多個美國區域))

    • 其餘設定請保留預設狀態,然後按一下「建立資料集」

bq

如要建立新的資料集,請使用 bq mk 指令搭配 --location 旗標。如需可能的完整參數清單,請參閱 bq mk --dataset 指令參考資料。

  1. 建立名為「bqml_tutorial」的資料集,並將資料位置設為「US」,說明則設為「BigQuery ML tutorial dataset」:

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

    這個指令採用 -d 捷徑,而不是使用 --dataset 旗標。如果您省略 -d--dataset,該指令預設會建立資料集。

  2. 確認資料集已建立完成:

    bq ls

API

請呼叫 datasets.insert 方法,搭配已定義的資料集資源

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

BigQuery DataFrames

在嘗試這個範例之前,請按照使用 BigQuery DataFrames 的 BigQuery 快速入門導覽課程中的 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. 查看「特徵欄」部分,瞭解模型輸入內容,並查看「標籤欄」部分,瞭解模型輸出內容。

    `tokenizer 模型的「詳細資料」窗格

  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 DataFrames

在嘗試這個範例之前,請按照使用 BigQuery DataFrames 的 BigQuery 快速入門導覽課程中的 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 DataFrames

在嘗試這個範例之前,請按照使用 BigQuery DataFrames 的 BigQuery 快速入門導覽課程中的 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 模型的輸出內容。