GPT‑6.1 Sol 工具调用失败?完整迁移到 Responses API

排查 GPT‑6.1 Sol 的端点与推理参数,完成工具执行、call_id 回传、状态保存和终止控制,附可下载代码与离线测试。

暖灰色背景上的镂空模板线稿,标题为 GPT-6.1 Sol Tools。

把模型名改成 gpt-6.1-sol 后工具失效,先检查端点,再改提示词。GPT‑6.1 Sol 的工具调用需要 Responses API;Chat Completions 虽然支持文本请求,但不支持该模型的工具调用。它还不接受 none 和 minimal 推理档位,因此只换模型名可能留下不兼容的旧请求。

本文以只读库存查询串起请求、工具执行和结果回传,提供完整 Python 文件与离线测试。测试使用合成响应检查应用逻辑,不是付费 API 实测,也不是模型性能测评。技术事实于 2026 年 9 月 30 日核对模型文档、迁移指南和函数调用文档。

先定位是哪一层失败

工具流程至少有四层:客户端构造请求、模型返回结构化调用、应用执行获准函数、应用把结果送回模型。只说“工具不能用”还不足以定位。

现象先查哪里处理方向
还没输出就被拒绝端点与字段改用 Responses,移除不兼容参数
只有文字,没有调用是否传入 tools、任务要求和工具选择检查结构化输出,不只看可见答案
返回调用但没执行应用分发器在本地执行白名单函数
下一轮接不上结果call_id 与历史保留原调用项,回传同一 ID
反复调用不结束工具错误、缺失数据、轮数限制回传明确错误,并有上限
界面说完成却没有结果成功判定必须有真实工具证据

不要在尚未分类时反复重试。不支持的参数不会在第五次自动变成支持;鉴权错误也不能用限流的处理办法解决。

官方英文文档注明 Sol 工具调用需要 Responses

真实英文文档截图,证明的是接口限制,不是库存工具已经运行成功。

请求结构也要迁移

Responses 的函数定义如下。name、description、parameters 直接放在工具对象上,不能原样照搬 Chat Completions 的 function 包装结构。

tool = {
    "type": "function",
    "name": "lookup_stock",
    "description": "Read stock for one known product SKU.",
    "parameters": {
        "type": "object",
        "properties": {"sku": {"type": "string"}},
        "required": ["sku"],
        "additionalProperties": False,
    },
    "strict": True,
}

最小请求使用 client.responses.create、input 和 reasoning={"effort": "medium"},并给出合适的 max_output_tokens。可用档位是 low、medium、high、xhigh、max;产品界面的 Ultra 不能直接写成 API 枚举。

当前迁移指南还要求为此类推理请求移除不支持的采样字段,例如 temperature、top_p、top_logprobs,以及相应的输出 log probabilities 请求。网关或 SDK 可能自动带入你没有显式写出的默认值。错误指向哪个字段,就检查最终发出的配置,而不只是模型名附近的几行代码。排查记录保留端点、模型、字段名、状态与请求 ID,避免暴露密钥。

跑通完整只读示例

下载 tool_loop.py。文件包含 Schema、两个虚构商品的库存、参数校验、白名单分发器、有界循环和离线测试。商品与数量是教学数据,不是业务记录。

先用 Python 3.9 或更新版本运行:

python3 tool_loop.py --self-test

预期显示 offline checks passed。此路径只用标准库,不读取 Key,不安装客户端,也不联网。它覆盖正确调用、损坏的 JSON、非法参数、未知函数、未知 SKU、未完成响应和轮数上限,并检查成功结果必须来自正确的库存查询。

若要在自己已获授权的 API 项目中实调,可以建立独立环境:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade openai
# 通过环境设置 OPENAI_API_KEY,不提交到代码仓库。
python tool_loop.py --live

--live 会产生 API 用量,需要 gpt-6.1-sol 访问权限;本文未执行付费路径。示例显式使用 OpenAI 官方 API 地址,避免环境中的其他 base URL 意外改变路由。任务查询 DEMO-A,本地样本库存是 12。验收需要实际出现 lookup_stock 调用、匹配的返回结果,以及与 12 一致的最终答案。只出现一句流畅回答不能算通过。

执行时记录 SDK 版本。安装命令获取当前官方包,并不表示本文对该环境完成了真实线上兼容性测试。

保留输出项,准确回传 call_id

完整循环的关键逻辑是:

history.extend(response.output)
for call in calls:
    result = dispatch(call.name, call.arguments)
    history.append({
        "type": "function_call_output",
        "call_id": call.call_id,
        "output": json.dumps(result),
    })

应保留 response.output,包括协议需要的推理项,不能只拿 response.output_text 重建历史。文本只是响应的一部分。一次返回多个调用时,逐个执行并用各自原始 call_id 回传;工具名不能替代 ID,客户端也不能自己另造一个。

本例重发完整累积历史,不同时附加 previous_response_id。也可以采用官方的有状态方式,但不能不清楚服务器已保存哪些内容,就把完整重放与上次响应引用混在一起,否则可能重复上下文。选定一种状态方案,再检查下一轮实际收到什么。

当响应不含工具调用时,脚本要求状态完成、存在最终文本,而且此前确实完成了 DEMO-A 返回 12 的正确查询。错误工具调用、未知商品或空 trace 都不能满足成功条件。脚本仍不自动判断自然语言答案是否与库存一致,最后的内容核对不可省。拒绝、未完成、传输失败或空输出也不能被包装成“成功”。

执行前必须由应用校验

严格 Schema 有助于约束参数,不等于服务端校验,更不授予执行权限。示例先解析 JSON,要求恰好一个字符串 sku,再检查函数白名单。商品不存在时返回结构化 unknown_sku。它不执行模型生成的 shell,也不把工具返回文字当作新指令。

教学例子把非法参数变成有界错误对象,供下一轮处理。生产系统还应记录错误类别,并在同一种非法操作反复出现时终止。不要把整库内容、隐私信息或完整异常堆栈塞进工具结果,只提供完成任务需要的内容。

写操作需要额外设计。网络超时后重试,可能重复一个服务器其实已完成的动作。支付、删除、部署等流程应考虑操作 ID、持久化状态和对应审批规则。本例刻意只读,目的是演示协议,而不是假装已经解决所有写入授权问题。

时间、轮数、费用分别设上限

脚本限定模型轮数,达到上限便报错;实调路径配置 SDK 超时并关闭自动重试,让失败可见。这是教学默认值,不是适用于所有生产任务的推荐参数。

轮数上限不等于金额上限:不同轮次的输入输出量不同,历史还可能跨过长上下文门槛。服务化后应补请求账本与预算限制,参见费用计算指南。

瞬时网络或限流错误可以在剩余预算内按退避策略重试;非法参数、不支持的端点和无模型权限,应先纠正根因。工具超时不能靠编造库存继续;达到轮数上限应标记任务未完成,并保存可排查的 ID。

替换旧链路前怎样验收

在隔离项目里使用合成输入,逐项确认:实际请求是 Responses 和精确模型 ID;响应包含结构化调用;应用执行白名单函数;下一轮包含原输出项和匹配结果;最终答案与库存样本一致。再把离线套件中的失败情形接入你的集成测试。

上线保留可回滚的模型与端点配置,用同一批任务比较结果,避免同时改模型、提示词、工具和权限。四项一起变,失败原因很难分辨。升级指南负责总体迁移决策,Codex 使用排查负责产品客户端,两者不替代自建 API 循环的协议验证。