Skip to content

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 或远程 MCPResponses API这些托管工具以 Responses 的工具模型为主
语义搜索、RAG 召回、相似度计算Embeddings + 向量数据库生成向量与生成回答是两个不同步骤
语音电话、实时打断、低延迟双向音频Realtime API它是长连接事件协议,不是普通 HTTP 请求的升级版
大量相互独立的离线请求Batch API使用 JSONL 批量提交,适合吞吐优先的任务
需要把 PDF、文档交给 File SearchFiles + 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 的最小示例:

python
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参数格式、字段组合或输入内容不合法修复请求,不要盲目重试
401API key 无效或缺失检查密钥与部署环境,不把密钥写进日志
403项目、区域、模型或权限不允许检查项目权限和模型可用性
404资源 ID、模型或路径不存在校验资源生命周期和环境配置
409资源状态冲突重新读取资源状态后决定是否继续
413请求或文件过大压缩、分片或改用文件/异步流程
429速率、并发或配额限制退避重试、限流、排队,不能无上限重试
5xx服务端或依赖暂时异常有界指数退避,记录 request ID
网络超时结果可能未知对读操作可重试;对写操作先查询或使用幂等设计

服务端应记录请求 ID、内部 run_id、模型、接口、耗时、状态码和 token 用量,但不要把 API key、完整敏感 prompt 或未经脱敏的工具输出写进普通日志。对长任务来说,客户端看到的“请求超时”不等于模型没有执行完成,任务状态必须存在独立的持久化存储中。

2.3 重试要先问“会不会重复副作用” ​

模型生成本身通常可以在策略允许时重试,但工具调用可能创建订单、发邮件、修改文件或写数据库。对于这类操作:

  1. 为一次业务意图生成稳定的幂等键。
  2. 把工具调用、参数摘要和幂等键落入运行记录。
  3. 超时后先查询外部系统是否已经成功。
  4. 无法确认时进入 UNKNOWN 或人工对账,不要直接当作失败重做。

API 层的 HTTP 重试和业务副作用的幂等不是同一个问题。SDK 帮你重发请求,并不代表外部业务一定不会被重复执行。

3. Responses API:新项目的主线 ​

3.1 最小请求和最小响应 ​

Responses API 的 endpoint 是:

text
POST /v1/responses

最简单的文本请求:

python
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 为准
outputtyped output Items 数组,可能包含 message、reasoning、function_call 等不同类型
output_textSDK 提供的便捷文本聚合字段;复杂流程仍应遍历 output
usage输入、缓存输入、输出和推理 token 等用量信息
error / incomplete_details失败或未完整生成时的结构化信息
created_at、model创建时间和实际模型信息

不要默认把 response.output[0] 当成最终文本。推理模型、工具调用和多模态输出都可能让 output 包含多个不同类型的 Item。只有确认是纯文本场景时,才使用 output_text 这个便捷属性。

3.2 Responses 请求参数分组 ​

下面按“它影响请求的哪一部分”来理解,而不是把所有参数当成同一层的旋钮。

A. 模型与输入 ​

参数类型作用与注意点
modelstring指定模型。模型决定能力、模态、参数支持、速率和价格
inputstring 或 Item 数组用户输入或完整输入上下文;可以包含文本、图像、文件和工具结果
instructionsstring顶层系统/开发者指导;与 input 分开,便于每轮稳定传入
conversationstring 或对象将响应绑定到持久 Conversation;由平台维护该会话的输入与输出 Item
previous_response_idstring将当前响应连接到上一响应,适合连续多轮;不代表历史输入免费,也不自动继承上一轮 instructions

conversation 和 previous_response_id 都能帮助管理上下文,但语义不同:前者是一个可持续的会话资源,后者是响应链路。若应用需要自己裁剪历史、实现租户隔离或控制数据保留,应明确选择手动传递 input Items,而不是只依赖平台状态。

B. 输出预算与推理 ​

参数类型作用与注意点
max_output_tokensinteger输出上限,推理模型中通常同时覆盖可见输出和 reasoning tokens;太小可能导致结果不完整
reasoningobject推理模型相关配置,例如推理强度或摘要选项;具体字段取决于模型和当前 API 版本
temperaturenumber部分模型支持的随机性参数;并非所有推理模型都支持,先查模型文档
top_pnumber核采样参数;与 temperature 通常选择一个调试,不要同时大幅调整
truncationstring控制上下文过长时的处理策略,使用前确认模型和接口的支持方式
max_tool_callsinteger限制内置工具调用次数,避免一次请求中的工具使用失控

max_output_tokens 是“硬预算”,而 reasoning 或 verbosity(如果目标模型支持)更多是“行为引导”。模型可能把预算用在不可见推理上,因此“最终文本很短”不等于“这次只消耗了很少 token”。

C. 工具与 Agent 能力 ​

参数类型作用与注意点
toolsarray声明模型可使用的函数工具或 OpenAI 托管工具
tool_choicestring 或 object控制工具自动选择、强制选择或禁止工具
parallel_tool_callsboolean是否允许同一轮提出多个可并行工具调用;有共享写状态时要谨慎
includearray请求额外返回的内容,例如 File Search 结果、Web Search 来源、代码执行输出或加密 reasoning 内容

Responses 原生工具常见类型包括 Web Search、File Search、Code Interpreter、Computer Use、Image Generation 和远程 MCP。工具是 Responses 的重要优势,但“平台提供工具”不等于“业务授权已经解决”:应用仍要校验用户身份、租户、资源权限和高风险操作审批。

D. 状态、存储与异步 ​

参数类型作用与注意点
storeboolean控制响应是否存储;需要无状态或特定数据保留策略时应显式设置
backgroundboolean将长耗时响应作为后台任务运行,之后查询状态或通过 webhook 接收完成事件
metadatamap附加少量结构化标签,便于检索、排查和运营分析;不要放敏感原文
promptobject引用平台中的可复用 prompt 模板和版本(若项目启用该能力)
prompt_cache_keystring用于提示缓存分桶的稳定键,具体支持范围和效果以模型文档为准

不要因为设置了 store: true 就把 Responses 当成自己的业务数据库;也不要因为使用 previous_response_id 就认为应用不需要保存 run_id、授权信息和审计事件。平台响应状态与企业业务状态仍然是两套状态。

3.3 Responses 的 Item 模型 ​

Chat Completions 把很多信息揉在 messages 和 choices[].message 中,Responses 把它们拆成有类型的 Item。常见 Item 包括:

Item 类型方向用途
messageinput/output普通用户或助手消息,content 还可以细分为文本、图像等部分
reasoningoutput/input推理模型的推理上下文或摘要;是否返回、是否能持久化取决于设置
function_calloutput模型提出调用自定义函数的意图
function_call_outputinput应用执行函数后回传的结果,通过 call_id 关联
web_search_calloutput托管 Web Search 的调用记录
file_search_calloutput托管 File Search 的调用记录
code_interpreter_calloutput代码解释器调用及其状态、输出或文件产物

这种拆分的价值是:上下文不再只是字符串拼接,而是一个可以被运行时、UI、审计和工具执行器分别理解的 typed event/item 流。代价是迁移时不能把每个 output Item 都强行转换成一条普通 assistant message。

3.4 多轮状态的三种方式 ​

方式一:使用 previous_response_id ​

python
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:

python
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 中,自定义函数工具通常使用这种形状:

python
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "查询城市当前天气",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
            "additionalProperties": False,
        },
        "strict": True,
    }
]

执行过程如下:

text
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 结构。文本流常见事件包括:

text
response.created
response.output_text.delta
response.output_text.done
response.completed
error

函数调用参数也可能分片到多个事件中,例如:

text
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 是:

text
POST /v1/chat/completions

最小请求:

python
completion = client.chat.completions.create(
    model="your-model",
    messages=[
        {"role": "system", "content": "你是一名严谨的技术助手。"},
        {"role": "user", "content": "什么是向量数据库?"},
    ],
)

print(completion.choices[0].message.content)

它的基本模型是:

text
messages[]
  -> Chat Completion
  -> choices[]
      -> message 或 tool_calls

4.2 messages 的角色与内容 ​

role作用关键注意点
developer开发者指令支持范围与优先级取决于模型;新模型常使用它承载应用约束
system系统指令存量代码最常见;不要假设所有模型对它的处理完全相同
user用户输入content 可以是文本或支持的多模态内容数组
assistant历史助手输出工具调用时必须保留相应的 tool call 信息
tool工具执行结果使用 tool_call_id 对应模型提出的调用
function老的函数消息形式历史兼容字段,新的工具调用代码优先使用 tools/tool

一个工具调用回合:

json
{
  "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. 基础输入 ​

参数类型作用与注意点
modelstring选择模型;支持范围由模型决定
messagesarray对话消息数组;角色、content 形状和工具消息必须匹配接口要求
storeboolean是否存储输出,当前默认和可用性应按账户与接口文档确认
metadatamap为请求附加有限的结构化标签

B. 采样与输出长度 ​

参数类型作用与注意点
temperaturenumber调整采样随机性;低值通常更稳定,高值变化更多
top_pnumber核采样;通常与 temperature 选一个调整
max_completion_tokensinteger生成上限;对支持推理的模型,可能包含 reasoning tokens
max_tokensinteger历史长度参数,已被新参数替代;兼容服务可能仍要求它
stopstring 或 array命中特定序列后停止;并非所有最新模型支持
ninteger一次生成多个候选;总输出 token、延迟和成本都会增加
frequency_penaltynumber根据已出现频率惩罚重复
presence_penaltynumber根据是否出现过惩罚重复,鼓励引入新 token/话题
logit_biasmap按 tokenizer 的 token ID 调整候选 token 的 logits,难以跨模型迁移

temperature 和 top_p 都影响“选哪个 token”,不要在一次实验里同时大幅修改两者。max_completion_tokens 解决“最多生成多少”,并不保证输出一定完整;需要结合 finish_reason 判断是否被截断。

C. 工具与结构化输出 ​

参数类型作用与注意点
toolsarray声明 function 或其他支持的工具
tool_choicestring 或 objectnone 禁止,auto 自动选择,required 要求调用,或强制某个函数
parallel_tool_callsboolean是否允许一轮返回多个工具调用;并发写操作需要额外协调
response_formatobject文本、JSON object 或 JSON Schema 结构化输出;Responses 对应 text.format

Chat Completions 的 function 工具通常写在 tools[].function 下;Responses 的函数定义则把 name、description、parameters 放在 function tool 对象本身。迁移时不能只换 endpoint,必须同时调整 schema、响应解析和工具结果回传。

D. 流式和概率信息 ​

参数类型作用与注意点
streamboolean以 SSE 逐块返回结果
stream_options.include_usageboolean流结束前追加完整用量 chunk;中断时可能收不到
logprobsboolean返回输出 token 的对数概率,支持情况依模型而定
top_logprobsinteger每个位置附带更多候选 token 概率,通常要求 logprobs=true

4.4 Chat Completions 的响应 ​

重点字段:

字段作用
idcompletion 标识
choices候选结果数组;每项有 message、index、finish_reason
choices[].message.content普通文本结果
choices[].message.tool_calls模型提出的工具调用
finish_reasonstop、length、tool_calls 等终止原因,具体取值按模型/接口确认
usage输入、输出和总 token 用量
system_fingerprint历史响应字段;新系统不要把它当作稳定复现机制

当 finish_reason 是 tool_calls 时,不能把 message.content 当作最终答案;应读取 tool calls,执行并追加 tool 消息,再发起下一次请求。

5. Responses 与 Chat Completions 的核心差异 ​

5.1 概念映射表 ​

Chat CompletionsResponses迁移时要做什么
POST /v1/chat/completionsPOST /v1/responses更换 endpoint 和 SDK 调用入口
messagesinput,可以是字符串或 Item 数组重新确认消息、文件、图像和工具结果的类型
system / developer message顶层 instructions 或兼容消息 Item每轮明确传入稳定指令,尤其是使用 previous_response_id 时
choices[0].message.contentoutput_text 或遍历 output复杂输出不能只取第一项
choices[].message.tool_callsfunction_call output Item读取 name、arguments、call_id
role: toolfunction_call_output input Item使用同一个 call_id 关联结果
response_formattext.format调整结构化输出的配置位置和 schema 形状
stream 的 delta chunktyped 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 迁移检查清单 ​

text
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:

text
POST /v1/embeddings

核心参数:

参数作用
model选择 embedding 模型
input一个字符串、字符串数组或模型支持的输入
encoding_format返回向量的编码形式,例如浮点数组或 base64,支持范围看模型文档
dimensions对支持该能力的模型请求较低维度输出,需同步调整向量库 schema
user 或相应终端用户标识旧代码中可能出现,具体合规字段按当前文档确认

Embeddings API 只负责把输入映射成向量,不负责最终回答。典型 RAG 链路是:

text
文档切分
  -> Embeddings API
  -> 向量数据库
  -> 查询文本 embedding
  -> 相似度召回 / 混合检索 / rerank
  -> Responses 或 Chat Completions 生成答案

要注意三件事:

  1. 建库和查询必须使用兼容的 embedding 模型、维度和距离度量。
  2. 向量维度不是越高越好,最终看召回质量、延迟、存储和成本。
  3. 文档权限不能只靠向量相似度解决,检索时必须带租户、用户和资源过滤条件。

6.2 Moderation API ​

Endpoint:

text
POST /v1/moderations

它用于对文本和图像输入进行安全分类。常见参数是 model 和 input,具体输入格式取决于模型。官方文档说明,当前 moderation 模型可处理文本与图像,不能把它当作音频审核接口;Moderation endpoint 的收费和模型政策应以官方当前说明为准。

Moderation 的结果可以用于:

  • 输入前置拦截。
  • 输出发布前复核。
  • 高风险请求转人工。
  • 账号或会话风险累计。

它不是完整的业务授权系统,也不是 prompt injection 的唯一防线。高风险工具仍需要独立的身份、权限、审批和审计链路。

6.3 Images API ​

常见 endpoint 包括:

text
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/speechmodel、input、voice、response_format、部分模型支持的 instructions
语音转文字/v1/audio/transcriptionsfile、model、language、prompt、response_format、时间戳选项
音频翻译/v1/audio/translations音频文件、目标模型和输出格式

音频接口一般是一次 HTTP 请求或文件处理流程,而 Realtime API 面向持续会话。不要用“录完整段音频后上传”的方式假装实现实时打断和低延迟对话。

6.5 Realtime API ​

Realtime API 面向低延迟双向交互,支持 WebRTC、WebSocket 或 SIP 等连接方式。它的核心不是一个巨大的 JSON 请求,而是:

text
建立会话
  -> 配置 session
  -> 发送 client events
  -> 接收 server events
  -> 持续追加文本/音频输入
  -> 触发 response
  -> 处理增量输出、工具调用、打断和错误

设计 Realtime 应用时要额外处理:会话生命周期、心跳、断线重连、音频缓冲、用户打断、事件顺序、客户端权限和临时凭证。Realtime 事件协议不能直接复用 Chat Completions 或 Responses 的普通 HTTP 解析器。

6.6 Files API 与 Vector Stores API ​

Files API 负责上传和管理文件;Vector Stores API 负责把文件组织成可检索的向量资源。它们的关系可以理解为:

text
上传文件
  -> 得到 file_id
  -> 创建或选择 vector_store
  -> 关联文件或 file_batch
  -> 等待索引完成
  -> Responses 使用 file_search tool

核心工程问题不是记住一个 file_id,而是:

  • 文件是否属于正确的项目、租户和数据保留策略。
  • 索引是否完成,失败时如何重试和告警。
  • 删除原文件后,向量库中的索引是否同步失效。
  • 检索是否返回来源、文件版本和权限过滤结果。
  • 大批量文件是否使用 file batch,而不是一个请求一个文件串行上传。

Responses 的 File Search 能力减少了应用自己实现检索工具的工作,但企业知识库仍要自己负责数据授权、版本、更新和审计。

6.7 Batch API ​

Batch API 适合大量相互独立、对实时延迟不敏感的请求。典型流程:

text
准备 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 页面或配置中心读取当前单价。抽象公式是:

text
文本模型成本
= 未缓存输入 token / 1,000,000 × 输入单价
 + 缓存命中输入 token / 1,000,000 × 缓存输入单价
 + 输出 token / 1,000,000 × 输出单价
 + reasoning / 其他模态 / 托管工具费用

如果 usage 能提供 prompt_tokens_details.cached_tokens,则可以近似这样拆:

python
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 请求可能长这样:

text
[稳定的系统指令]
[稳定的工具 schema]
[稳定的输出约束]
[会话历史与本轮工具结果]
[本轮用户问题]

前面几段如果长期保持相同,就有机会命中缓存;后面的动态内容通常会变化。缓存命中可以减少延迟和输入成本,但不能改变模型输出逻辑,也不能替代应用自己的结果缓存。

7.4 怎样提高缓存命中率 ​

最有效的策略是让每轮请求的长前缀稳定:

  1. 把稳定的系统指令放在前面,动态用户信息放在后面。
  2. 工具列表、工具顺序、JSON schema 和描述保持稳定,不要每轮随机排序。
  3. 不要把当前时间、request ID、随机 UUID、用户输入拼进 system prompt 的前缀。
  4. 对工具结果、检索结果和历史消息做稳定序列化,避免无意义空格、顺序和格式变化。
  5. 按合理的业务范围使用 prompt_cache_key,例如按应用、租户或工作流版本分桶;不要把所有用户隐私内容混进同一个共享前缀。
  6. 大段稳定规则不要每轮重复生成不同措辞;需要改规则时显式递增 prompt 版本。
  7. 让上下文压缩在稳定边界发生:不要每一轮都重写整段 system prompt,摘要和动态历史放在后部。
  8. 记录 cached_tokens / prompt_tokens,按模型、路由、租户和 workflow 版本观察,而不是凭感觉认为“应该命中”。

缓存命中率公式可以写成:

text
缓存命中率 = cached_input_tokens / total_input_tokens

但单纯追求高命中率也可能损害质量。例如为了保持前缀不变,把本轮真正重要的用户约束放到模型看不到的位置,或者把不该跨用户共享的信息放进共享缓存,都属于错误优化。应同时看任务成功率、延迟、成本和数据隔离。

8. 生产环境中的统一设计 ​

8.1 统一封装,不要把接口差异泄露到业务层 ​

可以在应用内部抽象出一层统一模型调用接口:

python
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 的部分文本成为系统事实。建议分开:

text
模型事件流 -> UI 展示层
模型/工具/状态事件 -> 运行时和审计层
最终验证结果 -> 业务状态和 artifact

例如 Coding Agent 流式显示“正在修改文件”时,只有文件写入成功、diff 检查通过且测试完成后,业务状态才能变成“修改已验证”。

8.4 兼容服务的“OpenAI compatible”意味着什么 ​

第三方服务说兼容 OpenAI,通常只代表它实现了部分 URL、请求字段和响应形状,不代表:

  • 所有参数都支持。
  • Chat 和 Responses 都支持。
  • 工具调用语义完全一致。
  • 流式事件名称和顺序相同。
  • usage 中有完整的缓存和 reasoning 细分。
  • 错误码、限流、价格和数据保留策略相同。

模型网关应维护能力矩阵,例如:

能力Provider AProvider B本地服务
Responses支持不支持不支持
Chat Completions支持支持支持
Function calling支持部分支持视模型而定
Structured Outputs支持JSON mode需应用校验
Streamingtyped eventsdelta 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. 一页式决策总结 ​

text
新建文本/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

持续学习,持续实践。