Follow a Request
沿着一条请求读懂引擎
从 LLM.generate 进入,追踪调度、执行、采样与状态更新。
引擎的一轮是一次协作边界,不等于单条请求恰好推进一个 token。
01入口负责接入,请求由引擎推进
LLM.generate 接收输入,将各条请求加入引擎,再由 LLM._run_engine 持续推进。入口关心请求如何创建、结果如何汇集;LLMEngine 负责把当前请求状态转换为下一轮工作。先区分这两层,可以避免把用户的一次 generate 调用误认为一次模型前向。
s01_request_flow.py
# Framework pseudocode, not an executable implementation.
for request in inputs:
llm_engine.add_request(request)
while llm_engine.has_unfinished_requests():
ready_outputs = llm_engine.step()
collect(ready_outputs)
collect(llm_engine.flush_inflight_reqs())
# Inside a scheduled round:
# Scheduler -> Worker -> ModelRunner -> sampling
# -> ready state updates and request outputs
# A round may cover several requests and token positions.02一次 step 穿过哪些边界
LLMEngine.step 先调用 C++ Scheduler 选择本轮序列和 token 预算,再交给 Worker 与 ModelRunner 组织执行。采样决定候选的选择或接受结果,后处理再更新请求状态。一次 step 可以涉及多条请求、prefill 分块或多个 draft 位置,不能画成每轮固定一个 token 的循环。
03输出就绪与引擎轮次不完全重合
开启 ZOS 时,当前前向、上一轮后处理与当前采样有明确顺序,部分状态更新延迟到下一轮。_run_engine 因此还要处理在途输出,并在结束时 flush。教学伪代码只标出这些职责;具体参数、分支和生命周期应在固定版本的上游源码中核对。
TRY IT YOURSELF
动手想一想
沿源码写出入口、调度、执行、采样和状态更新各由哪个模块负责。再说明为什么一轮 step 返回的输出不一定全部属于本轮采样。
把这个机制,加入你的工具箱。