看到一个问题,很多人会认为:多模型 API 适配是网关、中间件的事。
但实际开发中,前端也是一个被迫直接面对模型差异的地方

UI/交互逻辑依赖模型返回的结构
比如一个模型返回 choices[0].message.content,另一个返回 output.text,前端需要为每种模型写不同解析代码。

流式 / 非流式处理差异
有的模型支持 SSE,有的只支持 WebSocket,有的只能轮询任务。前端需要维护不同的状态机。

鉴权方式影响请求流程
API Key、JWT、临时 Token、请求头签名……每种鉴权在前端都可能需要不同的拦截器或配置。

错误处理与用户体验强相关
不同模型返回的错误码、错误字段完全不同,前端需要做大量 switch-case 才能给出“请稍后重试”或“余额不足”等友好提示。

成本统计的前端可视化
前端经常要展示本次请求消耗的 Token 数、费用,但每个模型的计费字段位置和单位不一致。

所以我觉得从前端角度说说我的感觉

AI 应用开发越来越慢,不是因为模型能力不够,而是因为“多模型适配”正成为一种隐形的、不断膨胀的技术债。
每个新模型加入,都意味着要在 API 调用、鉴权、数据结构、异步任务、错误处理、成本统计等多个维度上做一遍重复且易错的工作。

API 调用方式差异:前端状态机被撑爆

不同模型的 API 风格天差地别:

模型 请求方式 参数位置 响应结构示例
OpenAI POST JSON messages 数组 data.choices[0].message.content
Anthropic POST JSON prompt 字符串 data.content[0].text
国内某些模型 GET + URL 参数 query 字段 data.result
自托管模型 POST + 特殊签名 自定义 schema 不定


需要维护一个“适配器工厂”,每个模型对应一套请求构建 + 响应解析逻辑。
一旦模型升级(如 GPT 到 GPT-4 Turbo),可能字段变化,导致所有调用页面修改。

 鉴权方式各异:拦截器无法统一

  • OpenAI:Authorization: Bearer <key>

  • Anthropic:x-api-key: <key> + anthropic-version: 2023-06-01

  • Azure OpenAI:api-key 放在请求头,但 URL 中还要包含 api-version

  • 某些国产模型:先拿临时 token,再带 token 请求

axios 或 fetch 拦截器写得像巨型配置表,甚至需要为不同模型维护不同的 HTTP 客户端实例。

返回数据结构不一致:前端解构代码像在考古

同一个“AI 回复文本”,在不同模型里的路径:

javascript

// OpenAI
const reply = data.choices[0].message.content;

// Anthropic
const reply = data.content[0].text;

// Cohere
const reply = data.generations[0].text;

// 国产模型
const reply = data.output.text;

更麻烦的是 工具调用 / Function Calling

OpenAI 放在 tool_calls

其他模型可能叫 actionsfunctionsplugins
前端必须为每个模型写专门的参数提取和渲染逻辑。

异步与流式处理:前端需要维护多种状态机

  • 流式(SSE):OpenAI 推荐,前端用 EventSource 或 fetch + 分块读取。

  • 非流式:简单等待完整响应。

  • 长时间任务:某些文生图 / 视频模型返回 task_id,需要轮询或 Webhook。

每个模型可能要写一套:流式消息拼接逻辑\轮询重试策略\中止/取消请求的兼容

而且 UI 上要展示“生成中…”,不同模型的中断恢复逻辑也不同。

错误处理:没有统一错误码,全是特判

看几个真实例子:

模型 错误字段路径 错误码含义
OpenAI error.code (429, 401, 500) 比较规范
Anthropic error.type (overloaded, invalid_request) 需要映射到 HTTP 逻辑
某小厂模型 errno + errmsg,且结构不固定 经常出现空指针异常

前端为了给用户一个“网络错误,请稍后重试”的提示,需要写:

这种代码随模型数量线性增长,难以维护。

成本统计:字段不同、单位不同、甚至要靠估算

  • OpenAI 返回 usage.total_tokens

  • 某些模型返回 usage.prompt_tokens + usage.completion_tokens

  • 有些模型不返回 token 数,只返回 cost(美元或积分)

  • 自托管模型完全没数据,需要前端按字符估算

前端想做一个“本次调用花费 $0.002”的展示,就要为每个模型写一套计算函数,还要处理单位换算(1k token = ? 元)。

解决方案:统一 API / Task 层

解决这一切痛苦的唯一路径是 在前端与多个模型之间,增加一个统一抽象层。它至少要做:

  1. 统一请求接口
    POST /v1/chat/completions(与 OpenAI 兼容是最佳实践)

  2. 统一鉴权方式
    前端只用一个 API Key 或 JWT,后端负责转换。

  3. 统一响应结构
    { code, message, data: { content, tool_calls, usage } }
    不管背后是什么模型,前端解析逻辑不变。

  4. 统一异步任务模型

    • 同步任务直接返回

    • 异步任务返回 task_id,提供 /task/status/task/result 接口

    • 可选 WebSocket/SSE 统一推送进度

  5. 统一错误码
    定义 429(限流)、402(余额不足)、500(模型错误)等,前端只需要处理一套。

  6. 统一成本信息
    在响应里固定返回 usage.total_tokens 和 estimated_cost_usd

这个统一层可以是一个 BFF(Backend for Frontend)、一个 API 网关,甚至一个 Serverless 函数。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐