OpenAI 的文本生成模型(通常称为生成式预训练 Transformer 或大型语言模型)经过训练,能够理解自然语言、代码和图像。这些模型会根据其输入提供文本输出。这些模型的文本输入也被称为“提示词”。设计提示词本质上就是你“编程”大型语言模型的方式,通常是通过提供指令或一些如何成功完成任务的示例来实现。
可复现的输出
Chat Completions 默认是非确定性的(这意味着模型的输出可能会因请求而异)。话虽如此,我们通过向您提供 seed 参数和 system_fingerprint 响应字段,提供了一定程度的确定性控制。
要跨 API 调用获得(基本)确定性的输出,您可以:
- 将 seed 参数设置为您选择的任意整数,并在您希望获得确定性输出的请求中使用相同的值。
- 确保所有其他参数(如
promptortemperature)在不同请求中完全相同。
有时,由于 OpenAI 在我们这一端对模型配置进行了必要的更改,可能会影响确定性。为了帮助您跟踪这些更改,我们公开了 system_fingerprint 字段。如果此值不同,您可能会因为我们对系统所做的更改而看到不同的输出。
在 OpenAI Cookbook 中探索新的 seed 参数
管理令牌
语言模型以称为令牌的文本块来读取和写入文本。在英语中,一个令牌可以短至一个字符,也可以长至一个单词(例如, a or apple),而在某些语言中,令牌甚至可以短于一个字符或长于一个单词。
作为粗略的经验法则,对于英文文本,1 个令牌大约相当于 4 个字符或 0.75 个单词。
For example, the string "ChatGPT is great!" 被编码为六个令牌: ["Chat", "G", "PT", " is", " great", "!"].
API 调用中的令牌总数会影响:
- API 调用的成本,因为您按令牌付费
- API 调用所需的时间,因为写入更多令牌需要更多时间
- 您的 API 调用是否能成功,因为总令牌数必须低于模型的最大限制(对于
gpt-3.5-turbo)
输入和输出令牌均计入这些数量。例如,如果您的 API 调用在消息输入中使用了 10 个令牌,而在消息输出中收到了 20 个令牌,那么您将需要为 30 个令牌付费。但请注意,对于某些模型,输入令牌和输出令牌的单价是不同的(参见 定价 页面以获取更多信息)。
要查看一次 API 调用使用了多少 token,请检查 API 响应中的 usage 字段(例如, response['usage']['total_tokens']).
诸如 gpt-3.5-turbo and gpt-4-turbo-preview 等聊天模型使用 token 的方式与 completions API 中可用的模型相同,但由于其基于消息的格式,计算一段对话将使用多少 token 会更加困难。
Below is an example function for counting tokens for messages passed to gpt-3.5-turbo-0613.
The exact way that messages are converted into tokens may change from model to model. So when future model versions are released, the answers returned by this function may be only approximate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613"):
"""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-0613": # 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}.""")Next, create a message and pass it to the function defined above to see the token count, this should match the value returned by the API usage parameter:
1
2
3
4
5
6
7
8
9
10
11
12
13
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-0613"
print(f"{num_tokens_from_messages(messages, model)} prompt tokens counted.")
# Should show ~126 total_tokensTo confirm the number generated by our function above is the same as what the API returns, create a new Chat Completion:
1
2
3
4
5
6
7
8
9
10
11
# example token count from the OpenAI API
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=0,
)
print(f'{response.usage.prompt_tokens} prompt tokens used.')要在不进行 API 调用的情况下查看文本字符串中包含多少 token,请使用 OpenAI 的 tiktoken Python 库。示例代码可以在 OpenAI Cookbook 的 如何使用 tiktoken 计算 token.
指南中找到。传递给 API 的每条消息都会消耗内容、角色及其他字段中的 token 数量,另外还有少量用于幕后格式化的 token。未来这可能会有微小变动。
如果对话的 token 数量过多,超出了模型的最大限制(例如,对于 gpt-3.5-turbo 超过 4097 个 token,或者对于 gpt-4o超过 128k 个 token),你必须对文本进行截断、省略或其他缩减操作,直到其符合限制。请注意,如果某条消息被从 messages 输入中移除,模型将丢失关于它的所有信息。
请注意,过长的对话更有可能收到不完整的回复。例如,一段 gpt-3.5-turbo 长达 4090 个 token 的对话,其回复将在仅生成 6 个 token 后就被截断。
参数详情
频率和存在惩罚
频率和存在惩罚(可在 Chat Completions API and Legacy Completions API 中找到) 可用于降低采样到重复 token 序列的概率。
They work by directly modifying the logits (un-normalized log-probabilities) with an additive contribution.
mu[j] -> mu[j] - c[j] * alpha_frequency - float(c[j] > 0) * alpha_presenceWhere:
mu[j]is the logits of the j-th tokenc[j]is how often that token was sampled prior to the current positionfloat(c[j] > 0)is 1 ifc[j] > 0and 0 otherwisealpha_frequencyis the frequency penalty coefficientalpha_presenceis the presence penalty coefficient
As we can see, the presence penalty is a one-off additive contribution that applies to all tokens that have been sampled at least once and the frequency penalty is a contribution that is proportional to how often a particular token has already been sampled.
如果只是为了在一定程度上减少重复样本,惩罚系数的合理值大约在 0.1 到 1 之间。如果目标是强烈抑制重复,可以将系数增加到 2,但这可能会明显降低样本质量。负值可用于增加重复的概率。
Token 对数概率
The logprobs 参数(可在 Chat Completions API and Legacy Completions API 中找到),在被请求时,提供每个输出令牌的对数概率,以及每个令牌位置上数个最可能的令牌及其对数概率。这在某些情况下有助于评估模型对其输出的置信度,或检查模型可能给出的其他备选响应。
其他参数
中找到)请参阅完整的 API 参考文档 to learn more.