跳到主要内容

会话补全 Beta

ChatGPT 基于 OpenAI 最先进的语言模型 gpt-3.5-turbo

使用 OpenAI 的 API,你可以使用 gpt-3.5-turbo 构建你自己的应用来做这些事情:

  • 起草一份邮件或者其他文字内容
  • 写 Python 代码
  • 回答关于一组文档的问题
  • 创建会话代理 ( conversational agents )
  • 给你的软件提供一个自然语言的接口
  • 辅导各种学科
  • 语言翻译
  • 假扮成游戏中货其他内容的角色

这个指引说明了如何调用基于聊天的语音模型的 API并分享了一些能获取到更好结果的技巧。你也可以体验新的 OpenAI 在线编辑器的聊天格式

介绍

聊天模型通过一串聊天对话作为输入,并返回一个模型生成的消息作为输出。

尽管聊天格式的设计是为了多轮对话更简单,但它对于没有任何对话的单轮任务同样有用(例如以前由 text-davinci-003 等指令遵循模型提供的任务)。

下面是一个 API 调用的例子:

# 提示: 你需要使用 OpenAI Python v0.27.0 版本来运行下面的代码
import openai

openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个能干的助手."},
{"role": "user", "content": "谁赢得了2020年的世界职业棒球大赛?"},
{"role": "assistant", "content": "洛杉矶道奇队在2020年赢得了世界职业棒球大赛冠军."},
{"role": "user", "content": "它在哪里举办的?"}
]
)

在这里查看完整的 API 参考文档

messages 参数是主要的输入。 messages 必须是消息对象 ( message object )的数组,每个对象拥有一个 role ( “system”, “user”, 或 “assistant” ) 和 content ( 消息的内容 )。会话可以少至 1 条消息或者是有许多条。

通常,会话首先使用系统消息 ( “system” ) 格式化,然后交替使用用户消息 ( “user” )助手消息 ( “assistant” )

系统消息有助于设定助手的行为。在上面的例子中,助手被说明为“你是一个能干的助手”。

用户消息帮助指示助手。它们可以由应用的用户生成,也可以由开发者设置为指令。

助手消息用于存储之前的响应。它们也可以是由开发者编写用于获取期望响应的示例。

当用户的指令是关于之前的消息时,包含聊天历史记录将有所帮助。在前面的例子中,用户最后的问题“在哪里举办的?”只有在前面关于世界职业棒球大赛的上下文中有意义。因为模型不能记住前面的请求,所以全部的相关信息必须在会话中提供。如果会话包含的 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
}
]
}

在 Python 中,助手的返回可以通过 response[‘choices’][0][‘message’][‘content’] 来取值。

每个返回都会包含 finish_reasonfinish_reason 的值有可能是:

  • stop: API 返回完整的模型输出
  • length: 因为 max_tokens 参数或 token 限制,导致不完整的模型输出
  • content_filter: 因为我们的内容过滤的标记,删掉了内容
  • null: API 响应还在进行中或未完成

Function calling(函数调用)

在 API 调用中,您可以向和描述函数, gpt-3.5-turbo-0613gpt-4-0613 并让模型智能地选择输出包含参数的 JSON 对象来调用这些函数。聊天完成 API 不调用函数;相反,模型生成 JSON,您可以使用它来调用代码中的函数。

我们强烈建议在代表用户采取影响世界的行动(发送电子邮件,在线发布内容,进行购买等)之前建立用户确认流程。

提示

在后台,函数以模型训练的语法注入到系统消息中。这意味着函数会计入模型的上下文限制,并作为输入令牌计费。

如果遇到上下文限制,我们建议限制函数的数量或为函数参数提供的文档的长度。

函数调用允许您更可靠地从模型中获取结构化数据。例如,您可以:

  • 创建聊天机器人,通过调用外部 API(例如例如 ChatGPT 插件)
    • 例如定义函数,如 send_email(to: string, body: string) ,或 get_current_weather(location: string, unit: 'celsius' | 'fahrenheit')
  • 将自然语言转换为 API 调用
    • 例如,转换“谁是我的顶级客户?” get_customers(min_revenue: int, created_before: string, limit: int) 并调用您的内部 API
  • 从文本中提取结构化数据
    • 例如定义调用的函数 extract_data(name: string, birthday: string) ,或者 sql_query(query: string)

函数调用的基本步骤顺序如下:

  1. 使用用户查询和 functions 参数中定义的一组函数调用模型。
  2. 模型可以选择调用一个函数;如果是,内容将是一个符合您自定义模式的字符串化 JSON 对象(注意:该模型可能生成无效的 JSON 或幻觉参数)。
  3. 在代码中将字符串解析为 JSON,并使用提供的参数(如果存在)调用函数。
  4. 通过将函数响应作为新消息追加,再次调用模型,并让模型将结果汇总返回给用户。

您可以通过下面的示例看到这些步骤的实际操作:

import openai
import json


# Example dummy function hard coded to return the same weather
# In production, this could be your backend API or an external API
def get_current_weather(location, unit="fahrenheit"):
"""Get the current weather in a given location"""
weather_info = {
"location": location,
"temperature": "72",
"unit": unit,
"forecast": ["sunny", "windy"],
}
return json.dumps(weather_info)


def run_conversation():
# Step 1: send the conversation and available functions to GPT
messages = [{"role": "user", "content": "What's the weather like in Boston?"}]
functions = [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
]
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=messages,
functions=functions,
function_call="auto", # auto is default, but we'll be explicit
)
response_message = response["choices"][0]["message"]

# Step 2: check if GPT wanted to call a function
if response_message.get("function_call"):
# Step 3: call the function
# Note: the JSON response may not always be valid; be sure to handle errors
available_functions = {
"get_current_weather": get_current_weather,
} # only one function in this example, but you can have multiple
function_name = response_message["function_call"]["name"]
fuction_to_call = available_functions[function_name]
function_args = json.loads(response_message["function_call"]["arguments"])
function_response = fuction_to_call(
location=function_args.get("location"),
unit=function_args.get("unit"),
)

# Step 4: send the info on the function call and function response to GPT
messages.append(response_message) # extend conversation with assistant's reply
messages.append(
{
"role": "function",
"name": function_name,
"content": function_response,
}
) # extend conversation with function response
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=messages,
) # get a new response from GPT where it can see the function response
return second_response


print(run_conversation())
提示

函数调用中的幻觉输出通常可以通过系统消息来缓解。 例如,如果你发现一个模型正在使用没有提供给它的函数生成函数调用,尝试使用一条系统消息:“Only use the functions you have been provided with.”

在上面的例子中,我们将函数响应发送回模型,让它决定下一步。它用一个面向用户的消息来响应,该消息告诉用户波士顿的温度,但根据查询,它可能会选择再次调用一个函数。

例如,如果你询问模型“Find the weather in Boston this weekend, book dinner for two on Saturday, and update my calendar”,并为这些查询提供相应的功能,则它可以选择背靠背地调用它们,并且仅在最后创建面向用户的消息。

如果你想强制模型调用一个特定的函数,你可以通过设置 function_call: {"name": "<insert-function-name>"} 。也可以通过设置强制模型生成面向用户的消息 function_call: "none" 。请注意,默认行为( function_call: "auto" )是由模型自己决定是否调用函数,如果是,则调用哪个函数。

管理 tokens

语言模型会将文本分块阅读,这些分块被称为记。在英语中,一个 token 可以很短,只有一个字符,也可以很长可以是一个单词(例如, aapple );在一些语言中,一个 token 可以比一个字符还要短,也可以比一个单词还要。

例如,字符串 “ChatGPT is great!” 被解成了六个记 [“Chat”, “G”, “PT”, “ is “ great”, “!”]

API 中调用的 token 数会受以下方面影响:你所用 API 的价格,因为你是按记数付费;API 调用时间长度,因为写入更多的记需要更的时间;API 调用是否能够正常工作,因为总记数必须于模型的最大限制(例如 gpt-3.5-tur-0301 限制为 4096 个记)。

在 API 中调用的 token 数量的多少会产生这些影响: 影响你调用 API 将花费的金额,因为你要为每个 token 买单;影响你调用 API 所花费的时间,因为写更多的内容需要更多时间;影响 API 调用是否能够正常运行,因为 token 总数必须小于模型的最大限制 ( 例如 gpt-3.5-tur-0301 的限制为 4096 个 tokens )

输入和输出的 token 数都会被统计。例如,如果你的 API 在消息中使用了 10 tokens 并且你接收到 20 tokens 的响应输出,你的账单会计入 30 tokens。

要查看 API 调用所使用的 token 数量,可以从响应体中的 usage 字段获取 ( 例如,response[‘usage’][‘total_tokens’] )。

要在不调用 API 的情况下,查看文本字符串中有多少 token,请使用 OpenAI 的 tiktoken Python 库。可以在 OpenAI 的 Cookbook 的指引 如何使用 tiktoken 计算 token 数 中找到示例代码。

发送给 API 的每条消息都会消耗 contentrole 和其他字段中的 token 数量,以及一些用于隐式格式化的额外 token。这种情况在未来可能会略有改变。

如果一个对话有太多的 token ,无法满足模型的最大限制的话 ( 比如 gpt-3.5-turbo 中超过 4096 个 token),你必须截断、省略、或以其他方式缩小你的文本,直到它适合模型未知。要注意的是,如果消息从模型的输入中移除的话,模型就无法掌握这些消息的内容了。

还要注意的是,输入太长的会话可能会导致接收的响应不完整。例如,一个 gpt-3.5-turbo 模型输入的会话是 4090 个 token 的话,响应会在 6 个 token 的时候被截断。

给聊天模型进行说明指引

随着模型的版本变化,给模型进行说明指引的最佳实践也会变化。下面适用于 gpt-3.5-turbo-0301 模型的建议可能不适用于未来的模型。

许多对话都以系统消息 ( system message ) 开始,以隐式地指示助手 ( assistant )。比如这里是一个用来指示 ChatGPT 的系统消息:

You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible. Knowledge cutoff: {knowledge_cutoff} Current date: {current_date}

一般来说,gpt-3.5-turbo-0301 不需要太过于关注系统消息,所以更重要的说明指示消息通常放在用户消息 ( user message ) 中。

如果模型生成的不是你想要的结果,你可以随意迭代并进行潜在的改进,你可以尝试这样处理:

  • 让你的说明更详细
  • 指明你在答案中想要的格式
  • 让模型一步一步地思考,或者在确定答案之前讨论正反两方面

想要获得更多的工程想法,请阅读 OpenAI Cookbook 关于提高可靠性的技术指南

除了系统消息,temperaturemax_tokens 是在许多配置中 开发者用来影响聊天模型输出的两个。对于 temperature ,更高的值比如 0.8,会让结果更加随机,而更低的值比如 0.2 会让结果更加聚焦和明确。对于 max_tokens ,如果希望将响应限制在某个长度,则可以将 max_tokens 设置为某个值。比如如果你将 max_tokens 的值设为 5,而输出的值将会被截断并且结果对用户来说是没有意义的。

聊天模型 vs 补全模型

gpt-3.5-turbo text-davinci-003 两个模型拥有相似的能力,但前者的价格只是后者的十分之一,在大部分情况下,我们更推荐使用 gpt-3.5-turbo

对于许多开发者来说,转换就像重写和重新测试 prompt 一样简单。

例如,假设你使用下面的补全 prompt 来让英语转换成法语:

翻译接下来的英文文本为法语: “{text}”

一个对应的对话会话是这样的:

[
{“role”: “system”, “content”: “你是一个善于将英语翻译成法语的人工智能助手.”},
{“role”: “user”, “content”: ‘翻译接下来的英文文本为法语: “{text}”’}
]

或者甚至只要用户消息:

[
{“role”: “user”, “content”: ‘翻译接下来的英文文本为法语: “{text}”’}
]

常见问题

gpt-3.5-turbo 模型支持微调 ( fine-tuning ) 吗?

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

你们会把通过 API 获取到的数据进行保存吗?

从 2023 年 3 月 1 日起,我们会将你通过 API 发送给我们的数据保留 30 天但不会使用这些数据来提升模型。了解更多关于我们的数据使用条款

添加调节层

如果你想要给聊天 API 的输出添加一个调节层,你可以根据我们的调节指南,以避免违反 OpenAI 使用政策的内容被展示出来。