对文本嵌入调优

本页面介绍了如何对文本嵌入模型 textembedding-geckotextembedding-gecko-multilingual 调优。这些基础模型已使用大量公共文本数据进行训练。如果您的独特使用场景需要您自己的特定训练数据,则可以使用模型调优。对基础嵌入模型调优后,应根据您的应用场景量身定制模型。文本嵌入模型的稳定版本支持调优。

文本嵌入模型支持监督式调优。 监督式调优使用有标签样本,这些样本展示了您希望在推理期间从文本嵌入模型获得的输出类型。文本嵌入模型不支持使用基于人类反馈的强化学习 (RLHF) 进行调优。

如需详细了解模型调优,请参阅模型调优的工作原理

预期的质量改进

Vertex AI 使用参数高效调优方法进行自定义。在对公共检索基准数据集执行的实验中,此方法表现出高达 41%(平均 12%)的显著质量提升。

对嵌入模型调优的应用场景

通过对文本嵌入模型调优,您的模型可以适应特定领域或任务的嵌入。如果预训练的嵌入模型不能很好地满足您的特定需求,这将非常有用。例如,您可以针对公司的特定客户服务工单数据集微调嵌入模型。这有助于聊天机器人了解客户通常提出的各种客户服务问题,从而能够更有效地回答问题。如果不进行调优,模型将无法了解客户服务工单的具体细节,也不知道如何解决产品的具体问题。

调优工作流

Vertex AI 上 textembedding-geckotextembedding-gecko-multilingual 的模型调优工作流如下:

  • 准备模型调优数据集。
  • 将模型调优数据集上传到 Cloud Storage 存储桶。
  • 为 Vertex AI Pipelines 配置项目。
  • 创建模型调优作业。
  • 将调优后的模型部署到同名的 Vertex AI 端点。与文本或 Codey 模型调优作业不同,文本嵌入调优作业不会将调优后的模型部署到 Vertex AI 端点。

准备嵌入数据集

用于对嵌入模型调优的数据集包括与您希望模型执行的任务相配的数据。

用于对嵌入模型调优的数据集格式

训练数据集包含以下文件,这些文件需要位于 Cloud Storage 中。文件的路径在启动调优流水线时由参数定义。这三种类型的文件是语料库文件查询文件标签。只有训练标签是必需的,但您也可以提供验证和测试标签,以实现更好的控制。

  • 语料库文件:路径由参数 corpus_path 定义。这是一个 JSONL 文件,其中每一行都包含具有字符串值的字段 _idtitletext_idtext 是必需的,而 title 是可选的。下面是一个示例 corpus.jsonl 文件:

    {"_id": "doc1", "title": "Get an introduction to generative AI on Vertex AI", "text": "Vertex AI's Generative AI Studio offers a Google Cloud console tool for rapidly prototyping and testing generative AI models. Learn how you can use Generative AI Studio to test models using prompt samples, design and save prompts, tune a foundation model, and convert between speech and text."}
    {"_id": "doc2", "title": "Use gen AI for summarization, classification, and extraction", "text": "Learn how to create text prompts for handling any number of tasks with Vertex AI's generative AI support. Some of the most common tasks are classification, summarization, and extraction. Vertex AI's PaLM API for text lets you design prompts with flexibility in terms of their structure and format."}
    {"_id": "doc3", "title": "Custom ML training overview and documentation", "text": "Get an overview of the custom training workflow in Vertex AI, the benefits of custom training, and the various training options that are available. This page also details every step involved in the ML training workflow from preparing data to predictions."}
    {"_id": "doc4", "text": "Text embeddings are useful for clustering, information retrieval, retrieval-augmented generation (RAG), and more."}
    {"_id": "doc5", "title": "Text embedding tuning", "text": "Google's text embedding models can be tuned on Vertex AI."}
    
  • 查询文件:查询文件包含您的示例查询。该路径由参数 queries_path 定义。查询文件采用 JSONL 格式,并且与语料库文件具有相同的字段。下面是一个示例 queries.jsonl 文件:

    {"_id": "query1", "text": "Does Vertex support generative AI?"}
    {"_id": "query2", "text": "What can I do with Vertex GenAI offerings?"}
    {"_id": "query3", "text": "How do I train my models using Vertex?"}
    {"_id": "query4", "text": "What is a text embedding?"}
    {"_id": "query5", "text": "Can text embedding models be tuned on Vertex?"}
    {"_id": "query6", "text": "embeddings"}
    {"_id": "query7", "text": "embeddings for rag"}
    {"_id": "query8", "text": "custom model training"}
    {"_id": "query9", "text": "Google Cloud PaLM API"}
    
  • 训练标签:路径由参数 train_label_path 定义。train_label_path 是训练标签数据位置的 Cloud Storage URI,在创建调优作业时指定。标签必须是带有标题的 TSV 文件。您的训练标签文件中必须包含一部分查询和语料库。该文件必须包含 query-idcorpus-idscore 列。query-id 是一个字符串,与查询文件中的 _id 键匹配,corpus-id 是一个字符串,与语料库文件中的 _id 匹配。Score 是非负整数值。任何大于零的分数都表示文档与查询相关。数字越大表示相关性越高。如果省略得分,则默认值为 1。下面是一个示例 train_labels.tsv 文件:

    query-id  corpus-id   score
    query1    doc1    1
    query2    doc2    1
    query3    doc3    2
    query3    doc5  1
    query4    doc4  1
    query4    doc5  1
    query5    doc5  2
    query6    doc4  1
    query6    doc5  1
    query7    doc4  1
    query8    doc3  1
    query9    doc2  1
    
  • 测试标签:可选。测试标签的格式与训练标签的格式相同,并由 test_label_path 参数指定。如果未提供 test_label_path,则测试标签将自动与训练标签拆分。

  • 验证标签:可选。验证标签的格式与训练标签的格式相同,并由 validation_label_path 参数指定。如果未提供 validation_label_path,则验证标签将自动与训练标签拆分。

数据集大小要求

提供的数据集文件必须满足以下限制条件:

  • 查询数必须介于 9 到 40,000 之间。

  • 语料库中的文档数必须介于 9 到 500,000 之间。

  • 每个数据集标签文件必须至少包含 3 个查询 ID,并且在所有数据集拆分中必须至少有 9 个查询 ID。

  • 标签总数必须小于 500,000。

为 Vertex AI Pipelines 配置项目

使用 Vertex AI Pipelines 平台在项目中执行调优。

配置权限

流水线在两个 Google 管理的服务账号下执行训练代码。这些账号必须配置特定权限。

Compute Engine 默认服务账号
PROJECT_NUMBER-compute@developer.gserviceaccount.com

此服务账号需要:

  • 对您在 Cloud Storage 中创建的每个数据集文件的 Storage Object Viewer 权限。

  • 对流水线的输出 Cloud Storage 目录 PIPELINE_OUTPUT_DIRECTORYStorage Object User 权限。

  • 对项目的 Vertex AI User 权限。

您可以不使用 Compute Engine 默认服务账号,而是指定自定义服务账号。如需了解详情,请参阅配置具有精细权限的服务账号

Vertex AI Service Agent
service-PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com

此服务账号需要:

  • 对您在 Cloud Storage 中创建的每个数据集文件的 Storage Object Viewer 权限。

  • 对流水线的输出 Cloud Storage 目录 PIPELINE_OUTPUT_DIRECTORYStorage Object User 权限。

如需详细了解如何配置 Cloud Storage 数据集权限,请参阅为流水线工件配置 Cloud Storage 存储桶

使用加速器

以下任一加速器都可用于调优:

  • NVIDIA_L4

  • NVIDIA_TESLA_A100

  • NVIDIA_TESLA_T4

  • NVIDIA_TESLA_V100

  • NVIDIA_TESLA_P100

如要启动调优作业,您选择的加速器类型和区域需要有足够的 Restricted image training GPUs 配额,例如 Restricted image training Nvidia V100 GPUs per region。如需提高项目的配额,请参阅申请更多配额

并非每个区域都提供所有加速器。如需了解详情,请参阅在 Vertex AI 中使用加速器

创建嵌入模型调优作业

您可以使用 Google Cloud 控制台或 REST API 创建嵌入模型调优作业。

REST

在使用任何请求数据之前,请先进行以下替换:

  • DISPLAY_NAME:pipelineJob 的显示名称。
  • PIPELINE_OUTPUT_DIRECTORY:流水线输出工件的路径,以“gs://”开头。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
  • LOCATION:运行流水线的 Google Cloud 项目区域。项目具有足够 GPU 配额的任何区域都支持调优。如需了解详情,请参阅使用加速器。由于其他区域的服务资源可能有限,因此建议使用 us-central1
  • QUERIES_PATH:存储查询数据的 Cloud Storage 存储桶的 URI,以“gs://”开头。
  • CORPUS_PATH:语料库数据的 Cloud Storage URI,以“gs://”开头。
  • TRAIN_LABEL_PATH:训练标签数据位置的 Cloud Storage URI,以“gs://”开头。
  • TEST_LABEL_PATH:可选。测试标签数据位置的 Cloud Storage URI,以“gs://”开头。传递空字符串将指示流水线从训练数据集中自动拆分测试数据集。
  • VALIDATION_LABEL_PATH:可选。验证标签数据位置的 Cloud Storage URI,以“gs://”开头。传递空字符串将指示流水线从训练数据集中自动拆分验证数据集。
  • ACCELERATOR_TYPE:可选。用于训练的加速器类型。默认值为 NVIDIA_TESLA_V100。如需了解可能的值,请参阅使用加速器
  • ACCELERATOR_COUNT:可选。训练时要使用的加速器数量。使用更多的加速器可以加快训练速度,但对质量没有影响。默认值为 4。
  • MACHINE_TYPE:可选。用于训练的机器类型。默认值为 n1-standard-16。如需了解如何选择与您选择的加速器类型和数量匹配的机器类型,请参阅 GPU 平台
  • BASE_MODEL_VERSION_ID:可选。使用此参数指定要进行调优的文本嵌入模型。默认值为 textembedding-gecko@001。如需了解可能的值,请参阅稳定版本
  • MODEL_DISPLAY_NAME:可选。经调优的模型在 Model Registry 中显示时的显示名称。默认为“tuned-text-embedding-model”。
  • TASK_TYPE:可选。设置此参数可针对特定下游任务优化调优模型。 默认值为 DEFAULT。如需了解详情,请参阅获取文本嵌入
  • BATCH_SIZE:可选。训练批次大小。默认值为 128。
  • ITERATIONS:可选。执行模型调优的步骤数。默认为 1,000,并且必须大于 30。

HTTP 方法和网址:

POST https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/pipelineJobs

请求 JSON 正文:

{
  "displayName": "DISPLAY_NAME",
  "runtimeConfig": {
    "gcsOutputDirectory": "PIPELINE_OUTPUT_DIRECTORY",
    "parameterValues": {
      "project": "PROJECT_ID",
      "location": "LOCATION",
      "queries_path": "QUERIES_PATH",
      "corpus_path": "CORPUS_PATH",
      "train_label_path": "TRAIN_LABEL_PATH",
      "test_label_path": "TEST_LABEL_PATH",
      "validation_label_path": "VALIDATION_LABEL_PATH",
      "accelerator_type": "ACCELERATOR_TYPE",
      "accelerator_count": "ACCELERATOR_COUNT",
      "machine_type": "MACHINE_TYPE",
      "base_model_version_id": "BASE_MODEL_VERSION_ID",
      "model_display_name": "MODEL_DISPLAY_NAME",
      "task_type": "TASK_TYPE",
      "batch_size": "BATCH_SIZE",
      "iterations": "ITERATIONS"
    }
  },
  "templateUri": "https://us-kfp.pkg.dev/ml-pipeline/llm-text-embedding/tune-text-embedding-model/v1.1.2"
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

启动流水线后,通过 Google Cloud 控制台跟踪调节作业的进度。

前往 Google Cloud 控制台

Java

在尝试此示例之前,请按照《Vertex AI 快速入门:使用客户端库》中的 Java 设置说明执行操作。如需了解详情,请参阅 Vertex AI Java API 参考文档

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

package aiplatform;

// [START aiplatform_sdk_embedding_tuning]
import com.google.cloud.aiplatform.v1beta1.CreatePipelineJobRequest;
import com.google.cloud.aiplatform.v1beta1.LocationName;
import com.google.cloud.aiplatform.v1beta1.PipelineJob;
import com.google.cloud.aiplatform.v1beta1.PipelineJob.RuntimeConfig;
import com.google.cloud.aiplatform.v1beta1.PipelineServiceClient;
import com.google.cloud.aiplatform.v1beta1.PipelineServiceSettings;
import com.google.protobuf.Value;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class CreatePipelineJobEmbeddingModelTuningSample {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String project = "PROJECT";
    String baseModelVersionId = "BASE_MODEL_VERSION_ID";
    String taskType = "TASK_TYPE";
    String location = "us-central1";
    String pipelineJobDisplayName = "PIPELINE_JOB_DISPLAY_NAME";
    String modelDisplayName = "MODEL_DISPLAY_NAME";
    String outputDir = "OUTPUT_DIR";
    String queriesPath = "DATASET_URI";
    String corpusPath = "DATASET_URI";
    String trainLabelPath = "DATASET_URI";
    String testLabelPath = "DATASET_URI";
    int batchSize = 50;
    int iterations = 300;

    createPipelineJobEmbeddingModelTuningSample(
        project,
        baseModelVersionId,
        taskType,
        location,
        pipelineJobDisplayName,
        modelDisplayName,
        outputDir,
        queriesPath,
        corpusPath,
        trainLabelPath,
        testLabelPath,
        batchSize,
        iterations);
  }

  // Create a model tuning job
  public static void createPipelineJobEmbeddingModelTuningSample(
      String project,
      String baseModelVersionId,
      String taskType,
      String location,
      String pipelineJobDisplayName,
      String modelDisplayName,
      String outputDir,
      String queriesPath,
      String corpusPath,
      String trainLabelPath,
      String testLabelPath,
      int batchSize,
      int iterations)
      throws IOException {
    final String endpoint = String.format("%s-aiplatform.googleapis.com:443", location);
    PipelineServiceSettings pipelineServiceSettings =
        PipelineServiceSettings.newBuilder().setEndpoint(endpoint).build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (PipelineServiceClient client = PipelineServiceClient.create(pipelineServiceSettings)) {
      Map<String, Value> parameterValues = new HashMap<>();
      parameterValues.put("project", stringToValue(project));
      parameterValues.put("base_model_version_id", stringToValue(baseModelVersionId));
      parameterValues.put("task_type", stringToValue(taskType));
      parameterValues.put(
          "location",
          stringToValue(
              "us-central1")); // Deployment is only supported in us-central1.
      parameterValues.put("queries_path", stringToValue(queriesPath));
      parameterValues.put("corpus_path", stringToValue(corpusPath));
      parameterValues.put("train_label_path", stringToValue(trainLabelPath));
      parameterValues.put("test_label_path", stringToValue(testLabelPath));
      parameterValues.put("batch_size", numberToValue(batchSize));
      parameterValues.put("iterations", numberToValue(iterations));

      RuntimeConfig runtimeConfig =
          RuntimeConfig.newBuilder()
              .setGcsOutputDirectory(outputDir)
              .putAllParameterValues(parameterValues)
              .build();

      PipelineJob pipelineJob =
          PipelineJob.newBuilder()
              .setTemplateUri(
                  "https://us-kfp.pkg.dev/ml-pipeline/llm-text-embedding/tune-text-embedding-model/v1.1.2")
              .setDisplayName(pipelineJobDisplayName)
              .setRuntimeConfig(runtimeConfig)
              .build();

      LocationName parent = LocationName.of(project, location);
      CreatePipelineJobRequest request =
          CreatePipelineJobRequest.newBuilder()
              .setParent(parent.toString())
              .setPipelineJob(pipelineJob)
              .build();

      PipelineJob response = client.createPipelineJob(request);
      System.out.format("response: %s\n", response);
      System.out.format("Name: %s\n", response.getName());
    }
  }

  static Value stringToValue(String str) {
    return Value.newBuilder().setStringValue(str).build();
  }

  static Value numberToValue(int n) {
    return Value.newBuilder().setNumberValue(n).build();
  }
}

// [END aiplatform_sdk_embedding_tuning]

控制台

如需使用 Google Cloud 控制台调优文本嵌入模型,您可以按照以下步骤启动自定义流水线:

  1. 在 Google Cloud 控制台的 Vertex AI 部分中,进入 Vertex AI Pipelines 页面。

    前往 Vertex AI Pipelines

  2. 点击创建运行作业以打开创建流水线运行作业窗格。
  3. 点击从现有流水线中选择,然后输入以下详细信息:
    1. 选择资源下拉列表中选择“ml-pipeline”。
    2. 仓库下拉列表中选择“llm-text-embedding”。
    3. 流水线或组件下拉列表中选择“tune-text-embedding-model”。
    4. 版本下拉列表中选择标记为“v1.1.2”的版本。
  4. 指定运行名称以唯一标识流水线运行。
  5. 区域下拉列表中,选择区域以创建流水线运行。 目前仅支持 us-central1。
  6. 点击继续。此时会显示运行时配置窗格。
  7. Cloud Storage 位置下,点击浏览以选择用于存储流水线输出工件的 Cloud Storage 存储桶,然后点击选择
  8. 流水线参数下,指定用于调优流水线的参数。如需了解这些参数的含义,请参阅 REST 文档。
  9. 点击提交以创建流水线运行。

示例 curl 命令

PROJECT_ID=PROJECT_ID
LOCATION=LOCATION
BASE_MODEL_VERSION_ID=BASE_MODEL_VERSION_ID
PIPELINE_OUTPUT_DIRECTORY=PIPELINE_OUTPUT_DIRECTORY
QUERIES_PATH=QUERIES_PATH
CORPUS_PATH=CORPUS_PATH
TRAIN_LABEL_PATH=TRAIN_LABEL_PATH

curl -X POST  \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json; charset=utf-8" \
"https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/pipelineJobs?pipelineJobId=tune-text-embedding-$(date +%Y%m%d%H%M%S)" \
-d '{
  "displayName": "tune-text-embedding-model",
  "runtimeConfig": {
    "gcsOutputDirectory": "'${PIPELINE_OUTPUT_DIRECTORY}'",
    "parameterValues": {
      "project":  "'${PROJECT_ID}'",
      "base_model_version_id":  "'${BASE_MODEL_VERSION_ID}'",
      "location":   "'${LOCATION}'",
      "queries_path":  "'${QUERIES_PATH}'",
      "corpus_path":  "'${CORPUS_PATH}'",
      "train_label_path":  "'${TRAIN_LABEL_PATH}'"
    }
  },
  "templateUri": "https://us-kfp.pkg.dev/ml-pipeline/llm-text-embedding/tune-text-embedding-model/v1.1.2"
}'

使用调优后的模型

在 Model Registry 中查看经过调优的模型

调优作业完成后,调优后的模型不会自动部署到端点。它将作为 Model Registry 中的模型资源提供。您可以使用 Google Cloud 控制台查看当前项目中的模型列表,包括已调优的模型。

如需在 Google Cloud 控制台中查看调优后模型,请进入 Vertex AI Model Registry 页面。

进入 Vertex AI Model Registry

部署模型

对嵌入模型调优后,您需要部署模型资源。如需部署调优后的嵌入模型,请参阅将模型部署到端点

与基础模型不同,调优后的文本嵌入模型由用户管理。这包括管理机器类型和加速器等服务资源。为防止在预测期间出现内存不足错误,建议您使用 NVIDIA_TESLA_A100 GPU 类型进行部署,该类型可支持任何输入长度大小不超过 5 的批量大小。

textembedding-gecko 基础模型类似,调优后的模型支持多达 3072 个词元,并且可以截取更长的输入。

使用部署的模型获取预测结果

部署经过调优的模型后,您可以使用以下命令之一向调优后的模型端点发出请求。

调优后的 textembedding-gecko@001 模型的 curl 命令示例

如需使用 textembedding-gecko@001 的调优后版本获取预测结果,请使用以下示例 curl 命令。

PROJECT_ID=PROJECT_ID
LOCATION=LOCATION
ENDPOINT_URI=https://${LOCATION}-aiplatform.googleapis.com
MODEL_ENDPOINT=TUNED_MODEL_ENDPOINT_ID

curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json"  \
    ${ENDPOINT_URI}/v1/projects/${PROJECT_ID}/locations/${LOCATION}/endpoints/${MODEL_ENDPOINT}:predict \
    -d '{
  "instances": [
    {
      "content": "Dining in New York City"
    },
    {
      "content": "Best resorts on the east coast"
    }
  ]
}'

textembedding-gecko@001 模型的 curl 命令示例

其他模型的调优后版本(例如 textembedding-gecko@003textembedding-gecko-multilingual@001)还需要另外两个输入:task_typetitle。如需详细了解这些参数,请参阅 curl 命令

PROJECT_ID=PROJECT_ID
LOCATION=LOCATION
ENDPOINT_URI=https://${LOCATION}-aiplatform.googleapis.com
MODEL_ENDPOINT=TUNED_MODEL_ENDPOINT_ID

curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json"  \
    ${ENDPOINT_URI}/v1/projects/${PROJECT_ID}/locations/${LOCATION}/endpoints/${MODEL_ENDPOINT}:predict \
    -d '{
  "instances": [
    {
      "content": "Dining in New York City",
      "task_type": "DEFAULT",
      "title": ""
    },
    {
      "content": "There are many resorts to choose from on the East coast...",
      "task_type": "RETRIEVAL_DOCUMENT",
      "title": "East Coast Resorts"
    }
  ]
}'

输出示例

无论什么版本,此输出都适用于 textembedding-geckotextembedding-gecko-multilingual 模型。

{
 "predictions": [
   [ ... ],
   [ ... ],
   ...
 ],
 "deployedModelId": "...",
 "model": "projects/.../locations/.../models/...",
 "modelDisplayName": "tuned-text-embedding-model",
 "modelVersionId": "1"
}

后续步骤