Prhub

#23991 Add registry for custom speculative algorithms

原始 PR 作者 hnyls2002 合并时间 2026-05-08 07:11 文件变更 4 提交数 4 评论 7 代码增减 +430 / -7

执行摘要

为自定义推测算法添加注册机制

PR 描述明确指出目标是让下游用户可以注册自定义推测方法,而无需修改 SGLang 源码。此前推测算法以枚举值硬编码,第三方无法扩展;本 PR 通过注册表机制解耦。

值得精读,它展示了如何在不破坏现有代码的前提下提供扩展点。对于需要自定义推测算法的用户尤其有价值,设计模式具有参考意义。

讨论亮点
  • jasonjk-parkspec_registry.py 中询问 supports_spec_v2 是否应返回 self.supports_overlap(代码已如此)。
  • merrymercy 质疑自定义算法为何需要 is_eagle 等方法;hnyls2002 解释公共代码路径使用这些方法进行调度,若不实现可能导致自定义算法崩溃。

实现拆解

  1. 新增注册表模块 (spec_registry.py):定义 CustomSpecAlgo 鸭式类型(默认 is_*() 方法除 is_speculative 外均返回 False)和全局注册表 _REGISTRY,提供 register_algorithm 装饰器和 get_spec 查找函数。
  2. 集成到 SpeculativeAlgorithm 枚举 (spec_info.py):from_string 方法在枚举查找失败后回退到注册表查询;新增 register 类方法作为对外 API。
  3. 调整服务参数验证 (server_args.py):移除 --speculative-algorithm 的硬编码 choices,先统一转为大写,通过 from_string 解析;若返回 CustomSpecAlgo 实例且设有 validate_server_args,则调用进行自定义校验。
  4. 增加单元测试 (test_spec_registry.py):覆盖注册成功、重复名称冲突、保留名称保护、大小写不敏感、鸭式接口行为等,确保注册表隔离不污染测试环境。
文件 模块 状态 重要度
python/sglang/srt/speculative/spec_registry.py 注册表 added 8.84
python/sglang/srt/speculative/spec_info.py 枚举集成 modified 7.92
python/sglang/srt/server_args.py 服务参数 modified 6.35
test/registered/unit/spec/test_spec_registry.py 单元测试 added 7.75

关键符号

CustomSpecAlgo.__init__ CustomSpecAlgo.is_speculative CustomSpecAlgo.create_worker register_algorithm get_spec SpeculativeAlgorithm.from_string SpeculativeAlgorithm.register

关键源码片段

python/sglang/srt/speculative/spec_info.py dependency-wiring

修改枚举类,集成注册表查找和 register 类方法

# python/sglang/srt/speculative/spec_info.py ( 节选 )from __future__ import annotations
from typing import TYPE_CHECKING, Callable, Optional, Type, Unionfrom sglang.srt.speculative.spec_registry import (
    CustomSpecAlgo,
    ServerArgsValidator,
    WorkerFactory,
)
from sglang.srt.speculative.spec_registry import get_spec as _get_registered_spec
from sglang.srt.speculative.spec_registry import register_algorithm as _register_algorithm
​
​
class SpeculativeAlgorithm(Enum):
    """Builtin speculative algorithms. Plugin-registered ones are ``CustomSpecAlgo`` instances."""
​
    DFLASH = auto()
    EAGLE = auto()
    EAGLE3 = auto()
    FROZEN_KV_MTP = auto()
    STANDALONE = auto()
    NGRAM = auto()
    NONE = auto()
​
    @classmethod
    def from_string(
        cls, name: Optional[str]
    ) -> Union[SpeculativeAlgorithm, CustomSpecAlgo]:
        """解析算法名称:先尝试内置枚举,再查询注册表"""
        if name is None:
            return cls.NONE
        upper = name.upper()
        try:
            return cls[upper] # 内置枚举匹配
        except KeyError:
            pass
        spec = _get_registered_spec(upper) # 查询插件注册表
        if spec is not None:
            return spec
        raise ValueError(f"Unknown speculative algorithm name: {name}")
​
    @classmethod
    def register(
        cls,
        name: str,
        *,
        supports_overlap: bool = False,
        validate_server_args: Optional[ServerArgsValidator] = None,
        spec_class: Type[CustomSpecAlgo] = CustomSpecAlgo,
    ) -> Callable[[WorkerFactory], WorkerFactory]:
        """对外注册 API,委托给 _register_algorithm"""
        return _register_algorithm(
            name,
            supports_overlap=supports_overlap,
            validate_server_args=validate_server_args,
            spec_class=spec_class,
        )

评论区精华

supports_spec_v2 实现 正确性

jasonjk-park 在 spec_registry.py 中询问 supports_spec_v2 是否应返回 self.supports_overlap

结论:代码已正确返回 self.supports_overlap,该评论确认正确性后关闭 · 已解决

自定义算法需要 is_eagle 等方法的原因 设计

merrymercy 质疑自定义算法为何需要 is_eagle 等方法,hnyls2002 解释公共代码路径使用这些方法进行调度,若不实现可能导致自定义算法崩溃

结论:hnyls2002 解释了必要性,merrymercy 未进一步质疑,设计决策被接受 · 已解决

风险与影响

  1. 全局注册表冲突:不同插件可能覆盖相同名称,但通过保留名称集和重复注册检查缓解。
  2. 自定义算法接口兼容:部分调度代码仍通过 is_xxx() 硬编码分支,自定义算法默认返回 False 可能跳过优化路径,导致性能降级或功能异常。
  3. 硬编码字符串检查:server_args.py 中与特定算法相关的检查(如 DFLASH)仍使用字符串比较,自定义算法需额外处理。
  4. 迁移工作:并非所有 is_xxx 使用点都被识别为 capability 检查,后续需逐步重构为 supports_xxx

用户:可自由集成自定义推测算法,降低二次开发成本。系统:注册表查找增加极小开销,命名冲突有保护机制。团队:明确了扩展点,未来可将内置算法逐步迁移至同一框架,减少 special case。

全局注册表冲突 自定义算法接口兼容 硬编码路径未完全适配

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论