博客

  • 大语言模型基础与实践学习笔记

    💡 笔记简介

    本知识库由不会歌唱的老周维护,其在2026届秋招中人均斩获10+互联网大厂offer(字节、阿里、美团、快手、百度、京东、网易、B站等),大多为SSP或人才计划。

    内容涵盖大模型整体架构、预训练、后训练、常见模型、应用、训练推理优化、模型压缩、论文笔记、实践内容、面试八股&手撕、Agent、评估等,持续更新中。

    📂 目录

    序号章节
    0ML&DL 机器学习与深度学习简明入门
    1Architecture 大模型整体架构
    2Pre-training 预训练
    3Training & Inferring 训练推理优化
    4Post-training 后训练
    5Common Models 常见模型
    6Compression 模型压缩
    7Application 大模型应用
    8Agent 智能体专项
    9Evaluation 大模型评估
    10Papers 论文阅读笔记
    11Practice 大模型实践内容
    12Interview 大模型面试八股
    99Updating 持续更新内容

    0 ML&DL 机器学习与深度学习简明入门

    这章在讲什么:所有大模型的数学和算法地基都在这里——线性代数、最优化、各种经典 ML 算法、神经网络与 Transformer 的前置。如果你已经熟,可以快速翻过去;不熟也不用啃完再往下,遇到需要的概念回来查就行。

    0.1 ML 线性代数的几何观

    “The purpose of computing is insight, not numbers.” — Richard Hamming

    线性代数是机器学习的数学基石,本节从几何直觉出发,揭示向量、矩阵和线性变换的本质。

    0.1.1 向量的几何观

    想象在一个城市中导航,向量就像是从一个地点到另一个地点的”指令”:

    • 向东走 3 个街区
    • 向北走 2 个街区

    这个”指令”可以表示为向量 v=\begin{bmatrix}3\\2\end{bmatrix}。

    关键:

    1. 向量是位移,不是位置——向量描述的是”如何移动”,而不是”在哪里”
    2. 向量可以自由平移——同一个向量可以从任何起点出发
    3. 向量的大小和方向:\|v\|=\sqrt{3^2+2^2}=\sqrt{13}

    向量的基本运算:设 u, v \in \mathbb{R}^n,标量 c \in \mathbb{R}:

    • 向量加法:u+v = [u_1+v_1, u_2+v_2, \ldots, u_n+v_n]^T
    • 标量乘法:cv = [cv_1, cv_2, \ldots, cv_n]^T
    • 向量范数(欧几里得长度):\|v\|_2 = \sqrt{\sum_{i=1}^n v_i^2} = \sqrt{v^T v}
    • 点积(内积):u \cdot v = u^T v = \sum_{i=1}^n u_i v_i = \|u\|\|v\|\cos\theta,其中 \theta 是两向量之间的夹角。

    0.2 ML 优化理论基础

    “Machine learning is really just optimization in disguise.” — Unknown

    机器学习的核心任务是找到使损失函数最小的参数。

    0.2.1 梯度的几何观

    想象你站在山坡上,想要找到最低点(谷底),梯度就是指向最陡上升方向的向量。

    • 梯度的方向:函数增长最快的方向
    • 梯度的大小:该方向上的增长率
    • 负梯度:下降最快的方向(这就是为什么我们沿负梯度方向更新参数)

    关键洞察: 梯度始终与等高线垂直!梯度的基本定义与运算

    • 偏导数与梯度:对于多变量函数 f: \mathbb{R}^n \to \mathbb{R},在点 x=(x_1, x_2, \ldots, x_n) 的梯度定义为:\nabla f(x) = [\partial f/\partial x_1, \partial f/\partial x_2, \ldots, \partial f/\partial x_n]^T
    • 方向导数:沿单位向量 u 方向的方向导数:D_u f(x) = \nabla f(x) \cdot u = \|\nabla f(x)\| \cos\theta,其中 \theta 是 \nabla f 与 u 的夹角

    结论:

    • 当 \theta = 0(沿梯度方向),方向导数最大。
    • 当 θ=π(沿负梯度方向),方向导数最小
    • 当 θ=π/2(垂直于梯度),方向导数为零(等高线方向)

    中心差分法计算数值梯度

    def numerical_gradient(f, x, eps=1e-7):
        """
        使用中心差分法计算数值梯度。
        
        Parameters
        ----------
        f : callable
            目标函数
        x : np.ndarray
            计算梯度的点
        eps : float
            差分步长
            
        Returns
        -------
        np.ndarray
            数值梯度
        """
        x = np.array(x, dtype=float)
        grad = np.zeros_like(x)
        
        for i in range(len(x)):
            x_plus = x.copy()
            x_minus = x.copy()
            x_plus[i] += eps
            x_minus[i] -= eps
            grad[i] = (f(x_plus) - f(x_minus)) / (2 * eps)
        
        return grad
    

    0.2.2 Hessian 矩阵与二阶信息

    如果梯度告诉我们”坡度有多陡”,那么 Hessian 告诉我们”坡度变化有多快”

    • 正定 Hessian:像碗底,四面上升 → 局部最小值
    • 负定 Hessian:像山顶,四面下降 → 局部最大值
    • 不定 Hessian:像马鞍,有些方向上升,有些下降 → 鞍点

    Hessian 矩阵定义:对于 f:R n→R,Hessian 矩阵 H 是二阶偏导数组成的矩阵:

    0.3 ML KNN 与 KD-Tree

    “Tell me who your neighbors are, and I will tell you who you are.” — Proverb

    K 近邻 (KNN) 是最直观的机器学习算法:一个样本的类别由它的”邻居”投票决定。本节从零实现 KNN 及其加速结构 KD-Tree。

    0.3.1 距离度量

    KNN 的思路是”近朱者赤,近墨者黑”。但什么是”近”?在不同的问题中,”距离”的定义可能不同:

    • 地理距离:直线距离(欧几里得)
    • 城市街区:只能走横竖(曼哈顿)
    • 象棋国王:可以走斜线(切比雪夫)

    Minkowski 距离族:给定两点 x, y \in \mathbb{R}^n,Minkowski 距离定义为:

    d_p(x, y) = \left(\sum_{i=1}^n |x_i – y_i|^p\right)^{1/p}

    p名称公式几何意义
    1曼哈顿距离\sum_i \|x_i – y_i\|沿坐标轴的路径长度
    2欧几里得距离\sqrt{\sum_i (x_i – y_i)^2}直线距离

    0.4 ML 线性模型与正则化

    “The best model is the simplest one that explains the data.” — Occam’s Razor

    线性模型是机器学习的基础,本节从普通最小二乘法出发,逐步引入正则化,揭示其几何和贝叶斯解释。

    0.4.1 普通最小二乘法 (OLS)

    想象你有一堆散落的点,你想找一条直线(或超平面)来”最好地”穿过它们。什么叫”最好”?OLS 的回答:使所有点到直线的垂直距离平方和最小。

    为什么用平方?

    1. 惩罚大偏差(远离的点权重更大)
    2. 数学上更容易处理(可微、有闭式解)
    3. 与高斯噪声假设一致(最大似然估计)

    线性模型:\hat{y} = Xw + b = X_{\text{aug}} w_{\text{aug}},其中 X_{\text{aug}} = [X, 1] 包含偏置项。

    损失函数:L(w) = \|y – Xw\|^2 = (y – Xw)^T (y – Xw)

    正规方程:对 w 求导并令其为零:\partial L / \partial w = -2X^T(y – Xw) = 0,得到正规方程:

    X^T X w = X^T y

    0.5 ML 逻辑回归 (Logistic Regression)

    “Logistic regression is the ‘Hello World’ of classification.” — Every ML Practitioner

    逻辑回归是连接线性模型和概率分类的桥梁。本节从 Sigmoid 函数出发,通过最大似然估计推导交叉熵损失,最后扩展到多分类问题。

    0.5.1 Sigmoid 函数

    线性回归输出的是实数 (-\infty, +\infty),但分类问题需要概率 [0, 1]。我们需要一个函数来挤压实数到概率空间。Sigmoid 函数正是这样的压缩器:

    • 输入很大的正数 → 输出接近 1
    • 输入很大的负数 → 输出接近 0
    • 输入 0 → 输出 0.5

    Sigmoid 函数定义:\sigma(z) = \dfrac{1}{1 + e^{-z}}

    重要性质

    1. 值域:\sigma(z) \in (0, 1)
    2. 对称性:\sigma(-z) = 1 – \sigma(z)
    3. 导数:\sigma'(z) = \sigma(z)(1 – \sigma(z))

    导数推导

    \sigma'(z) = \frac{d}{dz}\left(\frac{1}{1+e^{-z}}\right) = \frac{e^{-z}}{(1+e^{-z})^2} = \frac{1}{1+e^{-z}} \cdot \frac{e^{-z}}{1+e^{-z}} = \sigma(z)(1-\sigma(z))

    0.6 ML 朴素贝叶斯 (Naive Bayes)

    “Despite its simplicity, Naive Bayes often outperforms more sophisticated classification methods.” — Andrew Ng

    朴素贝叶斯是一种基于贝叶斯定理的生成式分类器。它朴素地假设特征之间相互独立,但这种简化带来了高效的计算和出人意料的好效果。

    0.6.1 贝叶斯定理

    贝叶斯定理回答了一个核心问题:当我们观察到一些证据后,如何更新我们的信念?

    日常例子

    • 下雨的概率是 30%(先验)
    • 你看到乌云(证据)
    • 现在下雨的概率是多少?(后验)

    贝叶斯定理给出了从先验到后验的更新规则:

    P(y|x) = \frac{P(x|y) \cdot P(y)}{P(x)}

    各项含义

    • P(y|x):后验概率——给定特征 x,类别为 y 的概率
    • P(x|y):似然——给定类别 y,观察到特征 x 的概率
    • P(y):先验概率——类别 y 的初始概率
    • P(x):证据——特征 x 的总概率(归一化常数)

    0.7 ML 支持向量机与核方法 (SVM and Kernels)

    “Support Vector Machines are the most elegant supervised learning algorithm.” — Vladimir Vapnik (SVM 发明者)

    支持向量机是一种基于最大间隔的判别式分类器。它的思路是找到一个能够最大化类别间隔的决策边界。通过核技巧,SVM 可以处理非线性可分的数据。

    0.7.1 最大间隔分类器 ⭐

    想象你要在两组点之间画一条分割线。有无数种画法,哪种最好?SVM 的回答:选择间隔最大的那条线!

    为什么?

    • 间隔大 → 对噪声更鲁棒
    • 间隔大 → 泛化能力更强
    • 统计学习理论保证:间隔越大,VC 维越小,泛化误差上界越低

    关键概念

    • 决策边界:超平面 w^T x + b = 0,分类决策 \hat{y} = \mathrm{sign}(w^T x + b)
    • 几何间隔:点 x 到超平面的距离 \text{distance} = \dfrac{|w^T x + b|}{\|w\|}
    • 间隔(Margin):间隔是离超平面最近的点的距离的两倍 \text{margin} = \dfrac{2}{\|w\|}(通过缩放使得最近点满足 |w^T x + b| = 1)

    0.8 ML 决策树与集成学习 (Decision Trees and Ensembles)

    🪺 “A single decision tree is like one expert opinion; an ensemble is like a committee of experts.” — Leo Breiman

    决策树是一种直观的、基于规则的分类器。集成学习则通过组合多个弱学习器来构建强学习器。本节将从决策树的基础出发,逐步介绍 Random Forest 和 AdaBoost 等集成方法。

    0.8.1 信息熵与不确定性 ⭐

    熵(Entropy)衡量一个集合的混乱程度不确定性

    • 一个全是猫的集合:不确定性 = 0(你肯定知道下一个是猫)
    • 一半猫一半狗的集合:不确定性最大(完全猜不到下一个是什么)

    决策树的目标:找到能最大程度减少不确定性的划分方式。

    信息熵:对于一个包含 K 类的集合,第 k 类的比例为 p_k:

    H = -\sum_{k=1}^K p_k \log_2 p_k,\quad \text{约定 } 0\log_2 0 = 0

    性质

    • H \geq 0
    • H = 0 当且仅当所有样本属于同一类
    • H 在均匀分布时达到最大值 \log_2 K

    0.9 ML 偏差-方差权衡 (Bias-Variance Tradeoff)

    🐶 “All models are wrong, but some are useful.” — George Box

    理解模型为何会犯错是机器学习的核心问题。本节深入剖析泛化误差的组成,揭示过拟合与欠拟合的本质。

    0.9.1 偏差-方差的直觉 (The Intuition)

    一个简单的比喻:射箭。想象你在练习射箭,目标是正中靶心(真实函数 f(x)):

    • 偏差 (Bias):你的平均射击位置离靶心有多远?
      • 高偏差 = 系统性偏离(瞄准歪了)
      • 低偏差 = 平均而言瞄得准
    • 方差 (Variance):你的射击有多分散?
      • 高方差 = 射击点散得很开(手不稳)
      • 低方差 = 射击点集中
    射箭机器学习
    靶心真实函数 f(x)
    每次射击在不同训练集上学到的模型 \hat{f}(x)
    平均射击位置E[\hat{f}(x)]
    偏差E[\hat{f}(x)] – f(x)

    0.10 ML 评估指标与模型选择

    🥻 “In God we trust; all others must bring data.” — W. Edwards Deming

    选择正确的评估指标是机器学习成功的关键。不同的指标反映了对模型性能的不同关注点,错误的指标可能导致模型在实际应用中失败。

    0.10.1 评估指标的问题

    为什么准确率不够? 考虑一个垃圾邮件检测系统:

    • 总共 1000 封邮件
    • 990 封正常邮件,10 封垃圾邮件

    如果模型永远预测”正常”,准确率 = 990/1000 = 99%!但这个模型完全没用——它漏掉了所有垃圾邮件。

    不同错误的代价不同

    应用场景更严重的错误原因
    癌症检测漏诊 (FN)错过治疗时机
    垃圾邮件误判 (FP)重要邮件被删
    欺诈检测漏检 (FN)资金损失
    司法系统冤假错案 (FP)无辜者入狱

    0.11 ML 聚类算法 (Clustering Algorithms)

    ⛱️ “The goal is to turn data into information, and information into insight.” — Carly Fiorina

    聚类是无监督学习的核心任务:在没有标签的情况下,发现数据的内在结构。本教程将从 K-Means 开始,逐步介绍多种聚类算法。

    0.11.1 聚类直觉

    什么是聚类? 聚类的目标是将数据点分成若干组(簇),使得:

    • 簇内相似性高:同一簇内的点彼此接近
    • 簇间差异性大:不同簇的点彼此远离

    K-Means 的直觉:想象你有一群人站在操场上,你要把他们分成 K 个小组:

    1. 随机指定 K 个组长的位置
    2. 每个人走向最近的组长
    3. 每个组长移动到自己组员的中心
    4. 重复步骤 2-3,直到稳定

    0.12 DL 感知机与多层感知机

    ♦️ “The perceptron has no memory of the past.” — Frank Rosenblatt

    从单个神经元到万能函数逼近器,本教程将带你从第一性原理理解神经网络的构建过程。

    0.12.1 感知机 (Perceptron)

    感知机是最简单的神经网络单元,模拟生物神经元的基本功能:

    1. 接收输入:从多个来源收集信号(树突)
    2. 加权求和:对输入进行加权组合(细胞体)
    3. 激活判断:超过阈值则激活输出(轴突)

    想象一个简单的决策过程:

    • 输入:天气好?(x_1),有空?(x_2),朋友来?(x_3)
    • 权重:每个因素的重要性
    • 输出:是否出门?

    思路:感知机将输入空间用一个超平面分割成两部分。

    感知机模型:给定输入 x = [x_1, x_2, \ldots, x_n]^T,感知机计算:

    z = w^T x + b = \sum_{i=1}^n w_i x_i + b

    \hat{y} = \mathrm{sign}(z) = \begin{cases} +1 & \text{if } z \geq 0 \\ -1 & \text{if } z < 0 \end{cases}

    0.13 DL 张量与计算图

    第一部分:基础架构 — 张量代数与广播机制

    核心概念:张量在内存中是一维存储,通过 shape 和 stride 映射到多维空间。

    理论推导:内存映射公式

    计算机内存是线性地址空间,但我们需要用多维索引 (i_0, i_1, \ldots, i_{n-1}) 访问张量元素。那么,如何建立这个映射?

    🥖 推导步骤

    1. C-contiguous 存储假设:最后一维连续存储(行优先)
      • 对于 shape (d_0, d_1, \ldots, d_{n-1}) 的张量
      • 最后一维 i_{n-1} 对应连续的内存位置
    2. Stride 的定义
      • \text{stride}_{n-1} = 1(最后一维步长为 1)
      • \text{stride}_k = \text{stride}_{k+1} \times d_{k+1}(递推关系)
    3. 线性索引公式:\text{memory\_index} = \text{offset} + \sum_{i=0}^{n-1} \text{index}_i \times \text{stride}_i

    示例验证:对于 shape (2, 3, 4) 的张量。

    0.14 DL 优化与训练基础

    🗺️ 权重初始化

    • Xavier 初始化(适用于 Sigmoid/Tanh):W \sim N\left(0, \dfrac{2}{n_{\text{in}} + n_{\text{out}}}\right)
    • Kaiming 初始化(适用于 ReLU):W \sim N\left(0, \dfrac{2}{n_{\text{in}}}\right)

    原理:保持激活值和梯度的方差在各层之间稳定传播。

    理论推导:Xavier 初始化

    目标:保持前向传播时激活值的方差稳定,即 \text{Var}(y) = \text{Var}(x)。

    设定:

    • 输入:x \in \mathbb{R}^{n_{\text{in}}},假设 E[x_i] = 0,\text{Var}(x_i) = \sigma_x^2
    • 权重:W \in \mathbb{R}^{n_{\text{out}} \times n_{\text{in}}},假设 E[W_{ij}] = 0,\text{Var}(W_{ij}) = \sigma_W^2
    • 输出:y = Wx(不考虑偏置和激活函数)

    📚 推导步骤

    1. 计算输出的期望:E[y_i] = E\left[\sum_{j=1}^{n_{\text{in}}} W_{ij} x_j\right] = \sum_{j=1}^{n_{\text{in}}} E[W_{ij}] E[x_j] = 0
    2. 计算输出的方差(假设 W 和 x 独立)。

    0.15 DL 线性回归

    “线性回归是机器学习的 ‘Hello World’,理解它是深度学习的基础。”

    0.15.1 线性回归的数学原理

    问题建模与假设空间

    问题设定:给定训练数据集 D = \{(x^{(i)}, y^{(i)})\}_{i=1}^n,其中 x^{(i)} \in \mathbb{R}^d 是输入特征,y^{(i)} \in \mathbb{R} 是目标值。我们的目标是学习一个函数 f: \mathbb{R}^d \to \mathbb{R},使得 f(x) 能够准确预测 y。

    线性假设:线性回归假设存在线性关系:

    \hat{y} = f(x; w, b) = w_1 x_1 + w_2 x_2 + \cdots + w_d x_d + b = w^T x + b

    这个假设定义了一个假设空间 H = \{f(x) = w^T x + b \mid w \in \mathbb{R}^d, b \in \mathbb{R}\}。

    参数说明

    • x = [x_1, x_2, \ldots, x_d]^T \in \mathbb{R}^d:输入特征向量
    • w = [w_1, w_2, \ldots, w_d]^T \in \mathbb{R}^d:权重向量
    • b \in \mathbb{R}:偏置项/截距项
    • \hat{y} \in \mathbb{R}:模型的预测输出
    • y \in \mathbb{R}:真实的目标值

    向量化表示:为了简化符号,我们可以将偏置项吸收到权重向量中。定义增广特征向量 \tilde{x} = [1, x_1, \ldots, x_d]^T \in \mathbb{R}^{d+1} 和增广权重 \tilde{w} = [b, w_1, \ldots, w_d]^T \in \mathbb{R}^{d+1},则模型可以简写为:\hat{y} = \tilde{w}^T \tilde{x}。

    0.16 DL Softmax回归与多分类

    🍍🎼 “从回归到分类,从二分类到多分类,Softmax 是关键的一步。”

    0.16.1 多分类问题的数学建模

    问题定义

    • 输入:特征向量 x \in \mathbb{R}^d
    • 输出:类别标签 y \in \{1, 2, \ldots, K\}(K 是类别数)
    • 训练数据:D = \{(x^{(i)}, y^{(i)})\}_{i=1}^n
    • 目标:学习一个分类器 f: \mathbb{R}^d \to \{1, 2, \ldots, K\} 使得 f(x) \approx y

    从线性回归到线性分类器

    • 线性回归(单输出):\hat{y} = w^T x + b \in \mathbb{R}
    • 线性分类器(多输出):z = Wx + b \in \mathbb{R}^K

    其中:

    • W \in \mathbb{R}^{K \times d}:权重矩阵,第 k 行 w_k^T 对应第 k 个类别的权重
    • b \in \mathbb{R}^K:偏置向量,b_k 对应第 k 个类别的偏置
    • z = [z_1, z_2, \ldots, z_K]^T 是得分向量 (logits),z_k 表示样本属于第 k 类的”原始得分”

    0.17 DL 计算机视觉基础

    🛹 卷积神经网络机制卷积操作:

    Y[i, j] = \sum_{m=0}^{K-1} \sum_{n=0}^{K-1} X[i+m, j+n] \cdot W[m, n]

    Im2Col 技巧:将卷积转换为矩阵乘法,充分利用 BLAS 库优化:\text{Conv2D} \to \text{Im2Col}(X) \times W_{\text{flat}}

    理论推导:卷积的数学定义

    • 连续卷积(信号处理):(f * g)(t) = \int_{-\infty}^{\infty} f(\tau) g(t – \tau)\, d\tau
    • 离散卷积(深度学习,实际是互相关):Y[i, j] = \sum_{m=0}^{K-1} \sum_{n=0}^{K-1} X[i+m, j+n] \cdot W[m, n]

    注意:深度学习中的卷积实际是 Cross-correlation,不翻转卷积核。

    多通道卷积

    • 输入:X \in \mathbb{R}^{C_{\text{in}} \times H \times W}
    • 卷积核:W \in \mathbb{R}^{C_{\text{out}} \times C_{\text{in}} \times K \times K}
    • 输出:Y \in \mathbb{R}^{C_{\text{out}} \times H’ \times W’}

    Y[c_{\text{out}}, i, j] = \sum_{c_{\text{in}}=0}^{C_{\text{in}}-1} \sum_{m=0}^{K-1} \sum_{n=0}^{K-1} X[c_{\text{in}}, i+m, j+n] \cdot W[c_{\text{out}}, c_{\text{in}}, m, n]

    0.18 DL 序列建模

    🍔 RNN 与时间反向传播 RNN 前向传播:

    h_t = \tanh(W_{hh} h_{t-1} + W_{xh} x_t + b_h)

    梯度消失问题

    \frac{\partial h_t}{\partial h_0} = \prod_{k=1}^t \frac{\partial h_k}{\partial h_{k-1}} = \prod_{k=1}^t W_{hh} \cdot \text{diag}(\tanh'(z_k))

    当 \|W_{hh}\| < 1 时,梯度指数衰减。

    理论推导:BPTT 算法

    展开 RNN:将时间步展开为前馈网络 h_0 \xrightarrow{W_{hh}} h_1 \xrightarrow{W_{hh}} h_2 \xrightarrow{W_{hh}} \cdots \xrightarrow{W_{hh}} h_T

    损失函数(序列到序列):L = \sum_{t=1}^T L_t(h_t, y_t)

    梯度计算(对 W_{hh}):

    \frac{\partial L}{\partial W_{hh}} = \sum_{t=1}^T \sum_{k=1}^t \frac{\partial L_t}{\partial h_t} \cdot \frac{\partial h_t}{\partial h_k} \cdot \frac{\partial h_k}{\partial W_{hh}}

    关键项 \dfrac{\partial h_t}{\partial h_k} 是 Jacobian 矩阵的乘积:

    \frac{\partial h_t}{\partial h_k} = \prod_{i=k+1}^t \frac{\partial h_i}{\partial h_{i-1}} = \prod_{i=k+1}^t W_{hh}^T \cdot \text{diag}(\tanh'(z_i))

    0.19 DL 注意力与 Transformer

    自注意力机制

    Scaled Dot-Product Attention:

    \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V

    Multi-Head Attention:

    \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W^O

    其中 \text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V)。

    理论推导:Attention 作为软字典查询

    直觉:Attention 是可微分的字典查询操作。给定查询 q,在键值对 (K, V) 中查找:

    1. 计算相似度:\text{score}_i = q \cdot k_i
    2. 归一化权重:\alpha_i = \dfrac{\exp(\text{score}_i)}{\sum_j \exp(\text{score}_j)}
    3. 加权求和:\text{output} = \sum_i \alpha_i v_i

    矩阵形式(批量查询):\text{Attention}(Q, K, V) = \text{softmax}(QK^T) V

    理论推导:\sqrt{d_k} 缩放的必要性

    问题:为什么要除以 \sqrt{d_k}?方差分析。

    0.20 DL 生成模型

    🕒 变分自编码器 (VAE) ELBO 目标函数:

    \log p(x) \geq E_{q(z|x)}[\log p(x|z)] – D_{KL}(q(z|x) \| p(z))

    重参数化技巧:z = \mu + \sigma \odot \epsilon,\epsilon \sim N(0, I)

    理论推导:ELBO 的推导

    • 目标:最大化边缘似然 \log p(x)(困难,需要积分)
    • 变分推断:引入近似后验 q(z|x)
    • Jensen 不等式:

    \log p(x) = \log \int p(x, z)\, dz = \log E_{q(z|x)}\left[\frac{p(x,z)}{q(z|x)}\right] \geq E_{q(z|x)}\left[\log \frac{p(x,z)}{q(z|x)}\right]

    展开 ELBO:

    L = E_{q(z|x)}[\log p(x|z)] – D_{KL}(q(z|x) \| p(z))

    两项解释:

    1. 重构项:E[\log p(x|z)](解码器质量)
    2. 正则项:D_{KL}(q \| p)(编码器接近先验)

    重参数化技巧的必要性

    • 问题:z \sim q(z|x) 是随机采样,无法反向传播
    • 解决:将随机性外化

    0.21 DL LLM 基础

    🐻 分词算法 Byte-Pair Encoding (BPE):

    1. 初始化:每个字节作为一个 token
    2. 迭代:合并频率最高的相邻 token 对
    3. 重复直到达到目标词表大小

    优势:平衡词表大小和序列长度,处理未登录词。理论分析:压缩率权衡词表大小的影响:

    • 小词表(如 256):序列长,计算慢
    • 大词表(如 100k):嵌入矩阵大,罕见词泛化差

    BPE 的贪心策略:每次选择频率最高的 pair 合并:

    \text{score}(a, b) = \frac{\text{count}(a, b)}{\text{count}(a) \times \text{count}(b)}

    压缩率:\text{Compression} = \dfrac{\text{原始字符数}}{\text{token 数}},通常 BPE 可达 3 ~ 5 倍压缩(英文)。

    1. Architecture 大模型整体架构

    这章在讲什么:拆开一个现代大模型,看清它内部都有什么零件。从最外层的分词开始,一路看到 embedding、attention、FFN、归一化、位置编码、最终的结构。读完应该能回答”一个 token 从输入到输出经过了哪些计算”。

    后面 2-4 章讲怎么训练这个东西、3 章讲怎么把它在 GPU 上跑起来,都会反复用到这一章的概念。

    1.1 Tokenization 分词

    🕵️♀️

    1.1.1 分词介绍

    分词的目的与粒度

    分词的目的:将输入文本分成一个个词元(token),保证各个词元拥有相对完整和独立的语义,以供后续任务(比如学习 embedding 或者作为高级模型的输入)使用。

    ✏️ 分词的三种粒度 💕 词粒度 (word)

    英文天生空格分开词汇,中文可以使用 jieba 分词工具。

    • 优点:词的边界和含义得到保留
    • 缺点:
      1. 词粒度的词表由于长尾效应可能会非常大,包含很多的稀有词,存储和训练的成本都很高,并且稀有词往往很难学好
      2. OOV (out of vocabulary) 问题,对于词表之外的词无能为力
      3. 无法处理单词的形态关系和词缀关系,同一个词的不同形态,语义相近,完全当做不同的单词不仅增加了训练成本,而且无法很好地捕捉这些单词之间的关系;同时,也无法学习词缀在不同单词之间的泛化

    ⛩️ 字符粒度 (char) OOV 问题迎刃而解。

    • 优点:词表极小,比如 26 个英文字母可以组合出所有词,5000 多个中文常用字基本也能组合出足够的词汇,再加上一些常用字符
    • 缺点:
      1. 无法承载丰富语义
      2. 序列长度增长,带来计算成本的增长

    🍄 子词粒度 (subword)

    粒度介于 char 和 word 之间,基本思想为常用词应该保持原状,生僻词应该拆分成子词以共享 token 压缩空间。

    • 优点:可以较好地平衡词表大小与语义表达能力,比如 OOV 问题可以通过 subword 的组合来解决
    • 三种主流的 Subword 分词算法:BPE、WordPiece 和 Unigram Language Model

    1.2 Embedding 词嵌入

    🗨️

    1.2.1 词嵌入介绍

    🌟 一句话总结:Embedding 实际上就是一种映射关系,且是单射,可以看成是物理量语言文字、图像到数字的一种状态表征。

    • 物理意义:用数学的话来说:”它是单射且同构的”。简单来说,我们常见的地图就是对于现实地理的 Embedding,现实的地理地形的信息其实远远超过二维,但是地图通过颜色和等高线等来最大化表现现实的地理信息。通过它,我们在现实世界里的文字、图片、语言、视频就能转化为计算机能识别、能使用的语言,且转化的过程中信息不丢失。
    • 公式定义:Embedding 是一种将高维数据(如文本或图像)转换为较低维度的向量表示的技术。它以每个字在给定分布随机初始化的随机向量而组成的可学习参数矩阵,也就是一个全连接 Dense 层,其以 onehot 为输入,稠密向量为输出,即词向量。因此在实现上,用 lookup 查找表来代替矩阵乘积以提高性能。PyTorch 中常用的实现为 nn.Embedding(vocab_size, embed_dim)embed_dim 为词向量的表征维度大小,vocab_size 为词表大小。

    1.2.2 词嵌入方法

    词嵌入的发展可以分为三代:one-hot → 静态向量(Word2Vec/GloVe)→ 上下文相关向量(BERT/GPT 的 contextual embedding)。现代 LLM 用的是第三代。

    1. One-Hot

    最朴素的表示。词表大小为 V,每个词用一个 V 维向量、只在自己索引位置为 1。

    • ✅ 简单、无歧义
    • ❌ 维度爆炸(中文动辄 5 万词→ 5 万维稀疏向量)、任意两个词的余弦相似度都是 0,丢失语义关系

    2. Word2Vec(Mikolov 2013)

    第一个真正可用的稠密词向量。两种训练方式:

    • CBOW:用上下文预测中心词,适合小数据集
    • Skip-gram:用中心词预测上下文,适合大数据集
    flowchart LR
        subgraph CBOW
            Ctx[上下文 the cat _ on the] --> Hid1[隐藏层]
            Hid1 --> Pred1[预测中心词: sat]
        end
        subgraph SG["Skip-gram"]
            Cen[中心词 sat] --> Hid2[隐藏层]
            Hid2 --> P1[预测: the]
            Hid2 --> P2[预测: cat]
            Hid2 --> P3[预测: on]
        end
    

    关键技术:负采样(negative sampling)——不算所有词的 softmax 而是随机采几个负样本对比,把 O(V) 降到 O(k)。

    Word2Vec 的著名性质:向量空间里存在线性类比关系——king - man + woman ≈ queen

    3. GloVe(Stanford 2014):基于全局共现矩阵 + 矩阵分解。比 Word2Vec 训练快,效果接近。

    4. FastText(Facebook 2016):把每个词拆成 n-gram 字符再求和,能处理 OOV 词。中文场景里用得不多,但在欧洲小语种(形态学复杂)上效果好。

    5. Contextual Embedding(BERT/GPT 起)

    前面四种都是静态嵌入——一个词对应一个固定向量。但 “bank” 在 “river bank” 和 “bank account” 里意思完全不同——静态嵌入处理不了多义。

    BERT/GPT 的 embedding 层只是输入端的查找表,真正的”词向量”在中间层 hidden state——同一个词在不同上下文里的 hidden state 不一样。这就是 contextual embedding

    现代 LLM 实务中,”词嵌入”概念已经分裂成两个:

    • Input Embedding:模型最开始那张 lookup table nn.Embedding(vocab_size, hidden_size),参数量 V \cdot d,是模型的入口
    • Output Embedding / LM Head:把 hidden 投回词表概率,shape 是 d \cdot V
    • Tied / Weight Sharing:很多模型让 input 和 output embedding 共享同一份权重(减半参数量),LLaMA 1/2 不共享、GPT-2/Qwen 共享
    模型input/output embedding 是否共享
    GPT-2 / GPT-3✅ 共享
    LLaMA 1/2/3❌ 不共享
    Qwen 1/2✅ 共享
    DeepSeek-V3❌ 不共享

    不共享的好处:output embedding 可以单独学一个针对下一个 token 预测优化的表示;坏处:词表大时参数量翻倍(Llama-3 词表 128K × 4096 ≈ 0.5B,占整个模型 5%+)。

    6. 现代 Embedding 模型(用于 RAG 检索)

    跟 LLM 输入端的 embedding 不同,RAG 用的 embedding 是专门为”检索相似度”训练的模型:

    • BGE 系列(智源):bge-m3 支持稠密 + 稀疏 + ColBERT 多向量
    • Voyage AI:voyage-3 / voyage-large-2
    • OpenAI:text-embedding-3-large
    • Jina Embeddings:开源、性能均衡

    训练方式:对比学习(query/positive doc 拉近、negative doc 推远)。维度通常 768-3072,远大于 LLM 内部 hidden_size。

    1.3 Attention 注意力

    🎥

    1.3.1 Attention 介绍

    Attention 思路及理解

    👩🦯 Attention 机制处理时序问题,思路是在处理序列数据时,网络应该更关注输入中的重要部分,而忽略不重要的部分,通过学习不同部分的权重,将输入的序列中的重要部分显式地加权,从而使得模型可以更好地关注与输出有关的信息。

    传统的循环神经网络(RNN)或卷积神经网络(CNN)在处理整个序列时,难以捕捉到序列中不同位置的重要程度,可能导致信息传递不够高效,特别是在处理长序列时表现更明显。

    Transformer 中使用的 Scaled Dot-Product Attention(缩放点积注意力),其中 Q 和 K 用来产生重要性权重,然后加权 V 做聚合输出:

    \text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right) V

    Scaled Dot-Product Attention 计算流程

    flowchart LR
        X[输入 X<br/>shape=N×d] --> WQ[W_Q]
        X --> WK[W_K]
        X --> WV[W_V]
        WQ --> Q[Q]
        WK --> K[K]
        WV --> V[V]
        Q --> MM1[QK^T]
        K --> MM1
        MM1 --> SCALE[÷ sqrt d_k]
        SCALE --> MASK[Mask<br/>可选: causal/padding]
        MASK --> SM[Softmax]
        SM --> ATTN[Attention 权重<br/>N×N]
        ATTN --> MM2[× V]
        V --> MM2
        MM2 --> OUT[输出<br/>N×d]
    

    Multi-Head Attention:把上述过程做 h 次并行

    flowchart TD
        X[输入 X] --> Split[切分到 h 个 head<br/>每个 head 用独立的 W_Q W_K W_V]
        Split --> H1[Head 1<br/>Attention]
        Split --> H2[Head 2<br/>Attention]
        Split --> Hi[...]
        Split --> Hh[Head h<br/>Attention]
        H1 --> Concat[Concat]
        H2 --> Concat
        Hi --> Concat
        Hh --> Concat
        Concat --> WO[× W_O 输出投影]
        WO --> Out[多头输出]
    

    每个 head 学习不同的关注模式(语法、共指、长距依赖等),最后拼接 + 线性投影得到最终输出。

    1.3.2 KV Cache:自回归生成的核心优化

    为什么需要 KV Cache

    LLM 推理时是自回归生成:每生成一个新 token,都需要回顾之前所有 token 的 K、V 信息。如果不做缓存,每生成一步都要重新算所有历史 token 的 K、V——计算量是 O(N^2) 的,浪费极大。

    KV Cache 把每个 token 第一次算出的 K, V 缓存下来,下一步只需要:

    • 算出新 token 的 Q, K, V
    • 把新的 K, V append 到 cache
    • 用新 Q 与整段 cache 做 attention
    flowchart LR
        subgraph WithoutKV["❌ 不用 KV Cache(每步全量重算)"]
            T1[step 1: 算 token 1 KV]
            T2[step 2: 算 token 1,2 KV]
            T3[step 3: 算 token 1,2,3 KV]
            Tn[step N: 算 token 1..N KV]
            T1 --> T2 --> T3 --> Tn
        end
        subgraph WithKV["✅ KV Cache(增量计算)"]
            S1[step 1: 算 token 1 → cache]
            S2[step 2: 只算 token 2 → 追加 cache]
            S3[step 3: 只算 token 3 → 追加 cache]
            Sn[step N: 只算 token N → 追加 cache]
            S1 --> S2 --> S3 --> Sn
        end
    

    KV Cache 显存开销

    每层每 token 的 KV 占用:2 \times n_{\text{layer}} \times n_{\text{head}} \times d_{\text{head}} \times \text{precision}

    例如 Llama-7B(32 层、32 头、d_{\text{head}} = 128,FP16):

    \text{每 token KV} = 2 \times 32 \times 32 \times 128 \times 2\text{B} = 512\,\text{KB}

    一个 batch=16、seq_len=4096 的请求需要 16 \times 4096 \times 512\,\text{KB} \approx 32\,\text{GB}——比模型权重本身还大。这就是 GQA / MLA / PagedAttention 等技术存在的原因。

    1.3.3 MHA → MQA → GQA → MLA 演进

    为了压缩 KV Cache 显存,业界对多头注意力做了一系列改造:

    方案说明KV 头数典型模型
    MHA (Multi-Head)每个 head 独立的 Q、K、Vh原始 Transformer、GPT-3
    MQA (Multi-Query)所有 head 共享同一组 K、V1PaLM、Falcon
    GQA (Grouped-Query)把 head 分成 g 组,每组共享 K、VgLlama 2/3、Qwen2、Mistral
    MLA (Multi-head Latent)K、V 通过低秩压缩到 latent 向量,推理时按需还原等效极少DeepSeek V2/V3
    flowchart LR
        subgraph MHA["MHA: h 套 K V"]
            QM[Q × h] -.对应.-> KM[K × h]
            QM -.对应.-> VM[V × h]
        end
        subgraph MQA["MQA: 1 套 K V"]
            QQ[Q × h] -.全部共享.-> KQ[K × 1]
            QQ -.全部共享.-> VQ[V × 1]
        end
        subgraph GQA["GQA: g 套 K V"]
            QG[Q × h] -.每 h/g 个共享.-> KG[K × g]
            QG -.每 h/g 个共享.-> VG[V × g]
        end
        subgraph MLA["MLA: 低秩 latent"]
            QL[Q] --> LAT[Latent C_kv<br/>d_c 远 < d_h × h]
            LAT --> KL[需要时投影回 K]
            LAT --> VL[需要时投影回 V]
        end
    

    MLA 的核心数学(DeepSeek-V2 提出):

    c_t^{KV} = W^{DKV} h_t \quad (\text{压缩到 latent,} d_c \ll h \cdot d_h)k_t = W^{UK} c_t^{KV}, \quad v_t = W^{UV} c_t^{KV}

    KV Cache 只存 c_t^{KV}(约 \frac{1}{14} 的 MHA 大小),attention 计算时再上投影。配合 RoPE 的 decoupled 设计,MLA 在保持效果的同时把 KV Cache 压到——这是 DeepSeek-V3 能用 671B 参数低成本推理的关键。

    1.4 FFN & Add & LN 前馈层、残差、层归一化

    1.4.1 三个模块的作用

    • FFN(前馈层):在 Self-Attention 之后引入两层非线性变换,把每个 token 的表示从 d 维映射到一个更宽的中间维度(通常是 4d,Llama 用 SwiGLU 后约为 \frac{8}{3}d),再投回 d 维。它负责 Transformer 中绝大部分参数量,是模型存放”知识”和实现非线性表达的主要载体。
    • Add(残差连接):将子层的输入与输出按元素相加 x + \text{Sublayer}(x),让梯度可以在深层网络中无障碍地回传,缓解了梯度消失/爆炸,使训练更稳定。
    • LN(Layer Normalization):对单个 token 在特征维度做归一化(不依赖 batch),减小不同样本/位置间的尺度差异,配合残差使训练曲线更平滑。

    1.4.2 Pre-LN vs Post-LN

    原版 Transformer 采用 Post-LN(LN 放在残差之后):

    y = \text{LayerNorm}(x + \text{Sublayer}(x))

    但 Post-LN 训练深层模型时不稳定,需要复杂的 learning rate warmup。现代 LLM 主流采用 Pre-LN(LN 放在子层之前):

    y = x + \text{Sublayer}(\text{LayerNorm}(x))

    flowchart LR
        subgraph PostLN["Post-LN(原 Transformer)"]
            I1[输入 x] --> S1[Sublayer]
            I1 --> A1((+))
            S1 --> A1
            A1 --> L1[LayerNorm]
            L1 --> O1[输出]
        end
        subgraph PreLN["Pre-LN(现代主流)"]
            I2[输入 x] --> L2[LayerNorm]
            L2 --> S2[Sublayer]
            I2 --> A2((+))
            S2 --> A2
            A2 --> O2[输出]
        end
    

    Pre-LN 让残差路径保持”恒等”,梯度从顶到底无衰减地传递,使深层 Transformer 可以稳定训练;代价是最后输出前需要再加一个 LayerNorm。

    1.4.3 LayerNorm vs RMSNorm

    LayerNorm(标准)对特征向量 x \in \mathbb{R}^d 做:

    \text{LN}(x) = \gamma \cdot \frac{x – \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta, \quad \mu = \frac{1}{d}\sum x_i, \quad \sigma^2 = \frac{1}{d}\sum (x_i – \mu)^2

    RMSNorm(Llama 系列)省去了减均值和偏置项 \beta,只用均方根做归一化:

    \text{RMSNorm}(x) = \gamma \cdot \frac{x}{\sqrt{\frac{1}{d}\sum x_i^2 + \epsilon}}

    项目LayerNormRMSNorm
    计算减均值 + 除标准差 + 偏置只除均方根
    参数\gamma, \beta(2d 个)只有 \gamma(d 个)
    速度慢一些快 ~7-10%
    效果等价或略差与 LN 相当
    采用方GPT-2、GPT-3、BERTLlama 1/2/3、Qwen、DeepSeek、Mistral 等几乎所有现代 LLM

    现代 LLM 的标配组合Pre-RMSNorm + SwiGLU FFN + RoPE 位置编码 + GQA / MLA

    1.5 Positional Encoding 位置编码

    1.5.1 位置编码介绍

    ✏️ 位置编码的需求

    RNN 的结构包含了序列的时序信息,而 Transformer 却完全把时序信息给丢掉了,比如”他欠我 100 万”和”我欠他 100 万”,两者的意思千差万别,故为了解决时序的问题,Transformer 的作者用了一个绝妙的办法:位置编码 (Positional Encoding)。

    Attention 计算是无向的,而各种位置信息在 tokens 间的关系是很重要的。对于人来说很容易知道 tokens 的位置信息,比如:

    • 绝对位置信息:a1 是第一个 token,a2 是第二个 token……
    • 相对位置信息:a2 在 a1 的后面一位,a4 在 a2 的后面两位……
    • 不同位置间的距离:a1 和 a3 差两个位置,a1 和 a4 差三个位置……

    因此,我们需要这样一种位置表示方式,满足:

    • 它能用来表示一个 token 在序列中的绝对位置
    • 在序列长度不同的情况下,不同序列中 token 的相对位置/距离也要保持一致
    • 可以用来表示模型在训练过程中从来没有看到过的句子长度(长度外推问题)

    需要一个有界又连续的函数,最简单的正弦函数 sin 就可以满足这一点。频率设成非常低,这样几乎不会有不同 T 的位置编码重合的情况了:

    PE_t = [\sin(w_0 t), \sin(w_1 t), \ldots, \sin(w_{i-1} t), \ldots, \sin(w_{d_{\text{model}}-1} t)]

    其中 w_i = 1 / (d_{\text{model}} – 1)^{i / (d_{\text{model}} – 1)}。

    1.5.2 RoPE 旋转位置编码

    RoPE(Rotary Position Embedding,苏剑林 2021)是现代 LLM(Llama、Qwen、DeepSeek、ChatGLM 等)的默认位置编码方案。

    思路:不再把位置作为 embedding “加”到 x 上,而是把 Q, K 在二维平面上旋转一个与位置相关的角度,使得 Q_m^\top K_n 自然蕴含相对位置 m – n。

    将 d 维向量两两配对成 d/2 个二维子空间,每个子空间用旋转矩阵:

    R_m^{(i)} = \begin{pmatrix} \cos m\theta_i & -\sin m\theta_i \\ \sin m\theta_i & \cos m\theta_i \end{pmatrix}, \quad \theta_i = 10000^{-2(i-1)/d}

    对 Q 应用 R_m、对 K 应用 R_n,则:

    (R_m Q)^\top (R_n K) = Q^\top R_m^\top R_n K = Q^\top R_{n-m} K

    关键性质:内积只依赖于相对位置 n – m,与绝对位置无关——这正是注意力机制需要的。

    flowchart LR
        Q[Q 向量<br/>位置 m] --> RQ[旋转 m·θ]
        K[K 向量<br/>位置 n] --> RK[旋转 n·θ]
        RQ --> Dot[Q·K 内积]
        RK --> Dot
        Dot --> Rel[结果只依赖<br/>相对位置 n−m]
    

    RoPE 的三大优势:

    • 相对位置自然内嵌:无需额外参数,attention score 直接编码距离。
    • 长度外推友好:训练时见过 4K,推理时能在一定范围内用 NTK / YaRN 等技巧扩展到 32K+ 而不重训练。
    • 与 KV Cache 兼容:旋转在 Q, K 上做,不影响 cache 复用。

    1.5.3 长度外推方法

    训练时上下文窗口(如 4K)有限,但推理时想用更长(如 128K),需要”长度外推”:

    方法思路是否需要训练
    ALiBi不用位置编码,attention score 上加距离衰减的偏置 $-m \cdoti-j
    Position Interpolation (PI)把测试位置等比缩放到训练范围内,m’ = m \cdot L_{\text{train}} / L_{\text{test}}可少量微调
    NTK-aware scaling改变 RoPE 基数 \theta_i,让高频成分不被压缩否或少量微调
    YaRN分段缩放高低频,结合温度调整 attention 分布少量微调(< 1B token)
    DCA / LongLoRAshifted sparse attention、分段处理超长需要训练

    总结:现代主流 LLM(Llama 3、Qwen3、DeepSeek-V3)几乎都采用 RoPE + YaRN/NTK 外推 的组合获得 128K+ 上下文。

    1.6 Structure & Decoding 结构和解码

    📖 拓展阅读:🧑🎤 DeepSeek Engram 深度解读:当大模型学会查字典而不是硬背书

    1.6.1 大模型结构

    🗃️ 首先回顾 Transformer 的结构,主要分为编码器 Encoder 和解码器 Decoder 两部分,且都是多层叠加:

    • Encoder:MHA + FFN + LN & Add,采用双向注意力机制,前后的 token 都能看到
    • Decoder:先是 Masked MHA + LN & Add,单向注意力,当前 token 只能看到自己之前的 token,防止未来信息泄露,预测下一个 token 只能利用之前的信息;然后接上 Cross MHA(Encoder-Decoder Attention Layer),通过编码器输出的上下文信息来关注解码器这里的序列的相关部分,最后解码器生成与输入匹配的输出序列。

    Decoder-Only 大模型整体推理流程

    flowchart TD
        A[输入文本] --> B[Tokenizer 分词]
        B --> C[Token IDs]
        C --> D[Embedding 层<br/>token -> 向量]
        D --> E[+ 位置编码<br/>RoPE / ALiBi / 绝对]
        E --> F[Transformer Block × N]
        F --> G[Output LayerNorm]
        G --> H[LM Head<br/>线性投影到词表]
        H --> I[Softmax]
        I --> J[采样策略<br/>greedy / top-k / top-p / temperature]
        J --> K[下一个 Token]
        K -.自回归.-> A
    
        subgraph Block["单个 Transformer Block 内部"]
            direction TB
            B1[Masked Multi-Head<br/>Self-Attention]
            B2[Add & LayerNorm]
            B3[Feed-Forward Network<br/>FFN / MoE]
            B4[Add & LayerNorm]
            B1 --> B2 --> B3 --> B4
        end
    
        F -.展开.-> Block
    

    Encoder vs Decoder vs Encoder-Decoder 三种范式对比

    flowchart LR
        subgraph EO["Encoder-only (BERT 类)"]
            E1[双向 Attention] --> E2[句向量 / 标签]
        end
        subgraph DO["Decoder-only (GPT / LLaMA 类)"]
            D1[因果 Mask Attention] --> D2[自回归生成]
        end
        subgraph ED["Encoder-Decoder (T5 / BART 类)"]
            ED1[Encoder<br/>双向]
            ED2[Decoder<br/>因果 + Cross-Attention]
            ED1 --> ED2 --> ED3[条件生成]
        end
    

    1.6.2 解码采样策略

    LM head + softmax 得到的是下一个 token 在词表上的概率分布。怎么从这个分布里选出一个 token,决定了生成的”风格”——是稳重还是发散、是确定的还是有创意的。

    主流的五种采样方式:

    方法怎么选用途
    Greedy永远选概率最高的那个确定性任务(数学题、代码)
    Beam Search同时保留 k 条候选路径,最后选总体概率最高的翻译、摘要等结构化任务
    Temperature把 logits 除以 T 再 softmax;T<1 更尖锐,T>1 更平滑控制创造性
    Top-k只在概率最高的 k 个 token 里随机采样防止采到长尾低概率 token
    Top-p (Nucleus)累积概率超过 p 之前的 token 集合内随机采比 top-k 更自适应

    Temperature 的公式:

    P(x_i) = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)}

    • T \to 0:等同 greedy(最高概率独占)
    • T = 1:原始分布
    • T \to \infty:均匀分布

    实务组合:业界几乎都是 temperature + top-p 一起用——先用 T 调整分布形状,再用 p 截断长尾。常见参数:

    • 代码/数学:T=0T=0.1, top_p=1.0(要稳定)
    • 通用对话:T=0.7, top_p=0.9
    • 创意写作:T=0.9~1.2, top_p=0.95

    重复惩罚(repetition_penalty / presence_penalty):单独的一类后处理——对已经出现过的 token 在 logits 上施加惩罚,缓解模型陷入”我我我我我”的死循环。

    flowchart LR
        Logits[Logits z] --> RP[Repetition penalty<br/>对历史 token 减分]
        RP --> Temp[÷ Temperature]
        Temp --> Softmax[Softmax]
        Softmax --> TopK[Top-k 截断]
        TopK --> TopP[Top-p 截断]
        TopP --> Sample[多项式采样<br/>得到下一个 token]
    

    Beam Search 的边界:对开放生成(对话、创意)效果反而差——beam 倾向于生成”安全但无聊”的序列。所以 GPT 类对话模型几乎不用 beam,只在翻译、code completion 等结构化任务里用。

    2. Pre-training 预训练

    这章在讲什么:1 章把模型结构拆开看了,2 章告诉你怎么把这个空架子灌满知识。预训练就是用 10T 量级的 token 做下一个词预测,得到一个能”接龙”的 base model。

    你会看到训练数据从哪来、tokenizer 怎么训、整个 pretrain 流水线长什么样、训完怎么用 PPL 和 benchmark 衡量。还没对话能力——那是 4 章 SFT/RLHF 的事。

    2.1 预训练定义

    为什么要先预训练?

    直接拿一个随机初始化的网络去做具体任务(翻译、问答、分类),需要两样东西:海量标注数据 + 够大的算力。前者很贵,后者很烫。预训练绕开了这条死胡同——先用便宜的无标注文本灌一遍通识,让模型先学会”语言长什么样”,再用少量标注数据微调到下游任务。

    具体的两个动机:

    • 标注数据不够用。医学图像、法律条文这类专业语料,能找到的标注样本就那么点。预训练让模型在海量无标注语料上自学,下游微调时只需要几千到几万条标注。
    • 先验知识缺失。从零开始的模型连”主谓宾”都不知道。预训练之后模型已经隐式地学到了语法、常识、世界知识,下游任务起步就站在巨人肩膀上。

    预训练采用自监督学习——本身没有标签,但用”下一个 token”作为天然标签。训练目标是 Next Token Prediction loss:

    L = -\sum_{n=1}^N \log p(x_n \mid x_1, x_2, \ldots, x_{n-1}; \theta)

    模型每一步都在做同一件事:根据已经看到的前面那段话,猜下一个最可能出现的词。算 loss 时 prompt 和 response 都参与(这点跟 SFT 不一样,SFT 通常只算 response 部分)。

    2.2 预训练数据

    📖 拓展阅读:🦊 从 Pairwise 最优到多数据源混训配比

    ☀️ 整个预训练阶段最重要的就是数据的获取和处理。预训练的数据量级在 10T tokens,继续预训练则至少在 100B tokens 的量级。

    2.2.1 数据来源

    预训练数据通常来自以下几大类来源:

    • 网页爬取:CommonCrawl、C4、RedPajama、FineWeb 等大规模通用网页语料,是 LLM 知识广度的主要来源。
    • 百科与问答:Wikipedia、BaiduBaike、StackExchange、Zhihu 等,提供结构化知识与高质量问答样本。
    • 书籍与论文:Books3、ArXiv、PubMed,对长上下文理解、学术推理能力有显著作用。
    • 代码语料:GitHub、The Stack 等,是模型获得编程与符号推理能力的关键。
    • 多语种语料:mC4、CC-100、WuDao Corpora 等,让模型具备跨语言的迁移能力。
    • 自有/定向爬取:针对垂直领域(医疗、法律、金融)通过定向爬虫扩充行业语料。

    数据收集只是起点,后续还需要经过去重、质量过滤、PII 脱敏、毒性过滤、多源混训配比等清洗环节,才能进入正式的预训练流程。

    数据工程的核心信条Garbage In, Garbage Out. 同样规模的算力下,把 1T 噪声数据换成 500B 高质量数据,效果更好。LLaMA-3 之所以从 LLaMA-2 跃升,主要原因之一就是数据从 2T 翻到 15T 且质量飞跃。

    2.2.2 数据清洗:去重 + 质量过滤

    数据集里大量重复内容会让模型过拟合到 boilerplate——同一段免责声明出现 100 万次,模型就学会模板化输出。去重是数据工程的第一道关

    两类去重技术

    flowchart TD
        Raw[原始爬虫数据] --> URL[1. URL 级去重]
        URL --> Exact[2. 精确文本去重<br/>SHA-256 hash]
        Exact --> Fuzzy[3. 模糊去重<br/>MinHash + LSH]
        Fuzzy --> Sem[4. 语义去重<br/>Embedding + 聚类]
        Sem --> Clean[清洗后语料]
    
    • MinHash + LSH(Locality-Sensitive Hashing):把每个文档用 N-gram shingles → MinHash 签名 → LSH 分桶,复杂度从 O(N^2) 降到 O(N)。SlimPajama 用这套从 RedPajama 1.2T 砍掉 50% 重复变成 627B。
    • Semantic Dedup(语义去重):用 embedding 算余弦相似度,找出”意思一样但措辞不同”的文档。慢但精——通常作为 MinHash 之后的精修。

    质量过滤的常用维度

    • 长度(太短的句子无信息量)
    • 重复率(”hi hi hi”这类)
    • 困惑度(用一个小 LM 算,PPL 太高的剔除)
    • 语言识别(fastText 或 cld3 判别)
    • 敏感词 / NSFW 分类器
    • HTML 残留、模板化标记
    • 数学题/代码用专门的分类器筛

    FineWeb-Edu(HuggingFace 2024)的实验:用 Llama-3 给网页打”教育价值”分数(0-5),只保留 ≥3 的 1.3T token——同样 token 量下,训出来的模型在 MMLU 上比 RedPajama 高 5%+。数据质量 > 数据数量已经成为业界共识。

    2.2.3 数据混合配比:DoReMi 与动态采样

    不同数据源(网页 / 书籍 / 代码 / 数学)应该按什么比例混?这不是拍脑袋的事——配比错了,模型在通用能力或代码能力上会偏科。

    经验配比(参考 LLaMA-3)

    • 通用网页:50-60%
    • 代码:15-25%
    • 数学与学术:5-10%
    • 多语种:5-10%
    • 高质量书籍 / Wiki:5-10%

    DoReMi(Xie 2023):用小模型为大模型自动选配比

    flowchart LR
        D1[Domain 1: web<br/>w1] --> Train[训练小 reference 模型]
        D2[Domain 2: code<br/>w2] --> Train
        Dk[Domain k<br/>wk] --> Train
        Train --> Proxy[小 proxy 模型<br/>训练 → 看 loss]
        Proxy --> Update[Group DRO 更新 w]
        Update -.提升弱域权重.-> D1
        Update -.降低强域权重.-> D2
        Update --> Big[最终用 w* 训大模型]
    

    核心思路:用 280M 小模型 + Group DRO(Distributionally Robust Optimization)找出”最差表现的 domain”,提升它的权重——避免大模型在某些 domain 上过弱。在 8B 模型上验证有效。

    Data Mixture Laws(DoReMi 之后):研究发现混合 loss 与各域权重之间存在幂律关系,可以通过少量试验外推到最优配比,省去全量搜索。Qwen2 / DeepSeek-V3 都在用类似方法。

    2.2.4 课程学习与持续预训练(CPT)

    课程学习(curriculum learning):先训简单数据、再训困难数据。在 LLM 上效果不稳,但在某些垂域有用——比如先训”短文本 + 高质量”,再放开到”长文本 + 一般质量”。

    持续预训练(Continual Pre-Training, CPT):已经预训好的 base model 上,再用领域语料继续训。三个关键点:

    • 学习率要小:通常是初次预训练的 1/10(如 1\text{e-}5)
    • 加少量通用数据混训:防止”灾难性遗忘”,常见比例是 5-30% 通用数据
    • 不动 tokenizer:换 tokenizer 等于推倒重来

    典型应用:DeepSeek-Coder、Code-Llama、医学 GPT、法律 GPT 都是这条路线。

    2.2.5 Scaling Law:参数量、数据量、算力的配比

    Kaplan Scaling Law(OpenAI 2020) 是第一篇系统研究 LLM scaling 的论文,给出了 loss L 关于参数量 N、数据量 D、计算量 C 的幂律关系:

    L(N) = \left(\frac{N_c}{N}\right)^{\alpha_N}, \quad L(D) = \left(\frac{D_c}{D}\right)^{\alpha_D}, \quad L(C) = \left(\frac{C_c}{C}\right)^{\alpha_C}

    结论:模型越大、数据越多、算力越大,loss 越低。但 Kaplan 当年的实验偏向”数据无限、模型够大”,得出了”应该多花算力在扩模型上”的结论——这后来被证明是错的。

    Chinchilla Scaling Law(DeepMind 2022) 重新做实验,发现 Kaplan 低估了数据的重要性。核心结论:

    给定固定算力预算 C,最优的参数量 N 和数据量 D 应该按相同比例增长,且 D \approx 20 \times N。

    也就是说,训一个 7B 模型最优需要 ~140B token;训一个 70B 最优需要 ~1.4T token。Chinchilla 用 70B 参数 + 1.4T token 训出来的模型,明显优于 Gopher 280B + 300B token。

    flowchart LR
        C[算力预算 C ≈ 6ND] --> Pick{怎么分?}
        Pick -->|Kaplan 2020| Big[大模型 + 少数据]
        Pick -->|Chinchilla 2022| Equal[D ≈ 20N<br/>等比例扩张]
        Big -.被推翻.-> Equal
        Equal --> Recent[现代趋势<br/>"Over-training": D 远超 20N]
    

    算力估算公式:训练一次前向 + 反向的总 FLOPs 约为:

    C \approx 6 \cdot N \cdot D

    其中 6 = 1(前向)× 2(反向)× 3(梯度计算分 forward / 反向 forward / 反向 backward)。所以训一个 7B + 2T token 大约要 6 \times 7\text{B} \times 2\text{T} \approx 8.4 \times 10^{22} FLOPs,对应 ~3 万 GPU-小时(A100)。

    现代实践:远超 Chinchilla 最优

    Chinchilla 给的是”训练时 loss 最低”的配比,但推理成本是另一回事——同样的效果,小模型推理便宜得多。所以业界普遍用远超 20× 的 token 训小模型

    模型参数量 N训练 token DD / N
    Chinchilla(最优)70B1.4T20
    LLaMA 2 7B7B2T285
    LLaMA 3 8B8B15T1875
    Qwen2.5 7B7B18T2570

    这就是为什么近年 7B 模型越来越强——大家在用 100×~1000× Chinchilla 最优的数据量训练小模型,换取推理时的便宜。

    2.3 预训练流程

    2.3.1 训练 Tokenizer

    👍 在进行预训练之前,我们需要先选择一个预训练的模型基座。根据收集到的数据以及具体需求,训练一个 tokenizer。在收集到的数据集以及更大的通用数据集上,利用 BPE / BBPE / WordPiece 算法进行训练。

    一个较为普遍的问题是:大部分优秀的语言模型都没有进行充分的中文预训练(这段话在 2024 年可能是对的,但是在 2025 年有 DeepSeek R1 这样比较优秀的中文能力大模型存在,这句话可以选择性理解)。因此,许多工作都尝试将在英语上表现比较优秀的模型用中文语料进行二次预训练,期望其能够将英语上的优秀能力迁移到中文任务中来。

    通俗来讲,tokenizer 的目的就是将一句话进行切词,并将切好词的列表喂给模型进行训练。例如:你好世界 >>> ['你', '好', '世', '界']

    🍐 切词技巧

    至于怎么训 tokenizer:找一个内存空间很大的 CPU 机器,再找一份很大的 common 数据集,然后利用 BPE / BBPE 算法去跑。这里提醒一些细节:

    • 数字切分(避免 9.9 > 9.11 的问题回答不正确)
    • 控制压缩率,1 个 token 对应多少个汉字:压缩率太低,那就是字太多、词太少,很影响解码效率;压缩率太大,也就是词太多,又会影响模型的知识能力。通常压缩率越低的模型,loss 也会低,大部分中文大模型的 1 个 token 会映射成 1.5 个汉字左右
    • 手动移除脏的、敏感 token
    • 如果提前知道自己的业务场景,那就应该补充业务场景对应的 token,增加业务场景文本的压缩率,比如医疗场景,就提前把阿莫西林、青霉素等作为一个 token
    • 词表的中、英覆盖率要足够大,至于其他小语种是否要加,则看业务需求

    2.3.2 训练超参实务:lr / warmup / clip / batch

    预训练真正决定成败的不是模型架构,而是那些藏在 config 里的超参数。这里把每个关键参数掰开讲。

    学习率(learning rate)

    预训练的 lr 通常是 1\text{e-}4 \sim 6\text{e-}4,比 SFT/RLHF 的 5\text{e-}6 大得多——因为预训练是从零开始,不更新得快收敛不动。

    模型peak_lr备注
    GPT-3 175B6e-5较小
    LLaMA-2 70B1.5e-4中等
    LLaMA-3 8B3e-4较大
    Qwen2 7B3e-4较大

    通用经验公式:参数量越大 → lr 越小(损失曲面更陡),\eta \propto 1/\sqrt{N}。

    学习率调度(lr schedule)

    主流是 cosine schedule with warmup

    xychart-beta
        title "Cosine LR Schedule with Warmup"
        x-axis "训练步数" [0, 1000, 5000, 50000, 100000]
        y-axis "学习率" 0 --> 6
        line [0, 6, 5.8, 2.5, 0.6]
    
    • warmup 阶段(前 0.5-2% 的步数):lr 从 0 线性升到 peak,避免初期不稳定
    • cosine decay 阶段:从 peak 按余弦曲线降到 peak 的 10% 或 0
    • 训完 token 数确定后才能定 schedule——所以加 token 重训需要重置调度

    warmup ratio 经验:1\% \sim 5\% 总步数;模型越大、batch 越大,warmup 越久。

    梯度裁剪(gradient clipping)

    防止某个 batch 出现”梯度爆炸”导致 loss 飞掉。标准做法:clip-by-norm,让总梯度的 L2 范数不超过阈值 c:

    g \leftarrow g \cdot \min\left(1, \frac{c}{\|g\|_2}\right)

    LLM 训练几乎都用 c = 1.0。如果训练曲线偶尔出现 spike,先怀疑 clip 是否生效。

    Batch size 与全局 batch size

    • micro batch:单卡处理的 batch(受显存限制,常 1-8)
    • gradient accumulation:累积 k 个 micro batch 才更新一次(虚拟扩大 batch)
    • DP world_size:数据并行的卡数
    • global batch = micro × accum × DP

    大模型预训练的 global batch 通常 1\text{M} \sim 4\text{M} tokens(即 2\text{K} \sim 4\text{K} samples × seq_len 2K-4K)。batch 越大、训练越稳,但越大梯度噪声越小、可能影响泛化——Llama 3 用 16M batch、Qwen 用 4M。

    优化器:AdamW vs Lion vs Sophia

    优化器状态显存实测效果适用
    AdamW2× 参数(m + v)LLM 训练黄金标准通用
    Lion1× 参数(只有 momentum)持平或略差 AdamW,省显存显存紧
    Sophia接近 AdamW用 Hessian 估计,快 30-50%实验性
    AdaFactorO(\sqrt{d})T5/PaLM 用过,长尾噪声大历史方案

    AdamW 黄金参数:\beta_1 = 0.9、\beta_2 = 0.95(不是 0.999!),\epsilon = 10^{-8},weight_decay = 0.1。

    Adam 的 \beta_2 在 LLM 上要调低到 0.95——这是 GPT-3 论文给出的经验,否则训练后期会陷入”假收敛”。

    混合精度(mixed precision)

    • FP16:动态范围小,loss scaling 必须开
    • BF16:动态范围 = FP32,精度低些但训练稳——现代主流选择
    • FP8(H100/H200):见 6.1.7 FP8 训练与推理,需要 Transformer Engine
    flowchart LR
        W[FP32 master weights] --> F[FP16/BF16 forward]
        F --> Loss[Loss]
        Loss --> B[FP16/BF16 backward]
        B --> Grad[FP16/BF16 grad]
        Grad --> Conv[转 FP32]
        Conv --> Opt[AdamW 在 FP32 下更新]
        Opt --> W
    

    主权重保持 FP32 是关键——梯度信号小于 BF16 最小可表示数时,会被吞掉,FP32 才能积累。

    2.4 预训练评估

    📄 pretrain 的评估相对来说是 LLM 全链路评估工作中最简单的环节,因为它并不需要考察模型的指令 follow 能力、安全能力、幻觉现象等,只需要看模型整体的知识掌握程度即可。

    2.4.1 PPL 困惑度

    🐁 准备一些百科、逻辑、code 等数据,每天观察模型在这些测试集合上的 loss 表现,偶尔浮动是正常的,但整体趋势肯定是持续下降,最后趋于稳定的。

    特别地,PPL 只能是自己的模型和自己比,前面说过,由于 tokenizer 的压缩率不同,不同模型的 loss 没有明确可比性,全是字没有词的 tokenizer,loss 一定是最低的。不过另一方面,不管你的 tokenizer 压缩率多少,在通用知识测试集上的 loss 也是应该能降低到 2 以下的,否则就说明有点训练不充分。

    📌 困惑度在 1.5 Positional Encoding 位置编码中讲过,这里再复述一遍。

    困惑度(Perplexity)是自然语言处理中常用的一个评价指标,用于衡量语言模型的好坏。语言模型 Model 在测试集数据 T = \{w_1, w_2, \ldots, w_N\} 上的困惑度计算,困惑度越低,说明模型对下一个单词的预测越准确,模型性能越好:

    \text{Perplexity}(\text{Model}) = \exp\left(-\frac{1}{N} \sum_{i=1}^N \log P(w_i \mid w_1, \ldots, w_{i-1})\right)

    2.4.2 Benchmark

    除了用 PPL 跟踪自身训练曲线之外,业界还会用一系列公开 benchmark 来横向比较预训练模型的知识掌握度与基础能力:

    • 通用能力:MMLU、C-Eval、CMMLU、AGIEval。
    • 数学推理:GSM8K、MATH、MathQA。
    • 代码:HumanEval、MBPP、APPS。
    • 常识与阅读理解:HellaSwag、ARC、PIQA、TriviaQA。

    预训练阶段重点关注的是 zero-shot / few-shot 的”知识广度”和”语言建模质量”,因此挑选 benchmark 时优先覆盖跨领域的多任务集合,而把对话风格、安全等下游能力留给 SFT/RLHF 阶段评估。

    3. Training & Inferring 训练推理优化

    这章在讲什么:把”训练 / 推理”这件事从一张卡放大到一个集群。先估算显存(光算一下你就知道为什么 7B 都跑不动),再讲三大并行策略(DP/TP/PP)、ZeRO、Flash Attention,最后讲推理侧的 PagedAttention / vLLM 和 Speculative Decoding。

    把这章放在 4 章 Post-training 之前是有原因的——后训练里大量出现 LoRA、显存、混合精度的术语,先把基础设施过一遍,后面读得快。

    3.1 训练推理显存占用分析

    配套阅读:12.3 Transformer 参数量分析——本节给宏观直觉,那一节给计算细节。

    3.1.1 模型显存总体分析

    训练或推理时,显存分两块——AI 框架自己用的 + 系统占用的。总量可以用 nvidia-smi 直接看,每个 Python 进程占多少一目了然:

    +---------------------------------------------------------------------------------------+
    | Processes:                                                                            |
    |  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
    |        ID   ID                                                             Usage      |
    |=======================================================================================|
    |    1   N/A  N/A     67321      C   .../anaconda3/envs/py/bin/python         23646MiB |
    |    1   N/A  N/A     71612      C   .../anaconda3/envs/py/bin/python           848MiB |
    |    2   N/A  N/A     67321      C   .../anaconda3/envs/py/bin/python         25776MiB |
    +---------------------------------------------------------------------------------------+
    

    训练时占显存的东西大致七八种:模型参数、优化器状态、激活值、梯度、输入输出、临时变量、autograd 中间量。从用户角度可以分两类:

    • 可估算的(占大头):参数、优化器状态、梯度、激活、输入输出
    • 难估算的(小头但会爆 OOM):临时变量、自动梯度中间结果、框架自己的杂项

    后面 3.1.2 给一个 7B 模型的算例,看完你就明白为什么 80G A100 也跑不动一个朴素的 7B 全参训练。

    3.1.2 训练显存的四大块估算

    以 \Phi 参数(B 个,FP16 训练 + Adam 优化器)为例:

    组成公式7B 模型示例
    模型参数2\Phi B14 GB
    梯度2\Phi B14 GB
    Adam 优化器状态12\Phi B(master FP32 weight + m + v)84 GB
    激活值\approx 2 \cdot b \cdot s \cdot L \cdot h \cdot (34 + 5 \frac{a \cdot s}{h})取决于 batch / seq

    即一个 7B 模型不开任何优化的训练需要 ~110 GB 显存——单张 A100 80G 都装不下。这就是 ZeRO / 并行 / Flash Attention / 重计算 必须存在的原因。

    3.1.3 三大并行策略:DP / TP / PP

    flowchart TD
        subgraph DP["Data Parallel 数据并行"]
            DP1[GPU0: 完整模型 + batch 0-3]
            DP2[GPU1: 完整模型 + batch 4-7]
            DP3[GPU2: 完整模型 + batch 8-11]
            DP1 -.AllReduce 梯度.-> DP2
            DP2 -.AllReduce 梯度.-> DP3
        end
        subgraph TP["Tensor Parallel 张量并行"]
            TP1[GPU0: W 列切片 0]
            TP2[GPU1: W 列切片 1]
            TP1 -.AllReduce 激活.-> TP2
        end
        subgraph PP["Pipeline Parallel 流水线并行"]
            PP1[GPU0: Layer 0-7]
            PP2[GPU1: Layer 8-15]
            PP3[GPU2: Layer 16-23]
            PP1 --> PP2 --> PP3
        end
    
    维度DPTPPP
    切分对象batch单层权重矩阵模型层数
    通信内容梯度每层激活层间激活(micro-batch)
    通信频率每 step 一次每层一次阶段间
    适合场景模型能装下单卡模型单层就放不下模型层太多
    工具DDP、ZeROMegatron-LM 列/行并行GPipe、PipeDream、Megatron

    通信代价:TP > PP > DP。所以 TP 通常只在 node 内(NVLink 高带宽),PP 在 node 间,DP 包外面一层。这就是 Megatron-LM 推荐的 3D 并行 组合。

    进阶并行:

    • Sequence Parallel (SP):把序列维度切分到不同 GPU,减少长序列激活显存。
    • Expert Parallel (EP):MoE 时把不同 expert 切到不同 GPU,通过 all-to-all 通信交换 token。
    • Context Parallel (CP) / Ring Attention:把 attention 计算沿 seq 维分块、跨卡做 ring 通信,支持百万级上下文。

    3.1.4 ZeRO:消除冗余的数据并行

    ZeRO(DeepSpeed)把 DP 中每张卡冗余存储的 model state 切分到不同卡上

    阶段切分的状态显存节省通信代价
    ZeRO-1optimizer state与 DP 相同
    ZeRO-2optimizer state + gradient与 DP 相同
    ZeRO-3optimizer + grad + parameterN× (线性)增加 50%(参数 all-gather)
    ZeRO-Offload把 optimizer state 放 CPU
    ZeRO-Infinity进一步 offload 到 NVMe训万亿参数

    ZeRO-3 = FSDP(PyTorch 原生实现,FullyShardedDataParallel),现已是大模型训练标配。

    3.1.5 Flash Attention:IO 感知的精确注意力

    问题:标准 attention 在 GPU 上的瓶颈不是 FLOPs,而是 HBM ↔ SRAM 的内存带宽——中间矩阵 S = QK^\top、P = \text{softmax}(S) 都是 O(N^2) 大,需要反复读写 HBM。

    Flash Attention(Dao et al. 2022)的核心思路

    • Tiling:把 Q, K, V 分块加载到 SRAM 上做 attention,不把完整 N \times N 矩阵物化到 HBM。
    • Online softmax:用增量更新公式分块计算 softmax 而保持数值稳定。
    • Recomputation:反向传播时重算 attention 矩阵而不是从 HBM 读,节省 IO。
    flowchart LR
        subgraph Standard["标准 Attention(IO 瓶颈)"]
            Q1[Q in HBM] --> S1[S = QK^T<br/>写回 HBM]
            S1 --> P1[P = softmax S<br/>写回 HBM]
            P1 --> O1[O = PV]
        end
        subgraph Flash["Flash Attention(分块)"]
            Q2[加载 Q 块到 SRAM] --> Loop[for each K V 块:]
            Loop --> Tile[on-chip: 算 S P 增量 O]
            Tile --> Out[只写 O 到 HBM]
        end
    

    收益:训练加速 2-4×、显存降至 O(N)。Flash Attention 2/3 进一步优化 GPU SM 利用率。所有现代 LLM 训练栈(Megatron、DeepSpeed、HF Transformers)都默认开 FA

    3.1.6 PagedAttention / vLLM:推理服务的内存管理

    问题:传统推理框架给每个请求分配连续显存装 KV Cache,按”最大可能序列长度”预留——导致:

    • 内部碎片:实际生成长度 < 预留长度,浪费严重。
    • 外部碎片:不同请求大小不同,难以 pack。

    实测利用率经常 < 30%。

    PagedAttention(vLLM, Kwon et al. 2023)借鉴操作系统的”虚拟内存分页”

    • 把 KV Cache 切成固定大小的 block(如 16 个 token)。
    • 每个 sequence 维护一张 block table(类似页表),把 logical position 映射到 physical block。
    • 不同请求可以共享前缀 block(如同一个 system prompt),同一个 prompt 多次采样可以共享初始 block(Beam Search、Best-of-N)。
    flowchart LR
        subgraph Req1["Request 1"]
            L1[Logical: t0..t31] --> BT1[Block Table]
        end
        subgraph Req2["Request 2 (同一 system prompt)"]
            L2[Logical: t0..t31] --> BT2[Block Table]
        end
        subgraph Phys["Physical Memory Blocks"]
            B0[Block 0<br/>system prompt]
            B1[Block 1<br/>system prompt]
            B2[Block 2<br/>Req1 私有]
            B3[Block 3<br/>Req2 私有]
        end
        BT1 --> B0
        BT1 --> B1
        BT1 --> B2
        BT2 --> B0
        BT2 --> B1
        BT2 --> B3
    

    收益

    • KV Cache 利用率 > 95%;
    • batch size 可大幅提升 → 吞吐量 2-4×;
    • 前缀共享让 RAG / 多轮对话 / 多采样场景额外加速。

    vLLM 是目前最主流的开源推理引擎,配合 continuous batching(动态拼 batch)、CUDA Graph、Triton 自定义 kernel 等,QPS 远超 HF Transformers。

    3.1.7 Speculative Decoding:投机解码

    问题:自回归解码每步只能产 1 个 token,GPU 计算单元利用率极低(多数时间在等内存)。

    Speculative Decoding(Leviathan et al. 2023)的思路

    1. 用一个小的 draft model(如 Llama-7B 配 Llama-1B draft)先快速生成 K 个候选 token。
    2. 大模型一次性并行验证这 K 个 token——只需一次前向,就能并行获得 K 个位置的概率分布。
    3. 用拒绝采样从前往后接受候选 token,遇到第一个被拒绝的就重采样。
    flowchart LR
        P[Prompt] --> Draft[Draft Model 小]
        Draft --> Cand[候选 K 个 token]
        Cand --> Target[Target Model 大<br/>一次前向并行验证]
        Target --> Acc{逐个接受?}
        Acc -->|全接受| Out1[输出 K 个 token]
        Acc -->|第 i 个拒绝| Out2[输出 i-1 个 + 重采样 1 个]
        Out1 --> P
        Out2 --> P
    

    关键性质:输出分布与 target model 完全一致(数学上等价于直接采样),只是更快——理论加速 2-3×,实测在拒绝率低的简单任务上可到 3×+。

    变体

    • Medusa:在 target model 上接多个解码 head,省掉 draft model。
    • EAGLE:用 target model 自身的特征预测 draft,准确率更高。
    • Lookahead Decoding:用 Jacobi 迭代并行生成多 token,无需 draft model。
    • MTP(Multi-Token Prediction):训练时就让模型预测多个未来 token,DeepSeek-V3 把它做进训练目标。

    3.2 长上下文专项

    把模型从 4K 扩到 128K、1M 是 2024-2025 的主战场。挑战不在”能不能跑”,而在 (1) 训练时怎么省显存做 attention,(2) 推理时怎么不让 KV Cache 爆炸,(3) 模型在长上下文上是不是真有用

    3.2.1 Ring Attention:训练超长上下文的并行方案

    问题:训练 1M 上下文时,单卡显存装不下完整的 attention 计算(哪怕用了 Flash Attention)。

    Ring Attention(Liu 2023)的思路

    • 把序列沿 seq 维切分到 N 张卡(Context Parallel / Sequence Parallel
    • 每张卡只持有自己那段的 Q, K, V
    • 卡之间形成一个:每个时刻,每张卡用本地 Q 与”当前持有的 K, V 块”算 attention,然后把 K, V 块沿环传给下一张卡
    • 转一圈下来,每张卡的 Q 都和所有 K, V 算过 attention
    flowchart LR
        GPU0[GPU 0<br/>Q0, K0V0] -->|传 K0V0| GPU1[GPU 1<br/>Q1, K1V1]
        GPU1 -->|传 K1V1| GPU2[GPU 2<br/>Q2, K2V2]
        GPU2 -->|传 K2V2| GPU3[GPU 3<br/>Q3, K3V3]
        GPU3 -->|传 K3V3| GPU0
    

    理论上没有上下文长度上限——加卡就能继续扩。Gemini 1.5 / Claude 100K+ / Llama-3 128K 的训练都靠这套(或类似 stripe attention 的变体)。

    Striped Attention 是优化版:解决 causal mask 导致的负载不均(前几块 attention 比后几块少算很多)。

    3.2.2 StreamingLLM:让模型”流式”看无限长

    问题:训练只到 4K,推理时输入 100K 会发生什么?KV Cache 一旦超出训练长度,模型就崩——输出乱码。

    StreamingLLM(Xiao 2023)的核心发现

    • attention 在很多 head 上集中关注最前面几个 token(”attention sink”)——哪怕语义无关,模型也把它们当锚点
    • KV Cache 满了之后不要丢前几个 token,而要丢中间的、保留:(1) 最前 4 个 token(sink),(2) 最近的 W 个 token(local window)
    flowchart LR
        Old[Sink: t0..t3<br/>保留] --> Gap[...丢弃中间...]
        Gap --> New[Local: 最近 W 个 token<br/>保留]
        New --> Now[当前 token]
    

    效果:模型可以流式处理 4M+ token 而不崩,且推理时延恒定。代价:丢失中间内容的精确记忆(适合聊天历史这种”远古不重要”的场景,不适合大海捞针)。

    这条思路解释了为什么”system prompt 不要太长”的反直觉建议反而有时不对——前几个 token 是 attention sink,反而不会被遗忘

    3.2.3 长上下文外推:YaRN / NTK / DCA

    跟训练时扩长不同,外推是”不重训,就让推理时支持更长”。位置编码的外推方法见 1.5.3 长度外推方法——这里补一些工程实务。

    NTK-aware Scaling(直接调 RoPE 频率)

    RoPE 的不同维度对应不同频率:\theta_i = 10000^{-2i/d}。NTK 调整就是把基数 10000 改成 \alpha \cdot 10000:

    \theta_i’ = (\alpha \cdot 10000)^{-2i/d}, \quad \alpha = (L_{\text{test}} / L_{\text{train}})^{d/(d-2)}

    效果:高频维度(小 i)几乎不动、低频维度(大 i)被”拉伸”——保留细节的同时扩展感受野。免训练,推理时改个参数即可。

    YaRN(Peng 2023):在 NTK 之上加 temperature 调整 + 分段处理,效果优于纯 NTK。需要 ~1B token 的少量微调,可以从 4K 稳定外推到 128K。

    Dual Chunk Attention(DCA):把超长输入切块,块内做 full attention、块间做稀疏 attention——零训练扩到 100K+。Qwen2 长上下文版本用过。

    3.2.4 长上下文的”假信号”问题

    重要警告:模型号称的”128K 上下文”和”真能用 128K”经常是两码事。常用的验证方式:

    • NIAH(Needle In A Haystack):”大海捞针”——在长文中藏一句话,问模型能不能找出来。多数模型在 75% 位置开始衰减。
    • RULER(NVIDIA 2024):扩展版 NIAH,覆盖多针、变量跟踪、问答聚合等 13 类任务。这是当前最严格的长上下文 benchmark
    • InfiniteBench:100K+ 的真实长任务(小说问答、长代码理解等)。
    flowchart LR
        Claim[厂商宣传 128K] --> NIAH{大海捞针}
        NIAH -->|通过| Real128[真 128K]
        NIAH -->|失败| Fake[实际可用 < 32K]
        Real128 --> RULER{多任务长上下文 RULER}
        RULER -->|通过| Strong[真强长上下文]
        RULER -->|失败| Mid[只在 NIAH 上 work]
    

    经验:Gemini 1.5、Claude 3.5、GPT-4o、Qwen2.5-Turbo 在 RULER 上都能撑到 32K~64K 真有用;很多开源模型号称的 128K 实际只有 16K-32K 真好用。

    3.2.5 长上下文推理的工程优化

    长上下文的 KV Cache 是显存杀手。除了 GQA / MLA 这种架构层方案,还有几条工程路线:

    • KV Cache 量化:FP16 → INT8 / INT4,省 2-4× 显存。配合 vLLM、TensorRT-LLM 已成标配。
    • Sliding Window Attention:Mistral 用过,attention 只看最近 W 个 token。简单但损失全局信息。
    • 稀疏 KV Cache(H2O / Scissorhands):动态丢弃”不重要”的历史 KV,保留高 attention score 的 token。
    • Prefix Caching:多请求共享 system prompt 的 KV Cache,vLLM 默认支持,QPS 提升显著。

    4. Post-training 后训练

    这章在讲什么:2 章训出来的 base model 只会接龙、不会对话。后训练就是把它”驯化”成 ChatGPT 那种助手。

    三条主流路线:SFT 教会它听指令 → RLHF/PPO 或 DPO 对齐偏好 → 推理模型的 GRPO 路线(DeepSeek-R1)。还会讲 LoRA/QLoRA 这种”轻量微调”,以及怎么用 LLM-as-Judge 自动评估对齐效果。

    后训练完整流水线

    flowchart LR
        Pre[预训练 Base Model] --> SFT[SFT 监督微调<br/>指令对齐 instruction tuning]
        SFT --> RM[Reward Model 训练<br/>偏好数据打分]
        SFT --> PPO[PPO / GRPO<br/>RLHF 在线强化学习]
        RM --> PPO
        SFT --> DPO[DPO / KTO / SimPO<br/>离线偏好优化]
        PPO --> Chat[Chat Model]
        DPO --> Chat
        Chat --> RFT[RFT / RLAIF / Rejection Sampling<br/>持续迭代]
        RFT --> Chat
    

    三种主流后训练范式:

    • SFT → PPO(经典 RLHF):OpenAI、Llama2/3 的传统路线,需要训练独立 Reward Model,再用 PPO 在线更新策略。
    • SFT → DPO(离线偏好优化):DeepSeek、Qwen2 等部分模型采用,不需要 Reward Model 和在线采样,仅用偏好对做对比学习。
    • SFT → GRPO / RFT(推理模型路线):DeepSeek-R1 路线,使用规则可验证奖励(如数学答案对错),结合 group-wise advantage 估计,无需 Critic。

    4.1 SFT 监督微调

    拓展阅读:

    4.1.1 SFT 简介

    SFT(Supervised Fine-Tuning)做的事很简单:拿一个已经预训练好的 base model,在一份”指令-回答”格式的数据集上继续训一会,让它学会按指令回话。

    数据集的形式是 D = \{(I_k, A_k)\}_{k=1}^N,每条样本 = 一条指令 + 期望回答。模型选什么尺寸看具体任务和数据量:小模型在受限场景下够用,大模型(如 GPT-4 级别)才能撑住复杂任务和稀疏数据。

    SFT 跟 pretrain 在算法上几乎一样,区别在数据怎么组:

    • 打包方式:pretrain 把所有文本拼成连续长串,每条数据填满模型上下文上限;SFT 一条样本原本多长就多长,不拼接。
    • 角色分隔:SFT 引入 pretrain 阶段没见过的 special token(如 <im_start><im_end>)来标记角色边界——system / user / assistant 是标配,业务里也可以加”背景”、”旁白”、”事件”。这些 token 通过 SFT 阶段才学到含义。
    • loss mask:通常只对 assistant 部分算 loss,prompt 部分屏蔽掉——避免模型学到”我应该说用户的话”。

    4.1.2 Chat Template:多轮对话怎么进模型

    模型只看 token 序列,”多轮对话”对它而言是把所有对话拼成一长串。Chat Template 就是规定这个拼接格式的协议——什么 special token 标 role、system prompt 怎么放、轮次之间怎么分隔。

    OpenAI ChatML 格式(GPT-3.5/4 起,Qwen / Mistral 等沿用):

    <|im_start|>system
    你是一个有帮助的助手。<|im_end|>
    <|im_start|>user
    今天天气怎么样?<|im_end|>
    <|im_start|>assistant
    我没有实时天气数据,建议查询天气 App。<|im_end|>
    <|im_start|>user
    那香蕉好吃吗?<|im_end|>
    <|im_start|>assistant
    

    最后一行只有 <|im_start|>assistant\n 没闭合 —— 这就是”开始生成”的信号。

    Llama 系列格式(Llama-2):

    <s>[INST] <<SYS>>
    你是一个有帮助的助手。
    <</SYS>>
    
    今天天气怎么样? [/INST] 我没有实时天气数据... </s><s>[INST] 那香蕉好吃吗? [/INST]
    

    Llama-3 改成了类似 ChatML 的格式:<|start_header_id|>user<|end_header_id|> 等。

    DeepSeek-R1 推理格式:在 assistant 部分加 <think>...</think> 标签包裹思考过程:

    <|im_start|>assistant
    <think>
    让我先分析一下这个问题...
    </think>
    最终答案是:42<|im_end|>
    
    flowchart LR
        Raw[原始多轮对话<br/>list of messages] --> Apply[apply_chat_template]
        Apply --> Tokens[拼接成单串 token]
        Tokens --> Mask[生成 loss mask<br/>只在 assistant 部分为 1]
        Tokens --> Model[模型训练 / 推理]
        Mask --> Loss
    

    工程实务三个坑

    1. SFT 和推理用同一个 template:训练时用 ChatML、推理时用 Llama 格式,模型行为会乱掉。HuggingFace tokenizer.apply_chat_template 是规范做法。
    2. special token 必须在 tokenizer 词表中作为单 token:如果 <|im_start|> 被拆成多个 token,模型学到的边界就废了。
    3. 多轮 SFT 的 loss mask:所有 user 部分都 mask 掉、所有 assistant 部分都参与 loss,不要只算最后一轮。

    4.2 RL 强化学习基础

    💪 Reinforcement Learning 强化学习,这部分内容主要参考《动手学强化学习》,可以通过该书详细入门强化学习。这里做一些简要但是也比较全面的介绍,主要是想通过对强化学习有一定了解之后,看大模型强化学习会得心应手很多。

    4.2.1 强化学习问题、流程以及独特性

    强化学习解决的问题

    🦟 在机器学习领域,有一类重要的任务和人生选择很相似,即序贯决策(sequential decision making)任务。决策和预测任务不同,决策往往会带来”后果”,因此决策者需要为未来负责,在未来的时间点做出进一步的决策。实现序贯决策的机器学习方法就是强化学习(reinforcement learning)。预测仅仅产生一个针对输入数据的信号,并期望它和未来可观测到的信号一致,这不会使未来情况发生任何改变。

    强化学习(Reinforcement Learning,RL)是一种机器学习方法,用于解决需要在一定环境下通过与环境交互来学习最优行为策略的问题。其思路是通过试错(Trial and Error)和奖励机制来指导智能体(Agent)学习如何在不同情境下采取行动,以最大化长期累积奖励。

    应用场景:控制问题、游戏、资源管理优化、金融风险控制、推荐算法。

    强化学习流程:(待补充)

    4.3 RLHF 基于人类反馈的强化学习

    拓展阅读:⛓️ RL 又整花活:Rubric for Non-Verifiable RL 是个啥

    🚒 Reinforcement Learning from Human Feedback / Preference-based Reinforcement Learning(基于人类反馈的强化学习 / 基于偏好的强化学习)。

    本章主要包含 RLHF-PPO 的讲解及其改进算法 GRPO 等以及 GRPO 的改进算法的详解。

    4.3.1 RL 在 NLP 场景下的拓展

    NLP MDP 建模

    🥫 强化学习要应用到 NLP 任务中,需要进行马尔可夫决策过程 MDP 建模,对应的 agent、环境、状态和动作都需要明确的定义,MDP 详见 3.2.2 章节。

    RLHF-PPO 四模型架构

    flowchart TD
        Prompt[Prompt x] --> Actor[Actor π_θ<br/>策略模型<br/>训练中更新]
        Prompt --> Ref[Reference π_ref<br/>冻结的 SFT 模型]
        Actor -->|生成 y| Resp[Response y]
        Ref -->|生成 y| Resp
        Resp --> RM[Reward Model r_φ<br/>冻结]
        Resp --> Critic[Critic V_ψ<br/>价值模型<br/>训练中更新]
        RM --> KL[r - β·KL π_θ‖π_ref]
        Ref --> KL
        Actor --> KL
        KL --> Adv[Advantage<br/>A = R - V]
        Critic --> Adv
        Adv --> Loss[PPO Clipped Loss]
        Loss --> Actor
        Loss --> Critic
    

    四个模型的角色:

    • Actor(策略 / 训练):要被对齐的目标模型;输入 prompt,输出 response。
    • Reference(参考 / 冻结):SFT 后的初始策略;用于计算 KL 距离防止 Actor 跑偏。
    • Reward Model(奖励 / 冻结):基于人类偏好数据训练的打分器;输入 (prompt, response),输出标量。
    • Critic(价值 / 训练):估计每个 token 之后的期望累计奖励 V_t,用于 advantage 估计 A_t = R_t – V_t。

    显存压力主要来自 Actor + Critic 两个可训练 + 反向传播的模型,加上 RM + Ref 两个只前向的模型,工程上常用 LoRA / 共享底座来缓解。

    4.3.2 PPO 损失函数

    PPO 的 actor 用 clipped surrogate objective 避免策略更新过快:

    \mathcal{L}^{\text{CLIP}}(\theta) = \mathbb{E}_t \left[ \min\left( r_t(\theta) \hat{A}_t,\; \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t \right) \right]

    其中 r_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\theta_{\text{old}}}(a_t \mid s_t)} 是新旧策略比,\hat{A}_t 是优势估计(通常用 GAE)。\epsilon 一般取 0.1~0.2。

    加上 KL 约束后总目标:

    \mathcal{L}^{\text{PPO}}(\theta) = \mathcal{L}^{\text{CLIP}}(\theta) – \beta \cdot \text{KL}\!\left[\pi_\theta \,\|\, \pi_{\text{ref}}\right] + c \cdot \mathcal{L}^{\text{VF}}

    其中 \mathcal{L}^{\text{VF}} 是 Critic 的价值函数 MSE loss。

    4.3.3 GRPO:DeepSeek-R1 的群组相对策略优化

    GRPO(Group Relative Policy Optimization)由 DeepSeek-Math 提出、被 DeepSeek-R1 用作主算法,是 PPO 的轻量化变体,省去了 Critic

    思路:对同一个 prompt 采样 G 个 response 组成一个 group,用组内平均奖励作为 baseline 来估计 advantage,从而不需要单独训练 Critic。

    flowchart LR
        P[Prompt q] --> Actor[Actor π_θ]
        Actor --> R1[Response 1]
        Actor --> R2[Response 2]
        Actor --> Ri[...]
        Actor --> RG[Response G]
        R1 --> Rm[Reward / Verifier]
        R2 --> Rm
        Ri --> Rm
        RG --> Rm
        Rm --> Score[r_1, r_2, ..., r_G]
        Score --> Adv[Â_i = r_i - mean r / std r<br/>组内归一化]
        Adv --> Loss[GRPO Loss<br/>clipped + KL]
        Loss --> Actor
    

    GRPO 损失函数

    \hat{A}_i = \frac{r_i – \text{mean}(\{r_1, \ldots, r_G\})}{\text{std}(\{r_1, \ldots, r_G\})}

    \mathcal{L}^{\text{GRPO}}(\theta) = \mathbb{E}\!\left[\frac{1}{G}\sum_{i=1}^G \min\!\left( r_i(\theta) \hat{A}_i,\; \text{clip}(r_i(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_i \right) – \beta \cdot \text{KL}[\pi_\theta \| \pi_{\text{ref}}]\right]

    GRPO vs PPO 对比

    项目PPOGRPO
    训练模型Actor + CriticActor 只
    显存高(4 模型)中(3 模型:Actor + Ref + RM)
    AdvantageA = R – V(学到的)A = (r – \bar{r}) / \sigma_r(组内归一化)
    适合场景奖励稠密 / 步骤型可验证奖励(数学、代码)+ 长 CoT
    代表应用InstructGPT、Llama2-ChatDeepSeek-Math、DeepSeek-R1、Qwen2-Math

    为什么对 R1 有效:数学/代码问题有规则可验证的稀疏奖励(答对/答错),不需要稠密 reward signal,组内相对比较恰好抹平了 RM 噪声。DeepSeek-R1-Zero 甚至直接用规则奖励、跳过 SFT,从 base model 上做 GRPO 训练。

    4.3.4 R1-Zero 训练范式:纯 RL 涌现推理能力

    DeepSeek-R1-Zero 的关键发现:从一个纯 base model 出发,完全不做 SFT,只用规则奖励 + GRPO 训练,模型会自发涌现出长 CoT、self-verify、aha moment 等推理行为。

    flowchart LR
        Base[Base Model<br/>DeepSeek-V3-Base] --> RLZ[纯 GRPO 训练<br/>规则奖励:答案对错 + 格式]
        RLZ --> Zero[R1-Zero<br/>具备推理能力<br/>但可读性差]
        Zero --> Cold[少量 cold-start CoT 数据 SFT]
        Cold --> R1Rl[再次 GRPO]
        R1Rl --> R1[DeepSeek-R1<br/>可读 + 强推理]
        R1 --> Distill[蒸馏到 Qwen Llama]
        Distill --> Small[R1-Distill-Qwen-7B 等]
    

    这套范式打开了一条不依赖海量人类偏好标注的对齐路径,是 2025 推理模型范式(o1/o3、Qwen QwQ、Kimi K1.5、Seed-Thinking)的共同骨架。

    4.3.5 现代 RL 算法谱系

    GRPO 不是终点。2024-2025 业界陆续提出多个改进版,主要围绕三个问题:(1) GRPO 的 advantage 估计有偏差;(2) 长 CoT 的 reward 信号衰减;(3) clip 项的不对称性。

    RLOO(REINFORCE Leave-One-Out, Ahmadian 2024)

    最纯粹的 REINFORCE 变体,不需要 Critic、也不需要 KL 项。对同一 prompt 采 K 个样本,每个样本的 advantage = 自己的 reward − 其余 K-1 个样本的平均 reward:

    \hat{A}_i = r_i – \frac{1}{K-1}\sum_{j \neq i} r_j

    跟 GRPO 几乎一样的思想,但估计无偏(GRPO 用了 std 归一化是有偏的),HuggingFace TRL 库已经把 RLOO 和 GRPO 都列为推荐选项。

    REINFORCE++(Zhihu OpenRLHF 2024)

    在 REINFORCE 基础上加 KL 正则、长度归一化、advantage 标准化等5 个工程化 trick,但保留 Critic-free 的简洁性:

    • token-level KL(不是 sequence-level)
    • 全局 advantage normalization(跨 batch 而不只是组内)
    • mini-batch update

    实务上和 GRPO 性能接近,但显存占用更低。

    Dr. GRPO(DAPO, ByteDance 2025)

    对 GRPO 的两个偏差做了显式修正:

    • 去掉 std 归一化:GRPO 用 \hat{A} = (r – \bar{r}) / \sigma 是有偏的,问题难度大的样本 \sigma 小、advantage 被异常放大。Dr. GRPO 直接用 \hat{A} = r – \bar{r}。
    • 去掉 token-level loss 长度归一化:标准 GRPO 把整条 trajectory 的 loss 除以长度,导致长 CoT 被低估。Dr. GRPO 改成 sequence-level 平均。

    DAPO 在 AIME 2024 上把 Qwen2.5-32B 从 baseline 提到 50%,超越 R1-Distill。

    算法对比总览

    算法CriticKLAdvantageGroup适合场景
    PPO显式(loss 项)A = R – V通用,对齐
    GRPO显式(r – \bar{r}) / \sigma(组内)✅ K=4~16可验证奖励
    RLOO可选r_i – \bar{r}_{-i}(leave-one-out)与 GRPO 等价
    REINFORCE++显式全局 normalized显存敏感
    Dr. GRPO显式r – \bar{r}(无 std)长 CoT 推理
    VAPO✅(轻量)显式GAE + value性能
    flowchart LR
        REINFORCE[REINFORCE 原始<br/>1992] --> PPO[PPO 2017<br/>引入 clip + Critic]
        PPO --> GRPO[GRPO 2024<br/>去 Critic + group baseline]
        REINFORCE --> RLOO[RLOO 2024<br/>leave-one-out]
        REINFORCE --> REINFORCEpp[REINFORCE++<br/>工程化 5 trick]
        GRPO --> DrGRPO[Dr. GRPO / DAPO<br/>去 std 偏差]
        PPO --> VAPO[VAPO 2025<br/>value + GRPO 混合]
    

    实务选择

    • 想快速落地:GRPO(生态最成熟,TRL/verl/OpenRLHF 都支持)
    • 显存紧张:REINFORCE++RLOO
    • 追性能 + 长 CoT:Dr. GRPO / DAPO
    • 复杂 reward + 训练稳:还是 PPO

    4.3.6 Reward Model 类型:PRM vs ORM

    强化学习训推理模型时,奖励信号粒度有两种:

    • ORM(Outcome Reward Model):只看最终答案对不对。简单、cheap、抗 reward hacking 能力强。DeepSeek-R1 用的就是 ORM(数学答案验证、代码 unit test 通过)。
    • PRM(Process Reward Model):每一步 reasoning step 都打分。信号稠密、调试友好,但训练成本高(需要 step-level 标注),且容易被 reward hacking——模型学会”看起来像在推理”而非真正推理。
    flowchart LR
        Q[Question] --> Resp[CoT + Answer]
        Resp -->|ORM| O[只看答案对错<br/>0 or 1]
        Resp -->|PRM| P[每个 step 都打分<br/>0.3, 0.7, 0.5, 1.0]
        O --> Done1[简单 + 抗 hack<br/>但信号稀疏]
        P --> Done2[信号密 + 易解释<br/>但易 hack + 难标]
    

    DeepSeek 在 R1 论文里明确写”PRM 在我们的实验中没有带来收益”——这是个挺反直觉的发现。OpenAI 的 o1 据传也是 ORM 主导。结论:在数学/代码这种答案可验证的领域,ORM 已经够用;只在答案模糊的领域(如写作、咨询)才需要 PRM。

    4.4 DPO 直接偏好优化

    🍤 Direct Preference Optimization

    本章主要介绍 DPO 及其改进算法的详解。

    为什么不把 DPO 归类到 RLHF 章节?

    DPO 在数学上本质是 RLHF(PPO with KL constraint)的闭式解:作者证明在 KL 约束下的最优策略 \pi^* 与 reward r 之间存在确定的对应关系:

    r(x, y) = \beta \log \frac{\pi^*(y \mid x)}{\pi_{\text{ref}}(y \mid x)} + \beta \log Z(x)

    代入 Bradley-Terry 偏好模型后,可以完全消去 reward,得到只依赖策略本身的对比损失:

    \mathcal{L}_{\text{DPO}} = -\mathbb{E}_{(x, y_w, y_l)}\!\left[\log \sigma\!\left(\beta \log \frac{\pi_\theta(y_w \mid x)}{\pi_{\text{ref}}(y_w \mid x)} – \beta \log \frac{\pi_\theta(y_l \mid x)}{\pi_{\text{ref}}(y_l \mid x)}\right)\right]

    所以严格说 DPO 不是脱离 RLHF,而是 RLHF 的一种特殊形式:

    • 共同点:都是把策略 \pi 朝偏好数据指向的方向调整,且都有 KL-to-ref 的隐式约束(\beta 控制)。
    • 不同点:PPO 是在线交互式的 on-policy 优化(涉及采样、reward、Critic);DPO 把整个 RL 过程压缩成了一个对比损失,纯 offline、纯 supervised-like。

    因此本文把 DPO 单独成节,是为了和 PPO 这类显式在线 RL 的方法区分开来,便于工程实现层面的对比;但读者应理解 DPO 在理论上仍是 RLHF 的一种实例化。

    4.4.1 RLHF-PPO 的缺点

    • 两阶段训练带来的信息损失:RLHF 的过程是先利用偏好数据训练一个奖励函数模型,然后再用 PPO 或者其他强化学习算法训练最后的策略。这个过程中如果奖励函数模型学习存在偏差,比如奖励实际上并没有和人类偏好对齐的很好,那么后续的强化学习过程也会导致策略陷入次优。
    • PPO 算法带来的额外训练资源需求:强化学习的训练会伴随着探索和利用(explore and exploit)的过程,一般会较不稳定,PPO 算法在工程实现上利用了很多 trick 去保障训练的稳定和收敛。但是 PPO 仍然引入了 Actor、Critic、Reward 和 Reference 四个模型。在传统强化学习环境中,Actor、Critic 以及 Reference 都是简单的网络实现,reward 是环境自带的人为设计好的,所以并不存在大规模的资源需求;而到了 LLM 这里,所有的模型都是基于 LLM(SFT)模型初始化或者改进的,那么即使在 PPO 训练过程中只有 Actor 和 Critic 需要更新参数,四个模型的推理和训练就需要大量的计算资源,以及四个模型也会带来更多的累积误差。

    DPO vs RLHF-PPO 训练范式对比

    flowchart LR
        subgraph PPO_path["RLHF-PPO 路径"]
            direction TB
            P1[偏好数据 D] --> P2[训练 Reward Model]
            P2 --> P3[在线采样 Actor 生成]
            P3 --> P4[RM 打分]
            P4 --> P5[PPO 更新 Actor + Critic]
            P5 -.循环.-> P3
        end
        subgraph DPO_path["DPO 路径"]
            direction TB
            D1[偏好数据 D<br/>chosen y+ / rejected y-] --> D2[直接对比损失<br/>log σ β log π_θ y+ / π_ref y+ - β log π_θ y- / π_ref y-]
            D2 --> D3[更新 Actor]
        end
    

    DPO 直接用偏好对的对比损失隐式拟合”最优 reward 函数”,省去了显式 RM、Critic 和在线采样三大开销,只保留 Actor + Reference 两个模型;代价是无法利用新生成样本(off-policy),泛化与持续学习能力略弱于 PPO。

    4.4.2 DPO 变体家族

    DPO 提出后业界发现它有几个问题:(1) 依赖 reference model,部署不方便;(2) 容易过拟合到训练集;(3) 长度偏差(倾向生成更长的回答)。一系列变体围绕这些痛点改进:

    IPO(Identity Preference Optimization, Azar 2023)

    DPO 的隐式假设是 Bradley-Terry 偏好模型,对极端偏好对(”完全胜出”)会过拟合。IPO 改成均方损失,避免这个问题:

    \mathcal{L}_{\text{IPO}} = \mathbb{E}\left[\left(\log\frac{\pi_\theta(y_w)}{\pi_{\text{ref}}(y_w)} – \log\frac{\pi_\theta(y_l)}{\pi_{\text{ref}}(y_l)} – \frac{1}{2\beta}\right)^2\right]

    KTO(Kahneman-Tversky Optimization, ETH 2024)

    DPO 必须用成对的 chosen/rejected 数据。KTO 改成单点二分类——每条样本只需要一个 binary 标签(好 / 坏),借鉴行为经济学的前景理论:

    \mathcal{L}_{\text{KTO}}: \text{对 desirable 样本鼓励,对 undesirable 样本惩罚,二者权重不对称}

    意义:在工业场景里”成对偏好数据”难收集,”用户给个赞或踩”很容易拿到。KTO 让这种廉价信号也能用上。

    ORPO(Odds Ratio Preference Optimization, Hong 2024)

    更激进:把 SFT 和偏好优化合并到一个 loss,不需要 reference model:

    \mathcal{L}_{\text{ORPO}} = \mathcal{L}_{\text{SFT}}(y_w) + \lambda \cdot \mathcal{L}_{\text{OR}}, \quad \mathcal{L}_{\text{OR}} = -\log \sigma\left(\log\frac{\text{odds}_\theta(y_w)}{\text{odds}_\theta(y_l)}\right)

    省一个模型 + 省一个训练阶段,是当下”快速对齐”的实务首选。

    SimPO(Simple Preference Optimization, 2024)

    也是 reference-free。把 DPO 的”对数似然比”换成”平均对数似然”(长度归一化),缓解长度偏差:

    \mathcal{L}_{\text{SimPO}} = -\log \sigma\left(\frac{\beta}{|y_w|}\log\pi_\theta(y_w) – \frac{\beta}{|y_l|}\log\pi_\theta(y_l) – \gamma\right)

    引入 reward margin \gamma 推开正负样本距离,效果在多个 benchmark 上超 DPO 4-7 个点。

    家族总览

    方法数据形式需要 refKL 约束长度归一化适合场景
    DPOpairwise隐式通用对齐
    IPOpairwise隐式防止过拟合
    KTOpointwise + binary隐式廉价反馈数据
    ORPOpairwise❌(去掉)SFT + 对齐合并
    SimPOpairwise隐式强对齐 + 控长
    CPOpairwise隐式机器翻译等
    flowchart TD
        DPO[DPO 2023<br/>奠基] --> IPO[IPO<br/>防过拟合]
        DPO --> KTO[KTO<br/>单点标注]
        DPO --> ORPO[ORPO<br/>合并 SFT]
        DPO --> SimPO[SimPO<br/>去 ref + 控长]
        ORPO --> SimPO
    

    该选哪个? 现代实务的经验法则:

    • 数据成对完整且想稳:DPO / SimPO
    • 数据单点二分类(有/无 thumbs up):KTO
    • 一步到位(懒得分 SFT + 对齐两阶段):ORPO
    • DeepSeek-R1 路线(可验证奖励 + 推理):直接用 GRPO,跳过 DPO 家族

    4.5 PEFT 参数高效微调

    🦋 PEFT 方法仅微调少量或额外的模型参数,固定大部分预训练参数,大大降低了计算和存储成本,同时最先进的 PEFT 技术也能做到了与全量微调相当的性能。微调大模型时只训练一小部分参数,而不是训练全量的模型参数,对于下游任务只需要部分参数就可以。

    优点

    • 显存占用少,对硬件资源要求低
    • 训练速度快,耗时更短
    • 更低的存储成本,不同的任务可以共享大部分的权重参数
    • 可能会有更好的模型性能,减轻了过拟合问题

    但是一般有条件的时候还都是全量微调的。

    4.5.1 Prompt Tuning

    Prompt Tuning 概念

    🩼 Prompt Tuning 其实是一个比较广的概念,通过调整 prompt 模板来实现对模型的微调。不同的任务可以定义自己的 Prompt,然后拼接到数据上作为输入,但只在输入层加入 prompt tokens,并且不需要加入到后续的模型层 MLP 中进行调整来解决难训练的问题。固定整个预训练模型参数,只允许将每个下游任务的额外 k 个可更新的 tokens 前置到输入文本中,也没有使用额外的编码层或任务特定的输出层。

    • 对于建模方面:以 T5 为基础,将所有任务转化成文本生成任务,表示为 \Pr_\theta(Y \mid X)。Prompt Tuning 在输入 X 前额外添加一系列特殊 tokens P,输入语言模型生成 Y,即 \Pr_{\theta; \theta_P}(Y \mid [P; X])。其中,\theta 为预训练模型参数,在训练过程被固定;\theta_P 为 prompts 的专有参数,在训练过程被更新优化。通过将输入 X 的 embedding 矩阵 X_e 与 prompts 的 embedding 矩阵进行拼接 [P_e, X_e] 输入 T5 模型,最大化 Y 的概率训练模型,但是只有 prompt 参数被更新。

    4.5.2 LoRA:Low-Rank Adaptation

    LoRA(Low-Rank Adaptation,Hu et al. 2021)是工业界最常用的 PEFT 方法,几乎所有大模型微调框架(PEFT、Axolotl、LLaMA-Factory、Unsloth)都默认支持。

    核心假设:模型 fine-tune 时权重更新 \Delta W 具有低秩特性——即使原矩阵 W \in \mathbb{R}^{d \times k} 很大,\Delta W 可以用两个小矩阵的乘积近似:

    W’ = W + \Delta W = W + B A, \quad B \in \mathbb{R}^{d \times r},\; A \in \mathbb{R}^{r \times k},\; r \ll \min(d, k)

    训练时冻结 W,只学 A, B;推理时把 BA 合并回 W,没有任何额外延迟

    flowchart LR
        X[输入 x] --> WF[W 冻结<br/>原权重]
        X --> A[A 训练<br/>d × r 降维]
        A --> B[B 训练<br/>r × k 升维]
        WF --> Sum((+))
        B --> Sum
        Sum --> Y[输出 y = Wx + BAx]
    

    关键超参数

    • r(rank):典型取 8/16/32/64。r 越大表达力越强、参数越多。
    • alpha:缩放系数,实际 \Delta W = \frac{\alpha}{r} BA。
    • target_modules:选哪些层加 LoRA。典型为 q_projk_projv_projo_proj(attention 全套),也可加上 gate/up/down_proj(FFN)。

    参数量节省:对 Llama-7B 的 q,k,v,o 投影(每个 d=4096),r=8 时:

    \text{LoRA 参数} = 4 \times (4096 \times 8 + 8 \times 4096) = 4 \times 65{,}536 \approx 0.26\,\text{M}

    而全参微调要更新 4 \times 4096^2 \approx 67\,\text{M},LoRA 参数量降至 0.4%

    4.5.3 QLoRA:4-bit 量化 + LoRA

    QLoRA(Dettmers et al. 2023)让 65B 模型在单卡 A100 80G 上 fine-tune 成为可能。三项关键技术:

    • 4-bit NF4 量化:把冻结的 base model 权重量化到 4-bit NormalFloat(针对正态分布优化的 4-bit 数据类型)。
    • Double Quantization:对量化常数本身再做一次量化,进一步压缩。
    • Paged Optimizers:用 CUDA Unified Memory 将优化器状态在显存/内存间分页,避免长序列 OOM。

    训练时:base 用 4-bit 存储、反向时 dequantize 到 BF16 计算;LoRA adapter 保留 BF16 精度。最终效果 ≈ 全参 16-bit 微调。

    4.5.4 LoRA 系列变体

    方法特点适用场景
    LoRA标准低秩分解通用
    QLoRA4-bit base + LoRA大模型 / 单卡
    DoRA分解为 magnitude + direction,效果接近全参追求效果
    PiSSA用 SVD 初始化 A, B 而不是随机加速收敛
    AdaLoRA训练中动态调整每层的 rank不知道 r 怎么选
    LoRA-FA冻结 A、只训 B,再减半省显存
    LongLoRA配 shifted sparse attention 扩展长上下文长文本
    MoE-LoRA一个底座挂多个 LoRA expert,gate 路由多任务、多领域

    实务经验

    • 单卡 24G 微调 7B:用 QLoRA + r=16, alpha=32,target_modules 选 attention 全套,batch_size 1 + gradient accumulation 8。
    • 多领域共用 base:训练多个 LoRA adapter 各占几十 MB,部署时用 PEFT set_adapter 切换或 vLLM 的 multi-LoRA。

    4.6 JUDGE 大模型自动评估

    📔 近年来,随着大模型在智能问答、辅助决策、自动化服务等领域的常用,其输出质量成为影响产品体验和业务效果的关键因素。无论是面向终端用户的交互系统,还是后台支持工具,大模型生成内容都需要持续监控与优化。传统依赖人工评估的方法虽然准确,但难以应对规模化需求和快速迭代。因此,构建高效且可扩展的大模型自动化评估体系已成为行业共识。

    评估方式

    主流的大模型评估方法分为两类:绝对评价与相对评价。绝对评价关注单一结果是否达标,而相对评价则比较不同答案之间优劣。在实际落地中,相对评价能更准确反映局部提升,但存在本质缺陷——无法提供全局量化指标。例如,一个答案优于另一个,并不意味着其足够优秀,两者可能都未达到标准。因此,在产品上线及整体质量把控时,必须引入可量化、可追踪的绝对指标。

    目前常见绝对评分方案包括数字打分或等级(好/中/差)划分。我们最终采用了数值评分制,这不仅便于后续投票聚合,也方便数据统计分析。当然,好/中/差分类也有一定适用性,只是在复杂场景下难以满足精细需求。此外,我们会根据具体任务类型灵活调整评分维度,例如对于问答型任务,会设置”相关性”、”完整性”、”表达清晰度”等多个维度,每个维度独立打分。

    核心挑战与解决思路自动化评测真正决定成效的是评分规则设计与指令表达:

    • 首先要明确各项评分维度及其判定标准
    • 更具挑战的是如何将这些抽象规则转译为让大模型能够理解并执行的 prompt

    这一环节往往是影响自动化一致性的关键瓶颈。我们的流程是先建立调试集,用于验证和修正 prompt 有效性。在每次测试中,通过 CoT 提示,让模型输出详细推理过程,从而判断其是否真正”领会”规则。如果出现偏离,将 AI 生成结果、人工标注参考答案以及所有细则,一同输入到强基座大模型,让它分析原因并给出 prompt 修改建议,再由 AI 生成新的、更易被自身解析和执行的指令模板。这种自我反馈机制显著提高了规则传递效率,同时减少人为表述歧义带来的误差。

    5. Common Models 常见模型

    这章在讲什么:把 1-4 章的所有理论”套”到具体模型上看一遍。BERT / GPT / Llama / GLM / Qwen / DeepSeek / MoE 各家是怎么选 attention、怎么选 norm、用什么后训练方案。

    看完这章你应该能在面试里说出”为什么 Llama2 比 Llama1 加了 GQA”、”V2 到 V3 DeepSeek 改了什么”这类问题。

    5.1 BERT 及变体

    5.1.1 BERT

    🚣♂️ Bidirectional Encoder Representation from Transformers,encoder-only。BERT 主要是用来替代 Word2Vec 的预训练模型,通过 MLM 和 NSP 两大预训练任务学习表征,对于下游任务加上一个 layer 微调即可。

    👓 BERT Embedding

    BERT 的输入的编码向量(长度是 512)是 3 个嵌入特征的单位和,这三个词嵌入特征是:

    1. Position Embedding:位置嵌入是指将单词的位置信息编码成特征向量,位置嵌入是向模型中引入单词位置关系的关键的一环;BERT 直接去训练了一个 position embedding,给每个位置词一个随机初始化的词向量,再训练
    2. Token Embedding:上图的示例中 ‘playing’ 被拆分成了 ‘play’ 和 ‘ing’ 的 token
    3. Segment Embedding:用于区分两个句子,例如 B 是否是 A 的下文(对话场景,问答场景等)。对于句子对,第一个句子的特征值是 0,第二个句子的特征值是 1

    5.2 PaLM 系列

    5.2.1 PaLM1

    Pathways Language Model

    论文:PaLM: Scaling Language Modeling with Pathways

    • 模型结构:PaLM 使用标准的 Transformer 模型架构,只设置 Decoder-only,并做了以下修改:
      • SwiGLU 激活:FFN 部分更换为 SwiGLU 的结构
      • 并行层:标准的序列化表述为 y = x + \text{MLP}(\text{LayerNorm}(x + \text{Attention}(\text{LayerNorm}(x))));PaLM 使用并行化的结构:y = x + \text{MLP}(\text{LayerNorm}(x)) + \text{Attention}(\text{LayerNorm}(x))
      • MQA、RoPE、共享输入输出 embedding、去掉 dense 层和 LN 中的偏差项(提升训练稳定性)
      • 使用 SentencePiece 训练得到 256K 大小的词表,对于数字切分总是切分为单个(例如,”123.5 → 1 2 3 . 5″)
    • 训练数据集:(待补充)

    5.3 GPT 系列

    5.3.1 GPT1

    🤵♂️ Generative Pre-Training

    论文:Improving Language Understanding by Generative Pre-Training

    ⛹️ 模型结构

    Transformer decoder-only 12 层,具体细节跟 transformer 一样,但是位置编码是可训练的。

    原 transformer 的 decoder 包含 2 个 attention:

    • cross-attention (k, v 来自 encoder,q 来自 decoder)
    • mask multi-head attention

    GPT 只用了 mask multi-head attention。

    5.4 LLaMA 系列

    🕐 Open and Efficient Foundation Language Models,目前主流的开源大模型 (Dense) 基本上都是 LLaMA 架构,并在此基础上做各种改动。

    5.4.1 LLaMA1

    🍱 论文:LLaMA: Open and Efficient Foundation Language Models

    模型结构:相比 GPT 做出来如下改动:

    • 为了增强训练稳定性,采用 pre-RMSNorm 作为层归一化方法
    • 为了提高模型性能,采用 SwiGLU 作为激活函数
    • 为了更好地建模长序列数据,采用 RoPE 作为位置编码
    • 为了更好地编码数据,Llama-1 使用 BPE 算法进行分词,具体由 sentencepiece 进行实现。值得注意的是,Llama-1 将所有数字分解为单独的数字,并对未知的 UTF-8 字符回退到字节进行分解,词表大小为 32k

    👰♂️ 训练方式

    基础的自监督学习模型,没有经过任何形式的特定任务微调:

    • Llama-1 在公布的技术报告中详细描述了使用 AdamW 优化器的机器学习模型的具体训练配置。AdamW 是对 Adam 优化器的改进,可以更有效地处理权重衰减,从而提高训练的稳定性。\beta_1 和 \beta_2 参数的选择影响训练过程的收敛行为和稳定性
    • Llama-1 描述的余弦学习率调度是一种有效的技术,用于在训练期间调整学习率,通过逐渐减少学习率在某些情况下可以导致更好的收敛。实施 0.1 的权重衰减和 1.0 的梯度裁剪是预防过拟合和确保数值稳定性的标准做法
    • warmup 是一种策略性方法,旨在训练过程初期稳定训练动态。根据模型大小调整学习率和 batch 是一种优化资源分配和效率的实用方法,有可能提高模型性能

    5.5 GLM 系列

    5.5.1 GLM1

    论文:GLM: General Language Model Pretraining with Autoregressive Blank Infilling

    🤗 模型结构

    GLM1 是 prefix-decoder 结构的 Transformer(实际上就是 transformer decoder,只不过通过特殊的 mask 实现了 prefix 部分双向 attention,后面的部分单向 attention),然后做了一些改动:

    • Pre Deep Norm
    • 用一个单层线性层用来 output token 预测
    • ReLU → GeLU 激活函数

    🤗 GLM 训练目标 🛋️ 自回归填空这个任务包含了下面两个思想:

    • 自编码思想:在输入文本中,随机删除连续的 tokens
    • 自回归思想:顺序重建连续 tokens,在使用自回归方式预测缺失 tokens 时,模型既可以访问 corrupted 文本,又可以访问之前已经被预测的 spans

    5.6 Qwen 系列

    🧜♀️ 2 月 24 日修改

    5.6.1 Qwen1

    论文:QWEN TECHNICAL REPORT 👨⚖️ 模型结构

    基于 Transformer 改进,类似 LLaMA 结构:

    • tiktoken BPE,选择词汇表 cl100k_base 作为起点扩充词汇表,同时将数字拆分为单个数字,最终词汇表大小约为 152K
    • Untied Embedding:Input embedding 和 Output embedding 不进行权重共享,是单独的两个权重矩阵,但是代价是增加了内存消耗,不过可以明显提升模型的性能

    🤷♂️ 模型训练

    • 采用标准的自回归语言模型训练目标
    • 训练时上下文长度为 2048,为了构建批次数据,对文本内容进行随机打乱及合并,再将其截断到指定长度

    5.7 Deepseek系列

    4.7 Deepseek系列 4月27日修改

    拓展阅读:

    • 💾 DeepSeek Engram 深度解读:当大模型学会查字典而不是硬背书
    • ⛰️ DualPath 深度解读:DeepSeek 如何榨干每一块闲置网卡的带宽

    5.7.1 Deepseek-V1

    论文:DeepSeek LLM: Scaling Open-Source Language Models with Longtermism

    模型结构:

    • 基于 LLaMA,采用 Pre-RMSNorm、SwiGLU 和 RoPE,67B 模型使用 GQA 优化推理成本,调整了层数
    • 使用 BBPE 算法进行分词,训练了约 24GB 的语料库,词汇表大小为 102400

    SFT 训练:

    • 收集了 1.5M 的中英文指令数据
    • 微调 7B 模型 4 epochs,67B 模型 2 epochs,学习率分别为 1e-5 和 5e-6

    DPO 训练:

    • 用自己的 Deepseek Chat Models 产生 responses,进而构建偏好对
    • Batchsize 512,lr 5e-6

    5.7.2 DeepSeek-V2

    论文:DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model

    236B 总参数 / 21B 激活的 MoE 模型,两项核心创新让推理成本下降 ~93%:

    1. MLA(Multi-head Latent Attention)

    把 KV 投影到一个低维 latent 向量 c^{KV} \in \mathbb{R}^{d_c}(d_c \approx d/14),KV Cache 只存 c^{KV}。具体见 1.3.3 MHA → MQA → GQA → MLA 演进

    为了与 RoPE 兼容,MLA 把 Q/K 拆成 content + RoPE 两部分:

    Q = [Q^{\text{NoRoPE}}; Q^{\text{RoPE}}], \quad K = [K^{\text{NoRoPE}}; K^{\text{RoPE}}]

    只对 RoPE 部分做位置旋转,content 部分继续走低秩 latent。

    2. DeepSeekMoE 架构

    • 细粒度 expert:把每个 expert 切得更小(如 64 → 256 个),路由更精细。
    • 共享 expert(shared expert):少量 expert 始终激活,承载通用知识;其余是 routed expert。
    • 负载均衡 loss:传统 GShard 风格 aux-loss + device-level balance。

    5.7.3 DeepSeek-V3

    论文:DeepSeek-V3 Technical Report

    671B 总参数 / 37B 激活,用 2048 张 H800 训练 ~2 个月、总成本约 $5.6M——刷新了开源模型的性价比纪录。

    关键创新

    1. Auxiliary-Loss-Free Load Balancing:放弃辅助 loss,改用一个bias 修正项动态调整每个 expert 的路由分数——既保证负载均衡又不引入额外训练目标导致的性能损失。
    2. Multi-Token Prediction (MTP):训练时让模型同时预测下一个和下下个 token,提升数据效率;推理时可作为投机解码的 draft head,加速 1.8×。
    3. FP8 训练:自研 FP8 混合精度训练框架,吞吐量大幅提升、显存下降。
    4. DualPipe 流水线并行:bidirectional pipeline,前向 + 反向重叠通信和计算,几乎消除 pipeline bubble。
    flowchart TD
        V1[DeepSeek-V1<br/>67B Dense] --> V2[DeepSeek-V2<br/>236B/21B MoE + MLA]
        V2 --> V3[DeepSeek-V3<br/>671B/37B MoE<br/>Aux-Free LB + MTP + FP8]
        V3 --> R1Zero[DeepSeek-R1-Zero<br/>纯 GRPO 训练]
        V3 --> R1[DeepSeek-R1<br/>cold-start + GRPO]
        R1 --> Distill[R1-Distill 系列<br/>Qwen / Llama 蒸馏]
    

    5.7.4 DeepSeek-R1:推理模型

    论文:DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning

    R1 是基于 V3-Base 训练的推理模型,开创了”纯 RL 涌现推理”的新范式。

    训练流程

    1. R1-Zero:直接对 V3-Base 跑 GRPO + 规则奖励(数学/代码答案对错 + 输出格式 <think>...</think><answer>...</answer>),不做任何 SFT。结果:AIME 2024 从 V3-Base 的 ~30% 涨到 71%,但输出可读性差、有时混杂多语言。
    2. 冷启动 SFT:用少量人工写的 CoT 样本对 V3-Base 做 SFT,让模型学会”标准的思考格式”。
    3. 再次 GRPO:在冷启动模型上继续 RL,加入语言一致性奖励。
    4. 拒绝采样 + 再 SFT:用上一阶段的模型采样 600K 样本,加上 200K 通用对话数据做 SFT。
    5. 第二轮 RL:在所有场景上做最终 RL,加入 helpfulness/harmlessness 偏好奖励。

    详细 GRPO 算法见 4.3.3 GRPO:DeepSeek-R1 的群组相对策略优化4.3.4 R1-Zero 训练范式:纯 RL 涌现推理能力

    蒸馏开源:用 R1 生成的 800K 推理数据 SFT 到 Qwen2.5 和 Llama3 系列,得到 R1-Distill-Qwen-{1.5B, 7B, 14B, 32B}、R1-Distill-Llama-{8B, 70B}——证明强推理能力可以从大模型蒸馏到小模型而不需要 RL

    5.8 MOE 系列

    5.8.1 GShard

    论文:GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding

    GShard 把 Transformer 中的 FFN 层替换为稀疏激活的 MoE 层,每层包含若干 expert(FFN 子网络)和一个轻量的 gate 路由器。对每个 token,gate 根据其表示从所有 expert 中选出 top-k 个(GShard 使用 top-2)进行计算,并按门控权重加权求和:

    y = \sum_{i \in \text{TopK}(g(x))} g_i(x) \cdot E_i(x)

    其中 E_i 是第 i 个 expert,g_i(x) 是 gate 输出的归一化权重。配合 expert capacity(每个 expert 最多处理的 token 数)和辅助负载均衡 loss,GShard 在百亿到千亿参数规模上实现了”参数量上去、单次计算量不变”的稀疏扩张范式,是后续 Switch Transformer、Mixtral、DeepSeek-MoE 等工作的开创性。

    GShard MoE 层结构与 token 路由示意

    flowchart TD
        X[输入 token x] --> G[Gate 路由器<br/>linear + softmax]
        G --> Score[g_1, g_2, ..., g_N<br/>对 N 个 expert 的分数]
        Score --> TopK[选 Top-2<br/>g_i1, g_i2]
        TopK --> E1[Expert i1<br/>FFN]
        TopK --> E2[Expert i2<br/>FFN]
        X --> E1
        X --> E2
        E1 --> Sum[加权求和<br/>g_i1·E_i1 x + g_i2·E_i2 x]
        E2 --> Sum
        Sum --> Y[输出 y]
    
        Bal[Auxiliary Load-Balance Loss<br/>鼓励每个 expert 被均匀分配] -.约束.-> G
        Cap[Expert Capacity<br/>超额 token 被 drop 或 overflow] -.约束.-> TopK
    

    关键设计:

    • 稀疏激活:每个 token 只触发 2/N 个 expert,前向计算量 ≈ 一个常规 FFN,但总参数量 ×N。
    • Top-k 路由:k=1 是 Switch Transformer,k=2 是 GShard / Mixtral,k=8 是 DeepSeek-V3。k 越大表达力越强,通信代价越高。
    • 负载均衡:辅助 loss 防止”所有 token 都路由到几个明星 expert”导致其余 expert 退化。
    • Expert 并行:不同 expert 切到不同 GPU(EP, Expert Parallel),跨卡 all-to-all 通信交换 token。

    5.8.2 Mixtral:开源 MoE 的代表作

    Mixtral 8x7B(Mistral 2023) 是开源界第一个证明 MoE 在 LLM 上 work 的模型。架构:

    • 8 个 expert,每层 top-2 路由
    • 总参数量 47B,但每个 token 只激活 ~13B
    • 推理速度 ≈ 13B dense 模型,效果 ≈ 70B dense 模型

    后续 Mixtral 8x22B(141B 总参 / 39B 激活)继续推高 MoE 在开源界的上限。但 Mixtral 设计相对简单(继承自 Switch),DeepSeek-MoE 之后的”细粒度 + shared expert”才是真正的工业级精雕。

    5.9 Mamba / SSM 等非 Transformer 架构

    Transformer 不是唯一答案。2023-2024 涌现一批基于状态空间模型(SSM)的架构,在长上下文、推理速度上有结构性优势。这章简要梳理。

    5.9.1 SSM 基础与 Mamba

    状态空间模型(State Space Model)源自经典控制理论,把序列建模看作连续动力学的离散化:

    h'(t) = A h(t) + B x(t), \quad y(t) = C h(t)

    离散化(zero-order hold):

    h_t = \bar{A} h_{t-1} + \bar{B} x_t, \quad y_t = C h_t

    跟 RNN 很像——状态 h_t 是固定大小的”压缩历史”,所以每步推理复杂度 O(1)、内存 O(1),不需要 KV Cache。

    Mamba(Gu & Dao 2023)的关键创新:让 A, B, C 不再是固定矩阵,而是输入依赖(selective SSM)——根据当前 token 动态决定要”记住”什么、”遗忘”什么:

    \bar{A}_t = f(x_t), \quad \bar{B}_t = g(x_t)

    flowchart LR
        subgraph Transformer["Transformer"]
            T1[全量 attention<br/>O n² 内存] --> T2[KV Cache 越来越大]
        end
        subgraph Mamba["Mamba / SSM"]
            M1[固定大小状态 h] --> M2[O 1 每步推理]
            M1 -.RNN-like.-> M1
        end
    

    优劣对比

    维度TransformerMamba
    推理复杂度O(n) 每 token,但有 KV CacheO(1) 每 token
    长上下文显存线性增长常数
    训练并行度中(需要 selective scan)
    短序列效果略弱
    长序列效果(>32K)注意力稀释
    ICL 能力弱(缺 induction head)

    5.9.2 Hybrid 架构:把 SSM 和 Transformer 混搭

    纯 Mamba 在 ICL、复杂推理上不如 Transformer。所以业界主流是混合架构——大部分层用 SSM 占便宜,少数层留 attention 撑 ICL:

    • Jamba(AI21):1:7 attention:Mamba 比例,52B 参数 / 12B 激活
    • Zamba(Zyphra):每 6 层 Mamba 配 1 层共享 attention
    • Qwen3.5-Next(2025):Qwen 系列首次引入 Gated Delta Network(SSM 变体),在长上下文场景上速度大幅提升

    5.9.3 RWKV:另一条 RNN-like 路线

    RWKV(Receptance Weighted Key Value, 彭博 2021-2024) 是另一个非 Transformer 路线,用 R/W/K/V 四个状态量构造线性注意力,保留 RNN 的 O(1) 推理。

    • 训练:可以并行(time-mix + channel-mix)
    • 推理:纯 RNN 模式,每步 O(1)
    • RWKV-7(2025):升级到 dynamic state evolution,在多 benchmark 上接近同尺寸 Transformer

    RWKV 是 Linux Foundation AI 项目,社区驱动,与 Mamba 是非 Transformer 的两大开源代表。

    5.10 多模态模型(VLM)

    大模型的另一条主线——把文本之外的输入(图、视频、音频)接进来。视觉语言模型(VLM) 是迄今最成熟的多模态分支。

    5.10.1 经典对齐路线:CLIP

    CLIP(OpenAI 2021) 是多模态的开创性。架构:

    • 一个 image encoder(ViT)+ 一个 text encoder(Transformer)
    • 用 4 亿 image-text 对做对比学习:匹配的图文对在嵌入空间靠近,不匹配的远离
    flowchart LR
        Img[图片] --> IE[Image Encoder<br/>ViT] --> Iv[图像向量]
        Txt[文本] --> TE[Text Encoder] --> Tv[文本向量]
        Iv --> Sim[对比学习<br/>InfoNCE loss]
        Tv --> Sim
    

    CLIP 不直接生成,但它的 image encoder + 跨模态对齐空间成了后续所有 VLM 的标配基础设施。

    5.10.2 LLaVA / Qwen-VL:连接器范式

    主流 VLM 都是”CLIP image encoder + 投影层 + LLM”

    flowchart LR
        Img[图片] --> VE[Vision Encoder<br/>CLIP-ViT 或 SigLIP]
        VE --> Proj[Projector / Connector<br/>2-layer MLP 或 Q-Former]
        Proj --> LLM[LLM<br/>Llama / Qwen]
        Txt[文本 prompt] --> LLM
        LLM --> Out[文本输出]
    

    不同模型在三处做差异化:

    • Vision Encoder:CLIP-ViT-L、SigLIP、InternViT 等
    • Connector
      • Linear / MLP(LLaVA 1.5):最简单,把视觉 token 投影到 LLM embedding 空间
      • Q-Former(BLIP-2):用一组 query token “压缩” 视觉特征,灵活但训练复杂
      • Resampler / Perceiver(Flamingo):跨注意力机制提取
    • 训练策略:通常分两阶段——先冻结 LLM 训 connector(对齐),再全参/LoRA 微调

    代表模型

    模型Vision EncoderConnectorLLM
    LLaVA 1.5CLIP-ViT-L2-layer MLPVicuna
    LLaVA-NeXTCLIP-ViT-LMLPLlama 3
    Qwen-VLCLIP-ViT bigGSingle Cross-AttnQwen
    Qwen2-VLCustom ViT + NaViTMLPQwen2
    InternVL2InternViT-6BMLPInternLM
    MiniCPM-VSigLIP-400MResamplerMiniCPM

    5.10.3 原生多模态:从一开始就联合训练

    LLaVA 范式是”先训好 LLM 再接图片”。原生多模态(natively multimodal) 是更彻底的做法——预训练时就联合处理图、文、音、视频:

    • GPT-4o(2024):第一个公开的原生多模态商用模型
    • Gemini 系列:从 1.0 开始就是原生多模态
    • Seed1.5-VLQwen2.5-VLLlama 4:开源界跟进

    技术上的关键挑战:

    • 统一 tokenizer:图片切成 patch token、视频切帧 + patch、音频 mel-spectrogram → 都得有自己的 special token
    • 位置编码:图像/视频需要 2D/3D 位置编码(Qwen2-VL 的 MRoPE)
    • 训练数据平衡:图文对、纯文本、视频、OCR、视觉问答的配比

    5.10.4 视觉推理:MathVista / GUI Agent

    2024-2025 VLM 的两个主战场:

    1. 视觉推理(Visual Reasoning)

    让模型不仅”看懂图”,还要”看着图做推理”。代表 benchmark:

    Benchmark题型关键能力
    MMMU跨学科大学题 + 图多学科理解 + 推理
    MathVista数学题配图视觉数学推理
    ScienceQA中小学科学题 + 配图教学场景
    MMVet综合视觉问答OCR + 计数 + 空间关系
    CharXiv学术 chart 理解数据图表分析

    难点不是 OCR——而是把图里的视觉信号转成可推理的语义:空间关系(左/右、上/下、内/外)、数量、几何形状都要正确识别才能往下推。

    2. GUI Agent(屏幕智能体)

    让模型”看屏幕、点按钮、填表单”。代表工作:

    • CogAgent(清华 2023):第一代 GUI Agent 基础模型
    • SeeClick:以 grounding 为核心,”点击登录按钮” → 输出坐标
    • Qwen2-VL / Qwen2.5-VL:通用 VLM 但 grounding 能力强
    • Claude Computer Use(Anthropic 2024):商用产品,能直接操作电脑
    • OpenAI Operator(2025):浏览器 agent
    flowchart LR
        User[用户指令] --> VLM
        Screen[屏幕截图] --> VLM[VLM Agent]
        VLM --> Action[输出动作 click / type / scroll]
        Action --> OS[操作系统/浏览器执行]
        OS --> Screen
    

    关键技术

    • Grounding:把”登录按钮”映射到 (x=320, y=480) 精确坐标
    • Set-of-Marks:截图上叠加编号框,让模型按编号操作,避免直接预测坐标
    • Action Space:click / type / scroll / drag + 应用特定动作
    • 错误恢复:识别页面异常并重试

    评估 benchmark:WebArena / VisualWebArena、OSWorld、AndroidWorld、ScreenSpot。

    实务现状(2025):简单任务能 work(订票、查邮件),长程任务成功率仍 < 50%——主要 bottleneck 是多步规划 + 错误恢复,跟第 8 章 Agent 的核心难题完全一致。

    6. Compression 模型压缩

    这章在讲什么:训好的模型动辄几十上百 G,落到 4090、手机、推理服务上需要瘦身。四条压缩路线:量化(最常用)、剪枝、知识蒸馏、低秩分解。

    压缩是工程题,效果好坏很看具体数据和部署目标,所以这章重点在”知道有哪些路线、什么时候用哪个”。

    模型越训越大,部署成本越来越烫——压缩技术应运而生。本章四条主线:

    • 量化——把 FP32 砍到 INT8/INT4,工业界最常用。
    • 剪枝——找冗余权重砍掉。
    • 知识蒸馏——大教小,DeepSeek-R1 蒸馏到 Qwen 就是这套。
    • 低秩分解——LoRA 也属于这个家族。

    6.1 Quantization 模型量化

    6.1.1 量化简介

    量化的核心动作就一个:把权重从 FP32/FP16 这种高精度浮点,近似成 INT8/INT4 这种低位数整数。换来三件事:

    • 模型变小:FP16 → INT8 直接砍一半,FP16 → INT4 砍 4 倍。
    • 推理省内存:权重小了,KV Cache 和激活都跟着省。
    • 推理变快:很多硬件(如 H100、Apple Silicon)对低精度整数运算有专门加速单元。

    代价是精度损失。各种量化算法的差异,本质就是”怎么在不重训的前提下,把精度损失压到最小”。

    常用的数据类型

    • FP32:32位浮点数,是最常用的高精度表示方式
    • FP16:16位浮点数,数值范围比FP32小,但占用内存较少
    • BF16:16位截断的FP32,增加指数位,数值范围更广,常用于深度学习
    • INT8:8位整数,位数仅为FP32的1/4,适用于模型参数的数据范围映射
    • INT4:4位整数,进一步减少位数,适用于极端资源受限的场景
    • 二值网络(Binary Network):1位二值网络,参数只能取0或1,计算效率极高但精度损失较大
      工业界目前最常用的量化位数是8比特,低于8比特的量化被称为低比特量化。1比特是模型压缩的极限,可以将模型压缩为1/32,在推理时也可以使用高效的XNOR和BitCount位运算来提升推理速度

    量化对象

    • 权重 (Weight):最常见的目标,因为模型 deploy 时权重是静态的,只需要量化一次。
    • 激活值 (Activation):动态生成、且占大头。但激活分布有 outlier(少数维度数值极大),简单量化会损失严重。
    • KV Cache:长上下文时 KV Cache 比权重还大,专门的 KV Cache 量化(如 INT8/FP8)是 vLLM 等推理引擎的标配。

    对称 vs 非对称量化

    把浮点数 x 映射成整数 q 的基本公式:

    q = \text{round}(x / s + z), \quad x \approx s \cdot (q – z)

    • 对称量化:零点 z = 0,量化范围对称于零。简单、推理快。
    • 非对称量化:z \neq 0,对偏置分布(如激活值)拟合更紧。

    Per-tensor / Per-channel / Per-group

    scale s 怎么算决定了精度上限:

    • Per-tensor:整层一个 s,最粗。
    • Per-channel:每个 output channel 一个 s。
    • Per-group:每 g 个权重一个 s(如 g=128)。GPTQ/AWQ 都用这种,是精度 vs 体积的好折中。

    6.1.2 QAT vs PTQ

    按”量化在训练前还是训练后”分两大类:

    类别训练成本精度工程友好度代表方法
    PTQ(Post-Training Quantization)0(不重训)中-高GPTQ、AWQ、SmoothQuant
    QAT(Quantization-Aware Training)接近重训LLM-QAT、PEQA

    LLM 时代几乎都用 PTQ——重训太贵了。QAT 主要还在 CV 模型上常见。

    6.1.3 LLM.int8():发现”异常值”问题

    Dettmers 2022 的关键发现:LLM 的某些激活值上有 outlier——0.1% 的特征维度数值是其余的 100×。用普通 INT8 量化这些维度会全军覆没。

    做法:混合精度——把 outlier 维度保留 FP16,其余 99.9% 维度走 INT8。bitsandbytes 库的 load_in_8bit=True 就是这套,简单粗暴但有效。

    6.1.4 GPTQ:基于 Hessian 的逐层量化

    GPTQ(Frantar 2022)的核心思路:对每一层的权重矩阵 W,逐列量化每个权重时,利用 Hessian 矩阵补偿剩余列的损失:

    W_{q,j} = \text{quant}(w_j), \quad \delta = w_j – W_{q,j}, \quad W_{:, j+1:} \mathrel{-}= \frac{H^{-1}_{j, j+1:}}{H^{-1}_{j,j}} \delta

    简单说:量化第 j 列产生的误差,用 Hessian 的方向信息摊到后面没量化的列里,让总误差最小化。

    flowchart LR
        W[权重矩阵 W] --> Cal[Calibration 数据<br/>~128 条文本]
        Cal --> H[计算 Hessian H]
        W --> Loop[for 每一列 j:]
        H --> Loop
        Loop --> Q[量化 w_j → q_j]
        Q --> Err[误差 δ = w_j − q_j]
        Err --> Comp[把 δ 摊到 j+1..n 列]
        Comp --> Loop
    

    特点:

    • INT4 量化精度损失通常 < 1%
    • 需要 ~128 条 calibration 数据
    • 量化 70B 模型约 4 小时(A100)
    • 主要用于权重量化,不擅长激活

    6.1.5 AWQ:激活感知的权重量化

    AWQ(Lin 2023)的关键洞见:权重的重要性不均匀。少数与”大激活”对齐的权重通道更敏感——量化它们会严重伤害精度。

    AWQ 的做法:

    1. 用 calibration 数据观察哪些 input channel 的激活值大(”显著通道”)。
    2. 对显著通道的权重做逐通道缩放(per-channel scaling),把这部分权重的量化误差转移到激活上(激活可以用更高精度)。
    3. 然后再做 INT4 量化。

    \text{Q}(W \cdot \text{diag}(s)) \cdot (\text{diag}(s)^{-1} \cdot X)

    效果:

    • INT4 精度比 GPTQ 略好
    • 不需要反向传播(GPTQ 需要 Hessian),量化更快
    • 与 marlin/exllama 等高效 kernel 配合,推理吞吐 1.5-2× 于 GPTQ

    6.1.6 SmoothQuant:把激活的 outlier 转嫁到权重

    SmoothQuant(Xiao 2022)专攻 W8A8(INT8 权重 + INT8 激活)。核心思路:激活的 outlier 难量化,权重的分布比较均匀——那就在数学上等价地把激活的 outlier “转移”到权重上

    Y = (X \cdot \text{diag}(s)^{-1}) \cdot (\text{diag}(s) \cdot W) = X’ \cdot W’

    通过选择合适的 s(per-channel),让 X’ 变平滑、W’ 略不均匀——但二者都能用 INT8 量化了。

    6.1.7 FP8 训练与推理

    FP8 是 NVIDIA H100 引入的新数据类型,配合 Transformer Engine 库使用。两种格式:

    • E4M3(4 位指数 + 3 位尾数):动态范围小、精度高,适合前向激活和权重
    • E5M2(5 位指数 + 2 位尾数):动态范围大、精度低,适合梯度

    DeepSeek-V3 是第一个全程 FP8 训练的开源大模型——671B 参数能在 2000 张 H800 上 2 个月训完,FP8 功不可没。但 FP8 训练对数值稳定性要求高,需要 fine-grained quantization(per-block 而不是 per-tensor)。

    6.1.8 量化方法对比与选型

    方法精度位数量化对象是否需 calib工业部署
    LLM.int8()W8A8(mixed FP16)W + Abitsandbytes 库
    GPTQINT4/INT3W only✅ ~128主流 INT4 选项
    AWQINT4W only✅ ~128vLLM 推荐
    SmoothQuantW8A8W + A服务器推理
    QLoRANF4W (训练时)单卡微调
    FP8(H100/H200)FP8W + A + grad训练 + 推理
    GGUF/llama.cppINT2~INT8 多档W only本地/CPU 部署

    该选哪个?

    • 服务器部署,A100/H100:AWQ(精度好 + vLLM 加速好)
    • 个人电脑/Apple Silicon:GGUF(llama.cpp 生态)
    • 单卡微调 70B+:QLoRA
    • 训练新模型:FP8(如果有 H100/H200)
    • 快速试一下:bitsandbytes(一行代码 load_in_4bit=True

    6.2 Pruning 模型剪枝

    6.2.1 剪枝简介

    剪枝(pruning)跟量化是两条独立路线:

    • 量化减少每个权重的精度(FP32 → INT4)
    • 剪枝减少权重的数量——把”不重要”的连接直接置零或删掉

    剪枝在 CV 领域已经研究了十几年(深度学习兴起时的”彩票假设”),但在 LLM 上的工业应用没有量化那么成熟——因为大模型权重已经被高度训练,”冗余”没有那么多,激进剪枝精度损失大。2023 之后才出现 LLM 友好的剪枝算法(Wanda、SparseGPT)。

    剪枝粒度的层级

    flowchart LR
        Fine[Fine-grained<br/>单个权重] --> Vec[Vector-wise<br/>整列/整行]
        Vec --> NM["N:M sparse<br/>(2:4)"]
        NM --> Struct[Structured<br/>整个 head / layer]
    
        Fine -.稀疏度高.-> Fine
        Struct -.推理友好.-> Struct
    
    粒度稀疏度推理加速精度损失
    Unstructured(单权重)90%+难(需要特殊 kernel)
    N:M 稀疏(每 M 个里有 N 个非零)~50%NVIDIA Ampere+ 原生加速
    Vector-wise(整行/整列)50-80%较易中-大
    Structured(整个 head/layer)30%最易

    主流剪枝方法

    • Magnitude Pruning:最简单——按权重绝对值排序,删最小的 X%
    • Wanda(NeurIPS 2023):在 magnitude 基础上乘以激活值范数 W \cdot \|X\| 作为评分,无需重训练,50% 稀疏度精度损失 < 2%
    • SparseGPT(Frantar 2023):基于 Hessian 的逐层剪枝,跟 GPTQ 同源思路,60-70% 稀疏度精度损失可控

    6.2.2 剪枝流程

    经典剪枝有三种流派:

    flowchart TD
        A[原始稠密模型] --> P1[Train then prune<br/>训练后剪枝]
        A --> P2[Prune at init<br/>初始化时剪枝]
        A --> P3[Train + Prune iterative<br/>训练中迭代剪枝]
        P1 --> FT[微调恢复]
        P2 --> Sparse[直接稀疏训练]
        P3 --> Mature[Lottery Ticket 等]
    
    1. 训练后剪枝(PTP):训好的模型上剪 → 用少量数据微调 → 得到稀疏模型。LLM 主流——Wanda / SparseGPT 都是这条路。
    2. 初始化剪枝:训练前直接稀疏化(SNIP、GraSP),跳过完整训练。CV 上有应用,LLM 上少见。
    3. 迭代剪枝 + 重训:经典彩票假设(Lottery Ticket Hypothesis)的路线——剪一点、训一点、再剪。计算成本高,LLM 上几乎不用。

    6.2.3 LLM 剪枝的工业实务

    为什么 LLM 剪枝远不如量化普及?

    • LLM 的稠密权重已经被充分训练,激进剪枝(>50%)必然导致精度大降
    • 不规则稀疏(unstructured)在 GPU 上不一定加速——cuBLAS 对稠密矩阵已经极致优化
    • 量化(4-bit)能拿到 4× 体积压缩 + 接近无损,效果好得多

    真正用上的场景

    • 2:4 稀疏 + INT4(双管齐下):DeepSeek 等团队的实验性方案
    • 结构化剪枝(删整个 head / layer):模型蒸馏的前置步骤
    • MoE 中的 expert 剪枝:用频率最低的 expert 直接删除——降模型大小、保推理速度

    业内共识:优先做量化,剪枝作为补充优化

    6.3 Knowledge Distillation 知识蒸馏

    6.3.1 知识蒸馏简介

    蒸馏的思路很直观:用大模型当老师、小模型当学生,让小的学着模仿大的输出。学生模型参数少、推理快,老师的能力被”压缩”到了一个更经济的体积里。

    按”能拿到老师内部信息多少”分两类:

    • Blackbox 蒸馏:只能看到老师的最终输出(如 GPT-4 这类闭源模型只能调 API),学生用老师生成的样本做 SFT。
    • Whitebox 蒸馏:能拿到老师的参数、中间层激活、输出分布(开源大模型才行),学生不仅学最终答案,还学中间过程,效率高得多。

    完整算法三件套:知识(学什么)、蒸馏算法(怎么传)、师生架构(用什么模型)。常用数据是老师的预训练数据,也可以另准备一批专门用于蒸馏的样本。

    6.3.2 白盒知识蒸馏

    按”学老师的什么”再分三种:

    • Response-based:学最终 logits/概率分布。最经典——Hinton 2015 的 KD 就是这种,用温度软化老师的 softmax 然后让学生匹配。
    • Feature-based:学中间层的 hidden state、attention map。信息更丰富,对齐难度高。
    • Relation-based:学不同样本间的关系(如对比学习里的距离矩阵)。适合学结构知识。

    DeepSeek-R1 蒸馏案例:拿 R1 生成 800K 条带 reasoning 过程的数据,对 Qwen2.5 / Llama3 做 SFT,得到 R1-Distill 系列。这是典型的 Response-based + 在线数据生成。

    6.4 Low-Rank Factorization 低秩分解

    这里直接参考 4.5 PEFT 参数高效微调 中关于低秩分解的内容即可。

    7. Application 大模型应用

    这章在讲什么:把 5 章里那些模型当成黑盒,看怎么用起来。Prompt 工程、RAG 检索增强、Deep Research、数据打标——一切围绕”怎么让大模型干活”。

    Agent 因为已经成为独立学科,下一章 8 单独讲。

    7.1 Prompt Tech 提示技术

    拓展阅读:

    7.1.1 In-Context Learning 上下文学习

    GPT 系列里讲到的 Few-shot Learning 就属于 ICL 的一种。

    In-Context Learning 的核心是:模型不更新一个参数,只靠在 prompt 里塞几个示例,就能”现学现做”新任务。其实就是把预训练阶段学到的模式匹配能力,在推理时拿出来用。

    ICL 为什么能工作至今没有完全统一的理论解释,但有几条主流观点:

    • 隐式贝叶斯推断:模型把示例当成对任务分布的采样,在分布上做条件生成。
    • 诱导头机制(induction heads):Transformer 的某些 attention head 学会了”复制 + 推理”的模式,能在长上下文里找到类似 token 并复用其后文。
    • 梯度等价说:示例的存在等效于在 attention 上做了一次隐式梯度下降。

    实务上影响 ICL 效果的三件事:示例的质量、示例的顺序(越靠近 query 越重要)、示例与 query 的分布对齐度

    7.1.2 CoT 完整家族

    Chain-of-Thought 是 2022 年最重要的 Prompt 技术,演化出一整个家族。思路都是让模型把推理过程”写出来”,而不是直接给答案——多花一些 token 换取更高的准确率。

    1. CoT(Wei 2022):在 prompt 里加几步推理示例,让模型也按”想一步、写一步”的方式回答:

    Q: Roger 有 5 个网球。他买了 2 罐网球,每罐 3 个。现在共多少个?
    A: Roger 一开始有 5 个。买了 2 罐 × 3 个 = 6 个。
       5 + 6 = 11。答案是 11。
    

    2. Zero-shot CoT(Kojima 2022):神奇的一句话——Let's think step by step——就能让模型自己开 CoT,不需要示例。这是真正的”激活”型 prompt。

    3. Self-Consistency(Wang 2022):CoT 多次采样 + 投票。同一个题目用 T>0 采 k 条推理路径,选答案出现最多的那个:

    flowchart LR
        Q[问题] --> S1[CoT 采样 1]
        Q --> S2[CoT 采样 2]
        Q --> Sk[CoT 采样 k]
        S1 --> A1[答案: 42]
        S2 --> A2[答案: 42]
        Sk --> Ak[答案: 7]
        A1 --> Vote[多数投票]
        A2 --> Vote
        Ak --> Vote
        Vote --> Final[最终答案: 42]
    

    简单粗暴但有效,GSM8K 提升 ~17%。

    4. Tree of Thoughts(ToT, Yao 2023):把推理过程从一条线扩展为——每一步生成多个候选 thought、用启发式或 LLM 自评打分、按树搜索(BFS/DFS)。

    flowchart TD
        Q[问题] --> T1[Thought 1a]
        Q --> T2[Thought 1b]
        Q --> T3[Thought 1c]
        T1 --> E1{evaluator}
        T2 --> E2{evaluator}
        T3 --> E3{evaluator}
        E1 -.剪枝.-> X1[废弃]
        E2 --> T2a[Thought 2a]
        E2 --> T2b[Thought 2b]
        E3 --> T3a[Thought 2c]
        T2a --> Ans[最终答案]
    

    适合 24 点游戏、创意写作这种搜索空间大、可分步评估的任务。代价:token 消耗 10-100×。

    5. Graph of Thoughts(GoT, Besta 2023):再升级,允许不同分支之间聚合 / 反馈,不只是树形结构——适合更复杂的推理图。

    6. ReAct(Yao 2022):CoT + 工具调用。Reason → Act → Observation 循环。详见 8.0.1 ReAct

    7. Reflexion(Shinn 2023):失败时让模型自己写”反思笔记”,写进 prompt 再试。Memory-augmented self-improvement。

    8. Self-Refine(Madaan 2023):模型给出初稿 → 自评 → 改稿 → 再自评… 迭代直到满意。

    家族对比

    方法Token 成本适用问题是否需要采样
    CoT数学、逻辑
    Zero-shot CoT通用
    Self-Consistency有唯一答案
    ToT10-100×搜索型✅ + 评估器
    GoT50-200×复杂推理图
    ReAct需要工具
    Reflexion试错学习
    Self-Refine写作、代码

    CoT 与现代推理模型的关系:DeepSeek-R1 / o1 这类推理模型其实就是把 CoT “内化”到了模型权重里——通过 RL 训练让模型自发产生长 CoT,不再需要 prompt 工程去触发。可以理解为:CoT 从”推理时的 prompt 技巧”进化成”训练时的能力目标”

    7.2 LLM-based Agent 基于大模型的智能体

    7.2.1 智能体(Agent)的定义与历史沿革

    OpenAI 在 AGI 五级分类中对于 agent 的定义

    • Level 1: Conversational AI。可以与人类进行对话互动的AI系统,例如 ChatGPT,仅限于基于语言的任务,并且缺乏执行复杂问题的能力。
    • Level 2: Reasoners。在学术和专业领域中表现出色,无需外部工具即可解决复杂的问题。
    • Level 3: Agents。能够代表用户长时间自主行动的AI系统,可以在长达数天的时间内执行各种任务,做出决定并执行行动,而无需监督。
    • Level 4: Innovators。AI系统产生新的创新和思想,通过开发原创方案来推动科学技术等领域的突破。
    • Level 5: Organizers。AI可以管理整个组织,协调复杂的过程并超过高价值任务中的人类绩效。

    智能体的核心定义

    7.3 RAG 检索增强生成

    7.3.1 RAG 简介

    RAG(Retrieval Augmented Generation)给生成式模型了与外部世界互动的一个很有前景的做法。主要作用类似于搜索引擎,找到用户提问最相关的知识或者是相关的对话历史,并结合原始提问(查询),创造信息丰富的 prompt,指导模型生成准确输出。其应用了 In-Context Learning 的原理:

    RAG(检索增强生成) = 检索技术 + LLM(大语言模型)提示

    LLM 本身的局限性:

    • 知识的局限性:模型自身的知识完全源于它的训练数据,而现有的主流大模型的训练集基本都是构建于网络公开的数据,对于一些实时性的、非公开的或离线的数据是无法获取到的,这部分知识也就无从具备。
    • 幻觉问题:所有的 AI 模型的底层原理都是基于数学概率,其模型输出实质上是一系列数值运算,大模型也不例外,所以它有时候会一本正经地胡说八道,尤其是在大模型自身不具备某一方面的知识或不擅长的场景。而这种幻觉问题的区分是比较困难的,因为它要求使用者自身具备相应领域的知识。
    • 数据安全性:对于企业来说数据安全关键,没有企业愿意承担数据泄露的风险,将自身的私域数据上传第三方平台进行训练。这也导致完全依赖通用大模型自身能力的应用方案不得不在数据安全和效果方面进行取舍。

    RAG 的特点:

    • 依赖 LLM 来强化信息检索和输出:RAG 需要结合 LLM 来进行信息的检索和生成,但如果单独使用 RAG,它的能力会受到限制。也就是说,RAG 需要依赖语言模型支持,才能更有效地生成和提供信息。
    • 能与外部数据有效集成:RAG 能够很好地接入和利用外部数据库的数据资源。这一特性弥补了通用大模型在某些垂直或专业领域的知识不足或者数据时效问题,比如行业特定的术语和深度知识,能提供更精确的答案。
    • 数据隐私和安全保障:通常 RAG 所连接的私有数据库不会参与到大模型的数据集中训练。因此,RAG 既能提升模型的输出表现,又能有效地保护这些私有数据的隐私性和安全性,不会将敏感信息暴露给大模型的训练过程。
    • 表现效果因多方面因素而异:RAG 的效果受多个因素影响,比如所使用的语言模型的性能、输入数据的质量、算法以及检索系统的设计等。这意味着不同的 RAG 系统之间效果差异较大,不能一概而论。

    RAG 完整链路(离线建索引 + 在线检索生成)

    flowchart TD
        subgraph Offline["离线索引阶段"]
            direction TB
            D1[原始文档<br/>PDF / HTML / Markdown] --> D2[文本切分<br/>chunking]
            D2 --> D3[Embedding 模型<br/>e.g. bge / m3e]
            D3 --> D4[向量化 chunks]
            D4 --> D5[向量数据库<br/>Faiss / Milvus / Chroma]
        end
    
        subgraph Online["在线问答阶段"]
            direction TB
            Q1[用户 Query] --> Q2[Query 改写 / 扩展<br/>可选]
            Q2 --> Q3[Embedding<br/>同一个模型]
            Q3 --> Q4[向量检索 Top-K]
            Q4 --> Q5[Reranker<br/>cross-encoder 精排]
            Q5 --> Q6[上下文拼接<br/>检索片段 + Query]
            Q6 --> Q7[LLM 生成]
            Q7 --> Q8[最终回答<br/>+ 引用]
        end
    
        D5 -.被检索.-> Q4
    

    三个核心环节决定 RAG 效果:(1) Chunking 策略(粒度、滑动窗口、小→大 retrieval)、(2) Retrieval 召回质量(embedding 选择、混合检索、Query 改写)、(3) Reranker 精排(cross-encoder 模型对 Top-K 重排序)。详见 7.4 RAG优化工作推荐

    7.4 RAG优化工作推荐

    7.4.1 检索

    better semantic representation

    一句话总结:chunk optimization,针对文档进行切分,并且调整分块大小,太大或太小的文本块可能无法取得最佳召回效果。选择分块策略时,需要考虑的要素包括:索引内容的特点、使用的嵌入模型及其最适块大小、用户查询的预期长度和复杂度、以及检索结果在特定应用中的使用方式等等。

    具体的优化点

    • 滑动窗口技术通过多次检索,聚合全局相关信息,实现分层检索。
    • Small2big 技术在搜索过程中使用小文本块,并给语言模型更大的相关文本块进行处理。
    • 摘要嵌入(Abstract embedding)技术对文档摘要执行 Top K 检索,以提供完整的文档上下文。
    • 元数据过滤(Metadata Filtering)技术通过文档的元数据进行过滤。
    • 图索引(Graph Indexing)技术把实体和关系转化为节点和连接,这在处理多跳问题时明显提升相关性。
    • fine-tuning embedding model
      • 确定Chunk的适当大小之后,需要通过一个嵌入模型(Embedding model)将 Chunk 和查询嵌入到语义空间中。常见嵌入模型UAE、Voyage、BGE等等。
      • 对嵌入模型进行 基于领域知识微调,代表方法 LlamaIndex
      • 对嵌入模型进行 基于下游任务微调,代表方法 PROMPTAGATOR、LLM-Embedder

    7.4.2 RAG 进阶范式:HyDE / Self-RAG / CRAG / GraphRAG

    朴素 RAG(”检索 → 拼接 → 生成”)有几个老大难问题:

    • 用户 query 跟文档表达方式不同 → 检索召回差
    • 检索回来的 chunk 可能完全不相关 → 模型被误导
    • 多跳推理需要的信息分散在多个文档 → 单次检索不够

    围绕这些痛点,2023-2024 业界发展出几条进阶范式:

    1. HyDE(Hypothetical Document Embeddings, Gao 2022):先假设答案再检索

    朴素 RAG 用 user query 做检索,但 query 通常是疑问句、目标文档是陈述句,表达分布不一致。HyDE 让 LLM 先虚构一个看起来像答案的文档,用这个虚构文档去检索:

    flowchart LR
        Q[User Query<br/>问句] --> LLM1[LLM 虚构答案]
        LLM1 --> Hyp[Hypothetical Doc<br/>陈述句]
        Hyp --> Emb[Embedding]
        Emb --> Vec[(向量库)]
        Vec --> Real[真实相关文档]
        Real --> LLM2[最终生成]
    

    虽然虚构答案可能有事实错误,但表达分布跟真文档一致,召回率明显提升(5-10 个点 nDCG)。

    2. Self-RAG(Asai 2023):模型自己决定要不要检索 + 是否采纳

    朴素 RAG 每次必检索,但很多 query 不需要外部知识(如”hello”、”翻译这句话”)。Self-RAG 训练模型生成特殊 control token,自主决定流程:

    控制 token含义
    [Retrieve]需要检索
    [No Retrieve]不需要
    [Relevant]检索到的内容相关
    [Irrelevant]不相关,忽略
    [Supported]我的回答有 evidence 支持
    [Partially supported]部分支持

    通过 SFT 让模型学会这些 token,运行时根据 token 决定是否走检索分支、是否相信检索结果——其实就是把 RAG 流程”内化”到模型行为里。

    3. CRAG(Corrective RAG, Yan 2024):检索质量自评估 + 兜底

    CRAG 在检索回来之后加一个评估器判断 chunk 质量:

    flowchart LR
        Q[Query] --> R[Retrieve Top-K]
        R --> Eval{评估器打分}
        Eval -->|High confidence| Direct[直接用检索结果]
        Eval -->|Mid| Refine[拆解 + 精选]
        Eval -->|Low confidence| Web[降级为 web search]
        Direct --> Gen[Generation]
        Refine --> Gen
        Web --> Gen
    

    三个分支策略:

    • 检索质量高:正常使用
    • 一般:用 LLM 拆解 chunk,精选最相关的句子
    • 全部低分:触发 web search 兜底(避免幻觉)

    CRAG 的真正贡献是承认了”检索不可靠”——朴素 RAG 隐含假设”top-K 总是相关”,CRAG 显式处理了这个 failure mode。

    4. GraphRAG(Microsoft 2024):知识图谱 + 社区摘要

    朴素 RAG 在全局问题上失效——比如”这个公司的整体战略是什么?”——答案分散在几百份文档里、没有一份能直接命中。GraphRAG 的做法:

    flowchart TD
        Docs[原始文档] --> EE[实体抽取<br/>LLM 跑一遍]
        EE --> KG[知识图谱<br/>节点 = 实体, 边 = 关系]
        KG --> Comm[社区发现<br/>Leiden 算法分簇]
        Comm --> Sum[每个社区生成摘要<br/>LLM 跑一遍]
        Sum --> Hier[多层级摘要树]
    
        Q[Query] --> Type{全局 vs 局部?}
        Type -->|全局| Hier
        Type -->|局部| Vec[向量检索 chunk]
        Hier --> Ans[Map-Reduce 聚合]
        Vec --> Ans
    
    • 建索引阶段:花 100× 成本(每个 chunk 都让 LLM 抽实体关系),但建出来的知识图谱 + 多层摘要树是可复用资产
    • 查询阶段:根据问题类型走 graph 路径或 vector 路径,全局问题用 community summary

    GraphRAG 适合”高价值文档集 + 需要全局推理”的场景(如咨询、法律、专利分析)。代价是建索引贵,所以日均 query 不大的场景不划算。

    5. 进阶范式对比

    范式解决的问题复杂度何时用
    朴素 RAG基础信息检索简单问答
    HyDEquery/doc 分布失配召回不好
    Self-RAG不必要的检索 + 噪声高(要 SFT)高质量产品
    CRAG检索失败兜底容错要求高
    GraphRAG全局推理极高高价值文档集
    Agentic RAG多步推理 + 多次检索Deep Research

    Agentic RAG 是当前主流方向——用 Agent loop 把 retrieval 当成 tool call,模型根据中间结果决定是否继续检索、检索什么。详见 8.0.1 ReAct:Reasoning + Acting 的开山之作

    7.4.3 检索召回的混合策略

    工业级 RAG 几乎不会只用向量检索,而是多路召回 + 融合排序

    flowchart LR
        Q[Query] --> Vec[向量召回<br/>语义]
        Q --> BM25[BM25 / Elastic<br/>关键词]
        Q --> Spar[Sparse Vector<br/>SPLADE]
        Vec --> Fuse[RRF 融合<br/>Reciprocal Rank Fusion]
        BM25 --> Fuse
        Spar --> Fuse
        Fuse --> Rerank[Reranker<br/>cross-encoder]
        Rerank --> Final[Top-K]
    
    • 向量召回:召回语义相似但措辞不同的(”如何申请退款” vs “退款流程”)
    • BM25:召回实体精确匹配的(如人名、产品号、代码符号)
    • Sparse Vector(SPLADE / uniCOIL):神经网络生成的稀疏权重,结合了语义和关键词的优势
    • Reranker:用 cross-encoder(如 bge-reranker-v2-m3、Cohere Rerank)对 Top-100 重排,输出 Top-10

    RRF(Reciprocal Rank Fusion)公式

    \text{RRF}(d) = \sum_{r \in R} \frac{1}{k + \text{rank}_r(d)}, \quad k = 60

    简单到不像 work 但实测效果稳——多路结果各自的排名加权倒数即可,不需要训练。

    7.4.4 Chunking 策略的演进

    方法思路适合场景
    Fixed-size按固定 token 数(如 512)切简单文档
    Recursive按段落 → 句子 → token 多级 fallback通用首选
    Semantic Chunking用 embedding 相邻句相似度找边界长文本
    Late Chunking(2024)先对全文 embed、再按需切——保留全局上下文长文档 RAG
    Small-to-Big用小 chunk 检索、用大 chunk 喂模型召回 vs 上下文兼顾
    Contextual Retrieval(Anthropic 2024)每个 chunk 加一段 LLM 生成的”这个 chunk 在讲什么”前缀高准确率 RAG

    Anthropic 的 Contextual Retrieval 是 2024 年的重要进展:用 Claude 给每个 chunk 自动生成 50-100 token 的”上下文摘要”,加在 chunk 前面再 embed——检索召回率提升 35-50%。代价是建索引时多花一倍 LLM 调用。

    7.5 Deep Research工作梳理及推荐

    Deep Research 是什么

    Deep Research = Deep Search + “写报告”。Deep Search 解决的是”在网上反复搜+读+推理直到搜到答案”;Deep Research 在此基础上再把搜到的东西组织成一份能看的长报告。

    具体多做几件事:

    • 把答案整合到合理的章节结构里
    • 配图表、配数据
    • 保证术语统一、子章节不互相打架、过渡顺畅
    • 杜绝同一个观点反复出现

    Deep Search 内部

    一个三段循环:搜索 → 阅读 → 推理 → 缺什么继续搜 → … → 答案足够好为止。

    7.6 利用大模型进行数据打标

    本文围绕文本数据(含图文对)常见标注任务(如分类、结构化信息抽取、情感/风格打分等),从数据预处理、Prompt 设计、标注流程控制、多模型协同、自监督辅助、质量评估与纠错等角度,提出系统化方法论,强调实战经验与工程可操作性。整体流程尽量采用自动化标注,同时预留“自动+人工”降级路径,兼顾效率与准确。

    数据预处理

    • 数据清洗与规范化:对原始文本进行清理(去除HTML标签、特殊符号等)、统一编码和格式。对图像文本对,先用OCR或多模态大模型提取图像描述,将图像信息以文本形式编码,保证多模态输入一致性。
    • 去重与过滤:首先使用轻量级筛选(如URL哈希、文本长度、简单关键词过滤)剔除显然无效或重复样本,降低后续计算开销。之后再进行语义级重复检测(如Embedding聚类、BM25检索),避免相似内容多次标注。比如构建多阶段流水线,先执行URL去重、文本提取等启发式规则,再用模型驱动的语义去重;有研究显示这种多阶段处理能明显提升数据质量。
    • 类别与格式统一:根据任务需求,统一数据格式(如JSON、CSV),并明确标签体系和规则定义。对于多类分类或NER,最好提前制定好标签规范和示例,避免后续混淆。可以在预处理阶段,对输入文本进行预标注(如利用关键词或弱分类器初筛标签),给后续Prompt辅助信息。
    • 数据抽样与分批:为支持迭代开发和质量控制,应将数据划分成小batch进行标注验证。初期可从标注样本中抽取少量代表性数据,用来快速验证Prompt和标注逻辑是否合理,再大批量自动执行。

    Prompt设计

    8. Agent 智能体专项

    这章在讲什么:Agent 是 2024-2025 的主战场。从 tool-use 数据合成、Agentic 能力优化、入门项目推荐、AgenticRL,到 Harness Engineering——一条以”轨迹优化”为核心的全新工程方向。

    这章比上一章 7 应用要深入:7 章是”怎么用”,这章是”怎么把模型真正变成能完成长任务的智能体”。

    Q:为什么要单开 Agent 专项?

    A:当前主流基座模型(如 Qwen3、Kimi K2、Minimax M2 等)在架构与训练上都在向”更强的任务分解、工具调用与长上下文推理”优化,而工业界真正落地时几乎全部以 agent 为中心,将模型的思考能力与外部工具、业务流程解耦,让模型专注决策、agent 负责执行与编排,从而实现可控、可扩展的业务自动化。

    因此,无论从模型演进趋势还是从产品落地路径来看,agent 都已成为将大模型能力转化为稳定、高效、可规模化生产力的核心枢纽。

    ps:虽然但是,工业界目前大部分做法还是 workflow,真正做到纯 agentic 的链路少之又少。

    本章包含:

    • 8.0 经典 Agent 范式(ReAct / Reflexion / Tool Use / MCP)— 新加
    • 8.1 tool-use 数据合成
    • 8.2 Agentic 能力优化策略
    • 8.3 Agentic 入门项目推荐
    • 8.4 AgenticRL 项目推荐
    • 8.5 Harness Engineering 认知

    8.0 经典 Agent 范式

    在跳进 tool-use 数据合成、RL 训练这些前沿话题之前,先打好”Agent 的基础范式”——后面所有的工程都是在这些经典思路上演化的。

    8.0.1 ReAct:Reasoning + Acting 的开山之作

    ReAct(Yao 2022) 把 CoT 的”会想”和工具使用的”会做”合并成一个循环:

    Thought 1: 我需要查一下今天的天气。
    Action 1: search_weather("北京")
    Observation 1: {"temp": 12, "condition": "晴"}
    Thought 2: 现在我知道温度了,可以建议穿什么。
    Action 2: finish("建议穿一件薄外套")
    

    模型每一步只决定两件事:(1) 现在应该想什么 / 做什么,(2) 想完之后是再想一步还是结束。

    flowchart LR
        Q[用户问题] --> T[Thought 推理]
        T --> A[Action 选工具 + 填参]
        A --> Exec[执行工具]
        Exec --> O[Observation]
        O --> T
        T -.判断完成.-> Final[Final Answer]
    

    ReAct 是所有现代 Agent 框架(LangChain、AutoGen、CrewAI 等)的默认 reasoning loop

    8.0.2 Reflexion:失败时自我反思

    Reflexion(Shinn 2023) 在 ReAct 之上加一层 memory-augmented self-improvement

    flowchart LR
        Q[Task] --> Try[尝试解决]
        Try --> Eval{成功?}
        Eval -->|失败| Reflect[Self-reflect<br/>写反思笔记]
        Reflect --> Mem[(Episode Memory)]
        Mem -.作为 context.-> Try
        Eval -->|成功| Done
    

    每次失败后,让模型自己写一段”我哪里做错了 / 下次怎么改”的文字,存到 memory 里。下次解同一个任务时,把反思笔记当 context 喂回去。

    这是不更新模型参数的”学习”——纯靠 in-context 记忆改进。在 HumanEval、ALFWorld 等 benchmark 上能拉高 10-30%。

    8.0.3 Function Calling / Tool Use

    Function Calling(OpenAI 2023 起) 是 ReAct 的”工程协议化”:

    • 开发者定义工具的 JSON Schema(名字、参数、描述)
    • 模型在 SFT 阶段学会按这个 schema 输出结构化 tool call
    • 框架解析 JSON、调用真实函数、把结果回灌

    跟”模型自由写 Action: xxx” 相比,Function Calling 有三个好处:

    • 格式稳定:JSON schema 比自由文本更容易解析
    • 参数验证:可以严格 type-check
    • 并行调用:一次输出多个 tool call

    现代主流大模型(GPT-4、Claude、Qwen、DeepSeek)都原生支持 function calling,且 schema 协议高度收敛。

    8.0.4 MCP(Model Context Protocol):工具协议的统一

    MCP(Anthropic 2024) 是把”模型连接外部工具”标准化的协议——类似”USB 接口”,让任何模型都能即插即用任何工具。

    flowchart LR
        LLM[Any LLM<br/>Claude / GPT / Qwen] <--> MCP[MCP Client]
        MCP <-->|stdio / SSE| S1[MCP Server<br/>文件系统]
        MCP <--> S2[MCP Server<br/>数据库]
        MCP <--> S3[MCP Server<br/>GitHub]
        MCP <--> Sn[MCP Server<br/>自定义工具]
    

    MCP 把传统的”每个 Agent 框架定义自己的 tool”升级成”工具有独立的进程 + 标准协议”。意义:

    • 工具供应商(如 GitHub)只需要写一次 MCP server,所有支持 MCP 的客户端都能用
    • 开发者切换 LLM 时不用重写工具集成
    • 2025 已经成为 Claude Desktop、Cursor、Cline 等 IDE 的标准

    8.0.5 多 Agent 协作框架

    单 Agent 能力有限,多 Agent 是另一条路线:

    框架设计哲学协作模式
    AutoGen(Microsoft)对话驱动Agent 之间发消息
    LangGraph(LangChain)显式状态机有向图编排
    CrewAI角色分工Manager + Worker 团队
    MetaGPTSOP 模板软件公司角色(PM / 架构师 / 程序员)
    OpenAI Swarm轻量 handoffAgent 间传递 ownership

    实务上多 Agent 不一定好——通信开销大、错误累积、调试难。单 Agent + 强模型在大多数任务上反而更稳。多 Agent 的真正优势在并行(如多个 Agent 同时调研不同主题)和专业化(如代码 + Code Review 分工)。

    8.1 tool-use 数据合成

    📖 拓展阅读:多轮工具调用 SFT 数据清洗与构建工作汇总

    一、tool-use 数据合成的重要性

    对于 agent 而言,function call 能力是大模型从”会说话”向”会解决问题”转化的核心能力,而 tool-use 数据构成了这一能力学习的基础。没有充分反映真实工具行为和交互模式的数据,模型难以掌握在实际环境中选择合适工具、构造调用参数并对结果进行有效校验的能力。

    现实世界中工具调用往往成本高、调用样本稀少且场景复杂,单靠真实交互难以覆盖足够的任务空间并得到稳定、可泛化的学习信号。因此,大规模、可控且低成本的数据合成成为最有效的补充手段:

    • 通过系统化的数据合成,模型可以在多样化任务中练习工具选择、参数生成与结果验证等技能;
    • 在多步骤任务中提升决策一致性与鲁棒性,降低因数据稀疏带来的过拟合与偏差风险;
    • 在面向 agent 的应用场景中,合成数据应特别注重模拟多轮对话、工具调用及其对应的 action–feedback 轨迹,以训练模型在连续决策链中合理编排工具并保持语境连贯与状态一致性。

    配套资源:tool-use 合成技术发展的思维导图(见原飞书页面)。

    8.2 Agentic 能力优化策略

    一、优化 Agentic 能力的背景

    预训练阶段通常以自回归目标在海量文本语料上训练模型,使其掌握语言建模和基础知识。之后,通过 SFT 将模型适配下游任务,即使用人类标注的数据对模型进行监督学习,使其具备更好的任务执行能力和指令遵循能力。再进一步,采用 RLHF 方法对模型进行对齐:通过人类偏好打分或评分系统,将任务完成的质量作为奖励,使用策略梯度算法迭代优化模型策略,以提升模型生成结果的正确性和安全性。

    总体而言,预训练 + SFT + RLHF 构成了当前 LLM 训练的基础 pipeline;而对于 Agent 来说,针对更复杂的 Agentic 问题往往还需要更多定制策略来克服有限长记忆、稀疏奖励、工具调用及环境等挑战。

    对于 Agentic 能力的提升,主要分为三个阶段:

    • mid-training 阶段的原生 agentic 能力增强;
    • SFT 冷启动
    • RL 提升 pass@1 的准确率。

    考虑到绝大部分人没有机会接触到 mid-training,下面先聊聊如何从 SFT 和 RL 阶段提升 Agentic 能力。

    8.3 Agentic入门项目推荐

    一、理解 Agent 的核心机制

    1. pguso/ai-agents-from-scratch (1.6k stars)
      项目简介: 该项目旨在通过使用本地LLM(例如 node-llama-cpp)和基础编程语言。推荐理由: 它的哲学是通过构建来学习,帮助开发者深入理解 Agents 的工作原理,如 ReAct 模式和功能调用的底层实现,避免了高级框架的复杂抽象,。
    2. browser-use/browser-use (73.2k stars)
      项目简介: 这是一个开源库,赋予 LLM 智能体进行网页浏览、交互和自动化的能力,让 Agent 能够在网站上执行任务,如填写表格或购物。该项目旨在让网站对 AI Agents 变得可访问。推荐理由: 该项目将抽象的“工具调用”概念转化为具体的与外部世界的交互能力,展示了 Agent 如何访问真实的、有状态的网站,并处理认证、会话保持等问题。它还支持使用 Ollama 运行本地 LLM。二、Agent实战
    3. TransformerOptimus/SuperAGI (16.9k stars)
      项目简介: 这是一个面向开发者的开源自主 AI Agent 框架,旨在帮助开发者快速、可靠地构建、管理和运行实用的自主智能体。推荐理由: Dev-first 的生产化平台。 提供GUI,支持并发运行 Agent,并解决了生产部署中的关键工程问题,例如Performance Telemetry优化 Token 使用,这对于控制成本和监控 Agent 轨迹关键,。
    4. crewAIInc/crewAI (41k stars)
      项目简介: CrewAI 是一个用于编排角色是自主 AI Agent 的框架。它通过明确定义 Agent Role、Goal和任务Task,并将其组织成协作流程,来促进协作智能,共同解决复杂任务,。

    8.4 AgenticRL 项目推荐

    Search 向 Agentic RL 篇RL for Search Agent 的总览传统 RAG 更多是在固定的检索 pipeline 上做 prompt / reranker 优化,模型本身并不会去学会如何搜索,什么时候进行搜索。2025 年一些工作用 RL 训练 Search Agent,其大致有如下一些共同特征:

    • 环境:从静态的知识库,到真实 Web 浏览器、垂直检索引擎
    • 行为:LLM 作为策略,决定 何时搜索、搜什么、要不要继续搜索
    • 奖励:不只看 NDCG/BLEU 这类检索或生成指标,而是围绕任务完成质量 + 搜索成本去设计复合 reward
    • 算法:多用 PPO / GRPO 等 RLVR 算法的变体,支持长序列、工具调用和多步轨迹
      可以理解为在 LLM + 工具的基础上,把用好搜索工具变成大模型 RL 的学习目标基础:Search-R1 生态和多跳 QA Search-R1论文:https://arxiv.org/pdf/2503.09516 Github:https://github.com/PeterGriffinJin/Search-R1
    • Search-R1 提出了一套完整的 RL 训练框架,让 LLM 在推理过程中交替发出搜索调用(本地检索或 Google/Bing)、阅读结果、继续思考,最后给出答案
    • 场景:NQ、TriviaQA、PopQA、HotpotQA、MuSiQue、2WikiMultiHopQA、等开放域 QA
    • 核心设计:
      • 轨迹是 think + 搜索 action + 检索结果 的交错序列

    8.5 Harness Engineering 认知

    Harness Engineering:为 Agent 设计闭环系统

    一句话总结:Harness engineering 是在为 LLM 构造一个可执行、可观测、可验证、可纠偏的外部闭环。它关心的是模型能做什么、怎样收到反馈、失败后如何继续、系统如何防止错误扩散。

    OpenAI 对 Codex 的描述:长任务的稳定性不是来自一个更长的 prompt,而是来自一套持续循环的 agent loop;而在使用自定义工具时,真正负责跑工具和接回结果的,正是 client 侧的 harness。

    一、爆火的原因

    OpenAI 用 5 个月、几名工程师起步让 Codex 驱动一个内部 beta 产品,而且人类不直接写代码,主要工作转为”补工具、补约束、补文档、补验证”。

    我认为这件事的本质是:大模型的使用范式,正在从单步问答,切到轨迹优化

    • 在单步问答里,我们优化的是一次输出;
    • 在 agent 场景里,我们优化的是一条轨迹:规划 → 读文件 → 调工具 → 看报错 → 修复 → 再验证 → 最后结束。

    只要问题从”单轮生成”变成”多步执行”,模型就不再只是一个 conditional generator,而更像一个被放进环境里的策略。这个时候,真正决定性能的,模型权重,同时还包括它能观察到什么状态、能采取哪些动作、每一步能得到什么反馈。这个”环境设计”本身,就是 harness engineering。

    二、Harness Engineering 和 Prompt / Context Engineering 的边界

    Thoughtworks 对 context engineering 的定义很简洁:它是在整理”模型应该看到什么”,目标是让模型得到更好的结果;并且他们明确提醒,context 不是越多越好,过多上下文会拖垮效果和成本。

    但 harness engineering 比这再往前走了一层:

    • Context engineering 解决的是输入分布:比如规则文件、skills、MCP、repo 文档、历史对话、文件树。这些都在决定模型看到的状态表示。
    • Harness engineering 解决的是闭环动力学:它不仅决定输入,还决定状态如何流转、动作如何执行、反馈如何回到模型、失败如何兜底。

    Agent Loop 闭环示意(Harness 视角)

    flowchart TD
        Goal[用户目标 Goal] --> Plan[LLM 规划<br/>Thought]
        Plan --> Tool[Tool Call<br/>Action]
        Tool --> Exec[Harness 执行<br/>shell / API / browser]
        Exec --> Obs[Observation<br/>结果 / 报错 / 文件 diff]
        Obs --> Eval{Verifier 校验<br/>测试 / Lint / 静态分析}
        Eval -->|通过| Done[结束<br/>提交结果]
        Eval -->|失败| Retry[Reflection<br/>LLM 重新规划]
        Retry --> Plan
        Obs -.写入.-> Mem[Memory / Trace<br/>供后续步骤回看]
        Mem -.读取.-> Plan
    
        subgraph Harness["Harness 边界<br/>非模型部分"]
            Exec
            Eval
            Mem
        end
    

    Harness 的四大职责:

    • 可执行 (Executable):tool schema、参数校验、超时、retry、并发控制;
    • 可观测 (Observable):trace 日志、token 计费、tool 调用统计、错误分类;
    • 可验证 (Verifiable):测试套件、lint、形式化检查、cross-check;
    • 可纠偏 (Correctable):失败回滚、checkpoint、reflection-and-retry、人在回路。

    → 模型权重决定”能想到什么”;harness 决定”想错了怎么办、想对了能否落地”。

    9. Evaluation 大模型评估

    这章在讲什么:训练和应用都需要”知道好不好”。这章梳理传统 NLP 指标(BLEU/ROUGE/F1)、预训练阶段评估(PPL + benchmark)、SFT 之后的对齐评估。

    评估不是 train-eval-deploy 的最后一步,而是贯穿全程的反馈环——所以放在工程链路的总结位置。

    本章把”怎么衡量大模型好不好”按训练阶段拆开看:传统 NLP 指标 → Pretrain 阶段 → SFT 之后。RAG 和 Agent 的评估在第 7、8 章里穿插讲过,这里不重复。

    9.1 传统 NLP 评估指标

    从人工判断到自动打分

    大模型出现之前,NLP 评估的主战场是边界清晰的具体任务——文本分类、实体识别、机器翻译这类。当时的核心问题就一个:怎么用机器代替人工打分,又便宜又能复现?

    BLEU、ROUGE、F1 这些指标流行起来,其实就是对”快速复现 + 方便刷榜”需求的回应。但字符串重叠不等于语义质量,这条裂缝后来催生了 BERTScore、LLM-as-Judge 等更接近”理解”的评估方法。

    1. 传统评估的基本逻辑

    传统 NLP 指标大体可以分为三类,它们分别对应不同的任务假设和应用场景:

    1. 判别式指标:分类和序列标注任务里最常见的 Accuracy、Precision、Recall、F1。
    2. 答案匹配指标:典型代表是抽取式问答中的 Exact Match 和 token-level F1。
    3. 文本生成指标:代表性的就是机器翻译里的 BLEU 和摘要里的 ROUGE;再往后,则发展出基于预训练表示或监督学习的语义指标,例如 BERTScore、BLEURT 和 COMET。

    它们分别对应不同的任务假设:标签空间明确、答案边界可定位、语言生成质量可以通过参考文本相似度近似描述。

    指标类型核心假设代表任务典型指标
    判别式指标标签空间明确,非黑即白文本分类、序列标注Accuracy、Precision、Recall、F1
    答案匹配指标答案边界可定位抽取式问答(QA)、信息抽取Exact Match (EM)、Token-level F1
    文本生成指标生成质量可通过参考文本的相似度近似描述机器翻译、文本摘要BLEU、ROUGE、BERTScore

    9.2 Pretrain 阶段的评估

    前文回顾:2.1 预训练定义2.4 预训练评估

    从语言建模拟合到可迁移能力测度

    预训练阶段的评估与后续的 SFT、RLHF 或 RAG、Agent 评估在方法论上截然不同。预训练模型首先是一个自回归分布估计器,其直接优化目标是下一个 Token 预测的负对数似然。因此,这一阶段的核心问题不是”模型像不像一个有用的助手”,而是”模型是否学到了更好的语言分布近似,并且这种拟合能否转化为跨任务的可迁移能力”。

    为了具备科学解释力,预训练评估不能只看单个下游分数或训练损失,而应该从下面的三层评估框架着手:

    1. 内在评估 (Intrinsic Evaluation):衡量模型对文本分布的拟合质量。
    2. 外在评估 (Extrinsic Evaluation):衡量模型在标准化 Zero-shot 或 Few-shot 设置下的泛化能力。
    3. 可信度评估 (Reliability Evaluation):检查分数是否受 Prompt、数据污染或统计波动的系统性影响。

    9.3 SFT 阶段的评估

    前文回顾:4.1 SFT 监督微调

    从语言分布拟合到条件行为对齐

    如果说预训练阶段评估的核心对象是无条件或弱条件的语言分布拟合能力,那么 SFT 评估的对象已经发生了本质变化。SFT 之后,模型不再只是一个尽可能逼近互联网文本语料分布的生成器,而是一个在用户指令、系统约束、任务上下文条件下产生 response 的策略。此时,评估问题也不再是”模型是否更会续写”,而是”模型是否按要求回答、是否完成任务、是否在开放式交互中表现出帮助性、真实性与边界感”。

    因此,预训练阶段常见的困惑度、token-level NLL,至多只能作为辅助诊断指标,而不能再充当 SFT 成败的主判据。SFT 评估的重心,必须从分布拟合转向条件行为质量。

    1. SFT 改变了什么:评估对象从 p_\theta(x) 变成 p_\theta(y \mid x)

    在标准 SFT 中,训练数据通常由指令或对话上下文 x 与期望响应 y 构成,目标函数一般写作:

    \mathcal{L}_{\text{SFT}} = -\mathbb{E}_{(x, y) \sim \mathcal{D}_{\text{SFT}}} \sum_{t=1}^{|y|} \log \pi_\theta(y_t \mid x, y_{<t})

    这个目标仍然是交叉熵,但语义已经不同。预训练时,模型是在学习”语言通常怎样继续”;SFT 时,模型是在学习”面对特定任务指令时,什么样的响应更符合期望”。二者的差别看似只是条件项 x 的加入,实质上却意味着模型开始被拉向一个更窄、更人工、也更带有价值判断的目标分布。因此,SFT 评估其实就是在度量条件行为对齐,而不是一般语言流畅性。

    9.4 评估前沿:工具与平台

    前面几节讲的是评估思路。这一节讲业界实际在用的工具栈——从离线 benchmark 跑批,到在线人评 Arena。

    9.4.1 LM-Eval Harness:开源 benchmark 跑批工具

    lm-eval-harness(EleutherAI) 是开源界事实标准的 benchmark 跑批框架。HuggingFace Open LLM Leaderboard 用的就是它。

    • 内置 60+ benchmark:MMLU、HellaSwag、ARC、TruthfulQA、GSM8K、HumanEval、BBH、Winogrande 等
    • 支持 HF Transformers / vLLM / OpenAI API / Anthropic API 各种 backend
    • 标准化的 prompt 和评分——避免厂商各自实现导致的分数不可比

    用法

    lm_eval --model hf \
      --model_args pretrained=Qwen/Qwen2.5-7B \
      --tasks mmlu,gsm8k,humaneval \
      --batch_size 8
    

    主流 benchmark 分类

    维度代表 benchmark评估的能力
    通用知识MMLU、C-Eval、CMMLU、AGIEval跨领域知识广度
    数学GSM8K、MATH、MathQA、AIME数学推理
    代码HumanEval、MBPP、BigCodeBench、LiveCodeBench代码生成
    推理BBH、ARC-C、MMLU-Pro复杂推理
    常识HellaSwag、Winogrande、PIQA常识判断
    真实性TruthfulQA、HaluEval抗幻觉
    安全ToxiGen、SafetyBench、BeaverTails安全对齐
    多模态MMMU、MathVista、ScienceQAVLM 评估
    长上下文RULER、InfiniteBench、L-Eval长上下文真实可用度

    MMLU-Pro(2024) 是 MMLU 的升级版——增加干扰项数量(4→10)、提高难度,更难刷分、更能区分顶尖模型。

    9.4.2 MT-Bench / AlpacaEval:LLM-as-Judge 自动评估

    传统 benchmark 多是选择题,对开放式对话能力评估不准。LLM-as-Judge 是 2023 之后的主流做法——用强模型(GPT-4 / Claude)打分。

    MT-Bench(LMSys 2023)

    • 80 道多轮对话题(写作、推理、代码、数学、STEM、人文、提取信息、角色扮演)
    • GPT-4 当 judge,1-10 分打分
    • 给单一指标 “MT-Bench score”,方便对比
    flowchart LR
        M1[模型 A 回答] --> J[GPT-4 Judge]
        M2[模型 B 回答] --> J
        J --> R[打分 + reasoning]
        R --> Score[A 8.5, B 7.2]
    

    AlpacaEval 2.0

    • 805 道单轮指令
    • 用 GPT-4-Turbo 做”成对比较”——A vs baseline、B vs baseline,算胜率
    • 引入 length-controlled winrate 校正长回答的天然优势

    LLM-as-Judge 的三大坑

    • Position bias:先呈现的回答更容易被选中(要双向比较)
    • Verbosity bias:长回答系统性偏好(length-controlled 缓解)
    • Self-preference:让 GPT-4 当 judge,它倾向于给 GPT 类风格高分

    9.4.3 Chatbot Arena:人评的金标准

    Chatbot Arena(lmsys.org) 是 LLM 评估的”金标准”——用真实人类盲测投票:

    flowchart LR
        User[用户] --> Q[输入 prompt]
        Q --> Show[同时展示 Model A vs Model B 回答<br/>盲测]
        Show --> Vote[用户投票: A 赢 / B 赢 / 平 / 都差]
        Vote --> Elo[Elo 评分系统更新]
        Elo --> LB[Leaderboard]
    
    • 累计百万级人类投票
    • Elo Rating(国际象棋的评分系统)排名
    • 也提供分类排行(中文、代码、数学、长上下文)

    Arena 的优势:人类盲测,没有 LLM-as-Judge 的偏差,反映”真实使用体验”。
    Arena 的局限:投票偏向”看起来好”的回答(长、Markdown 排版、礼貌)——所以业界也开始关注 hard 子集(如 Arena-Hard)。

    Arena-Hard(2024):从 Arena 的真实 prompt 里筛出”区分度高”的 500 道题,用 GPT-4 当 judge,胜率作为分数。相比朴素 MT-Bench 更难刷分,与 Arena 真实排名相关性更高。

    9.4.4 评估方法谱系总览

    flowchart TD
        Eval[LLM 评估] --> Auto[自动化]
        Eval --> Human[人评]
        Auto --> Bench[选择题 benchmark<br/>MMLU / GSM8K / HumanEval]
        Auto --> Judge[LLM-as-Judge<br/>MT-Bench / AlpacaEval]
        Auto --> Domain[领域专用<br/>RAG: RAGAS<br/>Agent: SWE-bench]
        Human --> Arena[盲测 + Elo<br/>Chatbot Arena]
        Human --> Expert[专家评估<br/>领域专家细评]
    
    方法成本区分度反作弊实务用法
    选择题 benchmark中(顶尖模型差距小)易过拟合日常 dev / 发布报告
    LLM-as-Judge对比候选模型
    人评 Arena极高最高最终 ground truth
    专家评估极高视专家高价值垂域

    实务流程

    1. 开发期间用 lm-eval-harness 选择题 看大致水平
    2. 候选模型出来后用 MT-Bench / AlpacaEval-2 做对比
    3. 上线前人工抽检 100-1000 条真实业务 query
    4. 上线后接入 A/B 测试 + 用户反馈做长期评估

    9.4.5 专用评估:RAG / Agent / 长上下文

    RAG 评估(RAGAS / TruLens)

    • Faithfulness:回答的内容是否在检索结果里有支撑?
    • Answer Relevance:回答是否回应了 query?
    • Context Precision:检索回来的内容相关度
    • Context Recall:相关内容是否被召回

    Agent 评估

    • SWE-bench:真实 GitHub issue + PR,看 agent 能不能修 bug
    • WebArena / VisualWebArena:浏览器 agent 任务
    • GAIA:通用 AI 助手 benchmark,强调多步推理 + 工具使用
    • τ-bench:客服场景,多轮 + 工具调用 + 政策遵守

    长上下文评估:见 3.2.4 长上下文的”假信号”问题RULER 是当前最严格的标准。

    9.4.6 评估的反作弊机制

    模型公司在选择题 benchmark 上的”刷榜”问题严重——数据污染、专门针对 benchmark 微调等。业界的反制:

    • 数据污染检测:用 n-gram 匹配 / decontamination tool 检查训练数据是否包含测试集
    • 动态测试集:LiveCodeBench、LiveBench——周更题目避免被训进去
    • 私有 holdout:厂商打榜时只能拿到部分公开题,部分题不公开
    • 复述检测:把测试题轻微改写,分数大跌就说明模型只是记住了原题

    现实建议:看模型能力别只看一个分数。一个真正强的模型应该在多个 benchmark 上稳定优秀 + Arena 排名靠前 + 你自己业务场景的测试集上稳定通过——单一指标都可能被针对性优化。

    10. Papers 论文阅读笔记

    这章在讲什么:精选近期值得读的技术报告与论文,按主题分组:技术报告、o1 路线、Prompt、LLM-as-Judge、拓展阅读、工作推荐。

    不是体系化教程,是”读到哪算哪”的参考。前面 1-9 章的某个概念想深挖,可以来这里找对应论文。

    🚘 大模型论文阅读笔记,目前记录一些新的重要的技术报告论文笔记,以及个人感兴趣的一些方向比如强化学习、o1 技术路线、Prompt 技术、LLM-as-a-Judge 和 RAG 等。有些论文笔记会以算法详解等形式添加到前面章节的内容,比如 DAPO、VAPO 就直接添加到了 3.3 章里面。

    本章包含:

    • 🎬 8.1 技术报告详解
    • 🍯 8.2 o1 技术路线论文
    • 🏍️ 8.3 Prompt 技术
    • 🔋 8.4 LLM-as-Judge
    • 😀 8.5 拓展阅读
    • 🏰 8.6 工作推荐系列

    10.1 技术报告详解

    一些技术报告详解,还有部分技术报告详解已经融合进第四章常见模型的内容中了

    DeepSeek NSA 解读:三叉戟稀疏注意力

    10.1.1 DeepSeek-R1

    主要包含两个推理模型:DeepSeek-R1-Zero 和 DeepSeek-R1。

    • DeepSeek-R1-Zero 通过大规模强化学习(RL)训练,无需 SFT 作为前置初步步骤。在强化学习过程中,DeepSeek-R1-Zero 自然而然地出现了许多强大而有趣的推理行为。
    • DeepSeek-R1 在 RL 之前结合了多阶段训练和冷启动数据,来解决 Zero 的可读性差、语言混合等问题。
    • DeepSeek-R1 在推理任务上实现了与 OpenAI o1-1217 相当的性能。
    • 蒸馏模型:DeepSeek 开源了 DeepSeek-R1-Zero、DeepSeek-R1,以及基于 Qwen 和 Llama 从 DeepSeek-R1 中蒸馏出来的六个 Dense Model(1.5B、7B、8B、14B、32B、70B)。

    论文链接:https://github.com/deepseek-ai/DeepSeek-R1/blob/main/DeepSeek_R1.pdf

    R1 100 问:科学网—DeepSeek-R1的100问 – 王雄的博文,可以看看

    整体训练流程如下:

    10.1.2 Kimi-K1.5

    主要包含两个多模态推理模型 Kimi k1.5 LongCoT和Kimi k1.5 ShortCoT,重点内容包括:RL 训练技术、多模态数据和Infra优化

    • 长上下文扩展和改进的策略优化方法是关键,去掉了对MCTS、Value Model和PRM的依赖
    • k1.5 LongCoT在多个benchmark上实现了与 OpenAI 的 o1 相匹配的性能
    • 通过有效的 long2short 方法,k1.5 ShortCoT 推理结果在benchmark上优于GPT-4o 和 Claude Sonnet 3.5
      论文链接: https://github.com/MoonshotAI/Kimi-k1.5/blob/main/Kimi_k1.5.pdf

    10.1.3 MInimax-01

    论文地址:https://arxiv.org/pdf/2501.08313核心亮点

    1. 超长的文本处理能力(400w token)
    2. 轻量级Attention机制
    3. 是一个MoE架构
    4. 提出了EP+ETP优化该架构下的计算通信
    5. LASP+Varlen ring attention优化并行效率

    10.1.4 Deepseek-GRM

    DeepSeek-GRM:通用奖励建模的推理时扩展

    强化学习应用在大模型上的关键挑战在于,为各种领域获取准确的奖励信号,不仅仅局限于可验证的问题或人为制定的规则。本文研究通过增加推理计算量来改进针对通用问题的奖励建模,同时研究使用恰当的学习方法提高性能-计算量scaling的有效性。本文使用point-wise生成式奖励建模(GRM),并提出了自我原则批判微调(SPCT)学习方法,由此得到了DeepSeek-GRM模型,并引入元奖励(MetaRM)建模来指导投票过程。实验结果在各种奖励建模基准测试中优于现有方法和模型,且不存在严重偏差论文链接: https://arxiv.org/pdf/2504.02495

    Introduction问题背景

    10.1.5 Llama4

    Llama 4系列:原生多模态人工智能创新新时代的开端

    Llama 4系列是第一个原生多模态MoE模型系列,总共包含三个Size的模型,Scout、Maverick和Behemoth,其中Behemoth目前还不能获取仍在训练中(三个名字很有意思,Scout名词释义有童子军/侦察兵的意思,Maverick独行侠看NBA的都懂,Behemoth则是圣经中出现的一个巨型猛兽)Blog:https://ai.meta.com/blog/llama-4-multimodal-intelligence/

    10.1.6 Seed-Thinking-v1.5

    Seed-Thinking-v1.5:利用强化学习推进卓越推理模型发展

    Seed-Thinking-v1.5是 200B 参数的MoE模型,激活参数为20B,benchmark 表现为 AIME 2024 86.7,Codeforces 55.0,GPQA 77.3,展现出在STEM领域和编程方面卓越的推理能力。非推理任务胜率比DeepSeek R1 高出8%,这表明其应用范围更广论文链接: https://github.com/ByteDance-Seed/Seed-Thinking-v1.5/blob/main/seed-thinking-v1.5.pdf

    10.1.7 Seed1.5-VL 技术报告详解

    模型结构

    Seed1.5-VL由三个主要模块组成,分别是:视觉编码器、MLP适配器、LLM。图像/视频输入 → Seed-ViT → MLP Adapter → 多模态Token → MoE LLM

    10.1.8 QwenLong-L1

    QwenLong-L1:走向基于强化学习的长上下文大型推理模型

    近年来,大型推理模型(LRMs)通过强化学习展现出了推理能力。这些提升主要体现在短上下文推理任务中。相比之下,将LRMs扩展至通过RL有效处理和推理长上下文输入仍是一个尚未解决的关键挑战。QwenLong-L1 首先将长上下文推理 RL 范式形式化,并识别出训练效率欠佳和优化过程不稳定等关键挑战具体训练 pipeline: warm-up SFT → 课程引导的分阶段 RL(使用难度感知的回顾性采样策略来鼓励探索)实验结果:在七个长上下文问答 benchmark 上的实验表明,QwenLong-L1-32B 优于 OpenAI-o3-mini 和 Qwen3-235B-A22B 等闭源LRMs,性能与 Claude-3.7-Sonnet-Thinking 相当论文链接: https://arxiv.org/pdf/2505.17667

    10.1.9 Seed 1.6

    Seed 1.6 系列模型技术介绍

    Seed1.6 是通用模型系列,融合多模态能力,支持自适应的深度思考、多模态理解、图形界面操作,且支持 256K 长上下文的深度推理。Seed 1.6 主要探索了 Adaptive CoT 技术,让模型能够根据问题难度自动触发思考过程,取得了模型效果和推理性能的平衡。链接:https://seed.bytedance.com/zh/seed1_6。目前没有技术报告,只有官网的介绍链接,后续出了会进行补充。参考:10.1.6 Seed-Thinking-v1.5

    10.1.10 WebSailor

    通向通用智能体的关键一步——阿里通义发布开源第一的 WebSailor,性能超越 DeepSeek R1、Grok-3,是首个挑战 BrowseComp 基准的开源网络智能体。

    背景

    在互联网信息检索任务中,即使是很强的 LLM,有时也会陷入”信息迷雾”之中:

    • 当问题简单、路径明确时,模型往往能利用记忆或一两次搜索就找到答案;
    • 但面对高度不确定、线索模糊的问题,模型就很难做对。

    举个例子,我们平常问一个直白的问题(比如”某城市的人口是多少”),搜索引擎一查即可。但如果问题被设计得非常复杂——相关线索分散在多个网页、而且描述含糊,比如:

    “这首与南美某首都密切相关的乐曲,其歌词作者在 21 世纪初获颁当地荣誉称号,其旋律创作者曾就读于哥伦比亚西部的一所著名艺术学院。这首乐曲叫什么?”

    ——人类和 AI 都很难直接找到入口。这类问题需要阅读许多网页、抽丝剥茧地拼凑线索,逐步把迷雾拨开,才能找到答案。这超出了人类有限记忆和注意力的负荷,也远远超出了普通开源模型的能力范围:此前开源的 Agent 在类似 BrowseComp 这样复杂的、超越人类能力边界的基准上几乎为零。

    BrowseComp 的挑战在于,它将答案线索拆解得非常零碎,并散布在不同类型和时期的模糊信息源中,形成一张巨大的”信息迷雾网”。这就要求智能体必须主动在广阔的互联网中搜集信息,从海量内容中过滤掉无关的噪声,再通过严密的多步推理和交叉验证,才能将所有线索串联起来;比如下面这个问题,要求智能体追踪一个横跨大陆、涉及几代人的间谍网络。

    10.1.11 Kimi K2

    Kimi K2 是面向 智能体智能(Agentic Intelligence)的 MoE 模型,总参数 1T,激活参数 32B论文链接: https://github.com/MoonshotAI/Kimi-K2/blob/main/tech_report.pdf核心点概述:

    1. 预训练
      • MuonClip 优化器
      • 领域专用重述技术,高效 token 利用
      • 模型架构采用超稀疏 MoE 与 MLA
      • 训练基础设施结合 PP、EP 、 DP(ZeRO-1)、激活重计算、FP8 存储和 CPU 卸载
    2. 后训练
      • SFT:Agent 数据合成管道 pipeline 生成工具使用演示
      • RL:
        ▪可验证奖励 Gym ▪自我批判评分奖励▪算法优化:加入预算控制、PTX 损失、温度衰减Benchmark 测评如下图所示

    10.1.12 DeepSeek V3.2

    DeepSeek V3.2 旨在有效地将高计算效率与卓越的推理和 Agentic 性能结合起来。技术报告地址:https://huggingface.co/deepseek-ai/DeepSeek-V3.2/resolve/main/assets/paper.pdf

    核心创新点:

    1. DeepSeek Sparse Attention (DSA)
    2. 可扩展的强化学习框架
    3. 大规模Agentic任务合成管线

    性能表现:最引人注目的莫过于其高算力变体DeepSeek-V3.2-Speciale所取得的惊人性能。根据其技术报告,该模型既在推理能力上超越了GPT-5,也是达到了与业内顶尖的Gemini-3.0-Pro不相上下的水平。这一成就并非空谈,而是通过在国际顶级竞赛中的表现得到了验证:DeepSeek-V3.2-Speciale在2025IMO、IOI、ICPC World Final和CMO中,均取得了金牌水平的成绩。

    10.1.13 Kimi K2.5

    1. 背景和意义

    过去一年,多模态大模型的主线问题从 能看懂图片 扩展到三个更难的方向:

    1. 原生多模态:不是在强语言模型上后接视觉适配层,而是在预训练与后训练阶段让视觉与语言共同成长。
    2. 长上下文与长视频:多模态输入密度更高,真正落地任务常常是长文档、长网页、长视频、或大量截图/文件集合。

    10.2 o1技术路线论文

    主要是OpenAI-o1出来之后,到Deepseek-R1之前大家对o1技术路线的猜测、复现以及一些开创性工作

    对于简单或者中等难度的逻辑推理问题,通过inference-time 增加算力,比如树搜索等方式,比去增强模型的“预训练”阶段的逻辑推理能力来得效果要明显;而对于高难度的逻辑推理问题,则只靠inference-time很难提升,有时还是负面作用,不如去增强模型“预训练”阶段的逻辑能力

    学习策略优点缺点代表Behaviour Clone Expert

    1. 更像人、专家,并且有人的偏好
    2. 可以通过单agent的方式训练
    3. 当数据量无限多的时候可以取得完美表现
    4. 实际能力由于数据分布有偏
    5. 无法探索出人类行为之外的行为
    6. 无法利用错误数据

    各种游戏陪玩AI,LLM SFT

    10.2.1 STaR: Self-Taught Reasoner Bootstrapping Reasoning With Reasoning

    STaR:自教学推理器,通过推理引导推理

    逐步生成“思维链”推理过程可以提高语言模型在诸如数学或常识问答等复杂推理任务上的性能。然而,目前引导语言模型生成推理过程要么需要构建大量的推理数据集,要么通过仅使用少样本(few-shot)推理来牺牲准确性。来自斯坦福和谷歌的研究人员提出了自教学推理(Self-Taught Reasoner,STaR)方法,通过迭代利用少量推理示例和没有推理过程的大数据集,提升模型在复杂推理任务上的表现,使模型能从自身生成的推理中学习并改进论文链接: https://arxiv.org/pdf/2203.14465

    10.2.2 Let’s Verify Step by Step

    PRM 过程监督奖励模型:让我们一步步验证

    来自OpenAI的研究员探讨了在训练语言模型解决复杂多步推理问题时,过程监督(process supervision)和结果监督(outcome supervision)两种方法的效果,研究发现过程监督在训练模型解决具有挑战性的 MATH 数据集中的问题时显著优于结果监督论文链接: https://arxiv.org/pdf/2305.20050

    一、研究背景研究背景:

    • 大模型逐步推理过程中的逻辑错误和幻觉:大模型虽能通过逐步推理或者逐步思考(CoT, Chain of Thought)解决复杂任务,但即使最为先进的模型也会产生逻辑错误和幻觉,需要通过监督奖励模型来区分理想和不理想的输出

    10.2.3 Quiet-STaR: Language Models Can Teach Themselves to Think Before Speaking

    Quiet-STaR:语言模型可以在输出前自学思考

    Quite-STaR是对Self-Taught Reasoner(STaR)的推广,通讯作者都是一个。Quiet-STaR让LLM学习在每个token处都生成rationales或者thoughts以解释后续的文本,从而改进其预测的效果。本文提出了一种token并行采样算法,使用可学习的token来指示thought的开始和结束,生成的thoughts对难以预测的token有不成比例的帮助,并提高了语言模型直接回答难题的能力。在使用 Quiet-STaR LLM进行继续预训练后, GSM8K(5.9% 提升至 10.9%)和 CommonsenseQA(36.3% 提升至 47.2%)的零样本性能有所提高,并观察到自然文本中困难token的困惑度有所改善论文链接: https://arxiv.org/pdf/2403.09629

    10.2.4 Accessing GPT-4 level Mathematical Olympiad Solutions via Monte Carlo Tree Self-refine with LLaMa-3 8B

    MCTSr:蒙特卡洛树自优化算法增强大模型推理

    来自复旦大学和上海AIlab的研究人员提出了结合蒙特卡洛树搜索(MCTS)和自优化(Self-refine)的 MCT自优化(MCTSr)算法,旨在提升 LLMs 在复杂数学推理任务(如数学奥林匹克竞赛问题)中的性能,增强决策准确性和可靠性论文链接: https://arxiv.org/pdf/2406.07394

    10.2.5 Monte Carlo Tree Search Boosts Reasoning via Iterative Preference Learning

    MCTS-IPL:蒙特卡洛树搜索增强的迭代偏好学习

    来自新加坡国立大学和DeepMind的研究人员提出了一种利用MCTS蒙特卡洛树搜索生成偏好数据的迭代式DPO直接偏好优化方法来增强大型语言模型推理能力。受AlphaZero的启发,本文利用MCTS将instance-level奖励分解为更细化的step-level signals来收集偏好数据,然后直接用iterative DPO更新LLM的策略。本文方法在 GSM8K、MATH 和 ARC-C 数据集上的表现优于 Mistral-7B 监督微调(SFT)基线,准确率分别大幅提升至 81.8%(提高了 5.9%)、34.7%(提高了 5.8%)和 76.4%(提高了 15.8%)论文链接: https://arxiv.org/pdf/2405.00451

    一、研究背景研究背景:

    10.2.6 Q*: Improving Multi-step Reasoning for LLMs with Deliberative Planning

    Q*:利用深思熟虑的规划增强大模型多步推理

    自回归生成过程使得大语言模型在进行多步推理时容易产生错误、幻觉和不一致的陈述。来自昆仑万维和南洋理工大学的研究人员提出了 Q方法,这是一个通用、灵活且敏捷的框架,通过将大语言模型的多步推理视为一个启发式搜索问题,利用深思熟虑的规划来提高大语言模型的多步推理能力,将 LLMs 的多步推理过程形式化为马尔可夫决策过程(MDP),并使用 A 搜索算法和 Q 值函数建模来引导模型选择最有希望的推理步骤,从而提高多步推理性能。在 GSM8K、MATH 和 MBPP 上进行的大量实验证明了方法的优越性,有助于提高现有开源大语言模型的推理性能论文链接: https://arxiv.org/pdf/2406.14283

    10.2.7 o1-Coder: an o1 Replication for Coding

    o1-Coder:代码任务的o1复现技术报告

    来自北交大的团队介绍了o1-Coder,这是一个旨在复制 OpenAI 的 o1 模型并专注于代码任务的项目。o1-Coder集成了强化学习RL和MCTS以增强大模型的System-2思维能力。o1-Coder的框架主要包括训练一个测试用例生成器(TCG)用于标准化代码测试,使用MCTS生成带有推理过程的代码数据,最后迭代地微调策略模型。目前代码部分开源,并公布后续更新计划,包括RFT训练代码论文链接: https://arxiv.org/pdf/2412.00154代码链接:https://github.com/ADaM-BJTU/O1-CODER

    一、研究背景

    • o1 模型的影响:OpenAI 的 o1 模型具有出色的System-2思维能力(更深入、审慎和逻辑的思考步骤),推动了 AI 推理模型研究的发展,引发众多学术和工业界的复制尝试,截至o1-coder工作出来的时间已经有的相关工作如下图所示

    10.3 Prompt技术

    10.3.1 Self-Refine: Iterative Refinement with Self-Feedback

    论文地址:Self-Refine: Iterative Refinement with Self-Feedback一、研究背景

    Self-Refine模仿人类的三步过程,其中从LLM得到的初始输出通过一系列迭代反馈进行精炼。 这种方法最大的优势是它不需要任何监督训练数据、额外训练或强化学习。 一个单一的大型语言模型被用于生成、改进和反馈。

    二、研究方法

    生成 → 自我反馈 → 修改 → 自我反馈 → 修改……结合了模型「指令遵循」和「评估」能力。Self-Refine 依赖这两个能力,如果在某项任务上评估能力不足,那就没效果。如果外部评估准,可以引入外部评估,也能有效

    10.3.2 Tree of Thoughts: Deliberate Problem Solving with Large Language Models

    论文地址:Tree of Thoughts: Deliberate Problem Solving with Large Language Models一、 研究背景

    在我们处理新问题的时候,我们会经常意识到我们会需要反复的调整、探索才会得到最后的一个做法探索过程中会生成一些启发式信息,有助于产生新的发现因此就需要树结构
    – 树结构搜索是AI通用的一种问题解决过程
    – 相比于大语言模型,symbolic AI因为其手动的启发式算法限制了其通用性
    – 因此,大语言模型的通用特性与树结构的优势结合,会不会得到更好的performance

    二、研究方法

    10.4 LLM-as-Judge

    问题背景和进展

    近一年来,大型语言模型(LLMs)在各种自然语言处理(NLP)任务上迅速发展,并接近于人类水平的表现,这些任务包括问答、文本摘要、对话生成和代码生成。尽管取得了这些进步,但LLMs仍然经常产生虚假、不可靠和不连贯的输出,因此如何去评估LLMs生成的内容是一个非常值得讨论的方向

    在当前的自然语言处理(NLP)领域,文本生成的质量评估是一个关键的课题。随着大型语言模型(LLMs)如 GPT-4 和其他先进模型的出现,自动文本生成的能力已经取得了显著的进步。这些模型不仅能够产生高度连贯和语境相关的文本,而且在多步推理、信息提供、以及生成准确、信息丰富的回答方面展示了前所未有的能力。然而,随着这些模型的常用,评估它们生成的文本质量的准确性和公正性变得尤为重要

    传统工作中,文本生成的质量评估主要关注两个方面:

    • 生成文本是否达到了正确的结论;
    • 文本内容的信息量和有用性。
      下面是若干常见评估文本质量的指标;
    • BLEU : 用于评估机器翻译质量,但也可用于评估任何文本生成任务。它通过比较机器生成的文本与一个或多个参考文本之间的重叠来工作。
    • ROUGE : 主要用于自动摘要,通过比较生成文本与参考摘要之间的重叠来评估内容的覆盖度。
    • METEOR: 类似于BLEU,但考虑了同义词的匹配,以及词序对翻译质量的影响。
    • BERTScore: 利用预训练的BERT模型来评估生成文本与参考文本之间的语义相似度。

    10.4.1 自建评估体系

    所谓的自建评估体系就是本身建设指标或者流程来进行评估生成的文本,自建评估体系需要考虑到灵活性和可扩展性。2023年以来此类研究较多,下面简单介绍三篇此类研究方法的文章。

    Are Machine Rationales (Not) Useful to Humans? Measuring and Improving Human Utility of Free-Text Rationales ROSCOE: A SUITE OF METRICS FOR SCORING STEP-BY STEP REASONING RECEVAL: Evaluating Reasoning Chains via Correctness and Informativeness

    10.4.2 自训 Critical 模型

    考虑到人工评估生成文本质量的代价较大,自训Critical模型可能是一个不错的选择方案,通过自训Critical模型来评估生成文本质量并进行反馈也是一个非常热门的研究方向。下面给出四篇在这个方向的论文。

    Shepherd: A Critic for Language Model Generation TIGERSCORE: TOWARDS BUILDING EXPLAINABLE METRIC FOR ALL TEXT GENERATION TASKS Digital Socrates: Evaluating LLMs through explanation critiques CRITIQUELLM: Scaling LLM-as-Critic for Effective and Explainable Evaluation of Large Language Model Generation

    10.4.3 调用强基座模型

    LM vs LM: Detecting Factual Errors via Cross Examination A Closer Look into Automatic Evaluation Using Large Language Models Large Language Models are not Fair Evaluators

    10.5 拓展阅读

    这里记录一些其他类型的拓展阅读笔记

    10.5.1 Welcome to the Era of Experience

    强化学习祖师爷 Sutton 及其学生 AlphaGo 创始人之一的 David Silver一起撰写了《欢迎来到经验时代》这篇文章,被称为是强化学习(或智能体)版的《苦涩的教训》(The Bitter Lesson)我们正站在人工智能新时代的起点,这个时代有望实现前所未有的能力提升。新一代的智能体将通过从经验中学习来获得超越人类的能力,本文探讨这一即将到来的时代的关键特征

    链接:https://storage.googleapis.com/deepmind-media/Era-of-Experience%20/The%20Era%20of%20Experience%20Paper.pdf

    人类数据的时代 The Era of Human Data近年来的人工智能的显著进展依赖于使用大量人类生成的数据进行训练,并利用人类专家的示例和偏好进行微调。大语言模型 LLM 就是这种方法的典型代表,且通过这种方式 LLM 已具备了广泛的通用性,可以执行从写诗、解决物理问题,到诊断医疗问题和总结法律文件的各种各样的任务人类数据存在的问题:模仿人类足以在一定程度上重现人类的许多能力,但在许多重要的主题和任务上,目前尚未实现、而且很可能无法实现超越人类的智能水平

    • 在数学、编程和科学等关键领域,大多数高质量数据来源已经被使用或即将耗尽。仅从人类数据中进行监督学习带来的进步速度放缓,这表明需要一种新的方法

    10.5.2 Why We Think

    OpenAI 前安全副总裁 Weng Lilian 5 月又更新了自己的博客,上一次更新还是 24 年的 11 月。测试时计算(Test Time Compute,Graves et al. 2016;Ling et al. 2017;Cobbe et al. 2021)以及思维链(Chain of Thought, CoT,Wei et al. 2022;Nye et al. 2021)在模型性能提升方面有巨大作用,同时也引发了许多研究问题。这篇 Why We Think 主要回顾了近期关于有效使用测试时计算以及其为什么有效的进展。

    链接:https://lilianweng.github.io/posts/2025-05-01-thinking/

    动机 Motivation可以通过几种不同的方式来激励模型能够更长时间地思考

    类比心理学 Analogy to Psychology核心点在于,人类是如何思考的🤔?人类通常不能直接给出下面这个问题的答案:”12345 乘以 56789 得多少?”相反,人类在得出结果之前花时间思考和分析,尤其是对于复杂的问题,这是很自然的。在Thinking, Fast and Slow (Kahneman, 2013) 中,基于双系统理论,人类思考模式被分类为两种:

    • 系统1 快思考:快速、自动的思考,由直觉和情感驱动,几乎不消耗任何努力、精力
    • 系统2 慢思考:需要深思熟虑、逻辑思维和显著的认知努力,消耗更多的精神能量,需要有意识的参与
      系统1思考简单且迅速,所以通常最终成为主要的决策驱动因素,但是代价是牺牲一定的准确性和逻辑。其天然依赖于人类大脑的思维捷径(例如启发式方法),而且可能导致错误和偏差。通过有意识地花更多时间进行反思、改进和分析,我们可以进行系统2思考,挑战人类本能,做出更理性的选择

    10.5.3 WorldPM:Qwen 在偏好建模的「大模型」新突破

    价值信息总结Scaling Trends

    • 在大规模训练过程中,WorldPM在约 12.6M 样本处出现顿悟时刻,即损失骤降与梯度剧烈波动并发,表明模型找到了更有效的偏好表征方式,表现出更强的泛化能力。
    • 在具备明确参考答案的评测任务中,模型呈现清晰的power-law缩减趋势,即模型规模与训练数据越大,表现越好。但在主观性任务中未体现出类似趋势。
    • 对抗性评测中,模型对错误或无关响应的识别能力随着训练扩展显著增强,说明充足的数据可缓解RLHF中reward hacking问题。
    • 客观性评测中,只有在72B下才表现出全面的scale benefit,证明偏好建模本身的复杂性与门槛。
    • 主观性评测中,无明显缩减趋势,且模型在某些测试中反而随训练数据增加表现恶化,表明当前主观性评价中存在结构性矛盾。

    Style Impact Analysis

    • 通过引入响应长度、Markdown格式等风格特征,构建风格控制机制,将奖励分为内容得分和风格得分,以此分离风格对模型评测的干扰。

    10.6 工作推荐系列

    10.6.1 25 年 5 月 LLM reasoning 工作推荐

    综述

    1. Stop Overthinking: A Survey on Efficient Reasoning for Large Language Models
    2. Towards reasoning era: A survey of long chain-of-thought for reasoning large language models
    3. A Survey of Efficient Reasoning for Large Reasoning Models: Language, Multimodality, and Beyond
    4. Towards Large Reasoning Models: A Survey of Reinforced Reasoning with Large Language Models
      Overthinking
    5. The Danger of Overthinking: Examining the Reasoning-Action Dilemma in Agentic Tasks
    6. OVERTHINKING: Slowdown Attacks on Reasoning LLMs
    7. Between Underthinking and Overthinking: An Empirical Study of Reasoning Length and correctness in LLMs
    8. Innate Reasoning is Not Enough: In-Context Learning Enhances Reasoning Large Language Models with Less Overthinking
      RL算法
    9. StreamRL: Scalable, Heterogeneous, and Elastic RL for LLMs with Disaggregated Stream Generation
    10. An Empirical Study on Eliciting and Improving R1-like Reasoning Models
    11. DAPO: an Open-Source LLM Reinforcement Learning System at Scale
    12. Flow-GRPO: Training Flow Matching Models via Online RL
    13. Deep Policy Gradient Methods Without Batch Updates.Target Networks, or Replay Buffers
    14. Optimizing Chain-of-Thought Reasoners via GradientVariance Minimization in Rejection Sampling and RL

    10.6.2 近半年大模型 Agentic RL 训练论文梳理

    标题主题一句话总结
    Expanding LLM Agent Boundaries with Strategy-Guided Exploration训练方法/算法将探索从低层动作迁移到”自然语言策略空间”,用策略引导与多温度采样提升多环境下的探索效率与最终成功率。
    GAC: Stabilizing Asynchronous RL Training for LLMs via Gradient Alignment Control训练稳定性指出异步策略梯度会出现”梯度 stale-alignment”导致不稳定,并用梯度投影控制对齐方向来恢复稳定训练动力学。
    Contextualized Privacy Defense for LLM Agents安全性与对齐奖励提出上下文化防护指令作为主动式隐私防护点,并通过将隐私违规失败轨迹转化为环境、对指导模型进行 RL 训练来提升鲁棒性。
    Memex(RL): Scaling Long-Horizon LLM Agents via Indexed Experience Memory记忆;样本效率用”索引化经验记忆”把长历史证据外置到数据库并在上下文里保留索引,再用 RL 同时优化写入/读取策略以更好完成长程任务。
    RetroAgent: From Solving to Evolving via Retrospective Dual Intrinsic Feedback内在奖励/自进化通过”回顾式双重内在反馈”驱动智能体从完成任务走向自我演化,强调从事后反思/内部信号中构造学习增益。
    Agentic Critical Training奖励与回报建模将”自我反思”从模仿学习转为 RL:训练模型在备选动作中做出更优动作判断,以”判断是否正确”的奖励促生更真实的行动质量推理。
    Exploratory Memory-Augmented LLM Agent via Hybrid On- and Off-Policy Optimization探索;样本效率提出混合 on/off-policy 的 EMPO²,并引入记忆模块辅助探索,使策略既能”带记忆时高效探索”,也能”无记忆时保持鲁棒”。
    SELAUR: Self Evolving LLM Agent via Uncertainty-aware Rewards奖励与回报建模;探索;训练稳定性将模型不确定性(熵/置信度/边际等)显式注入奖励与失败感知重塑,提供更密集的学习信号以提升探索与稳定性。
    Agent World Model: Infinity Synthetic Environments for Agentic Reinforcement Learning环境与任务设计;样本效率;奖励设计构建代码驱动、数据库支撑的可执行合成环境管线(规模到 1,000 环境),并在其中进行大规模在线 RL 训练以提升 OOD 泛化。
    ScaleEnv: Scaling Environment Synthesis from Scratch for Generalist Interactive Tool-Use Agent Training环境与任务设计;样本效率从”域关键词”出发自动构建可交互环境与可验证任务,强调程序化测试与可执行动作验证,并研究环境域数扩展与泛化的关系。

    11. Practice 大模型实践内容

    这章在讲什么:动手部分。两类:练习项目(nanoGPT、从零训 SFT/DPO/蒸馏 等),简历项目(Agentic RAG+RL、code review agent)。

    看完前 9 章理论,至少跑通一两个练习项目,才知道理论里哪些是”纸上工程”。简历项目是给求职用的样板。

    💸 大模型实践内容,主要包括大模型训练相关的技术实战,涵盖 SFT、PPO、DPO、ReFT、RM、PRM 以及蒸馏的训练练习;包括大模型应用 Agent、RAG 的项目实战。

    本章包含:

    • 🏢 9.1 练习项目
    • 🧾 9.2 简历项目

    11.1 练习项目

    从源码理解并进行练习的小项目列表(按章节排列):

    11.1.1 nanoGPT:从头训练一个 GPT

    前期准备

    • 准备环境:新建一个 conda 环境,并安装依赖的包(如果你不会 Anaconda 环境管理,建议先学一下)。
    conda create -n nano python=3.10
    conda activate nano
    
    # 安装 PyTorch,可以去 https://pytorch.org/get-started/previous-versions/ 挑选合适的版本
    pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu118
    
    # 安装一些补充包
    pip install matplotlib
    

    其实这个数据集很小,可以直接打开上面的链接复制到新建txt文件里面😎代码解析

    11.1.2 OpenRLHF 微调教程及代码解析

    简介以及安装OpenRLHF 是一个基于 Ray、DeepSpeed 和 HF Transformers 构建的高性能 RLHF 框架:

    1. 简单易用: OpenRLHF 是目前可用的最简单的高性能 RLHF 库之一,无缝兼容 Huggingface 模型和数据集
    2. 高性能: RLHF 训练中 80% 的时间用于样本生成阶段。得益于使用 Ray, Packing Samples 以及 vLLM 生成加速的能力,OpenRLHF 的性能是优化的 DeepSpeedChat with Hybrid Engine 的3~4倍以上
    3. 分布式 RLHF: OpenRLHF 使用 Ray 将 Actor、Reward、Reference 和 Critic 模型分布到不同的 GPU 上,同时将 Adam 优化器放在 CPU 上。这使得使用多个 A100 80G GPU 和 vLLM 可以全面微调超过 70B+ 的模型 以及在多个 24GB RTX 4090 GPU 上微调 7B 模型
      同时OpenRLHF也支持全量SFT、QLoRA参数高效微调、KTO算法、PRM训练等
    • 环境准备:新建一个 conda 环境,并按照 OpenRLHF 的 README 进行操作。自己学习训练的话可以不使用 docker,推荐安装 vLLM 0.6.4.post1;在安装 vLLM 前应该先安装 PyTorch,否则会报依赖错误。git clone 网络有问题可以直接下载 zip 压缩包;如果在后续训练脚本中遇到 ninja 相关问题,需要 apt install ninja-build
    conda create -n openrlhf python=3.11
    conda activate openrlhf
    
    # 启动 docker container
    # docker run --runtime=nvidia -it --rm --shm-size="10g" --cap-add=SYS_ADMIN \
    #   -v $PWD:/openrlhf nvcr.io/nvidia/pytorch:24.07-py3 bash
    
    # sudo pip uninstall xgboost transformer_engine flash_attn -y
    # pip install openrlhf
    

    11.1.3 Qwen2.5-Math-PRM 代码复现

    Qwen2.5-Math-PRM和MM-01在这段时间风头正盛,可以Qwen的技术报告细节确实不够,大部分技术点只能靠猜,笔者这昨天闲来无事想着复现一下这项工作,当然可优化的点还有很多,目前只是一个demo。

    前期准备数据集:你需要一个高质量Prompt数据集,MATH的训练集是你很好的选择硬件资源:你需要2张显卡24G以上的显卡其他:待训练的Qwen2.5-Math-Instruct模型,qwen 或其他系列的 api

    • 涉及到的库:
    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torch.utils.data import Dataset, DataLoader
    from typing import List, Dict
    import re
    from openai import OpenAI
    from prompt import *
    import random
    import numpy as np
    from transformers import AutoTokenizer, AutoModelForCausalLM
    

    ok,废话不多说,开始代码拆解。

    11.1.4 从零开始训练大模型(预训练篇)

    最近室友实验室的卡没人用了,为了杜绝资源浪费,准备开启一个新的系列:从零开始训练大模型。我会从数据收集、数据清洗、模型构建、训练代码等角度详细进行拆解

    数据准备做Pretrain首先得收集大量数据,可以是开源的也可以去爬取定向网站,笔者从这两个维度讲讲如何准备数据。优质的开源数据数据名称语种量级Skywork/Skypile-150B中文600G wikipedia-zh-cn-20240820中文1.99G WuDao Corpora中文1T

    xuqinyang/BaiduBaike-5.63M

    中文5.63M RedPajama英文1T爬取数据如果想加入一些比较垂域的数据,需要对特定的网站进行爬虫,或者利用爬虫技术基于关键词向特定网站爬数据。

    • 爬取定向网站脚本示例

    11.1.5 从零开始训练大模型(ReFT 篇)

    本期基础上次的从零开始训练大模型(预训练篇)。笔者本来想先按照传统的SFT+DPO来做,但是突然想试试之前OpenAI提出的ReFT,跳过SFT做直接做RLHF。想验证一下ReFT在小模型上是否work。后面会出SFT+各类DPO变体的实验,并把模型迭代的优化方案整理出来,继续迭代Base和Chat model。

    数据准备可以选择下面三种数据集中的任意一种,因为训练的Qwen-0.8B主要是中文模型,故选用了中文COT数据集GSM8K_zh

    数据集名称量级语种处理脚本gsm8k 8.4k英语

    data-jucier/configs/data_juicer_recipes/gsm-8k.yaml

    math-eval/TAL-SCQ5K 5k中文

    data-jucier/configs/data_juicer_recipes/TAL-SCQ5K.yaml

    meta-math/GSM8K_zh 8K中文

    data-jucier/configs/data_juicer_recipes/GSM8K_zh

    laihuiyuan/mCoT-MATH 60w中文

    data-jucier/configs/data_juicer_recipes/GSM8K_zh

    数据选择

    若使用mCoT-MATH数据集来进行Reft训练,由于数据量有60w条,感觉不太需要这么多,需要做下数据选择。

    11.1.6 从零开始训练大模型(SFT 篇)

    本章节是在预训练完成的Qwen-0.8B模型的基础上进行SFT实践,通过进行数据清洗和数据配比获得训练数据集,然后在DS zero2下进行微调(在小尺寸的模型上建议使用全参微调)

    数据准备及清洗数据准备SFT训练数据的量级一般在10w左右,考虑到0.8B小尺寸模型,本文通过Data-Juicer进行数据清洗,最终筛选到15w的数据作为训练集。以下是源数据集:

    名字类型地址RefGPT多轮对话

    https://github.com/DA-southampton/RedGPT

    firefly-train-1.1M通用数据

    https://huggingface.co/datasets/YeungNLP/firefly-train-1.1M

    ShareChat对话翻译

    https://paratranz.cn/projects/6725

    数据清洗老规矩,先用data-jucier做数据过滤,最终得到14w条指令微调数据集。

    • 处理算子包括词重复度、语言分值、PPL、特殊词占比、文本长度、平均下划线长度等。

    11.1.7 从零开始训练大模型(DPO 篇)

    本章为大模型训练的最后一篇,在日常学习和大模型应用组中DPO依然是大部分人的选择,本章将会详细地从数据构造、模型训练和效果评估层面讲讲如何基于SFT模型训练得到一个对齐模型。

    1. 数据准备及构造
      开源的DPO数据集数据名介绍地址

    distilabel-capybara-dpo-7k-binarized

    多轮对话偏好数据集

    argilla/distilabel-capybara-dpo-7k-binarized

    HC3-Chinese由问题及其相应的人类/GPT 答案组成

    Hello-SimpleAI/HC3-Chinese

    zhihu_rlhf_3k知乎问答的人类偏好数据集liyucheng/zhihu_rlhf_3k Infinity-Preference智源的DPO数据集BAAI/Infinity-Preference

    • 训练数据格式:
    {
      "task_category": "xxx",
      "prompt": "xxx",
      "chosen": [{"content": "xxx", "role": "user"}]
    }
    

    11.1.8 分类任务上 Bert 和 LLM 谁更强

    面试的时候经常会被问到分类任务上,Bert和LLM谁的效果更好? 之前其实没有做过实验,回答起来没有底气。今天就用实验来说明谁的效果更好。

    前期准备在实验开始之前,你需要准备如下资源:

    1. 一张显存至少24G的显卡
    2. 短文本分类数据stanfordnlp/imdb、长文本ASR数据
    3. Qwen2.5-3B、Qwen2.5-3B-Instruct、Llam3.2-3B、Llama-3.2-3B-instruct、Bert

    实验设置

    1. 全量数据
    2. 随机抽取200条训练数据
    3. 筛选长文本数据
      数据预处理
    4. 从HF加载数据
      a.数据集介绍stanfordnlp/imdb

    11.1.9 OpenR 库 PRM+MCTS 实践

    虽然 DeepSeek-R1 推动了大模型纯强化学习范式的兴起,其技术报告也提到过关于 PRM+MCTS 的一些局限性,但是 PRM+MCTS 也不失为一种在 base model 能力较弱的情况下增强推理能力的方法。

    简介与安装相关技术报告:OpenR: An Open Source Framework for Advanced Reasoning with Large Language Models Github链接:https://github.com/openreasoner/openr OpenR 是一个专注 LLM 推理的开源框架,目前集成了以下功能:

    功能内容过程监督的数据生成

    • OmegaPRM: Improve Mathematical Reasoning in Language Models by Automated Process Supervision

    在线策略训练

    • 强化学习训练: 使用PRM进行在线RL训练,支持PPO、GRPO、TPPO算法

    PRM奖励模型的训练

    • PRM 训练: Supervised Training for PRMs
    • 生成式奖励模型训练: Direct GenRM

    多种搜索策略

    • Greedy Search
    • Best-of-N
    • Beam Search
    • MCTS
    • rStar: Mutual Reasoning Makes Smaller LLMs Stronger Problem-Solvers

    11.1.10 从零开始训练大模型(蒸馏篇)

    理论基础

    • 蒸馏的重要意义
      知识蒸馏是通过让轻量级学生模型学习教师模型的知识分布来提升小模型性能的技术,其核心在于利用教师模型输出的软标签(概率分布)替代传统监督学习的硬标签,通过KL散度损失函数使学生模型模拟教师模型的决策逻辑。相较于直接拟合答案的SFT,蒸馏过程更关注捕捉教师模型内部的推理特征,如大模型处理”1+1=2″时神经元的激活模式。在大模型时代,针对GPT-4等闭源系统的黑盒蒸馏成为主流,其实就是通过微调对齐大模型输出,在保持小模型体积(可压缩至原模型10%-20%)的同时逼近其推理能力,但需配合5万条以上的高质量指令数据以避免性能衰减。
    • 输出层蒸馏(软标签匹配)
      通过对齐教师模型输出的概率分布(软标签)训练学生模型,使用KL散度或交叉熵作为损失函数。这种方法直接模仿教师的最终决策,适用于分类任务,但对中间推理过程的捕捉有限,代表工作包括Hinton的经典蒸馏框架。
    • 数据增强蒸馏
      数据增强蒸馏主要通过教师模型生成多样化合成数据(如指令-响应对、思维链推理路径)或引入对抗扰动、扩散模型扩展原始训练集,结合动态质量过滤机制保留有效知识,使学生模型在增强的数据分布中学习教师的知识泛化模式,同时利用对比学习区分生成数据与真实数据的特征边界,缓解因合成数据噪声导致的性能衰减问题。

    准备工作

    • 在开发之前,你需要安装下面这些库

    11.1.11 白盒蒸馏 DeepSeek R1 32B

    在上一期大模型实践介绍了基于数据的大模型知识蒸馏,也就是我们所说的软蒸馏方法。本期介绍一下在传统NLP下常用的蒸馏策略:基于KL进行硬蒸馏。为了保证模型的效果

    一、 前期准备

    • 需要有两张3090级别以上的显卡。
    • 学生模型我选用的是Qwen2.5-1.5B,教师模型选用的R1-32B。
    • 为了取巧一些,训练的sft数据我们了蒸馏满血R1的数据集distill_r1_110k_sft.jsonl,数据集中不仅包含math数据,还包括大量的通用类型数据,总数量为110K。
      • 数据格式:
    • 为了确保程序顺利执行,用户需要安装下列库:
    datasets==2.21.0
    datasketch==1.6.4
    Flask==3.0.3
    Flask_Cors==4.0.0
    jieba==0.42.1
    jsonlines==4.0.0
    marshmallow==3.22.0
    matplotlib==3.5.1
    ngrok==1.4.0
    nltk==3.8
    numpy==1.26.4
    

    11.1.12 基于 MCP 实现的企业内部工具 agent 工作流

    首先来解析mcp_server.py ,其采用 Python 标准库中的 http.server,通过继承 BaseHTTPRequestHandler 实现对 POST 请求的统一处理。核心在于解析 HTTP 请求体中的 JSON-RPC 2.0 结构,分发到不同方法并返回 JSON。

    下面展示了如何读取请求、解析 JSON-RPC 字段、构造响应模板并调用 _send_response。这部分框架在大多数基于 JSON-RPC 的 HTTP 服务中都会存在:读取 method 字段决定走向,若未命中则返回 “Method not found”。

    11.1.13 基于 vllm+fschat 的数据合成 Agent 框架实现

    本节内容待补充。

    11.2 简历项目

    可以直接拿去写简历的项目列表:

    11.2.1 垂直领域多跳 Agentic RAG & RL 简历项目

    知识回顾

    使用指南

    项目的所有代码可以在 大模型笔记代码、简历模板及书籍资源下载 里面下载。

    • 项目详细讲解:AgenticRAG+RL 项目详解
    • 代码详细使用教程:AgenticRAG+RL 代码实战操作指南
    • 面试表达:AgenticRAG+RL 项目面试如何描述?
    • 面试题库:AgenticRAG+RL 项目面试题库

    看不懂的地方,或者面试遇到问题,可以划线评论提问,或者在文档底部对整个文档进行评论;解决问题的评论不要点解决,方便大家查看。

    11.2.2 基于 Agentic 的 code review 简历项目

    使用指南

    项目的所有代码可以在 大模型笔记代码、简历模板及书籍资源下载 里面下载。

    • 项目详细讲解:项目详解
    • 面试表达:面试表达模板
    • 面试题库:面试题库

    看不懂的地方,或者面试遇到问题,可以划线评论提问,或者在文档底部对整个文档进行评论。

    项目简介

    自动化代码审查 AI Agent,实现四阶段 PR 审查流程(Triage → Analyze → Review → Act),集成 11 个 GitHub 工具和 6 个 Memory 工具,自动发现安全漏洞、提交 inline review comments、对可修复问题创建 Fix PR,同时以 JSONL 格式采集完整工具调用轨迹,导出 SFT/DPO/工具监督三种训练数据格式。

    简历写法参考

    Agent 系统设计与工具编排:基于 Claude claude-opus-4-6 实现四阶段代码审查 Agent(Triage → Analyze → Review → Act),设计 30 轮安全上限的 tool-use 主循环;集成 11 个 GitHub 工具(PR 信息获取、diff 分析、inline review 批量提交、Fix PR 自动创建)和 6 个 Memory 工具;实现从 PR 读取到 review 提交的全自动化流程,支持 dry-run 模式用于开发调试。

    关键词:tool-use 主循环、工具编排、干运行模式。

    面试官追问时可以展开讲:

    • 30 轮上限的设计理由;
    • tool_router 的截断策略;
    • dry-run 模式的工程价值。

    12. Interview 大模型面试八股&手撕

    这章在讲什么:求职导向。Python 基础八股、面经合集、Transformer 参数量计算、答案题库、手撕代码、ML/DL 八股、面试经验总结。

    前面 1-9 章是”知道是什么”,这章是”能在面试里讲清楚”。两者差距不小,建议刷完真题再去面。

    👩💻 大模型算法面经和八股收集,也包含 Python 和经典机器学习、深度学习相关八股。

    本章包含:

    • 🏄♀️ 10.1 Python 相关八股
    • 🚅 10.2 实习校招秋招春招面经合集
    • ⛑️ 10.3 Transformer 量化分析计算
    • 🍑 10.4 八股面经(含答案)
    • 🧤 10.5 面试手撕专题
    • 💾 10.6 机器学习深度学习八股(初稿)

    12.1 Python相关八股

    12.1.1 基础问题

    1. Python数据类型:请解释Python中的常见数据类型,如列表、元组、集合和字典。它们之间有什么区别?
      • 列表(List):有序且可变的数据集合,使用方括号[]表示。
      • 元组(Tuple):有序且不可变的数据集合,使用圆括号()表示。此外不可变对象还有string、int、float、bool
      • 集合(Set):无序且不重复的数据集合,使用花括号{}表示。
      • 字典(Dictionary):键值对的无序集合,使用花括号{}表示,键是唯一的。
    2. 列表与元组的区别:在什么情况下你会选择使用列表而不是元组,反之亦然?
      • 列表:可变,支持增删改操作,适合需要频繁修改的数据。
      • 元组:不可变,创建后无法修改,适合存储不可变的数据,且因为不可变,所以速度比列表更快。
    3. 字符串操作:如何反转一个字符串?请写出相应的 Python 代码。 def reverse_string(s): return s[::-1]
    4. ==is 有什么区别?
      • 使用==操作符比较两个对象的值是否相等。
      • 使用is操作符比较两个对象是否是同一个对象(即是否有相同的内存地址)
    5. python是一种动态语言

    12.2 实习校招秋招春招面经合集

    京东直播-搜推

    1. 自我介绍
    2. 了解多少搜推知识
    3. 介绍一下RLHF流程
    4. 了解ANN算法吗,介绍Faiss的检索原理
    5. 推荐项目里的图检索具体是如何实现的
    6. 算法题:最大子数组和问题
    def max_subarray_sum(nums):
        # 初始化最大和为负无穷,当前和为 0
        max_sum = float('-inf')
        current_sum = 0
        for num in nums:
            # 如果当前和为负数,则重置为当前元素
            current_sum = max(num, current_sum + num)
            # 更新最大和
            max_sum = max(max_sum, current_sum)
        return max_sum
    
    # 示例数组
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    print(max_subarray_sum(nums))   # 输出应为 6,对应子数组 [4, -1, 2, 1]
    

    12.3 Transformer 量化分析计算

    主要分析 Decoder-only 架构的参数量与显存占用。

    12.3.1 模型参数量计算

    • self-attention 块:Q、K、V 以及输出 O 的四个权重矩阵和 bias,形状分别为 (h, h) 与 (h,),总参数量为 4h^2 + 4h。
    • MLP 块:第一个线性层权重和 bias 为 (h, 4h) 与 (4h,);第二个线性层为 (4h, h) 与 (h,);总参数量 8h^2 + 5h。
    • LN 部分:两个 LayerNorm,每个都有两个参数 \gamma, \beta,形状为 (h,),总参数量 4h。
    • Embedding 层:词表大小为 V,形状 (V, h),总参数量 Vh。
    • 位置编码:绝对位置编码形状 (l, h),l 为最大序列长度;RoPE、ALiBi 等相对位置编码不引入额外可训练参数。
    • Output 层:同 Embedding 层,形状 (h, V),参数量 Vh。

    12.4 八股面经(含答案)

    12.4.1 RNN、CNN和Transformer三大NLP特征提取器对比

    • RNN:采取线性序列结构不断从前往后收集输入信息,但这种线性序列结构在反向传播的时候存在优化困难问题,因为反向传播路径太长,容易导致严重的梯度消失或梯度爆炸问题。RNN 结构(LSTM、GRU)存在序列依赖,对大规模并行非常不友好。
    • CNN:卷积层其实是保留了相对位置信息的,并行能力比较强。

    RNN、CNN、Transformer 对比:

    1. 语义特征提取能力:Transformer 在这方面的能力非常显著地超过 RNN 和 CNN,RNN 和 CNN 两者能力差不太多。
    2. 长距离特征捕获能力:原生 CNN 特征抽取器在这方面极为显著地弱于 RNN 和 Transformer,Transformer 微弱优于 RNN(尤其在主语谓语距离小于 13 时),能力由强到弱排序为 \text{Transformer} > \text{RNN} \gg \text{CNN};但在比较远的距离上(主语谓语距离大于 13),RNN 微弱优于 Transformer,所以综合看,可以认为 Transformer 和 RNN 在这方面能力差不太多,而 CNN 则显著弱于前两者。
    3. 任务综合特征抽取能力(机器翻译):Transformer 综合能力要明显强于 RNN 和 CNN,而 RNN 和 CNN 看上去表现基本相当,貌似 CNN 表现略好一些。
    4. 并行计算能力及运行效率:RNN 在并行计算方面有严重缺陷,这是它本身的序列依赖特性导致的;对于 CNN 和 Transformer 来说,因为它们不存在网络中间状态不同时间步输入的依赖关系,所以可以非常方便及自由地做并行计算改造。Transformer 和 CNN 差不多,都远远远远强于 RNN。

    单从任务综合效果方面来说,Transformer 明显优于 CNN,CNN 略微优于 RNN。速度方面 Transformer 和 CNN 明显占优,RNN 在这方面劣势非常明显。

    12.4.2 手撕交叉熵

    首先是交叉熵的公式:

    \mathcal{L}_{\text{CE}} = -\sum_{i=1}^{C} y_i \log \hat{y}_i

    其中 C 为类别数,y_i 是 one-hot 编码的真实标签(仅在正确类别上为 1),\hat{y}_i 是模型对第 i 个类别的预测概率(通常由 Softmax 输出)。对单一样本,等价于 -\log \hat{y}_{\text{true}}。

    12.5 面试手撕专题

    大模型算法岗面试最常考的手撕代码全部集中在这里。建议:先看明白每段代码、再合上书自己写一遍、最后能向面试官口头讲清楚每行的设计意图。

    每道题给出:参考实现、考察点、常见 follow-up 问题。

    12.5.1 ML 基础:线性回归 / 逻辑回归

    线性回归(NumPy + SGD)

    import numpy as np
    
    def linear_regression_sgd(X, y, lr=0.01, n_iters=1000):
        """
        X: (n_samples, n_features)
        y: (n_samples, 1)
        """
        m, n = X.shape
        theta = np.zeros((n, 1))    # 权重
        b = 0                        # 偏置
        for _ in range(n_iters):
            y_pred = X @ theta + b
            grad_theta = (1 / m) * X.T @ (y_pred - y)
            grad_b     = (1 / m) * np.sum(y_pred - y)
            theta -= lr * grad_theta
            b     -= lr * grad_b
        return theta, b
    

    考察点:MSE loss 的梯度公式、矩阵求导、SGD vs BGD。

    逻辑回归(含 Sigmoid + 二分类交叉熵)

    import numpy as np
    
    def sigmoid(z):
        return 1 / (1 + np.exp(-z))
    
    class LogisticRegression:
        def __init__(self, lr=0.01, n_iters=1000):
            self.lr, self.n_iters = lr, n_iters
    
        def fit(self, X, y):
            m, n = X.shape
            self.w = np.zeros(n)
            self.b = 0
            for _ in range(self.n_iters):
                z = X @ self.w + self.b
                y_pred = sigmoid(z)
                grad_w = (1 / m) * X.T @ (y_pred - y)
                grad_b = (1 / m) * np.sum(y_pred - y)
                self.w -= self.lr * grad_w
                self.b -= self.lr * grad_b
    
        def predict(self, X):
            return (sigmoid(X @ self.w + self.b) >= 0.5).astype(int)
    

    考察点:BCE loss 的梯度恰好是 (y_{\text{pred}} – y) \cdot x(与线性回归同形,因为 sigmoid 的导数被消掉)。


    12.5.2 MLP:神经网络的”Hello World”

    import torch
    import torch.nn as nn
    
    class MLP(nn.Module):
        def __init__(self, in_dim, hidden_dim, out_dim):
            super().__init__()
            self.fc1 = nn.Linear(in_dim, hidden_dim)
            self.act = nn.ReLU()
            self.fc2 = nn.Linear(hidden_dim, out_dim)
    
        def forward(self, x):
            return self.fc2(self.act(self.fc1(x)))
    

    考察点:

    • 为什么要有非线性激活?(堆叠线性层等价于一个线性层,没法学非线性映射)
    • 隐藏层维度怎么选?(一般是 input 的 2-4 倍,Llama 的 FFN 是 \frac{8}{3}d)
    • 参数量公式:(in \times h) + h + (h \times out) + out

    12.5.3 Scaled Dot-Product Attention(最简版)

    import math
    import torch
    import torch.nn as nn
    
    class SelfAttention(nn.Module):
        """单头自注意力 - 面试入门版"""
        def __init__(self, hidden_size, dropout=0.1):
            super().__init__()
            self.q_proj = nn.Linear(hidden_size, hidden_size)
            self.k_proj = nn.Linear(hidden_size, hidden_size)
            self.v_proj = nn.Linear(hidden_size, hidden_size)
            self.dropout = nn.Dropout(dropout)
            self.scale = math.sqrt(hidden_size)
    
        def forward(self, x, mask=None):
            # x: (batch, seq_len, hidden)
            Q, K, V = self.q_proj(x), self.k_proj(x), self.v_proj(x)
            scores = Q @ K.transpose(-1, -2) / self.scale          # (B, L, L)
            if mask is not None:                                    # mask: (B, L, L), 0=屏蔽
                scores = scores.masked_fill(mask == 0, float('-inf'))
            attn = torch.softmax(scores, dim=-1)
            attn = self.dropout(attn)
            return attn @ V                                         # (B, L, hidden)
    

    考察点(几乎必问):

    • 为什么除 \sqrt{d_k}?(避免内积量级过大让 softmax 进入饱和区导致梯度消失)
    • mask 应该在 softmax 前还是后?(!softmax 后做 mask 会破坏概率归一化)
    • -inf 还是 -1e9?(理论上 -inf 更干净,但实际可能跟 mixed precision 冲突;工程常用 -1e9-1e4
    • dropout 加在哪?(加在 softmax 之后、矩阵乘 V 之前,是 attention weights 的 dropout)

    12.5.4 Multi-Head Attention(含 causal mask + padding mask)

    import math
    import torch
    import torch.nn as nn
    
    class MultiHeadAttention(nn.Module):
        """工业实务版 MHA - 含 dropout、padding mask、output projection"""
        def __init__(self, hidden_size, num_heads, dropout=0.1):
            super().__init__()
            assert hidden_size % num_heads == 0
            self.num_heads = num_heads
            self.head_dim = hidden_size // num_heads
            self.hidden_size = hidden_size
    
            self.q_proj = nn.Linear(hidden_size, hidden_size)
            self.k_proj = nn.Linear(hidden_size, hidden_size)
            self.v_proj = nn.Linear(hidden_size, hidden_size)
            self.o_proj = nn.Linear(hidden_size, hidden_size)
            self.dropout = nn.Dropout(dropout)
    
        def forward(self, x, attention_mask=None):
            # x: (B, L, H), attention_mask: (B, L) — 1 表示有效 token,0 表示 padding
            B, L, H = x.shape
    
            # 1) 线性投影 + 切多头 (B, L, H) → (B, n_heads, L, head_dim)
            Q = self.q_proj(x).view(B, L, self.num_heads, self.head_dim).transpose(1, 2)
            K = self.k_proj(x).view(B, L, self.num_heads, self.head_dim).transpose(1, 2)
            V = self.v_proj(x).view(B, L, self.num_heads, self.head_dim).transpose(1, 2)
    
            # 2) 注意力分数
            scores = Q @ K.transpose(-1, -2) / math.sqrt(self.head_dim)   # (B, n_heads, L, L)
    
            # 3) Padding mask: (B, L) → (B, 1, 1, L) 用广播
            if attention_mask is not None:
                mask = attention_mask[:, None, None, :]                    # (B, 1, 1, L)
                scores = scores.masked_fill(mask == 0, float('-1e9'))
    
            # 4) Softmax + dropout
            attn = torch.softmax(scores, dim=-1)
            attn = self.dropout(attn)
    
            # 5) 加权求和 + 合并头 + output projection
            out = (attn @ V).transpose(1, 2).contiguous().view(B, L, H)
            return self.o_proj(out)
    

    考察点:

    • 为什么要切多头?(不同 head 学不同关注模式:语法、共指、长程依赖)
    • 切多头时为什么用 view + transpose 而不是 reshape?(数学上等价,但 view 在 contiguous 内存上 zero-copy;transpose 后内存不连续,下次 view 之前要 .contiguous()
    • mask 的形状 (B, 1, 1, L) 怎么来的?(利用广播自动扩展到 (B, n_heads, L, L)
    • 输出投影 o_proj 的作用?(混合多头信息,理论上和”直接拼接”等价但加了一层可训练的混合)

    Follow-up:causal mask(解码器必备)

    # 生成 causal mask:下三角矩阵,禁止看未来的 token
    causal_mask = torch.tril(torch.ones(L, L)).bool()    # (L, L)
    scores = scores.masked_fill(~causal_mask, float('-1e9'))
    

    12.5.5 GQA / MQA:现代 Attention 的标配

    class GroupedQueryAttention(nn.Module):
        """GQA: Q 是 n_heads 个,K/V 共享为 n_kv_heads 个(n_heads 必须能被 n_kv_heads 整除)
           MQA 是 GQA 的特例,n_kv_heads=1
        """
        def __init__(self, hidden_size, num_heads, num_kv_heads, dropout=0.1):
            super().__init__()
            assert num_heads % num_kv_heads == 0
            self.num_heads = num_heads
            self.num_kv_heads = num_kv_heads
            self.head_dim = hidden_size // num_heads
            self.repeat = num_heads // num_kv_heads          # K/V 复制几次
    
            self.q_proj = nn.Linear(hidden_size, hidden_size)
            self.k_proj = nn.Linear(hidden_size, num_kv_heads * self.head_dim)
            self.v_proj = nn.Linear(hidden_size, num_kv_heads * self.head_dim)
            self.o_proj = nn.Linear(hidden_size, hidden_size)
            self.dropout = nn.Dropout(dropout)
    
        def forward(self, x, mask=None):
            B, L, _ = x.shape
            Q = self.q_proj(x).view(B, L, self.num_heads,    self.head_dim).transpose(1, 2)
            K = self.k_proj(x).view(B, L, self.num_kv_heads, self.head_dim).transpose(1, 2)
            V = self.v_proj(x).view(B, L, self.num_kv_heads, self.head_dim).transpose(1, 2)
    
            # GQA 核心:把 K/V 复制 repeat 次匹配 Q 的头数
            K = K.repeat_interleave(self.repeat, dim=1)      # (B, num_heads, L, head_dim)
            V = V.repeat_interleave(self.repeat, dim=1)
    
            scores = Q @ K.transpose(-1, -2) / math.sqrt(self.head_dim)
            if mask is not None:
                scores = scores.masked_fill(mask[:, None, None, :] == 0, float('-1e9'))
            attn = self.dropout(torch.softmax(scores, dim=-1))
            out = (attn @ V).transpose(1, 2).contiguous().view(B, L, -1)
            return self.o_proj(out)
    

    考察点(DeepSeek/Llama-3 面试必问):

    • MHA → MQA → GQA 三者的区别?(K/V 头数:n → 1 → g)
    • 为什么 GQA 比 MQA 效果好?(共享得没那么狠,保留更多表达能力)
    • repeat_interleave vs repeat?(interleave[A, A, B, B]repeat[A, B, A, B]——GQA 要 interleave 才能让同组 Q 看到同一个 K)

    12.5.6 RMSNorm(现代 LLM 标配,比 LayerNorm 快)

    import torch
    import torch.nn as nn
    
    class RMSNorm(nn.Module):
        """LLaMA / Qwen / DeepSeek 都用这个"""
        def __init__(self, hidden_size, eps=1e-6):
            super().__init__()
            self.weight = nn.Parameter(torch.ones(hidden_size))   # γ,无 β
            self.eps = eps
    
        def forward(self, x):
            # x: (..., hidden_size)
            rms = x.pow(2).mean(dim=-1, keepdim=True).add(self.eps).sqrt()
            return self.weight * (x / rms)
    

    对比 LayerNorm:

    class LayerNorm(nn.Module):
        def __init__(self, hidden_size, eps=1e-5):
            super().__init__()
            self.weight = nn.Parameter(torch.ones(hidden_size))
            self.bias   = nn.Parameter(torch.zeros(hidden_size))
            self.eps = eps
    
        def forward(self, x):
            mean = x.mean(-1, keepdim=True)
            var  = x.var(-1, keepdim=True, unbiased=False)
            x_norm = (x - mean) / torch.sqrt(var + self.eps)
            return self.weight * x_norm + self.bias
    

    考察点:

    • RMSNorm 为什么比 LayerNorm 快?(省掉了减均值和偏置 β,少一次归约)
    • BatchNorm 为什么不能用在 NLP?(batch 内不同样本是不同语义、不同长度,不能拿来一起归一化;而且推理时还要维护 running stats)
    • LayerNorm 的 mean/var 沿哪个维度?(最后一维,即 hidden_size 维度,不依赖 batch)

    12.5.7 SwiGLU FFN(LLaMA / Qwen / DeepSeek 都用)

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    class SwiGLU(nn.Module):
        """SwiGLU FFN: (Swish(W_gate · x)) ⊙ (W_up · x) → W_down
    
        intermediate_size 通常取 ~8/3 · hidden_size 以保持参数量接近 ReLU FFN
        """
        def __init__(self, hidden_size, intermediate_size):
            super().__init__()
            self.gate_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
            self.up_proj   = nn.Linear(hidden_size, intermediate_size, bias=False)
            self.down_proj = nn.Linear(intermediate_size, hidden_size, bias=False)
    
        def forward(self, x):
            # SiLU(x) = x * sigmoid(x),等价于 Swish
            return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
    

    考察点:

    • 为什么 SwiGLU 比 ReLU FFN 好?(gated 机制让每个维度自适应缩放,类似 attention 的”软选择”)
    • SwiGLU 比 ReLU FFN 多了一个矩阵(gate_proj),为什么还说参数量”接近”?(因为 intermediate_size 从 4d 缩到 ~8/3d 抵消)
    • SiLU、Swish、GeLU 三者关系?(SiLU 就是 \beta=1 的 Swish;GeLU 是 x \cdot \Phi(x),数值上和 Swish 很接近)

    12.5.8 RoPE 旋转位置编码

    import torch
    
    def precompute_rope_cache(dim, max_seq_len, base=10000.0):
        """预计算 cos / sin 缓存。dim 是 head_dim。"""
        theta = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))   # (dim/2,)
        seq_idx = torch.arange(max_seq_len).float()                       # (max_seq_len,)
        freqs = torch.outer(seq_idx, theta)                               # (max_seq_len, dim/2)
        cos = freqs.cos()                                                  # (max_seq_len, dim/2)
        sin = freqs.sin()
        return cos, sin
    
    def apply_rope(x, cos, sin):
        """对 Q 或 K 应用 RoPE。
        x: (B, num_heads, L, head_dim)
        cos, sin: (L, head_dim/2)
        """
        # 把 x 切成两半,做旋转:(x1, x2) → (x1·cos - x2·sin, x1·sin + x2·cos)
        x1, x2 = x[..., ::2], x[..., 1::2]                                # 偶数维 / 奇数维
        # 广播 cos/sin 到 (1, 1, L, head_dim/2)
        cos = cos[None, None, :, :]
        sin = sin[None, None, :, :]
        rotated_x1 = x1 * cos - x2 * sin
        rotated_x2 = x1 * sin + x2 * cos
        # 重新交错拼回
        out = torch.stack([rotated_x1, rotated_x2], dim=-1).flatten(-2)
        return out
    

    考察点:

    • 为什么用旋转而不是加法位置编码?(旋转后内积只依赖相对位置 n-m,天然适合 attention)
    • 频率公式 \theta_i = 10000^{-2i/d} 怎么来的?(继承自 sinusoidal PE,低维高频、高维低频)
    • 怎么扩长上下文?(调整 base,如 NTK / YaRN——详见 1.5.3 长度外推方法

    12.5.9 数值稳定的 Softmax + Online Softmax(Flash Attention 核心)

    普通 softmax(数值稳定版)

    def stable_softmax(x, dim=-1):
        """减去最大值防止 exp 上溢"""
        x_max = x.max(dim=dim, keepdim=True).values
        exp_x = (x - x_max).exp()
        return exp_x / exp_x.sum(dim=dim, keepdim=True)
    

    Online Softmax(一遍扫过算 softmax,Flash Attention 的核心)

    def online_softmax(x):
        """在线增量算 softmax:只扫一遍 x,省去普通版的"算 max + 算 sum"两遍扫描"""
        m = float('-inf')   # running max
        s = 0.0             # running sum of exp
        for xi in x:
            m_new = max(m, xi)
            # 关键:用 m_new 更新历史 sum
            s = s * (m - m_new).__class__(2.71828) ** (m - m_new) + (xi - m_new).__class__(2.71828) ** (xi - m_new)
            m = m_new
        # 第二次扫描时直接用 (xi - m).exp() / s
    

    考察点(Flash Attention 必问):

    • 普通 softmax 为什么要减最大值?(exp(800) 溢出成 inf,减最大值后 exp(0) = 1 始终安全)
    • Online Softmax 的核心数学技巧?(用增量更新公式:新一项进来时,把历史 sum 乘以 e^{m_{\text{old}} – m_{\text{new}}} 校正,保留概率正确性的同时一遍扫完)
    • Flash Attention 为什么用 Online Softmax?(标准 attention 要把整个 N \times N 的 softmax 矩阵写回 HBM,Online Softmax 让”分块 attention”也能数学等价正确,所以可以在 SRAM 上分块算)

    12.5.10 KV Cache 实现

    import torch
    import torch.nn as nn
    
    class CausalSelfAttentionWithKVCache(nn.Module):
        """单层自注意力 + KV Cache,支持自回归生成"""
        def __init__(self, hidden_size, num_heads):
            super().__init__()
            self.num_heads = num_heads
            self.head_dim = hidden_size // num_heads
            self.qkv = nn.Linear(hidden_size, 3 * hidden_size)
            self.o_proj = nn.Linear(hidden_size, hidden_size)
    
        def forward(self, x, kv_cache=None):
            # 推理时 x 只是新加入的 token,shape: (B, 1, H)
            B, L, H = x.shape
            qkv = self.qkv(x).view(B, L, 3, self.num_heads, self.head_dim)
            q, k, v = qkv.unbind(dim=2)                              # 每个 (B, L, n_heads, head_dim)
            q, k, v = [t.transpose(1, 2) for t in (q, k, v)]         # (B, n_heads, L, head_dim)
    
            # 拼接 KV cache
            if kv_cache is not None:
                past_k, past_v = kv_cache
                k = torch.cat([past_k, k], dim=2)                     # 沿 seq 维拼
                v = torch.cat([past_v, v], dim=2)
            new_cache = (k, v)                                        # 给下一步用
    
            # 注意力:只用当前 q 与全部历史 k/v 算
            scores = q @ k.transpose(-1, -2) / (self.head_dim ** 0.5)
            attn = torch.softmax(scores, dim=-1)
            out = (attn @ v).transpose(1, 2).contiguous().view(B, L, H)
            return self.o_proj(out), new_cache
    

    考察点:

    • 为什么不需要存 Q?(Q 只用一次——当前 token 算完就丢,K/V 才是历史信息)
    • KV Cache 一直增长,显存怎么办?(看 GQA / MLA 压缩头数、PagedAttention 分页管理)
    • prefill 和 decode 阶段的 KV Cache 用法区别?(prefill:一次性计算整个 prompt 并填充;decode:每次只算 1 个 token 的 K/V 追加到 cache)

    12.5.11 Cross-Entropy Loss(含 label smoothing)

    import torch
    import torch.nn.functional as F
    
    def cross_entropy(logits, target):
        """logits: (N, C), target: (N,) — 类别索引"""
        log_probs = F.log_softmax(logits, dim=-1)            # 数值稳定
        # gather 取出每个样本在 target 类别上的 log prob
        nll = -log_probs.gather(1, target.unsqueeze(1)).squeeze(1)
        return nll.mean()
    
    def cross_entropy_with_smoothing(logits, target, num_classes, smoothing=0.1):
        """label smoothing: 把 one-hot [0,0,1,0] 换成 [eps/(K-1), eps/(K-1), 1-eps, eps/(K-1)]
           缓解过拟合 + 提升泛化
        """
        log_probs = F.log_softmax(logits, dim=-1)
        with torch.no_grad():
            true_dist = torch.full_like(log_probs, smoothing / (num_classes - 1))
            true_dist.scatter_(1, target.unsqueeze(1), 1.0 - smoothing)
        return -(true_dist * log_probs).sum(dim=-1).mean()
    

    考察点:

    • log_softmaxlog(softmax(x)) 好在哪?(数值稳定——直接合并指数和对数避免 underflow)
    • label smoothing 缓解什么问题?(模型过分自信 + 减少幻觉)
    • ignore_index 是什么?(SFT 训练时把 padding 位置的 target 设为 -100,loss 自动忽略)

    12.5.12 解码采样:Top-k / Top-p / Temperature

    import torch
    
    def sample(logits, temperature=1.0, top_k=None, top_p=None):
        """logits: (vocab_size,) — 当前位置的下一个 token 概率"""
        logits = logits / temperature
    
        # Top-k: 保留 logits 最大的 k 个,其余 -inf
        if top_k is not None and top_k > 0:
            top_k_vals, _ = torch.topk(logits, top_k)
            threshold = top_k_vals[-1]
            logits[logits < threshold] = float('-inf')
    
        # Top-p(nucleus): 累积概率 ≤ p 的 token 集合内采样
        if top_p is not None and 0 < top_p < 1:
            sorted_logits, sorted_idx = torch.sort(logits, descending=True)
            cum_probs = torch.cumsum(torch.softmax(sorted_logits, dim=-1), dim=-1)
            # 找到累积概率超过 p 的位置,从这之后全部置 -inf
            sorted_mask = cum_probs > top_p
            sorted_mask[1:] = sorted_mask[:-1].clone()    # 保留第一个超过 p 的 token
            sorted_mask[0] = False
            mask = sorted_mask.scatter(0, sorted_idx, sorted_mask)
            logits[mask] = float('-inf')
    
        probs = torch.softmax(logits, dim=-1)
        return torch.multinomial(probs, num_samples=1)
    

    考察点:

    • temperature 三种极限行为?(T \to 0 greedy、T = 1 原分布、T \to \infty 均匀)
    • top-k 和 top-p 同时用会怎么样?(先 top-k 截断、再 top-p 截断——两者顺序通常先 k 再 p)
    • 为什么对话模型一般不用 beam search?(beam 倾向”安全无聊”输出,open-ended 任务下生成质量反而差)

    12.5.13 Beam Search(结构化生成必备)

    import torch
    
    def beam_search(model, start_token_id, end_token_id, beam_size=4, max_len=50):
        """简化版 beam search:每步保留 beam_size 条最高概率路径"""
        # 每条路径: (tokens 列表, 累计 log_prob)
        beams = [([start_token_id], 0.0)]
    
        for _ in range(max_len):
            new_beams = []
            for tokens, score in beams:
                if tokens[-1] == end_token_id:
                    new_beams.append((tokens, score))                  # 已结束的保留
                    continue
                logits = model(torch.tensor([tokens]))[-1, -1]          # 最后一步 logits
                log_probs = torch.log_softmax(logits, dim=-1)
                # 扩展 beam_size 个候选
                top_log_probs, top_idx = torch.topk(log_probs, beam_size)
                for lp, idx in zip(top_log_probs, top_idx):
                    new_beams.append((tokens + [idx.item()], score + lp.item()))
            # 从所有新候选里选 top beam_size 条
            beams = sorted(new_beams, key=lambda x: x[1], reverse=True)[:beam_size]
            if all(b[0][-1] == end_token_id for b in beams):
                break
        return beams[0][0]                                              # 返回最高分序列
    

    考察点:

    • beam 的”长度归一化”是什么?(直接比累计 log_prob 偏向短句,业界常用 \text{score} / |y|^\alpha 归一化,\alpha \approx 0.6)
    • beam_size 越大越好吗?(不一定——太大会引入”安全但无聊”的输出,业界很少 > 8)

    12.5.14 BPE Tokenizer 核心训练逻辑

    from collections import Counter, defaultdict
    
    class BPE:
        """极简版 BPE 分词器训练 - 演示核心思想"""
        def __init__(self, target_vocab_size):
            self.target_vocab_size = target_vocab_size
            self.merges = []                                 # 合并规则按顺序
            self.vocab = set()
    
        def get_stats(self, word_freqs):
            """统计当前所有相邻字符对的频率"""
            pairs = defaultdict(int)
            for word, freq in word_freqs.items():
                symbols = word.split()
                for i in range(len(symbols) - 1):
                    pairs[(symbols[i], symbols[i + 1])] += freq
            return pairs
    
        def merge_pair(self, pair, word_freqs):
            """把 word_freqs 里所有出现的 pair 合并成一个新 token"""
            new_word_freqs = {}
            bigram = ' '.join(pair)
            replacement = ''.join(pair)
            for word, freq in word_freqs.items():
                new_word = word.replace(bigram, replacement)
                new_word_freqs[new_word] = freq
            return new_word_freqs
    
        def train(self, words):
            # 初始:每个词拆成字符序列
            word_freqs = Counter(' '.join(w) + ' </w>' for w in words)
            # 初始 vocab 包含所有字符
            for w in word_freqs:
                self.vocab.update(w.split())
    
            # 迭代合并出现频率最高的字符对
            while len(self.vocab) < self.target_vocab_size:
                pairs = self.get_stats(word_freqs)
                if not pairs:
                    break
                best_pair = max(pairs, key=pairs.get)
                word_freqs = self.merge_pair(best_pair, word_freqs)
                self.merges.append(best_pair)
                self.vocab.add(''.join(best_pair))
    
            return self.vocab, self.merges
    

    考察点:

    • BPE / BBPE / WordPiece / Unigram 区别?(BPE 贪心合并最高频对、WordPiece 用语言模型概率、Unigram 反向裁剪、BBPE 是 byte-level BPE 处理 OOV)
    • 中文 tokenizer 怎么处理?(按字符 / 字节切;LLaMA 用 BBPE,DeepSeek/Qwen 在 BBPE 基础上加 CJK 优化)
    • </w> 这个特殊符号干嘛的?(标记词尾,防止 “low” 和 “lower” 的前缀 “low” 被错误合并)

    12.5.15 ZeRO 显存优化伪代码

    """ZeRO-3 伪代码:参数、梯度、优化器状态全部分片到 N 张卡"""
    
    class ZeRO3Optimizer:
        def __init__(self, model, world_size, rank):
            self.world_size = world_size
            self.rank = rank
            # 每张卡只持有 1/N 的参数、梯度、优化器状态
            self.local_params, self.local_grads, self.local_opt_states = \
                self._shard(model.parameters(), world_size, rank)
    
        def forward(self, x):
            # 前向计算前:从所有卡 all-gather 完整参数
            full_params = all_gather(self.local_params)
            # 用完整参数算前向
            output = model_forward(x, full_params)
            # 用完释放完整参数(只保留自己那 1/N)
            del full_params
            return output
    
        def backward(self, loss):
            # 反向也要 all-gather 参数
            full_params = all_gather(self.local_params)
            full_grads = model_backward(loss, full_params)
            # reduce-scatter 梯度:每张卡只接收自己负责的那 1/N 梯度
            self.local_grads = reduce_scatter(full_grads)
            del full_params, full_grads
    
        def step(self):
            # 每张卡用自己那 1/N 的梯度和优化器状态更新自己那 1/N 的参数
            self.local_params = adam_update(
                self.local_params, self.local_grads, self.local_opt_states
            )
    

    考察点:

    • ZeRO-1 / 2 / 3 切的是什么?(1: 优化器状态;2: + 梯度;3: + 参数)
    • 通信开销分别多少?(ZeRO-1/2 与 DP 同量级;ZeRO-3 多了前向 + 反向各一次 all-gather,约多 50% 通信)
    • FSDP 跟 ZeRO-3 的关系?(FSDP = PyTorch 原生实现的 ZeRO-3)

    12.5.16 手撕复习清单

    按面试出现频率分级:

    优先级题目高频面试场景
    P0 必背MHA / Cross-Entropy / RMSNorm / RoPE / KV Cache几乎每场
    P1 高频GQA / SwiGLU / Top-k/p 采样 / BPE / Online Softmax大模型岗 / 推理优化岗
    P2 中频Beam Search / LayerNorm / ZeRO 伪代码 / Label Smoothing训练岗
    P3 基础MLP / 线性回归 / 逻辑回归 / 激活函数机器学习岗

    面试节奏建议

    1. 一道题 5-10 分钟,先讲思路、再写代码
    2. 代码写到 80% 时主动问”是否需要考虑 mask / dropout / batch 维度”——这种问题面试官会喜欢
    3. 写完后自己跑一个 shape 例子:”输入 (2,3,4) 经过 reshape 是 (2,3,2,2),transpose 后是 (2,2,3,2)…”
    4. 必背几个关键 shape:MHA 的 (B, num_heads, L, head_dim)、attention scores 的 (B, num_heads, L, L)

    12.6 机器学习深度学习八股(初稿)

    待优化机器学习图谱:

    • 最大似然估计:侧重于找到使观测数据最有可能出现的参数值,不一定是无偏的;但在样本量趋于无穷时,它往往是渐近无偏的,并且具有渐近最小方差。
    • 无偏估计:保证了估计量的期望等于真实参数值,但不保证估计量是最可能的或方差最小的。

    过拟合与欠拟合

    过拟合是指模型在训练数据上表现得非常好,但在新的、未见过的数据上表现较差。这通常是因为模型过于复杂,捕捉到了训练数据中的噪声或细节,从而丧失了泛化能力。常见的表现包括:

    12.8 面试经验总结

    2026 大模型算法社招经验总结

    1. 经历match非常关键,应用基本进不了基座(所以校招能去基座还是去基座吧),反过来可以,除急招外大部分岗位卡1-3年工作经验,部分核心岗只招高P
    2. 基座社招基本是各家基座人才互相跳,做的也大差不差,当然也有kimi这种一线基座会卡候选者research sense的
    3. 应用算法大部分都是Agent相关的,对于偏业务应用的组,面试时主要靠打项目中Agent loop的设计与优化思路(比如海量skills的召回、工具设计思路等),以及评估体系构建,如何减少评估波动、如何基于评估指标设计reward体系反哺于Agentic RL训练
    4. 对于偏基座训练的Agent应用算法组,更加关注xx场景下的数据合成管线建设(被问到用国产sota模型合成数据时如何解决泛化性差的问题)、数据质量验证(可能会问到GRM是否自己训,如何训)及数据配比工作,以及Rubric设计思考,当然也会问一些post train的实验设置及观察到的现象,比如agentic rl时发现了哪些reward hacking,是如何监控的,优化的思路是什么等等。总体来说对于造数据到训练的整体pipeline要熟悉,对于训练框架非常了解,同时需要对业务有自己的思考来论证优化动作的合理性。
    5. 经历match的话,被问到的八股很少,手撕的次数也少,最多就是反转链表、MHA这种,感觉不用特意准备lc
    6. 几家比较有名的C端应用,其实主要还是在搞workflow,真正涉及到agentic loop的很少,当然这和c端用户本身query分布有关,但是复杂query+稍微垂领的query也确实承接不了
    7. 要做应用的话,还是需要把CC、Codex、Openclaw、Hermes-Agent这些框架好好研究一遍,有一定的认知,方便和面试官吹水(感觉真正搞透的人很少)

    大厂学长告诉你:2026 大模型应用算法还能不能去?

    Q:大模型应用都在做些什么,只需要写写 skills 吗?

    A:不同大模型应用方向差距蛮大的:

    • 用户画像、商品理解类:拿大模型来打打标签,最多就是做做传统的微调训练,技术壁垒确实低,只能积累一些业务经验。
    • AI 助手、客服类:之前可能在用 workflow,调 prompt 做 one-model 后训练;现在 harness 火了,不少大厂中台工程组会出自己的 Agent 框架,让不同的业务组接进来,业务算法写写 skills 就好了。这个最大的问题是:你不知道这个框架的底层实现,也无法在这个 env 中进行训练,失去了 co-design 的意义,只是做大了 harness。
    • 自建 Agent Loop 的业务组:会自己搭建一套适合自己业务的 Agent Loop,在此基础上迭代各种策略,同时也需要进行大规模的 post-train,并随着模型能力的提升不断优化 benchmark 体系、工具集合、框架层策略等。其实从技术栈来看和基座没啥区别,所以有些大厂的核心 C 端应用也会有基座团队来参与优化。

    13. Updating 持续更新内容

    这章在讲什么:临时存放的更新内容。一个新思路、一篇新论文、一个新框架——还不足以独立成章时先放在这里,攒到一定规模再迁出去。

    大部分内容会引用前面 1-12 章相关位置。

    索引

    #标题修改时间
    13.1⛓️ [[#13.1 ⛓️ RL 又整花活:Rubric for Non-Verifiable RL 是个啥RL 又整花活:Rubric for Non-Verifiable RL 是个啥]]
    13.2👍 [[#13.2 👍 Qwen3.5 技术深度解读:走向原生多模态智能体Qwen3.5 技术深度解读:走向原生多模态智能体]]
    13.3🧙‍♀️ [[#13.3 🧙‍♀️ LLM 在量化中的研究应用LLM 在量化中的研究应用]]
    13.4💾 [[#13.4 💾 DeepSeek Engram 深度解读:当大模型学会查字典而不是硬背书DeepSeek Engram 深度解读:当大模型学会查字典而不是硬背书]]
    13.5⛰️ [[#13.5 ⛰️ DualPath 深度解读:DeepSeek 如何榨干每一块闲置网卡的带宽DualPath 深度解读:DeepSeek 如何榨干每一块闲置网卡的带宽]]
    13.6💴 [[#13.6 💴 如何指导大模型写出高质量 Prompt如何指导大模型写出高质量 Prompt]]
    13.7🦊 [[#13.7 🦊 从 Pairwise 最优到多数据源混训配比从 Pairwise 最优到多数据源混训配比]]
    13.8👓 [[#13.8 👓 多轮工具调用 SFT 数据清洗与构建工作汇总多轮工具调用 SFT 数据清洗与构建工作汇总]]
    13.9💭 [[#13.9 💭 训练时教模型思考,推理时只让它回答:从 DSS 到隐式 CoT 的一条技术路线训练时教模型思考,推理时只让它回答:从 DSS 到隐式 CoT 的一条技术路线]]

    13.1 ⛓️ RL 又整花活:Rubric for Non-Verifiable RL 是个啥

    修改时间:1月7日

    背景与定义

    RL在可验证任务中通过自动打分信号(如单元测试、标准答案)进行优化,取得了显著成果。
    然而,对于开放式、主观性的任务通常缺乏唯一正确答案,无法直接得出明确奖励。在此类任务中,我们常用RLHF或问答式评估来提供反馈,但这些方法往往依赖难以解释的奖励模型且样本成本高。Rubric在此背景下被引入:Rubric 是一组明确的评价准则,将“优质答案”的标准分解为具体、可检验的子目标。通过rubric,可以将多样化的主观评判转化为结构化的奖励信号,给不可验证任务了新的可训练目标。

    Rubric的价值

    Rubric 将复杂的质量判断拆分成可理解的评价标准,弥补了二元正确性信号与粗糙偏好打分之间的空白。在缺乏唯一标准答案的场景下,rubric可以提供细化的、多维度的奖励反馈;例如,一道医学问答可以设立多个Rubric项并按权重计算最终得分。相对于黑盒的奖励模型,Rubric的规则明确、可解释,能更好地捕捉专家意图和细粒度细节。

    13.2 👍 Qwen3.5 技术深度解读:走向原生多模态智能体

    修改时间:4月24日

    扩展阅读参考链接:

    1. 官方 GitHub 仓库:QwenLM/Qwen3.5
    2. Hugging Face 模型卡:Qwen/Qwen3.5-397B-A17B
    3. NVIDIA NIM 模型卡:qwen3.5-397b-a17b/modelcard
    4. 官方博客:qwen.ai/blog?id=qwen3.5
    5. Transformers 源码:
      • src/transformers/models/qwen3_5/modular_qwen3_5.py, modeling_qwen3_5.py
      • src/transformers/models/qwen3_5_moe/modular_qwen3_5_moe.py, modeling_qwen3_5_moe.py
      • src/transformers/models/qwen3_next/modular_qwen3_next.py, modeling_qwen3_next.py
      • src/transformers/models/qwen3_vl/modular_qwen3_vl.py, modeling_qwen3_vl.py
    6. Transformers 文档:Qwen3.5 MoE 模型说明
    7. 相关论文:

    13.3 🧙‍♀️ LLM 在量化中的研究应用

    修改时间:2月26日

    QuantaAlpha: An Evolutionary Framework for LLM-Driven Alpha Mining

    动机

    QuantaAlpha 的总体目标就是:在市场非平稳与低信噪比常态下,把”多轮自动化因子挖掘”做成一种可演化、可继承、可约束的搜索过程。

    飞书原文该篇仍在更新中,更详细内容请参考原页面:飞书链接

    13.4 💾 DeepSeek Engram 深度解读:当大模型学会查字典而不是硬背书

    修改时间:3月10日

    类比

    想象你到了别人家,需要连 WiFi,有两种策略:

    • 策略 A:从第一性原理出发,先推导电磁波传播方程,再分析路由器的信号编码方式,然后逆向计算出可能的密码组合——经过 6 层复杂推理,你得出结论:密码大概是 12345678
    • 策略 B:看一下墙上的纸条,上面写着 WiFi: 12345678

    当你问大模型”黑曼巴是谁”,模型并不是翻笔记找到答案,而是用好几层 Attention + FFN 从零开始推导出这个实体——每次都重新算,每次都浪费算力。

    当前 Transformer 在两类任务上的不对称

    • 复杂推理类:现有 Transformer(尤其 MoE Transformer)已经很擅长做条件计算。遇到复杂推理、代码生成、数学求解时,MoE 通过稀疏激活专家来扩展计算容量。
    • 静态检索类:命名实体识别、事实回忆、固定短语匹配这类更接近静态模式检索的能力,现有架构没有原生的 lookup primitive,往往只能靠多层 Attention 和 FFN 把本该直接命中的知识重新算一遍。

    Engram 的核心思路

    DeepSeek Engram 给大模型配了一张”纸条”——一个 O(1) 复杂度的条件记忆模块,让模型在需要查事实时直接查表,把宝贵的计算深度留给真正需要推理的任务。

    flowchart LR
        X[Token x_t] --> H[Hidden state h_t]
        H --> NG[N-gram Hash<br/>固定 N 次查找]
        NG --> Mem[Memory Table<br/>K × d_v]
        Mem --> V[Retrieved values]
        V --> Y[输出 y_t]
        H --> Att[Attention + FFN<br/>正常计算路径]
        Att --> Y
    

    Engram 把”随着记忆表规模增长而扩张的知识容量”与”每 token 的计算量”解耦了:对每个位置只做固定数量的 N-gram 哈希检索,因此 memory 变大主要增加参数容量,而不线性增加 per-token FLOPs

    13.5 ⛰️ DualPath 深度解读:DeepSeek 如何榨干每一块闲置网卡的带宽

    修改时间:3月22日

    • 论文:DualPath: Breaking the Storage Bandwidth Bottleneck in Agentic LLM Inference
    • 链接:arxiv.org/abs/2602.21548

    核心观察:Prefill 节点的存储网卡跑满了,Decode 节点的存储网卡闲着。DualPath 开辟”存储 → Decode → RDMA → Prefill”的第二条路,将全集群存储带宽池化,离线推理加速 1.87×,在线服务吞吐提升 1.96×

    KV-Cache 和 PD 分离回顾

    KV-Cache 的重要性

    可以回顾 1.3 Attention 注意力

    LLM(Causal)在生成文本时,每生成一个新 token,都需要回顾之前所有 token 的信息。这个过程发生在 Transformer 的注意力层中,每个 token 会被投影成 Query、Key、Value 三个向量:

    • Q:我想查什么
    • K:我能提供什么线索
    • V:我的实际内容是什么

    生成第 N 个 token 时,需要用第 N 个 token 的 Q 去和前面所有 token 的 K 做匹配,计算注意力分数,再用分数对所有 V 做加权求和。如果不做缓存,每生成一个新 token,前面所有 token 的 K 和 V 都要重新算一遍,浪费很大——所以实际上会把每个 token 的 K 和 V 缓存起来,这就是 KV-Cache

    flowchart LR
        subgraph Prefill["Prefill 阶段(一次性计算 prompt)"]
            P1[prompt tokens] --> P2[计算所有层的 K V]
            P2 --> P3[写入 KV Cache]
        end
        subgraph Decode["Decode 阶段(逐 token 生成)"]
            D1[新 token] --> D2[只算自己的 Q K V]
            D2 --> D3[读取历史 KV Cache]
            D3 --> D4[Attention → 下一个 token]
            D4 --> D5[追加新 KV 到 Cache]
            D5 -.循环.-> D1
        end
        P3 -.转交.-> D3
    

    PD 分离(Prefill-Decode Disaggregation)将这两个阶段调度到不同节点:Prefill 是计算密集型、Decode 是内存带宽密集型,分离后可以各自配比硬件、避免相互干扰。

    13.6 💴 如何指导大模型写出高质量 Prompt

    修改时间:4月13日

    背景

    这两年,自动化 prompt 优化已经是一条相对成型的技术路线:

    • APE:把 instruction 当成待搜索对象,先生成一批候选,再按任务表现筛选。
    • ProTeGi:用自然语言反馈去改写 prompt。
    • OPRO:把历史 prompt + 分数一起交给模型继续搜索。
    • MIPROv2:直接把 prompt 和 few-shot example 作为程序参数去编译和优化。

    这说明:prompt 其实就是可优化对象,不是文案

    但,为什么 LLM 自己写的第一版 prompt,经常一上来就不太行?

    一、Why:任务被定义错了

    多数人给模型的指令是:”帮我写一个高质量 prompt。”

    这句话的问题在于,它定义的是一个写作任务,而不是一个规格设计任务

    • 模型会优先优化三件事:语气顺滑、结构完整、看起来专业。
    • 但 prompt 真正需要优化的其实是另外三件事:输入定义清不清楚、约束能不能执行、输出能不能稳定落到目标格式上

    一旦任务被定义成”写一段像 prompt 的文字”,模型自然会滑向它最熟悉的分布:像助手、像说明文、像模板。最后产物往往不难读,甚至还挺像样,但执行起来并不稳。

    二、最常见问题

    1. 风格泄漏

    很多模型写 prompt 时喜欢带 emoji、礼貌套话、口号式表达,或者”帮助你更好地完成任务”这种缓冲语。

    这不是因为它不懂 prompt,而是因为聊天模型默认学到的就是这种 assistant 风格。只要你没有显式切断这种风格分布,它就会自然往这个方向走。

    问题在于:这类内容只提升”可读性”、不提升”可执行性”。对 prompt 来说,这基本都是噪声

    13.7 🦊 从 Pairwise 最优到多数据源混训配比

    修改时间:5月7日

    1. 问题背景

    很多人做多数据源混训时,都会遇到同一个问题:

    已知 a 是辅助数据,b 也是辅助数据,c 是目标任务数据。单独实验发现 a:c = 1:2 时效果最好,同时也发现 b:c = 1:2 时效果最好。

    那三者一起训时,到底应该设成 a:b:c = 1:1:2 还是 a:b:c = 1:1:4?

    表面上看,1:1:2 好像”同时满足”了 a:c=1:2 和 b:c=1:2。但更深一点看,这个推理其实默认了一个很强的假设:a 和 b 对 c 的帮助是线性可加、互不冲突的。研究界这几年对多任务优化、梯度冲突、数据混合优化的结果,基本都在提醒你:这个假设通常并不成立。

    参考:Multi-Task Learning as Multi-Objective Optimizationarxiv.org/abs/1810.04650

    2. 到底在调什么

    混训里最容易混淆的是两个东西:

    1. sampling ratio:也就是 a:b:c 这种采样比例,控制的是模型”看见多少次哪类数据”。
    2. loss weight:也就是不同数据源或不同任务的 loss 系数,控制的是模型”看见以后谁的影响更大“。

    把它写成统一形式就是:

    \mathcal{L}(\theta) = \sum_{i=1}^{k} q_i \cdot w_i \cdot \mathbb{E}_{x \sim \mathcal{D}_i} \left[ \ell_i(x; \theta) \right]

    其中 q_i 是数据集 i 的采样概率(满足 \sum q_i = 1),w_i 是 loss 权重。两者乘性共同决定该数据源对总梯度的贡献,但调起来效果不同:q_i 改变看到的样本分布、w_i 改变每个样本的梯度尺度。

    13.8 👓 多轮工具调用 SFT 数据清洗与构建工作汇总

    修改时间:5月8日

    知识回顾:8.1 tool-use 数据合成

    1. 相关工作概述

    2025 下半年之后,多轮工具调用数据构建的主线已经从”LLM 根据 API 文档合成对话”转向”真实工具或可执行环境中的可验证轨迹”。这一点在以下工作中非常明显:

    • TOUCAN:用真实 MCP 工具构造 1.5M 轨迹。
    • MiniMax M2.1:把 GitHub PR、Docker 环境、F2P/P2P 测试、多 scaffold rollout 接入 SFT/RL。
    • GLM-5:把 agentic engineering 放进训练主线。
    • Qwen3-Coder-Next:明确使用可执行 coding environments 和 verifiable tasks。
    • 其他:DIVE、WebResearcher、Tongyi DeepResearch 等。

    对它们的清洗构建 pipeline 关键点总结:

    1. 可执行环境优先:数据必须能执行或能被 verifier 检查。
    2. 多轮轨迹不能只做整条过滤:必须做 turn-level filtering 和 loss mask。
    3. trace first / evidence first:任务和轨迹的构造越来越多从真实工具、真实 trace、真实 evidence 出发。
    4. RAG / Deep Research 类工具数据:需要 step-level 或 hop-level validation。
    5. model-aware 动态数据飞轮:数据生成与模型能力共同演进。

    13.9 💭 训练时教模型思考,推理时只让它回答:从 DSS 到隐式 CoT 的一条技术路线

    修改时间:4月23日

    核心问题

    “能不能在训练的时候输出 CoT,但是推理的时候不输出 CoT,同时让答案的准确率和整体质量都有提升?”

    这个问题表面上像是在问训练 trick,实际上问得很深,涉及一个很核心的技术判断:CoT 到底应该被当成”推理阶段的显式产物”,还是”训练阶段的辅助监督”?

    如果答案是后者,问题就变成了:能不能在训练阶段用 CoT 帮模型学会更强的推理能力,而在真正推理时只保留更短、更直接的答案输出路径——关注的是训练范式和部署范式能不能解耦

    flowchart LR
        subgraph Train["训练阶段"]
            Q[Question] --> CoT[显式 CoT<br/>step-by-step]
            CoT --> A[Answer]
        end
        subgraph Infer["推理阶段(隐式 CoT)"]
            Q2[Question] --> Direct[模型内部思考<br/>不输出过程]
            Direct --> A2[Answer<br/>更短、更快]
        end
        Train -.训练目标蒸馏到内部.-> Infer
    

    与自适应思考的区别

    • 隐式 CoT:训练时显式、推理时隐式,关注训练 vs 部署的解耦
    • 自适应思考(如 Qwen3 think-mode、Seed 1.6 Adaptive CoT):模型在推理阶段自己判断一道题值不值得思考、思考多久,关注推理时的计算分配