贡献指南#

欢迎来到 SGLang!感谢您有兴趣为本项目做出贡献。本指南简要概述了如何设置环境、运行测试、构建文档以及提交 Pull Request (PR)。无论您是修复一个小 bug 还是开发一个重大功能,我们都建议遵循这些步骤,以确保贡献过程顺利进行。

从源码安装 SGLang#

Fork 并克隆仓库#

注意:新贡献者没有直接向 SGLang 官方仓库推送代码的写权限。请在您的 GitHub 账号下 fork 该仓库,然后将您的 fork 克隆到本地。

git clone https://github.com/<your_user_name>/sglang.git

从源码构建#

请参考 从源码安装 SGLang

使用 pre-commit 格式化代码#

我们使用 pre-commit 来维持一致的代码风格检查。在推送更改之前,请运行:

pip3 install pre-commit
pre-commit install
pre-commit run --all-files
  • pre-commit run --all-files 会手动运行所有配置好的检查,并尽可能应用修复。如果第一次运行失败,请重新运行以确保 lint 错误已完全解决。在创建 Pull Request 之前,请确保您的代码通过了所有检查。

  • 不要直接提交main 分支。请务必创建一个新分支(例如 feature/my-new-feature),推送您的更改,然后从该分支开启 PR。

运行并添加单元测试#

如果您添加了新功能或修复了 bug,请添加相应的单元测试以确保覆盖率并防止回归。SGLang 使用 Python 内置的 unittest 框架。有关运行测试并将其集成到 CI 中的详细说明,请参考 test/README.md

编写文档#

我们建议新贡献者从编写文档开始,这有助于您快速了解 SGLang 的代码库。更多详情请参考 docs/README.md

测试准确性#

如果您的代码更改了模型输出,请运行准确性测试。few-shot GSM8K 是一个快速的完整性检查方法。

# Launch a server
python3 -m sglang.launch_server --model Qwen/Qwen2-7B-Instruct

# Evaluate
python3 -m sglang.test.few_shot_gsm8k --num-questions 200

请注意,上述脚本主要用于完整性检查,而非严谨的准确性或速度测试。由于批处理和推理引擎的非确定性,该测试的准确性可能会有较大波动(1%–5%)。此外,不要依赖该脚本中的“Latency/Output throughput”,因为它不是正式的速度测试。

如今 GSM8K 对于最先进的模型来说过于简单。请尝试您自己更具挑战性的准确性测试。您可以在以下文件中找到额外的准确性评估示例:

测试速度基准#

参考 基准测试与性能分析

请求合并审查#

您可以遵循 MAINTAINER.md 中描述的 Pull Request 合并流程。您需要与合并值班人员(Merge Oncall)、代码所有者(Codeowner)以及其他审阅者合作以获得批准。之后您的 PR 才能被合并。

如何触发 CI 测试#

虽然我们有很多开放的 PR,但 CI 机器资源有限,因此只有顶层且受信任的贡献者才有权限触发 CI 测试。拥有权限的用户列表见 CI_PERMISSIONS.json

若要在 Pull Request 上运行 CI,必须带有 “run-ci” 标签。授权用户可以通过在 PR 中回复以下命令来添加标签或重新运行失败的测试:

  • /tag-run-ci-label:添加 “run-ci” 标签。此后的每一次提交都会触发 CI。

  • /rerun-failed-ci:重新运行最近一次提交中失败或不稳定的测试。

  • /tag-and-rerun-ci:一个执行 /tag-run-ci-label/rerun-failed-ci 两个操作的组合命令。

  • /rerun-stage <stage-name>:重新运行特定的测试阶段,而不必等待其依赖项。当您想要快速验证针对特定测试失败的修复,而不想等待约 30 分钟让前置阶段完成时,这非常有用。

如果您拥有权限,斜杠命令处理器 (Slash Command Handler) 将运行您的命令并在您的评论下回复 👍。该反应可能需要几分钟才会显示。这里有一个使用示例

为了避免在 PR 中产生过多的 /rerun-failed-ci 评论,您也可以通过编辑现有评论并添加任何后缀(例如 /rerun-failed-ci try again)来触发命令。

重新运行单个测试阶段的示例:/rerun-stage unit-test-backend-4-gpu

如果您没有权限,请请求维护者为您触发 CI。

CI 速率限制#

我们实施了 CI 速率限制,以防止滥用并确保 CI 资源的公平使用。

每个 CI 工作流在其配置文件中都有一个默认限制。例如,在 pr-gate.yml 中,默认冷却时间为 120 分钟,每个工作流可以通过 cool-down-minutes 输入参数来覆盖它。

cool-down-minutes:
  description: "Default cooldown period in minutes; 0 disables rate limiting"
  type: number
  default: 120

CI_PERMISSIONS.json 中列出的用户可能拥有个人的冷却时间间隔。在实践中,我们取工作流默认窗口和用户特定间隔中的最小值。

代码风格指南#

  • 避免代码重复。如果同一代码段(超过五行)多次出现,请将其提取为共享函数。

  • 尽量减少设备同步。尽可能减少昂贵的 CPU-GPU 同步操作,如 tensor.item()tensor.cpu()。使用向量化代码。

  • 优先考虑极致效率。SGLang 是一个运行时(runtime),您的代码大多运行在每个请求的关键路径上。尽可能优化所有细微的开销,尤其是在模型的前向传播代码中。

    • 一个常见的模式是在模型前向传播中进行运行时检查(例如 这里)。这些检查对于每一层极可能都是相同的。请尽可能将结果缓存为单个布尔值。

  • 使函数尽可能纯净。避免对参数进行原地修改。

  • 保持文件简练。如果一个文件超过 2000 行代码,请将其拆分为多个较小的文件。(例如 scheduler.pyscheduler_output_processor_mixin.py

  • 保持测试快速运行。

    • 如果单个测试文件的运行时间超过 500 秒,请将其拆分为多个较小的文件(例如 test_eagle_infer_a.pytest_eagle_infer_b.py)。

    • 如果 GitHub 工作流中的单个作业运行时间超过 30 分钟,请将其拆分为更小的作业/步骤。

    • 在单元测试中重用服务器启动以加快测试运行速度。

  • 在支持新硬件或新功能时,请遵循以下准则:

    • 不要大幅改动现有代码。

    • 总是首选新建文件来引入针对新硬件的特定组件(例如 allocator_ascend.py)。

    • 如果您为新功能编写了多个 if/else 块,请确保通用路径(例如 NVIDIA 硬件或现有代码路径)位于第一个分支。

如何更新 sgl-kernel#

由于 sglang 和 sgl-kernel 是独立的 Python 包,我们目前的 GitHub CI 基础设施不支持在同一个 Pull Request (PR) 中更新内核并立即使用它。若要在 sgl-kernel 包中添加新内核或修改现有内核,必须使用多个 PR。

请遵循以下步骤:

  1. 提交一个更新 sgl-kernel 源代码的 PR,此时不要在 sglang python 包中使用它(例如 #8884)。

  2. 提升 sgl-kernel 的版本号(例如 #9220)。

    • 一旦合并,这将触发 sgl-kernel wheel 自动发布到 PyPI。

    • 如果不紧急,您可以等待其他人发布 wheel。新版本通常会在一周内发布。

  3. 应用更改:

    • 更新 sglang/python/pyproject.toml 中的 sgl-kernel 版本,以使用修改后的内核。

    • 更新 sglang 中相关的调用代码以使用新内核。

给新手的建议#

如果您想做出贡献但没有具体的想法,请选择带有 “good first issue” 或 “help wanted” 标签的任务。这些任务通常复杂度较低,是了解代码库的绝佳入口。此外,可以查看此 代码详解 以深入了解 SGLang 的工作流程。

如果您有任何问题或想发起讨论,请随时在我们的 Slack 频道 中提问。

感谢您对 SGLang 的关注。祝编码愉快!