深度剖析
本章通过源码级别的分析和批判性思考,帮助你从"会用框架"进阶到"理解框架"。我们不仅阅读代码,更要质疑代码 — 发现设计中的精妙之处,也揭示潜在的问题。
为什么需要源码剖析?
- 知其然更知其所以然:论文告诉你"做了什么",源码告诉你"怎么做的"
- 发现理论与实现的差距:论文中优雅的公式,在实现中可能有各种近似和妥协
- 培养批判性思维:好的代码值得学习,但没有完美的代码 — 能发现问题比能写代码更重要
章节目录
持续更新中
本章内容将持续补充,欢迎提交 Issue 建议感兴趣的源码分析主题。
学习建议
阅读本章时,建议打开对应的源码仓库,边读边跑。对于每个发现的问题,先尝试自己思考解决方案,再看作者的分析。如果你发现了我们没有提到的问题,欢迎提交 Issue 讨论。
详细内容索引
data-dedup-text.md — 深度剖析 text-dedup——MinHash / SimHash / Suffix Array 三种去重算法 (414 lines)
- 体系定位:去重在预训练 pipeline 中放在哪里 (L18)
- Part A——MinHash + LSH:抓段落级 Jaccard 近似 (L51)
- A.1 从 Jaccard 到 MinHash 的直觉 (L55)
- A.2 LSH banding——把 N² 比较降成期望 O(N) (L75)
- A.3 数据感 (L95)
- A.4 候选 → 等价类:Union-Find (L107)
- A.5 后置验证:MinHash 的 false positive 怎么办 (L113)
- Part B——SimHash:抓逐字微改的同质内容 (L121)
- B.1 与 MinHash 的本质差异 (L123)
- B.2 SimHash 算法本身 (L135)
- B.3 LSH on SimHash——Permutation-based 桶 (L145)
- B.4 SimHash 在中文上为什么效果一般 (L155)
- Part C——Suffix Array:抓跨文档的长公共子串 (L163)
- C.1 与前两者根本不同 (L165)
- C.2 算法骨架 (L173)
- C.3 数据感与代价 (L183)
- C.4 哪些训练数据用过它 (L194)
- C.5 为什么 Suffix Array 抓住的 noise 特别值钱 (L200)
- 苏格拉底时刻 (L208)
- 面试考点 (L228)
- 推荐资源 (L242)
- 手撕源码 (L253)
- 片段 1——MinHash signature 的核心计算 (L255)
- 片段 2——LSH banding:把 signature 切成 (B, R) 桶 (L281)
- 片段 3——SimHash fingerprint:±1 投票后取符号 (L307)
- 片段 4——Union-Find:把候选对压成等价类 (L333)
- 三套配置怎么读:数值背后的 trade-off (L367)
- 一图收尾:三种算法的对照表 (L400)
data-pipeline-datatrove.md — 深度剖析 datatrove——从 CommonCrawl 到 FineWeb 的工业流水线 (451 lines)
- 体系定位:为什么需要又一套数据流水线 (L18)
- 核心内容 (L42)
- 一、PipelineStep 抽象:每步都是一个独立算子 (L44)
- 二、Executor 抽象:local/slurm 同形对偶 (L80)
- 三、过滤层级:按计算成本递增的漏斗 (L128)
- 四、Gopher 质量过滤:十几条启发式规则的集合体 (L152)
- 五、近似去重的 4 阶段 MinHash:FineWeb 的真正核心 (L202)
- 六、数据感:实际跑起来什么样 (L319)
- 七、Reader、PII、Sentence Dedup:被忽视的配套件 (L332)
- 八、与 dclm 的差异(剧透) (L369)
- 九、实战工程经验:拍脑袋之前先看的 Checklist (L388)
- 十、把这套思路用到中文语料 (L410)
- 苏格拉底时刻:5 个开放问题 (L423)
- 面试考点 (L431)
- 推荐资源 (L439)
data-quality-classifier-dclm.md — 深度剖析 DCLM——用 fastText 质量分类器主导预训练数据筛选 (431 lines)
- 一、体系定位:从 heuristic filter 到 learned filter (L18)
- 1.1 一段简史:learned filter 的演化 (L39)
- 二、核心内容 (L54)
- 2.1 三个池子:DCLM-Pool / DCLM-RefinedWeb / DCLM-Baseline (L56)
- 2.2 为什么是 fastText 而不是 BERT / LLM (L81)
- 2.3 反直觉的训练配方:用 OpenHermes-2.5 + ELI5 当 positive (L113)
- 2.4 fastText 的训练流程 (L134)
- 2.5 推理与过滤的两阶段范式 (L146)
- 2.5.1 一组关键的消融数据 (L155)
- 2.6 fastText 在 pipeline 中的位置:在 BFF 去重之前还是之后? (L173)
- 2.6.1 阈值是怎么定的:threshold = 0.018112 的来历 (L196)
- 2.6.2 与 FineWeb-Edu 的对比:两条 learned filter 的路线之争 (L207)
- 2.7 数据感:分类器的吞吐与训练成本 (L229)
- 三、手撕源码 (L242)
- 3.1 fastText 训练入口 (L246)
- 3.2 fastText 推理:把概率写回 page (L272)
- 3.3 quality_filter:拿概率卡阈值 (L324)
- 3.4 把上面三件事串起来:YAML 配置 (L354)
- 四、苏格拉底时刻 (L374)
- 五、面试考点 (L403)
- 六、推荐资源 (L413)
deepseek-v4-internals.md — DeepSeek-V4 内部机制 (458 lines)
- V4 一图概览 (L16)
- Hybrid Attention:CSA + HCA 的双轨压缩 (L49)
- 1.1 为什么需要"混合" (L51)
- 1.2 CSA:先压缩再稀疏选 top-k (L65)
- 1.3 HCA:更狠的压缩 + 不做稀疏 (L95)
- 1.4 三个补丁:让 hybrid attention 真的能用 (L122)
- 1.5 效率账(§2.3.4) (L137)
- mHC:把残差映射约束在 Birkhoff 多面体 (L152)
- 2.1 标准 Hyper-Connections 与"撑不住深"的问题 (L154)
- 2.2 mHC 的核心:把
投到 doubly stochastic 矩阵流形 (L164) - 2.3 工程实现:动态 + 静态 + Sinkhorn-Knopp (L174)
- 2.4 训练稳定性的代价怎么吃下来 (L192)
- Muon Optimizer:基于 Newton-Schulz 正交化 (L202)
- 3.1 谁用 Muon、谁用 AdamW (L204)
- 3.2 Muon 的核心步骤(V4 报告 Algorithm 1) (L208)
- 3.3 Hybrid Newton-Schulz:两阶段系数(§2.4) (L221)
- MoE:与 V3 / V3.2 的精确差异 (L238)
- 训练稳定性:Anticipatory Routing + SwiGLU Clamping (L261)
- 5.1 Anticipatory Routing:异步 routing 索引 (L265)
- 5.2 SwiGLU Clamping (L280)
- 基础设施亮点(节选) (L284)
- 6.1 TileLang + MegaMoE 融合内核(§3.1, §3.2) (L286)
- 6.2 FP4 QAT(§3.4) (L298)
- 6.3 Batch Invariance + Determinism(§3.3) (L305)
- 异构 KV Cache + On-Disk Storage(§3.6) (L317)
- Post-Training:Specialist + On-Policy Distillation (L332)
- 8.1 Specialist Training(§5.1.1) (L336)
- 8.2 On-Policy Distillation(§5.1.2) (L349)
- 8.3 Tool-Call Schema:
<|DSML|>XML (L366) - 8.4 Quick Instruction:复用 KV 的辅助任务 (L380)
- 评估硬数据(节选) (L395)
- 苏格拉底时刻 (L413)
- 面试考点 (L431)
- 推荐资源 (L440)
eval-humaneval.md — 深度剖析 bigcode-evaluation-harness——pass@k 与代码评估 (488 lines)
- 体系定位:代码评估在评估生态的位置 (L16)
- Task 抽象:一份接口,所有 benchmark (L33)
- HumanEval:最朴素的实现 (L62)
- MBPP 的差异 (L93)
- 数据流:从 prompt 到 pass@k 的全链路 (L122)
- Stop Sequence:优雅地停下来 (L155)
postprocess_generation:剪掉 prompt + 接 stop (L182)
- pass@k:为什么贪心评估不够,怎么算才无偏 (L202)
- 直觉:贪心 t=0 的评估为什么不可信 (L204)
- 为什么这是无偏估计 (L219)
- 数值稳定计算:为什么不直接用组合数 (L225)
compute_code_eval:把生成 → 测试 → 分数串起来 (L259)
- 沙箱执行:为什么默认 disabled (L296)
- 模型可能写出什么 (L298)
- 为什么默认 disabled (L373)
- 关键参数:n_samples、temperature、batch_size 的关系 (L382)
- 温度 vs k 的经验配比 (L399)
n_samples的工程实现 (L411)
- 数据污染:pass@k 之外要警惕的事 (L432)
- 苏格拉底时刻 (L447)
- 面试考点 (L464)
- 推荐资源 (L472)
eval-llm-judge.md — 深度剖析 LLM-as-Judge——MT-Bench 与 AlpacaEval 工程实现 (464 lines)
- 一、体系定位:为什么需要 LLM 当裁判 (L22)
- 关键术语对齐 (L52)
- LLM-as-Judge 的核心工作流 (L64)
- 二、Part A:MT-Bench 怎么用一个 judge 跑出榜单 (L83)
- 2.1 80 道题、8 个类别、两轮对话 (L85)
- 2.2 三种 judge 模式 (L97)
- 2.3 NEED_REF_CATS:参考答案是给 GPT-4 看的 (L107)
- 2.4 Judge prompt 的设计:抗 bias 是写在 system prompt 里的 (L119)
- 2.5 多轮对话怎么塞进 judge prompt (L131)
- User: {question_1} (L137)
- Assistant A: {answer_a_1} (L138)
- User: {question_2} (L139)
- Assistant A: {answer_a_2} (L140)
- 2.6 解析 judge 输出:正则不是装饰,是工程必需品 (L146)
- 2.7 win-rate 怎么算:tie 当半个胜利 (L162)
- 2.8 决定性的细节:temperature=0 和 swap 评估 (L177)
- 2.9 被测模型生成时的 temperature:按类别分配 (L181)
- 2.10 完整成本估算 (L198)
- 三、Part B:AlpacaEval 怎么把 judge 做得"更像人" (L210)
- 3.1 与 MT-Bench 的差异 (L212)
- 3.2 默认 annotator 是 logprob 软投票,不是 hard A/B (L225)
- 3.3 logprob_parser 的实现:softmax over {m, M} (L254)
- 3.4 Position bias:随机交换 A/B 顺序 (L279)
- 3.5 Length bias:GPT-4 偏爱长回答怎么办 (L298)
- 3.6 LC-WR 的真正含义:把长度差扣到 0 重新预测 (L322)
- 3.7 GLM 训练机制:为什么用 LogisticRegressionCV (L344)
- 3.8 极端变化告警:GLM 没拟合好的兜底 (L354)
- 3.9 Human agreement:怎么验证 judge 与人对得上 (L369)
- 3.10 自定义 annotator:换一个更便宜的 judge (L385)
- 3.11 与 MT-Bench 的对比小结 (L397)
- 四、苏格拉底时刻 (L410)
- 实战清单:对齐迭代时该看哪些指标 (L424)
- 五、面试考点 (L435)
- 六、推荐资源 (L451)
eval-mmlu-likelihood.md — 深度剖析 lm-evaluation-harness——MMLU 的 likelihood 评估机制 (372 lines)
- 在大模型体系中的位置 (L20)
- 核心内容 (L44)
- Task / Instance / LM —— 三层抽象的工程契约 (L46)
- MMLU 的 YAML 怎么落到代码 (L106)
- construct_requests —— 把一道题炸成 4 条 request (L142)
- process_results —— 4 个 logprob 怎么变成「acc」和「acc_norm」 (L172)
- evaluator 的批量派发 (L206)
- 为什么 likelihood 比 generation 快这么多 (L226)
- few-shot 是怎么组装到 ctx 里的 (L257)
- registry——为什么写一个新 task 不用改 framework (L292)
- 苏格拉底时刻 (L310)
- 面试考点 (L344)
- 推荐资源 (L360)
kimi-k2-internals.md — Kimi K2 内部机制 (474 lines)
- K2 一图概览 (L16)
- MuonClip 优化器:QK-Clip 是怎么把 logits 摁住的 (L50)
- 为什么不能直接用 Muon (L52)
- 核心数学 (L63)
- MLA 的特殊处理 (L99)
- Algorithm 1(完整伪代码) (L112)
- 实验曲线:从"必爆"到"平稳" (L147)
- 稀疏 Scaling Law:为什么 384 expert + 64 head (L162)
- 固定激活量,加 expert 持续降 loss (L164)
- Attention head 砍一半的代价收益分析 (L172)
- Knowledge & Math Data Rephrasing:1× rephrase + 10 epoch 打败 raw 10 epoch (L189)
- Knowledge Rephrasing 三件套 (p.5) (L193)
- Table 1:1× rephrase 就把 SimpleQA 从 23.76 提到 27.39 (L199)
- Math Data Rephrasing:改写成"learning-note"风格 (L213)
- K2 vs DeepSeek-V3 架构对比 (L223)
- Agentic Data Synthesis Pipeline:3000+ MCP + 20000+ synthetic tools (L247)
- 三个阶段 (p.9-10) (L278)
- Self-Critique Rubric Reward:让模型评判自己 (L298)
- 核心循环 (L302)
- 三类 rubric (p.12) (L308)
- Closed-Loop Critic Refinement(关键创新) (L318)
- K1.5-style RL:均方损失 + Budget Control + PTX + 温度衰减 (L330)
- RL Loss 是均方形式,不是 PPO ratio (L332)
- Budget Control:抑制"越答越长" (L348)
- PTX Loss:防止灾难性遗忘 (L354)
- Temperature Decay:先探索后收敛 (L360)
- Checkpoint Engine:1T 参数全集群广播 < 30s (L369)
- 为什么 RL 阶段需要"快速广播" (L371)
- K2 的工程取舍:分布式 Checkpoint Engine (L386)
- 这个取舍的妙处 (L409)
- 苏格拉底时刻 (L421)
- 面试考点 (L437)
- 推荐资源 (L462)
llava-from-scratch.md — 手撕 LLaVA:从零实现多模态助手 (710 lines)
- 体系定位 (L18)
- 架构总览 (L35)
- Step 1:视觉编码器接入 (L74)
- Step 2:MLP Projector 设计 (L129)
- Step 3:视觉-文本拼接 (L199)
- Step 4:阶段 1 训练(特征对齐) (L328)
- Step 5:阶段 2 训练(指令微调) (L408)
- Step 6:推理与生成 (L512)
- 端到端 Demo:5 行跑起来 (L563)
- nano vs production:差在哪? (L623)
- 扩展路线:从 nano 到生产 (L647)
- 苏格拉底时刻 (L671)
- 推荐资源 (L685)
lora-from-scratch.md — 深度剖析 LoRA (329 lines)
- LoRA 的数学本质 (L11)
- 低秩假设 (L13)
- 参数量对比 (L33)
- 缩放因子
(L41) - 初始化策略 (L51)
- 核心实现:50 行 (L60)
- 验证正确性 (L111)
- 给模型注入 LoRA (L137)
- 在 GPT-2 上使用 (L183)
- LoRA 的保存与加载 (L203)
- 完整训练示例 (L233)
- LoRA 变体速览 (L288)
- 苏格拉底时刻 (L300)
- 常见问题 & 面试考点 (L310)
- 推荐资源 (L323)
minimind-end-to-end.md — minimind 端到端复现 (654 lines)
- 为什么要读 minimind (L11)
- 项目定位与硬件门槛 (L25)
- 模型架构亮点 (L56)
- 2.1 Config:一处控制所有 (L58)
- 2.2 RMSNorm 与 RoPE + YaRN (L91)
- 2.3 GQA Attention:Flash + 手写双路径 (L143)
- 2.4 MoE:单文件实现,aux_loss 直接累加 (L181)
- 预训练栈 (L226)
- SFT + LoRA:训练循环复用,loss 不变 (L268)
- 4.1 Full SFT 与 Pretrain 几乎一致 (L270)
- 4.2 LoRA monkey-patch:54 行实现一个 PEFT (L285)
- 4.3 LoRA 训练循环:冻结 + 收集 (L317)
- 对齐三件套:DPO / GRPO+CISPO / PPO (L347)
- 5.1 DPO:50 行核心实现 (L349)
- 5.2 GRPO + CISPO:一行 if 切换两种 loss (L387)
- 5.3 Reward 设计:规则 + 奖励模型 (L425)
- 5.4 Rollout 引擎:可插拔架构 (L455)
- 白盒蒸馏:温度平方 + α 混合 (L486)
- 服务化:FastAPI 流式 + tool calling (L538)
- 7.1 流式生成:
TextStreamer + Queue + Thread(L542) - 7.2 thinking 段与 tool_calls 的解析 (L574)
- 苏格拉底时刻 (L608)
- 学习路径建议 (L625)
- 推荐资源 (L647)
nano-agent-rl.md — 手撕 nano Agent-RL (459 lines)
- 为什么再写一个 nano (L19)
- 一图看清整体架构 (L37)
- 第一步:定义环境(ToolEnv) (L65)
- 第二步:多轮 Rollout (L145)
- 第三步:Reward 计算 + Loss Mask (L224)
- 第四步:GRPO 更新 (L259)
- 第五步:拼完整训练循环 (L331)
- 这个 nano 比生产框架少了什么 (L393)
- 怎么把它扩到一个真实任务 (L411)
- 苏格拉底时刻 (L431)
- 推荐资源 (L438)
nano-gpt.md — 深度剖析 GPT-2 (465 lines)
- 为什么要从零实现 GPT-2 (L11)
- 模型架构总览 (L20)
- 第一步:配置 (L52)
- 第二步:Causal Self-Attention (L84)
- 第三步:FFN(前馈网络) (L155)
- 第四步:Transformer Block (L183)
- 第五步:完整 GPT 模型 (L213)
- 第六步:文本生成 (L286)
- 第七步:训练循环 (L325)
- 参数量验证 (L385)
- 从 GPT-2 到现代 LLM (L431)
- 苏格拉底时刻 (L449)
- 推荐资源 (L459)
nano-rlhf.md — 深度剖析 RLHF Pipeline (796 lines)
- 为什么要从零实现 RLHF (L11)
- Bradley-Terry 偏好模型 (L30)
- 数学回顾 (L32)
- 从零实现 (L44)
- PPO 从零实现 (L104)
- 第一步:PPO 需要哪些模型 (L108)
- 第二步:GAE 优势估计 (L148)
- 第三步:KL 惩罚 + Reward 计算 (L192)
- 第四步:PPO 三大 Loss (L224)
- RLHF 完整 Pipeline (L284)
- DPO 从零实现 (L365)
- DPO Loss 推导直觉 (L369)
- 核心实现 (L383)
- GRPO 从零实现 (L450)
- GRPO 的三个关键组件 (L454)
- 从教学版到生产版 (L552)
- 工程优化清单 (L556)
- Multi-Adapter LoRA 架构 (L567)
- LoRA 参数复用:单卡 PPO 的工程实践 (L598)
- 传统 PPO 的显存瓶颈 (L600)
- 核心思路:一份基座 + 多组 LoRA 权重 (L614)
- 显存对比 (L638)
- 实现:基于 PEFT 的角色切换 (L648)
- 训练成本估算 (L725)
- 苏格拉底时刻 (L739)
- 面试考点 (L777)
- 推荐资源 (L788)
nano-vllm-v1.md — vLLM V1 与 PD 分离架构 (1019 lines)
- 全景图:V0 到 V1 再到 PD 分离 (L16)
- 第一部分:V0 的局限性 (L34)
- Prefill 阻塞 Decode (L38)
- 计算资源浪费 (L49)
- Kernel 割裂 (L53)
- 第二部分:V1 核心改进——Chunked Prefill (L69)
- 为什么 Decode 能"搭便车"? (L81)
- 第三部分:V1 核心组件详解 (L97)
- 3.1 KVPageManager:分页资源管理 (L101)
- 3.2 PagedKVStore:KV Cache 存储引擎 (L154)
- 3.3 InferenceRequest:请求状态机 (L222)
- 3.4 BatchPlanner:Chunked Prefill 调度器 (L267)
- 3.5 BatchPlan:Batch 描述符 (L333)
- 3.6 Attention Kernel:分离的 P/D 计算 (L367)
- 3.7 InferenceEngine:推理引擎主循环 (L438)
- 第四部分:Prefill-Decode 分离 (PD Disaggregation) (L493)
- 4.1 为什么要分离? (L495)
- 4.2 架构设计 (L520)
- 4.3 核心组件实现 (L557)
- 4.4 完整启动流程 (L819)
- 第五部分:Chunked Prefill 深度分析 (L857)
- 5.1 Chunked Prefill 的注意力计算 (L859)
- 5.2 Chunked Prefill 调度优化 (L884)
- 第六部分:性能对比与选型指南 (L903)
- V0 vs V1 vs PD 分离 (L905)
- 选型建议 (L917)
- 苏格拉底时刻 (L928)
- 面试考点 (L952)
- 高频问题 (L954)
- 进阶问题 (L974)
- 推荐资源 (L993)
- 论文 (L995)
- 开源项目 (L1004)
- 技术博客 (L1013)
nano-vllm.md — 手搓 vLLM 推理引擎 (956 lines)
- 为什么要手搓 vLLM? (L10)
- 整体架构 (L31)
- Step 1: Sequence — 请求的生命周期 (L72)
- Step 2: Block Manager — PagedAttention 的核心 (L144)
- Block 数据结构 (L148)
- BlockManager 初始化 (L168)
- Hash 计算——Prefix Caching 的基础 (L180)
- allocate()——分配 KV Cache 块 (L196)
- deallocate()——引用计数释放 (L239)
- can_append() / may_append()——Decode 阶段的块管理 (L254)
- Step 3: Scheduler — Continuous Batching 调度 (L288)
- schedule() 方法——调度策略 (L303)
- 抢占机制 (L354)
- postprocess()——检查终止条件 (L365)
- Step 4: Attention — Triton Kernel + Flash Attention (L379)
- Triton Kernel:写入 KV Cache (L383)
- Attention Forward:三条路径 (L414)
- Step 5: Model Runner — 模型执行与 CUDA Graph (L471)
- 初始化流程 (L475)
- warmup_model()——探测峰值显存 (L507)
- allocate_kv_cache()——计算可用块数 (L526)
- prepare_prefill()——构建 Prefill 输入 (L574)
- prepare_decode()——Decode 输入更简单 (L624)
- CUDA Graph——消除 Decode 阶段的 Launch 开销 (L647)
- 多 GPU 通信——SharedMemory (L709)
- Step 6: LLM Engine — 把一切串起来 (L729)
- 初始化——启动多进程 (L733)
- 主循环——generate() (L754)
- step()——单步执行 (L782)
- Step 7: 模型层实现 (L800)
- Tensor Parallel Linear (L802)
- RoPE 位置编码 (L825)
- RMS LayerNorm (L837)
- Sampler——Gumbel-Max 采样 (L861)
- Qwen3 模型组装 (L880)
- nano-vllm vs vLLM:简化了什么? (L896)
- 苏格拉底时刻 (L915)
- 面试考点 (L927)
- 推荐资源 (L949)
r1-reproduction.md — R1 风格推理模型训练复现 (617 lines)
- R1 是什么 (L11)
- DeepSeek-R1 的核心创新 (L13)
- "Aha Moment"——推理能力的涌现 (L27)
- 我们要复现什么 (L41)
- 技术方案选择:verl vs slime (L53)
- X-R1: 4×3090 低成本复现 R1-Zero (L83)
- 整体配方一览 (L91)
- 关键 yaml 超参拆解 (L103)
- 启动脚本 (L140)
- 单卡 LoRA 变体(1×3090,~8h) (L154)
- 与 verl / slime 的定位差异 (L177)
- 数据准备 (L191)
- GSM8K 数据集适配 (L193)
- verl 数据格式规范 (L246)
- 自定义数据集适配 (L269)
- Reward 设计 (L301)
- 规则奖励 vs 模型奖励 (L303)
- verl 中的奖励实现 (L315)
- slime 中的 DAPO 奖励 (L332)
- 训练配置 (L343)
- 环境搭建 (L345)
- DeepSpeed 配置 (L359)
- 模型选择策略 (L363)
- verl 训练实战 (L374)
- 架构概览 (L376)
- main_ppo.py 核心流程 (L396)
- 训练脚本要点 (L418)
- Qwen3-8B 的 Scaling 配置差异 (L430)
- slime 异步训练 (L438)
- 全异步架构 (L440)
- slime 训练脚本要点 (L469)
- Retool 模式:训推共享 GPU (L477)
- 评估与分析 (L486)
- GSM8K 准确率评估 (L488)
- WandB 监控 (L508)
- 从 0.6B 到 8B:Scaling 训练的注意事项 (L528)
- 显存管理 (L530)
- 超参调整建议 (L545)
- 常见问题排查 (L556)
- 苏格拉底时刻 (L577)
- 面试考点 (L589)
- 推荐资源 (L607)
safety-gcg.md — 深度剖析 GCG 攻击——白盒对抗后缀如何突破对齐 (380 lines)
- 来源声明 (L16)
- 体系定位:GCG 在 LLM 攻击谱中的位置 (L22)
- 与其他攻击家族的对比 (L33)
- 核心内容:GCG 是怎么把乱码变成「钥匙」的 (L46)
- 攻击目标的工程定义 (L48)
- token-level 梯度:one-hot 嵌入是怎么来的 (L88)
- sample_control:用随机性突破贪心的局部最优 (L134)
- 候选过滤:保住 token 边界一致性 (L174)
- universal 与 transferability:把多个 prompt 拼成一个 batch (L189)
- 控制 slice 与位置切片:工程上最容易踩坑的地方 (L217)
- 工程成本与超参 (L250)
- 主循环:把所有部件拼起来 (L270)
- 为什么后缀长得这样? (L293)
- 苏格拉底时刻 (L306)
- 面试考点 (L322)
- 防御视角:从攻击机制反推缓解策略 (L338)
- 推荐资源 (L355)
- 一手材料 (L357)
- 防御方向的代表性工作 (L362)
- 相关攻击家族(对比阅读) (L368)
- 项目内交叉阅读 (L373)
safety-redteam.md — 深度剖析 HarmBench——LLM 红队的标准化评测框架 (400 lines)
- 来源声明 (L14)
- 一、体系定位:单点攻击 vs benchmark 化红队 (L22)
- 1.1 从「能不能越狱」到「越多少、稳不稳」 (L24)
- 1.2 HarmBench 解决的三个问题 (L47)
- 二、核心内容 (L57)
- 2.1 Behavior 分类法:把红队任务结构化 (L59)
- 2.2 攻击 baseline 矩阵:18+ 种攻击对齐到同一接口 (L91)
- 2.3 自动判分:把 GPT-4-as-judge 蒸馏成 7B-13B 分类器 (L176)
- 2.4 ASR 的口径:三个常被混淆的层级 (L279)
- 2.5 Reproducibility:每个攻击都有冻结的 config (L291)
- 2.6 数据感与硬件成本 (L304)
- 三、苏格拉底时刻 (L317)
- 四、面试考点 (L348)
- 五、推荐资源 (L367)
- 总结 (L389)
safety-rlhf.md — 深度剖析 Safe RLHF——用 PPO-Lagrangian 把有用与安全解耦 (403 lines)
- 体系定位:从"加权"到"约束"的范式跃迁 (L18)
- 核心内容 (L43)
- 双 preference 标注:BeaverTails 数据集 (L45)
- 双值函数:Reward 与 Cost 模型的非对称性 (L61)
- PPO-Lagrangian:约束优化的拉格朗日松弛 (L74)
- Actor Loss 的双 advantage 组合 (L95)
- 训练动力学与超参经验 (L105)
- KL 约束与 cost 的双向耦合 (L121)
- 与 LLaMA 2 双 RM 加权法的工程对比 (L131)
- 端到端 Pipeline 的 5 个阶段 (L143)
- 手撕源码 (L159)
- 片段 1:cost loss 中的 sign 项(让 cost 零点有物理含义) (L161)
- 片段 2:lambda 的对数空间更新(dual ascent) (L183)
- 片段 3:actor loss 中的双 advantage 组合 (L212)
- 片段 4:rollout 阶段同时取 reward 和 cost (L239)
- 片段 5:Safety Preference 的双视角 collator (L269)
- 训练日志该看哪些信号 (L301)
- 与 DPO 的兼容性:Safe DPO 是否可行? (L317)
- 拉格朗日乘子 lambda 不收敛会怎样? (L323)
- 双 preference 标注成本翻倍,真的值得吗? (L331)
- cost model 失效了会怎样?怎么发现? (L335)
- 为什么不直接 multi-objective RL(Pareto 前沿)? (L344)
- 把 cost 当作"约束"而不是"负 reward",本质上买到了什么? (L348)
- 面试考点 (L352)
- 为什么 cost loss 要用 sigmoid 加 sign 项,而不是像 reward 那样只用 BT margin loss? (L354)
- lambda 在数值上不稳定怎么办?工程上有哪几招? (L358)
- PPO-Lagrangian 与 LLaMA 2 双 RM 加权法相比,多/少了什么? (L368)
- 双 advantage 组合公式
(A_R - lambda·A_C) / (1 + lambda)的分母是干嘛的? (L374)
- 双 advantage 组合公式
- 如果只有一份 helpfulness 标注(没有 safer 标注),还能用 PPO-Lagrangian 吗? (L378)
- 推荐资源 (L386)
