← 返回资讯

国产大模型的 OpenAI 兼容接口:统一接入方法与注意事项

2026-07-22

你手头的项目原来接的是 DeepSeek,聊天功能跑得好好的,某天产品经理甩过来一句”通义千问在阿里云生态里额度更划算,能不能顺手也接一下做 AB 测试”。你打开代码捏了把汗——还好,这活儿真没那么难。主流国产大模型这几年不约而同做了同一件事:把自家接口封装成 OpenAI Chat Completions 协议的样子,你只需要换掉 api_keybase_url 两个参数,原来调 DeepSeek 的代码几乎原封不动就能调通义千问、智谱 GLM、Kimi、文心一言、豆包。这不是巧合,是国产厂商心照不宣的策略:OpenAI 的 SDK 生态已经铺得足够广,谁兼容得越彻底,谁就越容易被开发者顺手接进现有项目,省掉大量二次开发和团队培训成本。

六大厂商端点速查

厂商base_url常用模型名(示例)
DeepSeekhttps://api.deepseek.com/v1deepseek-chat / deepseek-reasoner
通义千问https://dashscope.aliyuncs.com/compatible-mode/v1qwen-max / qwen-plus / qwen-turbo
智谱 GLMhttps://open.bigmodel.cn/api/paas/v4glm-4 / glm-4-flash
Kimihttps://api.moonshot.cn/v1moonshot-v1-8k / moonshot-v1-128k
文心一言https://qianfan.baidubce.com/v2ernie-4.5-8k / ernie-speed-128k
豆包https://ark.cn-beijing.volces.com/api/v3doubao-pro-32k / doubao-lite-4k

统一调用模板

下面的工厂函数封装了多厂商切换逻辑,运行时只需改 provider 变量:

from openai import OpenAI

PROVIDERS = {
    "deepseek": {
        "base_url": "https://api.deepseek.com/v1",
        "api_key": "sk-DEEPSEEK_KEY",
        "model": "deepseek-chat",
    },
    "qwen": {
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
        "api_key": "sk-QWEN_KEY",
        "model": "qwen-plus",
    },
    "glm": {
        "base_url": "https://open.bigmodel.cn/api/paas/v4",
        "api_key": "sk-GLM_KEY",
        "model": "glm-4-flash",
    },
    "kimi": {
        "base_url": "https://api.moonshot.cn/v1",
        "api_key": "sk-KIMI_KEY",
        "model": "moonshot-v1-8k",
    },
}

def chat(provider: str, prompt: str) -> str:
    cfg = PROVIDERS[provider]
    client = OpenAI(api_key=cfg["api_key"], base_url=cfg["base_url"])
    res = client.chat.completions.create(
        model=cfg["model"],
        messages=[{"role": "user", "content": prompt}],
    )
    return res.choices[0].message.content

# 使用示例
print(chat("deepseek", "简单解释一下 RAG 架构"))

这套工厂函数为什么这么写

PROVIDERS 字典把厂商差异收敛成配置,而不是写一堆 if provider == "deepseek": ... elif provider == "qwen": ... 的分支判断。好处很直接:以后再加一个厂商,只需要往字典里补一条记录,chat() 函数本身不用改一行,出 bug 的概率也小很多。这是做多模型路由最基础的工程习惯,哪怕你现在只接两三家,也建议从一开始就用配置化的方式写,省得后面推倒重来。

不过要提醒一句:上面这段代码是”能跑”的最简版本,直接搬进生产环境会踩坑。它没有设置 timeout,没有捕获异常,也没有重试逻辑——国产模型的接口偶尔会出现连接超时或者限流,调用方如果没有兜底,用户体验就是干等甚至直接抛 500。下面给一版更接近生产可用的写法:

import time
from openai import OpenAI, APITimeoutError, RateLimitError, APIStatusError

def chat_with_retry(provider: str, prompt: str, max_retries: int = 3) -> str:
    cfg = PROVIDERS[provider]
    client = OpenAI(
        api_key=cfg["api_key"],
        base_url=cfg["base_url"],
        timeout=20.0,  # 单次请求超时,国产模型高峰期建议设 15~30s
    )
    for attempt in range(max_retries):
        try:
            res = client.chat.completions.create(
                model=cfg["model"],
                messages=[{"role": "user", "content": prompt}],
            )
            return res.choices[0].message.content
        except RateLimitError:
            wait = 2 ** attempt  # 指数退避:1s / 2s / 4s
            time.sleep(wait)
        except (APITimeoutError, APIStatusError) as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(1)
    raise RuntimeError(f"{provider} 请求重试 {max_retries} 次仍失败")

这里用指数退避而不是固定间隔重试,是因为限流的恢复速度跟当前并发量有关——固定 1 秒重试在真正的高峰期基本没用,指数退避能让请求错峰重试,命中窗口的概率更高。如果你的场景是聊天界面而不是批处理任务,还应该用流式输出(stream=True)让用户能看到逐字返回,而不是等模型全部生成完再一次性吐出来,长回答的等待体感会差很多:

stream = client.chat.completions.create(
    model=cfg["model"],
    messages=[{"role": "user", "content": prompt}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content or ""
    print(delta, end="", flush=True)

兼容性差异清单

虽然各家宣称”OpenAI 兼容”,但仍存在细节差异,接入前需确认:

特性DeepSeek通义千问智谱 GLMKimi文心豆包
stream=True
Function Calling✓(强)
response_format: json_object部分部分
logprobs部分
多模态(images in messages)否(主力)✓(4V)
Batch API部分部分

以上信息截至 2026-06,各厂商持续迭代,以官方文档为准。

六家怎么选,别只看表格

表格能告诉你”有没有”,选型还得看”好不好用”。这是我们实际跑过项目后的取舍建议,仅供参考,具体以你的场景实测为准:

  • 对话/客服类高并发场景:优先 DeepSeek 或智谱 GLM-4-Flash,两者响应速度快、单价低,适合日调用量十万级以上的场景,成本压力小。
  • 需要强 Function Calling(接数据库查询、下单、工单系统):智谱 GLM 的工具调用稳定性在实测中相对更可靠,出参格式规范性更好,能减少你手写兜底解析的工作量。
  • 长文档处理(合同、论文摘要):Kimi 的 moonshot-v1-128k 上下文窗口大,适合一次性喂入长文本;文心一言的 ernie-speed-128k 也是同类选择,但注意它速度更快,精度上会有取舍,别混为一谈。
  • 多模态(图文混合输入):通义千问和豆包对图片输入支持得较早也较稳定,项目需要识图时这两家优先测试。
  • 强推理/代码生成:DeepSeek 的 deepseek-reasoner 系列在推理链路上表现突出,代码生成、数学题这类需要多步推理的任务可以优先试它。

实际项目里更常见的做法不是”选一个”,而是像开头那个例子一样,用工厂模式把多家接进来,按场景动态路由——简单对话走便宜的模型,复杂推理走贵一点但质量更好的模型,整体成本能压下来不少,这也是多模型路由这套架构真正的价值所在,而不只是图个”能切换”的方便。

三个常见踩坑点

1. base_url 末尾斜杠 部分 SDK 版本对 base_url 末尾 / 敏感,建议统一不加末尾斜杠,如 https://api.deepseek.com/v1 而非 https://api.deepseek.com/v1/

2. 文心一言鉴权差异 千帆平台早期版本使用 Access Key + Secret Key 换 token 的两步鉴权,新版 /v2 端点已支持直接 Bearer,建议升级到新端点。

3. 豆包模型名为”推理接入点 ID” 豆包在 ARK 平台创建应用后,模型名实际是平台分配的「推理接入点 ID」(如 ep-xxxxxx-xxxx),不是通用字符串,需在控制台查看。

再补四个你大概率会遇到的报错

4. 401 Unauthorized 但 Key 明明是对的 最常见的原因不是 Key 本身错了,而是复制的时候带了空格或换行符,尤其从网页控制台复制到 .env 文件时容易出这种问题。打印一下 len(api_key)repr(api_key),看首尾有没有多余的空白字符,十次里有八次是这个原因。另外文心千帆的旧版 Key 和新版 /v2 端点的 Key 格式不通用,混用同样会报 401。

5. 429 Too Many Requests 明明并发量不大 国产模型的限流经常按”每分钟 token 数”计算,不是单纯的”每秒请求数”。如果你的 prompt 很长(塞了几千字的上下文),哪怕只有三五个并发请求也可能撞到 TPM(tokens per minute)上限。解决办法是控制单次请求的 token 预算,或者去控制台申请提升限额,别一味加重试次数硬扛,那样只会把限流打得更狠。

6. 中文乱码或者字符被截断 偶尔会遇到流式返回里中文变成问号或者半个字符,多半是按字节切分了 chunk,导致一个多字节 UTF-8 字符从中间被切开。处理流式输出时,先用 chunk.choices[0].delta.content 把片段拼接成完整字符串,再统一做后续处理,不要对还没拼接完的半截片段做编码转换或者截断显示。

7. 400 报错提示上下文超长 不同厂商的上下文窗口不一样,deepseek-chat 常规版本是 64K,超出这个长度会直接报错拒绝。长文档问答场景别硬塞全文,先做一版简单的分段摘要,或者只检索出相关片段喂进去,这正是 RAG 架构要解决的问题——不是所有场景都靠”堆大窗口”就能解决。

上手前的三步自查

真正开始接入前,建议按这个顺序过一遍,能少走很多弯路:

  1. 先用 curl 裸调一次,不经过任何 SDK 封装,确认 base_url + /chat/completions 能通、鉴权头格式对。国产厂商个别端点的鉴权头细节有差异,curl 能帮你排除 SDK 封装带来的干扰,出问题时更容易定位是哪一层的锅。
  2. 测一次最短 prompt,比如就发一句”你好”,确认能拿到正常响应结构(choices[0].message.content 有值),再逐步加大 prompt 长度和复杂度,别一上来就拿生产环境的复杂 prompt 硬试。
  3. 专门测一次异常输入,故意传错 model 名字或者截断的 api_key,看报错信息长什么样、能不能被你的异常处理逻辑正确捕获。很多线上事故都是”正常流程测过,异常分支没测过”导致的。

跑完这三步,你应该能看到:裸调能通、正常 prompt 有正常回复、异常输入能被优雅捕获而不是让整个服务直接崩掉。做到这一步再上生产环境,心里才有底。

常见问题

用 LangChain 接国产模型需要特殊配置吗? 不需要。LangChain 的 ChatOpenAI 类支持 openai_api_baseopenai_api_key 参数,直接替换为国产厂商的端点即可。也可参考 LangChain 接入 AI 模型 完整示例。

OpenRouter 能代替直连国产模型吗? OpenRouter 聚合了部分国产模型,适合快速测试;但生产环境建议直连厂商端点,延迟更低、价格更透明,且国内模型走海外中转会增加响应时间。

如何判断某个国产模型是否真正兼容 OpenAI 格式? 最快的方式:用 openai Python SDK,设置 base_urlapi_key 直接发请求;如果无报错且响应结构符合 ChatCompletion 格式,即为兼容。


相关阅读国产大模型 API 全景指南 · 智谱 GLM API Key 获取教程 · 六大模型横向对比

分类导航国产模型专题

实用工具价格对比表