智谱 GLM 没有 provider profile:下游只能手写 extra_body,能力表与推理对账静默失效 #20

Closed
opened 2026-09-05 10:44:20 +08:00 by iomgaa · 1 comment
Owner

问题

DEFAULT_PROFILES 里没有智谱(GLM)。下游把 glm-5.3-flash / glm-5.3 挂在 provider=openai 这个兜底段名下,而 openai 的 thinking_on / thinking_off 都是 None(未知),所以一配 ENABLE_THINKING 就在装配期报错——这是 issue #5 之后的正确行为,本身没问题。

问题在于下游因此只剩一条路:在 EXTRA_BODY 里手写 {"reasoning_effort": "none"}。这条路能把参数发出去(_build_payloadpayload.update(source.extra_body)),但它绕过了本库为这件事准备的三道机制,而且是静默绕过:

  1. ThinkingCapability 查不到。下游不知道某个型号能不能关推理,只能自己去撞。
  2. resolve_thinking 的装配期报错不触发。关不掉的型号照样开跑。
  3. _warn_on_thinking_mismatch 的运行期对账不成立。source.enable_thinkingNonereconcile_thinking 认为调用方没有声明、也就没有矛盾可报。

第 3 条的实际后果最值得说:遥测的 thinking_observation 列一直老老实实记着 observed,库确实观测到了推理,但因为没有声明可以对账,这个信号谁也没看见。下游带着「我关掉了推理」这个错误前提跑了几千次调用,是靠人工直连渠道复测才发现的。

实测

测法:直连中转渠道(自建 new-api,OpenAI 兼容端点),绕开本库,httpx trust_env=False。提示词「23 乘以 47 等于多少?只回答一个数字,不要解释。」,temperature=0.6。判据取 usage.completion_tokens_details.reasoning_tokens(该渠道对 GLM 系稳定上报,usage_source=measured)。取数日期 2026-09-04。

表一,五种写法各 N=1rt = reasoning_tokens,ct = completion_tokens;答案本身 4 个 token):

模型 不带任何键 reasoning_effort:none thinking:{type:disabled} reasoning_effort:medium thinking:{type:enabled}
glm-5.3-flash rt=41 ct=45 rt=0 ct=4 rt=0 ct=4 rt=92 ct=96 rt=38 ct=42
glm-5.3 rt=57 ct=61 rt=6 ct=10 rt=6 ct=10 rt=101 ct=105 rt=42 ct=46

表二,nonemedium 各 N=8

模型 none 的 rt 均值 medium 的 rt 均值
glm-5.3-flash 0,2,0,6,0,2,0,0 1.2 56,48,41,36,49,49,49,8 42.0
glm-5.3 6,7,6,6,6,6,7,6 6.2 48,52,96,49,55,67,86,56 63.6

两个结论:reasoning_effort 对 GLM 系有效,档位语义与 minimax 一致;thinking:{"type":"disabled"} 同样有效。建议选 reasoning_effort,因为它有档位、能表达 thinking_on,而 thinking 只有开关两态。

一条限制:长上下文下 none 压不干净

拿一条真实的 26 轮、5552 输入 token 的 agent 做题上下文重放,同样配置各 N=3:

模型 none 的 rt medium 的 rt
glm-5.3-flash 0, 54, 167 121, 265, 162
glm-5.3 97, 5, 10 254, 195, 127

短提示词下 none 稳定在 0–7,长上下文下会跳到上百。所以 can_disable 该登记为 True,但 evidence 要写明这个限制——它对按 token 记账的调用方有实际影响。

建议

"zhipu": ProviderProfile(
    name="zhipu",
    thinking_on={"reasoning_effort": "medium"},
    thinking_off={"reasoning_effort": "none"},
    strip_think_tags=False,
),

thinking_onmedium 与 minimax 那条保持同一约定(五档里语义最接近「厂商正常强度」的一档,精确控制走 extra_body)。

能力登记:

"glm-5.3-flash": ThinkingCapability(
    can_disable=True,
    evidence=(
        "2026-09-04 经 new-api 中转实测: 短提示词 N=8, reasoning_effort=none "
        "rt 均值 1.2(0~6), 不带键基线 rt=41, medium 均值 42.0; "
        "thinking:{type:disabled} 同样有效。"
        "限制: 5552 token 的长上下文下 none 不能压到 0(N=3 实测 0/54/167)"
    ),
),
"glm-5.3": ThinkingCapability(
    can_disable=True,
    evidence=(
        "2026-09-04 经 new-api 中转实测: 短提示词 N=8, reasoning_effort=none "
        "rt 均值 6.2(6~7), 不带键基线 rt=57, medium 均值 63.6; "
        "thinking:{type:disabled} 同样有效。"
        "限制: 5552 token 的长上下文下 none 不能压到 0(N=3 实测 97/5/10)"
    ),
),

没有覆盖到的

  • glm-5.2 的数据不可信,不建议据此登记。 这个渠道对 glm-5.2 的请求,响应里的 model 字段回报 glm-5.3(遥测里 5 次历史调用加 1 次现测,6/6 全部如此),怀疑被路由到了 glm-5.3。所以我测到的「glm-5.2」行为可能根本是 glm-5.3 的。这是渠道侧的问题,不是本库的,写在这里只是说明为什么第三个型号缺席。
  • 只在这一个自建中转渠道上测过,没有直连智谱官方端点
  • 没测 high / low / minimal 三档。
  • strip_think_tagsFalse 是按响应里 content 字段干净、推理走 reasoning_content 观察到的,没有专门构造用例验证。
## 问题 `DEFAULT_PROFILES` 里没有智谱(GLM)。下游把 `glm-5.3-flash` / `glm-5.3` 挂在 `provider=openai` 这个兜底段名下,而 openai 的 `thinking_on` / `thinking_off` 都是 `None`(未知),所以一配 `ENABLE_THINKING` 就在装配期报错——这是 issue #5 之后的正确行为,本身没问题。 问题在于下游因此只剩一条路:在 `EXTRA_BODY` 里手写 `{"reasoning_effort": "none"}`。这条路能把参数发出去(`_build_payload` 里 `payload.update(source.extra_body)`),但它绕过了本库为这件事准备的三道机制,而且是**静默**绕过: 1. `ThinkingCapability` 查不到。下游不知道某个型号能不能关推理,只能自己去撞。 2. `resolve_thinking` 的装配期报错不触发。关不掉的型号照样开跑。 3. `_warn_on_thinking_mismatch` 的运行期对账不成立。`source.enable_thinking` 是 `None`,`reconcile_thinking` 认为调用方没有声明、也就没有矛盾可报。 第 3 条的实际后果最值得说:遥测的 `thinking_observation` 列一直老老实实记着 `observed`,库确实观测到了推理,但因为没有声明可以对账,这个信号谁也没看见。下游带着「我关掉了推理」这个错误前提跑了几千次调用,是靠人工直连渠道复测才发现的。 ## 实测 **测法**:直连中转渠道(自建 new-api,OpenAI 兼容端点),绕开本库,`httpx` `trust_env=False`。提示词「23 乘以 47 等于多少?只回答一个数字,不要解释。」,`temperature=0.6`。判据取 `usage.completion_tokens_details.reasoning_tokens`(该渠道对 GLM 系稳定上报,`usage_source=measured`)。取数日期 2026-09-04。 **表一,五种写法各 N=1**(`rt` = reasoning_tokens,`ct` = completion_tokens;答案本身 4 个 token): | 模型 | 不带任何键 | `reasoning_effort:none` | `thinking:{type:disabled}` | `reasoning_effort:medium` | `thinking:{type:enabled}` | | --- | --- | --- | --- | --- | --- | | glm-5.3-flash | rt=41 ct=45 | rt=0 ct=4 | rt=0 ct=4 | rt=92 ct=96 | rt=38 ct=42 | | glm-5.3 | rt=57 ct=61 | rt=6 ct=10 | rt=6 ct=10 | rt=101 ct=105 | rt=42 ct=46 | **表二,`none` 与 `medium` 各 N=8**: | 模型 | `none` 的 rt | 均值 | `medium` 的 rt | 均值 | | --- | --- | --- | --- | --- | | glm-5.3-flash | 0,2,0,6,0,2,0,0 | 1.2 | 56,48,41,36,49,49,49,8 | 42.0 | | glm-5.3 | 6,7,6,6,6,6,7,6 | 6.2 | 48,52,96,49,55,67,86,56 | 63.6 | 两个结论:`reasoning_effort` 对 GLM 系有效,档位语义与 minimax 一致;`thinking:{"type":"disabled"}` 同样有效。**建议选 `reasoning_effort`**,因为它有档位、能表达 `thinking_on`,而 `thinking` 只有开关两态。 ## 一条限制:长上下文下 `none` 压不干净 拿一条真实的 26 轮、5552 输入 token 的 agent 做题上下文重放,同样配置各 N=3: | 模型 | `none` 的 rt | `medium` 的 rt | | --- | --- | --- | | glm-5.3-flash | 0, 54, 167 | 121, 265, 162 | | glm-5.3 | 97, 5, 10 | 254, 195, 127 | 短提示词下 `none` 稳定在 0–7,长上下文下会跳到上百。所以 `can_disable` 该登记为 `True`,但 evidence 要写明这个限制——它对按 token 记账的调用方有实际影响。 ## 建议 ```python "zhipu": ProviderProfile( name="zhipu", thinking_on={"reasoning_effort": "medium"}, thinking_off={"reasoning_effort": "none"}, strip_think_tags=False, ), ``` `thinking_on` 取 `medium` 与 minimax 那条保持同一约定(五档里语义最接近「厂商正常强度」的一档,精确控制走 `extra_body`)。 能力登记: ```python "glm-5.3-flash": ThinkingCapability( can_disable=True, evidence=( "2026-09-04 经 new-api 中转实测: 短提示词 N=8, reasoning_effort=none " "rt 均值 1.2(0~6), 不带键基线 rt=41, medium 均值 42.0; " "thinking:{type:disabled} 同样有效。" "限制: 5552 token 的长上下文下 none 不能压到 0(N=3 实测 0/54/167)" ), ), "glm-5.3": ThinkingCapability( can_disable=True, evidence=( "2026-09-04 经 new-api 中转实测: 短提示词 N=8, reasoning_effort=none " "rt 均值 6.2(6~7), 不带键基线 rt=57, medium 均值 63.6; " "thinking:{type:disabled} 同样有效。" "限制: 5552 token 的长上下文下 none 不能压到 0(N=3 实测 97/5/10)" ), ), ``` ## 没有覆盖到的 - **`glm-5.2` 的数据不可信,不建议据此登记。** 这个渠道对 `glm-5.2` 的请求,响应里的 `model` 字段回报 `glm-5.3`(遥测里 5 次历史调用加 1 次现测,6/6 全部如此),怀疑被路由到了 `glm-5.3`。所以我测到的「glm-5.2」行为可能根本是 glm-5.3 的。这是渠道侧的问题,不是本库的,写在这里只是说明为什么第三个型号缺席。 - 只在这一个自建中转渠道上测过,**没有直连智谱官方端点**。 - 没测 `high` / `low` / `minimal` 三档。 - `strip_think_tags` 取 `False` 是按响应里 `content` 字段干净、推理走 `reasoning_content` 观察到的,没有专门构造用例验证。
Author
Owner

本 issue 由 1.3.3 交付并关闭。

你抱怨的三道机制,现在各自恢复了

合并前的独立验证用真实工厂路端到端跑过,zhipu 段与你原本误挂的 openai 兜底段两种拼法结果一致——能力表按 model 查、与 provider 无关,所以覆盖面比本 issue 建议的「补一条 zhipu profile」更宽:

机制 现状
ThinkingCapability 查不到 get_capability('glm-5.3') 返回 ('low','high','max') 并带出处
② 装配期报错不触发 触发,且带可执行替代: 文案给出该模型最省的档、可直接粘贴的 env 键与 Python 写法
③ 运行期对账不成立 成立。只配 REASONING_EFFORT=none(不配 ENABLE_THINKING)的源,观测到推理时如实喊出「未被满足」并附 evidence

第 ② 条的文案特意设计成必带出路——本 issue 的成因正是「报错不给出路,下游只能退回 extra_body」。

核心争议:glm-5.3 确实关不掉

T10 经 new-api 对 26 个模型做了约 500 次真实调用。请求 none 后 4/5 轮仍在推理,你记录的 rt≈1.2 是短提示词下的采样噪声。三个独立源(智谱官方文档、cherry-studio、OpenRouter)与实测一致。

真正让这个结论站住的是 glm-5.3-flash:短提示词 5/5 轮看着像关掉了,长上下文 3 轮里 2 轮露馅。只跑短提示词它会被判成「可以关」——这正是你当初中招的形态,所以实测判据里「短提示词的『关掉了』必须过长上下文复核」是硬性的。

因此 can_disable=True 没有按本 issue 的建议登记;glm-5.3 / glm-5.3-flash 登记为不可关闭,而这是 1.3.3 里唯一会打断存量配置的变更——升级后当场失败的下游,正是一直在静默烧推理 token 的那些。

你记的渠道串台仍在

本 issue 提到「glm-5.2 的请求 6/6 回报 model=glm-5.3」。实测复现且范围更大:glm-5 / glm-5.1 / glm-5.2 三个型号 5/5 轮全部被路由到 glm-5.3,这三条的能力表因此只能维持文档推定(evidence 已逐条写明原因)。这是渠道侧问题,库这边补不了,需要网关修路由。

glm-5.2 有个具体的下游陷阱:库按文档推定放行 none,而真正服务请求的 glm-5.3 关不掉推理,运行期对账只能事后告警。CHANGELOG 已就此写明。

顺带产出

  • 能力表 24 条(17 条实测 / 7 条文档推定,逐条自报家门);新增 zhipu / moonshot / anthropic / google 四个 provider 段
  • 遥测加第 26 个字段 reasoning_effort,「不同档位是不是真有用」这类压测在数据侧终于能分组
  • 两条本次挖出、留待后续的问题:#21(autoon_base={} 的 provider 上表达不了「开」)、#22(单源 + 上游 429 无 Retry-After 时挂满 stall window)

发布: https://gitea.iomgaa.online/iomgaa/PolyGateway/releases/tag/v1.3.3

本 issue 由 **1.3.3** 交付并关闭。 ## 你抱怨的三道机制,现在各自恢复了 合并前的独立验证用真实工厂路端到端跑过,`zhipu` 段与你原本误挂的 `openai` 兜底段**两种拼法结果一致**——能力表按 model 查、与 provider 无关,所以覆盖面比本 issue 建议的「补一条 zhipu profile」更宽: | 机制 | 现状 | |---|---| | ① `ThinkingCapability` 查不到 | `get_capability('glm-5.3')` 返回 `('low','high','max')` 并带出处 | | ② 装配期报错不触发 | 触发,且**带可执行替代**: 文案给出该模型最省的档、可直接粘贴的 env 键与 Python 写法 | | ③ 运行期对账不成立 | 成立。只配 `REASONING_EFFORT=none`(不配 `ENABLE_THINKING`)的源,观测到推理时如实喊出「未被满足」并附 evidence | 第 ② 条的文案特意设计成必带出路——本 issue 的成因正是「报错不给出路,下游只能退回 `extra_body`」。 ## 核心争议:glm-5.3 确实关不掉 T10 经 new-api 对 26 个模型做了约 500 次真实调用。**请求 `none` 后 4/5 轮仍在推理**,你记录的 rt≈1.2 是短提示词下的采样噪声。三个独立源(智谱官方文档、cherry-studio、OpenRouter)与实测一致。 真正让这个结论站住的是 `glm-5.3-flash`:短提示词 5/5 轮看着像关掉了,**长上下文 3 轮里 2 轮露馅**。只跑短提示词它会被判成「可以关」——这正是你当初中招的形态,所以实测判据里「短提示词的『关掉了』必须过长上下文复核」是硬性的。 因此 `can_disable=True` **没有**按本 issue 的建议登记;`glm-5.3` / `glm-5.3-flash` 登记为不可关闭,而这是 1.3.3 里唯一会打断存量配置的变更——升级后当场失败的下游,正是一直在静默烧推理 token 的那些。 ## 你记的渠道串台仍在 本 issue 提到「glm-5.2 的请求 6/6 回报 model=glm-5.3」。实测复现且范围更大:**`glm-5` / `glm-5.1` / `glm-5.2` 三个型号 5/5 轮全部被路由到 `glm-5.3`**,这三条的能力表因此只能维持文档推定(evidence 已逐条写明原因)。**这是渠道侧问题,库这边补不了**,需要网关修路由。 `glm-5.2` 有个具体的下游陷阱:库按文档推定放行 `none`,而真正服务请求的 `glm-5.3` 关不掉推理,运行期对账只能事后告警。CHANGELOG 已就此写明。 ## 顺带产出 - 能力表 24 条(**17 条实测 / 7 条文档推定**,逐条自报家门);新增 `zhipu` / `moonshot` / `anthropic` / `google` 四个 provider 段 - 遥测加第 26 个字段 `reasoning_effort`,「不同档位是不是真有用」这类压测在数据侧终于能分组 - 两条本次挖出、留待后续的问题:#21(`auto` 在 `on_base={}` 的 provider 上表达不了「开」)、#22(单源 + 上游 429 无 `Retry-After` 时挂满 stall window) 发布: https://gitea.iomgaa.online/iomgaa/PolyGateway/releases/tag/v1.3.3
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: iomgaa/PolyGateway#20