游乐游手机版
首页/AI热点日报/热点详情

多模型接入时网关层如何应对协议差异

类型:热点整理2026-06-01
Codex 接入多模型时,网关层需要处理哪些协议差异? 近期出现了一款轻量级工具 GodeX——这是一个本地 OpenAI Responses API 网关,旨在帮助 Codex、CLI Agent 等客户端顺利对接 DeepSeek、Xiaomi、MiniMax、Zhipu 等 Chat Comp

Codex 接入多模型时,网关层需要处理哪些协议差异?

近期出现了一款轻量级工具 GodeX——这是一个本地 OpenAI Responses API 网关,旨在帮助 Codex、CLI Agent 等客户端顺利对接 DeepSeek、Xiaomi、MiniMax、Zhipu 等 Chat Completions 服务提供商。

起初,这个需求似乎非常简单:

然而深入实践后,才发现实际情况远比想象复杂。

普通聊天请求可以顺利转换,但 Agent 请求完全不同:它可能携带工具调用、结构化输出、流式响应、previous_response_id、usage、cached tokens、reasoning、provider-specific finish reason。仅仅做字段名称映射,很快就会遭遇一大堆边界情况。

本文不讨论“项目发布”,而是重点分享在构建 GodeX 过程中遇到的几个关键协议桥接点。

1. Responses API 与 Chat Completions 并非同构

最直观的结构是:

Responses request-> gateway-> Chat Completions request-> provider response-> gateway-> Responses response

如果仅限于 input -> output_text,问题不大。

但 Agent 请求中会出现:

  • tool definitions;
  • tool_choice
  • structured output;
  • streaming;
  • previous_response_id
  • usage;
  • reasoning;
  • incomplete / failed;
  • upstream error;
  • provider-specific delta。

这些能力在不同 provider 上的支持程度参差不齐。

例如 tool_choice: required,部分 provider 支持,部分不支持。有的只支持 auto。如果网关默默降级,Agent 的行为可能直接改变:原本必须调用工具,结果模型却开始自由回答。

因此 GodeX 设计了一层 compatibility plan:请求进入后,先根据 provider capability 判断哪些能力原生支持、哪些需要降级、哪些必须拒绝,并将结果写入 diagnostics。

2. Provider 不应自行决定公共策略

一个容易跑偏的设计是:在每个 provider 里分别编写一套 mapper。

deepseek mapper
zhipu mapper
minimax mapper
xiaomi mapper

短期看似高效,长期却会带来两个问题。

第一,公共逻辑重复。工具调用恢复、结构化输出降级、Responses output item 重建等逻辑会散落到每个 provider。

第二,策略不一致。今天 DeepSeek 对 strict schema 降级,明天 Zhipu 直接报错,后天 MiniMax 静默丢弃字段,客户端看到的行为越来越不可预测。

GodeX 的做法是将边界拆分开:

  • bridge 负责公共 Responses-to-Chat 策略;
  • providers 仅描述 provider 差异;
  • responses 管理同步/流式 pipeline;
  • trace 负责可观测性。

Provider 只回答:

  • 支持哪些 tool choice;
  • 支持哪些 response format;
  • usage 从哪里读取;
  • stream delta 的形态;
  • finish reason 如何映射;
  • 是否需要 request patch。

至于“降级还是拒绝”,由 bridge kernel 统一决定。

3. Streaming 不能靠字符串拼接

流式响应是最容易被低估的环节。

Chat Completions SSE 通常是 provider delta;Responses SSE 则具有完整的事件生命周期。

一个 Responses stream 可能包含:

  • response created;
  • output item added;
  • content part added;
  • output text delta;
  • content part done;
  • output item done;
  • response completed;
  • response failed。

如果网关仅仅把上游 delta 原封不动转发,Codex 这类客户端就无法将其当作标准 Responses stream 使用。

因此 GodeX 在 bridge/stream 中实现了状态机,将上游 chunks 转换为 Responses events。状态机需要处理:

  • 何时创建 response;
  • 何时创建 output item;
  • delta 归属于哪个 content part;
  • tool call delta 如何聚合;
  • finish reason 如何映射;
  • usage 出现在何处;
  • 输出非法时如何 failed;
  • 上游中断时如何 incomplete。

这里的经验是:只要涉及 Agent streaming,就不要用一堆临时 if/else 拼事件。状态机虽然更啰嗦,但更容易证明行为。

4. Structured Output 需要显式降级

另一个典型问题是结构化输出。

部分 provider 支持 json_object,但不支持严格的 json_schema。如果客户端要求 strict schema,网关有几种选择:

  • 原生传递;
  • 降级为 json_object
  • 拒绝请求。

GodeX 当前的做法是:如果 provider 只支持 json_object,则降级并注入 schema 格式指令,最终输出阶段检查 JSON 语法。

它并非完整的 JSON Schema 校验,但至少避免了“请求看似成功,结果输出完全不是 JSON”的情况。

重点不是“永远降级”,而是“降级必须可诊断”。

5. Session 不要存储 provider 私有格式

Responses API 中的 previous_response_id 很容易被误解为会话 ID。

GodeX 将其当作父指针处理:每个 response 指向上一个 response,下一轮请求进来时,session store 恢复历史,再构建 provider-neutral history。

这里有一个关键取舍:session store 不保存 provider 私有的 message 格式,而是保存 API-shaped snapshot。

这样做的好处是:

  • 后续可以切换 provider;
  • bridge 策略可以调整;
  • session store 不被某个 provider 绑定;
  • 缺失父节点、成环、深度溢出都能统一检测。

6. Trace 要从第一版开始集成

Agent 请求失败时,问题可能出在多个环节:

  • model alias 解析;
  • provider capability;
  • request downgrade;
  • 上游 HTTP;
  • stream 中断;
  • tool call 恢复;
  • output contract;
  • session chain。

没有 trace,仅凭最终输出很难定位。

GodeX 默认写 SQLite trace,记录 provider request、response、stream event、usage 和 error。尤其是流式转换,能同时看到原始 provider event 和转换后的 Responses event,能显著节省排查时间。

架构图

请求流程

小结

如果只是调用一次模型 API,未必需要网关。

但如果你正在做 Codex 接入、多 provider 路由、内部 Agent 平台,网关层很快就会承担这些职责:

  • 协议转换;
  • provider capability 规划;
  • structured output 降级;
  • stream event 重建;
  • session chain;
  • trace;
  • diagnostics。

GodeX 只是这个问题的一种具体实现。回顾整个过程,最大的收获是:模型网关真正复杂的地方不在 HTTP 转发,而在协议语义的边界。

来源:https://juejin.cn/post/7645533401148522532

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。