微调
学习如何为您的应用程序自定义模型。[1]
介绍
本指南适用于新的OpenAI微调API用户。如果您是传统的微调用户,请参阅我们的传统微调指南。[2]
微调使您能够通过提供以下内容来更好地利用API可用的模型:
1.比提示词更高质量的结果2.能够训练更多示例,而不仅仅是适应提示词3.由于提示词更短而节省标记4.更低的延迟请求
GPT模型已经在大量文本上进行了预训练。为了有效地使用这些模型,我们在提示中包含说明,有时还包括几个示例。使用演示来展示如何执行任务通常被称为“少样本学习”。
微调通过对比提示训练更多的示例,从而在许多任务上获得更好的结果,从高层次来看,微调包括以下步骤:
1.准备并上传训练数据2.训练一个新的微调模型3.使用您的微调模型
一旦模型经过微调,您将不需要在提示中提供那么多示例。这可以节省成本并实现更低延迟的请求。
请访问我们的定价页面[3]以了解更多有关微调模型的培训和使用的计费信息。
可以进行微调的模型是哪些?
我们正在努力实现对GPT-4的微调,并预计这一功能将在今年晚些时候推出。
目前可以进行微调的模型包括以下几种:
•gpt-3.5-turbo-0613
(推荐)•babbage-002
•davinci-002
我们预计gpt-3.5-turbo
在结果和使用便捷性方面对大多数用户来说都是合适的模型,除非您正在迁移传统的微调模型。
何时使用微调
微调GPT模型可以使它们在特定应用中表现更好,但需要仔细的时间和精力投入。我们建议首先尝试通过良好的提示工程、提示链(将复杂任务分解为多个提示)和函数调用[4]来获得良好的结果,主要原因包括:
•我们的模型在许多任务上可能最初看起来表现不佳,但通过正确的提示可以改善结果,因此可能不需要微调。•在提示和其他策略上进行迭代比进行微调具有更快的反馈循环,后者需要创建数据集和运行训练作业。•在需要微调的情况下,最初的提示工程工作并不是浪费 - 我们通常在微调数据中使用良好的提示时(或将提示链/工具使用与微调相结合时)获得最佳结果。
我们的GPT最佳实践指南[5]提供了一些有效的策略和方法的背景,以在不进行微调的情况下获得更好的性能。您可能会发现在我们的playground[6]中快速迭代提示对您有所帮助。
以下是关于微调的常见用途的信息:
常见用途
一些微调可以改善结果的常见用途包括:
•设置风格、语气、格式或其他定性方面•提高生成所需输出的可靠性•纠正未能遵循复杂提示的问题•以特定方式处理许多边缘情况•执行难以在提示中明确表达的新技能或任务
一种高层次的思考这些情况的方式是,当更容易“展示,而不是告诉”的时候。在接下来的章节中,我们将探讨如何为微调设置数据以及微调如何改善基线模型的性能的各种示例。
另一个微调非常有效的情况是通过替代GPT-4或利用更短的提示来降低成本和/或延迟,而不会牺牲质量。如果您可以通过GPT-4获得良好的结果,通常可以通过在GPT-4完成上进行微调,可能还附带缩短的指令提示,从而实现类似质量的微调gpt-3.5-turbo
模型。
以下是有关准备数据集的信息:
准备您的数据集
一旦您确定微调是正确的解决方案(即您已经优化了提示,但仍然确定模型存在问题),您需要为训练模型准备数据。您应该创建一组多样化的示范对话,这些对话与您在生产中将要询问模型的对话类似。
数据集中的每个示例应该是一个对话,格式与我们的聊天完成API[7]相同,具体来说,是一个消息列表,其中每个消息都有一个角色、内容和可选的名称[8]。至少,一些训练示例应直接针对提示的模型表现不如预期的情况,数据中提供的助手消息应该是您希望模型提供的理想响应。
示例格式
在这个示例中,我们的目标是创建一个偶尔会提供讽刺回应的聊天机器人,以下是我们可以为数据集创建的三个训练示例(对话):
代码语言:javascript复制{"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, as if everyone doesn't know that already."}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]}
{"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": "Around 384,400 kilometers. Give or take a few, like that really matters."}]}
对于微调gpt-3.5-turbo
,需要采用对话式聊天格式。而对于babbage-002
和davinci-002
,您可以采用用于传统微调[9]的提示完成对格式,如下所示:
{"prompt": "<prompt文本>", "completion": "<理想生成文本>"}
{"prompt": "<prompt文本>", "completion": "<理想生成文本>"}
{"prompt": "<prompt文本>", "completion": "<理想生成文本>"}
创建提示
通常,我们建议将您在微调之前发现对模型效果最好的一组指令和提示,包含在每个训练示例中。这应该可以让您达到最佳和最通用的结果,尤其是如果您只有相对较少(例如不到一百个)的训练示例。
如果您希望缩短在每个示例中重复的指令或提示以节省成本,请记住,模型可能会表现得好像这些指令已包含在内,并且在推断时可能很难使模型忽略那些“内置”的指令。
为了获得良好的结果,可能需要更多的训练示例,因为模型必须完全通过演示来学习,没有引导性的指令。
以下是关于微调的示例数量建议以及其他相关信息:
示例数量建议
要进行微调模型,您需要提供至少10个示例。我们通常看到,使用50到100个训练示例对gpt-3.5-turbo
进行微调会明显改进,但确切的示例数量因具体用例而异。
我们建议首先使用50个精心制作的示范来进行微调,并查看模型是否在微调后显示出改进的迹象。在某些情况下,这可能足够了,但即使模型尚不达到生产质量,明显的改进也是提供更多数据将继续改进模型的良好迹象。如果没有改进,这可能意味着您需要重新考虑如何为模型设置任务或在扩展到有限示例集之外之前重构数据。
训练和测试分割
在收集初始数据集之后,我们建议将其分为训练和测试部分。当提交同时包含训练和测试文件的微调作业时,我们将在培训过程中提供有关这两者的统计信息。这些统计信息将是模型改进程度的初始信号。此外,在早期构建测试集将有助于确保您能够在训练后评估模型,方法是在测试集上生成样本。
标记限制
每个训练示例限制为4096个标记。超过这个长度的示例在训练时将被截断为前4096个标记。为了确保整个训练示例适合上下文,考虑检查消息内容中的总标记计数是否在4,000以下。
您可以使用我们的标记计数笔记本[10]来计算标记计数,这是OpenAI白皮书的一部分。
以下是有关估算成本、检查数据格式和上传训练文件的信息:
估算成本
请参阅定价页面[11]以获取有关每1,000个输入和输出标记的成本的详细信息(我们不会收取验证数据的标记费用)。要估算特定微调作业的成本,请使用以下公式:
每1,000个标记的基本成本 * 输入文件中的标记数量 * 训练的轮数
对于一个包含100,000个标记的训练文件,经过3轮训练,预期成本约为2.40美元。
检查数据格式
一旦您编制了数据集,并在创建微调作业之前,检查数据格式非常重要。为此,我们创建了一个简单的Python脚本,您可以使用它来查找潜在错误、查看标记计数并估算微调作业的成本。
上传训练文件
一旦您验证了数据,需要使用Files API[12]上传文件,以便在微调作业中使用:
代码语言:javascript复制import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.File.create(
file=open("mydata.jsonl", "rb"),
purpose='fine-tune'
)
上传文件后,可能需要一些时间来进行处理。在文件处理过程中,您仍然可以创建微调作业,但作业只会在文件处理完成后开始。
创建一个微调模型
在确保您的数据集具有正确的数量和结构,并已上传文件之后,下一步是创建一个微调作业。
使用OpenAI SDK启动您的微调作业:
代码语言:javascript复制openai.FineTuningJob.create(training_file="file-abc123", model="gpt-3.5-turbo")
在这个示例中,model
是您想要微调的模型的名称(gpt-3.5-turbo
、babbage-002
、davinci-002
或已存在的微调模型),而 training_file
是在将训练文件上传到OpenAI API时返回的文件ID。您可以使用suffix参数[13]来自定义您的微调模型的名称。
要设置其他微调参数,比如 validation_file
或 hyperparameters
,请参阅微调的API规范[14]。
一旦启动了微调作业,可能需要一些时间才能完成。您的作业可能会排在我们系统中其他作业的后面,根据模型和数据集的大小,训练模型可能需要几分钟或几小时。在模型训练完成后,创建微调作业的用户将收到一封电子邮件确认。
除了创建微调作业,您还可以列出现有作业、检索作业状态或取消作业。
代码语言:javascript复制# List 10 fine-tuning jobs
openai.FineTuningJob.list(limit=10)
# Retrieve the state of a fine-tune
openai.FineTuningJob.retrieve("ftjob-abc123")
# Cancel a job
openai.FineTuningJob.cancel("ftjob-abc123")
# List up to 10 events from a fine-tuning job
openai.FineTuningJob.list_events(id="ftjob-abc123", limit=10)
# Delete a fine-tuned model (must be an owner of the org the model was created in)
openai.Model.delete("ft:gpt-3.5-turbo:acemeco:suffix:abc123")
当一个作业成功完成后,当您检索作业详情时,您将看到fine_tuned_model
字段中填充了模型的名称。现在,您可以将此模型指定为Chat completions[15](对于gpt-3.5-turbo
)或legacy Completions[16](对于babbage-002
和davinci-002
)API的参数,并使用Playground[17]进行请求。
在您的作业完成后,该模型应该可以立即用于推理。在某些情况下,您的模型可能需要几分钟才能准备好处理请求。如果请求到您的模型超时或找不到模型名称,这可能是因为您的模型仍在加载中。如果发生这种情况,请稍后再试。
代码语言:javascript复制completion = openai.ChatCompletion.create(
model="ft:gpt-3.5-turbo:my-org:custom_suffix:id",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
print(completion.choices[0].message)
您可以通过将模型名称传递给上面所示的方式以及我们的GPT指南[18]开始进行请求。
分析您的微调模型
我们提供了在培训过程中计算的以下培训指标:培训损失、培训标记准确性、测试损失和测试标记准确性。这些统计数据旨在提供培训是否顺利进行的合理检查(损失应该减少,标记准确性应该增加)。在运行活动微调作业时,您可以查看一个包含一些有用指标的事件对象:
代码语言:javascript复制{
"object": "fine_tuning.job.event",
"id": "ftevent-abc-123",
"created_at": 1693582679,
"level": "info",
"message": "Step 100/100: training loss=0.00",
"data": {
"step": 100,
"train_loss": 1.805623287509661e-5,
"train_mean_token_accuracy": 1.0
},
"type": "metrics"
}
在微调作业完成后,您还可以通过查询微调作业[19],从result_files
中提取文件ID,然后检索该文件的内容[20]来查看有关训练过程的指标。每个结果CSV文件都包含以下列:step
、train_loss
、train_accuracy
、valid_loss
和 valid_mean_token_accuracy
。这些列提供了有关模型训练如何进行的详细信息。
step,train_loss,train_accuracy,valid_loss,valid_mean_token_accuracy
1,1.52347,0.0,,
2,0.57719,0.0,,
3,3.63525,0.0,,
4,1.72257,0.0,,
5,1.52379,0.0,,
虽然指标可以提供帮助,但从微调模型生成的样本提供了对模型质量最相关的感觉。我们建议从基础模型和微调模型上的测试集中生成样本,并将这些样本并排进行比较。测试集应理想地包括您在生产用例中可能发送给模型的输入的完整分布。如果手动评估太耗时,考虑使用我们的Evals库[21]来自动化未来的评估。
在数据质量上进行迭代
如果来自微调作业的结果不如您预期的那么好,考虑以下调整训练数据集的方式:
•收集示例以解决剩余问题•如果模型仍然在某些方面表现不佳,添加直接展示模型如何正确执行这些方面的训练示例•仔细审查现有示例以解决问题•如果您的模型存在语法、逻辑或风格问题,请检查您的数据是否存在相同的问题。例如,如果模型现在说“我会为您安排这次会议”(而不应该这样说),请查看现有示例是否教导模型说它可以做新的事情,而实际上它不能做到•考虑数据的平衡和多样性•如果数据中助手的60%回应是“我无法回答这个问题”,但在推断时只有5%的回应应该是这样的,您可能会得到过多的拒绝回应•确保您的训练示例包含了生成响应所需的所有信息•如果我们希望模型根据用户的个人特征称赞用户,而一个训练示例包括了助手对于在前面的对话中未找到的特征的称赞,模型可能会学习产生虚构信息•查看训练示例中的一致性/一致性•如果多人创建了训练数据,模型性能可能会受到人们之间一致性/一致性水平的限制。例如,在文本提取任务中,如果人们只同意了70%的提取片段,模型可能无法做得比这更好•确保所有训练示例都符合预期的推断格式。
在满意示例的质量和分布后,您可以考虑增加训练示例的数量。这往往有助于模型更好地学习任务,特别是在可能的“边缘情况”周围。每次您将训练示例数量加倍时,我们预计将会有类似的改进。您可以通过以下方式粗略估计通过增加训练数据大小来获得的预期质量提升:
•在您当前的数据集上进行微调•在您当前数据集的一半上进行微调•观察两者之间的质量差距
一般来说,如果不得不进行权衡,少量高质量的数据通常比大量低质量的数据更有效。
迭代超参数
我们允许您指定微调模型的时期数。我们建议初始训练时不指定时期数,让我们根据数据集大小为您选择一个默认值,然后根据以下情况进行调整:
•如果模型不如预期那样遵循训练数据,请增加1或2个时期的数量•这在存在单一理想完成(或一组相似的理想完成)的任务中更常见。一些示例包括分类、实体提取或结构化解析。这些通常是可以根据参考答案计算最终准确度指标的任务。•如果模型变得不如预期那样多样化,请减少1或2个时期的数量•这在存在各种可能的良好完成的任务中更常见。
代码语言:javascript复制openai.FineTuningJob.create(training_file="file-abc123", model="gpt-3.5-turbo", hyperparameters={"n_epochs":2})
现在,我们已经探讨了微调API的基础知识,让我们看一下如何在几种不同的用例中进行微调生命周期。
•风格和语气•结构化输出•函数调用
迁移传统模型
对于从/v1/fine-tunes
迁移到更新的/v1/fine_tuning/jobs
API和更新的模型的用户,您可以期望的主要区别是更新的API。为了确保平稳过渡,已经保留了传统的提示完成对数据格式,用于更新的babbage-002
和davinci-002
模型。新模型将支持带有4k标记上下文的微调,并具有2021年9月的知识截止日期。
对于大多数任务,您应该期望从gpt-3.5-turbo
获得比从GPT基本模型获得更好的性能。
常见问题解答
何时应该使用微调与带检索的嵌入?
带检索的嵌入最适合需要具有相关上下文和信息的大型文档数据库的情况。
默认情况下,OpenAI的模型经过训练,可以成为有用的通用助手。微调可用于制作一个狭义关注的模型,并呈现特定的内在行为模式。检索策略可以通过在生成响应之前提供相关上下文来使新信息对模型可用。检索策略不是微调的替代方案,实际上可以与微调相辅相成。
•我什么时候可以微调GPT-4或GPT-3.5-Turbo-16k?•我们计划在今年晚些时候发布对这两种模型的微调支持。•如何知道我的微调模型是否确实比基础模型更好?•我们建议在聊天会话的测试集上从基础模型和微调模型生成样本,并将这些样本并排进行比较。对于更全面的评估,考虑使用OpenAI evals框架[22]创建一个与您的用例特定的评估。•我可以继续微调已经微调过的模型吗?•是的,您可以在创建微调作业时将微调模型的名称传递给model
参数。这将使用微调模型作为起点启动一个新的微调作业。•我如何估算微调模型的成本?•请参阅上面的估算成本[23]部分。•新的微调端点是否仍然与Weights & Biases一起用于跟踪指标?•不,我们目前不支持这种集成,但正在努力在不久的将来启用它。•我可以同时运行多少个微调作业?•请参阅我们的速率限制指南[24]以获取最新的限制信息。•微调模型的速率限制是如何工作的?•微调模型从与其基于的模型相同的共享速率限制中提取。例如,如果您在给定时间段内使用标准的gpt-3.5-turbo
模型消耗了您的TPM速率限制的一半,那么您从gpt-3.5-turbo
微调的任何模型只能访问剩余的TPM速率限制,因为容量在所有相同类型的模型之间共享。换句话说,拥有微调模型并不会从总吞吐量的角度为您提供更多使用我们的模型的能力。
本文由山行翻译整理自:https://platform.openai.com/docs/guides/fine-tuning/fine-tuning-examples,供大家技术学习使用,感兴趣的请点赞、收藏、关注。
References
[1]
学习如何为您的应用程序自定义模型。: https://platform.openai.com/docs/guides/fine-tuning/fine-tuning
[2]
本指南适用于新的OpenAI微调API用户。如果您是传统的微调用户,请参阅我们的传统微调指南。: https://platform.openai.com/docs/guides/legacy-fine-tuning
[3]
定价页面: https://openai.com/api/pricing
[4]
函数调用: https://platform.openai.com/docs/guides/gpt/function-calling
[5]
GPT最佳实践指南: https://platform.openai.com/docs/guides/gpt-best-practices
[6]
playground: https://platform.openai.com/playground
[7]
聊天完成API: https://platform.openai.com/docs/api-reference/chat/create
[8]
可选的名称: https://platform.openai.com/docs/api-reference/chat/create#chat/create-chat/create-messages-name
[9]
传统微调: https://platform.openai.com/docs/guides/legacy-fine-tuning/prepare-training-data
[10]
标记计数笔记本: https://cookbook.openai.com/examples/How_to_count_tokens_with_tiktoken.ipynb
[11]
定价页面: https://openai.com/pricing
[12]
Files API: https://platform.openai.com/docs/api-reference/files/create
[13]
suffix参数: https://platform.openai.com/docs/api-reference/fine-tuning/create#fine-tuning/create-suffix
[14]
微调的API规范: https://platform.openai.com/docs/api-reference/fine-tuning/create
[15]
Chat completions: https://platform.openai.com/docs/api-reference/chat
[16]
legacy Completions: https://platform.openai.com/docs/api-reference/completions
[17]
Playground: https://platform.openai.com/playground
[18]
GPT指南: https://platform.openai.com/docs/guides/gpt/chat-completions-api
[19]
查询微调作业: https://platform.openai.com/docs/api-reference/fine-tuning/retrieve
[20]
检索该文件的内容: https://platform.openai.com/docs/api-reference/files/retrieve-contents
[21]
Evals库: https://github.com/openai/evals
[22]
OpenAI evals框架: https://github.com/openai/evals
[23]
估算成本: https://platform.openai.com/docs/guides/fine-tuning/estimate-costs
[24]
速率限制指南: https://platform.openai.com/docs/guides/rate-limits/what-are-the-rate-limits-for-our-api