上周三智谱发布 GLM-4 系列新版本,我当天晚上就想把手头一个 RAG 项目的底层模型切过去。结果折腾到凌晨两点,遇到两个文档压根没提的坑——OpenAI 兼容模式下 model_id 格式和鉴权 header 的细微变动会导致静默失败(不报错,但返回的是旧模型的响应)。这篇把我踩过的坑全写出来,省得你们再走一遍。

这篇适合谁

  • 已经在用智谱 GLM-4 系列 API,想切换到最新模型的开发者
  • openai Python SDK 通过兼容模式调用智谱模型的(Cursor / Cline / Cherry Studio 用户也算)
  • 遇到过 model not found 或者调用成功但响应明显不对的
  • 想一套代码同时兼容智谱、GPT、Claude 多模型切换的

整体流程

  1. 安装前置依赖(openai 库)
  2. 确认目标模型的 model_id 命名格式(和旧版本不一样)
  3. 更新 base_url(v4 端点不变,但有个尾部斜杠的坑)
  4. 检查 Authorization header 格式(两段式 Key 的点号问题)
  5. 跑通基础调用
  6. 处理两个静默失败的边界情况

先说结论

配置项 旧版写法 当前正确写法
base_url https://open.bigmodel.cn/api/paas/v4/ 同左(没变);路径本身不变,但末尾斜杠不可省略
model_id glm-4 / glm-4-flash 见第三步表格,全小写 + 连字符 + 点号版本号
鉴权 Bearer {api_key} 同左,但 Key 格式必须含点号分隔
静默失败坑 1 model 写法模糊时不报错但走 fallback
静默失败坑 2 base_url 末尾少斜杠时部分 SDK 版本静默降级

第零步:安装前置依赖

pip install openai

如果你用的是 zhipuai 官方 SDK(场景二会提到),另外安装:

pip install zhipuai

第一步:确认你的 API Key 格式

登录 open.bigmodel.cn 控制台,右上角头像 → API Keys → 新建。Key 长这样:

xxxxxxxxxxxxxxxx.yyyyyyyyyyyyyyyy

中间那个点号不能丢。我第一次复制的时候双击选中只选了前半段,结果报了这个:

Error code: 401 - {'error': {'code': '1113', 'message': 'ApiKey is invalid'}}

错误码 1113 对应 ApiKey is invalid,这是个人观测值,官方未公开完整错误码表,以实际返回的 message 字段为准。反正你要是看到这个报错,先检查 Key 里有没有点号。

第二步:用 OpenAI SDK 调通基础请求

装好 openai 库之后(见第零步),最小可用代码就这几行:

from openai import OpenAI

client = OpenAI(
    api_key="你的完整Key含点号",
    base_url="https://open.bigmodel.cn/api/paas/v4/"
)

注意 base_url 末尾那个 / ——这是第一个坑的伏笔,后面细说。

然后发请求:

response = client.chat.completions.create(
    model="glm-4-flash",
    messages=[{"role": "user", "content": "你好"}]
)
print(response.choices[0].message.content)

这里 model 填写你实际要调用的 model_id(见第三步表格)。如果你写的 model_id 不在官方支持列表里,可能会触发后文描述的静默失败,而不是直接报错。

第三步:理解 model_id 的命名规则

智谱 GLM-4 系列目前在 ofox.io 等兼容网关上可用的 model_id(以实际平台模型列表为准):

model_id 说明
glm-4 旗舰版
glm-4-flash 轻量版,速度快价格低(限时免费)
glm-4-air 性价比版
glm-4-long 超长上下文版,支持 1M tokens 上下文窗口

规则很简单:全小写 + 连字符。但问题是你写了一个不存在的 model_id 时,API 不一定会返回 model not found,而是可能悄悄把请求路由到了某个 fallback 模型。我测了一下午才发现返回质量不对劲,对比了 token 用量才确认不是目标模型在响应。

说实话这个行为挺坑的,官方文档没写。

如果你在使用 ofox.io 等聚合网关,请以该平台的模型列表页为准确认可用的 model_id,不要凭猜测填写。

第四步:处理两处静默失败

坑一:model_id 模糊匹配导致静默降级

验证是否真的在调用目标模型,最可靠的方式是看控制台用量明细里的模型标签:

resp = client.chat.completions.with_raw_response.create(
    model="glm-4-flash",
    messages=[{"role": "user", "content": "test"}]
)
print(resp.headers.get("x-request-id"))

拿到 x-request-id 之后,去控制台的用量明细里搜这个请求 ID,看对应的模型标签是否是你预期的那个。如果不是,说明被降级了。

注:x-request-id 是请求追踪 ID,其前缀格式与路由模型的对应关系没有官方说明,不建议仅凭前缀判断路由结果。以控制台用量明细中的模型标签为准。

坑二:base_url 尾部斜杠缺失

openai SDK 版本 >= 1.30 的时候,如果 base_url 写成:

base_url="https://open.bigmodel.cn/api/paas/v4"  # 少了末尾 /

部分请求会拼接出 /v4chat/completions 这种畸形路径。智谱那边不是返回 404,而是返回一个兜底响应。根据个人观测(测试环境:openai SDK 1.35,Python 3.11,单并发顺序请求),P95 延迟(即 95% 请求的响应时间)从正常的约 800ms 飙到约 2400ms,疑似走了错误路由——该数据为个人观测值,仅供参考,实际表现可能因网络环境和负载情况不同而有差异。

修复很简单,确保末尾有 /

graph TD
    A[你的代码] -->|base_url 末尾有 /| B[正确路由: /v4/chat/completions]
    A -->|base_url 末尾没 /| C[畸形路由: /v4chat/completions]
    B --> D[目标模型正常响应 ~800ms]
    C --> E[兜底响应 ~2400ms 且可能不是目标模型]

第五步:Streaming 调用

流式输出也是同样的 endpoint,加个参数就行:

stream = client.chat.completions.create(
    model="glm-4-flash",
    messages=[{"role": "user", "content": "写一首诗"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

不同场景怎么选

场景一:已有 OpenAI 项目想加一个模型选项

直接用 openai SDK 兼容模式,改 base_url 和 model 就行,代码改动最小。如果你的项目需要同时调用多个厂商的模型,可以用 OpenRouter 或 ofox.io 这类聚合 API 网关统一管理——ofox.io 支持 OpenAI 兼容协议,改一个 base_url 就能切不同厂商的模型,不用维护多套 client 实例。使用前请在 ofox.io 模型列表页确认目标模型的正确 model_id。

场景二:纯智谱生态,不需要兼容其他厂商

用官方 zhipuai SDK,类型提示更完整,Function Calling 的 tools 参数支持也更稳:

from zhipuai import ZhipuAI

client = ZhipuAI(api_key="你的Key")

场景三:Cursor / Cline 等编辑器接入

在设置里填 base_url https://open.bigmodel.cn/api/paas/v4/,model 填你要用的 model_id(见第三步表格),Key 填完整的两段式。Cursor 的 OpenAI API 配置面板直接支持。

场景四:想省钱先验证效果

glm-4-flash(当前限时免费)跑通流程,确认 prompt 没问题再切其他版本。

踩坑记录 / 常见问题 FAQ

Q: model_id 到底怎么写?写错了会报错吗?

A: 正确写法见第三步表格,全小写 + 连字符。写错不一定报错——这是最坑的地方。不存在的 model_id 可能静默 fallback 到其他模型。唯一可靠的确认方式是看控制台用量明细里的模型标签。

Q: 用 openai 库调用报 model not found 怎么办?

A: 报错长这样:Error code: 400 - {'error': {'code': '1210', 'message': 'model not found'}}。错误码 1210 对应 model not found 为个人观测值,以实际返回的 message 字段为准。检查三件事:1)model 拼写是否全小写且与官方列表一致;2)你的账户是否已开通该模型的调用权限(新模型上线初期可能需要在控制台手动申请);3)base_url 是否正确拼到了 /v4/

Q: 429 Rate limit exceeded 怎么解决?

A: 免费账户的 QPS 限制比较紧。方案一:加 time.sleep(1) 做简单限流;方案二:升级付费套餐提升配额;方案三:用多个 Key 轮询。我目前是方案一 + 方案二组合,够用了。

Q: base_url 末尾的斜杠到底要不要加?

A: 要加。写成 https://open.bigmodel.cn/api/paas/v4/(有末尾 /)。不加的话 openai SDK >= 1.30 版本会拼出错误路径,导致响应异常但不报错。

Q: 能不能用一个 base_url 同时调智谱和 GPT?

A: 智谱官方 endpoint 只能调智谱的模型。如果你需要一套代码切多个厂商,要么自己写路由层,要么用聚合 API 网关(OpenRouter、ofox.io 这类),一个 base_url 对接所有模型。

小结

智谱 GLM-4 系列的接入本身不复杂,核心就是 base_url + model_id + Key 三件事。但那两个静默失败的坑确实浪费了我不少时间——model_id 的模糊匹配行为和尾部斜杠的路径拼接问题,文档都没提。希望智谱后续能把这两个 case 加到文档里,或者干脆对不存在的 model_id 直接返回 400。

目前我也不确定模糊 model_id 路由到的具体是哪个模型,如果有人测出来了评论区告诉我一声。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐