跳转到内容

输入关键词开始搜索

    资料摘要:personal chatgpt 22 — llama2 源码分析 generate 的完整过程

    视频摘要更新 2026-08-02置信度 high待阅读原始来源 ↗#深度#大模型#课程#personal-chatgpt

    本讲由真实视频转录与作者 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)。

    课程示例 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:99:10……因此 decode 阶段每轮输入长度为 1。

    完整 prompt 同时送入时,序列内仍必须保持因果性,因此创建上三角 causal mask:

    Mij={0,ji,j>iM_{ij}=\begin{cases} 0,&j\le i\ -\infty,&j>i \end{cases}

    ii 个位置只能看到自身和之前的位置。RoPE 把位置信息注入 Q/K,各层把 prompt 的 K/V 写入缓存。

    后续步 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_token
    prev_pos = cur_pos

    只使用最后一个位置的 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:按概率排序后保留累计质量不超过阈值的最小候选集合,再归一化采样。

    课程在两张 4090 上运行 Llama 2 13B,模型并行度为 2。40 个 attention heads 被划为每个进程 20 个 local heads;调试器会在两个子进程重复命中断点。这是源码跟踪的环境现象,不是网络层被执行了两次。

    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 > p
    probs_sort[mask] = 0.0
    probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))
    next_token = torch.gather(probs_idx, -1, torch.multinomial(probs_sort, 1))

    温度缩放:

    pi(T)=exp(zi/T)jexp(zj/T)p_i(T)=\frac{\exp(z_i/T)}{\sum_j\exp(z_j/T)}

    • 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”。
    • 前接第 17–21 讲:把 RMSNorm、SwiGLU、RoPE、KV Cache、GQA 合并为完整推理路径。
    • 后接第 23 讲:从模型推理切换到 RLHF 第二阶段的奖励模型训练。
    1. 为什么首次 prompt 输入需要上三角 mask,而单 token decode 通常不需要?
    2. prev_poscur_pos 如何保证后续每轮只送入一个新 token?
    3. 历史 token 没有重复传入时,模型从哪里取得其 K/V?
    4. 为什么只取 logits[:, -1] 来采样下一 token?
    5. temperature 与 top-p 分别改变采样的哪一部分?
    • 滴答清单抓取时学习状态:已完成
    • 视频正文采用自动语音识别;关键术语已用标题、notebook 与源码校正,无法确认的口语细节不扩写。
    • notebook 未执行的 CUDA、权重下载、训练或外部 API 单元,不表述为已复现实验。