OpenAI API 如何限制 Token 和控制成本
简答:OpenAI API 控制 Token 和成本要分三层:请求中用 max_completion_tokens 或 max_output_tokens 限制单次生成,项目设置中配置 Spend alert 与 Hard spend limit,再通过 usage 和 Usage Dashboard 持续核对实际消耗。单次输出上限不能代替月度预算,模型价格也必须以官方定价页为准。
定义:OpenAI API 的 Token 成本控制,是同时限制单次请求生成量、控制项目或组织级支出,并根据实际 usage 监控输入、输出、缓存和推理 Token 的过程。
先用这张表判断该设置解决什么问题
本文是 apikey.sbs 的第三方使用指南,不是 OpenAI 官方页面。OpenAI 官方文档把请求大小、速率限制、支出限制和用量查看分开管理,因此不要只设置一个 max tokens 参数就认为已经完成成本控制。
| 目标 | 应设置或查看的位置 | 能控制什么 | 不能替代什么 |
|---|---|---|---|
| 限制单次回答长度 | max_completion_tokens 或 max_output_tokens | 限制一次请求最多生成的 Token;Responses API 的上限还包括推理 Token | 不能限制一个项目整月的总费用 |
| 避免短时间请求过密 | RPM、TPM、RPD、TPD 等速率限制 | 控制每分钟或每天的请求量、Token 量 | 不能当作月度预算上限 |
| 设置月度费用提醒 | Spend alert | 达到设定金额后发送通知,API 流量继续 | 不能强制阻止继续产生费用 |
| 设置月度费用硬上限 | Hard spend limit | 达到适用上限后,让受影响请求返回 429 | 执行存在传播延迟,记录费用可能略微超过设置值 |
| 核对真实消耗 | 响应中的 usage 与 Usage Dashboard | 查看单次请求和项目、组织在时间段内的 Token 使用 | 不能自动替你决定合适的模型或提示词 |
官方对 Token 的说明指出,输入、输出、缓存输入和推理 Token 可能分别影响用量与价格;不同端点的字段名称也不同。Chat Completions 通常查看 prompt_tokens、completion_tokens、total_tokens,Responses 则查看 input_tokens、output_tokens、total_tokens,可参考 OpenAI 的 Token 说明。
第一层:限制单次请求的最大输出 Token
如果你的首要问题是“某次回答不要生成太长”,应先在请求参数中设置输出上限。Chat Completions 使用 max_completion_tokens;Responses API 使用 max_output_tokens。官方说明中,Responses 的 max_output_tokens 是生成上限,包含可见输出和推理 Token,因此可见文字长度不一定等于这个参数的数值。
这类参数只约束单次请求。它不会限制历史消息、系统提示词、工具定义或文件输入带来的输入 Token,也不会替你设置项目月度费用上限。输入过长时,应同时删除重复上下文、做摘要、分段处理,或在发送前使用 Token 计数能力检查完整请求。
Responses API:Python 最小示例
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
response = client.responses.create(
model=os.environ["OPENAI_MODEL"],
input="请用不超过五条要点解释什么是 API Key。",
max_output_tokens=256,
)
print(response.output_text)
print({
"input_tokens": response.usage.input_tokens,
"output_tokens": response.usage.output_tokens,
"total_tokens": response.usage.total_tokens,
})Responses API 的创建接口将 max_output_tokens 定义为生成上限,官方参考页还展示了响应中的 usage 结构。使用前请把环境变量中的模型名替换为你项目实际可用的模型,并以对应模型文档为准:Responses API 创建接口。
Chat Completions:JavaScript 最小示例
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
const completion = await client.chat.completions.create({
model: process.env.OPENAI_MODEL,
messages: [
{ role: "user", content: "请用不超过五条要点解释什么是 API Key。" }
],
max_completion_tokens: 256
});
console.log(completion.choices[0].message.content);
console.log({
prompt_tokens: completion.usage?.prompt_tokens,
completion_tokens: completion.usage?.completion_tokens,
total_tokens: completion.usage?.total_tokens
});如果你使用的是推理模型,不要把“可见答案最多 256 个 Token”当成绝对结论,因为官方 Token 说明强调,推理 Token 也可能计入输出用量。参数是否支持、最小值和具体行为要以目标模型的 API 参考为准。官方 Token 计数页也说明,max_output_tokens 和 max_completion_tokens 会限制模型生成的全部 Token,而不仅是最终可见文本:OpenAI Token 计数指南。
第二层:区分 Token 限制、TPM 和月度预算
很多成本失控问题来自把三种限制混为一谈。单次输出参数解决的是“一次请求生成多少”;TPM 解决的是“一分钟内允许处理多少 Token”;Spend limit 解决的是“组织或项目在一个计费周期内允许产生多少支出”。它们的作用范围不同,不能互相替代。
| 限制类型 | 常见指标或字段 | 达到限制后的处理思路 |
|---|---|---|
| 单次请求输出限制 | max_completion_tokens、max_output_tokens | 降低单次生成上限,检查是否因上下文或推理 Token 导致提前结束 |
| 速率限制 | RPM、TPM、RPD、TPD | 减少并发和突发流量,遵循 Retry-After,必要时使用带抖动的指数退避 |
| 支出提醒 | Spend alert | 在达到阈值时通知负责人,继续检查日志、项目和用户配额 |
| 支出硬上限 | Hard spend limit | 达到适用上限后处理 429,并根据 error.code 判断是组织还是项目限制 |
OpenAI 的速率限制文档列出了 RPM、RPD、TPM、TPD 等指标,并明确说明速率限制与可配置的 Spend limits 分开管理。短时间内遇到 429 时,不要无限重试;官方建议优先遵循响应中的 Retry-After,没有有效值时再使用带随机抖动的指数退避,同时限制重试次数和总等待时间。参考 OpenAI Rate limits 指南。
应用层还应加一层用户配额
- 按用户、团队或 API Key 记录每日输入 Token、输出 Token 和请求次数。
- 为高成本功能单独设置额度,例如长文档分析、批量任务和多轮 Agent 调用。
- 为并发请求设置队列或信号量,避免多个请求同时放大 TPM 与费用。
- 为网络请求设置超时,并确认 SDK 的自动重试次数,避免应用层重试和 SDK 重试叠加。
- 遇到费用异常时,先暂停高风险任务或撤销暴露的 Key,再核对项目、用户和请求日志。
第三层:设置 Spend alert 和 Hard spend limit
如果目标是控制整月费用,仅设置单次输出参数是不够的。官方支出限制页面区分了 Spend alert 与 Hard spend limit:前者只发送通知,后者会在达到适用上限后让受影响请求返回 429。官方还说明,硬上限的执行不是瞬时完成,记录费用可能略微超过配置值,因此它更适合作为硬性保护层,而不是精确到每一分的实时断路器。
- 先确认你拥有管理组织或项目限制的权限。
- 组织级设置进入 Organization limits;项目级设置进入 Project settings,再打开 Limits。
- 在 Spend 区域选择 Edit spend limit,填写月度支出限制。
- 需要达到上限后停止受影响流量时,启用 Enforce a hard limit。
- 同时设置较低阈值的 Spend alert,为排查异常流量预留时间。
- 测试应用对 429 的处理,读取
error.code,不要把账单类 429 当作普通临时限流无限重试。
组织硬上限和项目硬上限可能同时作用于请求。官方文档列出的错误码包括 organization_spend_limit_exceeded 与 project_spend_limit_exceeded;达到后,应根据当前用量和限制配置决定是等待周期重置还是调整限制。具体配置路径和恢复方式见 OpenAI Spend limits 指南。
一个实用的生产配置是:开发项目使用较低额度和较密集的告警,生产项目单独管理;不要让测试流量和生产流量共用同一个项目,否则发生异常时很难判断是哪个环境消耗了 Token。
如何读取 usage 并计算单次请求成本
成本核算的基本公式是:
单次成本 =
输入 Token / 1,000,000 × 输入单价
+ 缓存输入 Token / 1,000,000 × 缓存输入单价
+ 输出 Token / 1,000,000 × 输出单价公式中的单价必须替换为目标模型在官方定价页显示的当前费率。不要把某个模型的价格复制到另一个模型,也不要只比较每百万 Token 单价;官方说明指出,同一任务在不同模型上的 Token 化方式、输出长度和推理用量可能不同,最终总成本需要用代表性请求测试。
Chat Completions 通常从 response.usage.prompt_tokens、response.usage.completion_tokens 和 response.usage.total_tokens 读取;Responses 通常从 response.usage.input_tokens、response.usage.output_tokens 和 response.usage.total_tokens 读取。缓存 Token 还要查看对应的 usage details,不能把缓存 Token 再按普通输入重复相加。
若使用流式 Chat Completions,需要确认请求是否启用了返回用量信息的选项,并在最终事件中读取 usage;具体字段和流式行为以当前 API 参考为准。单次日志建议至少保留时间、项目、模型、请求类型、用户或业务标识、输入 Token、输出 Token、缓存 Token、响应状态和错误码,不要记录完整 API Key。
官方用量页面支持按组织、项目、用户和时间范围查看活动,也可以用一分钟区间观察 TPM。控制台数据使用 UTC,和本地日志对照时要统一时区。查看方法可参考 Reviewing API usage and costs;模型的输入、缓存输入和输出费率以 OpenAI API Pricing 为准。
降低输入 Token 的四个实用方法
- 删除重复上下文。多轮对话不要无条件把全部历史消息重新发送;可以保留必要事实,把已经完成的讨论压缩成摘要。
- 分段处理长文档。先把文档切成任务相关的小段,再对中间结果汇总,避免每次请求都携带整份原文。
- 把稳定内容放在前面。系统提示词、固定规则和通用示例尽量形成稳定前缀,动态用户内容放在后面,有利于提示词缓存复用。
- 先测再换模型。用代表性输入记录输入、输出、缓存和推理 Token,比较完成同一任务的总成本,而不是只看回复表面长度。
提示词缓存会复用请求中相同的提示词前缀,官方说明其目的包括减少重复计算、降低缓存输入 Token 成本和改善首字节延迟。缓存默认只对支持的模型启用,缓存命中并非由保持会话本身保证;缓存输入仍然计入 TPM。稳定前缀、最小可缓存长度和缓存字段都应按模型文档核对,详见 OpenAI Prompt caching 指南。
需要注意,缓存不是“免费 Token”,也不是月度预算。它只能改变部分输入 Token 的处理和费率,输出 Token、推理 Token、请求数量以及未命中的输入仍可能产生费用。
从开发到生产的成本控制清单
- 开发阶段:为每个实验记录模型、请求参数、输入输出 Token 和响应耗时;先验证输出是否满足需求,再提高上限。
- 测试阶段:使用固定样本比较不同模型的总 Token 和总成本,覆盖短输入、长上下文、工具调用和失败重试。
- 上线前:分离开发与生产项目,配置 Spend alert 和 Hard spend limit,确认负责人有 Usage Dashboard 权限。
- 运行中:按项目和用户聚合 usage,观察 TPM、请求量、429 比例、超时和重试次数。
- 异常时:先查项目、模型、用户和时间段,再检查是否出现重复重试、循环调用、上下文膨胀或暴露的 Key。
- 模型调整:以完成任务的总成本和质量为依据,不只按每百万 Token 单价选择模型。
最小可行的闭环是:请求参数限制单次输出,应用层限制用户和并发,项目设置限制月度支出,日志和控制台负责发现偏差。四层缺一时,仍可能出现“单次回答不长但总费用持续上升”的情况。
常见问题
max_completion_tokens 能限制 OpenAI API 的月度费用吗?
不能。它只限制单次 Chat Completions 请求生成的 Token,不能限制请求次数、输入 Token、其他用户流量或整月支出。月度费用应通过 Spend alert、Hard spend limit、应用层配额和 Usage Dashboard 共同控制。
Chat Completions 和 Responses API 限制输出 Token 的参数一样吗?
不一样。Chat Completions 使用 max_completion_tokens,Responses API 使用 max_output_tokens。Responses 的输出上限还可能包含推理 Token,实际可见文字长度应根据模型和 usage 判断。
设置了 Hard spend limit 后,费用一定不会超过这个金额吗?
不能作绝对保证。官方说明硬上限的执行存在传播延迟,记录支出可能略微超过配置值。它适合阻止持续流量,不应被理解为精确到实时账单的断路器。
Token 成本应该按 total_tokens 直接乘一个单价吗?
通常不应这样简化。输入、缓存输入和输出可能采用不同费率,推理 Token 也可能计入输出用量。应根据响应 usage 拆分 Token 类别,再使用目标模型官方定价页的对应费率计算。
遇到 429 时,应该马上重试吗?
先判断 429 的原因。如果是临时速率限制,应优先遵循 Retry-After,并限制重试次数、总等待时间和并发;如果 error.code 表示组织或项目支出上限,继续重试通常不能解决问题,应先检查预算和用量。