模型定义、执行壳与 backend 实现边界#
运行时架构前面已经讲了 ModelConfig、TpModelWorker、ModelRunner 和并行 rank 身份,但如果不把 models/、layers/、ModelRunner 和 TpModelWorker 之间的边界重新压成一章,读者还是很容易停留在一种模糊认识上:模型很多、backend 很多、runner 也很多,却说不清这些东西在架构上到底谁包谁、谁依赖谁、谁才是 scheduler 真正驱动的执行单元。
这章真正要补齐的,就是这条“从模型定义到执行壳”的层次关系。只要这一层稳住,前面那些关于 ModelRunner、TpModelWorker、layers/ 的章节就会自然接起来,而不会像几个互相回扣的分散点。
先把这几层放回同一张层次图里#
很多人直觉上会把 models/ 和 layers/ 看成两个平行目录。更稳的理解方式是:它们都要经过执行壳这一层,才真正落到 runtime 里。下面这张图的作用,就是把这个层次关系明确画出来:
flowchart LR
Models["models/"] --> Runner["ModelRunner"]
Layers["layers/"] --> Runner
Runner --> Worker["TpModelWorker / draft worker"]
Worker --> Scheduler["Scheduler"]这张图最重要的一点是:scheduler 真正驱动的并不是裸模型定义,而是已经被执行壳和 worker 壳包起来的执行单元。
ModelConfig.from_server_args(...) 先决定的是模型人格,而不是模型文件#
从 TpModelWorker._init_model_config() 这条链看,系统并不是直接从 models/ 里挑一个文件就算完,而是先经过:
ModelConfig.from_server_args(...)
这层人格归一化会结合:
model_path- draft / non-draft 模型
- revision
- server args 里的多种能力开关
去决定后续模型到底以什么人格进入执行壳。也就是说,模型定义在这里先被抽成一组统一能力与边界,而不是直接以目录树形态进入运行时。对系统书来说,这一点特别重要,因为它能帮助读者先理解“模型人格怎样被收敛”,再去看后面为什么有 processor、多模态、draft path 等更具体分支。
TpModelWorker 更像外层执行壳,而不是“带 rank 的包装器”#
TpModelWorker 之所以值得单独点出来,是因为它不只是在传 rank 身份。更准确地说,它承担的是:
- 按 draft / non-draft 选择 model path
- 初始化
ModelRunner - 同步 random seed
- 提供
get_worker_info()、get_memory_pool()等稳定接口
这意味着 scheduler 依赖的不是模型定义本身,也不是 ModelRunner 这个内部执行中枢单独存在,而是一个已经被 worker 化、带资源边界、带 rank 身份、带固定对外接口的执行单元。把这一层看清楚,读者就不容易再把 TpModelWorker 误看成“只是分布式包装层”。
ModelRunner 才是 models/ 和 layers/ 真正汇合的地方#
如果说 models/ 更接近“模型语义”,layers/ 更接近“执行砖块”,那么 ModelRunner 就是两者真正汇合的地方。它会把这些东西一起收进同一个执行中枢里:
- 模型定义
- graph runner
- attention backend
- sampler / logits processor
- KV cache pool
- quantization 相关能力
也正因为这样,前面的 execution 章节才会不断回到 ModelRunner。这不是偶然,而是因为它确实站在模型定义层和执行砖块层的交点上。
models/ 大,不代表它本身就是执行主线#
models/ 下文件很多,这本身只说明一个事实:SGLang 不是围绕单模型写的。对技术书来说,更重要的问题不是“每个模型文件都讲一遍”,而是告诉读者:
- 这里是模型级定义层
- 真正执行时它们会统一进入
ModelRunner - 如果要读某个模型,最好先知道自己要看的是“模型特殊语义”还是“公共执行壳”
也就是说,大目录本身不值得被逐个展开,但它在架构中的位置必须讲清楚。否则读者一钻进 models/,就很容易把模型差异层误读成整个 execution 主线。
layers/ 也不是“底层细节堆”,而是执行砖块层#
从目录看,layers/ 至少已经包含:
attention/logits_processor.pysampler.pymoe/quantization/rotary_embedding/
这说明它并不是某个局部优化目录,而是 runtime 执行砖块的集中地。也正因为如此,进入 layers/ 之前最好先有一层运行时外壳心智模型,否则很容易把所有 backend 文件都读成平行主线。
技术书在这里最该做的,并不是把每个 backend 都展开,而是先让读者知道:layers/ 是 execution brick layer,它要经过 ModelRunner 才会变成统一执行壳的一部分。
speculative 让“执行壳”本身也会长出额外层次#
一旦 speculative 打开,TpModelWorker 可能不再只管理一个主 runner,还会引入:
- draft worker
- draft model path
- multi-layer eagle 的多 runner 列表
这说明执行壳并不是固定单层结构,而会因为 speculative 策略而长出额外分支。前面的 execution 章节讲的是“怎么跑”;这一章更偏“这些不同人格到底由谁包起来”。把这层边界点破之后,读者就不再会把 speculative 只看成 sampler 附近的小优化,而会看到它已经改写了更外层的执行壳组织方式。
最容易出现的三种误判#
第一,误把 models/ 看成执行主线。
更稳的理解是,它更像模型定义层,而不是 scheduler 直接驱动的那层。
第二,误把 layers/ 看成单纯优化细节。
它其实是 ModelRunner 组装执行壳时最核心的砖块层。
第三,误以为 TpModelWorker 只是为了分布式传 rank。
它还承担了执行壳的外层封装职责。
真正顺着“模型 -> 执行”这条链读源码时,更稳的顺序#
建议按下面顺序:
- 先看
ModelConfig.from_server_args(...) - 再看
TpModelWorker._init_model_config()/_init_model_runner() - 再看
ModelRunner - 最后按具体问题深入
models/或layers/
这样读的好处很明显:你先有壳,再读具体实现,而不是一上来就钻进某个后端文件。
小结#
这一章真正补齐的,是运行时架构里最后一层非常值钱的执行边界:models/ 是模型定义层,layers/ 是执行砖块层,ModelRunner 是汇合点,TpModelWorker / draft worker 则把它们包成可被 scheduler 驱动的执行壳。
到这里,运行时架构对“模型定义怎样真正变成执行单元”的解释就更完整了。
叶王 © 2013-2026 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。