国产大模型不同厂商返回字段不一致,网关层统一格式化输出

当业务同时接入多家国产大模型时,最头疼的往往不是模型能力,而是各家接口返回的字段命名、嵌套结构和错误码完全不一样。
有的返回 content,有的返回 text
有的把内容放在 message.content,有的放在 choices[0].text
如果在业务代码里逐家适配,会非常痛苦。
本文介绍一种通用做法:在网关层完成字段归一化,让下游只认一套标准格式。

为什么要放在网关层做格式化

网关层通常是请求统一入口,在这里做字段转换有三个明显好处:

  • 业务解耦:业务代码只需对接网关定义的标准响应格式,无需感知具体是哪个厂商的模型。
  • 集中维护:新增模型或厂商时,只在网关增加一套映射规则,不用改多个业务服务。
  • 便于监控和审计:统一后的响应可带上模型来源、耗时、token 用量等公共字段,方便日志分析。

如果你只是临时接一个模型,可以在服务内写转换函数;
但只要有两个以上厂商,建议先把网关层做起来,后面扩展会省力得多。

前置准备:确认入口和标准格式

开始前先明确三件事:

  1. 网关选型:可以用现成的 API 网关(如 Apache APISIX、Kong),也可以用 Nginx + Lua 或自研 Spring Cloud Gateway。如果不方便引入重型网关,单独写一个轻量转发服务也可以。
  2. 标准响应格式:先定义自己的统一返回结构。建议参考 OpenAI 风格,因为不少国产模型本身兼容这种格式,示例如下:
{
  "code": 0,
  "message": "success",
  "data": {
    "model": "qwen-plus",
    "content": "统一后的文本内容",
    "finish_reason": "stop",
    "usage": {
      "prompt_tokens": 10,
      "completion_tokens": 20,
      "total_tokens": 30
    }
  }
}
  1. 厂商映射关系清单:把要接入的厂商字段整理成表格,比如通义千问返回 output.text,智谱返回 choices[0].message.content,文心一言返回 result 等。这一步是后续写转换规则的依据。

核心操作:用配置化映射做字段归一

以轻量网关服务为例,推荐采用 JSON Schema 映射方式。
下面用伪代码演示核心逻辑:

{
  "provider": "qwen",
  "endpoint": "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
  "map": {
    "content": "output.text",
    "finish_reason": "output.finish_reason",
    "usage.prompt_tokens": "usage.input_tokens"
  }
}

网关收到响应后,按照 map 配置深拷贝取值并组装成统一结构。
如果某个字段不存在,则按默认值处理。
伪代码示意:

def convert_response(raw: dict, mapping: dict) -> dict:
    result = {}
    for standard_key, provider_path in mapping.items():
        result[standard_key] = fetch_by_dot_path(raw, provider_path)
    # 补充公共字段
    result["model"] = raw.get("model", "")
    return result

实际操作时不需要自己发明轮子,网上很多现成的 JSON 映射库可以省不少事。
重点是配置要能在线更新,否则每加一个模型都要重新发布网关。

避坑:错误码和流式输出也要统一

很多人在字段转换时只关注正常响应,忽略了错误处理和流式输出,导致生产环境经常踩坑。

错误码务必转换
不同厂商错误码含义差异很大,网关层要统一映射成自己的业务码。
例如:

  • 厂商返回 Throttling.RateLimit,网关统一为 429
  • 厂商返回 InvalidParameter,网关统一为 400

不然下游拿到原始错误码无法差异化处理。

流式输出要单独处理
如果通义千问用 SSE 流返回 data: {...},智谱也差不多,但字段结构仍可能不同。
网关需要按行解析每个 chunk,再把每个 chunk 内部字段统一映射后重新拼成标准的 SSE 事件。
特别留意结束标记,有些结束事件没有 content 字段,映射逻辑必须容错。

不建议在响应体里直接拼凑多个模型的结果
如果做模型路由或 fallback,网关应只返回最终选中的那份结果,不要把中间过程的原始响应暴露出去。

验证效果:用 mock 数据和真实请求分别测

配置完成后,至少验证以下三类情况:

  1. 正常响应:调用各厂商真实接口,检查网关输出是否符合统一 JSON 结构。
  2. 错误响应:故意传错参数或触发限流,确认网关返回的统一错误码是否符合约定。
  3. 流式响应:逐一检查每个 SSE chunk 的 content 字段是否为拼接后的标准格式,最后确认事件能正确结束。

可以写一个简单的断言脚本,自动比对字段是否齐全:

curl 'http://gateway.example.com/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -d '{"provider":"qwen","messages":[{"role":"user","content":"ping"}]}'

jq 检查返回:

curl ... | jq '.data.content, .data.model, .code'

如果输出里能看到统一后的 content 字段且 code 为 0,说明转换链路基本正常。
最后提醒一句:不同厂商的接口版本和字段变更频率并不一样,网关层建议保留原始响应日志便于回溯对比;
变更前建议先在测试环境跑一遍映射用例,确认正常再切线上流量。

分享到:
上一篇
支付平台余额系统数据库设计,扣减余额、事务防止超扣
下一篇
微调数据集清洗,过滤脏prompt,提升微调模型效果
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意