聊天完成度open in new window

使用OpenAI聊天API,你可以用gpt-3.5-turbogpt-4构建你自己的应用程序,来做一些事情:

  • 起草电子邮件或其他文章
  • 编写Python代码
  • 回答关于一组文件的问题
  • 创建对话代理
  • 给你的软件一个自然语言界面
  • 辅导一系列的科目
  • 翻译语言
  • 模拟视频游戏中的人物,以及更多

本指南解释了如何为基于聊天的语言模型进行API调用open in new window,并分享了获得良好结果的技巧。你也可以在OpenAI游乐场中试验新的聊天格式open in new window

介绍

聊天模型将一系列的消息作为输入,并将模型生成的消息作为输出返回。

尽管聊天格式的设计是为了使多轮对话变得容易,但它对没有任何对话的单轮任务也同样有用(比如以前由text-davinci-003这样的指令跟随模型提供的任务)。

一个API调用的例子看起来如下:

# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai

openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)
1
2
3
4
5
6
7
8
9
10
11
12

主要的输入是消息参数。消息必须是一个消息对象的数组,其中每个对象都有一个角色("系统"、"用户 "或 "助手")和内容(消息的内容)。对话可以短到1条消息,也可以写满很多页。

通常情况下,对话的格式是先有系统消息,然后是交替出现的用户和助手消息。

系统消息有助于设定助手的行为。在上面的例子中,助理被指示为 "你是一个有帮助的助理"。

TIP

gpt-3.5-turbo-0301open in new window并不总是对系统信息给予强烈关注。未来的模型将被训练成对系统信息的更强关注。

用户信息有助于指导助手。它们可以由应用程序的终端用户生成,也可以由开发人员设置为指令。

助理信息帮助存储先前的反应。它们也可以由开发者编写,以帮助提供所需行为的例子。

当用户指令参考先前的信息时,包括对话历史有助于。在上面的例子中,用户的最后一个问题 "在哪里播放的?"只有在先前关于2020年世界大赛的信息背景下才有意义。因为模型对过去的请求没有记忆,所有相关信息必须通过对话提供。如果一个对话不能在模型的token限制之内,就需要以某种方式缩短它。

响应格式

一个API响应的例子看起来如下:

{
 'id': 'chatcmpl-6p9XYPYSTTRi0xEviKjjilqrWU2Ve',
 'object': 'chat.completion',
 'created': 1677649420,
 'model': 'gpt-3.5-turbo',
 'usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},
 'choices': [
   {
    'message': {
      'role': 'assistant',
      'content': 'The 2020 World Series was played in Arlington, Texas at the Globe Life Field, which was the new home stadium for the Texas Rangers.'},
    'finish_reason': 'stop',
    'index': 0
   }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在Python中,可以用response['choice'][0]['message']['content']来提取助手的回复。

每个响应都将包括一个finish_reasonfinish_reason的可能值是:

  • stop:API返回完整的模型输出
  • length:由于max_tokens参数open in new window或token限制,模型输出不完整
  • content_filter:由于我们的内容过滤器的一个标志而遗漏了内容
  • null:API响应仍在进行中或不完整

管理token

语言模型以被称为"token"的块状物来阅读文本。在英语中,一个token可以短到一个字符或长到一个单词(例如,aapple),而在一些语言中,token甚至可以短于一个字符或长于一个单词。

例如,字符串 "ChatGPT is great!"被编码为六个token:["Chat", "G", "PT", " is", " great", "!"]

一个API调用中的token总数影响:

  • 你的API调用的成本是多少,因为你是按token付费的
  • 你的API调用需要多长时间,因为编写更多的token需要更多时间
  • 你的API调用是否有效,因为token总数必须低于模型的最大限制(gpt-3.5-turbo-0301为4096个token)。

输入和输出的token都计入这些数量。例如,如果你的API调用在信息输入中使用了10个token,而你在信息输出中收到了20个token,你将被收取30个token的费用。

要查看一个API调用使用了多少个token,请检查API响应中的usage字段(例如,response['usage']['total_tokens'])。

gpt-3.5-turbogpt-4这样的聊天模型使用token的方式与其他模型相同,但由于其基于消息的格式化,要计算一个对话将使用多少个token比较困难。

计算聊天API调用的token

下面是一个计算传递给gpt-3.5-turbo-0301的消息的token的函数示例。 消息转换为token的确切方式可能会在不同的模型中发生变化。所以当未来的模型版本发布时,这个函数返回的答案可能只是近似的。ChatML文档open in new window解释了消息是如何被OpenAI API转换为token的,对于编写你自己的函数可能是有用的。

def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301"):
  """Returns the number of tokens used by a list of messages."""
  try:
      encoding = tiktoken.encoding_for_model(model)
  except KeyError:
      encoding = tiktoken.get_encoding("cl100k_base")
  if model == "gpt-3.5-turbo-0301":  # note: future models may deviate from this
      num_tokens = 0
      for message in messages:
          num_tokens += 4  # every message follows <im_start>{role/name}\n{content}<im_end>\n
          for key, value in message.items():
              num_tokens += len(encoding.encode(value))
              if key == "name":  # if there's a name, the role is omitted
                  num_tokens += -1  # role is always required and always 1 token
      num_tokens += 2  # every reply is primed with <im_start>assistant
      return num_tokens
  else:
      raise NotImplementedError(f"""num_tokens_from_messages() is not presently implemented for model {model}.
  See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

接下来,创建一个消息,并将其传递给上面定义的函数,以查看token计数,这应该与API使用参数返回的值一致:

messages = [
  {"role": "system", "content": "You are a helpful, pattern-following assistant that translates corporate jargon into plain English."},
  {"role": "system", "name":"example_user", "content": "New synergies will help drive top-line growth."},
  {"role": "system", "name": "example_assistant", "content": "Things working well together will increase revenue."},
  {"role": "system", "name":"example_user", "content": "Let's circle back when we have more bandwidth to touch base on opportunities for increased leverage."},
  {"role": "system", "name": "example_assistant", "content": "Let's talk later when we're less busy about how to do better."},
  {"role": "user", "content": "This late pivot means we don't have time to boil the ocean for the client deliverable."},
]

model = "gpt-3.5-turbo-0301"

print(f"{num_tokens_from_messages(messages, model)} prompt tokens counted.")
# Should show ~126 total_tokens
1
2
3
4
5
6
7
8
9
10
11
12
13

为了确认我们上面的函数生成的数字与API返回的数字相同,创建一个新的聊天完成:

# example token count from the OpenAI API
import openai

response = openai.ChatCompletion.create(
    model=model,
    messages=messages,
    temperature=0,
)

print(f'{response["usage"]["prompt_tokens"]} prompt tokens used.')
1
2
3
4
5
6
7
8
9
10

要想在不调用API的情况下查看一个文本字符串中有多少个token,可以使用OpenAI的tiktokenopen in new windowPython库。示例代码可以在OpenAI Cookbook关于如何使用tiktoken计算tokenopen in new window的指南中找到。

传递给API的每条消息都会消耗内容、角色和其他字段中的token数量,加上一些额外的幕后格式化。这在未来可能会略有变化。

如果一个对话有太多的token,无法适应模型的最大限制(例如,对于gpt-3.5-turbo来说,超过4096个token),你将不得不截断、省略或以其他方式缩减你的文本,直到它适合。请注意,如果一条信息从信息输入中被删除,模型将失去对它的所有了解。

还要注意的是,很长的对话更有可能收到不完整的回复。例如,一个长达4090个符号的gpt-3.5-turbo对话,仅在6个符号之后就会被切断回复。

指导聊天模型

指导模型的最佳做法可能因模型版本不同而改变。下面的建议适用于gpt-3.5-turbo-0301,可能不适用于未来的模型。

许多对话以系统信息开始,以温和地指导助手。例如,这里是用于 ChatGPT 的系统消息之一:

一般来说,gpt-3.5-turbo-0301不会对系统信息给予强烈关注,因此重要的指示往往放在用户信息中更好。

如果模型没有产生你想要的输出,请随意迭代并尝试潜在的改进。你可以尝试以下方法:

  • 使你的指令更加明确
  • 指定你希望答案的格式
  • 在确定答案之前,要求模型逐步思考或辩论利弊

关于更多的提示性工程想法,请阅读OpenAI Cookbook关于提高可靠性的技术指南open in new window

除了系统消息外,温度和最大token是开发者影响聊天模型输出的众多选项中的两个open in new window。对于温度,较高的值如0.8会使输出更加随机,而较低的值如0.2会使其更加集中和确定。在最大token的情况下,如果你想把响应限制在一定的长度内,最大token可以被设置为一个任意的数字。这可能会引起一些问题,例如,如果你将最大token值设置为5,因为输出会被切断,结果对用户来说没有意义。

Chat vs Completions

因为gpt-3.5-turbo的性能与text-davinci-003相似,但每个token的价格却只有10%,所以我们推荐gpt-3.5-turbo用于大多数使用情况。

对于许多开发者来说,过渡就像重写和重新测试一个提示符一样简单。

例如,如果你把英语翻译成法语,有以下的完成度提示:

Translate the following English text to French: "{text}"
1

一个相当的聊天对话可能看起来像:

[
  {"role": "system", "content": "You are a helpful assistant that translates English to French."},
  {"role": "user", "content": 'Translate the following English text to French: "{text}"'}
]
1
2
3
4

或者甚至只是用户信息:

[
  {"role": "user", "content": 'Translate the following English text to French: "{text}"'}
]
1
2
3

FAQ

Is fine-tuning available for gpt-3.5-turbo?

不,从2023年3月1日起,你只能微调基本的GPT-3模型。关于如何使用微调模型的更多细节,请参阅微调指南

Do you store the data that is passed into the API?

从2023年3月1日起,我们保留你的API数据30天,但不再使用你通过API发送的数据来改进我们的模型。在我们的数据使用政策open in new window中了解更多。

Adding a moderation layer

如果你想给聊天API的输出添加一个审核层,你可以按照我们的审核指南来防止违反OpenAI使用政策的内容被显示。

Last Updated:
Contributors: lanheixingkong