Sampling、logits 处理与 speculative decoding#

这章解决什么问题#

上一章已经把 ForwardBatch -> ModelRunner -> sample 的最小闭环讲清楚了,但还没有充分展开“前向结束之后到底发生了什么”。这正是很多读者最容易模糊的地方:logits 是怎么被处理的?sampling 参数究竟改变了什么?speculative decoding 到底是在替换主循环,还是在主循环里插入了额外模式?

这一章要解决的,就是 execution model 里“后半段”的细节。没有这一层,你会知道模型在 forward,但不知道 next token 是怎样被真正选出来的,也不知道 draft / verify 为什么会让同一条执行链显得更复杂。

SamplingParams 为什么是执行模型的一部分#

python/sglang/srt/sampling/sampling_params.py 明确把 temperaturetop_ptop_kmin_p、penalty 参数、json_schemaregexebnfsampling_seed 等都放在同一个对象里。这个设计非常重要,因为它说明:从 runtime 视角看,采样不是一个“可有可无的后处理插件”,而是 next-token 选择的一等输入。

这也是为什么 execution model 要专门拆出一章讲 sampling。只要把 sampling 看成“最后随便调几个参数”,你就很难理解为什么后面的 structured generation 会直接复用这些字段,也很难理解为什么不同调用表面最后都要回到这一层。

logits 从哪里来,又怎样进入 sample#

bench_one_batch.py 的缩小版路径里,你能直接看到 model_runner.forward(forward_batch).logits_output 之后紧跟着 model_runner.sample(...)。这条链路最值得抓住的一点是:前向和采样之间有一个清晰边界。模型负责给出 logits,采样层负责在这些 logits 上施加策略和约束,再选出 next token。

这意味着调试“输出内容不对”时,不能把所有问题都丢给模型前向。一部分问题属于 logits 的上游实现,一部分则属于 logits 之后的采样和约束路径。本章正是为了把这条边界讲清楚。

speculative decoding 到底改变了什么#

ForwardMode 和官方 docs/advanced_features/speculative_decoding.md 看,speculative decoding 并不是“另一套独立执行模型”,而是在同一执行链里加入 TARGET_VERIFYDRAFT_EXTEND 等模式。也就是说,它不替换 ForwardBatch -> forward -> sample 这个闭环,而是在闭环内部插入“先草拟、再验证”的额外路径。

这对理解 tradeoff 非常重要。speculative decoding 的收益,是减少目标模型逐 token 推进的成本;代价是执行状态更复杂,draft 与 target 两条路径之间的协调难度更高,对 forward mode、调度路径和 cache 状态的要求也更高。因此它适合被看成 execution model 的复杂化版本,而不是单纯的“性能选项”。

一个更像运行时解释的对照#

普通 decode:
ForwardBatch -> forward -> logits -> sample -> next token

speculative decode:
ForwardBatch(target/draft mode) -> draft extend / target verify -> logits -> accept / reject -> next token

这个对照表的价值,不在于代码更接近真实实现,而在于它让你看到:speculative decoding 并没有跳出执行模型,而是在执行模型里增加了验证与接受判断。只要把这一点看清楚,很多“为什么会更快、为什么也更复杂”的问题就都有了着力点。

调试时最常见的两类问题#

第一类是“输出质量或选择行为不符合预期”。这时优先看 SamplingParams、logits 处理和 sample(...) 之间的关系,而不是先怀疑 HTTP 或 scheduler。
第二类是“打开 speculative decoding 后行为变复杂”。这时优先看 ForwardMode 切换、verify / draft 路径和相关文档,而不是把所有问题都归因于底层 kernel。

优秀技术书的价值,常常就在这里:它不是告诉你“有这个特性”,而是告诉你“出问题时先从哪一层看”。这一章要补的,正是这种执行链上的判断框架。

本章对应哪些代码路径#

这一章最重要的锚点包括 python/sglang/srt/sampling/sampling_params.pypython/sglang/srt/model_executor/forward_batch_info.pypython/sglang/bench_one_batch.py 以及 docs/advanced_features/speculative_decoding.md。如果要进一步下钻 speculative 具体实现,还可以继续追 python/sglang/srt/speculative/ 下的相关 worker 与 info 文件。

小结#

execution model 的后半段真正讲的是:logits 之后,系统如何在不同采样策略和不同执行模式之间做出 next-token 选择。把这层讲清楚之后,结构化生成和接口参数不再像外加选项,而会重新回到执行主线里。