成本无法从“兼容”宣传判断
如果只是读文档做参数对照,很容易低估迁移成本。两套 API 的表面差异通常集中在 URL、鉴权头、模型名这几个位置;真正决定工时的是代码已经建立起来的隐式假设。例如某个字段在没有值时的行为、流式事件到达的顺序、错误重试是否安全、工具调用参数是否以多段方式返回。任何一层出现不一致,都可能让一次简单的 provider 切换变成调试事故。
“兼容”的意义取决于调用面。一个只做基础文本生成的服务,与一个运行多轮 Agent 循环的服务,在同一个 API 迁移上的成本可能相差一个量级。因此,第一步不是填参数映射表,而是把线上实际使用到的调用面固化成契约基线。
注意:本文所讨论的兼容性差异均为迁移时的通用检查方法,不代表 DeepSeek 当前版本已存在该差异。具体差异应以实际 API 响应和契约测试结果为准。
先建立契约基线
契约基线指一组“带有固定输入和完整真实响应”的样本,用来回答“迁移后行为是否一致”:
- 排查仓库里所有直接或封装后发送请求的模块,找到客户端初始化、鉴权/Header 配置、请求构造、响应解析四个位置。这四个位置分别对应不同种类的改造。
- 为当前使用的每个重要场景保存原始响应。包括正常返回、空结果、长度截断、内容审核拒绝、工具调用与限流错误。只保存正常场景不足以支撑迁移。
- 用相同请求调用目标 API,逐字段 diff 真实响应。要注意,这里 diff 的不是“文档字段”,而是“你的代码读取的字段”。目标 API 多返回一些字段不会破坏业务,少返回或者返回不同的枚举值才会。
这组基线进入 CI 后价值最大。在 CI 中做真实网络请求可能不稳定,但至少要在预发布环境保留一条固定请求的冒烟测试;单元测试里的 mock 无法暴露迁移差异。
不过也要注意:契约基线解决的是“前后行为是否一致”,解决不了“新平台能力是否符合业务需求”。后者必须由下游业务输出进行语义评估。
五个容易隐藏成本的差异层
在向新平台切换时,建议从下面五个层次区分验证,而不是做一个大的“API 替换”任务。
访问与网络配置
这一层至少要核对几个点:客户端初始化方式是否被封装在框架里;鉴权配置是在初始化时读取还是每次请求动态获取;是否存在代理网关、日志拦截器或自定义 Header 把旧平台的请求上下文透传到新平台;连接和读超时是否需要调整。
如果现有代码在多个地方直接创建客户端,切换时容易漏改。工程上建议预留一次“环境替换演练”:只改配置、不改业务代码,看服务能否完成一次调用。做不到时说明客户端被业务代码耦合过多,这也是迁移成本的一部分。
请求参数与默认值
参数名称相同不等于行为相同。尤其要注意没有显式传入的参数:旧平台有默认值,新平台不一定有;即使都有默认值,默认含义也可能不同。请求体构造越依赖框架自动填充,越容易在迁移后引入隐藏差异。
请求参数边界也要测试,例如:最大长度、空数组、空字符串、非法枚举值、超长输入。目标 API 如果对这些值的处理更严格,错误处理路径会先于正常路径暴露问题。
响应结构解析
迁移时最常见的无效工作是“把旧平台解析类型复制到新平台”,然后期待字段含义一致。建议的做法是:只保留业务真正消费的字段,解析层的结构体重新定义;对不确定字段采用显式校验,而不是静默忽略;在日志里保留原始响应 JSON 一段时间,方便线上问题回放。
如果多个端点被包含在同一个 SDK 中,还要确认响应结构是否按端点独立演进。某一个端点的格式看起来兼容,不能推导出另一个端点也兼容。
流式输出与工具调用
流式输出是迁移成本最容易被低估的部分。不要只比较“最终拼出来的文本一致”,而要记录整条事件流。建议在代码层标记五个时间点:连接建立、首个事件到达、相邻事件间隔、终止事件到达、错误事件到达。任何一个时间点的行为不同,都会影响用户体验。
工具调用(function calling)则在流式场景中更复杂。工具参数往往以多段增量到达,解析器需要按照完整事件边界重组参数,而不是把文本流简单拼接后再解析。如果你的业务代码包含了“如果返回工具调用就暂停生成、执行本地工具并把结果回填到对话”的循环,那么这串循环每一次与 API 的交互契约都要重新验证。
值得单独测试的边界包括:工具调用参数为空或非法 JSON、模型在一条消息中返回多个工具调用、工具调用结果回填后是否在下一轮被正常引用。任何一个环节的差异都会打破 Agent 循环。
错误与重试语义
错误处理是看起来简单、线上容易出问题的部分。HTTP 状态码和错误结构只是入口,更重要的是重试策略。可以把错误分为几类:网络不可达,可能值得重试;鉴权失败,重试无意义且可能需要告警;参数非法,说明请求构造有 bug,重试会掩盖问题;限流或过载,应该退避而不是立即重试;部分错误表示请求已经执行成功,重试可能产生重复成本。这个分类不能靠错误消息中的关键词匹配实现,因为不同平台对同类错误的表达方式可能不同。
业务代码中也要为未知错误结构预留逃生通道:记录原始错误对象与请求标识,而不是在序列化时把未知字段丢弃。迁移期间尤其需要保留这类信息。
注意:HTTP 状态码与错误码都可能随版本变化,实际实现前应核对目标平台最新错误码文档。
用适配层隔离 provider 语义
如果团队准备长期保留双通道或多云策略,建议在一开始就引入 Provider 适配层,而不是继续在业务代码中直接依赖某个 provider 的响应类型。
适配层的主要职责有三个:把业务需要的参数转换成各 provider 的请求格式;把各 provider 的响应归一化成业务内部类型;把各 provider 的错误转换成统一的内部错误枚举。request_id、provider、重试次数等上下文应该在边界处写入日志。
需要避免的是把 provider 原始类型直接渗透到业务层。如果业务层的 Agent 状态机依赖 provider 的字段枚举,那么每次新接入一个 provider 都要改业务状态机,成本会随 provider 数量线性增长。
引入适配层的目标不是消除所有差异,而是把差异约束在单一边界内,让“切换 provider”从“全仓库改动”收敛成“新写一个 adapter + 跑契约测试”。
不同业务场景的验证重点
- 基础文本生成:优先跑正常与截断两类契约测试,再对生成结果做小样本人工评估。工具调用、流式和复杂错误路径可以第二阶段再做。
- 流式对话:重点做事件流记录与回放对比,尤其关注弱网、长时间连接、客户端中断后的行为。
- Agent / 工具调用密集场景:把契约测试扩大到“多轮工具调用 + 结果回填”的完整链路,而不是单轮工具调用。
- 同时使用多个端点:必须逐个验证。一个平台对某类接口的兼容性,不能用于推断其他类型接口的兼容性。
- 双 Provider 灾备:不要只考虑“迁移当天的成本”,还要考虑后续每次模型更新或参数变化时,两组契约测试的同步维护成本。
结论
在没有对目标 API 的当前版本做契约测试之前,严谨的结论只能到“潜在差异点清单”为止。迁移成本取决于实际调用面,不取决于兼容性宣传。从工程角度,最快降低评估风险的方法是:马上采集现有流量中的真实请求与响应,形成基线,然后用最少的代码验证目标 API 的五个关键层。若基线测试通过,后续改造重点是参数语义、工具调用和错误重试;若基线测试失败,则先谈适配层设计,而不是继续铺开替换。