Skip to main content

三代 LLM API 技术演进白皮书

1. 演进总览

LLM API 的三代迭代,本质上是模型能力边界开发者编排复杂度之间的重新分配:

代际时间代表模型核心范式编排责任方
V1 Completions2020GPT-3 (Davinci)Prompt → Text开发者(100%)
V2 Chat Completions2023.03GPT-3.5 Turbo结构化对话 + 工具声明开发者(80%)
V3 Responses2025.03GPT-4.1 / GPT-5 系列有状态 Agent Loop服务端(60%)

核心规律:模型每新增一项原生能力(对话、工具调用、状态记忆),API 就向上抽象一层,将对应的编排复杂度从客户端迁移到服务端。


2. V1 Completions API:文本生成的原始形态

2.1 接口语义

Completions API 诞生于 GPT-3 时代,其设计哲学是**"无状态文本补全"**——模型仅作为概率分布生成器,对输入 prompt 进行续写。

POST /v1/completions
Content-Type: application/json

{
"model": "text-davinci-003",
"prompt": "为一家冰淇淋店写一句标语:",
"max_tokens": 50,
"temperature": 0.7
}

2.2 响应结构

{
"id": "cmpl-xxx",
"object": "text_completion",
"choices": [
{
"text": ""甜蜜每一刻,冰爽每一口!"",
"index": 0,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 15,
"total_tokens": 27
}
}

2.3 技术局限

维度状态技术影响
角色系统❌ 不存在无法区分系统指令、用户输入、模型输出
对话状态❌ 无状态多轮对话需客户端手动拼接历史
工具调用❌ 不支持无法与外部系统交互
上下文管理手动开发者自行计算 token 上限并截断
约束机制前缀注入仅能在 prompt 开头写指令,易被用户输入覆盖

2.4 对话模拟的脆弱性

在 V1 时代实现多轮对话,完全依赖字符串约定

系统:你是一名手机客服助手,请礼貌回答。
用户:我的手机开不了机。
客服:请长按电源键 10 秒以上。
用户:还是不行。

技术缺陷

  • 模型无法语义化区分 "系统"、"用户"、"客服" 边界
  • 角色漂移(Role Drift)概率极高
  • 无原生机制防止提示词注入攻击

3. V2 Chat Completions API:对话原语与工具链的奠基

3.1 架构升级

2023 年 3 月随 GPT-3.5 Turbo 发布,Chat Completions 将对话建模为一等公民数据结构,引入四种原生角色:

┌─────────────────────────────────────────┐
│ Chat Completions │
├─────────────────────────────────────────┤
│ Role: system → 全局行为约束 │
│ Role: user → 人类输入 │
│ Role: assistant → 模型输出 │
│ Role: tool → 工具执行结果 │
└─────────────────────────────────────────┘

关键突破:模型在后训练阶段针对这些角色做了专门强化,具备语义化的角色区分能力。

3.2 Function Calling 交互协议

Chat Completions 首次标准化了模型 → 工具 → 模型的三角交互协议:

Step 1:工具声明

POST /v1/chat/completions
Content-Type: application/json

{
"model": "gpt-4",
"messages": [
{"role": "system", "content": "你是一名天气助手。"},
{"role": "user", "content": "北京今天天气怎么样?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"]
}
}
}
],
"tool_choice": "auto"
}

Step 2:模型返回工具调用意图

{
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": "北京\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}

Step 3:客户端执行并回填

import json

# 解析第一层嵌套
tool_call = response.choices[0].message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)

# 本地执行工具
weather_result = get_weather(**arguments) # {"temperature": 32, "condition": "晴"}

# 手动重建完整对话历史
messages.append(response.choices[0].message) # assistant 的调用消息
messages.append({
"role": "tool",
"tool_call_id": "call_abc123",
"content": json.dumps(weather_result)
})

# 第二轮请求
second_response = client.chat.completions.create(
model="gpt-4",
messages=messages
)

Step 4:模型给出最终回答

{
"choices": [{
"message": {
"role": "assistant",
"content": "北京今天天气晴朗,气温 32°C,适合外出。"
},
"finish_reason": "stop"
}]
}

3.3 关键技术约束

约束 1:assistant / tool 消息必须成对

✅ 合法序列:
assistant(tool_calls) → tool(result) → assistant(text)

❌ 非法序列:
assistant(tool_calls) → user(text) [模型会将用户输入误判为工具结果]

模型在后训练时专门学习了这种成对模式,打破该模式会导致严重的语义错乱。

约束 2:content 与 tool_calls 互斥

{
"message": {
"content": null, // 有工具调用时强制为 null
"tool_calls": [...] // 与 content 互斥
}
}

这导致类型系统无法提供编译期保证,开发者必须在运行时进行分支判断。

3.4 五大技术痛点深度分析

痛点 1:Agent Loop 的胶水代码爆炸

# 一个完整的 Chat Completions Agent Loop(伪代码)
def agent_loop(user_input, tools, messages):
messages.append({"role": "user", "content": user_input})

while True:
response = client.chat.completions.create(
model="gpt-4", messages=messages, tools=tools
)
msg = response.choices[0].message
messages.append(msg)

if msg.finish_reason == "tool_calls":
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments) # 手动解析 JSON 字符串
result = execute_tool(tc.function.name, args) # 本地执行
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": json.dumps(result)
})
elif msg.finish_reason == "stop":
return msg.content
else:
raise AgentError(f"Unexpected finish_reason: {msg.finish_reason}")

复杂度来源

  • 手动解析 JSON 字符串参数
  • 手动维护消息数组顺序
  • 手动管理工具调用 ID 的映射关系
  • 无原生循环支持,需外层 while 包裹

痛点 2:返回路径的深层嵌套

获取单个工具参数需要遍历 4 层路径:

city = (
response
.choices[0] # 第 1 层:选择列表
.message # 第 2 层:消息对象
.tool_calls[0] # 第 3 层:工具调用列表
.function # 第 4 层:函数对象
.arguments # JSON 字符串,需再次解析
)

这种设计违背了最小惊讶原则(Principle of Least Astonishment),且对静态类型检查极不友好。

痛点 3:流式输出的状态机困境

Chat Completions 的 SSE 流只有一个事件类型 data,所有语义信息压缩在 delta 字段中:

event: data
data: {"choices":[{"delta":{"content":"北京"}}]}

event: data
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"city\""}}]}}]}

event: data
data: {"choices":[{"delta":{"finish_reason":"tool_calls"}}]}

技术债务

  • 客户端必须维护一个状态机来区分 content_deltatool_call_deltafinish_reason
  • 工具参数以增量 JSON 片段形式传输,需在客户端累积并解析
  • 无法通过事件名称直接路由处理逻辑

痛点 4:Reasoning 状态的每轮失忆

Round 1: 用户提问 → 模型思考 2000 tokens → 输出 tool_call
[思考过程:分析需求 → 识别意图 → 选择工具 → 构造参数]

Round 2: 工具结果回填 → 模型重新思考 2000 tokens → 输出答案
[思考过程:重新分析需求 → 重新识别意图 → ...]

每一轮 chat.completions.create() 都是一次独立的上下文窗口初始化,模型内部的 reasoning tokens(thinking tokens)不会被保留。对于代码审查、数学证明、复杂决策链等深度推理任务,这导致严重的 token 浪费和逻辑断裂。

痛点 5:请求体的参数平铺灾难

{
"model": "gpt-4",
"messages": [...],
"tools": [...],
"tool_choice": "auto",
"parallel_tool_calls": true,
"response_format": {"type": "json_object"},
"stream_options": {"include_usage": true},
"temperature": 0.7,
"max_tokens": 4096
}

所有控制开关平铺在顶层命名空间,缺乏逻辑分组:

  • response_format:输出格式控制
  • tool_choice:工具选择策略
  • parallel_tool_calls:并行调用开关
  • stream_options:流式元数据控制

这种设计导致参数命名空间污染,且新增能力时只能继续平铺,可维护性持续下降。


4. V3 Responses API:服务端托管的 Agent 运行时

4.1 架构范式转移

Responses API 的设计目标非常明确:将 Agent Loop 的执行时从客户端迁移到服务端

┌─────────────────────────────────────────────────────────────┐
│ 架构责任重新分配 │
├─────────────────────────────────────────────────────────────┤
│ Chat Completions │ Responses API │
│ ──────────────────────────│ ───────────────────────────── │
│ 客户端管理消息历史 │ 服务端通过 response_id 管理 │
│ 客户端执行工具 │ 内置工具服务端执行 │
│ 客户端解析流式状态 │ 语义化事件类型 │
│ 客户端维护推理上下文 │ 跨轮 reasoning 持久化 │
└─────────────────────────────────────────────────────────────┘

4.2 核心数据模型

请求模型

POST /v1/responses
Content-Type: application/json

{
"model": "gpt-4.1",
"input": [
{
"role": "user",
"content": "北京今天天气怎么样?"
}
],
"instructions": "你是一名天气助手。",
"tools": [
{
"type": "function",
"name": "get_weather",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
}
],
"tool_choice": "auto"
}

关键变化

  • messagesinput:更简洁的输入抽象,支持字符串或结构化 item 数组
  • system 角色 → instructions 字段:将系统提示从对话历史中解耦
  • instructions无状态的,不会通过 previous_response_id 继承

响应模型(工具调用阶段)

{
"id": "resp_xxx",
"status": "completed",
"output": [
{
"type": "function_call",
"call_id": "call_abc123",
"name": "get_weather",
"arguments": "{\"city\": "北京\"}"
}
],
"usage": {
"input_tokens": 45,
"output_tokens": 28
}
}

响应模型(最终回答阶段)

{
"id": "resp_yyy",
"previous_response_id": "resp_xxx",
"status": "completed",
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "北京今天晴,气温 25°C。"
}
]
}
]
}

4.3 五大技术改进详解

改进 1:有状态上下文管理(Stateful Context)

# Responses API 的 Agent Loop(伪代码)
def agent_loop_v3(user_input, tools):
# 第一轮:用户提问
resp1 = client.responses.create(
model="gpt-4.1",
input=user_input,
instructions="你是一名天气助手。",
tools=tools
)

# 检查输出类型并分发
for item in resp1.output:
if item.type == "function_call":
result = execute_tool(item.name, json.loads(item.arguments))

# 第二轮:仅传递工具结果 + 引用上轮
resp2 = client.responses.create(
model="gpt-4.1",
previous_response_id=resp1.id, # 关键:服务端自动恢复上下文
input=[{
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result)
}]
)
return resp2.output_text # SDK 便捷属性,无需遍历 choices[0]

技术收益

  • 无需手动维护 messages 数组
  • 无需担心消息顺序错误
  • 服务端负责 KV Cache 的命中与恢复

技术代价

  • 上下文压缩(Context Compression)的主动权交给服务端
  • Session 切换、消息编辑等高级操作受限
  • 大部分第三方 provider 实际未实现 previous_response_id 的有状态能力

改进 2:服务端内置工具(Server-Side Native Tools)

Chat Completions 的工具是声明式代理(Declarative Proxy):

客户端声明函数签名 → 模型决定是否调用 → 客户端本地执行 → 客户端解析结果

Responses API 将常用工具下沉为服务端原生能力

工具类型声明方式执行位置结果处理
web_search声明类型即可,无需传定义服务端返回带 citationweb_search_call
code_interpreter声明类型即可服务端沙箱返回执行结果 + 输出文件
file_search声明类型即可服务端向量检索返回检索片段
function需传完整 schema客户端客户端执行后回填

Web Search 返回示例

{
"output": [
{
"type": "web_search_call",
"status": "completed"
},
{
"type": "message",
"content": [
{
"type": "output_text",
"text": "根据最新搜索结果...",
"annotations": [
{
"type": "url_citation",
"url": "https://example.com/news",
"title": "今日北京天气"
}
]
}
]
}
]
}

技术意义

  • 开发者无需对接 Tavily/Serper 等外部搜索服务
  • 搜索执行、限流、结果解析、引用标注全部由服务端处理
  • 特别适合联网搜索、代码执行、文件检索等标准化场景

改进 3:工具延迟加载(Deferred Tool Loading)

在工具数量庞大的场景(如企业级 Agent 接入数百个内部 API),工具定义的 JSON Schema 会严重挤占上下文窗口。

方案 A:Defer Loading(延迟加载)

{
"tools": [
{
"type": "function",
"name": "crm::get_customer",
"defer_loading": true // 仅加载名称和描述,不加载完整 schema
},
{
"type": "function",
"name": "math::query",
"defer_loading": true
}
]
}

方案 B:Tool Search(增量检索)

{
"tools": [
{
"type": "tool_search",
"max_num_results": 2,
"namespaces": ["crm", "logistics"]
}
]
}

交互流程:

Round 1: 模型发现需要物流相关工具 → 返回 tool_search_call
Round 2: 客户端检索到 get_shipping_data → 通过 tool_search_output 传回
Round 3: 模型使用 get_shipping_data 完成后续推理

技术细节

  • tool_search_output 不会进入消息头部,避免污染主上下文
  • 模型在后训练阶段专门学习了 tool_search_output 的语义
  • 对比 Chat Completions 实现:需自行维护工具路由层,且动态更新 tools 列表可能导致 KV Cache 失效

改进 4:返回结构的类型安全(Typed Output)

Chat Completions 的 choices[0].message万能容器

msg = response.choices[0].message
# msg.content: Optional[str]
# msg.tool_calls: Optional[List[ToolCall]]
# msg.refusal: Optional[str]
# 必须运行时判断

Responses API 的 output带类型的异构数组

{
"output": [
{"type": "reasoning", "summary": "..."},
{"type": "function_call", "call_id": "...", "name": "..."},
{"type": "message", "content": [...]}
]
}

类型分发模式

for item in response.output:
match item.type:
case "reasoning":
process_thinking(item.summary)
case "function_call":
dispatch_tool(item)
case "message":
yield item.content[0].text
case "refusal":
raise SafetyException(item.explanation)

流式事件的语义化

事件类型语义Chat Completions 等价物
response.output_text.delta文本增量choices[0].delta.content
response.function_call_arguments.delta工具参数增量choices[0].delta.tool_calls[...].function.arguments
response.reasoning_summary_part.added推理摘要片段❌ 无对应(被丢弃)
response.completed响应完成choices[0].finish_reason

双刃剑效应

  • :事件名称即语义,无需状态机猜测
  • :事件类型超过 20 种,客户端需实现完整的事件分发层;简单 Q&A 场景下大量元数据事件属于冗余噪声

改进 5:Reasoning 状态的跨轮持久化

问题定义

在 Chat Completions 中,每轮调用都是独立的推理上下文:

Round 1: [User Q] → [Model thinks 2000 tokens] → [Tool Call]
↑_________________________________________↓
思考过程被丢弃,不进入 KV Cache 或消息历史

Round 2: [Tool Result] → [Model re-thinks 2000 tokens] → [Answer]
↑ 必须从头分析,无法复用 Round 1 的分析结论

Responses API 的解决方案

通过 previous_response_id 串联时,服务端的 KV Cache 保留 reasoning 状态的键值对:

# Round 1: 深度分析
resp1 = client.responses.create(
model="gpt-4.1",
input="这段代码的 bug 在哪里?",
reasoning={"effort": "high"} # 启用深度推理
)

# Round 2: 基于已有分析进行修复
resp2 = client.responses.create(
model="gpt-4.1",
previous_response_id=resp1.id, # 继承 reasoning 状态
input="好的,帮我修复它。"
)

性能数据(OpenAI 官方基准):

  • TauBench 任务准确率提升约 5%
  • KV Cache 利用率提升 40% - 80%
  • 深度推理任务(代码审查、数学证明、复杂决策链)收益显著

现实约束

  • DeepSeek 的 Responses API 实现不支持该能力
  • 持久化 reasoning 状态会占用额外的服务端资源
  • 实际收益高度依赖任务类型,需自行验证

5. 三代 API 技术规格对比矩阵

5.1 请求/响应模型对比

特性CompletionsChat CompletionsResponses API
输入字段prompt (string)messages (array)input (string or array)
系统提示前缀注入messages[0].role="system"instructions (无状态) 或 inputdeveloper 角色
角色体系system / user / assistant / tooluser / assistant / developer + 结构化 item 类型
工具声明❌ 不支持tools 数组,需完整 schematools 数组,支持 defer_loading
内置工具❌ 不支持❌ 不支持✅ web_search / code_interpreter / file_search
状态管理无状态无状态(客户端维护)previous_response_id 有状态串联
流式协议SSE data 事件SSE data 事件,delta 字段语义化命名事件(20+ 种)

5.2 开发者体验对比

维度Chat CompletionsResponses API
Agent Loop 代码量高(手动解析、执行、回填)低(previous_response_id 自动串联)
消息路径深度4 层(choices→message→tool_calls→function)2 层(output→typed_item)
类型安全弱(运行时判断 content/tool_calls)强(type 字段显式标记)
流式解析复杂度高(需状态机区分 delta 类型)中(事件分发即可,但事件类型多)
上下文控制权高(完全控制 messages 数组)低(交给服务端管理)
第三方生态成熟度中(较新,库和范例较少)

5.3 架构权衡对比

权衡维度Chat CompletionsResponses API
编排责任客户端重服务端重
数据出域仅模型输入/输出工具执行结果也流经服务端
供应商锁定低(可自建工具层)高(依赖服务端内置工具)
灵活性高(可任意修改消息历史)中(受限于服务端状态管理策略)
延迟优化空间大(客户端可并行、缓存)小(主要依赖服务端优化)

6. 生产环境选型建议

6.1 选择 Chat Completions 的场景

  • 需要完全控制对话历史:如消息编辑、删除、重新排序等高级操作
  • 多供应商兼容:需要同时对接 OpenAI、Anthropic、Google、DeepSeek 等
  • 工具执行敏感:工具涉及内部数据库、私有 API,不能将结果流经第三方服务端
  • 复杂流式处理:需要自定义流式事件的消费逻辑,而非使用标准事件分发
  • 已有成熟基础设施:大量基于 Chat Completions 的现有代码和中间件

6.2 选择 Responses API 的场景

  • 快速构建 Agent 原型:减少胶水代码,加速迭代
  • 重度依赖内置工具:频繁使用联网搜索、代码执行、文件检索
  • 深度推理任务:代码审查、数学证明、复杂多步决策(且 provider 支持 reasoning 持久化)
  • 工具数量庞大:需要 defer_loading 或 tool_search 管理上下文窗口
  • 单供应商部署:完全基于 OpenAI 生态,不担心供应商锁定

6.3 混合策略

┌─────────────────────────────────────────────┐
│ 混合架构示例 │
├─────────────────────────────────────────────┤
│ 对外接口:Chat Completions(兼容多厂商) │
│ 内部路由:根据任务类型分发 │
│ - 标准对话 → 各厂商 Chat Completions │
│ - 搜索/代码 → OpenAI Responses API │
│ - 敏感工具 → 本地 Chat Completions + 自管 │
└─────────────────────────────────────────────┘