![[Bug]: thinking_token_budget not enforced on re-entry after natural](https://www.chat-gpts.plus/wp-content/uploads/2026/07/45974-e67f0614.jpg)
[Bug]: thinking_token_budget not enforced on re-entry after natural
快速结论:当模型在同一个 completion 中自然结束一个 thinking 块(输出 </think>)后又开启第二个 <think> 块时,thinking_token_budget 不会生效,导致第二个 thinking 块可以无限推理。优先排查是否运行在 vLLM 最新 main 分支,并检查 PR #43757 是否已合入。
问题场景
用户在使用 vLLM 推理引擎时,启用了 thinking_token_budget 配置参数(用于限制模型在 <think> 块中的推理 token 数量),且模型在一个 completion 内可能输出多个 <think> 块。当模型在第一个 thinking 块自然结束时(主动输出 </think> 而非被预算强制截断),再开启第二个 thinking 块时,预算控制完全失效。
报错原文
Block 2 should be budget-enforced after 14 tokens (budget=10), but in_end=False
实际表现为:第二个 thinking 块可以输出任意数量的 token,thinking_token_budget 不会触发强制结束。
原因分析
确定原因:vLLM 的 ThinkingBudgetStateHolder 状态机在处理自然结束的 thinking 块时存在状态残留问题。具体来说:
- 自然结束的 thinking 块不会更新
scan_offset(起始扫描位置),该值保持为 0。 - 状态变量
start_thinking和end_thinking也不会被重置,仍然指向第一个 thinking 块的位置。 - 当第二个
<think>出现时,_find_last_sequence_index从位置 0 开始搜索,找到的是第一个 thinking 块的start_thinking,且因为start_thinking (0) < end_thinking (7),状态机误判为“正在退出 thinking 模式”,导致第二个 thinking 块永远不会被识别为进入 thinking 模式。
对比已修复的强制结束情况(#43757):强制截断后会更新 scan_offset 和重置状态变量,所以重新进入 thinking 块能被正确检测。
环境排查
- vLLM 版本:确认是否在
vllm/vllm-openai:latest或最新main分支上(问题仍存在)。 - 确认启用了
thinking_token_budget配置,且模型能够生成多个 thinking 块。 - 检查 PR #43757 是否已合入(该 PR 修复了强制结束后的重新进入问题,但未覆盖自然结束的情况)。
解决步骤
以下修复方案来自 Issue 讨论,已经作者本地验证通过(Docker 环境测试:修复前 3/5 测试用例失败,修复后全部通过):
- 修改
_find_last_sequence_index的搜索起点:将其搜索范围改为从scan_offset开始,而不是从 0 开始。 - 自然结束时的状态重置:当检测到自然结束(
start_thinking < end_thinking或仅找到end_thinking)时,重置以下状态变量:start_thinking = -1,end_thinking = -1,continue_thinking = False,并将scan_offset更新为当前输出 token 数量。 - 强制结束时的状态重置:在强制结束路径(END_COMPLETE)中应用相同的重置逻辑(PR #43757 中已有,扩展其适用范围)。
- (可选)使用
had_forced_end标志:另一种实现方案是在状态字典中新增布尔标志had_forced_end,用于区分自然结束和强制结束,以决定强制结束后的新 thinking 块是否需要立即被截断。但作者认为直接用scan_offset足够,无需新增标志。
验证方法
运行 Issue 中提供的单元测试代码(test_natural_end_reentry.py),验证以下场景全部通过:
- 自然结束 + 单 token 重新进入
- 自然结束 + 多 token 重新进入
- 强制结束场景(回归测试)
- 两个无回归测试(确保原有逻辑未被破坏)
此外,可通过实际推理测试确认模型在第二个 thinking 块时确实被预算截断(输出 token 数不超过 thinking_token_budget)。


![[问与答] codex 的重置卡过期是废弃还是自动重置一次](https://www.chat-gpts.plus/wp-content/uploads/2026/07/ai_cover_4-335-768x403.jpg)
