> ## Documentation Index
> Fetch the complete documentation index at: https://opc-43d279b8.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# LLM 训练流程

> 预训练、SFT、RLHF/DPO 到 LoRA 微调，覆盖 LLM 训练流程与成本的高频考点。

> LLM 训练我按阶段记：预训练给语言和知识，SFT 给格式，RLHF/DPO 给偏好。数据量级和成本差在哪，比背三个缩写更有用。

***

## Q1: LLM 训练的完整流程是什么？

LLM 的训练不是一步到位的，而是一个多阶段的渐进式能力塑造过程。Andrej Karpathy 在其 "State of GPT" 演讲中将这个流程清晰地划分为四个阶段 <sup>\[1]</sup>：

```text theme={null}
┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│  预训练       │ → │  SFT         │ → │  RM + RLHF   │ → │  部署        │
│  Pre-training │   │  监督微调     │   │  奖励模型     │   │  Deployment  │
│  海量文本     │   │  高质量对答   │   │  人类偏好     │   │  上线服务     │
└──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘
     成本：$$$$$        成本：$$$           成本：$$$           成本：$
```

**1. 预训练 (Pre-training): 学习语言和知识**

在海量互联网文本上训练基座模型，让模型学会语言的统计规律、世界知识和基础推理能力。这一步消耗了 95% 以上的训练算力，产出的是一个"会补全文本但不会回答问题"的基座模型。

**2. 监督微调 (SFT): 学会按指令回答**

用高质量的"指令-回答"对微调基座模型，让它学会按人类期望的格式和风格回答问题。这一步把"文本补全机器"变成"对话助手"。

**3. 奖励模型 + RLHF: 对齐人类偏好**

训练奖励模型学习人类对回答质量的排序偏好，再用强化学习（PPO）优化模型输出，使其更符合人类期望——更有帮助、更安全、更诚实。

**4. DPO 等新方法: 简化对齐流程**

2023-2025 年，DPO（Direct Preference Optimization）等方法跳过了奖励模型训练，直接从偏好数据中优化模型，大幅简化了对齐流程 <sup>\[2]</sup>。

**LLM 训练解决的核心问题：**

```text theme={null}
问题：基座模型只会"续写文本"，不会"回答问题"

基座模型：给它一个问题，它可能续写成更多问题、写一首诗、或编造答案
它不懂什么是"好的回答"，什么是"有害的回答"

解决：通过多阶段训练逐步塑造模型行为

SFT：教会它"回答问题"的格式
RLHF/DPO：教会它"什么是好的回答"
```

> [!NOTE]
>
> LLM 训练是一个从"学习语言"到"学习做人"的多阶段过程——预训练学知识，SFT 学格式，RLHF/DPO 学偏好。

> [card] 🚫 没有 SFT 和 RLHF
>
> 基座模型像一个读过所有书但从没跟人交流过的学者——它知识渊博，但不会用对话的方式表达，可能答非所问甚至编造信息。你问它"今天天气怎么样"，它可能续写成一首关于天气的诗。

> [card] ✅ 引入 SFT 和 RLHF
>
> 经过 SFT 和 RLHF 训练的模型像一个既博学又善于沟通的顾问——它用清晰的格式回答问题，知道什么该说什么不该说，能根据你的需求给出有用的建议。

> [!TIP]
>
> 回答时用 Andrej Karpathy 的"四阶段"框架作为主线，先说每个阶段"解决什么问题"，再说"怎么解决"。想听的是你对训练流程设计动机的理解，而不是背诵步骤名称。

***

## Q2: 预训练（Pre-training）—— 基座模型是怎么炼成的？

预训练是 LLM 训练中成本最高、耗时最长的阶段。它的核心任务是让模型在海量文本数据上学习"预测下一个 token"，从而掌握语言规律、世界知识和基础推理能力 <sup>\[1]</sup>。

```text theme={null}
┌─────────────────────────────────────────────────────────────┐
│                    预训练数据集                                │
│  互联网网页 │ 书籍 │ 代码 │ 维基百科 │ 论文 │ 新闻 ...      │
│  典型规模：数万亿 tokens（GPT-3: 300B tokens）               │
└──────────────────────────┬──────────────────────────────────┘
                           │ 自回归训练（Next-token Prediction）
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                    基座模型 (Base Model)                      │
│  能力：语言理解、知识存储、基础推理                             │
│  缺陷：不会按指令回答、可能编造、格式不可控                      │
└─────────────────────────────────────────────────────────────┘
```

```python theme={null}
# ============================================================
# 预训练核心目标：Next-token Prediction（带详细注释）
# 比喻：预训练就像一个人花十年读完整个图书馆——
#       积累了海量知识，语言表达流畅，什么话题都能聊几句
#       但从未学过"怎么当客服"——问它问题可能答非所问
#
# ASCII 流程图：
# ┌─────────────────────────────────────────────┐
# │  海量文本："The capital of France is ___"    │
# │  标签：    "Paris"                           │
# │  模型预测："London" (概率 30%)               │
# │           "Paris"  (概率 60%) ← 正确答案     │
# │           "Berlin" (概率 10%)                │
# │                                              │
# │  损失 = -log(0.6) = 0.51                     │
# │  → 反向传播 → 调整参数 → 让 "Paris" 概率更高  │
# └─────────────────────────────────────────────┘
# ============================================================

# 模拟预训练的简化流程（实际会用 PyTorch/TensorFlow）
import numpy as np

def pretrain_step(model, tokenizer, text, target_next_token):
    """
    预训练的单步训练过程

    参数：
        model: Transformer 模型
        tokenizer: 分词器
        text: 输入文本（如 "The capital of France is"）
        target_next_token: 正确的下一个 Token（如 "Paris"）

    返回：
        loss: 损失值（越小表示模型预测越准）

    关键细节：
        1. 损失函数是交叉熵——衡量模型预测分布与真实分布的差距
        2. 反向传播计算每个参数的梯度
        3. 优化器根据梯度更新参数，使预测更准
    """
    # 第 1 步：分词——把文本切成 Token 序列
    # "The capital of France is" → [464, 3139, 286, 4881, 318]
    input_ids = tokenizer.encode(text)

    # 第 2 步：前向传播——模型预测下一个 Token 的概率分布
    # 输出是词表中每个 Token 的分数（logits），词表通常有 50000+ 个 Token
    logits = model.forward(input_ids)  # shape: [seq_len, vocab_size]
    next_token_logits = logits[-1]     # 只看最后一个位置的预测

    # 第 3 步：Softmax——把分数转成概率分布
    probs = softmax(next_token_logits)  # 每个 Token 的概率，加起来 = 1

    # 第 4 步：计算交叉熵损失
    # 损失 = -log(P(正确答案))
    # 如果模型给 "Paris" 的概率是 60%，损失 = -log(0.6) ≈ 0.51
    # 如果模型给 "Paris" 的概率是 99%，损失 = -log(0.99) ≈ 0.01（很好！）
    target_id = tokenizer.encode(target_next_token)[0]
    loss = -np.log(probs[target_id] + 1e-10)  # 加 1e-10 防止 log(0)

    # 第 5 步：反向传播 + 参数更新
    # 计算每个参数对损失的梯度，然后调整参数使损失变小
    loss.backward()       # 计算梯度
    optimizer.step()      # 更新参数
    optimizer.zero_grad() # 清零梯度（为下一步准备）

    return loss

# --- 训练后的效果 ---
# 模型学会了语言规律和世界知识：
#   "法国的首都" → "巴黎"（知识）
#   "function add(a, b) {" → "return a + b; }"（代码模式）
#   "React 是由" → "Meta（原 Facebook）开发的"（事实）
#
# 但模型不会按指令回答：
#   "请帮我写一个函数" → 可能续写更多问题，而不是写函数
#   这就是为什么需要 SFT 阶段
```

```javascript theme={null}
// 预训练的核心目标：Next-token Prediction
// 给定前文，预测下一个最可能的 token

// 训练过程（伪代码）
for (epoch of epochs) {
  for (batch of trainingData) {
    // 输入：一段文本的前 N 个 token
    const input = "The capital of France is";
    // 标签：第 N+1 个 token（正确答案）
    const target = " Paris";

    // 模型预测下一个 token 的概率分布
    const logits = model.forward(input);

    // 计算交叉熵损失
    const loss = crossEntropy(logits, target);

    // 反向传播更新参数
    loss.backward();
    optimizer.step();
  }
}
// 训练完成后，模型学会了：
// - "法国的首都" → "巴黎"
// - "function add(a, b) {" → "return a + b; }"
// - 但"请帮我写一个函数" → 可能续写更多问题而不是写函数
```

> [!WARNING]
>
> 预训练的成本极其惊人，以 GPT-4 级别模型为参考：
>
> * **数据量**：数万亿 tokens（约几十 TB 文本数据）
> * **GPU 需求**：数千张 A100/H100 GPU，训练数月
> * **成本**：GPT-3 训练成本约 $4.6M，GPT-4 估计超过 $100M
> * **电力消耗**：训练期间消耗数百万度电
>
> 这也是为什么只有少数大厂能从零训练基座模型，大多数团队基于开源基座做微调。

> [!TIP]
>
> 预训练就像一个人花十年时间读完整个图书馆——他积累了海量知识，语言表达流畅，什么话题都能聊几句。但他从未学过"怎么当客服"——你问他问题，他可能开始背书、写诗、或者反过来问你问题。这就是基座模型的状态：知识渊博，但不会按人类期望的格式回答。

### 预训练数据的质量与配比

预训练数据不是"越多越好"，数据的质量和配比直接影响模型能力：

| 数据来源 | 典型占比 | 作用 |
| - | - | - |
| 互联网网页（Common Crawl 等） | 60-70% | 通用语言能力和世界知识 |
| 书籍和学术论文 | 10-15% | 深度知识和推理能力 |
| 代码（GitHub 等） | 10-15% | 代码理解和生成能力 |
| 维基百科 | 3-5% | 结构化知识和事实准确性 |
| 对话数据 | 2-5% | 对话能力和问答格式 |

### 从 GPT-1 到 GPT-4 的训练演进

| 模型 | 年份 | 参数量 | 训练数据 | 关键突破 |
| - | - | - | - | - |
| GPT-1 | 2018 | 117M | \~5GB | 证明了自回归预训练的可行性 |
| GPT-2 | 2019 | 1.5B | 40GB | 证明了规模定律（Scaling Laws） |
| GPT-3 | 2020 | 175B | 300B tokens | Few-shot 学习能力涌现 |
| GPT-4 | 2023 | 未公开（业内推测为 MoE 架构） | 未公开 | 多模态、推理能力大幅提升 |

***

## Q3: SFT（Supervised Fine-Tuning）—— 让模型学会回答问题

SFT 是 LLM 训练的第二阶段，用高质量的"指令-回答"对微调基座模型，把它从"文本补全机器"变成"对话助手" <sup>\[1]</sup>。

```text theme={null}
┌──────────────────────────────────────────┐
│          高质量 SFT 数据集                 │
│  {                                       │
│    "instruction": "解释什么是闭包",       │
│    "input": "",                          │
│    "output": "闭包是指函数能够访问..."    │
│  }                                       │
│  典型规模：1 万 - 10 万条                  │
└─────────────────────┬────────────────────┘
                      │ 监督学习
                      ▼
┌──────────────────────────────────────────┐
│          SFT 模型                        │
│  能力：按指令回答、格式可控、减少幻觉      │
│  仍然存在的问题：回答质量参差不齐           │
└──────────────────────────────────────────┘
```

```python theme={null}
# ============================================================
# SFT（监督微调）训练过程（带详细注释）
# 比喻：SFT 就像给新员工做岗前培训——
#       看几百份优秀的"报告范例"，学会按公司规范格式工作
#       关键不是数量（1 万份低质量不如 100 份高质量）
#
# ASCII 流程图：
# ┌─────────────────────────────────────────────┐
# │  基座模型（知识渊博但不会按格式回答）          │
# │       +                                      │
# │  高质量 SFT 数据（指令 → 标准回答）           │
# │       ↓                                      │
# │  监督学习：模型学习生成与标准回答一致的输出    │
# │       ↓                                      │
# │  SFT 模型（会按指令回答，格式可控）            │
# └─────────────────────────────────────────────┘
# ============================================================

# SFT 数据格式（典型的 instruction-following 格式）
sft_dataset = [
    {
        "instruction": "请用简洁的语言解释什么是 React 的虚拟 DOM",
        "input": "",  # 有些任务不需要额外输入
        "output": (
            "虚拟 DOM 是 React 在内存中维护的一棵轻量级 DOM 树副本。"
            "当状态变化时，React 先在虚拟 DOM 上计算差异（Diff），"
            "再将最小变更批量应用到真实 DOM，避免频繁的 DOM 操作带来的性能损耗。"
        ),
    },
    {
        "instruction": "以下代码有什么问题？",
        "input": "const [count, setCount] = useState(0);\nuseEffect(() => {\n  setCount(count + 1);\n});",
        "output": (
            "这段代码会导致无限循环。useEffect 没有依赖数组，每次渲染后都会执行，"
            "而 setCount 触发重新渲染，形成死循环。"
            "修复：添加空依赖数组 `[]` 或指定 `[count]` 作为依赖。"
        ),
    },
    # ... 数万条高质量示例
]

def sft_train_step(model, example):
    """
    SFT 的单步训练过程

    参数：
        model: 基座模型（已预训练，但不会按指令回答）
        example: 一条 SFT 数据 {"instruction": ..., "input": ..., "output": ...}

    返回：
        loss: 损失值

    关键细节：
        1. SFT 只做"格式对齐"，不注入新知识——数据量太少（1-10 万条）
        2. 数据质量远比数量重要——1 万条精心标注 > 100 万条低质量
        3. 损失函数和预训练一样（交叉熵），但只在 output 部分计算
    """
    # 第 1 步：拼接 Prompt
    # 把指令和输入拼成模型能理解的格式
    prompt = (
        f"### 指令：{example['instruction']}\n"
        f"### 输入：{example['input']}\n"
        f"### 回答："
    )

    # 第 2 步：把 prompt + output 拼接成完整的训练序列
    full_text = prompt + example["output"]

    # 第 3 步：分词
    input_ids = tokenizer.encode(full_text)
    prompt_ids = tokenizer.encode(prompt)

    # 第 4 步：前向传播
    logits = model.forward(input_ids)  # [seq_len, vocab_size]

    # 第 5 步：计算损失（只在 output 部分计算，prompt 部分不计算）
    # 这是 SFT 和预训练的关键区别——预训练在整个序列上计算损失
    # SFT 只在"回答"部分计算损失，让模型学习"怎么回答"
    output_logits = logits[len(prompt_ids) - 1 : -1]  # output 部分的预测
    target_ids = input_ids[len(prompt_ids) :]           # output 部分的真实 Token
    loss = cross_entropy(output_logits, target_ids)

    # 第 6 步：反向传播 + 更新参数
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

    return loss

# --- SFT 训练后的效果 ---
# 基座模型（训练前）：
#   输入："什么是闭包？"
#   输出："什么是全局变量？什么是作用域？什么是..."  ← 续写更多问题
#
# SFT 模型（训练后）：
#   输入："什么是闭包？"
#   输出："闭包是指函数能够访问其词法作用域中的变量..."  ← 按格式回答
```

```javascript theme={null}
// SFT 数据格式（典型的 instruction-following 格式）
const sftDataset = [
  {
    instruction: "请用简洁的语言解释什么是 React 的虚拟 DOM",
    input: "",
    output:
      "虚拟 DOM 是 React 在内存中维护的一棵轻量级 DOM 树副本。当状态变化时，React 先在虚拟 DOM 上计算差异（Diff），再将最小变更批量应用到真实 DOM，避免频繁的 DOM 操作带来的性能损耗。",
  },
  {
    instruction: "以下代码有什么问题？",
    input:
      "const [count, setCount] = useState(0);\nuseEffect(() => {\n  setCount(count + 1);\n});",
    output:
      "这段代码会导致无限循环。useEffect 没有依赖数组，每次渲染后都会执行，而 setCount 触发重新渲染，形成死循环。修复：添加空依赖数组 `[]` 或指定 `[count]` 作为依赖。",
  },
  // ... 数万条高质量示例
];

// SFT 训练过程
for (const example of sftDataset) {
  // 拼接 instruction 和 input 作为 prompt
  const prompt = `### 指令：${example.instruction}\n### 输入：${example.input}\n### 回答：`;

  // 模型学习生成与 output 一致的回答
  const loss = computeLoss(model(prompt), example.output);
  loss.backward();
  optimizer.step();
}
```

> [!WARNING]
>
> SFT 阶段的核心原则是"数据质量远比数据数量重要"。1 万条精心标注的高质量数据，效果往往优于 100 万条低质量数据 <sup>\[1]</sup>。
>
> * **质量标准**：回答准确、格式规范、逻辑清晰、无有害内容
> * **多样性**：覆盖不同任务类型（问答、代码、翻译、摘要等）
> * **一致性**：同类型任务的回答风格和格式保持一致
> * **来源**：通常由专业标注团队或强模型（如 GPT-4）生成后人工审核

> [!TIP]
>
> SFT 就像给新员工做岗前培训。基座模型是一个知识渊博但没有工作经验的毕业生——他什么都知道一点，但不知道怎么写报告、怎么回邮件、怎么跟客户沟通。SFT 就是给他看几百份优秀的"报告范例""邮件模板""客户沟通记录"（高质量数据），让他学会按公司的规范和格式来工作。培训的关键不是数量——看 1 万份低质量的报告不如看 100 份优秀的报告。

### 前端工程师关注的 SFT 响应格式

SFT 不仅教会模型"回答什么"，还教会它"怎么格式化回答"。对前端工程师来说，以下格式尤为重要：

| 格式 | 用途 | 示例 |
| - | - | - |
| **JSON** | 结构化数据输出 | API 响应、代码分析结果 |
| **Markdown** | 文档和富文本 | 技术文档、README |
| **代码块** | 代码生成 | React 组件、TypeScript 类型 |
| **表格** | 对比和总结 | 技术选型对比、API 文档 |

### SFT 与预训练的关键区别

| 维度 | 预训练 | SFT |
| - | - | - |
| **目标** | 学习语言和知识 | 学会按指令回答 |
| **数据** | 海量无标注文本 | 少量高质量标注数据 |
| **数据量** | 数万亿 tokens | 1-10 万条 |
| **训练成本** | 数百万美元 | 数千到数万美元 |
| **输出** | 文本续写 | 指令跟随 |
| **类比** | 读遍图书馆 | 岗前培训 |

***

## Q4: RLHF（Reinforcement Learning from Human Feedback）—— 对齐人类偏好

RLHF 是 LLM 训练的第三阶段，通过人类反馈的强化学习，让模型的输出更符合人类期望——更有帮助、更安全、更诚实 <sup>\[1]</sup> <sup>\[2]</sup>。

```text theme={null}
┌─────────────────────────────────────────────────────┐
│  步骤 1：收集人类偏好数据                              │
│  人类标注员对模型的多个回答进行排序                      │
│  回答 A > 回答 B > 回答 C（从好到差）                  │
└──────────────────────────┬──────────────────────────┘
                           ▼
┌─────────────────────────────────────────────────────┐
│  步骤 2：训练奖励模型 (Reward Model)                   │
│  输入：(问题, 回答) → 输出：标量分数（奖励值）           │
│  奖励模型学会了判断"什么是好回答"                       │
└──────────────────────────┬──────────────────────────┘
                           ▼
┌─────────────────────────────────────────────────────┐
│  步骤 3：PPO 算法优化策略模型                          │
│  SFT 模型生成回答 → 奖励模型打分 → PPO 更新参数         │
│  目标：最大化奖励分数，同时不偏离 SFT 模型太远           │
└─────────────────────────────────────────────────────┘
```

```javascript theme={null}
// RLHF 的三步流程（伪代码）

// 步骤 1：收集偏好数据
const preferenceData = [
  {
    prompt: "解释什么是闭包",
    chosen: "闭包是指函数能够访问其词法作用域中的变量...",
    rejected: "闭包就是函数里面套函数，外面的变量在里面能用...",
  },
  // ... 数万条偏好对
];

// 步骤 2：训练奖励模型
for (const { prompt, chosen, rejected } of preferenceData) {
  const rewardChosen = rewardModel(prompt, chosen); // 好回答的分数
  const rewardRejected = rewardModel(prompt, rejected); // 差回答的分数

  // 损失函数：好回答的分数应该高于差回答
  const loss = -log(sigmoid(rewardChosen - rewardRejected));
  loss.backward();
  optimizer.step();
}

// 步骤 3：PPO 优化
for (const prompt of prompts) {
  const response = sftModel.generate(prompt); // SFT 模型生成回答
  const reward = rewardModel(prompt, response); // 奖励模型打分
  const klPenalty = klDivergence(sftModel, refModel); // KL 散度惩罚

  // 总奖励 = 奖励模型分数 - KL 惩罚
  // KL 惩罚防止模型偏离 SFT 模型太远（避免 reward hacking）
  const totalReward = reward - beta * klPenalty;

  // PPO 更新策略模型
  ppoUpdate(sftModel, totalReward);
}
```

> [!WARNING]
>
> RLHF 中最关键的工程细节是 KL 散度约束。如果没有这个约束，模型会学会"欺骗"奖励模型——生成奖励模型给高分但人类并不喜欢的回答（Reward Hacking）。KL 散度惩罚确保模型不会偏离 SFT 模型太远 <sup>\[2]</sup>。
>
> * **Reward Hacking 的例子**：模型发现回答中加"根据权威专家的说法"会得到更高分数，于是所有回答都加上这句话，但内容质量并没有提升
> * **KL 约束的作用**：限制新模型与 SFT 模型的差异，保持回答的自然性

> [!TIP]
>
> RLHF 就像制定考试阅卷标准的过程。第一步（偏好数据）：请一批老师对学生的答卷进行排序——"这份答得好，那份答得差"。第二步（奖励模型）：把这些排序结果总结成一套评分标准（"开头要明确、逻辑要清晰、举例要具体"）。第三步（PPO 优化）：让学生按照评分标准来改进自己的答卷——每写一版就请评分标准打分，不断迭代直到得高分。KL 约束就像告诉学生"你可以改进，但不能完全变成另一个人"——保持你原有的知识和风格，只是在表达方式上优化。

### PPO 算法的核心思想

PPO（Proximal Policy Optimization）是 RLHF 中最常用的强化学习算法：

| 概念 | 含义 | 作用 |
| - | - | - |
| **策略 (Policy)** | SFT 模型 | 生成回答的"决策者" |
| **奖励 (Reward)** | 奖励模型的输出 | 衡量回答质量的分数 |
| **KL 惩罚** | 与参考模型的差异 | 防止偏离太远 |
| **Clip 机制** | 限制更新幅度 | 保证训练稳定性 |

### RLHF 需要解决的三个核心挑战

| 挑战 | 问题 | 解决方案 |
| - | - | - |
| **标注成本高** | 需要大量人类标注员 | 用强模型替代人类标注（Constitutional AI） |
| **训练不稳定** | PPO 超参数敏感 | KL 约束 + Clip 机制 |
| **Reward Hacking** | 模型欺骗奖励模型 | KL 约束 + 定期更新奖励模型 |

***

## Q5: DPO（Direct Preference Optimization）—— RLHF 的简化版本

DPO 是 2023 年提出的 RLHF 替代方案，它的核心创新是**跳过奖励模型训练，直接从偏好数据中优化模型** <sup>\[2]</sup>。2024-2025 年，DPO 及其变体（IPO、KTO、SimPO、ORPO）已成为主流对齐方法。

```text theme={null}
RLHF 流程（复杂）：
偏好数据 → 训练奖励模型 → PPO 优化策略模型
   ↑ 需要同时维护 3 个模型，训练不稳定

DPO 流程（简洁）：
偏好数据 → 直接优化策略模型
   ↑ 策略模型 + 冻结的参考模型共 2 个，不需要奖励模型和 PPO 的 critic
```

```javascript theme={null}
// RLHF vs DPO 的核心区别

// ===== RLHF：需要训练奖励模型 =====
// 步骤 1：训练奖励模型
const rewardModel = new RewardModel();
for (const { prompt, chosen, rejected } of preferenceData) {
  const loss = -log(
    sigmoid(rewardModel(prompt, chosen) - rewardModel(prompt, rejected)),
  );
  loss.backward(); // 需要单独训练奖励模型
}

// 步骤 2：PPO 优化
for (const prompt of prompts) {
  const response = policyModel.generate(prompt);
  const reward = rewardModel(prompt, response);
  const klPenalty = klDivergence(policyModel, refModel);
  ppoUpdate(policyModel, reward - beta * klPenalty);
}

// ===== DPO：直接从偏好数据优化 =====
// 不需要奖励模型，直接用偏好数据训练
for (const { prompt, chosen, rejected } of preferenceData) {
  // DPO 损失函数：让 chosen 的概率高于 rejected
  const logProbChosen = policyModel.logProb(prompt, chosen);
  const logProbRejected = policyModel.logProb(prompt, rejected);
  const logProbRefChosen = refModel.logProb(prompt, chosen);
  const logProbRefRejected = refModel.logProb(prompt, rejected);

  // DPO 损失：隐式地最大化 chosen 和 rejected 的概率差
  const loss = -log(
    sigmoid(
      beta *
        (logProbChosen -
          logProbRefChosen -
          (logProbRejected - logProbRefRejected)),
    ),
  );
  loss.backward();
  optimizer.step();
}
```

> [!WARNING]
>
> DPO 的核心洞察是：RLHF 中的奖励模型可以被解析求解，从而跳过奖励模型训练。DPO 直接优化一个损失函数，使模型更偏好 chosen 回答、更不偏好 rejected 回答 <sup>\[2]</sup>。
>
> * **优势**：训练更稳定（不需要调 PPO 超参数）、计算成本更低（不需要维护奖励模型）
> * **局限**：不支持在线学习（不能实时从新反馈中学习）、对偏好数据质量更敏感
> * **2025 趋势**：DeepSeek 等模型使用 GRPO（Group Relative Policy Optimization）结合两者优点

> [!TIP]
>
> RLHF 就像学做菜的"标准流程"：先请美食评论家写一本《评分标准手册》（训练奖励模型），然后你做一道菜，请手册打分，根据分数改进（PPO 优化）。DPO 就像"直接看对比视频"：不需要评分手册，直接看两道菜的对比视频——"这道比那道好吃"——然后记住差异，下次改进。DPO 更简单直接，但如果视频质量不高（偏好数据不好），学到的东西可能不准确。

### DPO vs RLHF 全面对比

| 维度 | RLHF | DPO |
| - | - | - |
| **训练流程** | 偏好数据 → 奖励模型 → PPO | 偏好数据 → 直接优化 |
| **模型数量** | 3 个（策略、奖励、参考） | 2 个（策略、参考） |
| **训练稳定性** | 不稳定（PPO 超参数敏感） | 稳定 |
| **计算成本** | 高 | 低 |
| **推理能力对齐** | 更强 | 一般 |
| **在线学习** | 支持 | 不支持 |
| **2024-2025 趋势** | 仍有优势（复杂推理） | 成为主流（简单偏好） |
| **代表模型** | ChatGPT、Claude 2 | Llama 3、Mistral |

### DPO 的变体（2024-2025 年）

| 变体 | 核心改进 | 适用场景 |
| - | - | - |
| **IPO** | 防止 DPO 的过度优化 | 数据质量一般时 |
| **KTO** | 只需要"好/坏"标签，不需要配对 | 标注成本受限时 |
| **SimPO** | 简化参考模型 | 进一步降低计算成本 |
| **ORPO** | 将 SFT 和偏好优化合并为一步 | 端到端训练 |
| **GRPO** | 组内相对策略优化 | 复杂推理任务 |

***

## Q6: 微调方法（LoRA、QLoRA、全量微调）—— 前端工程师最实用的技能

对于前端工程师来说，从零训练基座模型不现实，但基于开源模型做微调是完全可以落地的。LoRA 和 QLoRA 让消费级 GPU 也能微调大模型 <sup>\[3]</sup>。

```text theme={null}
全量微调：更新模型所有参数
┌──────────────────────────────┐
│  原始权重 W (冻结)             │
│  ΔW = 所有参数都在更新         │  ← 需要巨大显存
└──────────────────────────────┘

LoRA：只更新低秩适配器
┌──────────────────────────────┐
│  原始权重 W (冻结)             │
│  ΔW = B × A (低秩矩阵)       │  ← 只需少量显存
│  A ∈ R^(r×k), B ∈ R^(d×r)   │
│  r << min(d, k)  通常 r=8    │
└──────────────────────────────┘
```

```javascript theme={null}
// LoRA 的核心原理（伪代码）

// 原始模型的前向传播
// output = W × input  （W 是预训练权重，d×k 矩阵）

// LoRA 修改后的前向传播
// output = W × input + (B × A) × input
// 其中：
//   W 冻结不动（不参与训练）
//   A ∈ R^(r×k)  降维矩阵（随机初始化）
//   B ∈ R^(d×r)  升维矩阵（零初始化）
//   r << min(d, k)  典型值 r = 8

// 具体数字（7B 参数模型为例）
// 原始权重矩阵：4096 × 4096 = 16,777,216 参数
// LoRA (r=8)：8 × (4096 + 4096) = 65,536 参数
// 参数减少：99.6%！

// QLoRA：在 LoRA 基础上加 4-bit 量化
// 原始权重用 4-bit 存储（而非 16-bit/32-bit）
// 显存需求从 ~14GB 降到 ~5GB（7B 模型）
// 可以在单张 RTX 3090/4090 上微调 7B 模型
```

> [!WARNING]
>
> LoRA 的效果取决于几个关键超参数 <sup>\[3]</sup>：
>
> * **r (rank)**：低秩矩阵的秩，通常取 4-64。r 越大，能力越强，但参数越多
> * **alpha (缩放因子)**：控制适配器的影响力，通常设为 r 的 1-2 倍
> * **target\_modules**：应用 LoRA 的层（通常是 Attention 的 Q/K/V/O 投影层）
> * **dropout**：LoRA 层的 dropout，防止过拟合
>
> LoRA 训练完成后，适配器权重可以合并回原始模型（`W' = W + B × A`），推理时没有额外延迟。

> [!TIP]
>
> LoRA 就像给汽车装改装件。全量微调是"把整辆车拆了重新造"——成本高、时间长，但效果最好。LoRA 是"保留原车不动，加装涡轮增压和运动悬挂"——原车的发动机、底盘都不动（冻结权重），只加几个改装件（低秩矩阵）。改装件很小（参数量只有 0.06%），但能显著提升性能。QLoRA 更进一步——"用更便宜的材料做改装件"（4-bit 量化），效果几乎一样，但成本更低。

### 三种微调方法全面对比

| 维度 | 全量微调 | LoRA | QLoRA |
| - | - | - | - |
| **可训练参数** | 100% | \< 1% | \< 1% |
| **7B 模型显存** | \~112 GB | \~28 GB | \~5-6 GB |
| **训练速度** | 慢 | 快 | 中等 |
| **效果** | 最优 | 接近全量 | 接近 LoRA |
| **适用 GPU** | A100 80GB | RTX 3090/4090 | RTX 3060 12GB |
| **模型存储** | 完整模型副本 (\~14GB) | 适配器 (\~10-50MB) | 适配器 (\~10-50MB) |
| **多任务切换** | 每个任务一个模型 | 热插拔适配器 | 热插拔适配器 |

### 微调数据准备的最佳实践

```javascript theme={null}
// 微调数据格式（以代码审查为例）
const fineTuneData = [
  {
    // 任务：代码审查
    instruction: "审查以下 React 组件的性能问题",
    input: `function UserList({ users }) {
  return (
    <div>
      {users.map(user => (
        <div key={user.id}>
          <img src={user.avatar} />
          <span>{user.name}</span>
          <span>{user.email}</span>
        </div>
      ))}
    </div>
  );
}`,
    output: `发现以下性能问题：

1. **缺少 memo 化**：UserList 组件在父组件重渲染时会无条件重渲染。
   建议：用 React.memo 包裹组件。

2. **列表项缺少 memo 化**：每个 UserItem 在父组件更新时都会重渲染。
   建议：将列表项抽为独立组件并用 React.memo 包裹。

3. **img 缺少 loading 属性**：大量头像同时加载可能阻塞首屏。
   建议：添加 loading="lazy"。

修复后的代码：
\`\`\`jsx
const UserItem = React.memo(function UserItem({ user }) {
  return (
    <div>
      <img src={user.avatar} loading="lazy" />
      <span>{user.name}</span>
      <span>{user.email}</span>
    </div>
  );
});

const UserList = React.memo(function UserList({ users }) {
  return (
    <div>
      {users.map(user => (
        <UserItem key={user.id} user={user} />
      ))}
    </div>
  );
});
\`\`\``,
  },
  // ... 更多高质量示例
];
```

***

## Q7: 高频面试题

> [!TIP]
>
> LLM 训练的四个阶段对应学生成长的四个阶段。预训练是"上学读书"——从小学到大学，学习语言、知识和基础推理（花 16 年，成本最高）。SFT 是"岗前培训"——看优秀范例，学会按规范格式工作（花几个月，成本中等）。RLHF 是"导师指导"——导师不断给反馈，告诉你"这样做更好""那样做不对"（持续迭代，成本中等）。DPO 是"看对比案例自学"——不需要导师实时指导，直接看好坏案例的对比就能学到标准（更高效，但不如导师指导精准）。

### 基础梳理

| 阶段 | 目标 | 数据 | 成本 | 产出 |
| - | - | - | - | - |
| **预训练** | 学习语言和知识 | 海量无标注文本 | \$\$\$\$ | 基座模型 |
| **SFT** | 学会按指令回答 | 高质量指令-回答对 | \$\$ | 对话模型 |
| **RLHF** | 对齐人类偏好 | 人类排序数据 | \$\$\$ | 对齐模型 |
| **DPO** | 简化对齐流程 | 偏好对数据 | \$\$ | 对齐模型 |
| **LoRA 微调** | 适配特定任务 | 任务特定数据 | \$ | 领域模型 |

### 专家视角深度剖析

很多人能背出"预训练 → SFT → RLHF"的流程，但实际更在意的是：**每个阶段的设计动机是什么？为什么不能跳过某个阶段？这些权衡对前端工程师意味着什么？**

预训练阶段的核心价值不是"让模型知道很多东西"，而是"让模型学会语言的内在结构"。基座模型在预训练后学到的不仅是知识，更是一种"语言直觉"——它知道什么样的句子是通顺的、什么样的推理是合理的。这种能力无法通过 SFT 从零教会——就像你无法通过岗前培训让一个不会中文的人写出流畅的中文文章。

SFT 阶段的核心价值是"格式对齐"而非"知识注入"。很多人的误区是认为 SFT 是在"教模型新知识"——实际上，SFT 的数据量（1-10 万条）远不足以注入新知识。SFT 真正做的是教会模型"按什么格式回答"和"什么场景下该说什么话"。这也是为什么 SFT 数据质量如此重要——一条高质量的示例，能让模型学到一种回答模式。

RLHF/DPO 阶段的核心价值是"价值对齐"——教会模型什么是"好的回答"。这是一个比"格式对齐"更深层的问题。一个好的回答不仅要格式正确，还要准确、安全、有帮助。RLHF 通过人类反馈让模型学会这种"品味"，DPO 则通过偏好对比实现同样的目标 <sup>\[1]</sup> <sup>\[2]</sup>。

对于前端工程师来说，理解这些阶段的实际意义是：当你用 LLM 构建应用时，你需要知道哪些能力来自哪个阶段。模型的知识来自预训练（所以它可能不知道最新的 API），回答格式来自 SFT（所以你可以通过 prompt 调整格式），回答质量来自 RLHF/DPO（所以不同模型的"品味"不同）。

***

## 🔍 底层源码：LoRA 的矩阵运算

LoRA 的低秩分解是怎么在 Transformer 中实现的？

LoRA 在 Transformer 的 Attention 层中注入低秩适配器（详见 [LoRA 论文](https://arxiv.org/abs/2106.09685)）：

```javascript theme={null}
// LoRA 在 Attention 层的实现（简化伪代码）
class LoRALinear {
  constructor(originalWeight, rank = 8, alpha = 16) {
    this.originalWeight = originalWeight; // 冻结的原始权重
    this.originalWeight.requiresGrad = false;

    // 低秩矩阵
    const d = originalWeight.shape[0]; // 输出维度
    const k = originalWeight.shape[1]; // 输入维度

    this.A = randomNormal(rank, k) * 0.01; // 降维矩阵（随机初始化）
    this.B = zeros(d, rank); // 升维矩阵（零初始化）
    this.scaling = alpha / rank; // 缩放因子
  }

  forward(x) {
    // 原始输出 + LoRA 输出
    const originalOutput = matmul(this.originalWeight, x);
    const loraOutput = matmul(this.B, matmul(this.A, x)) * this.scaling;
    return originalOutput + loraOutput;
  }

  merge() {
    // 训练完成后合并权重，推理时无额外开销
    return this.originalWeight + matmul(this.B, this.A) * this.scaling;
  }
}
```

LoRA 通常应用在 Attention 的 Q/K/V/O 四个投影层上。以 Llama 7B 为例：每个 Attention 层有 4 个投影矩阵，共 32 层，所以总共 128 个 LoRA 适配器。每个适配器只有几千个参数，但组合起来能有效适配模型行为。

***

## Q8: 满分回答 vs 及格回答

### 问题："请描述 LLM 从零到可用的完整训练流程"

**及格回答（60-70分）：**

> "先预训练，用海量数据训练基座模型。然后 SFT 微调，用高质量数据教模型回答问题。最后 RLHF，用人类反馈优化模型输出。"

问题出在：**知道流程但不理解每个阶段的设计动机和权衡**。

**满分回答（90-100分）：**

> "LLM 训练是一个从'学习语言'到'学习做人'的多阶段过程，核心分为四个阶段。预训练阶段在数万亿 tokens 的互联网文本上训练，目标是 next-token prediction，让模型学会语言结构和世界知识。这一步消耗了 95% 以上的训练算力，GPT-3 级别的训练成本约 \$4.6M。产出的基座模型会续写文本但不会回答问题。<sup>\[1]</sup>"

> "SFT 阶段用 1-10 万条高质量的指令-回答对微调基座模型。关键原则是数据质量远比数量重要——1 万条精心标注的数据效果优于 100 万条低质量数据。SFT 真正做的是'格式对齐'而非'知识注入'，教会模型按人类期望的格式回答问题。<sup>\[1]</sup>"

> "RLHF 阶段训练奖励模型学习人类对回答质量的排序偏好，再用 PPO 算法优化策略模型。关键工程细节是 KL 散度约束——防止模型学会'欺骗'奖励模型（Reward Hacking）。2023 年后 DPO 跳过了奖励模型训练，直接从偏好数据优化模型，训练更稳定、成本更低，已成为 2024-2025 年的主流方法。<sup>\[2]</sup>"

> "对于前端工程师来说，最实用的技能是 LoRA/QLoRA 微调。LoRA 通过低秩矩阵分解，只训练 0.06% 的参数就能接近全量微调的效果。QLoRA 在此基础上加 4-bit 量化，让 RTX 3090 就能微调 7B 模型。这意味着前端工程师可以在自己的开发机上定制领域模型，比如专门用于前端代码审查的 LLM。<sup>\[3]</sup>"

### 常见追问

> [accordion] 预训练的数据量大概是什么量级?
>
> **答题要点：**
> 用具体数字说明规模，对比不同模型。
>
> **高分回答：**
> "GPT-3 的预训练数据是 300B tokens（约 45TB 文本），使用了 1024 张 V100 GPU 训练了约 34 天，成本约 $4.6M。GPT-4 的具体数据未公开，但业界估计训练数据在 10T+ tokens 级别，使用了 25000 张 A100 GPU，训练成本超过 $100M。Llama 3 405B 的训练数据是 15T+ tokens，使用了 16000 张 H100 GPU。
>
> 数据来源主要是互联网网页（Common Crawl，占比 60-70%）、书籍和论文（10-15%）、代码（10-15%）、维基百科（3-5%）。数据质量和配比比数据量更重要——Meta 在 Llama 3 的技术报告中详细描述了数据清洗和去重流程，这比简单堆数据量有效得多。"

> [accordion] SFT 数据的质量标准是什么?
>
> **答题要点：**
> 从准确性、格式、多样性三个维度回答。
>
> **高分回答：**
> "SFT 数据的质量标准有三个维度：
>
> 1. **准确性**：回答内容必须事实正确、逻辑清晰。一条错误的示例可能教会模型一种错误的回答模式。所以 SFT 数据通常需要人工审核或用强模型（GPT-4）生成后人工校验。
>
> 2. **格式一致性**：同类任务的回答格式必须统一。如果 10 条代码审查示例中，5 条用 JSON 格式、5 条用 Markdown 格式，模型学到的格式就会不稳定。
>
> 3. **多样性**：覆盖不同任务类型和难度。如果所有示例都是简单的代码解释，模型遇到代码审查任务就不知道怎么处理。数据集需要覆盖问答、代码、翻译、摘要等多种任务。
>
> 典型的数据量是 1-10 万条。Alpaca 项目用 52K 条 GPT-4 生成的数据就实现了不错的 SFT 效果，说明数据质量比数量重要得多。"

> [accordion] RLHF 中的 Reward Model 是怎么训练的?
>
> **答题要点：**
> 解释偏好数据收集、奖励模型架构、训练目标。
>
> **高分回答：**
> "Reward Model 的训练分三步：
>
> 1. **收集偏好数据**：对同一个问题，让 SFT 模型生成 4-9 个不同的回答（通过不同的温度/采样参数），然后由人类标注员对这些回答进行排序。例如：'回答 A 最好，回答 C 次之，回答 B 最差'。每两个回答构成一个偏好对 (chosen, rejected)。
>
> 2. **模型架构**：Reward Model 通常基于 SFT 模型初始化，去掉最后的语言模型头，换成一个线性层输出标量分数。输入是 (问题, 回答) 的拼接，输出是一个浮点数表示回答质量。
>
> 3. **训练目标**：对于每对偏好数据，优化 Bradley-Terry 模型——让 chosen 的分数高于 rejected 的分数。损失函数是 `-log(sigmoid(r_chosen - r_rejected))`。训练数据通常有 10-50 万对偏好数据。"

> [accordion] PPO 算法在 RLHF 中是怎么工作的?
>
> **答题要点：**
> 解释 PPO 的核心机制和 KL 约束。
>
> **高分回答：**
> "PPO 在 RLHF 中的工作流程：
>
> 1. **采样阶段**：SFT 模型（策略模型）对一批 prompt 生成回答。
> 2. **评分阶段**：Reward Model 对每个回答打分，得到奖励值。
> 3. **KL 惩罚**：计算当前策略模型与参考模型（SFT 原始模型）的 KL 散度，防止偏离太远。
> 4. **优势估计**：用 GAE（Generalized Advantage Estimation）估计每个 token 的优势函数。
> 5. **PPO 更新**：用 Clip 机制限制策略更新幅度——新策略概率与旧策略概率的比值被裁剪在 \[1-ε, 1+ε] 范围内（ε 通常取 0.2）。
>
> Clip 机制的核心作用是防止策略更新太剧烈。如果某次回答得到很高奖励，没有 Clip 的话模型可能会大幅调整参数去复现这种回答，导致训练不稳定。Clip 确保每次更新都是'小步快跑'。"

> [accordion] DPO 为什么能跳过奖励模型?
>
> **答题要点：**
> 解释 DPO 的数学推导核心思想。
>
> **高分回答：**
> "DPO 能跳过奖励模型的原因是它发现了一个数学等价关系：RLHF 中奖励模型的最优解可以被解析求解，从而把奖励模型的参数用策略模型的参数表示出来。
>
> 具体来说，RLHF 的目标是最大化奖励的同时保持与参考模型的 KL 散度约束。这个优化问题的最优解有一个闭合形式：最优策略的概率比（chosen vs rejected）与奖励差成指数关系。DPO 直接把这个关系代入损失函数，用策略模型自身的概率来隐式表达奖励。
>
> 所以 DPO 的损失函数只需要两样东西：策略模型的概率和参考模型的概率。不需要单独训练奖励模型，直接从偏好数据中优化策略模型。这不仅简化了流程，还消除了奖励模型这个'中间商'可能引入的误差。"

> [accordion] LoRA 的秩 r 应该取多少?
>
> **答题要点：**
> 解释 r 的选择与任务复杂度的关系。
>
> **高分回答：**
> "LoRA 的秩 r 的选择取决于任务复杂度和数据量：
>
> 1. **r = 4-8**：适合简单的格式对齐任务（如让模型用 JSON 格式输出、调整回答风格）。参数量极少，训练快。
> 2. **r = 16-32**：适合中等复杂度的任务（如领域知识注入、代码审查）。大多数场景的推荐值。
> 3. **r = 64-128**：适合复杂任务（如数学推理、复杂代码生成）。接近全量微调效果。
>
> 经验值：r=8 + alpha=16 是一个很好的起点。如果效果不够好，先检查数据质量，再考虑增大 r。增大 r 的收益是递减的——从 r=8 到 r=16 提升明显，从 r=64 到 r=128 提升很小。
>
> 另外，target\_modules 的选择也很重要。只对 Q/V 投影层应用 LoRA（2 个模块）效果已经不错，对 Q/K/V/O 全部应用（4 个模块）效果更好但参数量翻倍。"

> [accordion] 🔥 预训练、SFT、RLHF 哪个阶段最重要?
>
> **答题要点：**
> 这是一个争议性问题，需要展示辩证思维。
>
> **高分回答：**
> "表面上看，预训练最重要——没有预训练就没有后面的一切。但这个答案太浅了。
>
> 反面的证据：2023 年的研究表明，用 GPT-3.5 做 SFT 和 RLHF 的效果，可能超过用更好的基座模型但不做对齐。Alpaca 项目用 Llama 7B + 52K 条 SFT 数据，效果接近 GPT-3.5，说明 SFT 和对齐的价值可能被低估。
>
> 我的判断是：三个阶段缺一不可，但重要性取决于你的起点。如果你从零开始，预训练最重要（没有基座，后面都是空中楼阁）。如果你基于开源模型做应用，SFT 最重要（它决定了模型在你的场景下的表现）。如果你追求极致品质，RLHF/DPO 最重要（它决定了模型的'品味'和安全性）。
>
> 升华：这个问题的本质是'数据、算法、对齐哪个更重要'。答案是：它们是乘法关系而非加法关系——任何一个阶段做不好，整体效果都会大打折扣。"

> [accordion] 🔥 前端工程师为什么要了解 LLM 训练?
>
> **答题要点：**
> 从实际工作场景出发，说明前端工程师了解训练流程的价值。
>
> **高分回答：**
> "前端工程师了解 LLM 训练流程有三个实际价值：
>
> 1. **更好地使用 LLM API**：理解模型的能力边界。预训练决定了模型的知识截止日期（不知道最新 API），SFT 决定了模型的回答格式（可以通过 prompt 调整），RLHF 决定了模型的安全限制（某些内容模型会拒绝回答）。理解这些，你就能更精准地设计 prompt，避免踩坑。
>
> 2. **微调领域模型**：LoRA/QLoRA 让前端工程师也能微调模型。比如微调一个专门用于前端代码审查的模型，或微调一个能准确解析你的项目代码风格的 Copilot。理解 SFT 数据格式和微调流程，是实现这些的前提。
>
> 3. **架构 LLM 应用**：当你用 LangChain 构建 RAG 或 Agent 时，理解模型的训练方式能帮你做出更好的架构决策。比如：模型的知识来自预训练（所以 RAG 需要注入最新文档），模型的格式偏好来自 SFT（所以 prompt 要匹配模型的训练方式），模型的安全边界来自 RLHF（所以某些任务需要特殊的 prompt 来绕过限制）。"

***

## 📚 延伸阅读与引用参考

* 🔗 [Andrej Karpathy: State of GPT (YouTube)](https://www.youtube.com/watch?v=bZQun8Y4L2s)：Karpathy 在 Microsoft Build 2023 的经典演讲，系统讲解 LLM 训练的四个阶段。<sup>\[1]</sup>
* 📖 [Lilian Weng: Reward Hacking in RLHF](https://lilianweng.github.io/posts/2023-10-25-rlhf/)：OpenAI 应用研究主管对 RLHF 机制和 Reward Hacking 问题的深度分析。<sup>\[2]</sup>
* 📖 [LoRA: Low-Rank Adaptation of Large Language Models](https://arxiv.org/abs/2106.09685)：微软提出的 LoRA 方法原始论文，理解低秩适配的数学原理。<sup>\[3]</sup>
* 🔗 [DPO 论文: Direct Preference Optimization](https://arxiv.org/abs/2305.18290)：斯坦福提出的 DPO 方法论文，2024-2025 年主流对齐方法的理论基础。
* 📖 [Llama 3 技术报告](https://ai.meta.com/research/publications/the-llama-3-herd-of-models/)：Meta 对 Llama 3 训练流程的完整描述，包括预训练数据、SFT、DPO/PPO 的工程细节。
* 🟢 [Hugging Face PEFT 文档](https://huggingface.co/docs/peft)：LoRA/QLoRA 微调的官方工具库文档，前端工程师入门微调的最佳起点。
* 🧑‍💻 [Andrej Karpathy: Let's build GPT from scratch (YouTube)](https://www.youtube.com/watch?v=kCc8FmEb1nY)：Karpathy 手把手从零实现 GPT，理解预训练的底层机制。
* 🧑‍💻 [宝玉 (Baoyu) 微博/X](https://weibo.com/baoyu)：国内 AI 核心论文及工程技术最快翻译与布道者，持续跟进 LLM 训练最新进展。
* 📖 [DeepSeek 技术报告](https://arxiv.org/abs/2401.02954)：DeepSeek 对 GRPO 等创新训练方法的描述，展示 2024-2025 年对齐技术的最新演进。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.