# PR #36704 完整报告

- 仓库：`sgl-project/sglang`
- 标题：Refactor JIT kernel and expert-pack directory layout
- 合并时间：2026-08-29 07:41
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/36704

---

# 执行摘要

- 一句话：重构 JIT 内核与专家打包目录布局
- 推荐动作：值得快速浏览，了解目录组织模式（ops 与 jit 分离、工具内嵌包）及延迟导入、Git 元数据回退等实用技巧。对于负责打包、部署或维护 JIT 内核的工程师，建议精读 `expert_pack_runtime.py` 和 `minicpm_sala/__init__.py` 的改动。

# 功能与动机

PR body 指出需要保持 JIT 内核树组织有序：将 Python 操作包装器与 JIT 基础设施分离，按功能区域分组 CUDA 源码，并避免功能特定的仓库级 tools 目录。这同时也是对 #35314 目录布局反馈的后续跟进。

# 实现拆解

1. **迁移 MiniCPM-SALA 包装器**：将 `python/sglang/kernels/jit/minicpm_sala/` 整体移至 `python/sglang/kernels/ops/minicpm_sala/`，新增 `__init__.py` 采用延迟导入（`__getattr__` 和 `__dir__`），避免过早加载 `get_block_table`，同时删除旧的 `jit/minicpm_sala/__init__.py`。CUDA 源文件保留在 `jit/csrc/minicpm_sala`，通过 loader 路径更新引用。
2. **重组 JIT 头文件**：将两个散落的 JIT 头文件分别移入 `csrc/elementwise` 和 `csrc/speculative`，并同步更新 loader 路径和 JIT 开发指南文档，使头文件按功能领域归档。
3. **迁移 expert_pack 工具**：将 `tools/expert_pack` 下所有文件（`build.py`、`format.py`、`kimi_ggml.py`、`prepare_deepseek_pack.py`、`prepare_kimi_pack.py`、`prepare_kimi_manifest.py`、`validate.py` 等）以 rename 方式迁入 `python/sglang/srt/model_loader/expert_pack/`，并新增包 `__init__.py`。运行时引用同步更新：`expert_pack_runtime.py` 中原先基于仓库根目录的 `_repo_root()` 改为 `_expert_pack_tools_dir()`，通过 `Path(__file__).with_name("expert_pack")` 定位工具目录，并将子进程 `cwd` 改为该目录。
4. **适配 CLI 与 Git 行为**：`prepare_kimi_manifest.py` 中仓库根路径从 `parents[2]` 改为 `parent`；`build.py` 的 `git_sha()` 增加 `try/except`，在非 git 环境下回退为 `"unknown"`，并补充 SPDX 许可头。
5. **同步测试与文档**：更新 `test/registered/expert_pack/test_expert_pack_runtime.py` 的导入与断言，新增对包路径的验证；更新 JIT 开发指南和示例中对移动后路径的引用，确保示例可运行。

关键文件：
- `python/sglang/srt/model_loader/expert_pack_runtime.py`（模块 模型加载；类别 source；类型 data-contract；符号 _expert_pack_tools_dir, ensure_kimi_assets, prepare_raw_kimi_server_args）: 核心运行时适配：将基于仓库根的路径解析改为包内相对路径，是本次重构的关键数据契约变更。
- `python/sglang/srt/model_loader/expert_pack/build.py`（模块 模型加载；类别 source；类型 rename-or-move；符号 git_sha）: expert_pack 核心构建工具，搬迁后调整 git_sha 回退逻辑。
- `python/sglang/kernels/ops/minicpm_sala/__init__.py`（模块 内核层；类别 infra；类型 infrastructure；符号 __getattr__, __dir__）: MiniCPM-SALA 包装器新入口，采用延迟导入避免加载性能损耗。
- `python/sglang/srt/model_loader/expert_pack/prepare_kimi_manifest.py`（模块 模型加载；类别 source；类型 rename-or-move；符号 main）: Kimi manifest 准备脚本，路径基准从仓库根调整为包目录。
- `python/sglang/kernels/jit/minicpm_sala/__init__.py`（模块 内核层；类别 source；类型 deletion）: 原 JIT 包装器入口被删除，避免旧路径继续生效。
- `test/registered/expert_pack/test_expert_pack_runtime.py`（模块 测试；类别 test；类型 test-coverage）: 同步更新测试导入和断言，验证包内工具路径解析。

关键符号：_expert_pack_tools_dir, ensure_kimi_assets, prepare_raw_kimi_server_args, prepare_raw_deepseek_server_args, git_sha, __getattr__

## 关键源码片段

### `python/sglang/srt/model_loader/expert_pack_runtime.py`

核心运行时适配：将基于仓库根的路径解析改为包内相对路径，是本次重构的关键数据契约变更。

```python
def _expert_pack_tools_dir() -> Path:
    # 解析工具目录为当前文件同级的 expert_pack 子目录，
    # 这样安装包后也能正确定位准备脚本，而不依赖源代码检出。
    tools_dir = Path(__file__).with_name("expert_pack")
    required_tools = (
        "prepare_deepseek_pack.py",
        "prepare_kimi_manifest.py",
        "prepare_kimi_pack.py",
    )
    # 显式检查必需脚本，缺失时给出清晰错误，避免子进程失败难排查。
    missing = [name for name in required_tools if not (tools_dir / name).is_file()]
    if missing:
        raise RuntimeError(
            "expert_pack preparation tools are missing: " + ", ".join(missing)
        )
    return tools_dir

```

### `python/sglang/kernels/ops/minicpm_sala/__init__.py`

MiniCPM-SALA 包装器新入口，采用延迟导入避免加载性能损耗。

```python
"""MiniCPM-SALA kernels."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from sglang.kernels.ops.minicpm_sala.get_block_table import get_block_table


def __getattr__(name: str) -> Any:
    # 延迟导入：仅在实际访问 get_block_table 时才加载内核符号，
    # 避免模块导入阶段触发不必要的 Triton 编译或 CUDA 初始化。
    if name == "get_block_table":
        from sglang.kernels.ops.minicpm_sala.get_block_table import get_block_table

        globals()[name] = get_block_table
        return get_block_table
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


def __dir__() -> list[str]:
    # 让 dir() 反映完整公开 API，弥补 __getattr__ 延迟导入的可见性空缺。
    return sorted(set(globals()) | set(__all__))


__all__ = ["get_block_table"]

```

# 评论区精华

本 PR 没有 review 评论或实质设计讨论。评论区仅有作者 BBuf 两次触发 `/tag-and-rerun-ci extra`，用于重跑额外 CI。PR 的变更点（如延迟导入、Git 元数据回退）均在实现中直接体现，未产生公开争议。

- 暂无高价值评论线程

# 风险与影响

- 风险：主要风险来自路径重构：
 - `python/sglang/srt/model_loader/expert_pack_runtime.py` 原先依赖 `_repo_root()` 扫描父目录，现改为包内相对路径 `_expert_pack_tools_dir()`，若安装包被裁剪或工具脚本缺失，会抛出运行时错误（已显式检查必需文件）。
 - `build.py` 的 `git_sha()` 在非 git 目录下返回 `"unknown"`，可能影响 manifest 中 git 可追溯性，但属于预期降级。
 - 所有移动文件均为 rename 操作，逻辑无变化，但外部脚本或用户代码若引用旧路径（如 `tools/expert_pack` 或 `kernels.jit.minicpm_sala`）将失效。PR 内已做仓库级扫描确认无旧引用残留，但无法覆盖下游使用者。
 - 验证中 GPU 测试未能运行，虽然路径重构不影响逻辑，但无法确认新加载路径在真实 GPU 环境下的行为。
 - 影响：对用户：通过 pip 安装的使用者不再需要仓库级 `tools` 目录，expert_pack 工具可直接从包内调用，但旧导入路径失效。对系统：JIT 内核与 ops 分离、工具脚本随包分发，包结构更符合规范。对团队：后续新增 JIT 内核或专家打包工具需遵循新目录约定，避免在仓库根目录创建功能特定目录。影响程度中等，主要是开发期路径变化，无运行时行为变化。
 - 风险标记：路径重构 , 导入引用变更 , Git 元数据回退 , 缺少 GPU 测试

# 关联脉络

- PR #35314 Directory-layout feedback for JIT kernels and expert pack (referenced in PR #36704 body): 本 PR 是对该 PR 提出的目录布局反馈的后续跟进。