雨天小六

读懂 Codex(5.10):完整请求和增量请求的选择条件

· 更新于 2026-08-02 · 专栏:读懂 Codex

#Codex#Agent Runtime#Responses API#流式协议#软件架构

连接复用并不自动允许增量请求。Codex 要同时证明所有非 Input 属性相同,并证明当前 Input 以“上次请求 Input + 上次完成输出项”为严格前缀,才发送剩余 delta。

具体问题与启用条件

本节给出完整/增量选择算法。Response ID 怎样保存和失效由 5.11 接着说明。

条件来源决定字段或状态对本机制的影响
传输Responses WebSocketHTTP SSE 始终发送完整 body
历史状态存在 last_request 与已完成 LastResponse提供比较基线
内容关系属性相等且 Input 前缀相等允许 previous + delta

协议、类型与状态所有权

状态或协议所有者生命周期关键不变量
last_requestWebsocketSession上一次发送后到重置保存完整逻辑请求,不是 wire delta
LastResponse.items_addedmap_response_events仅 Completed 后可取只含 OutputItemDone 项
incremental_itemsprepare_websocket_request当前发送是当前 Input 剩余后缀

机制调用链如下:

构造当前完整 ResponsesApiRequest
→ 取上次 Completed 的 LastResponse
→ 比较所有非 Input 属性
→ baseline = last_request.input + last_response.items_added
→ 与 current.input 前缀逐项比较
→ 匹配:previous_response_id + suffix
→ 不匹配:完整请求
完整请求与增量请求的选择算法
图 5.10-1:三个证明条件任一失败都安全回退完整请求。

机制怎样工作

属性比较采用穷举解构,新增请求字段若未作复用决定会在编译期暴露。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)

失败、取消与恢复

增量后缀和完整回退的上下文等价关系
图 5.10-2:只有 A+B 得到证明时才省略它们,否则传输重新发送完整上下文。
故障或边界已发生的状态对上层的结果能否直接重试恢复动作
任一非 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 后有效。

评论


← 返回文章列表