接入教程

OpenAI 兼容 API 迁移:Responses、Base URL 与回滚

OpenAI 兼容 API 迁移应先冻结协议契约,再做脱敏影子验证、低风险灰度切流和一键回滚;只改 Base URL 不能证明迁移完成。

OpenAI 兼容 API 迁移从冻结协议契约到影子验证、灰度切流和一键回滚的门禁图
OpenAI 兼容迁移门禁:冻结契约、影子验证、灰度切流与一键回滚

先说结论: 把 Provider 配置与业务代码解耦,保留原端点,先用固定回归集验证七类契约,再按小流量灰度。只有当协议正确、业务质量、错误率、延迟和账单都达到预设门槛,并且回滚已经演练,才算完成迁移。

OpenAI 兼容 API 迁移经过协议字段流式工具调用用量错误和回滚七道验收门槛
OpenAI 兼容 API 迁移经过协议字段流式工具调用用量错误和回滚七道验收门槛

OpenAI Base URL 切换的四道迁移门禁是什么?

封面所示迁移状态是冻结契约 → 影子验证 → 灰度切流 → 一键回滚。每道门都要有可观察证据;影子请求只使用脱敏、无副作用样本,不能复制真实写操作。

状态必须固定或验证进入下一状态的证据
冻结契约SDK、wire API、模型、提示词、超时与重试可重复基线和 Provider 配置快照
影子验证对象形状、流式、工具、错误、用量与日志脱敏固定回归集双端点差异可解释
灰度切流低风险流量、错误、延迟、质量、费用预设门槛在代表性窗口内通过
一键回滚原端点、密钥、模型、队列和工具副作用恢复后冒烟与账单核对通过

OpenAI 兼容到底兼容什么?

“OpenAI 兼容”通常表示某些资源路径、鉴权方式和 JSON 结构可以被 OpenAI SDK 或相似客户端调用,但不自动包含全部功能。应把兼容范围写成可测试的契约。

契约面 必须确认的问题 常见假兼容表现
资源路径 支持 /v1/responses、/v1/chat/completions 还是两者 SDK 初始化成功,调用时 404
鉴权 Bearer Key、项目头和自定义头如何处理 密钥可用但项目归属错误
OpenAI 模型映射 模型 ID、别名、能力与下线策略 任意字符串都接受,实际路由不透明
OpenAI 流式事件兼容 SSE 事件、顺序、结束、错误与取消 最终文字可见,事件或用量丢失
OpenAI 工具调用兼容 调用 ID、参数分片、并行工具与结果回传 单工具成功,并行或续接失败
错误语义 400、401、404、429、5xx 是否可区分 所有失败都变成 500 或普通文本
用量账单 输入、输出、缓存、模型和费用能否关联 总余额变化,但请求级无法复算

OpenAI 官方文档说明,API 可能以兼容方式增加可选字段、响应属性和流式事件类型。客户端不能用“字段必须完全等于旧样本”的方式解析;网关也不能删除不认识的字段后假装兼容。

Responses API 迁移:Chat Completions 对比 Responses

契约面ResponsesChat Completions迁移断言
输入typed input Items 与 instructionsmessages[]不能只改路径后复用旧提取逻辑
输出typed output Items / output_textchoices[]断言对象类型与完成状态
流式response.* 语义事件choices[].delta chunk分别保存原始 SSE 夹具
工具function call/output Items 用 call_id 关联tool message 用 tool_call_id 关联覆盖并行、分片与续接
结构化输出text.formatresponse_format检测静默忽略或降级
多轮状态previous_response_id、Conversations 或自管历史应用回传 messages明确由谁保存和删除状态

供应商若只实现其中一条资源路径,应在能力表里写明。模型别名、上游、版本与下线策略也要可追踪,不能用“OpenAI 兼容”四个字代替协议清单。

迁移前先做一张配置清单

至少记录以下基线:

  • 当前 SDK 名称与版本;
  • 使用 Responses API 还是 Chat Completions;
  • Base URL、模型 ID、超时、重试和代理设置;
  • 系统或开发者消息、采样参数、最大输出;
  • 流式、结构化输出、工具调用和图像输入;
  • 请求 ID、Token、费用和错误日志在哪里查看;
  • 数据保留、区域、敏感信息与合规要求;
  • 原端点密钥、回滚开关和负责人。

迁移期间冻结与协议无关的 SDK、提示词和模型改动。一次只改变 Provider,才能知道问题来自哪里。

怎样设计可逆的 Provider 配置?

把端点、密钥、模型映射和协议类型放在配置层,业务代码只依赖内部模型名。示例使用占位变量,不要把真实密钥提交到仓库:

from dataclasses import dataclass
from openai import OpenAI
import os

@dataclass(frozen=True)
class Provider:
    name: str
    base_url: str
    api_key: str
    model: str
    protocol: str

provider = Provider(
    name=os.environ["AI_PROVIDER"],
    base_url=os.environ["AI_BASE_URL"],
    api_key=os.environ["AI_API_KEY"],
    model=os.environ["AI_MODEL"],
    protocol=os.environ.get("AI_PROTOCOL", "responses"),
)

client = OpenAI(api_key=provider.api_key, base_url=provider.base_url)

配置中心只保存密钥引用,密钥本体进入服务器端密钥管理系统。浏览器、移动端和公开日志中不应出现上游或中转站完整 API Key。

OpenAI 兼容 API 迁移需要哪些回归用例?

1. 普通响应

确认鉴权、模型字段、文本、结束状态和请求 ID。不要只检查 HTTP 200,还要断言对象结构和必需字段。

2. 流式响应

确认 Content-Type、首个事件、文本增量、结束事件、流内错误和主动取消。记录 TTFT 与总耗时,但不要把一次速度差异当成稳定性结论。

3. 工具调用

覆盖单工具、并行工具、参数 JSON 分片、工具错误和结果回传。调用 ID 必须从模型请求一直关联到工具结果和后续响应。

4. 结构化输出

用真实 JSON Schema 验证可解析性、必需字段和拒绝场景。若网关只支持旧 JSON 模式,应在能力清单中明确,而不是自动忽略 json_schema。

5. 错误请求

主动制造无效密钥、未知模型、参数错误、超限和上游故障。断言状态码、机器可读错误类型、可重试性与请求 ID,防止错误被包装成 assistant 文本。

6. 用量与账单

对每个成功和失败样本保存模型、输入输出 Token、缓存用量、倍率和最终费用。若取消流没有完整用量,应显示“不完整”或上游最终记录,不能填猜测值。

7. 数据与副作用

验证日志是否脱敏、保留周期是否符合要求,以及工具调用是否可能重复执行。影子流量只能使用脱敏、无副作用的数据集,不能复制真实客户请求去触发第二次邮件、付款或写操作。

更细的事件测试可参考 API 流式输出与工具调用指南,错误断言见 API 中转站错误码排查。

重试、密钥与日志的迁移边界

官方 SDK 可能已经对连接错误、408、409、429 与 5xx 做有限重试;应用、网关和上游若各自再重试,会放大流量。临时速率限制、额度耗尽和组织或项目限额也不能采用同一处置。

  • 为新旧 Provider 使用不同、最小权限且有独立预算的 Key;不要在浏览器或配置样本中放长期密钥。
  • 记录 X-Client-Request-Id 和返回的 x-request-id,但对 Authorization、正文、工具参数和客户标识脱敏。
  • 轮换时先部署新 Key,确认调用成功且旧 Key 流量归零;回滚窗口结束后再撤销旧 Key。
  • 对发送邮件、扣费、写库等副作用使用应用级幂等键;不要假定生成端点存在未文档化的通用幂等合约。

更细的恢复策略见 重试、熔断与故障切换,密钥控制见 API Key 安全指南。

灰度发布应该看哪些门槛?

先为每个指标写出通过标准,再看结果,避免看到局部好数据后临时降低要求。

维度 建议门槛形式 不应采用的判断
协议 必测用例全部通过,未知事件可容忍 “普通聊天能用”
可靠性 与原端点按相同窗口比较成功率与错误分布 单次请求成功
业务质量 固定评测集达到预设评分和失败上限 主观觉得回答不错
性能 比较 TTFT、P50、P95 与长流中断 只看平均延迟
账单 请求级费用可复算,差异可解释 只看账户总余额
安全 密钥、正文、日志和工具副作用通过检查 “使用 HTTPS 就安全”

推荐顺序是本地固定集、内部账号、低风险小流量、逐步扩大。每个阶段至少跨过一个代表性高峰窗口,并保留相同时间段的原端点对照。

OpenAI API 回滚清单:迁移故障怎样演练?

  1. 冻结扩大:停止新灰度,暂停会产生外部副作用的工具写操作。
  2. 切回配置:只在 Provider 层恢复原 base_url、wire API、模型和密钥引用,不临时改业务提示词。
  3. 处理在途:用请求 ID 清点流、队列和工具调用,防止重复邮件、付款或写库。
  4. 四组冒烟:重跑非流式、流式、工具调用和故意错误请求。
  5. 恢复监控:确认错误分布、延迟、用量、账单与日志路由回到原基线。
  6. 收尾密钥:保留必要取证后撤销失败 Provider 的 Key,并清除 Secret 与缓存副本。

回滚不是把所有限制放宽。权限过窄导致失败时,应恢复到上一份已验证的最小权限模板,而不是改成全局权限。每次演练都记录负责人、时间、配置版本、请求 ID 和恢复证据。

迁移完成后还要持续做什么?

模型别名、SDK、事件类型和兼容网关都会演进。把协议回归放入 CI,在 SDK、模型或网关升级前运行;生产按 Provider、模型、状态码和请求 ID 监控错误、延迟、Token 与费用。

第一次接入可先读 OpenAI 兼容 API 接入指南。需要多上游路由时,再结合 多模型 API 网关设计;重试与故障切换已在前文给出,不要在迁移当天同时引入自动路由。

GPTZZZ 的关系与适用边界

GPTZZZ 提供独立的 OpenAI 兼容多模型 API 服务,不是 OpenAI 官方网站、代理或关联机构。本文描述的是通用迁移和验证方法;具体模型、协议能力、价格与数据处理方式,应以目标 Provider 在迁移当日的公开文档、控制台和实际回归结果为准。

可复现:双端点请求、响应差异和回滚门槛

将原端点和候选端点分别放入 OLD_BASE_URL、NEW_BASE_URL,密钥与模型也分开管理。下面的合成请求不会触发工具副作用;响应正文写入本轮唯一临时目录,验证后按数据策略删除。

set +x
RUN_ID="$(python -c 'import uuid; print(uuid.uuid4().hex)')"
PROBE_DIR=".work/migration-probe/${RUN_ID}"
mkdir -p "${PROBE_DIR}"
probe () {
  label="$1"; base="$2"; token="$3"; model="$4"
  printf 'header = "Authorization: Bearer %s"\n' "${token}" | \
  curl --config - --silent --show-error \
    --request POST "${base%/}/v1/responses" \
    --header "Content-Type: application/json" \
    --header "X-Client-Request-Id: migration-${RUN_ID}-${label}" \
    --data "{\"model\":\"${model}\",\"input\":\"Reply only with pong\",\"store\":false}" \
    --dump-header "${PROBE_DIR}/${label}.headers" \
    --output "${PROBE_DIR}/${label}.json" \
    --write-out "${label} http=%{http_code} start=%{time_starttransfer}s total=%{time_total}s\n"
}
probe old "$OLD_BASE_URL" "$OLD_API_KEY" "$OLD_MODEL"
probe candidate "$NEW_BASE_URL" "$NEW_API_KEY" "$NEW_MODEL"
python -m json.tool "${PROBE_DIR}/old.json" > /dev/null
python -m json.tool "${PROBE_DIR}/candidate.json" > /dev/null

预期输出只表示传输成功,不能单独作为迁移通过结论:

old http=200 start=<measured>s total=<measured>s
candidate http=200 start=<measured>s total=<measured>s
参数边界验证指标错误或失败模式
/v1/responses 与 /v1/chat/completions 分开资源路径通过率、对象类型、完成状态SDK 初始化成功但目标资源 404
模型、提示词、超时和重试固定返回模型、错误分布、P50/P95、质量集评分同时换模型与 SDK,差异无法归因
请求 ID 与用量逐请求关联x-request-id、Token、费用差异200 文本掩盖错误,或总账变化无法复算
影子数据必须脱敏且无副作用重复写入数、外部动作数必须为零复制真实工具请求导致重复邮件、扣费或写库

故障排查:404 先确认 wire API;401/403 核对独立 Key 和项目权限;429 区分临时限流与额度或项目上限;200 但解析失败时比较原始 JSON 与 Content-Type。任一硬门槛失败,就冻结灰度并用 Provider 开关执行前文六步回滚,再用同一脚本确认旧基线恢复。

参考资料

常见问题

OpenAI 兼容 API 迁移是不是只改 Base URL?

不是。还要验证资源路径、鉴权、模型 ID、Responses 或 Chat Completions 的对象形状、流式事件、工具关联、错误、用量、数据处理与回滚。

新接入应优先验证 Responses 还是 Chat Completions?

先以应用实际使用的 wire API 为准。OpenAI 当前建议新项目优先评估 Responses,但兼容网关可能只实现其中一部分,因此两条路径必须分别声明和测试。

Responses 和 Chat Completions 最大的协议差异是什么?

Responses 使用 typed Items、显式响应状态与事件族;Chat Completions 以 messages、choices 和 delta chunk 为中心。工具结果与多轮状态的形状也不同。

429 都可以直接重试吗?

不可以。临时速率限制、额度耗尽和组织或项目限额的处置不同;还要确认 SDK 是否已经自动重试,避免应用与网关叠加成重试风暴。

怎样降低 OpenAI 兼容 API 迁移风险?

保留原 Provider,用固定脱敏样本做双端点对比,先切内部低风险流量;只有协议、质量、错误、延迟、账单和安全门槛都通过才扩大。

迁移后模型效果变化一定是网关问题吗?

不一定。模型别名、版本、提示词、SDK 默认值和安全策略都可能变化;应冻结这些变量,并用请求 ID 和原始响应区分协议故障与行为差异。

提示

模型名称、价格与可用性会变化,请以 GPTZZZ 控制台的实时信息为准。