OpenAI API 核心接口与参数指南
阅读目标:看完这篇后,你不应该只会背几个请求字段,而应该能回答三个问题:当前任务应该选哪个接口?请求和响应中的关键数据如何流转?怎样处理状态、工具、token、缓存、错误和成本?
OpenAI 的 API 不是一个单独的“聊天接口”。它是一组围绕模型能力和平台资源组织的接口:有用于文本、图像和工具调用的模型生成接口,有用于实时语音的 Realtime API,也有用于文件、向量库、批处理、微调和评估的资源或任务接口。
其中,Responses API 是新项目优先学习的模型交互接口;Chat Completions API 仍然受支持,并且因为生态成熟、第三方服务大量兼容,仍然会长期出现在存量系统中。官方迁移文档把 Responses 描述为 Chat Completions 的演进,并建议新项目优先使用 Responses。两者不是“一个马上不能用、另一个只是实验品”的关系,而是两种抽象层次不同的接口。
本文以官方当前 API 文档为基准,核对日期为 2026-09-04。接口字段、模型支持范围、价格和限制会变化,实际开发仍应以目标模型的 API Reference 为准。本文不把所有管理后台接口逐字段展开,而是重点覆盖 AI 应用开发、Agent、RAG 和企业应用最常用的接口。
1. 先看懂 OpenAI API 的接口地图
先把接口按“它在系统中扮演的角色”分类,比按 URL 背参数更容易建立整体认识。
| 类别 | 代表接口 | 解决什么问题 | 常见应用 |
|---|---|---|---|
| 模型生成 | Responses API、Chat Completions API | 给模型输入,得到文本、结构化结果、工具调用或多模态输出 | 对话、Agent、问答、信息抽取、代码生成 |
| 向量表示 | Embeddings API | 把文本或其他支持的输入转换为向量 | 语义检索、相似度、聚类、RAG |
| 内容安全 | Moderation API | 判断文本或图像输入是否涉及安全风险 | 输入拦截、输出复核、人工审核路由 |
| 图像 | Images API、Responses 的图像生成工具 | 生成或编辑图像 | 文生图、图片编辑、Agent 生成视觉素材 |
| 音频与实时交互 | Audio API、Realtime API | 转写、翻译、语音合成和低延迟多轮语音会话 | 语音助手、会议转写、电话机器人 |
| 文件与知识资源 | Files API、Vector Stores API | 上传文件、管理文件、建立可检索资源 | 文件问答、File Search、知识库 |
| 异步与批处理 | Batch API、Background responses、Webhooks | 把长耗时或大量请求变成可追踪任务 | 离线分类、批量 embedding、批量评估 |
| 模型适配 | Fine-tuning、Evals、Datasets | 训练定制模型、评估模型和管理数据集 | 领域适配、回归测试、模型优化 |
| 平台管理 | Models、Projects、API keys、Usage、Audit logs | 管理组织、项目、模型访问和运营数据 | 多项目治理、权限、审计、配额管理 |
1.1 按场景选接口
| 需求 | 优先考虑 | 原因 |
|---|---|---|
| 新建文本问答、Agent、工具调用应用 | Responses API | 输入输出是 typed Items,原生支持工具、状态和 Agent 能力 |
已经有 messages -> choices 的生产系统 | Chat Completions | 改造成本低,第三方 OpenAI 兼容服务支持广 |
| 需要自己维护完整对话历史,且追求供应商兼容 | Chat Completions 或 Responses 的手动 input | 上下文由应用自己掌控,便于统一抽象 |
| 需要 Web Search、File Search、Code Interpreter、Computer Use 或远程 MCP | Responses API | 这些托管工具以 Responses 的工具模型为主 |
| 语义搜索、RAG 召回、相似度计算 | Embeddings + 向量数据库 | 生成向量与生成回答是两个不同步骤 |
| 语音电话、实时打断、低延迟双向音频 | Realtime API | 它是长连接事件协议,不是普通 HTTP 请求的升级版 |
| 大量相互独立的离线请求 | Batch API | 使用 JSONL 批量提交,适合吞吐优先的任务 |
| 需要把 PDF、文档交给 File Search | Files + Vector Stores + Responses tools | 文件上传、索引和模型检索是不同资源阶段 |
一个常见误区是把“接口”与“模型”混为一谈:Responses API 和 Chat Completions API 是接口抽象;具体模型决定支持哪些输入模态、推理参数、工具和上下文能力。换模型时,不要只改 model 字符串,还要重新检查参数支持、输出结构、价格、速率限制和评估结果。
一个小场景:做“请假政策助手”
用户问“我还剩几天年假?”,系统通常不是只调用一次文本生成:先用 Responses 接收问题,再由模型提出查询员工假期的函数调用;服务端验证员工身份和权限,调用人事系统,把结果以 function_call_output 送回模型,最后才生成自然语言答复。若换成 Chat Completions,消息、工具调用字段和结果回传方式都要重新适配。把这条链路画出来,比死记参数名更不容易漏掉权限和幂等处理。
2. 所有 HTTP API 都共享的基础
2.1 认证、客户端和服务端边界
API 请求通常使用 Authorization: Bearer $OPENAI_API_KEY。API key 应只放在服务端、受控的 Worker 或安全的 CI 环境中,不应直接打包到浏览器、移动端或用户可下载的 JavaScript 里。浏览器或移动端需要调用时,应由服务端代理,或使用专门的短期客户端凭证机制。
Python SDK 的最小示例:
from openai import OpenAI
client = OpenAI() # 默认从 OPENAI_API_KEY 读取密钥
response = client.responses.create(
model="your-model",
input="用一句话解释什么是 RAG。",
)
print(response.output_text)不要把示例中的模型名直接当作永远有效的模型名。生产系统应通过配置选择模型,并把实际使用的模型、模型版本或快照记录到 trace 中。
2.2 失败不是只有一种
应用层至少应区分以下错误:
| 类别 | 常见原因 | 处理方式 |
|---|---|---|
400 | 参数格式、字段组合或输入内容不合法 | 修复请求,不要盲目重试 |
401 | API key 无效或缺失 | 检查密钥与部署环境,不把密钥写进日志 |
403 | 项目、区域、模型或权限不允许 | 检查项目权限和模型可用性 |
404 | 资源 ID、模型或路径不存在 | 校验资源生命周期和环境配置 |
409 | 资源状态冲突 | 重新读取资源状态后决定是否继续 |
413 | 请求或文件过大 | 压缩、分片或改用文件/异步流程 |
429 | 速率、并发或配额限制 | 退避重试、限流、排队,不能无上限重试 |
5xx | 服务端或依赖暂时异常 | 有界指数退避,记录 request ID |
| 网络超时 | 结果可能未知 | 对读操作可重试;对写操作先查询或使用幂等设计 |
服务端应记录请求 ID、内部 run_id、模型、接口、耗时、状态码和 token 用量,但不要把 API key、完整敏感 prompt 或未经脱敏的工具输出写进普通日志。对长任务来说,客户端看到的“请求超时”不等于模型没有执行完成,任务状态必须存在独立的持久化存储中。
2.3 重试要先问“会不会重复副作用”
模型生成本身通常可以在策略允许时重试,但工具调用可能创建订单、发邮件、修改文件或写数据库。对于这类操作:
- 为一次业务意图生成稳定的幂等键。
- 把工具调用、参数摘要和幂等键落入运行记录。
- 超时后先查询外部系统是否已经成功。
- 无法确认时进入
UNKNOWN或人工对账,不要直接当作失败重做。
API 层的 HTTP 重试和业务副作用的幂等不是同一个问题。SDK 帮你重发请求,并不代表外部业务一定不会被重复执行。
3. Responses API:新项目的主线
3.1 最小请求和最小响应
Responses API 的 endpoint 是:
POST /v1/responses最简单的文本请求:
response = client.responses.create(
model="your-model",
instructions="你是一名严谨的技术助手。",
input="请解释向量数据库和关系数据库的区别。",
)
print(response.output_text)这里有两个值得记住的字段:
instructions:放系统级或开发者级指导。使用previous_response_id时,上一响应的顶层instructions不会自动继承,因此需要按请求重新传入稳定指令。input:可以是字符串,也可以是输入 Item 数组。输入 Item 可以表达消息、图片、文件、函数结果等不同类型。
响应不是 Chat Completions 的 choices 数组,而是一个带 id 的 Response 对象,核心字段包括:
| 字段 | 作用 |
|---|---|
id | 当前 response 的稳定标识,可用于后续关联 |
object | 对象类型,通常为 response |
status | 响应生命周期状态,具体取值以当前 API Reference 为准 |
output | typed output Items 数组,可能包含 message、reasoning、function_call 等不同类型 |
output_text | SDK 提供的便捷文本聚合字段;复杂流程仍应遍历 output |
usage | 输入、缓存输入、输出和推理 token 等用量信息 |
error / incomplete_details | 失败或未完整生成时的结构化信息 |
created_at、model | 创建时间和实际模型信息 |
不要默认把 response.output[0] 当成最终文本。推理模型、工具调用和多模态输出都可能让 output 包含多个不同类型的 Item。只有确认是纯文本场景时,才使用 output_text 这个便捷属性。
3.2 Responses 请求参数分组
下面按“它影响请求的哪一部分”来理解,而不是把所有参数当成同一层的旋钮。
A. 模型与输入
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
model | string | 指定模型。模型决定能力、模态、参数支持、速率和价格 |
input | string 或 Item 数组 | 用户输入或完整输入上下文;可以包含文本、图像、文件和工具结果 |
instructions | string | 顶层系统/开发者指导;与 input 分开,便于每轮稳定传入 |
conversation | string 或对象 | 将响应绑定到持久 Conversation;由平台维护该会话的输入与输出 Item |
previous_response_id | string | 将当前响应连接到上一响应,适合连续多轮;不代表历史输入免费,也不自动继承上一轮 instructions |
conversation 和 previous_response_id 都能帮助管理上下文,但语义不同:前者是一个可持续的会话资源,后者是响应链路。若应用需要自己裁剪历史、实现租户隔离或控制数据保留,应明确选择手动传递 input Items,而不是只依赖平台状态。
B. 输出预算与推理
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
max_output_tokens | integer | 输出上限,推理模型中通常同时覆盖可见输出和 reasoning tokens;太小可能导致结果不完整 |
reasoning | object | 推理模型相关配置,例如推理强度或摘要选项;具体字段取决于模型和当前 API 版本 |
temperature | number | 部分模型支持的随机性参数;并非所有推理模型都支持,先查模型文档 |
top_p | number | 核采样参数;与 temperature 通常选择一个调试,不要同时大幅调整 |
truncation | string | 控制上下文过长时的处理策略,使用前确认模型和接口的支持方式 |
max_tool_calls | integer | 限制内置工具调用次数,避免一次请求中的工具使用失控 |
max_output_tokens 是“硬预算”,而 reasoning 或 verbosity(如果目标模型支持)更多是“行为引导”。模型可能把预算用在不可见推理上,因此“最终文本很短”不等于“这次只消耗了很少 token”。
C. 工具与 Agent 能力
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
tools | array | 声明模型可使用的函数工具或 OpenAI 托管工具 |
tool_choice | string 或 object | 控制工具自动选择、强制选择或禁止工具 |
parallel_tool_calls | boolean | 是否允许同一轮提出多个可并行工具调用;有共享写状态时要谨慎 |
include | array | 请求额外返回的内容,例如 File Search 结果、Web Search 来源、代码执行输出或加密 reasoning 内容 |
Responses 原生工具常见类型包括 Web Search、File Search、Code Interpreter、Computer Use、Image Generation 和远程 MCP。工具是 Responses 的重要优势,但“平台提供工具”不等于“业务授权已经解决”:应用仍要校验用户身份、租户、资源权限和高风险操作审批。
D. 状态、存储与异步
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
store | boolean | 控制响应是否存储;需要无状态或特定数据保留策略时应显式设置 |
background | boolean | 将长耗时响应作为后台任务运行,之后查询状态或通过 webhook 接收完成事件 |
metadata | map | 附加少量结构化标签,便于检索、排查和运营分析;不要放敏感原文 |
prompt | object | 引用平台中的可复用 prompt 模板和版本(若项目启用该能力) |
prompt_cache_key | string | 用于提示缓存分桶的稳定键,具体支持范围和效果以模型文档为准 |
不要因为设置了 store: true 就把 Responses 当成自己的业务数据库;也不要因为使用 previous_response_id 就认为应用不需要保存 run_id、授权信息和审计事件。平台响应状态与企业业务状态仍然是两套状态。
3.3 Responses 的 Item 模型
Chat Completions 把很多信息揉在 messages 和 choices[].message 中,Responses 把它们拆成有类型的 Item。常见 Item 包括:
| Item 类型 | 方向 | 用途 |
|---|---|---|
message | input/output | 普通用户或助手消息,content 还可以细分为文本、图像等部分 |
reasoning | output/input | 推理模型的推理上下文或摘要;是否返回、是否能持久化取决于设置 |
function_call | output | 模型提出调用自定义函数的意图 |
function_call_output | input | 应用执行函数后回传的结果,通过 call_id 关联 |
web_search_call | output | 托管 Web Search 的调用记录 |
file_search_call | output | 托管 File Search 的调用记录 |
code_interpreter_call | output | 代码解释器调用及其状态、输出或文件产物 |
这种拆分的价值是:上下文不再只是字符串拼接,而是一个可以被运行时、UI、审计和工具执行器分别理解的 typed event/item 流。代价是迁移时不能把每个 output Item 都强行转换成一条普通 assistant message。
3.4 多轮状态的三种方式
方式一:使用 previous_response_id
first = client.responses.create(
model="your-model",
instructions="你是一个订单助手。",
input="订单 1001 现在是什么状态?",
)
second = client.responses.create(
model="your-model",
instructions="你是一个订单助手。",
previous_response_id=first.id,
input="如果已发货,预计什么时候送达?",
)适合普通多轮场景,代码简单。注意:历史输入 token 仍会进入计费;上一轮的顶层指令不自动继承;如果需要严格的数据保留和上下文裁剪,应选择其他方式。
方式二:应用自己保存并传递 Item
应用保存经过权限处理的输入和输出 Item,下一次将需要的 Item 放进 input。适合:
- 需要自己做摘要、裁剪和上下文预算。
- 需要把多租户、业务状态和模型历史分开保存。
- 需要在不同模型或供应商之间切换。
这种模式要求你正确保留工具调用和工具结果的关联,不能只保存最终自然语言文本,否则后续模型可能失去关键的工具上下文。
方式三:使用 Conversations API
当需要一个独立、持久、可复用的会话资源时,可以使用 Conversations API 与 Responses 配合。它适合多个请求围绕同一个会话对象推进;但仍应评估数据保留、租户隔离、删除和合规要求。
3.5 Responses 中的结构化输出
Responses 的结构化输出配置放在 text.format,而不是 Chat Completions 的 response_format:
response = client.responses.create(
model="your-model",
input="Jane 今年 34 岁。",
text={
"format": {
"type": "json_schema",
"name": "person",
"description": "人物信息",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0},
},
"required": ["name", "age"],
"additionalProperties": False,
},
"strict": True,
}
},
)结构化输出解决的是“输出形状不稳定”,不是“内容一定正确”。仍需处理:模型拒答、响应不完整、业务字段语义错误、数字范围和数据库约束。应用端应做二次 schema 校验和业务校验。
3.6 Responses 中的函数调用
在 Responses 中,自定义函数工具通常使用这种形状:
tools = [
{
"type": "function",
"name": "get_weather",
"description": "查询城市当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
"strict": True,
}
]执行过程如下:
1. 应用把 tools schema 传给 Responses
2. 模型返回 function_call(name, arguments, call_id)
3. 应用解析 arguments,做 schema 和权限校验
4. 应用真正执行函数
5. 应用构造 function_call_output,并带上同一个 call_id
6. 把新的 input Item 发送给 Responses
7. 模型继续调用工具,或返回最终 message关键点:模型只提出调用意图,不执行函数;call_id 是调用和结果的关联键;函数结果不能直接拼接成一段没有来源标识的文本;工具执行器要有超时、幂等、输出截断和脱敏。
3.7 Responses 流式输出
设置 stream=True 后,Responses 返回的是有类型的 Server-Sent Events,而不是 Chat Completions 的 delta 结构。文本流常见事件包括:
response.created
response.output_text.delta
response.output_text.done
response.completed
error函数调用参数也可能分片到多个事件中,例如:
response.function_call_arguments.delta
response.function_call_arguments.done消费流时应做到:
- UI 可以实时显示文本增量,但不能把每个 delta 当成已经完成的业务事实。
- 工具调用参数需要按 call ID 和事件顺序拼接,完整后再校验和执行。
- 处理中断、断线和
error事件;不能只等待一个“字符串结束”标记。 - 服务端保存最终 response 或业务 artifact,避免只在浏览器内存中保留结果。
4. Chat Completions API:兼容与存量系统
4.1 它的抽象是什么
Chat Completions 的 endpoint 是:
POST /v1/chat/completions最小请求:
completion = client.chat.completions.create(
model="your-model",
messages=[
{"role": "system", "content": "你是一名严谨的技术助手。"},
{"role": "user", "content": "什么是向量数据库?"},
],
)
print(completion.choices[0].message.content)它的基本模型是:
messages[]
-> Chat Completion
-> choices[]
-> message 或 tool_calls4.2 messages 的角色与内容
| role | 作用 | 关键注意点 |
|---|---|---|
developer | 开发者指令 | 支持范围与优先级取决于模型;新模型常使用它承载应用约束 |
system | 系统指令 | 存量代码最常见;不要假设所有模型对它的处理完全相同 |
user | 用户输入 | content 可以是文本或支持的多模态内容数组 |
assistant | 历史助手输出 | 工具调用时必须保留相应的 tool call 信息 |
tool | 工具执行结果 | 使用 tool_call_id 对应模型提出的调用 |
function | 老的函数消息形式 | 历史兼容字段,新的工具调用代码优先使用 tools/tool |
一个工具调用回合:
{
"messages": [
{"role": "system", "content": "你是天气助手。"},
{"role": "user", "content": "北京现在多少度?"},
{
"role": "assistant",
"tool_calls": [
{
"id": "call_123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"北京\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_123",
"content": "{\"temperature_c\": 28}"
}
]
}messages 是应用自己维护的上下文,不是模型的永久记忆。每次请求都要传入当前需要的历史,或者由应用使用摘要、裁剪、检索和外部记事本控制长度。
4.3 Chat Completions 常用参数
A. 基础输入
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
model | string | 选择模型;支持范围由模型决定 |
messages | array | 对话消息数组;角色、content 形状和工具消息必须匹配接口要求 |
store | boolean | 是否存储输出,当前默认和可用性应按账户与接口文档确认 |
metadata | map | 为请求附加有限的结构化标签 |
B. 采样与输出长度
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
temperature | number | 调整采样随机性;低值通常更稳定,高值变化更多 |
top_p | number | 核采样;通常与 temperature 选一个调整 |
max_completion_tokens | integer | 生成上限;对支持推理的模型,可能包含 reasoning tokens |
max_tokens | integer | 历史长度参数,已被新参数替代;兼容服务可能仍要求它 |
stop | string 或 array | 命中特定序列后停止;并非所有最新模型支持 |
n | integer | 一次生成多个候选;总输出 token、延迟和成本都会增加 |
frequency_penalty | number | 根据已出现频率惩罚重复 |
presence_penalty | number | 根据是否出现过惩罚重复,鼓励引入新 token/话题 |
logit_bias | map | 按 tokenizer 的 token ID 调整候选 token 的 logits,难以跨模型迁移 |
temperature 和 top_p 都影响“选哪个 token”,不要在一次实验里同时大幅修改两者。max_completion_tokens 解决“最多生成多少”,并不保证输出一定完整;需要结合 finish_reason 判断是否被截断。
C. 工具与结构化输出
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
tools | array | 声明 function 或其他支持的工具 |
tool_choice | string 或 object | none 禁止,auto 自动选择,required 要求调用,或强制某个函数 |
parallel_tool_calls | boolean | 是否允许一轮返回多个工具调用;并发写操作需要额外协调 |
response_format | object | 文本、JSON object 或 JSON Schema 结构化输出;Responses 对应 text.format |
Chat Completions 的 function 工具通常写在 tools[].function 下;Responses 的函数定义则把 name、description、parameters 放在 function tool 对象本身。迁移时不能只换 endpoint,必须同时调整 schema、响应解析和工具结果回传。
D. 流式和概率信息
| 参数 | 类型 | 作用与注意点 |
|---|---|---|
stream | boolean | 以 SSE 逐块返回结果 |
stream_options.include_usage | boolean | 流结束前追加完整用量 chunk;中断时可能收不到 |
logprobs | boolean | 返回输出 token 的对数概率,支持情况依模型而定 |
top_logprobs | integer | 每个位置附带更多候选 token 概率,通常要求 logprobs=true |
4.4 Chat Completions 的响应
重点字段:
| 字段 | 作用 |
|---|---|
id | completion 标识 |
choices | 候选结果数组;每项有 message、index、finish_reason |
choices[].message.content | 普通文本结果 |
choices[].message.tool_calls | 模型提出的工具调用 |
finish_reason | stop、length、tool_calls 等终止原因,具体取值按模型/接口确认 |
usage | 输入、输出和总 token 用量 |
system_fingerprint | 历史响应字段;新系统不要把它当作稳定复现机制 |
当 finish_reason 是 tool_calls 时,不能把 message.content 当作最终答案;应读取 tool calls,执行并追加 tool 消息,再发起下一次请求。
5. Responses 与 Chat Completions 的核心差异
5.1 概念映射表
| Chat Completions | Responses | 迁移时要做什么 |
|---|---|---|
POST /v1/chat/completions | POST /v1/responses | 更换 endpoint 和 SDK 调用入口 |
messages | input,可以是字符串或 Item 数组 | 重新确认消息、文件、图像和工具结果的类型 |
system / developer message | 顶层 instructions 或兼容消息 Item | 每轮明确传入稳定指令,尤其是使用 previous_response_id 时 |
choices[0].message.content | output_text 或遍历 output | 复杂输出不能只取第一项 |
choices[].message.tool_calls | function_call output Item | 读取 name、arguments、call_id |
role: tool | function_call_output input Item | 使用同一个 call_id 关联结果 |
response_format | text.format | 调整结构化输出的配置位置和 schema 形状 |
stream 的 delta chunk | typed response events | 更新事件处理器,不能复用旧 chunk 解析逻辑 |
应用自己维护 messages | 手动 Item、previous_response_id 或 Conversations | 选择状态归属、裁剪和数据保留策略 |
n 多候选生成 | Responses 不提供同名 n | 需要多候选时发起多次请求并自行管理成本 |
| 自己实现 Web Search 等工具 | Responses 原生工具或自定义工具 | 评估托管工具的权限、成本、证据和数据边界 |
5.2 什么时候继续用 Chat Completions
继续使用 Chat Completions 并不等于技术落后,合理场景包括:
- 现有业务已经围绕
messages、choices和稳定的 function calling 建成完整测试。 - 供应商、私有化模型或本地推理服务只提供 Chat Completions 兼容接口。
- 业务需要
n多候选,且当前实现已经有候选排序和成本控制。 - 团队有统一的模型网关,希望底层不同供应商都暴露同一个消息协议。
但如果新项目需要 Responses 的原生工具、typed Items、连续 reasoning context、background mode 或最新 Agent 能力,应该优先从 Responses 开始,而不是先用 Chat Completions 自己重造一套编排层。
5.3 迁移检查清单
1. 请求 endpoint 从 /v1/chat/completions 改为 /v1/responses
2. messages 改为 input,检查每种 Item 的类型
3. system/developer 指令改用 instructions 或兼容 Item
4. choices[0].message.content 改为 output_text 或 output 遍历
5. tool_calls 改为 function_call Item,结果使用 function_call_output
6. 用 call_id 关联函数调用和函数结果
7. response_format 改为 text.format
8. Chat 的 delta 处理器改为 Responses typed event 处理器
9. 选择 previous_response_id、手动 Item 或 Conversations 的状态策略
10. 比较任务成功率、工具正确率、延迟、token、缓存和错误率官方迁移文档还强调,previous_response_id 不会免除历史输入 token 的计费;如果应用必须无状态运行,需要结合 store: false 和合适的加密 reasoning Item 策略,不能只删除本地对话数组。
6. 其他常用接口:不要把所有能力都塞进 Responses
6.1 Embeddings API
Endpoint:
POST /v1/embeddings核心参数:
| 参数 | 作用 |
|---|---|
model | 选择 embedding 模型 |
input | 一个字符串、字符串数组或模型支持的输入 |
encoding_format | 返回向量的编码形式,例如浮点数组或 base64,支持范围看模型文档 |
dimensions | 对支持该能力的模型请求较低维度输出,需同步调整向量库 schema |
user 或相应终端用户标识 | 旧代码中可能出现,具体合规字段按当前文档确认 |
Embeddings API 只负责把输入映射成向量,不负责最终回答。典型 RAG 链路是:
文档切分
-> Embeddings API
-> 向量数据库
-> 查询文本 embedding
-> 相似度召回 / 混合检索 / rerank
-> Responses 或 Chat Completions 生成答案要注意三件事:
- 建库和查询必须使用兼容的 embedding 模型、维度和距离度量。
- 向量维度不是越高越好,最终看召回质量、延迟、存储和成本。
- 文档权限不能只靠向量相似度解决,检索时必须带租户、用户和资源过滤条件。
6.2 Moderation API
Endpoint:
POST /v1/moderations它用于对文本和图像输入进行安全分类。常见参数是 model 和 input,具体输入格式取决于模型。官方文档说明,当前 moderation 模型可处理文本与图像,不能把它当作音频审核接口;Moderation endpoint 的收费和模型政策应以官方当前说明为准。
Moderation 的结果可以用于:
- 输入前置拦截。
- 输出发布前复核。
- 高风险请求转人工。
- 账号或会话风险累计。
它不是完整的业务授权系统,也不是 prompt injection 的唯一防线。高风险工具仍需要独立的身份、权限、审批和审计链路。
6.3 Images API
常见 endpoint 包括:
POST /v1/images/generations
POST /v1/images/edits生成或编辑时常见参数有:
| 参数 | 作用 |
|---|---|
model | 图像模型 |
prompt | 生成或编辑描述 |
size | 输出尺寸,受模型支持范围限制 |
quality | 质量档位,通常影响速度和价格 |
n | 生成图片数量,增加输出成本 |
background | 透明或不透明背景,需模型支持 |
output_format | 输出格式,例如 PNG、JPEG、WebP,受 endpoint/模型支持限制 |
| 输入图片 | 编辑时通过上传文件或 URL 等方式提供,具体格式按接口要求 |
moderation | 部分图像模型提供的内容审核档位 |
Responses 也可以通过 image generation tool 参与 Agent 流程。区别在于:Images API 是专门的图像资源生成接口;Responses 中的图像工具是 Agent 一次运行中的一个工具步骤。选择时看你是“单独生成图片”,还是“让 Agent 在多步任务中决定是否生成图片”。
6.4 Audio API
音频相关接口通常包括:
| 能力 | 代表 endpoint | 典型字段 |
|---|---|---|
| 语音合成 | /v1/audio/speech | model、input、voice、response_format、部分模型支持的 instructions |
| 语音转文字 | /v1/audio/transcriptions | file、model、language、prompt、response_format、时间戳选项 |
| 音频翻译 | /v1/audio/translations | 音频文件、目标模型和输出格式 |
音频接口一般是一次 HTTP 请求或文件处理流程,而 Realtime API 面向持续会话。不要用“录完整段音频后上传”的方式假装实现实时打断和低延迟对话。
6.5 Realtime API
Realtime API 面向低延迟双向交互,支持 WebRTC、WebSocket 或 SIP 等连接方式。它的核心不是一个巨大的 JSON 请求,而是:
建立会话
-> 配置 session
-> 发送 client events
-> 接收 server events
-> 持续追加文本/音频输入
-> 触发 response
-> 处理增量输出、工具调用、打断和错误设计 Realtime 应用时要额外处理:会话生命周期、心跳、断线重连、音频缓冲、用户打断、事件顺序、客户端权限和临时凭证。Realtime 事件协议不能直接复用 Chat Completions 或 Responses 的普通 HTTP 解析器。
6.6 Files API 与 Vector Stores API
Files API 负责上传和管理文件;Vector Stores API 负责把文件组织成可检索的向量资源。它们的关系可以理解为:
上传文件
-> 得到 file_id
-> 创建或选择 vector_store
-> 关联文件或 file_batch
-> 等待索引完成
-> Responses 使用 file_search tool核心工程问题不是记住一个 file_id,而是:
- 文件是否属于正确的项目、租户和数据保留策略。
- 索引是否完成,失败时如何重试和告警。
- 删除原文件后,向量库中的索引是否同步失效。
- 检索是否返回来源、文件版本和权限过滤结果。
- 大批量文件是否使用 file batch,而不是一个请求一个文件串行上传。
Responses 的 File Search 能力减少了应用自己实现检索工具的工作,但企业知识库仍要自己负责数据授权、版本、更新和审计。
6.7 Batch API
Batch API 适合大量相互独立、对实时延迟不敏感的请求。典型流程:
准备 JSONL
-> Files API 上传,purpose=batch
-> 创建 Batch,指定 endpoint 和 completion_window
-> 轮询 batch 状态或接收 webhook
-> 下载 output_file_id / error_file_id
-> 用每行的 custom_id 对应原始业务记录Batch 输入中的每一行通常需要唯一 custom_id、目标 method、url 和 body。可批处理的 endpoint 取决于官方当前支持列表,常见包括 Responses、Chat Completions、Embeddings、Moderations、Images 等;不能假设 Realtime 这类长连接接口也能放进 Batch。
Batch 的结果可能延迟很久,因此业务系统要保存批次 ID、输入文件、行级 custom ID、输出文件、失败文件和重试记录。它适合离线任务,不适合用户正在等待的交互式对话。
6.8 Fine-tuning、Evals、Models 与 Webhooks
这些接口更偏平台工程:
- Fine-tuning:提交训练文件、创建微调任务、查询状态和产出模型。它不能替代 RAG,也不能自动修复过时知识。
- Evals:用数据集和评分逻辑比较模型、prompt 或 Agent 版本。评估结果应与配置版本、模型版本和数据集版本绑定。
- Models:列出或读取项目可用模型的能力信息。生产配置不要只硬编码一个“最新模型”别名而不做回归。
- Webhooks:接收 Batch 完成、Background response 完成、Fine-tuning 完成等异步事件。必须验证签名、做幂等消费,并把 webhook 当作“唤醒信号”,最终状态仍应通过 API 查询确认。
7. Token、缓存和成本:从 usage 算出一次请求花了多少
“调用一次模型多少钱”不能只看 total_tokens,至少要拆开输入、缓存输入、可见输出和 reasoning tokens。
7.1 常见 token 字段
不同接口和模型的字段层级可能不同,但通常会看到这些概念:
| 概念 | 含义 |
|---|---|
| 输入 token | 本次请求送入模型的文本、工具 schema、历史和检索内容 |
| 缓存命中输入 token | 输入前缀命中 prompt cache 的 token,通常使用较低单价 |
| 未缓存输入 token | 没有命中缓存的输入 token,使用普通输入价格 |
| 可见输出 token | 用户最终看到的文本、结构化输出或工具参数 |
| reasoning token | 推理模型内部生成的推理 token,可能不可见但会计费并占输出预算 |
| 总 token | 输入与输出等 token 的汇总,具体定义按接口 usage 字段确认 |
| 工具/平台费用 | 某些托管工具、图像、音频或其他能力可能有独立费用,不一定包含在文本 token 中 |
Responses 链式调用也一样:使用 previous_response_id 方便传递状态,不等于历史输入 token 不计费。上下文是否由平台自动关联,与计费是否按输入 token 统计,是两个问题。
7.2 成本计算公式
不要把价格写死在文章或代码里,应该从官方 pricing 页面或配置中心读取当前单价。抽象公式是:
文本模型成本
= 未缓存输入 token / 1,000,000 × 输入单价
+ 缓存命中输入 token / 1,000,000 × 缓存输入单价
+ 输出 token / 1,000,000 × 输出单价
+ reasoning / 其他模态 / 托管工具费用如果 usage 能提供 prompt_tokens_details.cached_tokens,则可以近似这样拆:
uncached_input = prompt_tokens - cached_tokens
cost = (
uncached_input / 1_000_000 * input_price
+ cached_tokens / 1_000_000 * cached_input_price
+ output_tokens / 1_000_000 * output_price
)真实实现还要处理:
- 输入、缓存输入和输出单价不同。
- reasoning tokens 可能包含在 completion/output 总数中,也可能在 details 中单独展示,不能重复相加。
- 图像、音频、视频和托管工具可能按图片、秒数、调用次数或其他维度计价。
- Batch、Priority、Flex 等处理档位可能有不同价格和延迟特征。
- 失败请求、超时后重试和多个候选
n都可能产生费用。
因此应保存原始 usage JSON、价格配置版本、实际模型、接口、处理档位和计算后的金额,方便日后重新核算。
7.3 Token 缓存是什么
这里的 prompt token cache 不是“把上一次完整回答缓存起来”,也不是浏览器 HTTP 缓存。它通常指服务端发现多次请求的输入前缀相同,于是复用这部分前缀的处理结果。
一个 Agent 请求可能长这样:
[稳定的系统指令]
[稳定的工具 schema]
[稳定的输出约束]
[会话历史与本轮工具结果]
[本轮用户问题]前面几段如果长期保持相同,就有机会命中缓存;后面的动态内容通常会变化。缓存命中可以减少延迟和输入成本,但不能改变模型输出逻辑,也不能替代应用自己的结果缓存。
7.4 怎样提高缓存命中率
最有效的策略是让每轮请求的长前缀稳定:
- 把稳定的系统指令放在前面,动态用户信息放在后面。
- 工具列表、工具顺序、JSON schema 和描述保持稳定,不要每轮随机排序。
- 不要把当前时间、request ID、随机 UUID、用户输入拼进 system prompt 的前缀。
- 对工具结果、检索结果和历史消息做稳定序列化,避免无意义空格、顺序和格式变化。
- 按合理的业务范围使用
prompt_cache_key,例如按应用、租户或工作流版本分桶;不要把所有用户隐私内容混进同一个共享前缀。 - 大段稳定规则不要每轮重复生成不同措辞;需要改规则时显式递增 prompt 版本。
- 让上下文压缩在稳定边界发生:不要每一轮都重写整段 system prompt,摘要和动态历史放在后部。
- 记录
cached_tokens / prompt_tokens,按模型、路由、租户和 workflow 版本观察,而不是凭感觉认为“应该命中”。
缓存命中率公式可以写成:
缓存命中率 = cached_input_tokens / total_input_tokens但单纯追求高命中率也可能损害质量。例如为了保持前缀不变,把本轮真正重要的用户约束放到模型看不到的位置,或者把不该跨用户共享的信息放进共享缓存,都属于错误优化。应同时看任务成功率、延迟、成本和数据隔离。
8. 生产环境中的统一设计
8.1 统一封装,不要把接口差异泄露到业务层
可以在应用内部抽象出一层统一模型调用接口:
class ModelGateway:
def generate(self, request: "ModelRequest") -> "ModelResult":
"""统一处理模型、usage、重试、trace 和错误映射。"""
raise NotImplementedError业务层关心的是“生成文本、请求结构化结果或执行一个 Agent turn”;网关层负责把请求翻译为 Responses、Chat Completions 或其他供应商协议。不要为了统一而抹平所有差异:output Items、choices、typed streaming events、tool call 和 reasoning 状态应该在网关的结果模型中显式表达。
8.2 记录配置版本
一次模型调用至少应能追溯到:
run_id、request_id和用户/租户标识的脱敏版本。- 接口类型与 endpoint。
- 实际模型和模型版本。
- prompt 或 instructions 版本。
- 工具列表与 schema 版本。
- 知识库或 vector store 版本。
- temperature、top_p、max output 等参数。
- 输入、缓存输入、输出和 reasoning token。
- 处理档位、延迟、状态码和错误。
如果只保存“模型回答文本”,后面无法判断质量变化究竟来自模型、prompt、工具、知识库还是缓存策略。
8.3 流式输出的正确边界
流式输出适合改善用户体验,但不能让 UI 的部分文本成为系统事实。建议分开:
模型事件流 -> UI 展示层
模型/工具/状态事件 -> 运行时和审计层
最终验证结果 -> 业务状态和 artifact例如 Coding Agent 流式显示“正在修改文件”时,只有文件写入成功、diff 检查通过且测试完成后,业务状态才能变成“修改已验证”。
8.4 兼容服务的“OpenAI compatible”意味着什么
第三方服务说兼容 OpenAI,通常只代表它实现了部分 URL、请求字段和响应形状,不代表:
- 所有参数都支持。
- Chat 和 Responses 都支持。
- 工具调用语义完全一致。
- 流式事件名称和顺序相同。
- usage 中有完整的缓存和 reasoning 细分。
- 错误码、限流、价格和数据保留策略相同。
模型网关应维护能力矩阵,例如:
| 能力 | Provider A | Provider B | 本地服务 |
|---|---|---|---|
| Responses | 支持 | 不支持 | 不支持 |
| Chat Completions | 支持 | 支持 | 支持 |
| Function calling | 支持 | 部分支持 | 视模型而定 |
| Structured Outputs | 支持 | JSON mode | 需应用校验 |
| Streaming | typed events | delta chunks | 自定义 |
| Prompt cache usage | 有细分字段 | 不提供 | 自行实现 |
在切换 provider 前,必须用同一组回归样本测试请求兼容性,而不是只把 base_url 换掉。
9. 高频误区
误区一:OpenAI API 就是 Chat Completions
Chat Completions 是重要接口,但 Responses、Embeddings、Moderation、Images、Audio、Realtime、Files、Vector Stores 和 Batch 分别承担不同职责。先按场景选接口,再学习参数。
误区二:Responses 只是在 Chat Completions 上换了一个 URL
它的输入输出抽象、工具 schema、结构化输出、状态管理和流式事件都发生了变化。迁移要同时改请求、响应、上下文、工具和事件处理。
误区三:previous_response_id 就等于免费记忆
它解决的是响应之间如何关联,不代表历史输入 token 不收费,也不自动继承顶层 instructions。上下文、费用和数据保留要分别设计。
误区四:JSON Schema 通过就说明答案正确
Schema 只保证结构,不能保证事实、权限、业务规则和数值语义。结构化输出后仍要做业务校验。
误区五:模型返回了工具调用,工具就已经执行
模型返回的是意图。应用必须校验参数、授权、审批、幂等、超时和结果,再把结果作为正确类型的 Item 回传。
误区六:流式输出收到 [DONE] 就可以宣布成功
流式传输可能中断,且“文本生成结束”不等于工具执行成功或业务写入成功。最终状态应依赖持久化事件和验证结果。
误区七:Prompt cache 命中越高越好
缓存优化的前提是质量不降、数据不串、上下文仍然正确。应同时观察缓存 token、总成本、P95 延迟和任务成功率。
误区八:兼容 OpenAI 就支持全部 OpenAI 参数
兼容服务通常只实现一个子集。生产网关要做能力探测、参数降级和 provider 专属测试。
误区九:API 重试一定安全
如果请求触发了外部写操作,重试可能重复副作用。需要幂等键、状态查询和未知结果处理。
10. 一页式决策总结
新建文本/Agent 应用?
-> 先看 Responses API
维护已有 messages/choices 系统或接入 OpenAI 兼容服务?
-> Chat Completions 仍然合理
要做语义检索?
-> Embeddings + 向量数据库,不要让生成接口代替 embedding
要做文件知识库?
-> Files / Vector Stores,回答阶段再使用 File Search
要做实时语音?
-> Realtime API;普通 Audio API 负责转写、翻译或语音合成
要做大量离线请求?
-> Batch API,使用 custom_id 对应业务记录
要算成本?
-> 读取 usage,拆分未缓存输入、缓存输入、输出、reasoning 和其他模态费用
要提高缓存?
-> 保持长前缀稳定,把动态内容放后面,并用 cached_tokens 实测
要做生产系统?
-> 加上版本、trace、限流、重试、幂等、权限、数据保留和回归评估和课程其他章节的连接
| 本文主题 | 继续阅读 |
|---|---|
| Chat Completions 的 tool loop、工具结果回传 | 工具调用循环 |
| Function calling 的 schema、参数校验和执行边界 | Function Calling |
| 上下文裁剪、摘要、缓存与 token 预算 | 上下文工程 |
| Embeddings、向量库和 RAG 链路 | RAG Pipeline |