---
type: finding
node_id: finding:2026-08-25-thinking-observability-regression
title: "issue #16/#17 实测: M3 推理正常,失效的是推理的可观测信号"
date: 2026-08-25
---

# issue #16/#17 实测：M3 推理正常，失效的是推理的**可观测信号**

> 类型：finding｜日期：2026-08-25｜网关 `newapi.iomgaa.online`
> 本文推翻 issue #16/#17 的原始诊断（"模型不再推理"），是 `designs/2026-08-25-thinking-observability-design.md` 的事实基础。

## 1. 为什么要重测

issue #16/#17 判定 MiniMax-M3 的开启推理"静默失效：模型没有推理"，依据是 `tests/e2e/test_thinking_live.py` 的 L2/L3b/L4/L5 四条全红，四条的共同判据是 `reasoning_tokens > 0`。issue 自己留了一个未区分的岔路：网关侧模型行为变了，还是库的注入失效了。区分方法写得很清楚——抓一次真实请求体与原始响应。本文就是那次抓取。

## 2. 方法

两层探针，都不走 slow 套件：

其一**绕开库**，用裸 `httpx` 直接 POST `/chat/completions`，矩阵化七种参数形态 × 流式/非流式，记录完整 `usage` 与 `message` 的键集合。绕开库是必要的——要证的命题之一正是"库有没有把参数弄丢"，用库测这一条是循环论证。

其二**用库本身**跑 `GatewayClient.chat`，记录 `LLMResponse` 的 `reasoning_tokens` 与 `thinking` 两个字段。两层对照才能定位缺口落在哪一层。

对照组取 `qwen3.7-plus` 与 `deepseek-v4-pro`——同一网关、同一 key，用来区分"MiniMax 这一路变了"与"网关全局变了"。

## 3. 原始观测

### 3.1 MiniMax-M3，裸 httpx，非流式

| 变体 | prompt | completion | `completion_tokens_details` | `reasoning_content` |
|---|---|---|---|---|
| 不注入（基线） | 194 | 3 | **整个容器缺失** | 无 |
| `reasoning_effort=medium` | **216** | **48** | 整个容器缺失 | 无 |
| `reasoning_effort=high` | **216** | **65** | 整个容器缺失 | 无 |
| `reasoning_effort=none` | 194 | 3 | 整个容器缺失 | 无 |
| `thinking={"type":"enabled"}` | 194 | 3 | 整个容器缺失 | 无 |
| `enable_thinking=true` | 194 | 3 | 整个容器缺失 | 无 |
| 非法值 `definitely-not-a-real-level` | 207 | 87 | 整个容器缺失 | 无 |

### 3.2 MiniMax-M3，裸 httpx，流式

| 变体 | delta 的键集合 | `reasoning_content` 累计 | usage |
|---|---|---|---|
| 不注入 | `content`,`role` | 0 字符 | prompt 194 / completion 3，无 ctd |
| `reasoning_effort=medium` | `content`,**`reasoning_content`**,`role` | **124 字符，完整推理过程** | prompt 216 / completion 60，无 ctd |
| `reasoning_effort=none` | `content`,`role` | 0 字符 | prompt 194 / completion 3，无 ctd |

流式 medium 档抓到的推理正文（前 120 字符）：`We need answer Chinese, only two digits. Chickens x rabbits y. x+y=35,2x+4y=94 => x+y*? 2*35+2y=94 y=12, x=23. Output 23`

### 3.3 对照组（流式）

| 模型 | 变体 | `reasoning_content` | `completion_tokens_details.reasoning_tokens` |
|---|---|---|---|
| deepseek-v4-pro | 不注入 | 135 字符 | **88** |
| deepseek-v4-pro | `effort=medium` | 134 字符 | **89** |
| deepseek-v4-pro | `effort=none` | 0 | 容器缺失 |
| qwen3.7-plus | 不注入 | 350 字符 | **158** |
| qwen3.7-plus | `effort=medium` | 606 字符 | **229** |
| qwen3.7-plus | `effort=none` | 0 | 容器缺失 |
| qwen3.7-plus | 非法值 | — | **HTTP 400** |

### 3.4 用库跑（`LLMResponse` 字段）

| 场景 | `reasoning_tokens` | `thinking` 字符数 | completion |
|---|---|---|---|
| M3 开启，流式 | None | **185** | 69 |
| M3 开启，非流式 | None | **0** | 53 |
| M3 关闭，流式/非流式 | None | 0 | 3 |
| M3 不干预 | None | 0 | 3 |
| qwen 开启，流式 | **205** | 484 | 213 |
| qwen 关闭，流式 | None | 0 | 5 |

## 4. 五条结论

**① M3 的推理完全正常，issue 的诊断是错的。** 流式 medium 档抓到 124 字符完整推理过程；`prompt_tokens` 194→216（供应商注入推理指令）、`completion_tokens` 3→60（推理段被计费）。三个独立信号一致。

**② 真正变的是 MiniMax 这一路不再返回 `usage.completion_tokens_details`。** 而 qwen 与 deepseek 在同一网关同一 key 上照常返回。所以这不是网关全局改了 usage 处理，是 MiniMax 这一路上游的 usage 形态变了。`reasoning_tokens` 恒 NULL 由此而来。

**③ 库自己已经握有决定性证据，却没有用。** `LLMResponse.thinking` 在 M3 开启档流式路径下是 185 字符的实打实推理正文。e2e 的 `_reasoning_on` 只看 `reasoning_tokens` 与 `completion_tokens` 长度，从不看 `thinking`——四条红是判据的盲区，不是功能的失效。

**④ M3 非流式路径下推理内容整体丢失，且下游在付费。** `completion_tokens` 53 vs 关闭档 3，说明推理段确实产生并计费；而 `message` 的键集合只有 `content`/`role`，`reasoning_content` 不存在。下游用非流式调 M3 开推理 = 付钱买看不见的东西，且当前库不告诉它。这不是库能修的（上游不返回），但库必须让它可见。

**⑤ 三家供应商在"未推理"时都是整个 `completion_tokens_details` 缺失，无人上报 `0`。** 与 2026-08-02 findings §4c 的记录一致。推论：**"容器在不在"不能当作"有没有推理"的判据**——它与真实信号高度混淆，拿它做裁定等于把噪声当信号。

## 5. 顺带纠正的两处既有认识

**`enable_thinking` / `thinking:{type:enabled}` 对 M3 无效这一条仍然成立**（prompt 恒 194 = 基线），只有 `reasoning_effort` 是真开关。`providers.py` 的 minimax profile 用的正是 `reasoning_effort`，选型至今正确。

**L3b 的"非法值反证"手法只对不校验值的 provider 成立。** minimax 对非法 `reasoning_effort` 返回 200 且照常推理（prompt 207，介于基线 194 与 medium 216 之间，说明走了第三条模板路径）；qwen 对同样的非法值直接 **HTTP 400**。这条手法写进测试时只在 minimax 上验过，它不可移植——若哪天把 L3b 套到别的 provider 上会得到假红。

## 6. `can_disable` 复测

M3 的 `ThinkingCapability(can_disable=True)` 的 evidence 停在 2026-08-02。2026-08-25 复测：`reasoning_effort=none` → prompt 194（= 基线）、completion 3、无 `reasoning_content`。**声明依然成立**，只需刷新 evidence 日期并补记本文新发现的两条限制（非流式不可观测、仅 `reasoning_effort` 有效）。
