OpenAI 进阶用法

2026-11-09 10:10 更新

OpenAI的文本生成模型通常被称为生成式预训练Transformer或大语言模型,经过训练后能够理解自然语言、代码和图像,并根据输入生成文本。模型接收的文本输入也称为提示词(prompt)。设计提示词就像给大语言模型“编程”:通常通过指令或展示成功完成任务的示例,引导模型产生所需结果。

可复现的输出

Chat Completions默认具有非确定性,同一请求多次调用可能得到不同输出。可以通过seed参数和响应中的system_fingerprint字段,对输出的可复现程度进行一定控制。

要让不同API调用得到大体一致的结果:

  • 将seed设为自行选择的整数,并在需要复现的请求中使用相同值。
  • 确保其他参数,例如prompt、temperature等,完全相同。

这仍不保证输出完全一致。OpenAI可能需要调整服务端模型配置,这些变化会影响确定性。system_fingerprint用于帮助追踪此类变化;字段值不同时,输出差异可能源于服务端系统调整。

在OpenAI Cookbook中查看seed可复现输出示例。

管理词元

语言模型以词元(token)为单位读取和生成文本。英语中的一个词元可能短至单个字符,也可能长至一个单词,例如a或apple;在其他语言中,词元还可能短于一个字符,或长于一个单词。

英语文本可粗略按1个词元约等于4个字符或0.75个单词估算。这不是中文等语言的固定换算公式。可以用Tokenizer工具检查具体字符串如何划分为词元。

来源举例:"ChatGPT is great!"可编码为6个词元:["Chat", "G", "PT", " is", " great", "!"]。具体划分取决于使用的分词器。

一次API调用的总词元量会影响:

  • 费用:API按词元计费。
  • 耗时:生成更多词元通常需要更多时间。
  • 请求能否完成:总量必须适合模型的上限;来源以早期gpt-3.5-turbo的4,097词元限制为例。

输入与输出都计入用量。例如输入10个词元、输出20个词元,合计计量30个词元;部分模型对输入和输出采用不同单价,详见价格。计量总数并不意味着30个词元按同一种单价计费。

可在响应的usage中查看实际用量,例如response['usage']['total_tokens']。

gpt-3.5-turbo、gpt-4-turbo-preview等聊天模型与Completions模型一样使用词元,但聊天消息具有额外格式,因而更难精确计算整段会话的词元数。

下面保留来源面向gpt-3.5-turbo-0613的计数函数。不同模型或版本的消息编码可能变化;这个函数不应直接当作新模型的通用精确计数器。该旧模型示例需要外围环境已导入tiktoken,这里只做静态检查,没有验证模型当前可调用性。

来源示例 1(python):

## [中文] 仅为gpt-3.5-turbo-0613估算消息词元;依赖外围导入tiktoken。按角色/内容/名称与格式开销累计,其他模型抛出异常,不能当作新模型通用计数器。
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
    raise ValueError(
        f"num_tokens_from_messages() only supports gpt-3.5-turbo-0613, not {model}."
    )

接着构造消息并调用函数。来源示例将企业术语转换为通俗英语,预期约126个词元;实际结果应与适用模型的API用量对照,而不是据此认定其他模型也得到同一结果。

来源示例 2(python):

## [中文] 消息示范把企业术语改成通俗英语:协作带来收入增长、稍后有空再讨论改进;最后要求简化客户交付相关表述。依赖上一个计数函数及tiktoken,来源预期约126词元,未实际运行。
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_tokens

要与API返回的数字比较,可以创建Chat Completion。JavaScript和Python版本沿用上文的model、messages;Java版本单独发送一句翻译要求,其消息并不是上文完整数组,不能用来断言该数组的126词元结果。

来源示例 3(javascript):

// [中文] 沿用上文model与messages创建Chat Completion,温度为0,再打印prompt_tokens;model与messages需由外围环境提供。
import OpenAI from "openai";

const client = new OpenAI();

const response = await client.chat.completions.create({
  model,
  messages,
  temperature: 0,
});

console.log(`${response.usage.prompt_tokens} prompt tokens used.`);

来源示例 4(python):

## [中文] 沿用上文Python变量与完整消息数组发起Chat Completion,打印实际输入词元;本次未调用API。
## 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.")

来源示例 5(java):

// [中文] Java片段单独要求把一句话译成通俗英语,消息不同于前述完整数组;依赖外围client,不能用其用量验证126词元的数组结果。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params =
    ChatCompletionCreateParams.builder()
        .model("gpt-3.5-turbo-0613")
        .addUserMessage("Translate this sentence into plain English.")
        .temperature(0)
        .build();

var completion = client.chat().completions().create(params);
var usage =
    completion.usage().orElseThrow(() -> new IllegalStateException("No usage returned"));
System.out.println(usage.promptTokens() + " prompt tokens used.");

不调用API也可用OpenAI的tiktoken Python库检查文本词元,具体示例见使用tiktoken计数。

发给API的每条消息除了正文,还包括角色、其他字段及少量内部格式词元,这些开销以后可能略有变化。

当会话超出模型上限时,需要截断、删除或压缩输入。来源以早期gpt-3.5-turbo超过4,097词元、gpt-4o超过128k词元为例;这些是原指南中的模型示例,不是所有当前模型的统一上限。删除消息也会使模型失去那部分上下文。

长会话更容易挤占输出空间。来源举例:采用上述约4,097词元窗口的gpt-3.5-turbo,如果会话已占4,090词元,可供回复的空间仅约6个词元,回答可能被截断。实际预算应结合具体模型及消息格式计算。

参数详解

频率惩罚与存在惩罚

Chat Completions API和旧版Completions API中的频率惩罚(frequency penalty)与存在惩罚(presence penalty),可用于降低重复词元序列的采样概率。具体参数支持情况应以所用模型为准。

它们以加法项直接修改logit,即尚未归一化的对数概率:

来源示例 6(python):

## [中文] 公式片段:在第j个词元的logit中减去出现次数乘频率惩罚,再减去已出现词元的一次性存在惩罚;mu、c及两系数由算法环境提供。
mu[j] = mu[j] - c[j] * alpha_frequency - float(c[j] > 0) * alpha_presence

来源示例 7(ruby):

## [中文] Ruby公式与Python相同;出现次数大于0时才扣除存在惩罚,变量由外围算法提供。
mu[j] = mu[j] - c[j] * alpha_frequency - ((c[j] > 0) ? alpha_presence : 0.0)

其中:

  • mu[j]:第j个词元的logit。
  • c[j]:这个词元在当前位置之前已经被采样的次数。
  • 存在惩罚:如果c[j] > 0,减去alpha_presence;否则不减。
  • alpha_frequency:频率惩罚系数。
  • alpha_presence:存在惩罚系数。

存在惩罚对所有至少出现过一次的词元施加一次性加法调整;频率惩罚的大小则与该词元此前出现的次数成正比。

如果只希望适度减少重复,来源建议系数约为0.1到1。若想强力抑制重复,可提高到2,但可能明显降低生成质量。负值会提高重复出现的可能性。这些是原指南的调参建议,并非所有模型或任务的保证。

词元对数概率

Chat Completions及旧版Completions的logprobs参数可请求每个输出词元的对数概率,以及每个位置上数量有限的高概率候选词元及其对数概率。这可用于分析模型对输出的置信程度,或检查模型还可能给出哪些候选答案。

其他参数

其他参数见完整API参考。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号