刚刚!OpenAI 开放 GPT-3.5 微调 API,手把手教你打造专属 ChatGPT

IT知识
278
0
0
2024-01-18
标签   ChatGPT

大数据文摘出品

刚刚!OpenAI宣布,开放GPT-3.5微调的API。

这意味着,每个人都可以基于GPT-3.5微调自己的模型。

换句话说,之前用户在结合业务用例构建专属ChatGPT时候,需要使用大量的Propmt调教模型进行上下文学习。现在只需要四步即可打造自己的专属模型:准备数据→上传文件→创建微调工作→使用微调模型。

据OpenAI介绍,微调后的GPT-3.5,在某些特定任务上可以超越GPT-4。不过,GPT-4的微调 API 也将在今年秋季推出。同时,他们也提到,微调API传送的所有数据都是客户的私有资料,OpenAI或其他任何机构都不会用它来训练其他模型。

OpenAI的这次开放微调API的操作,文摘菌认为是是对Meta开源大模型的应对,大模型赛道上,对那些利用Llama 2开源框架将AI微调部署到下游行业(例如法律、医疗等)的企业而言,将会有一定程度上的冲击。赛道上的这些选手将面临严峻的考验。

微调后的大模型,有哪些提升?

OpenAI在博客中,提到自GPT-3.5 Turbo面世以来,开发者和各大企业一直希望能够对模型进行个性化定制,以便用户能使用更为独特和差异化的体验。现在,开发者可以通过有监督的微调技术,让模型更适合自己的特定需求。

在封闭测试中,采用微调的用户已成功在多个常用场景下显著提升了模型的表现。例如:

提高指令遵从性:通过微调让模型更准确地执行指令,无论是简洁地输出信息,还是始终用指定的语言回应。例如开发者可以设置模型在被要求使用德语时,一律用德语进行回应。

统一输出格式:微调还增强了模型在输出格式上的一致性,这一点对需要特定输出格式的应用,显的尤为重要,如代码自动补全或API调用生成,开发者可以通过微调确保模型可将用户的输入准确转化为与自己系统兼容的高质量JSON代码段。

调整输出语气:微调还能让模型的输出更贴近企业的品牌语气。具有明确品牌调性的企业可以通过微调,使模型的输出与其品牌风格更加吻合。

除了性能提升外,微调还允许用户在不牺牲性能的前提下,简化其使用的提示语。并且,与GPT-3.5 Turbo微调过的模型能处理多达4000个token,是以前模型的两倍。有的早期测试者甚至通过将指令直接嵌入模型,减少了90%的prompt的浪费,从而加快API调用速度并降低成本。

微调使用指南

目前仅有三款模型支持微调功能,包括gpt-3.5-turbo-0613、babbage-002、davinci-002。强烈推荐gpt-3.5-turbo,因为它在性能和操作便利性上都表现得相当出色。

微调技术在以下几个常见应用场景中具有显著的效果:

1、设定具体的输出风格、语调、格式或其他感性因素;

2、增强模型在生成输出时的靠谱性;

3、解决模型对复杂Prompt不敏感或无法准确响应的问题;

4、针对特定场景的边缘情况进行特别处理;

5、用于难以用简单Prompt明确描述的新技能或任务。

因此,从更高的维度上观察,上述场景仅仅通过文字或语言指示(即“讲解”)可能不足以让模型达到最佳性能。相反,通过实际的“示范”或样本(比如微调中使用的具体数据集)来训练模型,可能会更有效。

举个例子,如果想让模型生成符合特定风格和语气的文本,仅仅通过命令或提示很难准确地传达需求。但如果能提供一系列符合这种风格和语气的实例文本,然后用这些文本来微调模型,模型就更容易理解并生成符合要求的内容。

一、准备数据

当确认微调是解决模型缺陷的有效手段后,接下来的任务就是准备用于训练的数据。在这一阶段,需要构造一组样例对话,这些对话不仅要多样化,还要与模型在实际应用中可能遇到的情景高度相似,以便提高模型在真实场景下的推理准确性。

为了确保数据集的有效性,每一个样例对话都应遵循特定格式。具体来说,每个样例都应是一个消息列表,列表中的每条消息都应明确标注发送者的角色、消息内容,以及可选的发送者名称。更重要的是,数据集应包含一些专门用来解决模型当前表现不佳的问题的样例。这些特定样例的回应应该是期望模型未来能输出的理想答案。

举个例子,假如创建一个偶尔会给出讽刺回应的聊天机器人,下面是为数据集创建的三个训练示例:

{"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."}]}

提一嘴,目前还不支持函数调用,OpenAI还在努力开发。

如果要用微调gpt-3.5-turbo模型,使用对话式聊天的格式是必要的。至于babbage-002和davinci-002模型,可以用传统微调的提示和完成配对格式。

{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}

设计 Prompts。一般来说,建议用在微调之前效果最好的各种指令和输入prompt,并将它们纳入到每一个训练样例中。这样,尤其当训练样例不多(比如少于一百个)的时候,可以实现最佳应用效果。此外,由于模型是完全通过观察示例来学习,而没有明确的指导步骤,因此要达到良好的效果可能需要更多的训练样例。

推荐的样本数量。要对一个模型进行微调,需要最少10个样本。通常,使用gpt-3.5-turbo在50到100个训练样本上进行微调会带来明显的效果提升,但具体需要多少样本则要根据不同应用场景来定。

建议从50个精选的训练样本开始,然后观察微调后模型表现是否有所提升。如果有所改进,那么即使模型还未达到可用于生产的标准,也表明通过增加更多训练数据可以进一步优化模型。相反,如果性能没有显著提升,可能需要在增加更多样本之前,重新考虑模型的任务设置或对现有数据进行优化。

划分训练数据集与测试数据集。在收集完初始数据集之后,建议将其分为两部分:一部分用于训练,另一部分用于测试。提交微调任务时,如果提供了这两种类型的文件,将在训练过程中给出这两个数据部分的统计信息。这些统计结果是评估模型性能是否得到提升的初步指标。此外,提前准备好测试集不仅能帮助在训练结束后更容易地评价模型性能,还可以通过在该测试集上生成样本进行更细致的分析。

Token 限制。每个训练样本的长度不能超过4096个token。如果样本太长,训练时会被截短至前4096个token。为确保样本完整性,请检查每个消息内容的总token数不超过4000。目前,单个文件的最大允许大小是50MB。可以使用OpenAI的“计数token”工具来计算令牌数量。

计数token:

https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb

openai.File.create(
  file=open("mydata.jsonl", "rb"),
  purpose='fine-tune'
)

验证完数据后,就需要上传这个文件,以进行微调工作☝。

二、创建微调模型

通过OpenAI SDK开始微调任务:

import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.FineTuningJob.create(training_file="file-abc123", model="gpt-3.5-turbo")

上述代码,model选项能选择一个基础模型进行微调,比如gpt-3.5-turbo、babbage-002或davinci-002。还可以通过设置后缀参数来给微调模型起个名字。

任务启动后,完成可能需要一段时间,因为任务可能需要排队等待。根据所选模型和数据集的大小,这个过程可能需要从几分钟到几小时不等。

除此之外,还可以查看当前的微调任务列表,查询任务进度或者取消已有任务。

# List 10 fine-tuning jobs
openai.FineTuningJob.list(limit=10)

# Retrieve the state of a fine-tune
openai.FineTuningJob.retrieve("ft-abc123")

# Cancel a job
openai.FineTuningJob.cancel("ft-abc123")

# List up to 10 events from a fine-tuning job
openai.FineTuningJob.list_events(id="ft-abc123", limit=10)

# Delete a fine-tuned model (must be an owner of the org the model was created in)
import openai
openai.Model.delete("ft-abc123")

三、使用微调模型

当成功完成微调任务并查看任务的详细信息,会注意到“fine_tuned_model”字段已经填入了新模型的名字。这意味着现在可以立刻将这个新模型用在聊天自动补全(适用于gpt-3.5-turbo)或在旧版补全API(适用于babbage-002和davinci-002)上。当然,也可以在OpenAI的Playground中对其进行测试。

然而,虽然理论上模型应当立即可用,实际操作中可能需要几分钟的准备时间。如果遇到请求超时或无法找到模型的情况,很可能是因为模型正在加载过程中。这时,稍等几分钟后再进行尝试通常是个好办法。

import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

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使用指南,可以开始通过模型名称发起各种请求。

四、分析微调模型

提供了一系列在训练中得到的关键指标,包括训练损失和准确率,以及测试损失和准确率。这些数据可以帮助了解训练是否成功(理论上,损失应减小,准确率应提高)。

但实际上,最能反映模型质量的是从微调模型中生成的样本。建议在测试集上用原始模型和微调模型各生成一些样本,并将两者进行对比。这个测试集最好包括所有可能向模型输入的数据类型。如果手动评估不现实,也可以用OpenAI的Evals库,通过GPT-4进行自动评估。

优化数据质量。如果微调的效果没有达到预期,以下几个建议可能有助于调整训练数据:

1、补充针对模型弱点的训练数据:如果模型在某些方面的表现不佳,加入更多具有针对性的示例来改善。

2、仔细审查已有的数据:如果模型出现语法、逻辑或风格问题,检查训练数据中是否有相应的不足或错误。

3、平衡和多样化数据:如果大多数训练数据的回应都是“我不能回答这个问题”,但实际应用中这种回应应少见,那么模型很可能会产生过多的拒绝回应。

4、完备性检查:确保每一个训练示例都包含生成正确回应所需的所有信息。

5、保证数据一致性:如果训练数据由多人创建,确保数据间有良好的一致性,以避免影响模型性能。

6、格式统一:确保所有训练数据都是以推断所需的格式存在。

对数据量进行优化和调整。一旦数据示例的质量和分布都比较理想,可以考虑扩大训练数据的规模。这样做通常能让模型更全面地掌握任务,尤其在处理一些不太常见但又很关键的“边缘情况”时。预计每次将训练数据数量加倍,模型的性能都会有相应程度的提升。为了估算增加数据量能带来多大的性能提升,可以:

  • 在完整的当前数据集上做一次微调
  • 再在只有一半数据的数据集上做一次微调
  • 比较这两次微调后模型性能的差异

总的来说,如果需要在数据量和数据质量之间做出选择,那么少量但高质量的数据通常会比大量但低质量的数据更有用。

进行超参数的迭代调整。建议最初不要指定迭代次数,系统会根据数据集大小选择一个默认值。然后,如果观察到以下情况,可进行相应调整:

  • 若模型对训练数据的适应度不达标,考虑增加1或2个迭代次数。这种调整通常适用于具有唯一或少数几个理想结果的任务,比如分类、实体抽取或结构化解析任务。在这些任务中,往往可以根据标准答案来计算模型的准确率。
  • 若观察到模型的输出结果多样性减少,可以减少1或2个迭代次数。这种情况多出现在那些有多种有效完成方式的任务中。

关于价格

GPT-3.5的费用是这样计算的:如果用它来训练模型,每1000个token的费用是0.0080美元。对于输入的数据,每1000个token的成本是0.0120美元。同样地,输出的每1000个token也要收费0.0120美元。

以gpt-3.5-turbo微调任务为例,如果训练文件包含100,000个token,并且要训练3轮(epochs),那么预计的总费用将是2.40美元。