在 Azure AI Foundry 模型中使用 Azure OpenAI,您可以通过称为 微调的过程,将我们的模型根据您的专属数据集进行定制。 通过此自定义步骤,你可以更充分地利用服务,获得以下好处:
- 结果的质量比从提示工程中获取的质量更高
- 能够根据超出模型最大请求上下文限制的更多示例进行训练。
- 由于提示较短,节省了令牌
- 更低延迟的请求,尤其是在使用较小的模型时。
与少样本学习相比,微调通过训练超出提示范围的更多示例来改进模型,从而让你在处理大量任务时取得更好的结果。 由于微调会调整基本模型的权重以提高特定任务的性能,因此无需在提示中包含过多的示例或说明。 这意味着发送的文本更少,每次 API 调用处理的令牌更少,从而可能节省成本并改善请求延迟。
我们使用 LoRA 或低排名适应来微调模型,从而降低其复杂性,而不会显著影响其性能。 此方法的工作原理是用较低秩的矩阵来近似原始的高秩矩阵,因此在监督训练阶段仅微调较小的“重要”参数子集,从而使模型更易于管理和高效。 对于用户,这使得训练比其他技术更快、更经济实惠。
Azure AI Foundry 门户中提供了两种独特的微调体验。
- 中心/项目视图 - 支持来自多个提供商的微调模型,包括 Azure OpenAI、Meta Llama、Microsoft Phi 等。
- Azure OpenAI 中心视图 - 仅支持微调 Azure OpenAI 模型,但支持其他功能,例如权重和偏差 (W&B) 预览集成。
如果只是微调 Azure OpenAI 模型,我们建议通过导航到 https://ai.azure.com/resource/overview 来获得以 Azure OpenAI 为中心的微调体验。
重要
本文中标记了“(预览版)”的项目目前为公共预览版。 此预览版未提供服务级别协议,不建议将其用于生产工作负载。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款。
先决条件
- 参阅何时使用 Azure OpenAI 微调指南。
- Azure 订阅。 免费创建一个。
- Azure OpenAI 资源位于支持微调 Azure OpenAI 模型的区域中。 查看模型摘要表和区域可用性,获取按区域列出的可用模型列表以及支持的功能。 有关详细信息,请参阅使用 Azure OpenAI 创建资源和部署模型。
- 微调访问需要认知服务 OpenAI 参与者角色。
- 如果尚无权查看配额并在 Azure AI Foundry 中部署模型,则需要其他权限。
支持的模型
请参阅模型页,以查看当前支持微调的区域。
或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}。
审阅 Azure AI Foundry 门户的工作流
请花点时间审阅使用 Azure AI Foundry 门户的微调工作流:
- 准备训练和验证数据。
- 使用 Azure AI Foundry 门户中 的“创建微调模型 ”对话框来训练自定义模型。
- 检查自定义微调模型的状态。
- 部署自定义模型以供使用。
- 使用自定义模型。
- (可选)分析自定义模型的性能和拟合度。
准备训练和验证数据
训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。
使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档,并且必须采用聊天完成 API 使用的聊天格式设置格式。
通常建议使用在每一个训练示例中找到的最佳说明和提示。 这将帮助你获得最佳结果,尤其是在只有不到一百个示例的情况下。
示例文件格式
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who discovered Antarctica?"}, {"role": "assistant", "content": "Some chaps named Fabian Gottlieb von Bellingshausen and Mikhail Lazarev, as if they don't teach that in every school!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the biggest ocean?"}, {"role": "assistant", "content": "The Pacific Ocean. It's not like it's a small pond or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest planet?"}, {"role": "assistant", "content": "It's called Jupiter, you might have heard of it...or not."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who painted the Mona Lisa?"}, {"role": "assistant", "content": "Oh, some obscure artist named Leonardo da Vinci. Not that he is famous or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the boiling point of water?"}, {"role": "assistant", "content": "Exciting fact of the day: it's 100 degrees Celsius. Life-changing, isn't it?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'The Odyssey'?"}, {"role": "assistant", "content": "Oh, just some poet named Homer. Nothing special, really."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest mammal?"}, {"role": "assistant", "content": "Blue Whale. Quite a big fish isn't it? Oh wait, it's not a fish!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the highest mountain peak?"}, {"role": "assistant", "content": "Everest. Brace yourself, it's not a walk in the park."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who invented the telephone?"}, {"role": "assistant", "content": "A guy named Alexander Graham Bell. Bet you didn't guess that one!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the distance from Earth to the Sun?"}, {"role": "assistant", "content": "About 93 million miles. Just a quick drive, really."}]}
多轮次聊天文件格式 Azure OpenAI
还支持在 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}]}
使用视觉的聊天补全
{"messages": [{"role": "user", "content": [{"type": "text", "text": "What's in this image?"}, {"type": "image_url", "image_url": {"url": "https://raw.githubusercontent.com/MicrosoftDocs/azure-ai-docs/main/articles/ai-services/openai/media/how-to/generated-seattle.png"}}]}, {"role": "assistant", "content": "The image appears to be a watercolor painting of a city skyline, featuring tall buildings and a recognizable structure often associated with Seattle, like the Space Needle. The artwork uses soft colors and brushstrokes to create a somewhat abstract and artistic representation of the cityscape."}]}
除 JSONL 格式外,训练和验证数据文件必须以 UTF-8 编码并包含字节顺序标记 (BOM)。 文件大小必须小于 512 MB。
数据集大小注意事项
训练示例越多越好。 如果没有至少 10 个训练示例,微调作业将无法继续,但如此少量的作业不足以显著影响模型响应。 最佳做法是提供数百个(如果不是数千个)训练示例来获得成功。 建议从 50 个高质量的训练数据开始。
通常,将数据集大小加倍会促使模型质量呈线性增长。 但请记住,低质量的示例可能会对性能产生负面影响。 如果你根据大量内部数据来训练模型,而不是先修剪数据集以便获得最高质量的示例,则最终可能会得到一个性能比预期差得多的模型。
创建微调的模型
Azure AI Foundry 门户提供了 “创建微调模型 ”对话框,因此,在一个位置,可以轻松为 Azure 资源创建和训练微调的模型。
转到 Azure AI Foundry 门户 https://ai.azure.com/ ,并使用有权访问 Azure OpenAI 资源的凭据登录。 在登录工作流中,选择适当的目录、Azure 订阅和 Azure OpenAI 资源。
在 Azure AI Foundry 门户中,浏览到“工具”>“微调”窗格,然后选择“微调模型”。
选择要微调的模型,然后选择“ 下一步 ”以继续。
现在应会看到“ 创建微调的模型 ”对话框。
选择训练方法
第一步是确认模型选择和训练方法。 并非所有模型都支持所有训练方法。
选择模型时,还可以选择 以前经过微调的模型。
选择训练类型
选择您要用于微调任务的训练级别:
如果没有数据驻留要求,选择Global可以利用当前区域以外的训练资源。 在公共预览版阶段,“全局”可能在当前区域中不可用。 查阅
在某些情况下, 标准 在当前区域中可能不可用。 如果需要数据驻留,请查阅所选 模型的模型可用性 中列出的区域。
选择训练数据
下一步是选择现有的已准备训练数据,或通过选择 “添加训练数据”来上传自定义模型时要使用的新准备训练数据。
“训练数据”对话框显示任何现有的以前上传的数据集,并提供用于上传新训练数据的选项。
如果训练数据已上传到服务,请选择“来自连接的 AI 资源的文件”。
- 从显示的下拉列表中选择文件。
上传新的训练数据时可使用以下选项之一:
- 选择“ 上传文件 ”以从本地文件上传训练数据。
- 选择 Azure Blob 或其他共享 Web 位置 ,从 Azure Blob 或其他共享 Web 位置导入训练数据。
对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。 有关 Azure Blob 存储的详细信息,请参阅什么是 Azure Blob 存储?
注意
训练数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。
选择验证数据(可选)
如果有验证数据集,请选择 “添加训练数据”。 可以选择现有的已准备验证数据,也可以上传自定义模型时要使用的新准备验证数据。
“验证数据”对话框显示任何现有的、以前上传的训练和验证数据集,并提供可以上传新验证数据的选项。
如果验证数据已上传到服务,请选择“选择数据集”。
- 从“验证数据”窗格中显示的列表中选择文件。
上传新的验证数据时可使用以下选项之一:
- 选择 “本地文件 ”,从本地文件上传验证数据。
- 选择 Azure Blob 或其他共享 Web 位置 ,从 Azure Blob 或其他共享 Web 位置导入验证数据。
对于大型数据文件,建议从 Azure Blob 存储导入数据。 大型文件在通过多部分表单上传时可能会变得不稳定,因为请求是原子化的,无法重试或继续。
注意
与训练数据文件类似,验证数据文件的格式必须设置为 JSONL 文件,采用 UTF-8 编码并带有字节顺序标记 (BOM)。 文件大小必须小于 512 MB。
使模型可识别(可选)
我们还建议包括一个 suffix
参数,以便更轻松地区分微调模型的不同迭代。 一 suffix
个字符串最多包含 18 个字符,用于命名生成的微调模型。
配置训练参数(可选)
可以提供可选的 种子 并调整其他超参数。
种子控制作业的可重现性。 传入相同的种子和作业参数应会产生相同的结果,但在极少数情况下可能会有差异。 如果未指定种子,则会为你随机生成一个种子。
以下超参数可用于通过 Azure AI Foundry 门户进行优化:
名称 | 类型 | 描述 |
---|---|---|
批大小 | 整数 | 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。 |
学习速率乘数 | 数字 | 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。 |
纪元数 | 整数 | 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。 |
启用自动部署(可选)
为节省时间,可以选择为生成的模型启用自动部署。 如果训练成功完成,将使用所选 部署类型部署模型。 部署将根据为您的自定义模型生成的唯一名称以及您之前可能已提供的可选后缀进行命名。
查看所做的选择并训练模型
查看你的选择,并选择“提交”开始训练新的微调模型。
检查自定义模型的状态
提交微调作业后,你将看到一个页面,其中包含有关优化模型的详细信息。 可以在 Azure AI Foundry 门户中的“ 微调 ”页上找到有关微调模型的状态和详细信息。
你的作业可能排在系统上的其他作业后面。 训练模型可能需要几分钟或几小时,具体取决于模型和数据集大小。
检查点
每个训练纪元完成时,都会生成一个检查点。 检查点是模型的完全功能版本,可以将其部署并用作后续微调作业的目标模型。 检查点可能会特别有用,因为它们可能在过度拟合之前提供快照。 当微调作业完成时,你将拥有可供部署的三个最新版本的模型。
分析自定义模型
完成每个微调作业后,Azure OpenAI 会将一个名为 results.csv 的结果文件附加到该作业。 可以使用该结果文件来分析自定义模型的训练和验证性能。 在 Azure AI Foundry 门户的“模型”窗格的“结果文件 ID”列中,列出了每个自定义模型的结果文件的文件 ID。 可以使用文件 ID 从 Azure AI Foundry 门户的“数据文件”窗格中标识和下载结果文件。
结果文件是一个 CSV 文件,其中包含标题行,以及微调作业执行的每个训练步骤的行。 结果文件包含以下列:
列名称 | 说明 |
---|---|
step |
训练步数。 一个训练步骤代表针对一批训练数据的一次向前和向后的传递。 |
train_loss |
训练批的损失。 |
train_mean_token_accuracy |
训练批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
valid_loss |
验证批的损失。 |
validation_mean_token_accuracy |
验证批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
full_valid_loss |
在每个纪元结束时计算的验证损失。 训练正常时,损失应减少。 |
full_valid_mean_token_accuracy |
在每个纪元结束时计算的有效平均标记准确性。 训练正常时,标记准确性应增加。 |
还可以在 Azure AI Foundry 门户中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。
随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。
部署微调模型
一旦您对微调任务的指标感到满意,或者只是想转向推理阶段,您就必须部署模型。
如果要进行进一步验证,请考虑使用开发者部署来进行测试。
如果已准备好部署生产或具有特定数据驻留需求,请遵循我们的 部署指南。
使用部署的微调模型
部署微调模型后,可像使用任何其他已部署的模型一样使用它。 可使用 Azure AI Foundry 中的“操场”来试验新部署。 还可以使用 REST API 从自己的应用程序调用微调模型。 你甚至可以开始在提示流中使用此新的微调模型来生成你的生成式 AI 应用程序。
注意
对于聊天模型,用于指导微调模型的系统消息(无论是微调模型已部署还是可用于在操场中进行测试)必须与用于训练的系统消息相同。 如果使用其他系统消息,则模型可能无法按预期执行。
持续微调
创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。
若要对以前经过微调的模型执行微调,请使用与 创建微调模型 中所述的相同过程,而不是指定通用基础模型的名称,而是指定已微调的模型。 自定义微调模型将类似于 gpt-4o-2024-08-06.ft-d93dda6110004b4da3472d96f4dd4777-ft
清理部署、自定义模型和训练文件
处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。
删除模型部署
重要
在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。
删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure AI Foundry 模型中的 Azure OpenAI 定价中所述,所部署的每个自定义(微调)模型都会产生每小时托管成本,而无论是否对模型进行补全或聊天补全调用。 若要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅 计划管理 Azure OpenAI 成本的指南。
可以在 Azure AI Foundry 门户的“部署”窗格中删除自定义模型的部署。 选择要删除的部署,然后选择“删除”以删除部署。
删除自定义模型
可以在 Azure AI Foundry 门户的“模型”窗格中删除自定义模型。 在“自定义模型”选项卡中选择要删除的自定义模型,然后选择“删除”以删除该自定义模型。
注意
如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。
删除训练文件
可以选择在 Azure AI Foundry 门户的“管理”“数据 + 索引”窗格中删除为进行训练上传的训练和验证文件,以及在训练期间生成的结果文件>。 选择要删除的文件,然后选择“删除”以删除该文件。
先决条件
- 参阅何时使用 Azure OpenAI 微调指南。
- Azure 订阅。 免费创建一个。
- Azure OpenAI 资源。 有关详细信息,请参阅使用 Azure OpenAI 创建资源和部署模型。
- 以下 Python 库:
os
、json
、requests
、openai
。 - OpenAI Python 库应至少为版本 0.28.1。
- 微调访问需要认知服务 OpenAI 参与者角色。
- 如果尚无权查看配额并在 Azure AI Foundry 中部署模型,则需要其他权限。
注意
REST API 目前不支持 全局 训练作业。 通过 API 检查全局训练作业可能会返回不正确的信息。
支持的模型
请参阅模型页,以查看当前支持微调的区域。
或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}
。
审阅 Python SDK 的工作流
花点时间审阅将 Python SDK 与 Azure OpenAI 配合使用的微调工作流:
- 准备训练和验证数据。
- 选择基础模型。
- 上传训练数据。
- 训练新的自定义模型。
- 检查自定义模型的状态。
- 部署自定义模型以供使用。
- 使用自定义模型。
- (可选)分析自定义模型的性能和拟合度。
准备训练和验证数据
训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。
使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档,并且必须采用聊天完成 API 使用的聊天格式设置格式。
如果想要了解有关微调 gpt-4o-mini-2024-07-18
的逐步演练,请参阅 Azure OpenAI 微调教程
示例文件格式
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who discovered Antarctica?"}, {"role": "assistant", "content": "Some chaps named Fabian Gottlieb von Bellingshausen and Mikhail Lazarev, as if they don't teach that in every school!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the biggest ocean?"}, {"role": "assistant", "content": "The Pacific Ocean. It's not like it's a small pond or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest planet?"}, {"role": "assistant", "content": "It's called Jupiter, you might have heard of it...or not."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who painted the Mona Lisa?"}, {"role": "assistant", "content": "Oh, some obscure artist named Leonardo da Vinci. Not that he is famous or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the boiling point of water?"}, {"role": "assistant", "content": "Exciting fact of the day: it's 100 degrees Celsius. Life-changing, isn't it?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'The Odyssey'?"}, {"role": "assistant", "content": "Oh, just some poet named Homer. Nothing special, really."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest mammal?"}, {"role": "assistant", "content": "Blue Whale. Quite a big fish isn't it? Oh wait, it's not a fish!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the highest mountain peak?"}, {"role": "assistant", "content": "Everest. Brace yourself, it's not a walk in the park."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who invented the telephone?"}, {"role": "assistant", "content": "A guy named Alexander Graham Bell. Bet you didn't guess that one!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the distance from Earth to the Sun?"}, {"role": "assistant", "content": "About 93 million miles. Just a quick drive, really."}]}
多轮次聊天文件格式
还支持在 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}]}
使用视觉的聊天补全
{"messages": [{"role": "user", "content": [{"type": "text", "text": "What's in this image?"}, {"type": "image_url", "image_url": {"url": "https://raw.githubusercontent.com/MicrosoftDocs/azure-ai-docs/main/articles/ai-services/openai/media/how-to/generated-seattle.png"}}]}, {"role": "assistant", "content": "The image appears to be a watercolor painting of a city skyline, featuring tall buildings and a recognizable structure often associated with Seattle, like the Space Needle. The artwork uses soft colors and brushstrokes to create a somewhat abstract and artistic representation of the cityscape."}]}
除 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-10-21" # This API version or later is required to access seed/events/checkpoint capabilities
)
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-4.1-2025-04-14", # Enter base model name. Note that in Azure OpenAI the model name contains dashes and cannot contain dot/period characters.
seed = 105 # seed parameter controls reproducibility of the fine-tuning job. If no seed is specified one will be generated automatically.
)
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))
还可以传递其他可选参数(例如超参数),以更好地控制微调过程。 对于初始训练,我们建议使用存在的自动默认值,而不指定这些参数。
当前支持的微调超参数有:
名称 | 类型 | 描述 |
---|---|---|
batch_size |
整数 | 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。 |
learning_rate_multiplier |
数字 | 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。 |
n_epochs |
整数 | 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。 |
seed |
整数 | 种子控制作业的可重现性。 传入相同的种子和作业参数应会产生相同的结果,但在极少数情况下可能会有差异。 如果未指定种子,则会为你生成一个种子。 |
使用 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-10-21" # This API version or later is required
)
client.fine_tuning.jobs.create(
training_file="file-abc123",
model="gpt-4.1-2025-04-14", # 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))
列出微调事件
若要检查训练期间生成的单个微调事件,可能需要使用 pip install openai --upgrade
以下命令将 OpenAI 客户端库升级到最新版本。
response = client.fine_tuning.jobs.list_events(fine_tuning_job_id=job_id, limit=10)
print(response.model_dump_json(indent=2))
检查点
每个训练纪元完成时,都会生成一个检查点。 检查点是模型的完全功能版本,可以将其部署并用作后续微调作业的目标模型。 检查点可能会特别有用,因为它们可能在过度拟合之前提供快照。 当微调作业完成时,你将拥有可供部署的三个最新版本的模型。 最后一个纪元将由你的微调模型表示,前两个纪元将作为检查点提供。
可以运行列表检查点命令来检索与单个微调作业关联的检查点列表。 可能需要使用 pip install openai --upgrade
将 OpenAI 客户端库升级到最新版本才能运行此命令。
response = client.fine_tuning.jobs.checkpoints.list(job_id)
print(response.model_dump_json(indent=2))
分析自定义模型
完成每个微调作业后,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 |
训练批的损失。 |
train_mean_token_accuracy |
训练批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
valid_loss |
验证批的损失。 |
validation_mean_token_accuracy |
验证批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
full_valid_loss |
在每个纪元结束时计算的验证损失。 训练正常时,损失应减少。 |
full_valid_mean_token_accuracy |
在每个纪元结束时计算的有效平均标记准确性。 训练正常时,标记准确性应增加。 |
还可以在 Azure AI Foundry 门户中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。
随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。
部署微调模型
如果对微调作业中的指标感到满意,或者只想进行推理,就必须部署模型。
如果要进行进一步验证,请考虑使用开发者部署来进行测试。
与以前的 SDK 命令不同,必须使用需要单独授权的控制平面 API、不同的 API 路径和不同的 API 版本才能完成部署。
变量 | 定义 |
---|---|
令牌 | 可通过多种方式生成授权令牌。 初始测试的最简单方法是从 Azure 门户启动 Cloud Shell。 然后运行 az account get-access-token 。 可以将此令牌用作 API 测试的临时授权令牌。 建议将其存储在新的环境变量中。 |
订阅 | 关联的 Azure OpenAI 资源的订阅 ID。 |
resource_group | Azure OpenAI 资源的资源组名称。 |
资源名称 | Azure OpenAI 资源名称。 |
模型部署名称 | 新微调模型部署的自定义名称。 这是在进行聊天补全调用时将在代码中引用的名称。 |
fine_tuned_model | 请从上一步的微调作业结果中检索此值。 该字符串类似于 gpt-4.1-2025-04-14.ft-b044a9d3cf9c4228b5d393567f693b83 。 需要将该值添加到 deploy_data json。 或者,也可以通过传递将以 ftchkpt-e559c011ecc04fc68eaa339d8227d02d 格式显示的检查点 ID 来部署检查点 |
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-41-ft" # custom deployment name that you will use to reference the model when making inference calls.
deploy_params = {'api-version': "2024-10-01"} # control plane API version rather than dataplane API for this call
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-4.1-2025-04-14.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())
在此处了解更多有关跨区域部署的信息,并使用已部署的模型。
如果已准备好部署生产或具有特定数据驻留需求,请遵循我们的 部署指南。
持续微调
创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。
若要对之前微调过的模型执行微调,可以使用创建自定义模型中所述的流程,但无需指定通用基础模型的名称,而只需指定已微调的模型的 ID。 已微调的模型的 ID 类似于 gpt-4.1-2025-04-14.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-10-21"
)
response = client.fine_tuning.jobs.create(
training_file=training_file_id,
validation_file=validation_file_id,
model="gpt-4.1-2025-04-14.ft-5fd1918ee65d4cd38a5dcf6835066ed7"
)
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 AI Foundry 的“模型”页面中查找此信息,也可以使用 REST API 为给定 Azure OpenAI 资源生成模型列表。
清理部署、自定义模型和训练文件
处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。
删除模型部署
重要
在你部署自定义模型之后,如果部署处于非活动状态的时间超过十五 (15) 天,则会删除部署。 如果模型是在超过十五 (15) 天前部署的且在连续 15 天内无补全或聊天补全调用,则自定义模型的部署处于非活动状态。
删除非活动状态的部署时,不会删除或影响基础自定义模型,并且可以随时重新部署自定义模型。 如 Azure AI Foundry 模型中的 Azure OpenAI 定价中所述,所部署的每个自定义(微调)模型都会产生每小时托管成本,而无论是否对模型进行补全或聊天补全调用。 若要详细了解如何使用 Azure OpenAI 规划和管理成本,请参阅 计划管理 Azure OpenAI 成本的指南。
可以使用各种方法来删除自定义模型的部署:
删除自定义模型
同样,可以使用各种方法删除自定义模型:
注意
如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。
删除训练文件
可以选择性地在 Azure OpenAI 订阅中删除为训练上传的训练和验证文件,以及在训练期间生成的结果文件。 可使用以下方法删除训练、验证和结果文件:
- Azure AI Foundry
- REST API
- Python SDK
以下 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)
先决条件
- 参阅何时使用 Azure OpenAI 微调指南。
- Azure 订阅。 免费创建一个。
- Azure OpenAI 资源。 有关详细信息,请参阅使用 Azure OpenAI 创建资源和部署模型。
- 微调访问需要认知服务 OpenAI 参与者角色。
- 如果尚无权查看配额并在 Azure AI Foundry 中部署模型,则需要其他权限。
注意
REST API 目前不支持 全局 训练作业。 通过 API 检查全局训练作业可能会返回不正确的信息。
支持的模型
请参阅模型页,以查看当前支持微调的区域。
或者,可以微调以前微调过的模型,格式为 base-model.ft-{jobid}。
审阅 REST API 的工作流
花点时间审查将 REST APIS 和 Python 与 Azure OpenAI 配合使用的微调工作流:
- 准备训练和验证数据。
- 选择基础模型。
- 上传训练数据。
- 训练新的自定义模型。
- 检查自定义模型的状态。
- 部署自定义模型以供使用。
- 使用自定义模型。
- (可选)分析自定义模型的性能和拟合度。
准备训练和验证数据
训练数据和验证数据集由输入和输出示例组成,这些示例表示你希望模型如何执行。
使用的训练和验证数据必须格式化为 JSON 行 (JSONL) 文档,并且必须采用聊天完成 API 使用的聊天格式设置格式。
如果想要了解有关微调 gpt-4o-mini-2024-07-18
的逐步演练,请参阅 Azure OpenAI 微调教程。
示例文件格式
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who discovered Antarctica?"}, {"role": "assistant", "content": "Some chaps named Fabian Gottlieb von Bellingshausen and Mikhail Lazarev, as if they don't teach that in every school!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the biggest ocean?"}, {"role": "assistant", "content": "The Pacific Ocean. It's not like it's a small pond or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest planet?"}, {"role": "assistant", "content": "It's called Jupiter, you might have heard of it...or not."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who painted the Mona Lisa?"}, {"role": "assistant", "content": "Oh, some obscure artist named Leonardo da Vinci. Not that he is famous or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the boiling point of water?"}, {"role": "assistant", "content": "Exciting fact of the day: it's 100 degrees Celsius. Life-changing, isn't it?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'The Odyssey'?"}, {"role": "assistant", "content": "Oh, just some poet named Homer. Nothing special, really."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest mammal?"}, {"role": "assistant", "content": "Blue Whale. Quite a big fish isn't it? Oh wait, it's not a fish!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the highest mountain peak?"}, {"role": "assistant", "content": "Everest. Brace yourself, it's not a walk in the park."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who invented the telephone?"}, {"role": "assistant", "content": "A guy named Alexander Graham Bell. Bet you didn't guess that one!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the distance from Earth to the Sun?"}, {"role": "assistant", "content": "About 93 million miles. Just a quick drive, really."}]}
多轮次聊天文件格式
还支持在 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}]}
使用视觉的聊天补全
{"messages": [{"role": "user", "content": [{"type": "text", "text": "What's in this image?"}, {"type": "image_url", "image_url": {"url": "https://raw.githubusercontent.com/MicrosoftDocs/azure-ai-docs/main/articles/ai-services/openai/media/how-to/generated-seattle.png"}}]}, {"role": "assistant", "content": "The image appears to be a watercolor painting of a city skyline, featuring tall buildings and a recognizable structure often associated with Seattle, like the Space Needle. The artwork uses soft colors and brushstrokes to create a somewhat abstract and artistic representation of the cityscape."}]}
除 JSONL 格式外,训练和验证数据文件必须以 UTF-8 编码并包含字节顺序标记 (BOM)。 文件大小必须小于 512 MB。
创建训练和验证数据集
训练示例越多越好。 如果没有至少 10 个训练示例,微调作业将无法继续,但如此少的数量不足以显著影响模型响应。 最佳做法是提供数百个(如果不是数千个)训练示例来获得成功。
通常,将数据集大小加倍会促使模型质量呈线性增长。 但请记住,低质量的示例可能会对性能产生负面影响。 如果你根据大量内部数据来训练模型,而不是先修剪数据集以便获得最高质量的示例,则最终可能会得到一个性能比预期差得多的模型。
上传训练数据
下一步是选择已准备好的现有训练数据或上传已准备好的新训练数据,以便在微调模型时使用。 准备好训练数据后,可将文件上传到服务。 可通过两种方式上传训练数据:
对于大型数据文件,建议从 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=2024-10-21 \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "gpt-4.1-2025-04-14",
"training_file": "<TRAINING_FILE_ID>",
"validation_file": "<VALIDATION_FILE_ID>",
"seed": 105
}'
还可以传递其他可选参数(例如超参数),以更好地控制微调过程。 对于初始训练,我们建议使用存在的自动默认值,而不指定这些参数。
当前支持的微调超参数有:
名称 | 类型 | 描述 |
---|---|---|
batch_size |
整数 | 要用于训练的批大小。 批大小表示用于训练单个前向和后向传递的训练示例的数量。 一般情况下,我们发现较大的批大小往往更适合较大的数据集。 此属性的默认值和最大值特定于基础模型。 批大小越大意味着模型参数的更新频率越低,但方差越小。 |
learning_rate_multiplier |
数字 | 用于训练的学习率乘数。 微调学习率是用于预训练的原始学习率乘以该值。 较大的学习率通常在较大的批大小中表现更好。 建议试验 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。 较小的学习率可以用于避免过度拟合。 |
n_epochs |
整数 | 训练模型的时期数。 一个时期是指训练数据集的一个完整周期。 |
seed |
整数 | 种子控制作业的可重现性。 传入相同的种子和作业参数应会产生相同的结果,但在极少数情况下可能会有差异。 如果未指定种子,则会为你生成一个种子。 |
检查自定义模型的状态
开始微调作业后,可能需要一些时间才能完成。 你的作业可能排在系统上的其他作业后面。 训练模型可能需要几分钟或几小时,具体取决于模型和数据集大小。 以下示例使用 REST API 检查微调作业的状态。 该示例使用上一示例返回的作业 ID 检索有关作业的信息:
curl -X GET $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs/<YOUR-JOB-ID>?api-version=2024-10-21 \
-H "api-key: $AZURE_OPENAI_API_KEY"
列出微调事件
若要检查训练期间生成的各个微调事件:
curl -X POST $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs/{fine_tuning_job_id}/events?api-version=2024-10-21 \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
检查点
每个训练纪元完成时,都会生成一个检查点。 检查点是模型的完全功能版本,可以将其部署并用作后续微调作业的目标模型。 检查点可能会特别有用,因为它们可能在过度拟合之前提供快照。 当微调作业完成时,你将拥有可供部署的三个最新版本的模型。 最后一个纪元将由你的微调模型表示,前两个纪元将作为检查点提供。
可以运行列表检查点命令来检索与各个微调作业关联的检查点的列表:
curl -X POST $AZURE_OPENAI_ENDPOINT/openai/fine_tuning/jobs/{fine_tuning_job_id}/checkpoints?api-version=2024-10-21 \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
分析自定义模型
完成每个微调作业后,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 |
训练批的损失。 |
train_mean_token_accuracy |
训练批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
valid_loss |
验证批的损失。 |
validation_mean_token_accuracy |
验证批中模型正确预测的标记百分比。 例如,如果批大小设置为 3 并且数据包含完成 [[1, 2], [0, 5], [4, 2]] ,在模型预测 [[1, 1], [0, 5], [4, 2]] 后,此值将设置为 0.83 (5/6)。 |
full_valid_loss |
在每个纪元结束时计算的验证损失。 训练正常时,损失应减少。 |
full_valid_mean_token_accuracy |
在每个纪元结束时计算的有效平均标记准确性。 训练正常时,标记准确性应增加。 |
还可以在 Azure AI Foundry 门户中以绘图形式查看 results.csv 文件中的数据。 选择已训练模型的链接,你将看到三个图表:损失、平均令牌准确度和令牌准确度。 如果你提供了验证数据,则这两个数据集将显示在同一绘图上。
随着时间的推移,损失会减少,而准确度提高。 如果训练和验证数据之间存在分歧,这可能表明过度拟合。 请尝试使用更少的循环次数或较小的学习速率乘数进行训练。
部署微调模型
如果对微调作业中的指标感到满意,或者只想进行推理,就必须部署模型。
如果要进行进一步验证,请考虑使用开发者部署来进行测试。
如果已准备好部署生产或具有特定数据驻留需求,请遵循我们的 部署指南。
变量 | 定义 |
---|---|
令牌 | 可通过多种方式生成授权令牌。 初始测试的最简单方法是从 Azure 门户启动 Cloud Shell。 然后运行 az account get-access-token 。 可以将此令牌用作 API 测试的临时授权令牌。 建议将其存储在新的环境变量中。 |
订阅 | 关联的 Azure OpenAI 资源的订阅 ID。 |
resource_group | Azure OpenAI 资源的资源组名称。 |
资源名称 | Azure OpenAI 资源名称。 |
模型部署名称 | 新微调模型部署的自定义名称。 这是在进行聊天补全调用时将在代码中引用的名称。 |
fine_tuned_model | 请从上一步的微调作业结果中检索此值。 该字符串类似于 gpt-4.1-2025-04-14.ft-b044a9d3cf9c4228b5d393567f693b83 。 需要将该值添加到 deploy_data json。 或者,也可以通过传递将以 ftchkpt-e559c011ecc04fc68eaa339d8227d02d 格式显示的检查点 ID 来部署检查点 |
curl -X POST "https://management.azure.com/subscriptions/<SUBSCRIPTION>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.CognitiveServices/accounts/<RESOURCE_NAME>/deployments/<MODEL_DEPLOYMENT_NAME>api-version=2024-10-21" \
-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"
}
}
}'
在此处了解更多有关跨区域部署的信息,并使用已部署的模型。
持续微调
创建微调模型后,你可能希望在一段时间内通过进一步微调继续完善模型。 持续微调是选择已经微调的模型作为基础模型并在新的训练示例集上进一步对其进行微调的迭代过程。
若要对之前微调过的模型执行微调,可以使用创建自定义模型中所述的流程,但无需指定通用基础模型的名称,而只需指定已微调的模型的 ID。 已微调的模型的 ID 类似于 gpt-4.1-2025-04-14.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-4.1-2025-04-14.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 AI Foundry 的“模型”页面中查找此信息,也可以使用 REST API 为给定 Azure OpenAI 资源生成模型列表。
清理部署、自定义模型和训练文件
处理完自定义模型后,可以删除部署和模型。 如果需要,还可以删除已上传到服务的训练和验证文件。
删除模型部署
可以使用各种方法来删除自定义模型的部署:
删除自定义模型
同样,可以使用各种方法删除自定义模型:
注意
如果自定义模型具有现有部署,则无法删除它。 必须先删除模型部署,然后才能删除自定义模型。
删除训练文件
可以选择性地在 Azure OpenAI 订阅中删除为训练上传的训练和验证文件,以及在训练期间生成的结果文件。 可使用以下方法删除训练、验证和结果文件:
后续步骤
- 在 Azure OpenAI 微调教程中了解微调功能。
- 查看微调模型区域可用性
- 详细了解 Azure OpenAI 配额