# PR #25454 完整报告

- 仓库：`sgl-project/sglang`
- 标题：fix(eagle3): drop +1 offset on aux layer ids when first id != 1
- 合并时间：2026-05-19 02:25
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25454

---

# 执行摘要

- 一句话：修复 EAGLE3 draft 模型 aux 层 ID 偏移问题
- 推荐动作：建议合并。此修复针对特定 draft 模型的兼容性问题，逻辑清晰，风险低，且有助于提升模型准确度。

# 功能与动机

EAGLE3 draft 模型生成的 `eagle_aux_hidden_state_layer_ids` 有两种不同的编码约定，原代码无条件对所有 ID 加 1，导致遵循第二种约定（first id == 2）的 draft 接受长度下降约 0.10（例如 `lightseekorg/kimi-k2.5-eagle3-mla` 模型）。此 PR 旨在通过检查第一个 ID 的值来区分两种约定，正确应用偏移。

# 实现拆解

1. 在 `DeepseekV2ForCausalLM.set_eagle3_layers_to_capture` 方法中（文件 `deepseek_v2.py`），将原先无条件对所有 `layer_ids` 加 1 的逻辑改为条件判断：当 `layer_ids[0] == 1` 时，说明属于“output-of-layer-X”约定，执行 `val + 1`；否则直接使用原值。 
2. 添加了 `TODO` 注释，提醒后续检查其他 draft 模型是否需要类似的 layer id 调整。
3. 仅修改了一个分支路径，不影响空 `layer_ids` 时的默认行为（`[2, num_layers//2, num_layers-3]`），也不影响 `set_dflash_layers_to_capture` 方法（保持无条件加 1）。

关键文件：
- `python/sglang/srt/models/deepseek_v2.py`（模块 模型层；类别 source；类型 data-contract；符号 set_eagle3_layers_to_capture）: 核心变更文件，修改了 set_eagle3_layers_to_capture 方法中的 layer id 偏移逻辑，通过条件判断区分两种编码约定。

关键符号：set_eagle3_layers_to_capture

## 关键源码片段

### `python/sglang/srt/models/deepseek_v2.py`

核心变更文件，修改了 set_eagle3_layers_to_capture 方法中的 layer id 偏移逻辑，通过条件判断区分两种编码约定。

```python
def set_eagle3_layers_to_capture(self, layer_ids: Optional[List[int]] = None):
    if not self.pp_group.is_last_rank:
        return

    if layer_ids is None:
        self.capture_aux_hidden_states = True
        num_layers = self.config.num_hidden_layers
        self.model.layers_to_capture = [2, num_layers // 2, num_layers - 3]
    else:
        self.capture_aux_hidden_states = True
        # TODO (Qiaolin-Yu): check if other draft models need similar layer id
        # adjustment
        # 约定 1: first id == 1 表示 output-of-layer-X, sglang 捕获循环在 layer i 之前触发 ,
        # 因此需要加 1 偏移以获取第 X 层的输出；
        # 约定 2: first id == 2 表示 input-to-layer-X / capture-before-X, 无需偏移。
        if layer_ids and layer_ids[0] == 1:
            self.model.layers_to_capture = [val + 1 for val in layer_ids]
        else:
            self.model.layers_to_capture = list(layer_ids)

```

# 评论区精华

代码 review 获得 approve，无其他讨论。

- 暂无高价值评论线程

# 风险与影响

- 风险：风险较低。变更仅影响 `set_eagle3_layers_to_capture` 中 `layer_ids` 非 None 的分支，且通过 first id 值做了区分。对于遵循第一种约定的 draft（`first id == 1`），行为与之前一致。对于未使用此路径或 `layer_ids` 为 None 的情况，无影响。可能存在未覆盖的边界情况：如果 `layer_ids` 为空列表，但代码中 `if layer_ids and layer_ids[0] == 1` 会优雅地进入 else 分支，不会出错。
- 影响：影响范围小，仅涉及 EAGLE3 speculative decoding 场景，且仅影响显式传入 layer_ids 的 draft 模型（如 `kimi-k2.5-eagle3-mla`）。对于使用默认 layer_ids（None）的模型（如 `kimi-k1.5`），无变化。
- 风险标记：暂无

# 关联脉络

- 暂无明显关联 PR