刘敏杰的技术笔记AI 应用开发 · 后端工程

用 OpenAI 兼容协议统一接入多家大模型

刘敏杰 · 2026-11-02 · 大模型API架构

为什么需要统一接入

一个典型的 AI 应用往往同时用到好几个模型:便宜的小模型做分类和抽取,强模型做推理和写作,还有专门的向量模型做检索。如果每家都直接调用各自的 SDK,会遇到几个问题:

现在绝大多数厂商和开源推理框架(vLLM、Ollama 等)都提供了 OpenAI 兼容接口,即 POST /v1/chat/completions 这一套请求格式。把它当作内部的“标准协议”,问题就简单了很多。

最小可用的网关结构

网关只做四件事:鉴权、路由、记账、兜底。

type Route struct {
    Prefix  string // 例如 "claude-"、"qwen-"
    BaseURL string
    APIKey  string
}

func pick(model string, routes []Route) (Route, bool) {
    for _, r := range routes {
        if strings.HasPrefix(model, r.Prefix) {
            return r, true
        }
    }
    return Route{}, false
}

业务方只认识一个地址和一个内部密钥,请求里的 model 字段决定转发到哪个上游。

几个容易踩的坑

  1. 流式响应要逐块转发。SSE 响应不能先读完再返回,否则首字延迟会变得很长。Go 里记得每写一块调用一次 Flush()。
  2. 兼容不等于完全一致。部分厂商不支持 tools 字段,或者把推理过程放在 reasoning_content 里。网关最好在启动时对每个模型做一次探测,记录它真实支持的能力。
  3. 超时要分层设置。连接超时可以短(5 秒),但长文本生成的读超时要放宽到几分钟。
  4. 记录 usage 字段。返回体里的 prompt_tokens 和 completion_tokens 是成本核算的唯一可靠来源,要落库。

模型能力探测

我在项目里写了一个小脚本:先请求 GET /v1/models 拿到模型列表,再对每个模型发一次带工具定义的请求,根据返回是否包含 tool_calls 判断它是否支持函数调用。探测结果写进配置文件,上层就能按能力挑模型,而不是凭印象。

小结

统一协议的价值不在于省几行代码,而在于把“用哪个模型”从代码决策变成配置决策。模型更新很快,这一层抽象能让业务保持稳定。