你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

通过微调自定义模型

借助 Azure OpenAI 服务,你可以使用称为“微调”的过程根据个人数据集定制模型。 通过此自定义步骤,你可以更充分地利用服务,获得以下好处:

  • 结果的质量比从提示工程中获取的质量更高
  • 能够根据超出模型最大请求上下文限制的更多示例进行训练。
  • 由于提示较短,节省了令牌
  • 更低延迟的请求,尤其是在使用较小的模型时。

与少样本学习相比,微调通过训练超出提示范围的更多示例来改进模型,从而让你在处理大量任务时取得更好的结果。 由于微调会调整基本模型的权重以提高特定任务的性能,因此无需在提示中包含过多的示例或说明。 这意味着发送的文本更少,每次 API 调用处理的令牌更少,从而可能节省成本并改善请求延迟。

我们使用 LoRA(即低秩近似)来微调模型,以降低其复杂性而不显著影响其性能。 此方法的工作原理是用较低秩的矩阵来近似原始的高秩矩阵,因此在监督训练阶段仅微调较小的“重要”参数子集,从而使模型更易于管理和高效。 对于用户,这使得训练比其他技术更快、更经济实惠。

先决条件

注意

目前,必须提交应用程序才能访问 Azure OpenAI 服务。 若要申请访问权限,请填写此表单

模型

以下模型支持微调:

  • babbage-002
  • davinci-002
  • gpt-35-turbo (0613)
  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)

请参阅模型页,以查看当前支持微调的区域。

审阅 Azure OpenAI Studio 的工作流

花点时间审阅用于 Azure OpenAI Studio 的微调工作流:

  1. 准备训练和验证数据。
  2. 使用 Azure OpenAI Studio 中的“创建自定义模型”向导来训练自定义模型。
    1. 选择基础模型
    2. 选择训练数据
    3. (可选)选择验证数据
    4. (可选)为微调作业配置高级选项
    5. 审阅所做的选择并训练新的自定义模型
  3. 检查自定义微调模型的状态。
  4. 部署自定义模型以供使用。
  5. 使用自定义模型。
  6. (可选)分析自定义模型的性能和拟合度。

准备训练和验证数据

训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。

不同的模型类型需要不同格式的训练数据。

你使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档。 对于 gpt-35-turbo-0613,必须以聊天补全 API 使用的对话格式来设置微调数据集的格式。

如果想要了解有关微调 gpt-35-turbo-0613 模型的逐步演练,请参阅 Azure OpenAI 微调教程

示例文件格式

{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Is Xbox better than PlayStation?"}, {"role": "assistant", "content": "I apologize, but I cannot provide personal opinions. My primary job is to assist you with any issues related to your Xbox device. Do you have any Xbox-related issues that need addressing?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Can I play PC games on my Xbox?"}, {"role": "assistant", "content": "While Xbox consoles don't natively support PC games, they can play an array of Xbox games, many of which are also available on PC. Can I assist you with finding games compatible with your Xbox device?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "I'm having trouble connecting my Xbox to the Wi-Fi."}, {"role": "assistant", "content": "No worries, let's go through the network settings on your Xbox. Can you please tell me what happens when you try to connect it to the Wi-Fi?"}]}

多轮次聊天文件格式

还支持在 jsonl 训练文件单行中的多轮次对话。 要跳过对特定助手消息的微调,请添加可选的 weight 键值对。 目前,weight 可设置为 0 或 1。

{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already.", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "William Shakespeare", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "384,400 kilometers", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters.", "weight": 1}]}

除 JSONL 格式外,训练和验证数据文件必须以 UTF-8 编码并包含字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

创建训练和验证数据集

训练示例越多越好。 如果没有至少 10 个训练示例,微调作业将无法继续,但如此少的数量不足以显著影响模型响应。 最佳做法是提供数百个(如果不是数千个)训练示例来获得成功。

通常,将数据集大小加倍会促使模型质量呈线性增长。 但请记住,低质量的示例可能会对性能产生负面影响。 如果你根据大量内部数据来训练模型,而不是先修剪数据集以便获得最高质量的示例,则最终可能会得到一个性能比预期差得多的模型。

使用“创建自定义模型”向导

Azure OpenAI Studio 提供了“创建自定义模型”向导,让你能够以交互方式为 Azure 资源创建和训练已微调的模型。

  1. 打开 Azure OpenAI Studio (https://oai.azure.com/),然后使用有权访问 Azure OpenAI 资源的凭据登录。 在登录工作流中,选择适当的目录、Azure 订阅和 Azure OpenAI 资源。

  2. 在 Azure OpenAI Studio 中,浏览到“管理”>“模型”窗格,然后选择“创建自定义模型”。

    显示如何访问 Azure OpenAI Studio 中的“创建自定义模型”向导的屏幕截图。

随即将打开“创建自定义模型”向导。

选择基础模型

选择基础模型是创建自定义模型的第一步。 你可通过“基础模型”窗格选择用于自定义模型的基础模型。 所做的选择会影响模型的性能和成本。

从“基础模型类型”下拉列表中选择基础模型,然后选择“下一步”以继续。

可从以下可用基础模型之一创建自定义模型:

  • babbage-002

  • davinci-002

  • gpt-35-turbo (0613)

  • gpt-35-turbo (1106)

  • 或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}。

具有自定义微调模型的模型选项屏幕截图。

有关可进行优化的基本模型的详细信息,请参阅模型

选择训练数据

下一步是选择已准备好的现有训练数据或上传已准备好的新训练数据,以便在自定义模型时使用。 “训练数据”窗格显示了任何现有的和以前上传的数据集,并提供了用于上传新训练数据的选项。

Azure OpenAI Studio 中“创建自定义模型”向导的“训练数据”窗格的屏幕截图。

对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。 有关 Azure Blob 存储的详细信息,请参阅什么是 Azure Blob 存储?

注意

训练数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

从本地文件上传训练数据

可使用以下方法之一将新的训练数据集从本地文件上传到服务:

  • 将文件拖放到“训练数据”窗格的工作区中,然后选择“上传文件”。

  • 在“训练数据”窗格的工作区中选择“浏览文件”,在“打开”对话框中选择要上传的文件,然后选择“上传文件”。

选择并上传训练数据集后,选择“下一步”继续。

“创建自定义模型”向导的“训练数据”窗格的屏幕截图,其中显示了本地文件选项。

从 Azure Blob 存储导入训练数据

可通过提供文件的名称和位置从 Azure Blob 或其他共享 Web 位置导入训练数据集。

  1. 输入文件的文件名。

  2. 对于“文件位置”,请提供 Azure Blob URL、Azure 存储共享访问签名 (SAS) 或其他指向可访问共享 Web 位置的链接。

  3. 选择“上传文件”,将训练数据集导入服务。

选择并上传训练数据集后,选择“下一步”继续。

“创建自定义模型”向导的“训练数据”窗格的屏幕截图,其中显示了 Azure Blob 和共享 Web 位置选项。

选择验证数据

下一步提供配置模型以在训练过程中使用验证数据的选项。 如果你不想使用验证数据,可以选择“下一步”为模型选择高级选项。 否则,如果你有验证数据集,可以选择已准备好的现有验证数据或上传已准备好的新验证数据,以便在自定义模型时使用。

“验证数据”窗格显示了任何现有的及以前上传的训练和验证数据集,并提供了用于上传新验证数据的选项。

Azure OpenAI Studio 中“创建自定义模型”向导的“验证数据”窗格的屏幕截图。

对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。

注意

与训练数据文件类似,验证数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

从本地文件上传验证数据

可使用以下方法之一将新的验证数据集从本地文件上传到服务:

  • 将文件拖放到“验证数据”窗格的工作区中,然后选择“上传文件”。

  • 在“验证数据”窗格的工作区中选择“浏览文件”,在“打开”对话框中选择要上传的文件,然后选择“上传文件”。

选择并上传验证数据集后,选择“下一步”继续。

“创建自定义模型”向导的“验证数据”窗格的屏幕截图,其中显示了本地文件选项。

从 Azure Blob 存储导入验证数据

可通过提供文件的名称和位置从 Azure Blob 或其他共享 Web 位置导入验证数据集。

  1. 输入文件的文件名。

  2. 对于“文件位置”,请提供 Azure Blob URL、Azure 存储共享访问签名 (SAS) 或其他指向可访问共享 Web 位置的链接。

  3. 选择“上传文件”,将训练数据集导入服务。

选择并上传验证数据集后,选择“下一步”继续。

“创建自定义模型”向导的“验证数据”窗格的屏幕截图,其中显示了 Azure Blob 和共享 Web 位置选项。

配置高级选项

创建自定义模型”向导在“高级选项”窗格中显示用于训练已微调的模型的超参数。 可使用以下超参数:

Name 类型 描述
batch_size integer 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。
learning_rate_multiplier 数字 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。
n_epochs integer 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。

“创建自定义模型”向导的“高级选项”窗格的屏幕截图,其中选择了默认选项。

选择“默认”以便对微调作业使用默认值,或选择“高级”以显示并编辑超参数值。 选择默认值后,我们会根据训练数据通过算法确定正确的值。

配置高级选项后,选择“下一步”以审阅所做的选择并训练已微调的模型

查看所做的选择并训练模型

向导的“审阅”窗格显示有关配置选项的信息。

Azure OpenAI Studio 中“创建自定义模型”向导的“审阅”窗格的屏幕截图。

如果已准备好训练模型,请选择“开始训练作业”,以启动微调作业并返回到“模型”窗格。

检查自定义模型的状态

“模型”窗格在“自定义模型”选项卡中显示有关自定义模型的信息。该选项卡包含有关自定义模型的微调作业的状态和作业 ID 信息。 作业完成后,选项卡会显示结果文件的文件 ID。 可能需要选择“刷新”才能看到模型训练作业的更新状态。

Azure OpenAI Studio 中的“模型”页的屏幕截图,其中显示了自定义模型。

启动微调作业后,可能需要一些时间才能完成。 你的作业可能排在系统上的其他作业后面。 训练模型可能需要几分钟或几小时,具体取决于模型和数据集大小。

可在“模型”窗格上执行以下任务:

  • 在“自定义模型”选项卡的“状态”列中检查自定义模型的微调作业的状态。

  • 在“模型名称”列中,选择模型名称以查看有关自定义模型的详细信息。 可以查看微调作业的状态、训练结果、训练事件和作业中使用的超参数。

  • 选择“下载训练文件”以下载用于模型的训练数据。

  • 选择“下载结果”,下载附加到模型微调作业的结果文件,并分析自定义模型的训练和验证性能。

  • 选择“刷新”更新页面信息。

Azure OpenAI Studio 中的“模型”页的屏幕截图,其中显示了自定义模型。

部署自定义模型

微调作业成功后,可以从“模型”窗格部署自定义模型。 必须部署自定义模型才能使其可用于完成调用。

重要

在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。

删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure OpenAI 服务定价中所述,部署的每个自定义(微调)模型都会产生每小时的托管成本,无论是否对模型进行补全或聊天补全调用,都是如此。 要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅计划管理 Azure OpenAI 服务的成本中的指南。

注意

自定义模型只允许一个部署。 如果选择已部署的自定义模型,会显示错误消息。

要部署自定义模型,请选择要部署的自定义模型,然后选择“部署模型”。

显示如何在 Azure OpenAI Studio 中部署自定义模型的屏幕截图。

此时会打开“部署模型”对话框。 在该对话框中,输入部署名称,然后选择“创建”,开始部署自定义模型。

Azure OpenAI Studio 中的“部署模型”对话框的屏幕截图。

可在 Azure OpenAI Studio 的“部署”窗格中监视部署进度。

跨区域部署

微调支持将微调后的模型部署到与模型最初进行微调时所在的区域不同的区域。 还可以部署到其他订阅/区域。

唯一的限制是新区域还必须支持微调,并且在部署交叉订阅时为部署生成授权令牌的帐户必须有权访问源订阅和目标订阅。

跨订阅/区域部署可以通过 PythonREST 完成。

使用已部署的自定义模型

部署自定义模型后,可像使用任何其他已部署的模型一样使用它。 可使用 Azure OpenAI Studio 中的“操场”来试验新部署。 可以继续对自定义模型使用相同的参数,例如 temperaturemax_tokens,就像对其他已部署的模型一样。 对于微调的 babbage-002davinci-002 模型,将使用“补全”操场和补全 API。 对于微调的 gpt-35-turbo-0613 模型,将使用“聊天”操场和聊天补全 API。

Azure OpenAI Studio 的“操场”页的屏幕截图,其中突出显示了某些部分。

分析自定义模型

完成每个微调作业后,Azure OpenAI 会将一个名为 results.csv 的结果文件附加到该作业。 可以使用该结果文件来分析自定义模型的训练和验证性能。 Azure OpenAI Studio 的“模型”窗格的“结果文件 ID”列中,列出了每个自定义模型的结果文件的文件 ID。 可以使用文件 ID 从 Azure OpenAI Studio 的“数据文件”窗格中识别和下载结果文件。

结果文件是一个 CSV 文件,其中包含标题行,以及微调作业执行的每个训练步骤的行。 结果文件包含以下列:

列名称 说明
step 训练步数。 一个训练步骤代表针对一批训练数据的一次向前和向后的传递。
train_loss 训练批的损失。
training_accuracy 训练批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
train_mean_token_accuracy 训练批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。
valid_loss 验证批的损失。
valid_accuracy 验证批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
validation_mean_token_accuracy 验证批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。

还可以在 Azure OpenAI Studio 中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。

随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。

清理部署、自定义模型和训练文件

处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。

删除模型部署

重要

在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。

删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure OpenAI 服务定价中所述,部署的每个自定义(微调)模型都会产生每小时的托管成本,无论是否对模型进行补全或聊天补全调用,都是如此。 要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅计划管理 Azure OpenAI 服务的成本中的指南。

可在 Azure OpenAI Studio 的“部署”页中删除自定义模型的部署。 选择要删除的部署,然后选择“删除”以删除部署。

删除自定义模型

可在 Azure OpenAI Studio 的“模型”窗格中删除自定义模型。 在“自定义模型”选项卡中选择要删除的自定义模型,然后选择“删除”以删除该自定义模型。

注意

如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。

删除训练文件

可选择性地在 Azure OpenAI Studio 的“管理”>“数据文件”窗格中删除为训练上传的训练和验证文件,以及在训练期间生成的结果文件。 选择要删除的文件,然后选择“删除”以删除该文件。

持续微调

创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。

若要对之前微调过的模型执行微调,可以使用创建自定义模型中所述的流程,但无需指定通用基础模型的名称,而只需指定已微调的模型。 自定义微调模型将类似于 gpt-35-turbo-0613.ft-5fd1918ee65d4cd38a5dcf6835066ed7

“创建自定义模型 UI”的屏幕截图,其中突出显示了微调模型。

我们还建议添加 suffix 参数,以便更轻松地区分已微调模型的不同迭代。 suffix 接受一个字符串,并设置为标识已微调的模型。 OpenAI Python API 支持最多 18 个字符的字符串,该字符串将添加到已微调的模型名称中。

先决条件

注意

目前,必须提交应用程序才能访问 Azure OpenAI 服务。 若要申请访问权限,请填写此表单

模型

以下模型支持微调:

  • babbage-002
  • davinci-002
  • gpt-35-turbo (0613)
  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)

或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}。

具有自定义微调模型的模型选项屏幕截图。

请参阅模型页,以查看当前支持微调的区域。

审阅 Python SDK 的工作流

花点时间审阅将 Python SDK 与 Azure OpenAI 配合使用的微调工作流:

  1. 准备训练和验证数据。
  2. 选择基础模型。
  3. 上传训练数据。
  4. 训练新的自定义模型。
  5. 检查自定义模型的状态。
  6. 部署自定义模型以供使用。
  7. 使用自定义模型。
  8. (可选)分析自定义模型的性能和拟合度。

准备训练和验证数据

训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。

不同的模型类型需要不同格式的训练数据。

你使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档。 对于 gpt-35-turbo-0613,必须以聊天补全 API 使用的对话格式来设置微调数据集的格式。

如果想要了解有关微调 gpt-35-turbo-0613 的逐步演练,请参阅 Azure OpenAI 微调教程

示例文件格式

{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Is Xbox better than PlayStation?"}, {"role": "assistant", "content": "I apologize, but I cannot provide personal opinions. My primary job is to assist you with any issues related to your Xbox device. Do you have any Xbox-related issues that need addressing?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Can I play PC games on my Xbox?"}, {"role": "assistant", "content": "While Xbox consoles don't natively support PC games, they can play an array of Xbox games, many of which are also available on PC. Can I assist you with finding games compatible with your Xbox device?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "I'm having trouble connecting my Xbox to the Wi-Fi."}, {"role": "assistant", "content": "No worries, let's go through the network settings on your Xbox. Can you please tell me what happens when you try to connect it to the Wi-Fi?"}]}

多轮次聊天文件格式

还支持在 jsonl 训练文件单行中的多轮次对话。 要跳过对特定助手消息的微调,请添加可选的 weight 键值对。 目前,weight 可设置为 0 或 1。

{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already.", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "William Shakespeare", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "384,400 kilometers", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters.", "weight": 1}]}

除 JSONL 格式外,训练和验证数据文件必须以 UTF-8 编码并包含字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

创建训练和验证数据集

训练示例越多越好。 如果没有至少 10 个训练示例,微调作业将无法继续,但如此少的数量不足以显著影响模型响应。 最佳做法是提供数百个(如果不是数千个)训练示例来获得成功。

通常,将数据集大小加倍会促使模型质量呈线性增长。 但请记住,低质量的示例可能会对性能产生负面影响。 如果你根据大量内部数据来训练模型,而不是先修剪数据集以便获得最高质量的示例,则最终可能会得到一个性能比预期差得多的模型。

上传训练数据

下一步是选择已准备好的现有训练数据或上传已准备好的新训练数据,以便在自定义模型时使用。 准备好训练数据后,可将文件上传到服务。 可通过两种方式上传训练数据:

对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。 有关 Azure Blob 存储的详细信息,请参阅什么是 Azure Blob 存储?

注意

训练数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

以下 Python 示例使用 Python SDK 上传本地训练和验证文件,并检索返回的文件 ID。

# Upload fine-tuning files

import os
from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-02-01"  # This API version or later is required to access fine-tuning for turbo/babbage-002/davinci-002
)

training_file_name = 'training_set.jsonl'
validation_file_name = 'validation_set.jsonl'

# Upload the training and validation dataset files to Azure OpenAI with the SDK.

training_response = client.files.create(
    file=open(training_file_name, "rb"), purpose="fine-tune"
)
training_file_id = training_response.id

validation_response = client.files.create(
    file=open(validation_file_name, "rb"), purpose="fine-tune"
)
validation_file_id = validation_response.id

print("Training file ID:", training_file_id)
print("Validation file ID:", validation_file_id)

创建自定义模型

上传训练和验证文件后,即可启动微调作业。

以下 Python 代码演示了使用 Python SDK 新建微调作业的示例:

response = client.fine_tuning.jobs.create(
    training_file=training_file_id,
    validation_file=validation_file_id,
    model="gpt-35-turbo-0613" # Enter base model name. Note that in Azure OpenAI the model name contains dashes and cannot contain dot/period characters. 
)

job_id = response.id

# You can use the job ID to monitor the status of the fine-tuning job.
# The fine-tuning job will take some time to start and complete.

print("Job ID:", response.id)
print("Status:", response.id)
print(response.model_dump_json(indent=2))

还可以传递其他可选参数(例如超参数),以更好地控制微调过程。 对于初始训练,我们建议使用存在的自动默认值,而不指定这些参数。

当前支持的微调超参数有:

Name 类型 描述
batch_size integer 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。
learning_rate_multiplier 数字 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。
n_epochs integer 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。

使用 1.x 版 OpenAI Python API 来设置自定义超参数:

from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-02-01"  # This API version or later is required to access fine-tuning for turbo/babbage-002/davinci-002
)

client.fine_tuning.jobs.create(
  training_file="file-abc123", 
  model="gpt-35-turbo-0613", # Enter base model name. Note that in Azure OpenAI the model name contains dashes and cannot contain dot/period characters. 
  hyperparameters={
    "n_epochs":2
  }
)

检查微调作业状态

response = client.fine_tuning.jobs.retrieve(job_id)

print("Job ID:", response.id)
print("Status:", response.status)
print(response.model_dump_json(indent=2))

部署自定义模型

微调作业成功后,响应正文中的 fine_tuned_model 变量的值将设置为自定义模型的名称。 现在还可以从列表模型 API 中发现该模型。 但是,只有在部署自定义模型之后,才能对自定义模型发出完成调用。 必须部署自定义模型才能使其可用于完成调用。

重要

在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。

删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure OpenAI 服务定价中所述,部署的每个自定义(微调)模型都会产生每小时的托管成本,无论是否对模型进行补全或聊天补全调用,都是如此。 要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅计划管理 Azure OpenAI 服务的成本中的指南。

可使用 Azure OpenAIAzure CLI 部署自定义模型。

注意

自定义模型只允许一个部署。 如果选择已部署的自定义模型,则会发生错误。

部署微调的模型

与以前的 SDK 命令不同,必须使用需要单独授权的控制平面 API、不同的 API 路径和不同的 API 版本才能完成部署。

variable 定义
token 可通过多种方式生成授权令牌。 初始测试的最简单方法是从 Azure 门户启动 Cloud Shell。 然后运行 az account get-access-token。 可以将此令牌用作 API 测试的临时授权令牌。 建议将其存储在新的环境变量中
订阅 关联的 Azure OpenAI 资源的订阅 ID
resource_group Azure OpenAI 资源的资源组名称
resource_name Azure OpenAI 资源名称
model_deployment_name 新微调模型部署的自定义名称。 这是在进行聊天补全调用时将在代码中引用的名称。
fine_tuned_model 请从上一步的微调作业结果中检索此值。 该字符串类似于 gpt-35-turbo-0613.ft-b044a9d3cf9c4228b5d393567f693b83。 需要将该值添加到 deploy_data json。
import json
import os
import requests

token= os.getenv("<TOKEN>") 
subscription = "<YOUR_SUBSCRIPTION_ID>"  
resource_group = "<YOUR_RESOURCE_GROUP_NAME>"
resource_name = "<YOUR_AZURE_OPENAI_RESOURCE_NAME>"
model_deployment_name ="gpt-35-turbo-ft" # custom deployment name that you will use to reference the model when making inference calls.

deploy_params = {'api-version': "2023-05-01"} 
deploy_headers = {'Authorization': 'Bearer {}'.format(token), 'Content-Type': 'application/json'}

deploy_data = {
    "sku": {"name": "standard", "capacity": 1}, 
    "properties": {
        "model": {
            "format": "OpenAI",
            "name": <"fine_tuned_model">, #retrieve this value from the previous call, it will look like gpt-35-turbo-0613.ft-b044a9d3cf9c4228b5d393567f693b83
            "version": "1"
        }
    }
}
deploy_data = json.dumps(deploy_data)

request_url = f'https://management.azure.com/subscriptions/{subscription}/resourceGroups/{resource_group}/providers/Microsoft.CognitiveServices/accounts/{resource_name}/deployments/{model_deployment_name}'

print('Creating a new deployment...')

r = requests.put(request_url, params=deploy_params, headers=deploy_headers, data=deploy_data)

print(r)
print(r.reason)
print(r.json())

跨区域部署

微调支持将微调后的模型部署到与模型最初进行微调时所在的区域不同的区域。 还可以部署到其他订阅/区域。

唯一的限制是新区域还必须支持微调,并且在部署交叉订阅时为部署生成授权令牌的帐户必须有权访问源订阅和目标订阅。

下面是一个示例,说明了如何将已在一个订阅/区域中微调的模型部署到另一个订阅/区域。

import json
import os
import requests

token= os.getenv("<TOKEN>") 

subscription = "<DESTINATION_SUBSCRIPTION_ID>"  
resource_group = "<DESTINATION_RESOURCE_GROUP_NAME>"
resource_name = "<DESTINATION_AZURE_OPENAI_RESOURCE_NAME>"

source_subscription = "<SOURCE_SUBSCRIPTION_ID>"
source_resource_group = "<SOURCE_RESOURCE_GROUP>"
source_resource = "<SOURCE_RESOURCE>"


source = f'/subscriptions/{source_subscription}/resourceGroups/{source_resource_group}/providers/Microsoft.CognitiveServices/accounts/{source_resource}'

model_deployment_name ="gpt-35-turbo-ft" # custom deployment name that you will use to reference the model when making inference calls.

deploy_params = {'api-version': "2023-05-01"} 
deploy_headers = {'Authorization': 'Bearer {}'.format(token), 'Content-Type': 'application/json'}



deploy_data = {
    "sku": {"name": "standard", "capacity": 1}, 
    "properties": {
        "model": {
            "format": "OpenAI",
            "name": <"FINE_TUNED_MODEL_NAME">, # This value will look like gpt-35-turbo-0613.ft-0ab3f80e4f2242929258fff45b56a9ce 
            "version": "1",
            "source": source
        }
    }
}
deploy_data = json.dumps(deploy_data)

request_url = f'https://management.azure.com/subscriptions/{subscription}/resourceGroups/{resource_group}/providers/Microsoft.CognitiveServices/accounts/{resource_name}/deployments/{model_deployment_name}'

print('Creating a new deployment...')

r = requests.put(request_url, params=deploy_params, headers=deploy_headers, data=deploy_data)

print(r)
print(r.reason)
print(r.json())

若要在同一订阅但不同区域之间进行部署,只需让源变量和目标变量的订阅和资源组相同,并且仅源资源名称和目标资源名称需要独一无二。

使用 Azure CLI 部署模型

以下示例演示如何使用 Azure CLI 部署自定义模型。 使用 Azure CLI 时,必须为自定义模型的部署指定名称。 有关使用 Azure CLI 部署自定义模型的详细信息,请参阅 az cognitiveservices account deployment

若要在控制台窗口中运行此 Azure CLI 命令,必须将以下 <占位符> 替换为自定义模型的相应值:

占位符
<YOUR_AZURE_SUBSCRIPTION> Azure 订阅的名称或 ID。
<YOUR_RESOURCE_GROUP> Azure 资源组的名称。
<YOUR_RESOURCE_NAME> Azure OpenAI 资源的名称。
<YOUR_DEPLOYMENT_NAME> 用于模型部署的名称。
<YOUR_FINE_TUNED_MODEL_ID> 自定义模型的名称。
az cognitiveservices account deployment create 
    --resource-group <YOUR_RESOURCE_GROUP>
    --name <YOUR_RESOURCE_NAME>  
    --deployment-name <YOUR_DEPLOYMENT_NAME>
    --model-name <YOUR_FINE_TUNED_MODEL_ID>
    --model-version "1" 
    --model-format OpenAI 
    --sku-capacity "1" 
    --sku-name "Standard"

使用已部署的自定义模型

部署自定义模型后,可像使用任何其他已部署的模型一样使用它。 可使用 Azure OpenAI Studio 中的“操场”来试验新部署。 可以继续对自定义模型使用相同的参数,例如 temperaturemax_tokens,就像对其他已部署的模型一样。 对于微调的 babbage-002davinci-002 模型,将使用“补全”操场和补全 API。 对于微调的 gpt-35-turbo-0613 模型,将使用“聊天”操场和聊天补全 API。

import os
from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-02-01"
)

response = client.chat.completions.create(
    model="gpt-35-turbo-ft", # model = "Custom deployment name you chose for your fine-tuning model"
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},
        {"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},
        {"role": "user", "content": "Do other Azure AI services support this too?"}
    ]
)

print(response.choices[0].message.content)

分析自定义模型

完成每个微调作业后,Azure OpenAI 会将一个名为 results.csv 的结果文件附加到该作业。 可以使用该结果文件来分析自定义模型的训练和验证性能。 将列出每个自定义模型的结果文件的文件 ID,你可以使用 Python SDK 检索该文件 ID,并下载结果文件进行分析。

以下 Python 示例检索附加到自定义模型微调作业的第一个结果文件的文件 ID,然后使用 Python SDK 将该文件下载到工作目录进行分析。

# Retrieve the file ID of the first result file from the fine-tuning job
# for the customized model.
response = client.fine_tuning.jobs.retrieve(job_id)
if response.status == 'succeeded':
    result_file_id = response.result_files[0]

retrieve = client.files.retrieve(result_file_id)

# Download the result file.
print(f'Downloading result file: {result_file_id}')

with open(retrieve.filename, "wb") as file:
    result = client.files.content(result_file_id).read()
    file.write(result)

结果文件是一个 CSV 文件,其中包含标题行,以及微调作业执行的每个训练步骤的行。 结果文件包含以下列:

列名称 说明
step 训练步数。 一个训练步骤代表针对一批训练数据的一次向前和向后的传递。
train_loss 训练批的损失。
training_accuracy 训练批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
train_mean_token_accuracy 训练批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。
valid_loss 验证批的损失。
valid_accuracy 验证批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
validation_mean_token_accuracy 验证批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。

还可以在 Azure OpenAI Studio 中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。

随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。

清理部署、自定义模型和训练文件

处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。

删除模型部署

重要

在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。

删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure OpenAI 服务定价中所述,部署的每个自定义(微调)模型都会产生每小时的托管成本,无论是否对模型进行补全或聊天补全调用,都是如此。 要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅计划管理 Azure OpenAI 服务的成本中的指南。

可以使用各种方法来删除自定义模型的部署:

删除自定义模型

同样,可以使用各种方法删除自定义模型:

注意

如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。

删除训练文件

可以选择性地在 Azure OpenAI 订阅中删除为训练上传的训练和验证文件,以及在训练期间生成的结果文件。 可使用以下方法删除训练、验证和结果文件:

以下 Python 示例使用 Python SDK 删除自定义模型的训练、验证和结果文件:

print('Checking for existing uploaded files.')
results = []

# Get the complete list of uploaded files in our subscription.
files = openai.File.list().data
print(f'Found {len(files)} total uploaded files in the subscription.')

# Enumerate all uploaded files, extracting the file IDs for the
# files with file names that match your training dataset file and
# validation dataset file names.
for item in files:
    if item["filename"] in [training_file_name, validation_file_name, result_file_name]:
        results.append(item["id"])
print(f'Found {len(results)} already uploaded files that match our files')

# Enumerate the file IDs for our files and delete each file.
print(f'Deleting already uploaded files.')
for id in results:
    openai.File.delete(sid = id)

持续微调

创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。

若要对之前微调过的模型执行微调,可以使用创建自定义模型中所述的流程,但无需指定通用基础模型的名称,而只需指定已微调的模型的 ID。 已微调的模型的 ID 类似于 gpt-35-turbo-0613.ft-5fd1918ee65d4cd38a5dcf6835066ed7

from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-02-01"  
)

response = client.fine_tuning.jobs.create(
    training_file=training_file_id,
    validation_file=validation_file_id,
    model="gpt-35-turbo-0613.ft-5fd1918ee65d4cd38a5dcf6835066ed7" # Enter base model name. Note that in Azure OpenAI the model name contains dashes and cannot contain dot/period characters. 
)

job_id = response.id

# You can use the job ID to monitor the status of the fine-tuning job.
# The fine-tuning job will take some time to start and complete.

print("Job ID:", response.id)
print("Status:", response.id)
print(response.model_dump_json(indent=2))

我们还建议添加 suffix 参数,以便更轻松地区分已微调模型的不同迭代。 suffix 接受一个字符串,并设置为标识已微调的模型。 OpenAI Python API 支持最多 18 个字符的字符串,该字符串将添加到已微调的模型名称中。

如果不确定现有的已微调模型的 ID,可以在 Azure OpenAI Studio 的“模型”页面中找到此信息,也可以使用 REST API 为某个给定 Azure OpenAI 资源生成模型列表

先决条件

注意

目前,必须提交应用程序才能访问 Azure OpenAI 服务。 若要申请访问权限,请填写此表单

模型

以下模型支持微调:

  • babbage-002
  • davinci-002
  • gpt-35-turbo (0613)
  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)

请参阅模型页,以查看当前支持微调的区域。

审阅 REST API 的工作流

花点时间审查将 REST APIS 和 Python 与 Azure OpenAI 配合使用的微调工作流:

  1. 准备训练和验证数据。
  2. 选择基础模型。
  3. 上传训练数据。
  4. 训练新的自定义模型。
  5. 检查自定义模型的状态。
  6. 部署自定义模型以供使用。
  7. 使用自定义模型。
  8. (可选)分析自定义模型的性能和拟合度。

准备训练和验证数据

训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。

不同的模型类型需要不同格式的训练数据。

你使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档。 对于 gpt-35-turbo-0613 和其他相关模型,必须按聊天补全 API 使用的对话格式来设置微调数据集的格式。

如果想要了解有关微调 gpt-35-turbo-0613 的逐步演练,请参阅 Azure OpenAI 微调教程

示例文件格式

{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Is Xbox better than PlayStation?"}, {"role": "assistant", "content": "I apologize, but I cannot provide personal opinions. My primary job is to assist you with any issues related to your Xbox device. Do you have any Xbox-related issues that need addressing?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "Can I play PC games on my Xbox?"}, {"role": "assistant", "content": "While Xbox consoles don't natively support PC games, they can play an array of Xbox games, many of which are also available on PC. Can I assist you with finding games compatible with your Xbox device?"}]}
{"messages": [{"role": "system", "content": "You are an Xbox customer support agent whose primary goal is to help users with issues they are experiencing with their Xbox devices. You are friendly and concise. You only provide factual answers to queries, and do not provide answers that are not related to Xbox."}, {"role": "user", "content": "I'm having trouble connecting my Xbox to the Wi-Fi."}, {"role": "assistant", "content": "No worries, let's go through the network settings on your Xbox. Can you please tell me what happens when you try to connect it to the Wi-Fi?"}]}

多轮次聊天文件格式

还支持在 jsonl 训练文件单行中的多轮次对话。 要跳过对特定助手消息的微调,请添加可选的 weight 键值对。 目前,weight 可设置为 0 或 1。

{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already.", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "William Shakespeare", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?", "weight": 1}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "384,400 kilometers", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters.", "weight": 1}]}

除 JSONL 格式外,训练和验证数据文件必须以 UTF-8 编码并包含字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

创建训练和验证数据集

训练示例越多越好。 如果没有至少 10 个训练示例,微调作业将无法继续,但如此少的数量不足以显著影响模型响应。 最佳做法是提供数百个(如果不是数千个)训练示例来获得成功。

通常,将数据集大小加倍会促使模型质量呈线性增长。 但请记住,低质量的示例可能会对性能产生负面影响。 如果你根据大量内部数据来训练模型,而不是先修剪数据集以便获得最高质量的示例,则最终可能会得到一个性能比预期差得多的模型。

选择基础模型

选择基础模型是创建自定义模型的第一步。 你可通过“基础模型”窗格选择用于自定义模型的基础模型。 所做的选择会影响模型的性能和成本。

从“基础模型类型”下拉列表中选择基础模型,然后选择“下一步”以继续。

可从以下可用基础模型之一创建自定义模型:

  • babbage-002
  • davinci-002
  • gpt-35-turbo (0613)
  • gpt-35-turbo (1106)

或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}。

具有自定义微调模型的模型选项屏幕截图。

有关可进行优化的基本模型的详细信息,请参阅模型

上传训练数据

下一步是选择已准备好的现有训练数据或上传已准备好的新训练数据,以便在微调模型时使用。 准备好训练数据后,可将文件上传到服务。 可通过两种方式上传训练数据:

对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。 有关 Azure Blob 存储的详细信息,请参阅什么是 Azure Blob 存储?

注意

训练数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。

上传训练数据

curl -X POST $AZURE_OPENAI_ENDPOINT/openai/files?api-version=2023-12-01-preview \
  -H "Content-Type: multipart/form-data" \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -F "purpose=fine-tune" \
  -F "file=@C:\\fine-tuning\\training_set.jsonl;type=application/json"

上传验证数据

curl -X POST $AZURE_OPENAI_ENDPOINT/openai/files?api-version=2023-12-01-preview \
  -H "Content-Type: multipart/form-data" \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -F "purpose=fine-tune" \
  -F "file=@C:\\fine-tuning\\validation_set.jsonl;type=application/json"

创建自定义模型

上传训练和验证文件后,即可启动微调作业。 以下代码演示了使用 REST API 新建微调作业的示例:

curl -X POST $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs?api-version=2023-12-01-preview \
  -H "Content-Type: application/json" \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -d '{
    "model": "gpt-35-turbo-0613", 
    "training_file": "<TRAINING_FILE_ID>", 
    "validation_file": "'<VALIDATION_FILE_ID>"
}'

还可以传递其他可选参数(例如超参数),以更好地控制微调过程。 对于初始训练,我们建议使用存在的自动默认值,而不指定这些参数。

当前支持的微调超参数有:

Name 类型 描述
batch_size integer 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。
learning_rate_multiplier 数字 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。
n_epochs integer 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。

检查自定义模型的状态

开始微调作业后,可能需要一些时间才能完成。 你的作业可能排在系统上的其他作业后面。 训练模型可能需要几分钟或几小时,具体取决于模型和数据集大小。 以下示例使用 REST API 检查微调作业的状态。 该示例使用上一示例返回的作业 ID 检索有关作业的信息:

curl -X GET $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs/<YOUR-JOB-ID>?api-version=2023-12-01-preview \
  -H "api-key: $AZURE_OPENAI_API_KEY"

部署自定义模型

重要

在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。

删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure OpenAI 服务定价中所述,部署的每个自定义(微调)模型都会产生每小时的托管成本,无论是否对模型进行补全或聊天补全调用,都是如此。 要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅计划管理 Azure OpenAI 服务的成本中的指南。

以下 Python 示例演示如何使用 REST API 为自定义模型创建模型部署。 REST API 为自定义模型的部署生成名称。

variable 定义
token 可通过多种方式生成授权令牌。 初始测试的最简单方法是从 Azure 门户启动 Cloud Shell。 然后运行 az account get-access-token。 可以将此令牌用作 API 测试的临时授权令牌。 建议将其存储在新的环境变量中
订阅 关联的 Azure OpenAI 资源的订阅 ID
resource_group Azure OpenAI 资源的资源组名称
resource_name Azure OpenAI 资源名称
model_deployment_name 新微调模型部署的自定义名称。 这是在进行聊天补全调用时将在代码中引用的名称。
fine_tuned_model 请从上一步的微调作业结果中检索此值。 该字符串类似于 gpt-35-turbo-0613.ft-b044a9d3cf9c4228b5d393567f693b83。 需要将该值添加到 deploy_data json。
curl -X POST "https://management.azure.com/subscriptions/<SUBSCRIPTION>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.CognitiveServices/accounts/<RESOURCE_NAME>/deployments/<MODEL_DEPLOYMENT_NAME>api-version=2023-05-01" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": {"name": "standard", "capacity": 1},
    "properties": {
        "model": {
            "format": "OpenAI",
            "name": "<FINE_TUNED_MODEL>",
            "version": "1"
        }
    }
}'

跨区域部署

微调支持将微调后的模型部署到与模型最初进行微调时所在的区域不同的区域。 还可以部署到其他订阅/区域。

唯一的限制是新区域还必须支持微调,并且在部署交叉订阅时为部署生成授权令牌的帐户必须有权访问源订阅和目标订阅。

下面是一个示例,说明了如何将已在一个订阅/区域中微调的模型部署到另一个订阅/区域。

curl -X PUT "https://management.azure.com/subscriptions/<SUBSCRIPTION>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.CognitiveServices/accounts/<RESOURCE_NAME>/deployments/<MODEL_DEPLOYMENT_NAME>api-version=2023-05-01" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": {"name": "standard", "capacity": 1},
    "properties": {
        "model": {
            "format": "OpenAI",
            "name": "<FINE_TUNED_MODEL>", 
            "version": "1",
            "source": "/subscriptions/{sourceSubscriptionID}/resourceGroups/{sourceResourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{sourceAccount}" 
        }
    }
}'

若要在同一订阅但不同区域之间进行部署,只需让源变量和目标变量的订阅和资源组相同,并且仅源资源名称和目标资源名称需要独一无二。

使用 Azure CLI 部署模型

以下示例演示如何使用 Azure CLI 部署自定义模型。 使用 Azure CLI 时,必须为自定义模型的部署指定名称。 有关使用 Azure CLI 部署自定义模型的详细信息,请参阅 az cognitiveservices account deployment

若要在控制台窗口中运行此 Azure CLI 命令,必须将以下 <占位符> 替换为自定义模型的相应值:

占位符
<YOUR_AZURE_SUBSCRIPTION> Azure 订阅的名称或 ID。
<YOUR_RESOURCE_GROUP> Azure 资源组的名称。
<YOUR_RESOURCE_NAME> Azure OpenAI 资源的名称。
<YOUR_DEPLOYMENT_NAME> 用于模型部署的名称。
<YOUR_FINE_TUNED_MODEL_ID> 自定义模型的名称。
az cognitiveservices account deployment create 
    --resource-group <YOUR_RESOURCE_GROUP>
    --name <YOUR_RESOURCE_NAME>  
    --deployment-name <YOUR_DEPLOYMENT_NAME>
    --model-name <YOUR_FINE_TUNED_MODEL_ID>
    --model-version "1" 
    --model-format OpenAI 
    --sku-capacity "1" 
    --sku-name "Standard"

使用已部署的自定义模型

部署自定义模型后,可像使用任何其他已部署的模型一样使用它。 可使用 Azure OpenAI Studio 中的“操场”来试验新部署。 可以继续对自定义模型使用相同的参数,例如 temperaturemax_tokens,就像对其他已部署的模型一样。 对于微调的 babbage-002davinci-002 模型,将使用“补全”操场和补全 API。 对于微调的 gpt-35-turbo-0613 模型,将使用“聊天”操场和聊天补全 API。

curl $AZURE_OPENAI_ENDPOINT/openai/deployments/<deployment_name>/chat/completions?api-version=2023-05-15 \
  -H "Content-Type: application/json" \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -d '{"messages":[{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},{"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},{"role": "user", "content": "Do other Azure AI services support this too?"}]}'

分析自定义模型

完成每个微调作业后,Azure OpenAI 会将一个名为 results.csv 的结果文件附加到该作业。 可以使用该结果文件来分析自定义模型的训练和验证性能。 将列出每个自定义模型的结果文件的文件 ID,你可以使用 REST API 检索该文件 ID,并下载结果文件进行分析。

以下 Python 示例使用 REST API 检索附加到自定义模型微调作业的第一个结果文件的文件 ID,然后将该文件下载到工作目录进行分析。

curl -X GET "$AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs/<JOB_ID>?api-version=2023-12-01-preview" \
  -H "api-key: $AZURE_OPENAI_API_KEY")
curl -X GET "$AZURE_OPENAI_ENDPOINT/openai/files/<RESULT_FILE_ID>/content?api-version=2023-12-01-preview" \
    -H "api-key: $AZURE_OPENAI_API_KEY" > <RESULT_FILENAME>

结果文件是一个 CSV 文件,其中包含标题行,以及微调作业执行的每个训练步骤的行。 结果文件包含以下列:

列名称 说明
step 训练步数。 一个训练步骤代表针对一批训练数据的一次向前和向后的传递。
train_loss 训练批的损失。
training_accuracy 训练批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
train_mean_token_accuracy 训练批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。
valid_loss 验证批的损失。
valid_accuracy 验证批中模型预测标记与真实完成标记完全匹配的完成百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.67 (2/3)。
validation_mean_token_accuracy 验证批中模型正确预测的标记百分比。
例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]],在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。

还可以在 Azure OpenAI Studio 中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。

随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。

清理部署、自定义模型和训练文件

处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。

删除模型部署

可以使用各种方法来删除自定义模型的部署:

删除自定义模型

同样,可以使用各种方法删除自定义模型:

注意

如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。

删除训练文件

可以选择性地在 Azure OpenAI 订阅中删除为训练上传的训练和验证文件,以及在训练期间生成的结果文件。 可使用以下方法删除训练、验证和结果文件:

持续微调

创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。

若要对之前微调过的模型执行微调,可以使用创建自定义模型中所述的流程,但无需指定通用基础模型的名称,而只需指定已微调的模型的 ID。 已微调的模型的 ID 类似于 gpt-35-turbo-0613.ft-5fd1918ee65d4cd38a5dcf6835066ed7

curl -X POST $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs?api-version=2023-12-01-preview \
  -H "Content-Type: application/json" \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -d '{
    "model": "gpt-35-turbo-0613.ft-5fd1918ee65d4cd38a5dcf6835066ed7", 
    "training_file": "<TRAINING_FILE_ID>", 
    "validation_file": "<VALIDATION_FILE_ID>",
    "suffix": "<additional text used to help identify fine-tuned models>"
}'

我们还建议添加 suffix 参数,以便更轻松地区分已微调模型的不同迭代。 suffix 接受一个字符串,并设置为标识已微调的模型。 后缀最多可包含 40 个字符(a-z、A-Z、0-9、- 和 _),这些字符将添加到已微调模型的名称中。

如果不确定已微调模型的 ID,可以在 Azure OpenAI Studio 的“模型”页面中找到此信息,也可以使用 REST API 为某个给定 Azure OpenAI 资源生成模型列表

疑难解答

如何启用微调? “创建自定义模型”在 Azure OpenAI Studio 中灰显?

为了成功获取微调功能,你需要分配有 Azure 认知服务 OpenAI 参与者角色。 即使是具有高级服务管理员权限的人员也需要显式设置此帐户才能访问微调。 有关详细信息,请查看基于角色的访问控制指南

为什么我上传失败?

如果文件上传失败,可以在 Azure OpenAI Studio 中的“数据文件”下查看错误消息。 将鼠标悬停在显示“错误”(状态列下)的位置,将显示关于失败的说明。

微调错误消息的屏幕截图。

我微调后的模型似乎没有改进

  • 缺少系统消息:微调时需要提供系统消息;使用微调后的模型时,需要提供相同的系统消息。 如果提供不同的系统消息,你看到的结果可能会与微调后的结果不同。

  • 数据不足:虽然运行管道的最小数量是 10,但需要数百到数千个数据点来教授模型一项新技能。 数据点过少可能会导致过度拟合和泛化性能不佳。 微调后的模型可能在训练数据上表现良好,但在其他数据上表现不佳,因为它记住了训练示例而不是学习模式。 为了获得最佳结果,请计划准备包含数百个或数千个数据点的数据集。

  • 错误的数据:策展不当或不具有代表性的数据集将生成低质量模型。 模型可能会从数据集中学习不准确或有偏差的模式。 例如,如果你正在训练一个用于客户服务的聊天机器人,但仅提供一种场景(例如商品退货)的训练数据,它将不知道如何响应其他场景。 或者,如果训练数据不正确(包含不正确的响应),模型将学习提供不正确的结果。

后续步骤