# PR #26354 完整报告

- 仓库：`sgl-project/sglang`
- 标题：[SPEC] fix: use effective max draft tokens for adaptive spec initiali…
- 合并时间：2026-05-29 04:33
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/26354

---

# 执行摘要

- 一句话：修复 adaptive spec 初始化使用错误 draft token 数
- 推荐动作：建议所有维护 speculative decoding 模块的开发者阅读此 PR，了解如何正确使用 'cached_property' 和统一最大 draft token 数的获取方式。改动虽小但修复了隐蔽的 bug，值得认可。

# 功能与动机

引用 PR body：缓存最大 draft token 数到 'max_speculative_num_draft_tokens' 以避免每次调用重新解析 candidate steps，并修复初始化位置（'get_alloc_len_per_decode'、'tokenizer_manager'、mamba state reservation）使用 'effective_max_speculative_num_draft_tokens()' 而不是原始的 'speculative_num_draft_tokens'，确保 adaptive spec 切换到更大 candidate steps 时分配正确。

# 实现拆解

1. **添加 cached_property**（server_args.py）：将原本实例方法改为 `@cached_property` 属性 `max_speculative_num_draft_tokens`，缓存计算后的最大 draft token 数。
2. **更新模型运行器 **（model_runner_kv_cache_mixin.py）：在 `_init_pools` 中替换 `effective_max_speculative_num_draft_tokens()` 调用为 `max_speculative_num_draft_tokens` 属性。
3. **更新工具函数 **（managers/utils.py）：在 `get_alloc_len_per_decode` 中将 `speculative_num_draft_tokens` 改为 `max_speculative_num_draft_tokens`。
4. **更新 tokenizer 管理器 **（managers/tokenizer_manager.py）：在 `init_model_config` 中同样替换为新的属性。
5. **移除冗余字段**：根据 review 建议删除新加的 `speculative_adaptive_max_draft_tokens` 字段，完全由 cached_property 承担缓存作用。

关键文件：
- `python/sglang/srt/server_args.py`（模块 配置层；类别 source；类型 core-logic；符号 max_speculative_num_draft_tokens, effective_max_speculative_num_draft_tokens）: 核心变更文件，添加 cached_property 并替换方法，影响所有调用点
- `python/sglang/srt/model_executor/model_runner_kv_cache_mixin.py`（模块 运行器；类别 source；类型 data-contract；符号 _init_pools）: 在 _init_pools 中替换调用为新的属性，影响 KV cache 预留
- `python/sglang/srt/managers/utils.py`（模块 管理器；类别 source；类型 core-logic；符号 get_alloc_len_per_decode）: 修改 get_alloc_len_per_decode 使用 max_speculative_num_draft_tokens，影响解码分配长度
- `python/sglang/srt/managers/tokenizer_manager.py`（模块 Token 化管理器；类别 source；类型 core-logic；符号 init_model_config）: 在 init_model_config 中修改 num_reserved_tokens 的计算，使用新的属性

关键符号：max_speculative_num_draft_tokens, get_alloc_len_per_decode, init_model_config, _init_pools

## 关键源码片段

### `python/sglang/srt/server_args.py`

核心变更文件，添加 cached_property 并替换方法，影响所有调用点

```python
from functools import cached_property

class ServerArgs:
    # Adaptive speculative decoding 配置
    speculative_adaptive: bool = False
    speculative_adaptive_config: Optional[str] = None

    @cached_property
    def max_speculative_num_draft_tokens(self) -> Optional[int]:
        '''Return the maximum draft-token count speculative decoding may use.
        缓存最大 draft token 数，避免每次解析 adaptive 配置。
        '''
        if self.speculative_num_draft_tokens is None:
            return None
        if not self.speculative_adaptive:
            return self.speculative_num_draft_tokens
        # 解析 adaptive 配置并计算最大值
        # 具体实现略（涉及候选 steps 映射）
        return computed_max_draft

```

# 评论区精华

在 review 中，Qiaolin-Yu 建议：
- 使用 'cached_property' 代替实例方法来缓存最大 draft token 数
- 移除新添加的 'speculative_adaptive_max_draft_tokens' 字段，因为它不是用户配置项
作者 alphabetc1 回复 "done" 并实施了建议。无其他争议。

- 使用 cached_property 代替实例方法 (design): 作者采纳，改为 cached_property 并移除了字段。

# 风险与影响

- 风险：风险较低，但涉及核心解码分配逻辑：
 - **回归风险**：所有调用点都已被替换，但如果未来新增类似引用可能遗漏。
 - **性能影响**：'cached_property' 相比实例方法减少了重复计算，但有微小内存开销。
 - **兼容性**：对用户配置无影响，'speculative_num_draft_tokens' 仍然作为输入，但内部使用缓存后的 'max_speculative_num_draft_tokens'。
 - **mamba 状态预留**：PR 提到修复 mamba state reservation，但相关代码未在本次变更中直接体现（可能在其他文件），需确认是否已完成。
- 影响：影响所有使用 adaptive speculative decoding 的用户：
 - 确保在 adaptive 模式下，当 candidate steps 增大时，解码分配长度和 KV cache 预留正确。
 - 用户无需更改配置，但应注意到行为修复可能改变内存占用（之前可能分配不足）。
 - 对团队：代码结构更清晰，cached_property 避免了重复逻辑。
 - 风险标记：核心路径变更 , 缺少测试覆盖

# 关联脉络

- 暂无明显关联 PR