GLM-5.2 预览版报 400 怎么办?两个只在预览版触发的请求格式陷阱 + 排查方案
上周三智谱把 GLM-5.2 预览版放出来HN 上一堆人说基准跑分超了 Claude Opus 4.7我当天晚上就把项目里的模型从 GLM-5 切过去了。结果第二天早上起来一看日志满屏 400 Bad Request。诡异的是同样的请求体发给 GLM-5 跑得好好的一切到glm-5.2-preview就炸。折腾了大半天最后确认了两个只在 5.2 预览版才会触发的格式陷阱——正式版 GLM-5 会自动容错的写法预览版直接拒绝。直接说结论GLM-5.2 预览版对请求格式的校验比 GLM-5 严格得多主要踩坑点是 messages 数组中 system/user 的顺序校验以及 max_tokens 超限时返回的错误码和提示信息都跟你预期不一样。为什么会出现这个问题GLM-5.2 还在预览阶段智谱显然收紧了输入校验逻辑。我猜是为了在正式版发布前收集边缘用例但官方文档目前没有单独说明预览版和正式版的差异——你只能靠报错信息自己摸。graph TD A[同一份请求体] -- B{发给 GLM-5} A -- C{发给 GLM-5.2 预览版} B -- D[200 OK 正常返回] C -- E[400 Bad Request] E -- F[陷阱一role 顺序校验] E -- G[陷阱二max_tokens 超限]陷阱一system 消息的位置校验变严了GLM-5 对 messages 数组里 system 和 user 的排列顺序很宽容。你把 system 放中间、放最后、甚至连续塞两条 system它都能跑。但 GLM-5.2 预览版不行——system 必须是数组第一条且只能有一条否则直接 400。我项目里的写法是这样的简化版messages [ {role: user, content: 帮我写个函数}, {role: system, content: 你是一个Python专家}, ]发给 GLM-5没问题它内部会把 system 提前处理。发给glm-5.2-preview直接返回{ error: { code: 1113, message: Invalid messages: system message must be the first message in the array, type: invalid_request_error } }这个报错信息还算清楚但坑在于——如果你的 messages 里有多条 system比如多轮对话拼接时不小心重复了报错变成了一句含糊的Invalid messages format不告诉你具体哪里错。修复很简单确保 system 在数组第一位且只出现一次。messages [ {role: system, content: 你是一个Python专家}, {role: user, content: 帮我写个函数}, ]陷阱二max_tokens 超限返回 400这个更难排查。据实测GLM-5.2 预览版的单次输出上限大约在 4096 tokens 左右官方尚未公布预览版的具体数值超出后直接返回 400{ error: { code: 1113, message: Invalid value for max_tokens, type: invalid_request_error } }注意看——错误码还是 1113跟上面那个消息格式错误用的是同一个码。message 里也不告诉你上限是多少。我一开始以为是模型名拼错了排查了二十分钟才意识到是 max_tokens 的问题。另外值得注意的是OpenAI API 对参数超限通常返回 400智谱这里同样使用 400但与消息格式错误共用同一个业务错误码 1113导致两类问题在日志里难以区分。修复预览版先把 max_tokens 控制在 4096 以内。response client.chat.completions.create( modelglm-5.2-preview, max_tokens4096, # 据实测不超过此值较为安全官方上限待确认 messagesmessages )两种验证方法我用了两种方式确认这俩问题确实只在预览版触发方法一同请求体双发对比写个脚本同一个 messages 和参数分别发glm-5和glm-5.2-preview对比响应结果。注意 openai SDK 的chat.completions.create()返回的是ChatCompletion对象HTTP 层的 400 错误会直接抛出异常因此需要用 try/except 来区分两种模型的行为for model in [glm-5, glm-5.2-preview]: try: resp client.chat.completions.create( modelmodel, messagesbad_messages ) print(f{model}: 请求成功) except Exception as e: print(f{model}: 请求失败 - {e})GLM-5 正常返回GLM-5.2 抛出异常由此确认问题来源。方法二逐字段排除法把请求体里的字段一个个去掉/改回默认值直到异常消失。我是先去掉 max_tokens 发现能通了再单独测 messages 顺序。笨办法但管用。临时规避方案在智谱正式发布 GLM-5.2 之前目前还是预览版我的做法是加一层请求预处理def sanitize_for_glm52(messages, max_tokens): # 强制 system 在首位且唯一 sys_msgs [m for m in messages if m[role] system] other_msgs [m for m in messages if m[role] ! system] clean (sys_msgs[:1] if sys_msgs else []) other_msgs return clean, min(max_tokens, 4096)不管上游怎么拼 messages发出去之前都会被规范化。等正式版出了再看要不要去掉这层。另一个思路是走聚合 API 网关有些平台会在转发前帮你做参数校验和自动修正。我测试时用 OpenRouter 和 ofox.io 都试了ofox.io 据称提供智谱模型的转发服务转发时会对 messages 格式做基础校验并返回更详细的错误提示比如会告诉你system message 不在首位比直连智谱原始 API 的报错信息友好一些。不过建议使用前自行核实该平台当前支持的模型列表以官方页面为准。常见问题 FAQQ: GLM-5.2 预览版的模型名到底怎么填目前控制台显示的是glm-5.2-preview全小写带-preview后缀。填GLM-5.2或glm-5.2会返回 1113 模型未找到。预览版模型名大小写敏感。Q: 为什么我的 GLM-5.2 请求返回 1261 而不是 11131113 是模型名不存在1261 是模型名对了但你的套餐没权限。预览版可能需要在控制台手动申请开通免费账户不一定默认有权限。去智谱控制台的模型管理页面看一眼。Q: 免费账户调用 GLM-5.2 预览版 QPS 限制是多少不同模型和时期的限制可能有所不同建议以智谱官方文档的当前说明为准。超限后会返回 429 错误码 1301可以加个time.sleep()或做简单的令牌桶来规避。Q: max_tokens 上限到底是多少官方文档没写据实测 4096 能过8192 报错中间值没有逐一验证。官方尚未公布预览版的具体上限正式版是否调整也未知。保险起见先用 4096。Q: 预览版的报错结构跟正式版一样吗结构一样都是{error: {code: ..., message: ..., type: ...}}。但预览版的 message 字段内容明显更简略正式版有时会附带建议操作预览版基本就一句话。挺烦人的。我的最终选择目前项目里 GLM-5.2 预览版只用在非关键路径的测试环境生产还是跑 GLM-5。等正式版出来再全面切换。那个请求预处理函数我封装成了一个 decorator不管底下换什么模型版本都先过一遍格式校验——反正多花不了几毫秒省得半夜被报警吵醒。