连接复用并不自动允许增量请求。Codex 要同时证明所有非 Input 属性相同,并证明当前 Input 以“上次请求 Input + 上次完成输出项”为严格前缀,才发送剩余 delta。
具体问题与启用条件
本节给出完整/增量选择算法。Response ID 怎样保存和失效由 5.11 接着说明。
| 条件来源 | 决定字段或状态 | 对本机制的影响 |
|---|---|---|
| 传输 | Responses WebSocket | HTTP SSE 始终发送完整 body |
| 历史状态 | 存在 last_request 与已完成 LastResponse | 提供比较基线 |
| 内容关系 | 属性相等且 Input 前缀相等 | 允许 previous + delta |
协议、类型与状态所有权
| 状态或协议 | 所有者 | 生命周期 | 关键不变量 |
|---|---|---|---|
| last_request | WebsocketSession | 上一次发送后到重置 | 保存完整逻辑请求,不是 wire delta |
| LastResponse.items_added | map_response_events | 仅 Completed 后可取 | 只含 OutputItemDone 项 |
| incremental_items | prepare_websocket_request | 当前发送 | 是当前 Input 剩余后缀 |
机制调用链如下:
构造当前完整 ResponsesApiRequest
→ 取上次 Completed 的 LastResponse
→ 比较所有非 Input 属性
→ baseline = last_request.input + last_response.items_added
→ 与 current.input 前缀逐项比较
→ 匹配:previous_response_id + suffix
→ 不匹配:完整请求
机制怎样工作
属性比较采用穷举解构,新增请求字段若未作复用决定会在编译期暴露。model、instructions、tools、tool choice、parallel、reasoning、store、stream、include、service tier、cache key、text controls 都必须相等。stream_options 只影响本次事件交付,不定义 previous response 的上下文,因此忽略;client_metadata 也不参与模型上下文比较。
Input 基线还要把服务端上次完整输出项接在上次请求之后,因为下一次逻辑 Prompt 的 History 已记录这些项。比较时只忽略内部 chat metadata,其他字段、顺序和内容必须相同。允许空 delta 是为了预热后首请求复用;没有上次 Completed、Response ID 为空、长度不足或任一项变化,全部回退完整请求。
Python 风格伪代码
这段伪代码保留生产实现中会改变结果的状态、分支和异步边界;认证 SDK、遥测字段和 Rust 所有权样板被折叠为明确的领域对象。
def incremental_delta(current: Request, state: WsState) -> Incremental | None:
previous = state.last_request
response = state.take_last_completed_response()
if previous is None or response is None or not response.response_id:
return None
if not same_non_input_properties(previous, current):
return None
baseline = previous.input + response.items_added
if len(current.input) < len(baseline):
return None
for old, new in zip(baseline, current.input):
if normalize_internal_metadata(old) != normalize_internal_metadata(new):
return None
return Incremental(response.response_id, current.input[len(baseline):])
def choose_wire_request(current: Request, state: WsState) -> dict:
delta = incremental_delta(current, state)
return response_create(previous=delta.id, input=delta.items) if delta else response_create(previous=None, input=current.input)
失败、取消与恢复
| 故障或边界 | 已发生的状态 | 对上层的结果 | 能否直接重试 | 恢复动作 |
|---|---|---|---|---|
| 任一非 Input 属性变化 | 旧基线仍可保留 | 发送完整请求 | 不需要错误重试 | 更新 last_request |
| 当前 Input 更短 | 历史可能压缩/回滚 | 发送完整请求 | 不适用 | 不得引用旧 response |
| 前缀项内容或顺序变化 | 逻辑上下文已分叉 | 发送完整请求 | 不适用 | 重建服务端上下文 |
| 上次流未 Completed | 没有可靠 LastResponse | 发送完整请求 | 是 | 不使用半截输出 |
设计取舍与验证
严格比较会放弃部分理论可复用场景,但保护“增量线请求与完整逻辑请求模型可见内容等价”。穷举字段比较增加维护成本,却能防止新增输出 Schema 或 tool 控制字段后被错误忽略。
| 可验证契约 | 证据方式 | 预期结果 |
|---|---|---|
| 严格前缀只发送后缀 | 两次 WS 请求捕获 | 第二次 input 等于新增项 |
| 属性变化回退完整请求 | 逐字段参数化测试 | previous_response_id 缺失 |
| 跨 Turn 仍可评估增量 | 两 Turn 请求捕获 | 连接/基线复用但 turn token 重置 |
Mini Codex 对照
Mini Codex 应先实现完整请求,再把增量算法写成无副作用函数。比较字段要显式列出;不要用删掉 input 后的松散字典比较,以免新增字段默认被忽略。
本节边界
本节证明了何时可用增量。5.11 继续追踪其中的 response_id 和 receiver 为什么只在 Completed 后有效。
评论
登录后即可评论