MiniMax-M3 开启推理已静默失效:参数进了请求体但模型不推理,reasoning_tokens 恒 NULL #16

Closed
opened 2026-08-24 12:28:58 +08:00 by iomgaa · 1 comment
Owner

现象

MiniMax-M3 的开启推理已经不生效,而且是静默的:请求照常成功、内容照常返回,只是模型没有推理,reasoning_tokens 恒为 NULL关闭推理的方向一切正常。

tests/e2e/test_thinking_live.py 的前后对比(报告落在 tests/outputs/e2e/):

检查项 2026-08-02 2026-08-20
L2 开启推理(流式,注入 medium) PASS,15/15 轮观察到推理 FAIL,0/10 轮
L3b 非法值反证 none 被识别 PASS,非法值 5/5 轮推理 FAIL,非法值 0/3 轮推理
L4 extra_body 覆盖 profile 注入 PASS,7/7 轮推理 FAIL,0/5 轮
L5 非流式路径重跑 L1/L2 PASS,开启 7/7 轮 FAIL,开启 0/5 轮
L1 / L3 / L6 / L7 / L8(关闭方向与其他 provider) PASS 仍全部 PASS

已经排除的两个可能

不是库把参数弄丢了。 同一份报告里 L2b 是 PASS:「关闭档最大 194 < 开启档最小 216」。开启档的 prompt_tokens 比关闭档高 22,说明推理参数确实进了请求体并被计费,是模型收到之后没照做。

不是 1.2.4 引入的。296c765(1.2.3,issue #14 合并之前)上单跑 test_l2_enable_actually_enables,同样 FAIL(35 秒)。这两批改动没有任何一处碰过 transports/providers.py

为什么之前没被发现

test_thinking_live.py 一直标着 slow,被 addopts = "-m 'not slow'" 默认排除,平时不跑。上次真跑是 2026-08-02——正好是最后一次全绿。这 18 天里没有任何一次日常测试会碰到它。

(同批已把另外三个 tests/e2e/ 文件也标上 slow,并把 pytest -m slow 写进了发布清单第 4 步。否则这类问题只会被埋得更久。)

线索

providers.py:119 对 M3 的能力声明,证据日期正是 8 月 2 日:

"MiniMax-M3": ThinkingCapability(
    can_disable=True,
    evidence="2026-08-02 经 new-api 中转实测 N=10: reasoning_effort=none 稳定关闭,零跳变",
),

注册表停在 8 月 2 日的实测证据上,而这 18 天里上游变了。候选原因(未验证,按怀疑度排序):

  1. 中转层(new-api)吞掉或改写了推理参数 —— 关闭方向仍生效说明不是整个参数被丢,更像是"开启"那一档的取值不再被接受
  2. MiniMax 改了 M3 的参数契约 —— 比如 reasoning_effort 的合法取值变了,或改用了别的字段名
  3. M3 的模型版本被上游悄悄换掉 —— 开启档 prompt_tokens 从 8 月 2 日的最小 207 变成 216,同样的注入产生了不同的 token 数,这一点值得先查

排查建议:先用 curl 直接打中转和(如果可能)直连 MiniMax,对比同一份请求体的响应,把"中转改写"与"模型变更"分开。

影响

  • 依赖 M3 推理能力的下游拿到的是不推理的答案,而库不报错——与 issue #7 记录的那类"静默失效"同形
  • reasoning_tokens 对 M3 恒为 NULL,issue #6 加的推理开销归因对这个模型等于失效
  • ThinkingCapabilitycan_disable=True 声明本身仍然成立(关闭方向实测仍 PASS),但整条证据链的时效性需要重新审视——注册表里的 evidence 是有保质期的,这可能才是这个 issue 最该沉淀下来的东西

复现

conda run -n PolyGateway python -m pytest \
  "tests/e2e/test_thinking_live.py::TestMiniMaxM3" -m slow -q

需要 .env 里配好 LLM__MINIMAX__1__*。报告会落到 tests/outputs/e2e/

## 现象 MiniMax-M3 的**开启**推理已经不生效,而且是静默的:请求照常成功、内容照常返回,只是模型没有推理,`reasoning_tokens` 恒为 `NULL`。**关闭**推理的方向一切正常。 `tests/e2e/test_thinking_live.py` 的前后对比(报告落在 `tests/outputs/e2e/`): | 检查项 | 2026-08-02 | 2026-08-20 | |---|---|---| | L2 开启推理(流式,注入 medium) | PASS,**15/15** 轮观察到推理 | **FAIL,0/10 轮** | | L3b 非法值反证 none 被识别 | PASS,非法值 5/5 轮推理 | **FAIL,非法值 0/3 轮推理** | | L4 `extra_body` 覆盖 profile 注入 | PASS,7/7 轮推理 | **FAIL,0/5 轮** | | L5 非流式路径重跑 L1/L2 | PASS,开启 7/7 轮 | **FAIL,开启 0/5 轮** | | L1 / L3 / L6 / L7 / L8(**关闭**方向与其他 provider) | PASS | **仍全部 PASS** | ## 已经排除的两个可能 **不是库把参数弄丢了。** 同一份报告里 L2b 是 PASS:「关闭档最大 194 < 开启档最小 216」。开启档的 `prompt_tokens` 比关闭档高 22,说明推理参数**确实进了请求体并被计费**,是模型收到之后没照做。 **不是 1.2.4 引入的。** 在 `296c765`(1.2.3,issue #14 合并之前)上单跑 `test_l2_enable_actually_enables`,同样 FAIL(35 秒)。这两批改动没有任何一处碰过 `transports/` 或 `providers.py`。 ## 为什么之前没被发现 `test_thinking_live.py` 一直标着 `slow`,被 `addopts = "-m 'not slow'"` 默认排除,平时不跑。上次真跑是 2026-08-02——正好是最后一次全绿。这 18 天里没有任何一次日常测试会碰到它。 (同批已把另外三个 `tests/e2e/` 文件也标上 `slow`,并把 `pytest -m slow` 写进了发布清单第 4 步。否则这类问题只会被埋得更久。) ## 线索 `providers.py:119` 对 M3 的能力声明,证据日期正是 8 月 2 日: ```python "MiniMax-M3": ThinkingCapability( can_disable=True, evidence="2026-08-02 经 new-api 中转实测 N=10: reasoning_effort=none 稳定关闭,零跳变", ), ``` 注册表停在 8 月 2 日的实测证据上,而这 18 天里上游变了。候选原因(未验证,按怀疑度排序): 1. **中转层(new-api)吞掉或改写了推理参数** —— 关闭方向仍生效说明不是整个参数被丢,更像是"开启"那一档的取值不再被接受 2. **MiniMax 改了 M3 的参数契约** —— 比如 `reasoning_effort` 的合法取值变了,或改用了别的字段名 3. **M3 的模型版本被上游悄悄换掉** —— 开启档 `prompt_tokens` 从 8 月 2 日的最小 207 变成 216,同样的注入产生了不同的 token 数,这一点值得先查 排查建议:先用 `curl` 直接打中转和(如果可能)直连 MiniMax,对比同一份请求体的响应,把"中转改写"与"模型变更"分开。 ## 影响 - 依赖 M3 推理能力的下游拿到的是**不推理的答案,而库不报错**——与 issue #7 记录的那类"静默失效"同形 - `reasoning_tokens` 对 M3 恒为 `NULL`,issue #6 加的推理开销归因对这个模型等于失效 - `ThinkingCapability` 的 `can_disable=True` 声明本身仍然成立(关闭方向实测仍 PASS),但整条证据链的时效性需要重新审视——**注册表里的 evidence 是有保质期的**,这可能才是这个 issue 最该沉淀下来的东西 ## 复现 ```bash conda run -n PolyGateway python -m pytest \ "tests/e2e/test_thinking_live.py::TestMiniMaxM3" -m slow -q ``` 需要 `.env` 里配好 `LLM__MINIMAX__1__*`。报告会落到 `tests/outputs/e2e/`。
Author
Owner

已随 1.3.1 修复并发布。

先纠正诊断:M3 的推理一直是正常的

本 issue 判定「模型不推理」。2026-08-25 绕开库、用裸 httpx 抓真实响应,结论相反:M3 流式开启档拿到 124 字符完整推理正文,prompt_tokens 194→216、completion_tokens 3→60,三个独立信号一致。

真正变的是 MiniMax 这一路上游不再返回 usage.completion_tokens_details(qwen 与 deepseek 在同一网关、同一 key 上照常返回),reasoning_tokens 因此恒为 None。而库把「推理是否发生」全押在这一个字段上,于是手里握着 185 字符推理正文,却对外报告「没推理」

四条 e2e 红的是判据盲区,不是功能失效。完整实测见 research-wiki/findings/2026-08-25-thinking-observability-regression.md

修的是三层,不是那一条

缺陷 本版
reasoning_tokens=None 同时承载「没推理」与「没上报」,不可区分(types.py 的 docstring 早写明了这个歧义,但只是描述它) LLMResponse.thinking_observation 三态:observed / absent / unknown,判不出来时说 unknown,不折叠进「没推理」
库解析出的 thinking 正文从未参与任何判定——手里的硬证据丢在地上 裁定按证据硬度排序:推理正文是事实本身,token 计数是对事实的转述,转述缺失时事实仍然作数
能力表是静态单向声明,没有任何机制把声明与运行时观测对账 每次调用做一次对账,矛盾即告警(按 源×模型×方向 节流一次),让声明过期从静默错觉变成可报警事件

第 ③ 层是重点:M3 的 evidence 曾停在 08-02 整整 23 天而无人知晓它是否还成立。不修这一层,下一个同构故障会更隐蔽——若哪天 M3 变成关不掉推理,旧判据下连测试都是绿的。

顺带确认的事实

  • reasoning_effort 仍是 M3 唯一有效的开关(enable_thinking / thinking:{type:enabled} 对它无效),can_disable=True 经复测依然成立。
  • 「非法值反证」这一测试手法不可移植:minimax 对非法 reasoning_effort 返 200 且照常推理,qwen 对同值返 HTTP 400。

见 issue #17(同一件事的另一份记录)与 CHANGELOG 1.3.1。

已随 **1.3.1** 修复并发布。 ## 先纠正诊断:M3 的推理一直是正常的 本 issue 判定「模型不推理」。2026-08-25 绕开库、用裸 `httpx` 抓真实响应,结论相反:M3 流式开启档拿到 **124 字符完整推理正文**,`prompt_tokens` 194→216、`completion_tokens` 3→60,三个独立信号一致。 真正变的是 **MiniMax 这一路上游不再返回 `usage.completion_tokens_details`**(qwen 与 deepseek 在同一网关、同一 key 上照常返回),`reasoning_tokens` 因此恒为 `None`。而库把「推理是否发生」全押在这一个字段上,于是**手里握着 185 字符推理正文,却对外报告「没推理」**。 四条 e2e 红的是判据盲区,不是功能失效。完整实测见 `research-wiki/findings/2026-08-25-thinking-observability-regression.md`。 ## 修的是三层,不是那一条 | 层 | 缺陷 | 本版 | |---|---|---| | ① | `reasoning_tokens=None` 同时承载「没推理」与「没上报」,不可区分(`types.py` 的 docstring 早写明了这个歧义,但只是描述它) | `LLMResponse.thinking_observation` 三态:`observed` / `absent` / `unknown`,判不出来时说 `unknown`,**不折叠进「没推理」** | | ② | 库解析出的 `thinking` 正文从未参与任何判定——手里的硬证据丢在地上 | 裁定按证据硬度排序:推理正文是事实本身,token 计数是对事实的转述,转述缺失时事实仍然作数 | | ③ | 能力表是静态单向声明,没有任何机制把声明与运行时观测对账 | 每次调用做一次对账,矛盾即告警(按 源×模型×方向 节流一次),**让声明过期从静默错觉变成可报警事件** | 第 ③ 层是重点:M3 的 evidence 曾停在 08-02 整整 23 天而无人知晓它是否还成立。不修这一层,下一个同构故障会更隐蔽——若哪天 M3 变成关不掉推理,旧判据下连测试都是绿的。 ## 顺带确认的事实 - `reasoning_effort` 仍是 M3 唯一有效的开关(`enable_thinking` / `thinking:{type:enabled}` 对它无效),`can_disable=True` 经复测依然成立。 - 「非法值反证」这一测试手法**不可移植**:minimax 对非法 `reasoning_effort` 返 200 且照常推理,qwen 对同值返 HTTP 400。 见 issue #17(同一件事的另一份记录)与 CHANGELOG 1.3.1。
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: iomgaa/PolyGateway#16