资料摘要:personal chatgpt 22 — llama2 源码分析 generate 的完整过程
本讲由真实视频转录与作者 notebook/代码交叉整理。原始层:🔒 带时间戳视频转录;课程总览:personal chatgpt — LLMs 实践系列。
本讲把第 17–21 讲的 RMSNorm、SwiGLU、RoPE、KV Cache、GQA 等组件串进 Llama 2 的完整 generate 流程。核心是两个不同阶段:首次把完整 prompt 送入模型并建立 KV Cache(prefill);随后每一步只送入一个新 token,复用历史 K/V,得到下一 token 的 logits 并采样(decode)。
1. generate 外层循环
Section titled “1. generate 外层循环”课程示例 prompt 为 I believe the meaning of life is,tokenize 后长度约为 8。生成循环维护:
prev_pos:上一次已经送入模型的位置;cur_pos:本轮目标位置;tokens[:, prev_pos:cur_pos]:本轮实际送入forward的 token 区间;- EOS 标志:所有样本结束后可提前退出。
第一次是 0:8,后续依次是 8:9、9:10……因此 decode 阶段每轮输入长度为 1。
2. Prefill:一次处理完整 prompt
Section titled “2. Prefill:一次处理完整 prompt”完整 prompt 同时送入时,序列内仍必须保持因果性,因此创建上三角 causal mask:
第 个位置只能看到自身和之前的位置。RoPE 把位置信息注入 Q/K,各层把 prompt 的 K/V 写入缓存。
3. Decode:每次只输入一个 token
Section titled “3. Decode:每次只输入一个 token”后续步 seqlen = 1,不再需要当前小块内部的三角 mask;新 token 的 Q 与缓存中的全部历史 K/V 做注意力。历史信息并不在本轮输入 token 中,而保存在每层的 KV Cache 中。
课程用源码逐步展示:
h = self.model.forward(tokens[:, prev_pos:cur_pos], prev_pos)next_token = sample_top_p(probs, top_p)tokens[:, cur_pos] = next_tokenprev_pos = cur_pos4. 从 logits 到下一 token
Section titled “4. 从 logits 到下一 token”只使用最后一个位置的 logits:
logits = self.output(h).float()probs = torch.softmax(logits[:, -1] / temperature, dim=-1)next_token = sample_top_p(probs, top_p)temperature < 1:分布更尖锐,接近贪心。temperature > 1:分布更平,低概率 token 更容易被采到。top_p:按概率排序后保留累计质量不超过阈值的最小候选集合,再归一化采样。
5. 模型并行下的源码观察
Section titled “5. 模型并行下的源码观察”课程在两张 4090 上运行 Llama 2 13B,模型并行度为 2。40 个 attention heads 被划为每个进程 20 个 local heads;调试器会在两个子进程重复命中断点。这是源码跟踪的环境现象,不是网络层被执行了两次。
公式 / 代码要点
Section titled “公式 / 代码要点”Top-p notebook 实现:
probs_sort, probs_idx = torch.sort(probs, dim=-1, descending=True)probs_sum = torch.cumsum(probs_sort, dim=-1)mask = probs_sum - probs_sort > pprobs_sort[mask] = 0.0probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))next_token = torch.gather(probs_idx, -1, torch.multinomial(probs_sort, 1))温度缩放:
00:27:回顾第 17–21 讲子模块,并说明本讲用generate串联。01:42:进入model.generate接口与生成参数。02:12:说明 top-p 截断采样。03:18:介绍 13B 两卡模型并行环境。04:23:外层循环先送完整 prompt,之后 token-by-token。10:58:首次输入需要 causal mask。15:00:40 个 heads 在两进程中各为 20 个 local heads,并写入 KV Cache。19:11:只取最后一个 token 的 logits 并采样。24:00:新 token 与缓存的全部历史 K/V 做注意力。25:55:解释 temperature;随后总结 top-p 与 KV Cache。
- 课程实跑的是 Llama 2 13B、batch size 1、两卡模型并行;其它规模、batch size 与并行方式需另测。
- 原始权重和 tokenizer 路径依赖本地部署,notebook 不是可直接无配置运行的一键脚本。
- 调试两个 worker 时会重复命中断点,分析 shape 时必须区分 global heads 与 local heads。
- “prefill / decode”是对转录所展示两阶段的标准术语校正;课程口头主要称“第一次完整输入”和“后续 token by token”。
与前后讲关系
Section titled “与前后讲关系”- 前接第 17–21 讲:把 RMSNorm、SwiGLU、RoPE、KV Cache、GQA 合并为完整推理路径。
- 后接第 23 讲:从模型推理切换到 RLHF 第二阶段的奖励模型训练。
- 为什么首次 prompt 输入需要上三角 mask,而单 token decode 通常不需要?
prev_pos和cur_pos如何保证后续每轮只送入一个新 token?- 历史 token 没有重复传入时,模型从哪里取得其 K/V?
- 为什么只取
logits[:, -1]来采样下一 token? - temperature 与 top-p 分别改变采样的哪一部分?
- 视频:llama2 源码分析 generate 的完整过程
- 转录:🔒 personal chatgpt 22 视频转录
- 课件 / 代码:🔒 llama2_src_generate.ipynb
- 滴答清单抓取时学习状态:已完成。
- 视频正文采用自动语音识别;关键术语已用标题、notebook 与源码校正,无法确认的口语细节不扩写。
- notebook 未执行的 CUDA、权重下载、训练或外部 API 单元,不表述为已复现实验。