雨天小六

读懂 Codex(5.24):Output Schema 和结构化结果验证

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

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

Codex 把 final_output_json_schema 编译成 Responses text.format,严格模式由服务端约束模型输出。通用采样链不会再在本地用 JSON Schema 验证一次;它仍把最终内容作为 Assistant Message 文本交付,专用调用方可再反序列化自己的领域类型。

具体问题与启用条件

本节区分请求约束、服务端严格验证、客户端 JSON 解析和领域 fallback,避免把四件事合成一个“结构化输出解析器”。

条件来源决定字段或状态对本机制的影响
Turn 输入final_output_json_schema=Some(Value)Prompt 携带 output_schema
请求编译output_schema_strict生成 text.format.strict
Guardian reviewer source特殊来源strict=false;普通 Turn 默认 true

协议、类型与状态所有权

状态或协议所有者生命周期关键不变量
JSON Schema ValueTurnContext一次 Turn,可由输入覆盖不作为文本指令拼接
TextControls.formatModelClient一次请求name 固定 codex_output_schema
Schema enforcementResponses 服务端生成期间Core 依赖服务合同
最终 JSON 文本Assistant Message/调用方Item Done 后通用 Core 不返回已验证 Value

机制调用链如下:

Op::UserInput(final_output_json_schema)
→ TurnContext snapshot
→ Prompt.output_schema + strict flag
→ create_text_param_for_request
→ text.format{name,type=json_schema,schema,strict}
→ Responses 服务端约束输出
→ Message OutputText
→ Core 原样交付文本
→ 专用消费者可 json.loads/deserialize
Output Schema 从 Turn 输入到 Responses text.format
图 5.24-1:Schema 始终是结构化请求字段,不拼进自然语言指令。

机制怎样工作

build_prompt 从 TurnContext 复制 final schema。普通来源把 strict 设为 true,Guardian reviewer 例外为 false。请求编译器只有在 verbosity 或 schema 至少一个存在时才创建 text;schema 被包进固定 name codex_output_schema 和 type json_schema。这部分有纯序列化测试固定字段形状。

响应回来后仍走普通 Message 路径。json_result 集成测试会在测试端把 AgentMessage 文本交给 serde_json::from_str,证明服务端返回符合 Schema 的 JSON,而且 Core 没有改写它;这不是通用 Core 内置的 Schema Validator。Review 等专用流程另行尝试反序列化领域类型,失败时可截取首个 JSON Object 或退回纯文本解释。由此可见,“模型输出受约束”和“客户端拿到强类型对象”之间仍有一层应用解析。

Python 风格伪代码

这段伪代码保留生产实现中会改变结果的状态、分支和异步边界;认证 SDK、遥测字段和 Rust 所有权样板被折叠为明确的领域对象。

def text_controls(verbosity: str | None, schema: dict | None,
                  strict: bool) -> dict | None:
    if verbosity is None and schema is None:
        return None
    controls: dict = {}
    if verbosity is not None:
        controls["verbosity"] = verbosity
    if schema is not None:
        controls["format"] = {
            "type": "json_schema",
            "name": "codex_output_schema",
            "strict": strict,
            "schema": schema,
        }
    return controls

async def consume_structured_result(message: str, decoder: Callable[[dict], T]) -> T:
    # 应用层验证;通用模型流只交付 message
    value = json.loads(message)
    return decoder(value)  # 可再用 jsonschema/Pydantic 校验

失败、取消与恢复

服务端结构约束与客户端强类型解析的边界
图 5.24-2:Core 交付完整文本,领域消费者自行决定是否再次验证。
故障或边界已发生的状态对上层的结果能否直接重试恢复动作
Schema 本身不被服务接受请求未生成响应InvalidRequest修正支持的 JSON Schema
strict=false 输出偏离 SchemaMessage 仍可完成应用解析失败不自动专用 fallback/重新请求
调用方期待 dict 但收到文本Core 合同被误解类型错误显式 json.loads + validate
流在 Message Done 前断开可能见到半截 JSON Delta不提交结果只解析完整 Message

设计取舍与验证

把 Schema 交给服务端可在生成阶段约束结构,减少客户端“生成后再拒绝”的浪费。通用 Core 不重复验证保持 Provider 无关和低依赖,代价是调用方若需要强类型保证必须再解析。专用 fallback 提升容错,但不应被宣传为严格 Schema 成功。

可验证契约证据方式预期结果
strict true/false 精确序列化client_common 单元测试format 字段逐项相等
最终 JSON 作为 AgentMessage 交付json_result 集成测试调用方可成功 parse
无 schema/verbosity 时省略 text序列化测试请求不发空 controls

Mini Codex 对照

Mini Codex 应把输出约束和结果解析分成 RequestCompilerStructuredResultDecoder[T]。若 Provider 不支持 JSON Schema,必须报告能力缺失或用明确的弱保证 fallback,不能仍声称 strict。

本节边界

本节能证明 wire Schema 和消息交付,不能把服务端实现细节写成本地验证算法。5.25 处理最后一个普通流生命周期问题:取消时暂态、连接与已完成 Item 怎样收尾。

评论


← 返回文章列表