# PR #27017 完整报告

- 仓库：`sgl-project/sglang`
- 标题：fix(schema): update tokens_after_end
- 合并时间：2026-06-10 07:52
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/27017

---

# 执行摘要

- 一句话：修复 schema 缓存导致的 reasoning 状态残留 bug
- 推荐动作：值得合入，修复逻辑清晰。建议后续为 `reasoner_grammar_backend` 添加单元测试覆盖 cached schema 场景，防止回归。

# 功能与动机

由 #23953 引入，当 schema 被缓存后，grammar 对象的最后状态仍然保留，导致 `tokens_after_end` 未被正确重置，从而引发状态错误。PR body 指出需要“init a full fresh state”。

# 实现拆解

1. **定位问题**：在 `reasoner_grammar_backend.py` 的 `MaybeInitReasoning` 方法中，当 `reasoning=True` 进入思考模式时，只重置了 `tokens_in_think`，没有重置 `tokens_after_end`，导致从缓存恢复的 grammar 对象 `tokens_after_end` 保留旧值（可能为 0 或正数），使得 `_is_generation()` 误判为生成阶段。
2. **单行修复**：在 `maybe_init_reasoning` 的 `reasoning=True` 分支中，新增 `self.tokens_after_end = -1`，与 `_is_thinking()` 的判断条件 (`tokens_in_think >= 0 and tokens_after_end == -1`) 保持一致，确保进入思考模式时状态完全正确。
3. **无测试配套改动**：PR 未添加单元测试，但改动极简（1 行），通过 CI 测试验证。

关键文件：
- `python/sglang/srt/constrained/reasoner_grammar_backend.py`（模块 约束后端；类别 source；类型 core-logic；符号 maybe_init_reasoning）: 修复核心文件，在 `maybe_init_reasoning` 中增加 `tokens_after_end = -1` 重置，是本次变更的唯一文件。

关键符号：maybe_init_reasoning

## 关键源码片段

### `python/sglang/srt/constrained/reasoner_grammar_backend.py`

修复核心文件，在 `maybe_init_reasoning` 中增加 `tokens_after_end = -1` 重置，是本次变更的唯一文件。

```python
# reasoner_grammar_backend.py 片段
class ReasonerGrammarBackend:
    # ...

    def maybe_init_reasoning(self, reasoning: bool):
        """
        根据 reasoning 是否为 True 初始化状态。
        当 reasoning=True 时，进入思考模式，重置 tokens_in_think 为 0，
        并将 tokens_after_end 设为 -1（与 _is_thinking 的判断条件一致）。
        修复前缺少 tokens_after_end = -1 的赋值，导致 schema 缓存后状态残留。
        """
        if reasoning:
            self.tokens_in_think = 0
            # 修复：确保进入思考模式时 tokens_after_end 为 -1，
            # 避免复用 cached grammar 对象时残留旧值导致的错误。
            self.tokens_after_end = -1
        else:
            self.tokens_in_think = -1
            self.tokens_after_end = 0

```

# 评论区精华

reviewer JustinTong0323 在批准时评论：“LGTM. Resetting `tokens_after_end = -1` correctly puts cached grammar objects back into THINKING state on reuse.” 确认了修复的正确性。无其他讨论。

- 暂无高价值评论线程

# 风险与影响

- 风险：**风险低**：该修复仅涉及单行赋值，逻辑与 `_is_thinking()` 判断条件吻合，不会引入新问题。但缺少对 cached schema 场景的单元测试，未来若有类似状态扩展可能再次遗漏。
- 影响：**影响范围**：影响使用 grammar 约束推理的 reasoning 模型（如 DeepSeek-R1 等）。修复后，当 schema 被缓存且复用 grammar 对象进入 reasoning 时，状态判断正确，避免生成阶段错误地调用 thinking 逻辑或 vice versa。用户无需更改配置，重启后自动生效。
- 风险标记：缺少测试覆盖

# 关联脉络

- PR #23953 相关 PR （编号为假设）: PR body 提到该 bug 由 #23953 引入，但实际仓库中未找到该 PR。