今天我们将深入探索ChatGPT的两项核心技术:Fine-tuning(微调)和Embeddings(嵌入)。这些技术在现代自然语言处理领域扮演着至关重要的角色,为模型的性能提升和适应特定任务需求提供了关键支持。ChatGPT作为GPT家族的一员,已经在多个领域展现了出色的表现,而其背后的Fine-tuning和Embeddings技术则是其成功的关键因素之一。
Fine-tuning,又称微调,是指在预训练模型(如GPT-3)的基础上,通过在特定任务上继续训练模型,使其适应特定任务的需求。GPT-3在大规模文本语料上进行了预训练,学会了丰富的语言知识和模式。然而,要使模型在特定任务上表现出色,就需要对其进行进一步的微调。
ChatGPT的Fine-tuning涉及到将模型暴露在各种对话和语境中,以便它能够更好地理解并生成自然对话。举个例子,如果我们想要让ChatGPT用于医疗咨询,Fine-tuning的过程将包括让模型学习医学知识、专业术语和与患者交流的最佳实践。这种Fine-tuning使得ChatGPT能够根据任务的特定上下文作出更准确的回应。
微调可让你通过 API 提供以下功能,从而更充分地利用可用模型:
GPT 模型已经过大量文本的预训练。为了有效地使用模型,在提示中包含说明,有时还包含几个示例。使用演示来展示如何执行任务通常称为“小样本学习”。
微调通过训练超出提示范围的更多示例来改进小样本学习,让你在大量任务上取得更好的结果。一旦模型经过微调,你就不需要在提示中提供那么多示例。这可以节省成本并实现更低延迟的请求。
在较高层面上,微调涉及以下步骤:
目前可对以下型号进行微调:
目前gpt-3.5-turbo在结果和易用性方面成为大多数用户的正确模型。
微调 GPT 模型可以使其更好地适应特定应用,但这需要仔细投入时间和精力。建议首先尝试通过 Prompt 工程、Prompt Chaining(将复杂的任务分解为多个Prompt)和函数调用来获得良好的结果,主要原因是:
GPT 最佳实践指南提供了一些最有效的策略和策略的背景知识,无需微调即可获得更好的性能。
微调可以改善结果的一些常见用例:
思考这些案例的一种高级方法是“展示而不是讲述”更容易。在接下来的部分中,我们将探讨如何设置用于微调的数据以及微调可以提高基准模型性能的各种示例。
微调有效的另一种情况是通过替换 GPT-4 或使用较短的 Prompt 来降低成本和/或延迟,而不牺牲质量。gpt-3.5-turbo如果您可以使用 GPT-4 获得良好的结果,那么您通常可以通过对 GPT-4 补全进行微调(可能还需要缩短指令提示)来使用微调模型达到类似的质量。
一旦你确定微调是正确的解决方案(即已经尽可能优化了 Prompt 并确定了模型仍然存在的问题),你将需要准备数据来训练模型。你应该创建一组多样化的演示对话,这些对话类似于您要求模型在生产中的推理时响应的对话。
数据集中的每个示例都应该是与我们的聊天完成 API 格式相同的对话,特别是消息列表,其中每条消息都有角色、内容和可选名称。至少一些训练示例应该直接针对提示模型未按预期运行的情况,并且数据中提供的辅助消息应该是您希望模型提供的理想响应。
在此示例中,我们的目标是创建一个偶尔给出讽刺性响应的聊天机器人,这是我们可以为数据集创建的三个训练示例(对话):
{"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提示完成对格式,如下所示。
{"prompt": "
{"prompt": "
{"prompt": "
要微调模型,你需要提供至少 10 个示例。我们通常会看到对 50 到 100 个训练示例进行微调会带来明显的改进,gpt-3.5-turbo但正确的数量根据具体的用例而有很大差异。
建议从 50 个精心设计的演示开始,看看模型在微调后是否显示出改进的迹象。在某些情况下,这可能就足够了,但即使模型尚未达到生产质量,明显的改进也是一个好兆头,表明提供更多数据将继续改进模型。没有任何改进表明你可能需要重新考虑如何在超出有限示例集之前设置模型任务或重组数据。
编译数据集后,在创建微调作业之前,检查数据格式非常重要。为此,我们创建了一个简单的 Python 脚本,您可以使用它来查找潜在错误、检查令牌计数并估计微调作业的成本。
验证数据后,需要上传文件才能用于微调作业:
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)
openai.FineTuningJob.retrieve("ft-abc123")
openai.FineTuningJob.cancel("ft-abc123")
openai.FineTuningJob.list_events(id="ft-abc123", limit=10)
import openai
openai.Model.delete("ft-abc123")
如果微调作业的结果不如预期,请考虑以下方式调整训练数据集:
收集示例以解决剩余问题
仔细检查现有示例是否存在问题
考虑数据的平衡性和多样性
确保您的训练示例包含响应所需的所有信息
查看训练示例中的一致性/一致性
确保所有训练示例都采用相同的格式,正如推理所预期的那样
OpenAI 的文本嵌入衡量文本字符串的相关性。嵌入通常用于:
嵌入是浮点数的向量(列表)。两个向量之间的距离衡量它们的相关性。距离小表明相关性高,距离大表明相关性低。
要获得Embeddings,请将文本字符串以及嵌入模型 ID 的选择(例如)发送到嵌入 API 端点text-embedding-ada-002。响应将包含一个嵌入,你可以提取、保存和使用它。
请求示例:
curl https://api.openai.com/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"input": "Your text string goes here",
"model": "text-embedding-ada-002"
}'
响应示例:
{
"data": [
{
"embedding": [
-0.006929283495992422,
-0.005336422007530928,
…
-4.547132266452536e-05,
-0.024047505110502243
],
"index": 0,
"object": "embedding"
}
],
"model": "text-embedding-ada-002",
"object": "list",
"usage": {
"prompt_tokens": 5,
"total_tokens": 5
}
}
OpenAI 提供了一个第二代嵌入模型(-002在模型 ID 中用 表示)和 16 个第一代模型(-001在模型 ID 中用 表示)。
建议对几乎所有用例使用 text-embedding-ada-002。它更好、使用更简单。
在Github中获取数据集,该数据集包含截至 2012 年 10 月亚马逊用户留下的总共 568,454 条食品评论。出于说明目的,我们将使用 1,000 条最新评论的子集。评论是英文的,往往是正面的或负面的。每条评论都有 ProductId、UserId、Score、评论标题(摘要)和评论正文(文本)。例如:
def get_embedding(text, model="text-embedding-ada-002"):
text = text.replace("\n", " ")
return openai.Embedding.create(input = [text], model=model)['data'][0]['embedding']
df['ada_embedding'] = df.combined.apply(lambda x: get_embedding(x, model='text-embedding-ada-002'))
df.to_csv('output/embedded_1k_reviews.csv', index=False)
要从保存的文件加载数据,你可以运行以下命令:
import pandas as pd
df = pd.read_csv('output/embedded_1k_reviews.csv')
df['ada_embedding'] = df.ada_embedding.apply(eval).apply(np.array)
在 Python 中,您可以使用 OpenAI 的 tokenizer 将字符串拆分为标记tiktoken。
示例代码:
import tiktoken
def num_tokens_from_string(string: str, encoding_name: str) -> int:
"""Returns the number of tokens in a text string."""
encoding = tiktoken.get_encoding(encoding_name)
num_tokens = len(encoding.encode(string))
return num_tokens
num_tokens_from_string("tiktoken is great!", "cl100k_base")
对于像文本嵌入ada-002这样的第二代嵌入模型,请使用cl100k_base编码。
为了快速搜索许多向量,我们建议使用向量数据库。您可以在 GitHub 上的 Cookbook 中找到使用矢量数据库和 OpenAI API 的示例。
矢量数据库选项包括:
推荐余弦相似度。距离函数的选择通常并不重要。
OpenAI 嵌入标准化为长度 1,这意味着:
尽管Fine-tuning和嵌入技术在提高ChatGPT性能方面起到了关键作用,但也存在一些挑战。其中之一是过拟合的问题。在Fine-tuning过程中,如果模型过于关注训练数据中的噪声或特定示例,可能导致模型在其他情况下表现不佳。因此,合适的正则化和数据清洗是确保模型泛化能力的重要因素。
另一个挑战是平衡预训练和Fine-tuning的关系。预训练阶段使模型具备了广泛的语言知识,但Fine-tuning阶段又需要在特定任务上进行调整。如何在这两者之间取得平衡,以及如何在Fine-tuning过程中保留预训练模型的有益特性,都需要深入研究和实验。
ChatGPT的成功背后离不开Fine-tuning和Embeddings技术的支持。Fine-tuning使得模型能够适应特定任务,而嵌入技术则使模型能够更好地理解语义和上下文。然而,这些技术也面临着挑战,需要持续的研究和改进。随着人工智能领域的不断发展,我们可以期待看到更多关于Fine-tuning、嵌入技术以及模型个性化的创新和突破。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章