LLM 知识梳理

背景

初步学习了 ML/DL、Transformer、RAG、SFT、RL等,为了更好的记忆、理解以及应对面试,故此博客文章诞生。

不定期更新。

ML/DL

数据集

数据集种类

  • 训练集:用于拟合模型,更新权重参数
  • 验证集:用于超参数调优(如学习率、层数、Dropout 概率)和早期停止(Early Stopping)
  • 测试集:仅用于最终评估模型的泛化能力。它代表了模型在“未见过”的真实数据上的表现

面试陷阱: 如果你在训练过程中根据测试集的表现去调整模型,这就叫 “数据泄露” (Data Leakage),会导致评估结果虚高

数据集配比

  • 万级以下
    • 70-15-15:小规模数据(<10k样本)
    • 80-10-10:中等规模数据(10k-100k)
  • 百万级以上
    • 90-5-5:大规模数据(>100k)
    • 98-1-1:超大规模数据(如LLaMA训练数据)
  • 数据量较小时:交叉验证
    • 当数据量较小时,简单的划分会导致评估结果受随机性影响太大。充分利用每一条数据,评估结果更稳健,减少因数据划分不均匀导致的偏差
    • K-Fold 交叉验证: 将数据集分为 $K$ 个等份,轮流用其中 1 份做验证,剩下的 $K-1$ 份做训练。最后取 $K$ 次结果的平均值

数据质量与预处理

  • 数据去重
    • 为什么: 如果训练集和测试集有重复(或高度相似),模型会通过“背诵”而非“理解”来获得高分,导致评估失效
    • 技术: MinHash, LSH (局部敏感哈希)
  • 数据不平衡
    • 问题: 某类样本极多(如正常请求),某类极少(如恶意攻击)
    • 对策:
      • 过采样 (Oversampling): 增加少数类样本
      • 欠采样 (Undersampling): 减少多数类样本
      • 代价敏感学习: 在 Loss 函数中加大对少数类预测错误的惩罚

数据泄露

  • 时间泄露: 在时间序列任务中,用“未来”的数据训练模型去预测“过去”。(应使用时间切分法)
  • 特征泄露: 包含了不该有的目标信息。例如预测是否患病,特征中包含“处方药名称”
  • 预处理泄露: 在划分数据集之前做了全局归一化(Normalization)。正确做法: 先分集,用训练集的均值/方差去处理验证集和测试集

过拟合处理

数据层面

核心逻辑:让模型从“死记硬背”转向“举一反三”。

  • 1.1 增加数据量与多样性
    • 原理:数据越多,模型越难记住每个样本,被迫学习通用规律。涵盖不同领域、风格、情绪
  • 1.2 数据增强 (Data Augmentation)
    • 手段回译(Back-Translation)、同义词替换LLM 文本改写、加入微小噪声
  • 1.3 提升质量 (Data Cleaning)
    • 关键点:去除重复(Deduplication)、修正错误标签、过滤低质量垃圾文本

训练层面

核心逻辑:通过惩罚项或时机控制,约束模型复杂度。

  • 2.1 正则化 (Regularization)
    • 权重衰减 (L2/Weight Decay):通过惩罚大权重,让模型变得更“平滑”
    • Dropout:训练时随机“关闭”一部分神经元,强迫模型不依赖单一路径,增强冗余性。
  • 2.2 早停 (Early Stopping)
    • 策略:监控验证集(Val Loss),一旦表现不再提升或开始变差,立即停止训练。防止从“学习”滑向“记忆”
  • 2.3 学习率调度 (LR Scheduling)
    • 方案余弦退火 (Cosine Decay) 或线性衰减。
    • 目的:后期减小步长,使模型稳定在泛化性好的区域(平坦最小值区)
  • 2.4 LoRA Rank (r) 的权衡:
    • 秩越小,模型可更新的参数越少,过拟合风险越低。
    • 建议:对于 SQL 生成这种逻辑任务,r=16r=64 比较平衡。如果 r=256 甚至更高,且训练数据量小于 5000 条,极易过拟合。

架构层面

核心逻辑:降低自由度,锁死大部分参数。

  • 3.1 参数高效微调 (PEFT/LoRA)
    • 原理冻结 99%+ 的原参数,只训练极少数(<1%)的新增参数(Adapter/Rank 矩阵)
    • 防过拟合优势
      1. 限制自由度:参数极少,模型难以“背诵”微调数据
      2. 保留通用性:原始底座知识被锁死,防止“灾难性遗忘”和针对特定任务的过拟合

正则化

正则化(Regularization)是一种在训练机器学习模型时,在损失函数中添加额外项,来 惩罚过大的参数,进而限制模型复杂度、避免过拟合,提高模型泛化能力的技术。

  • L1 正则化(Lasso 回归):惩罚参数绝对值之和,使部分参数为 0,实现特征选择
  • L2 正则化(Ridge 回归):惩罚参数平方和,使参数值普遍较小,提高模型稳定 性
  • ElasticNet:结合 L1 和 L2 正则化,平衡稀疏性和稳定性

模型评估

分类任务指标 (Classification Metrics)

  • 准确率 (Accuracy):预测正确的样本占总样本的比例。
    • 缺点:在数据不平衡(比如 99% 都是负样本)时会失效。
  • 精确率 (Precision):预测为正的样本中,有多少是真的正样本(查准率)。
  • 召回率 (Recall):实际的正样本中,有多少被你找出来了(查全率)。
  • F1-Score:精确率和召回率的调和平均数。
  • ROC 曲线与 AUC 值
    • ROC 是以假正率(FPR)为横轴,真正率(TPR)为纵轴的曲线。
      • 真正例 (TP):预测为正,实际也为正(预测正确)
      • 真负例 (TN):预测为负,实际也为负(预测正确)
      • 假正例 (FP):预测为正,实际为负(误报)。
      • 假负例 (FN):预测为负,实际为正(漏报)
        $$FPR = \frac{FP}{FP + TN}$$
        $$TPR = \frac{TP}{TP + FN}$$
    • AUC 为曲线下的面积,越接近 1 代表模型分辨正负样本的能力越强。

回归任务指标 (Regression Metrics)

用于预测连续数值(如房价预测、股价预测)

  • MAE (平均绝对误差):预测值与真实值差的绝对值均值。
  • MSE (均方误差):惩罚大的误差,对异常值非常敏感。
  • RMSE (均方根误差):单位与原始数据一致,直观。
  • R² (决定系数):越接近 1 说明模型拟合效果越好。

生成与 NLP 任务指标 (NLP & Generation)

用于评价文本生成或序列标注。

  • BLEU (Bilingual Evaluation Understudy)
    • 常用于机器翻译。计算模型输出与参考答案之间的 n-gram 重合度。
  • ROUGE (Recall-Oriented Understudy for Gisting Evaluation)
    • 常用于文本摘要。侧重于参考答案中有多少内容出现在了模型输出中(召回率)。
  • PPL (Perplexity, 困惑度)
    • 衡量语言模型生成一段文本的“确定性”。PPL 越低,模型生成的文本越自然、越确定。
  • seqeval (IOB 评价)
    • 专门用于评价 NER(命名实体识别),会根据实体的边界和类型是否同时准确来计算 F1。

排序与检索指标 (Ranking & Retrieval)

  • MRR (Mean Reciprocal Rank):只关注第一个正确答案出现的位置。如果第 1 位是正确的,得 1 分;第 2 位正确,得 0.5 分。最后取平均。适用于“只有一个标准答案”的任务,如你项目中的库表字段召回
  • MAP(Mean Average Precision):考虑所有相关文档的准确率。它会对排名靠前的正确结果给予更高权重。适用于目标是找回“所有相关文档”的场景,比 MRR 更全面。
  • nDCG@K (Normalized Discounted Cumulative Gain):考虑了相关度的级别(不仅是 0/1,可以是 0-5 分)和排名位置。排名越靠后,增益衰减越快。工业界最标准。用于评估搜索结果的整体排序质量,@K 表示只看前 K 个结果。

RAGAS (Retrieval-Augmented Generation Assessment) 是目前评估 RAG 流程最流行的开源框架。它提出了一个“无参考训练(Reference-free)”的概念,利用 LLM 来评价 LLM。

其核心是 “RAG 三元组” 的四个评估维度:

  1. Faithfulness (忠实度):生成的回答是否完全来自检索到的上下文?(防止幻觉)。
  2. Answer Relevance (答案相关性):生成的回答是否直接回答了用户的问题?
  3. Context Precision (检索精准度):检索到的片段中,真正有用的信息是否排在前面?
  4. Context Recall (检索完备度):为了回答问题所需的全部信息,是否都被找回来了?

学习率调度

  • Warmup:训练初期为什么要用低 LR(防止初始梯度冲击破坏权重)。
  • 余弦退火:后期缓慢下降如何帮助模型找到更深层的全局最优。

AdamW

AdamW 是 Adam 的改进版,主要区别在于:AdamW 正确地将“权重衰减(Weight Decay)”与“梯度更新”解耦,而 Adam 中的 L2 正则化会被自适应学习率“抵消”,导致正则化失效。
AdamW = Adam + Decoupled Weight Decay (解耦的权重衰减)

特性 Adam AdamW
是否支持权重衰减 ✅ 支持(通过 L2 正则化) ✅ 支持(显式 weight_decay 参数)
正则化是否被自适应学习率影响 ❌ 是,被 vt缩放,效果不稳定 ✅ 否,独立于学习率,稳定有效
参数更新公式 正则化项进入梯度 正则化项单独加在参数上
实际效果 可能欠正则化或过正则化 更稳定、可控的正则化
使用场景 早期研究、简单任务 现代大模型训练(BERT、LLaMA、ViT)首选

架构

RNN

RNN (Recurrent Neural Networks) 通过循环结构处理序列数据,每个时间步的输出依赖当前输入和上一时间步的隐藏状态, 能建模上下文信息。

链式法则乘法效应: 在反向传播(BPTT)过程中,梯度需要跨越时间步相乘。
如果权重矩阵的最大特征值 $< 1$,梯度会指数级衰减(消失);如果 $> 1$,则会指数级增长(爆炸)。
导致模型会“忘记”很久以前的输入,无法捕获长程依赖(Long-term Dependency)

并行计算: RNN 必须按顺序计算(串行),效率低;Transformer 采用 Self-Attention,可以并行计算,适合大规模预训练。

显存占用: RNN 的显存随序列长度线性增长(只存当前状态),而标准 Transformer 是平方增长(KV Cache 压力大)。

LSTM

LSTM (Long Short-Term Memory) 引入记忆单元(Memory Cell)和三个门控机制(遗忘门、输入门、输出门)

  • 遗忘门: 控制忘记多少历史信息
  • 输入门: 控制存入多少新信息到记忆单元
  • 输出门: 控制从记忆单元读取多少信息作为当前隐藏状态。

加法更新: 记忆单元的更新主要是“加法”操作,这比 RNN 的“连乘”更能有效缓解梯度消失。

LSTM 是通过门控逻辑和加法连接,极大缓解了梯度消失,使得它能处理的序列长度从 RNN 的十几个时间步提升到了几百个。但如果序列达到上千甚至上万,LSTM 依然会出现严重的记忆遗忘和梯度消散现象。这时候通常需要 Transformer 的 Attention 机制 来解决。

GRU

GRU (Gated Recurrent Unit, 门控循环单元) GRU 只有两个门:更新门 (Update Gate)重置门 (Reset Gate)

  • 更新门 : 类似于 LSTM 遗忘门和输入门的结合体。它决定了前一时刻的状态 $h_{t-1}$ 有多少要保留,以及当前候选状态 $\tilde{h}_t$ 有多少要存入。
  • 重置门 : 决定在计算当前候选状态时,忽略多少过去的隐藏状态。如果重置门接近 0,说明模型在当前步骤“忘记”了之前的历史,只看当前输入。

“RNN 是基础,但有梯度消失的致命伤;LSTM 通过三个门和细胞状态解决了长期记忆问题;GRU 则是对 LSTM 的精简优化,在保持长记忆的同时,减少了参数量,提高了训练效率。”

特性 RNN (循环神经网络) LSTM (长短期记忆网络) GRU (门控循环单元)
核心机制 简单的递归循环 门控机制 (遗忘、输入、输出门) 门控机制 (更新、重置门)
状态量 只有隐藏状态 $h_t$ 双状态:细胞状态 $C_t$ + 隐藏状态 $h_t$ 单状态:合并为隐藏状态 $h_t$
参数量 最少 (1组权重) 最多 (4组权重) 较少 (3组权重,是 LSTM 的 75%)
长程依赖 极差 (易梯度消失/爆炸) (细胞状态保护了长期记忆) (与 LSTM 效果接近)
计算效率 最高 (计算最简单) 最低 (结构最复杂) 中等 (比 LSTM 快,比 RNN 慢)
主要应用 极短序列、流式信号处理 复杂长文本、翻译、语音识别 强化学习、中等复杂度序列预测

Attention

Query: 表示当前词的用于发起注意力匹配的向量
Key: 表示序列中每个位置的内容标识,用于与 Query 进行匹配
Value: 表示该位置携带的信息,用于加权汇总得到新的表示

缩写 全称 核心特点
MHA Multi-Head Attention 每个 Query 都有自己的一组 Key 和 Value
MQA Multi-Query Attention 所有 Query 共享同一组 Key 和 Value
GQA Grouped-Query Attention Query 分组,每组共享一组 Key 和 Value
MLA Multi-head Latent Attention 通过 低秩压缩 大幅减少 KV 显存

既然 MLA 这么好,它为什么不直接在所有模型上普及?
答案要点: 因为 MLA 涉及复杂的矩阵重新投影(Projection),在训练时的计算开销和复杂度高于 GQA。
此外,MLA 对 RoPE(旋转位置编码)的适配也需要特殊技巧。

MLA步骤

  1. 全局潜空间投影 (Global Latent Projection)
    • 步骤: 传统的 $K$ 和 $V$ 矩阵,首先被投影到一个低维的潜空间中。
    • 作用: 这是一个“信息浓缩”**的过程,捕捉原始 Key/Value 中的核心信息。
  2. 潜空间融合 (Latent Space Aggregation)
    • 步骤: 随着序列的增长,新的 Query 进来,它对应的 Key 和 Value 也会被投影到这个低维潜空间。然后,所有这些低维的潜 Key/Value 向量会被聚合起来。
    • 作用: 相当于在低维空间中维护一个“浓缩的历史上下文”,而不是存储每一个原始的 KV 向量。这个聚合可以是一个简单的求和,或者更复杂的递归操作。
  3. 解压缩与局部注意力 (Decompression & Local Attention)
    • 步骤: 当一个 Query 需要计算注意力时,它不会直接和低维的潜 KV 向量进行点积。
      1. 从低维潜空间中解压缩出一个近似的、高维的 Key 和 Value 矩阵。
      2. 然后使用这个近似的 KV 矩阵与当前的 Query 进行标准的注意力计算。
    • 作用: 确保了最终的注意力计算依然是高维的,但存储和传输的 KV Cache 始终是低维的,极大地减少了显存开销。

Flash Attention

特性 SRAM (静态随机存储) HBM (高带宽显存) DRAM (动态随机存储)
物理位置 芯片内部(就在算力核心旁边) 芯片封装内(通过中间层连接) 主板上(通过总线连接,如内存条)
容量 极小 (MB 级别) (如 H100 的 80GB) 极大 (几百 GB 到 TB)
速度/带宽 极快 (TB/s 级别,纳秒延迟) (1-3 TB/s) (几十 GB/s)
成本 极高 (涉及 3D 堆叠工艺) (成熟的大规模工业品)
AI 角色 计算工作台 (存 Tile、中间计算值) 大模型仓库 (存权重 W、KV Cache) 冷备份/数据源 (存放原始训练数据集)

为什么标准的 Attention 很慢?

在标准的 Attention 计算中,最大的瓶颈不是计算量(FLOPs),而是内存访问(Memory Wall)

  • 中间矩阵巨大: 计算 $QK^T$ 会产生一个 $L \times L$ 的矩阵($L$ 是序列长度)。如果序列长达 128K,这个矩阵大到显存根本装不下。
  • 读写太频繁: 显卡(GPU)的计算核心(CUDA Core)很快,但从显存(HBM)搬运数据到核心(SRAM)的速度很慢。标准做法是频繁地在显存和核心之间读写巨大的中间矩阵,导致 GPU 大部分时间在“等数据搬运”。

Flash Attention 提出了两个绝招来打破瓶颈:

A. 分块计算 (Tiling)

  • 做法: 将大矩阵拆成一个个小方块(Tiles)。
  • 原理: 每次只搬一小块 $Q, K, V$ 到 GPU 的高速缓存(SRAM) 里,在里面把这一小块的注意力算完。
  • 结果: 整个过程不需要在显存(HBM)中存储那个巨大的 $L \times L$ 中间矩阵,极大地减少了数据搬运次数。

B. 重计算 (Recomputation / Gradient Checkpointing)

  • 做法: 在反向传播时,不存储前向计算的中间结果。
  • 原理: 因为中间结果太占地方,Flash Attention 选择在反向传播时根据 SRAM 里的数据现场重新算一遍
  • 结果: 看起来多算了,但因为省去了读写显存的时间,总时间反而快得多(用计算换带宽)。

Flash Attention 2

  • 并行维度的改进(核心区别)
    • V1:主要在序列长度(Sequence Length)维度做并行。如果序列不够长,GPU 的利用率就跑不满。
    • V2:不仅在序列维度,还在**注意力头(Attention Heads)**维度也做了并行。这意味着即便在 Batch Size 较小或序列中等的情况下,也能榨干 GPU 的算力。
  • 计算效率优化
    • 减少非矩阵乘法开销:V2 优化了 Softmax 的计算逻辑,减少了在 GPU 缓存(SRAM)中对非矩阵乘法(Non-matmul)的操作。GPU 最擅长做矩阵乘法,V2 让它更多地留在“舒适区”。
  • 因果掩码优化(Causal Masking)
    • 在处理像 LLM 这种从左往右生成的模型时,V2 能够跳过那些被掩码(Mask)掉的、不需要计算的区域,计算速度翻倍。

激活函数

特性 ReLU GELU SwiGLU
是否门控 ❌ 否 ❌ 否 ✅ 是(双分支)
是否平滑 ❌ 否(折点) ✅ 是 ✅ 是
计算复杂度
是否零中心 ❌ 否 ✅ 接近 ✅ 是
梯度特性 可能消失/死亡 良好 优秀
使用模型 早期模型 BERT、GPT-2、ViT LLaMA、PaLM
推荐场景 轻量模型 通用 NLP/CV 大模型、高性能需求

MoE

MoE(Mixture of Experts,混合专家模型) 是在传统 FeedForward模块基础上的一种结构扩展

核心思想:使用多个并行的 FeedForward 专家替代单一的 FeedForward 层, 并通过 Router(路由器)根据输入 Token 的特征选择其中少量最合适的专家参与计算。

不同类型的输入能够由擅长处理该类模式的专家负责,从而显著增强模型的表达能力与适应性。
MoE 已成为当前主流大语言模型(LLM)中广泛采用的、用于提升性能与效 率的关键结构之一

  1. 核心优势 (Pros) —— “大而快”
    • 计算效率 : 推理时仅激活 Top-K 专家,FLOPs(计算量) 显著降低
      • 能以较小的活跃参数量实现巨大的总参数量(Total Params)性能
    • 高扩展性: 模型容量暴力扩张,而训练/推理成本不随之翻倍
    • 任务特化: 专家会自发分工(如代码、数学、文案专家),提升复杂长尾任务的上限
  2. 核心挑战 (Cons) —— “贵而难”
    • 显存饥饿 : 虽然推理快,但显存必须装下所有专家权重
    • 训练不稳 : 易发生专家崩溃 (Expert Collapse):路由集中在少数专家
      • 需引入 负载均衡损失 ,平衡不好会损耗模型精度
    • 通信瓶颈 : 分布式场景下存在巨大的 All-to-All 节点间通信 开销(Token 跨卡寻找专家)
    • 微调困难: 在下游小数据集上极易过拟合,对数据分布变化敏感。
维度 稠密模型 (Dense) 混合专家模型 (MoE)
计算复杂度 随参数量同步增长 (取决于激活参数)
显存占用 与参数量成正比 极高 (必须全量装载)
硬件要求 算力 (GPU Core) 显存带宽 + 节点间带宽 (NVLink)
训练策略 标准收敛,稳定 复杂,需负载均衡策略

mHC

mHC 将可学习的矩阵 映射为 双随机矩阵,即 的总和均为1的矩阵

特性 传统残差 (Residual) HC (Hyper-Connections) mHC (Manifold-Constrained)
路径数量 单一路径 多条并行路径 约束后的多条并行路径
数学逻辑 简单的元素相加 自由权重的矩阵叠加 流形约束(Birkhoff 流形)
稳定性 极高(工业界标准) 极差(易爆炸/消失) 极高(能支撑超大规模训练)
表达上限 受限(信息拥挤) 很高但无法训练 最高(兼顾容量与稳定)
代表模型 GPT 系列、Llama 系列 实验性小模型 DeepSeek 相关前沿架构
![[mHC.png]]

归一化

归一化(Normalization) 技术的演进是为了解决深层神经网络中的“内部协变量偏移”问题,并确保梯度在数十层甚至上百层网络中依然能够稳定流动。

  • Batch Norm (BN):
    • 原理:对当前 Batch 内的所有样本,在每一个特征维度上独立计算均值和方差。
    • 局限性
      • 如果 Batch 太小,计算出的均值和方差不具备代表性,模型效果剧降。
      • 在 NLP 中,句子长度不一。BN 在计算时会将有效字符与补齐字符(Padding)混合计算,严重干扰语义表达。
  • Layer Norm (LN):
    • 原理:针对单个样本,对其内部的所有特征值计算均值和方差。
    • 优势
      • 独立性:计算不依赖其他样本,无论 Batch Size 是 1 还是 1024,结果一致。
      • NLP 适配:它是 TransformerBERT 架构的基础,能完美处理不同长度的句子。
  • RMSNorm:
    • 核心改进:舍弃平移(Re-centering)重缩放(Rescaling)才是归一化的核心价值。RMSNorm 直接去掉了均值计算,只计算均方根
  • Pre-Norm vs. Post-Norm:路径的抉择
    • 这决定了残差连接(Residual Connection)与归一化层的先后顺序,直接影响训练的稳定性。
特性 Post-Norm (经典 Transformer/BERT) Pre-Norm (GPT/Llama/DeepSeek)
结构 $x = \text{Norm}(x + \text{Sublayer}(x))$ $x = x + \text{Sublayer}(\text{Norm}(x))$
位置 放在残差连接之后。 放在子层运算之前。
梯度流动 路径上存在 Norm 变换,梯度会被层层削弱或增强。 存在恒等路径,梯度可以直接流向浅层,不会被中途拦截。
训练表现 收敛难。如果不配合精心设计的 Warmup,极易崩盘。 非常平稳。允许模型堆叠到数百层而不会梯度消失。

位置编码

绝对位置编码 (Absolute PE)

模型为每一个物理位置(索引 $0, 1, 2 \dots$)分配一个唯一的特征向量,并在输入层直接加到词向量上。

  • 固定式 (Fixed/Sinusoidal):
    • 原理: 使用正弦(Sin)和余弦(Cos)函数计算。
    • 优点: 无需训练参数,理论上能处理训练时没见过的长度。
    • 代表: 原始 Transformer。
  • 可学习式 (Learned):
    • 原理: 维护一个 (max_len, hidden_dim)Embedding 查找表
    • 优点: 灵活性高,能学到特定位置的统计特征。
    • 缺点(致命伤):“长度硬上限”。如果预设 512,遇到第 513 个 Token 就会报错。
    • 代表: BERT、GPT-2。

相对位置编码 (Relative PE)

模型不关心绝对坐标,它关心的是词与词之间的距离差值(如:$i-j = -2$ 代表目标词在我左边两个位子)。

  • 偏置式 (Learned Bias):
    • 原理: 在计算 Attention Score 时,根据距离查表获取一个**可学习的偏置标量(Bias)加进去
    • 优点: 具备平移不变性(句子整体挪动不影响结果),外推性好
    • 缺点: 推理慢。每一步生成都要重新算距离,对 KV Cache 的实现很不友好
    • 代表: T5、DeBERTa
  • 线性衰减 (ALiBi):
    • 原理: 不用向量,直接在 Attention 矩阵上按距离强行扣分(距离越远扣得越多。
    • 代表: Bloom

旋转位置编码 (RoPE) —— “转出来的相对关系”

目前大模型(Llama 3, DeepSeek)的绝对标配。它是绝对位置的形式,相对位置的灵魂。

  • 原理: 将词向量两两一组看作复数,根据位置 $n$ 旋转角度 $n\theta$。

    $$q_m \cdot k_n = \text{Re}{ \mathbf{q}_m \mathbf{k}_n^* e^{i(m-n)\theta} }$$

  • 核心特性(面试必背):

    1. 绝对的形式: 每个词根据自己的位置 $m$ 独立旋转,不依赖别人,推理快。
    2. 相对的效果: 两个词点积的结果只由它们的夹角差(相对距离 $m-n$) 决定
    3. 远程衰减: 随着距离拉长,点积结果会自然衰减
  • 代表: Llama 系列、Qwen、DeepSeek。

维度 绝对位置编码 (Learned) 相对位置编码 (T5 Bias) 旋转位置编码 (RoPE)
实现方式 nn.Embedding 查找表 Attention Score 加偏置项 向量旋转变换
是否可学习 (函数固定)
长度外推 极差 (有硬上限) 较好 极好 (支持插值扩展)
推理效率 极高 (加法运算) 较低 (每步重算距离) 高 (硬件友好)
主流地位 早期模型 (BERT) 特定模型 (T5) 现代模型标配

Transformer

Milvus 索引

  1. 稠密向量索引 (Dense Vector Indexes)

这是 RAG 系统中最常用的索引,主要用于处理像 BGE-m3 (1024维) 这种 Embedding 向量。根据实现机制,又可细分为:

  • 暴力搜索 (FLAT)
    • 特点:不做任何压缩或聚类,全量计算。
    • 适用:数据量极小(百万级以下),要求 100% 召回率的场景。
  • 倒排文件索引 (IVF 系列):通过聚类将空间划分为“桶”,查询时只搜索最近的桶。
    • IVF_FLAT:不压缩向量,平衡速度与精度。
    • IVF_SQ8:采用标量量化(4字节变1字节),大幅减少内存占用。
    • IVF_PQ:采用乘积量化,压缩率极高,适合超大规模数据,但有精度损耗。
  • 图索引 (HNSW)
    • 特点:构建多层图结构,查询速度极快,QPS 高。
    • 适用:你项目中的 NL2SQL 或 RAG 实时检索,它是目前大多数生产环境的首选方案。
  • 基于磁盘的索引 (DiskANN)
    • 特点:将索引存在 SSD 上,仅在内存保留极少部分。
    • 适用:内存预算有限,但数据量达到亿级的场景。

查询参数 ef:在高峰期,可以适当调小 ef 值(例如从 200 降到 64)。ef 越小,搜索时遍历的节点越少,速度越快,虽然精度会有轻微下降,但在 NL2SQL 等语义容错较高的场景下非常划算。

构建参数 M:如果业务数据更新不频繁,建议在构建索引时增大 M(如 32 或 48),这会增加索引文件大小,但能显著提升检索时的路径寻找效率。

  1. 稀疏向量索引 (Sparse Vector Indexes)

主要用于处理 BM25 关键词特征或词袋模型生成的向量。

  • SPARSE_INVERTED_INDEX:类似于搜索引擎的倒排索引,专门针对非零元素极少的稀疏向量进行优化。

  • SPARSE_WAND:一种弱与(Weak AND)算法加速的稀疏索引,用于在大规模稀疏数据中快速过滤。

    1. 标量索引 (Scalar Indexes)

用于处理非向量字段(如用户 ID、订单日期、商品类别等)的过滤查询。

  • INVERTED (倒排索引)最推荐,适用于字符串、整数等,支持精确匹配和前缀搜索。

  • BITMAP (位图索引):适用于基数(Unique values)较少的字段,如“性别”、“是否在售”。

  • STL_SORT:利用排序进行二分查找,适用于数值型的范围查询。

  • Trie (字典树):专门优化字符串的前缀匹配。

    1. GPU 加速索引

如果你的 L20 集群 算力充足,可以使用专门针对 GPU 优化的索引来获取极致性能:

  • GPU_CAGRA:针对 GPU 深度优化的图形索引,适合超高并发。
  • GPU_IVF_FLAT / GPU_IVF_PQ:将 IVF 的搜索过程搬到 GPU 上。

微调

部署方式

维度 vLLM (最终选择) SGLang (备选/关注) TRT-LLM (放弃)
部署哲学 动态即时加载 动态前缀加速 静态提前编译 (AOT)
核心优势 极高的工业稳定性与兼容性 长文本/RAG 场景下的极低 TTFT 极致的单卡原始吞吐量
显存管理 PagedAttention (成熟稳定) RadixAttention (前缀复用) 静态分配 (容易浪费显存)
分布式底座 Ray (弹性、自动化运维) Ray / Native MPI (配置极其繁琐)
研发兼容性 最高 (支持各种量化与模型) 较高 (偏学术和 Agent 场景) 最低 (环境依赖极度严苛)
  1. 研发效率与后训练(DPO)的完美契合
    • 痛点回避:TRT-LLM 每次 DPO 训练后都需要半小时编译,这会中断我们的“训练-评估”闭环。
    • vLLM 优势:支持直接加载 HuggingFace 格式权重。在 L20 集群上,我们可以实现分钟级的模型版本切换,极大地加速了 NL2SQL 模型的迭代速度。
  2. L20 显存特性的极致利用
    • 显存灵活性:L20 有 48GB 显存,虽然充裕但并非无限。
    • vLLM 表现:相比 TRT-LLM 必须写死 Max_Length 导致的显存预占(浪费),vLLM 的 PagedAttention 允许我们在同一张卡上动态处理不同长度的 SQL 请求。在处理复杂的、长短不一的数据库 Schema 时,vLLM 的显存利用率更高,支持的实际并发数往往超过了静态配置的 TRT-LLM。
  3. 分布式运维的“减负” (基于 Ray)
    • 选型逻辑:在 L20 集群中,我们经常需要从单卡扩展到多卡 TP(张量并行)。
    • vLLM 胜出:基于 Ray 的分布式架构让我们只需通过一个参数(--tensor-parallel-size)即可完成扩容。Ray 自动处理了多进程间的资源竞争、健康检查和失败自愈。
    • 对比 MPI:放弃 TRT-LLM 的主要原因之一就是它依赖 MPI,在容器化部署和动态扩缩容时,MPI 的网络配置和静态引擎分发是极大的运维负担。
  4. 工业级稳定性与 FP8 生态
    • 硬件匹配:L20 的核心优势是 FP8
    • 实测结论:2026 年的 vLLM 对 FP8 推理的支持已经非常成熟。在我们的实测中,vLLM 的 FP8 吞吐量已经能够满足业务高峰需求,而 TRT-LLM 带来的额外性能提升(15%左右)并不足以抵消它在维护和开发上的巨大成本。

“在 L20 集群的部署选型中,我最终选择了 vLLM。我的决策核心在于:‘用最成熟的工业方案,换取最高的研发周转率’

  1. 避开 TRT-LLM 的‘静态陷阱’:它虽然快,但‘静态编译’和‘MPI 依赖’严重阻碍了我们 DPO 训练后的快速验证,不符合 NL2SQL 这种需要频繁迭代 Prompt 和权重的业务逻辑。

  2. 对比 SGLang 的‘稳健考量’:虽然 SGLang 的前缀缓存很诱人,但在大规模集群生产环境下,vLLM 的社区支持更完备,对于各种量化格式(尤其是 L20 擅长的 FP8)的兼容性更稳。

  3. 拥抱 Ray 的‘分布式效率’:基于 Ray 的 vLLM 让我们在 L20 节点之间实现了声明式的资源管理,极大地降低了分布式运维的复杂度。

总结来说,vLLM 在 L20 硬件上提供了最平衡的性价比,让我们能把精力集中在 SQL 生成的准确率优化上,而不是卡在部署工具的底层报错里。”

Ray

为什么要用 Ray 来实现并行?(底座逻辑)

目的:

  • 跨进程抽象:Python 有全局解释器锁(GIL),单进程无法同时利用多张显卡。Ray 能将多个 Python 进程(Actors)像管理本地对象一样管理起来。
  • 统一调度:在一个 L20 集群中,Ray 自动处理“哪个进程去哪张卡”的问题。
  • 低延迟通信:Ray 优化了进程间通信,并能很好地集成 NCCL(NVIDIA 集合通信库),这对于张量并行中高频的矩阵数据交换至关重要。
    缺点:
  • 额外开销:Ray 作为一个中间管理层,会占用少量的 CPU 和内存资源。
  • 调试复杂度:当分布式系统报错时,日志散落在不同进程中,比单进程更难排查。

不同并行方式的深度对比

A. 张量并行 (Tensor Parallelism, TP) —— “横着切”

  • 做法:将每一层网络里的巨大**矩阵运算(Matrix Multiplication)**拆分。比如 2 张 L20 各算一半,最后求和。
  • 目的降低单卡计算延迟。它是解决“单次推理太慢”的最有效手段。
  • 缺点通信频率极高。每经过一层网络,多张卡之间都要进行一次数据同步(All-Reduce)。如果显卡之间没有 NVLink(比如普通的 PCIe 连接),通信开销会迅速抵消计算收益。

B. 流水线并行 (Pipeline Parallelism, PP) —— “竖着切”

  • 做法:将模型的层(Layers) 拆分。比如前 40 层放卡 A,后 40 层放卡 B。
  • 目的解决显存容量不足。当模型(如 70B)在单张卡(即使是 48GB 的 L20)上完全装不下时,必须用 PP。
  • 缺点流水线气泡(Bubbles)。当卡 B 在算第 41 层时,卡 A 如果没有新任务就会闲置。虽然 vLLM 通过连续批处理缓解了这一点,但它的延迟表现通常不如 TP。

C. 数据并行 / 多副本并行 (Data Parallelism / Replica) —— “复制”

  • 做法:每张卡上都跑一个完整的模型。
  • 目的提升集群总吞吐量(QPS)。适合用户量大的场景。如果 100 个人同时提问,两个副本可以各处理 50 个。
  • 缺点显存浪费。如果模型本身很大,每个副本都要占一份显存,无法处理超大规模模型。

为什么面试中要强调“结合业务选并行”?
你可以结合你的 NL2SQL 项目,给面试官一个“专业架构师”的视角:

“在我们的 L20 显卡环境下,针对 Qwen-32B 模型,我采用了 TP=2 的策略。

  • 为什么不选 PP? 因为 32B 模型在 L20 (48GB) 上单卡勉强能装下,但为了留出足够的显存给 KV Cache(处理长 Schema),我们选择横向切分。PP 在这种规模下会引入不必要的层间等待,影响 SQL 生成的流畅度。

  • 为什么不只选数据并行? 因为 NL2SQL 的 Prompt 通常很长,单卡推理延迟(TTFT)较高。通过 TP=2,我们利用 Ray 协调两张卡协同计算,将首字延迟降低了约 40%。

  • Ray 的价值:它帮我抹平了多进程启动和 NCCL 初始化的复杂逻辑,让我能通过一套代码灵活切换 tp_size。”

总结:并行的选择逻辑图

并行模式 核心解决的问题 带来的负面影响 推荐场景
TP (张量) 计算慢 极其依赖显卡间带宽 (NCCL) 单次请求响应要求极快
PP (流水线) 装不下 产生计算空隙 (气泡) 超大规模模型 (70B+)
DP (多副本) 接不住 显存占用翻倍 高并发、小模型场景
结合方式 解决的核心矛盾 牺牲的代价 2026 年现状
TP + DP 延迟 vs 并发 显存占用翻倍 主流配置。vLLM 默认支持得最好。
TP + PP 计算速度 vs 显存容量 通信延迟累加 仅在超大模型 (100B+) 部署时使用。
PP + DP 容量 vs 并发 存在流水线气泡 较少见,通常会被 TP + DP 取代。

vLLM加速推理的原理

PagedAttention
这是 vLLM 的灵魂,灵感来自操作系统的虚拟内存分页管理。

  • 痛点:在传统推理中,LLM 需要为每个请求分配一段连续的显存来存放 KV Cache(缓存已生成的词,避免重复计算)。由于模型生成的长度不可预测,框架往往会按照“最大长度”预分配显存,导致大量碎片(内存碎片化)和显存浪费。

  • 原理:PagedAttention 将 KV Cache 分解为固定大小的 “物理块”**(类似于内存页)。这些块在物理显存上可以是不连续的。

  • 效果

    • 零浪费:显存利用率接近 100%
    • 并发数翻倍:因为不再需要为每个请求预留大量空白显存,同一块显卡能同时跑的请求数(Batch Size)提升了数倍。
  • 传统静态 Batching (Static Batching): 类似公交车。必须等一整车人都上齐了(Batch 里的所有请求都完成了 Token 生成),车才会开往下一站。如果其中一个请求要生成 500 个 Token,而其他请求只要 10 个,那么那几个短请求必须在原地“陪跑”,导致 GPU 算力极度浪费。

  • Continuous Batching (连续批处理): 类似电梯。电梯不需要等所有人到一楼才重新运行。只要有人出电梯(某个请求生成结束),新的人(新请求)就可以立马进电梯。它是在 Iteration(迭代)级别进行调度的,每生成一个 Token,调度器就会检查有没有新请求可以塞进来,或者旧请求是否已结束。

DeepSpeed 和 vLLM 是什么关系

特性 DeepSpeed vLLM
主要阶段 训练阶段 (Training / Fine-tuning) 推理/部署阶段 (Inference / Serving)
核心目标 节省显存、支持超大模型训练 提高吞吐量 (QPS)、降低延迟
关键技术 ZeRO 1/2/3, 梯度累积, 混合精度 PagedAttention, Continuous Batching
形象比喻 它是建筑工人,负责把楼盖起来 它是物业管家,负责让住户快速进出

DeepSpeed ZeRO

在传统的 DDP(分布式数据并行)中,每个 GPU 都要复制一份完整的模型。对于大模型,内存主要被“模型状态”占据,包括:1. 参数(Params)2. 梯度(Gradients)3. 优化器状态(Optimizer States,如 Adam 的动量和方差)

阶段 存储策略 内存节省 通信开销 适用场景
ZeRO-0 传统的 DDP 无(每个 GPU 都有完整副本) 模型很小,单卡能放下。
ZeRO-1 只切分优化器状态 ($P_{os}$) 减少约 4 倍 与 DDP 一致 显存压力适中,最常用
ZeRO-2 切分优化器状态 + 梯度 ($P_{os+g}$) 减少约 8 倍 与 DDP 一致 大多数微调任务的首选。
ZeRO-3 切分模型参数 + 优化器 + 梯度 ($P_{os+g+p}$) 随显卡数线性减少 显著增加 单卡放不下模型

KV Cache 管理机制

  • vLLM (PagedAttention):将 KV Cache 分页,解决了显存碎片问题,但在处理共享前缀(Shared Prefix) 时(比如 RAG 里的长文档,或者多轮对话里重复的 System Prompt),它通常需要重复计算。

  • SGLang (RadixAttention):它维护了一个“树状结构”的 KV Cache。它能自动识别并缓存 Common Prefix(公共前缀)

    • 效果:如果你有 100 个问题都是基于同一个长文档(RAG),vLLM 可能会重复处理文档,而 SGLang 只处理一次并永久缓存该前缀,首字延迟(TTFT)能降低数倍。

Prefix-Tuning(PEFT)

技术名称 插入位置 每一层都加吗? 训练参数量 擅长领域 核心痛点
Prompt Tuning Input Embedding 层 ❌ 仅第一层 极小 (0.01%) 只有超大模型 (10B+) 才好使 小模型效果差;收敛慢
Prefix Tuning Attention 层 (KV Cache) ✅ 每一层 较小 (0.1%-1%) 生成任务 (NLG) 如翻译/摘要 占用 KV Cache 长度;推理稍慢
P-Tuning (v1) Input Embedding 层 ❌ 仅第一层 极小 (0.01%) 理解任务 (NLU) 如分类/抽取 依然只在第一层,表达力有限
P-Tuning v2 Attention 层 (KV Cache) ✅ 每一层 较小 (0.1%-3%) 全能型 (NLU+NLG+大小模型) 实现复杂度略高

① Prompt Tuning (谷歌出品) —— “最纯粹的软提示”

  • 做法:在输入的文字 Embedding 前面拼上一段可训练的向量。
  • 例子:用户说“查询 SQL”,模型前面先塞 10 个随机向量。
  • 面试点:它发现了一个神奇现象——模型越大,效果越好。当模型到 100B 规模时,Prompt Tuning 效果直逼全量微调,但在 7B/13B 这种“小模型”上表现很烂。

② Prefix Tuning (斯坦福出品) —— “每一层的强力引导”

  • 做法:它不改 Embedding,而是直接在每一层 Transformer 的 Attention Key/Value 前面加上前缀。
  • 关键点:它通过一个 MLP 来生成这些前缀。因为它在每一层都施加了影响,所以它在生成任务(NLG)上表现非常稳。

③ P-Tuning v1 (清华/THUDM) —— “用 LSTM 解决离散问题”

  • 对比 Prompt Tuning:它也是只在输入层加向量,但它引入了 LSTM 编码器
  • 为什么要加 LSTM? 因为作者认为提示词向量之间应该有相关性。LSTM 能让这些虚拟 Token 变得更“平滑”,解决了 Prompt Tuning 在 NLU(自然语言理解)任务上不稳定的问题。

④ P-Tuning v2 (清华/THUDM) —— “PEFT 的集大成者”

  • 本质P-Tuning v2 $\approx$ 针对 NLU 优化后的 Prefix Tuning。
  • 改进点
    1. 多层注入:学 Prefix Tuning,在每一层都加提示向量。这让它在 1B-10B 的小模型上也能爆发。
    2. 分类头改进:不再用复杂的 Verbalizer(词表映射),直接在输出层加线性层,更符合传统微调习惯。
    3. 多任务共享:支持不同任务间共享 Prompt。

LoRA 原理(PEFT)

LoRA (Low-Rank Adaptation) :低秩自适应

核心思想:大模型虽然参数多,但在针对特定任务(比如写 SQL)微调时,并不需要改变所有参数,只需要改变一个 “低维度的本质空间”

  • 传统微调:修改模型原本的权重矩阵 $W$(参数量极大)。
  • LoRA 做法:冻结原有的 $W$(不训练它)。在旁边外挂两个小矩阵 $A$ 和 $B$。
    • $A$ 的形状是 $(d \times r)$,$B$ 的形状是 $(r \times d)$。
    • $r$ 就是 Rank(秩),通常选 8、16、64。因为 $r \ll d$,所以 $A$ 和 $B$ 的参数量极小(通常不到原模型的 1%)。
  • 计算公式:$h = Wx + \Delta Wx = Wx + BAx$
  • 优点
    • 显存省:不需要存储原始大矩阵的梯度和优化器状态。
    • 无推理延迟:部署时可以把 $BA$ 合并回 $W$,不增加预测时间。

QLoRA (Quantized LoRA) :量化低秩自适应

核心思想:在 LoRA 的基础上,把“省显存”做到了极致。它是 LoRA 的升级版,引入了三个关键技术:

① 4-bit NormalFloat (NF4)

  • 原理:普通量化是均匀分布的,但模型权重通常呈“正态分布”。QLoRA 专门设计了一种 NF4 数据类型,让 4 位数字能更精准地描述正态分布的权重。
  • 效果:虽然只用了 4-bit,但精度几乎等同于 FP16。

② 双量化 (Double Quantization)

  • 原理:量化本身需要存储一些“缩放系数(Quantization Constants)”。QLoRA 觉得这些系数也占地方,于是对这些系数又进行了一次量化。
  • 效果:每亿个参数能再省下约 0.5GB 显存。

③ 分页优化器 (Paged Optimizers)

  • 原理:利用类似 CPU 内存分页的机制。当 GPU 显存偶尔“爆掉”时,它会把部分优化器状态临时传给 CPU 内存,等需要时再传回来。
  • 效果:防止了长文本训练时突然发生的显存溢出(OOM)。

为什么 LoRA 依然是“老大哥”?

目前企业内部(尤其是拥有 A100/H100 或高性能国产算力集群的公司)更倾向于使用 LoRA,原因如下:

  • 训练速度更快:LoRA 使用的是 FP16/BF16 精度,不需要像 QLoRA 那样在训练过程中不断地进行“量化/反量化”的计算转换。在大规模数据集上,LoRA 的训练效率通常比 QLoRA 高出 20%~30%

  • 精度损失几乎为零:虽然 QLoRA 宣称精度接近全量微调,但在极高性能要求的垂直领域(如金融法律条文、医疗诊断),FP16 的 LoRA 表现出的鲁棒性(稳定性)比 4-bit 量化的 QLoRA 更可靠。

  • 工程生态更成熟:很多早期的微调框架和推理引擎(如 vLLM、TGI)对 LoRA 适配得极好,能够实现“1 个底座 + N 个 LoRA 插件”的秒级切换。

PTQ、QAT、AWQ

PTQ (Post-Training Quantization) —— 训练后量化

  • 做法:模型训练完了,直接拿来“砍一刀”。它通过一小部分数据(校准集)观察权重的分布,然后把 FP16 的浮点数映射到 INT8 或 INT4。
  • 特点快、省钱。不需要重新训练模型,几小时就能搞定。
  • 现状:目前 90% 的开源量化模型(如 GPTQ 格式)都属于 PTQ。

QAT (Quantization Aware Training) —— 量化感知训练

  • 做法:在训练阶段就告诉模型:“你以后是要被砍成 INT4 的”。在训练中模拟量化的损失,让模型学会补偿这种精度损失。
  • 特点精度最高,尤其是在 2-bit 或 4-bit 的极低比特下。
  • 缺点。需要巨大的算力和数据重新训练,通常只有模型原作者(如 Meta、阿里)会做。

AWQ (Activation-aware Weight Quantization) —— 激活感知量化

  • 做法:这是一种更聪明的 PTQ。它发现:权重里只有 1% 是“核心资产”,剩下的 99% 是“平庸大众”。AWQ 会通过观察激活值,把那 1% 的核心权重保护起来不乱砍,只砍剩下的。
  • 特点目前推理性能和精度的甜点点。相比 GPTQ,AWQ 在 vLLM 上的推理速度通常更快,且对逻辑推理能力的保留更好。

AWQ 量化

主要分为量化(模型压缩)部署(加载执行) 两个环节。
在工业界,通常不会从零写代码,而是利用成熟的工具链。以下是操作 Qwen 2.5 模型的具体步骤:

什么是 AWQ?(核心原理)

传统的量化(如 GPTQ)通常只看 权重(Weights) 本身,尝试寻找让权重误差最小的量化参数。但 AWQ 的核心发现是:并非所有权重都同等重要。

  • 观察激活值(Activation-aware):AWQ 发现,在模型推理过程中,只有不到 1% 的显著通道(Salient Channels)对输出结果起决定性作用。

  • 保护“重要”权重:AWQ 不直接对权重进行复杂的二阶优化,而是通过观察推理时的激活值分布,识别出那些对性能贡献最大的权重通道。

  • 缩放变换(Scaling):为了保护这些重要通道,AWQ 会对它们进行空间缩放,使其在量化后的精度损失降到最低。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_path = "Qwen/Qwen2.5-32B"
save_path = "Qwen2.5-32B-AWQ"

# 1. 加载模型
model = AutoAWQForCausalLM.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 2. 量化配置 (指定 4-bit, 组大小 128)
quant_config = {"zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM"}

# 3. 执行量化 (这里会用到校准集)
model.quantize(tokenizer, quant_config=quant_config)

# 4. 保存模型
model.save_quantized(save_path)

量化好后,部署就非常简单了。vLLM 内置了对 AWQ 的原生支持,会自动识别模型文件夹里的 `quantize_config.json`。

python -m vllm.entrypoints.openai.api_server \
--model /path/to/Qwen2.5-32B-AWQ \
--quantization awq \
--dtype half \
--max-model-len 8192 \
--gpu-memory-utilization 0.9

模型蒸馏

蒸馏的核心三要素

  • 教师模型 (Teacher):大而强,它是知识的源头。
  • 学生模型 (Student):小而快,它是被训练的对象。
  • 知识 (Knowledge):教师模型输出的“软目标(Soft Targets)”——即模型不仅告诉学生什么是对的,还告诉学生错误选项之间的相似性(这就是所谓的“暗知识”)。

蒸馏的具体做法(三类主流路径)

A. 响应蒸馏 (Response-based) —— 模仿结论
这是最常用的方式,让学生模型去拟合教师模型的 Logits(输出层概率分布)

  • 操作
    1. 用同一个样本输入两个模型。
    2. 计算学生输出与教师输出(软标签)之间的 KL 散度(Kullback-Leibler Divergence)
    3. 结合原始的硬标签(Ground Truth)损失,进行联合训练。

B. 特征蒸馏 (Feature-based) —— 模仿过程
不仅看结果,还要求学生模型中间层的 特征图 (Feature Maps)注意力矩阵 (Attention Maps) 与教师一致。

  • 操作:在学生模型中间加一个投影层(Projection Layer),使其维度对齐教师模型,然后计算 MSE 损失
  • 价值:让学生模型学习教师模型的“思考逻辑”。

C. 关系蒸馏 (Relation-based) —— 模仿逻辑
让学生模型学习样本之间的相互关系

  • 操作:如果教师模型认为 A 样本和 B 样本很像,那么学生模型也必须认为它们很像。

进阶玩法:

  • 数据生成式蒸馏 (Data Augmentation)
    • 利用教师模型对大量无标签数据进行标注(打分、解释、推理链),生成高质量的 SFT 数据集,再给学生模型训练。
  • 思维链蒸馏 (CoT Distillation)
    • 让大模型输出“推理过程(Rationale)”而不只是答案。学生模型通过学习这些推理逻辑,可以显著提升逻辑推导能力。
  • DPO 引导蒸馏
    • 利用教师模型作为 Reward Model,对学生模型的多个输出进行排序,然后利用 DPO(直接偏好优化) 进行微调。

模型剪枝

剪枝的两种主要流派

在面试或工程中,你会听到这两个词,它们的区别决定了你的模型能不能在硬件上跑得更快:

非结构化剪枝 (Unstructured Pruning)

  • 做法:随机剪掉单个神经元之间的连线。哪里没用点哪里。
  • 结果:权重矩阵变成了“稀疏矩阵”(像网眼布一样,到处是洞)。
  • 缺点:虽然参数少了,但 GPU 的计算单元通常是成块计算的。这些“洞”太乱,GPU 还是得扫过整个区域,计算时间往往不减反增

结构化剪枝 (Structured Pruning) —— 工业界更看重

  • 做法:整行、整列或整层地剪掉。比如直接砍掉一个 Attention Head(注意力头)或一整层。
  • 结果:矩阵变小了,但依然是整齐的矩形。
  • 优点:GPU 能够直接识别变小后的矩阵,推理速度会显著变快,显存占用也会实打实地降低。

剪枝的核心分类

A. 非结构化剪枝 (Unstructured Pruning)

  • 原理:哪里权重小删哪里。参数矩阵会变得像“马赛克”一样,到处是零散的零。
  • 缺点“看起来瘦,跑起来肉”。虽然参数少了,但 GPU 的并行计算(Tensor Core)不喜欢这种不规则的稀疏矩阵,导致实际推理速度反而变慢。

B. 结构化剪枝 (Structured Pruning)

  • 原理:整行、整列、甚至整个注意力头(Attention Head)地删。
  • 优点:删完之后模型矩阵依然规整。GPU 跑起来飞快,显存也实打实地降下来了。

C. 半结构化剪枝 (2:4 Sparsity) —— 大厂主流

  • 原理:NVIDIA 在 Ampere 架构(如 A100)后推出的黑科技。每 4 个连续参数里,必须有两个是 0。
  • 效果:这种特殊的稀疏性可以获得 2 倍的硬件加速,且精度损失极小。

梯度累积

梯度裁剪

梯度裁剪(Gradient Clipping)是一种防止梯度爆炸的技术。在反向传播中,如果梯度的范数超过某个阈值,就将梯度按比例缩小,使得其范数等于阈值。

这样可以避免梯度更新过大,导致模型参数更新不稳定,甚至发散。
在训练Transformer等深层网络时,梯度裁剪非常常用,因为深层网络容易出现梯度爆炸。

EMA

EMA通过计算模型权重的指数移动平均值,得到更加平滑的权重。在训练过程中,模型的权重会在最优值附近波动,而EMA通过平均这些权重,使得最终模型更接近最优值。

数学上,EMA的更新公式为:

θ_ema_t = β * θ_ema_{t-1} + (1 - β) * θ_t

其中θ_t是第t步的模型权重,θ_ema_t是第t步的EMA权重,β是衰减率。

从优化角度,EMA可以看作是对权重空间的历史值进行平均,从而减少权重更新的方差,使得模型更加稳定。同时,EMA相当于在训练过程中使用了多个模型(历史模型)的集成,而模型集成通常能提升泛化能力。

FGM、PGD、FreeLB

这三种都是对抗训练的方法,旨在提升模型的鲁棒性。

FGM(Fast Gradient Method):在embedding上添加扰动,扰动方向为梯度方向,大小为ε。只进行一次攻击。计算代价小,适合大规模训练。

PGD(Projected Gradient Descent):进行多次迭代攻击,每次攻击将扰动投影到ε球内。比FGM更强,但计算代价高。

FreeLB(Free Large-Batch):在训练过程中,对同一个样本进行多次前向传播,每次添加不同的扰动,然后累积梯度。相当于在一个大batch内进行对抗训练。计算代价最高,但效果通常更好。

适用场景

  • 如果计算资源有限,且对抗训练只是为了提升模型的泛化能力(而非针对对抗攻击),可以使用FGM。
  • 如果追求更好的鲁棒性,且计算资源充足,可以使用PGD或FreeLB。
  • 在NLP中,FGM和PGD通常用于embedding层,而FreeLB可以用于所有层。

Warmup

Linear Warmup(线性预热):学习率从0线性增加到初始学习率。例如,如果预热步数为1000,初始学习率为1e-4,则每一步学习率增加1e-7。

Cosine Warmup(余弦预热):学习率从0开始,按照余弦函数的形式增加到初始学习率。公式为:lr = initial_lr * (1 - cos(pi * current_step / warmup_steps)) / 2。这样,学习率的增加先快后慢。

区别:余弦预热在开始阶段增加较快,然后逐渐变慢,使得学习率在接近初始学习率时变化平缓。线性预热则以恒定速度增加。余弦预热通常能带来更好的训练稳定性,但两者在实际中差异不大,很多时候可以互换。

LLamA-Factory

LLamaFactory 的本质是一个基于 PyTorch + HuggingFace Transformers + PEFT (Parameter-Efficient Fine-Tuning) 的高度封装层。它的设计遵循以下核心原则:

它将不同的训练范式抽象为独立的“工作流”:

  • Pre-training (预训练):因果语言建模。
  • Supervised Fine-Tuning (SFT):有监督微调,最常用的指令对齐方式。
  • Reward Modeling (奖励模型):为 RLHF 准备评分模型。
  • PPO/DPO (偏好对齐):利用强化学习或直接偏好优化,让模型更符合人类价值观。

LLamaFactory 能够快速集成业界最新的优化技术,而无需用户修改底层代码:

  • 算子优化:原生支持 FlashAttention-2、Unsloth(加速 LoRA 训练)。
  • 内存优化:集成 DeepSpeed (ZeRO 2/3)、bitsandbytes (8-bit/4-bit 量化)。
  • 参数高效技术:深度集成 PEFT 库,支持 LoRA、QLoRA、DoRA、GaLore 等。

LLaMA-Factory 日志

1
2
3
4
5
6
7
8
9
10
<|im_start|>system 
你是一个专业的 ChatBI 助手。
<|im_end|>

<|im_start|>user
帮我查一下上个月的销售额。
<|im_end|>

<|im_start|>assistant
好的,正在为您查询...

LLaMA-Factory 参数

通用核心参数(无论哪种模式都要配)

这些参数决定了数据的来源、模型的位置以及基础训练策略:

  • model_name_or_path: 基础模型路径(如 Qwen/Qwen2.5-32B)。
  • dataset: 训练数据集名称(在 dataset_info.json 中注册的名字)。
  • template: 模型对应的提示词模板(如 qwenllama3),选错会导致模型学不会对话。
  • finetuning_type: 微调模式,可选 lorafull(全量)、freeze
  • output_dir: 模型权重和日志的保存路径。
  • per_device_train_batch_size: 单张显卡上的物理批次大小(如 2 或 4)。
  • gradient_accumulation_steps: 梯度累积步数(用来模拟更大的 Batch Size)。
  • learning_rate: 学习率。全量微调通常设为 $5e^{-6}$,LoRA 通常设为 $1e^{-4}$。
  • num_train_epochs: 训练轮次,一般建议 3 轮。
  • bf16 / fp16: 开启混合精度。L20 显卡务必开启 bf16=True
  • cutoff_len: 文本截断长度(如 4096 或 8192)。

LoRA 模式特有参数

finetuning_type = lora 时,需要额外配置以下参数:

  • lora_rank (r): LoRA 的秩(如 8, 16, 64)。对于 NL2SQL 等逻辑任务,建议设为 32 或 64
  • lora_alpha: 缩放系数,通常设为 lora_rank 的 2 倍
  • lora_target: 必填!指定要对哪些模块加 LoRA。
    • 设为 all(推荐):自动寻找所有线性层(q_proj, v_proj, k_proj, o_proj, gate_proj, up_proj, down_proj)。这样效果最好,但显存占用略高。
  • lora_dropout: 丢弃率,防止过拟合,通常设为 0.05 或 0.1。

QLoRA 模式特有参数

QLoRA 是在 LoRA 的基础上叠加了 4-bit 量化,用于在极低显存下训练。

  • quantization_bit: 设为 4
  • quantization_type: 设为 nf4(这是针对权重分布优化的格式,效果优于普通的 fp4)。
  • double_quant: 设为 True(开启双量化,进一步压缩显存)。
  • compute_dtype: 设为 bfloat16(量化后计算时使用的精度)。
  • 注意:QLoRA 必须配合 finetuning_type = lora 使用。

全量微调 (Full Fine-tuning) 参数

finetuning_type = full 时,显存压力巨大,必须配合分布式插件。

  • deepspeed: 必须指定 DeepSpeed 配置文件路径(如 ds_z3_config.json)。
    • 对于 32B 模型,即便是 L20 也不够全量微调,必须开启 ZeRO-3 才能跑起来。
  • flash_attn: 设为 fa2。全量微调时开启 Flash Attention 2 能显著节省显存并加速。

三种模式参数配置对比表(以 L20 微调 32B 模型为例)

参数名称 LoRA 模式 QLoRA 模式 全量微调模式
finetuning_type lora lora full
quantization_bit (None) 4 (None)
lora_rank 64 64 (None)
lora_target all all (None)
deepspeed 可选 (ZeRO-2) 不需要 必选 (ZeRO-3)
显存要求 (32B) 约 30GB - 40GB 约 20GB > 160GB (需多卡)

核心概念区分:LoRA vs. QLoRA

在 LLaMA-Factory 的界面或命令行中,这两者的设置逻辑是:

  • LoRA:模型以 BF16/FP16 全精度加载,显存占用较高(32B 模型约需 70GB+ 显存才能启动训练)。
  • QLoRA:模型以 4-bit 量化加载,通过 bitsandbytes 技术极大压缩显存(32B 模型仅需约 20GB 显存即可启动)。

详细参数设置手册

  1. 基础模型设置 (Model Arguments)
    • Model Name/Path: 选 Qwen2.5-32B-Instruct
    • Finetuning Method: 选 lora
    • Quantization Bit:
      • LoRA: 选 None (或者不选)。
      • QLoRA: 选 4。这是开启 QLoRA 的开关。
  2. LoRA 核心参数 (Adapter Settings)
    • LoRA Rank (r):
      • 推荐:1632
      • 说明:数值越大,可训练参数越多,表达能力越强,但显存占用也随之增加。
    • LoRA Alpha ($\alpha$):
      • 推荐:3264
      • 说明:通常设置为 $2 \times r$,用于缩放学习率。
    • LoRA Dropout:
      • 推荐:0.050.1
      • 说明:防止过拟合,若数据集很小,建议保持 0.05。
    • LoRA Target Modules:
      • 推荐:填写 all
      • 说明:在 QLoRA 论文中证明,覆盖所有线性层(q, k, v, o, gate, up, down)能达到接近全量微调的效果。
  3. 训练超参数 (Training Arguments)
    • Learning Rate:
      • LoRA: 推荐 1e-4
      • QLoRA: 推荐 2e-4(量化后学习率可以稍微大胆一点)。
    • Compute Type:
      • 推荐:bf16 (如果使用 L20 显卡,务必选 bf16,性能和稳定性最优)。
    • Gradient Checkpointing:
      • 推荐:开启 (True)
      • 说明:极大地节省显存,代价是训练速度慢约 20%。

训练框架

框架名称 核心武器 (Best for) 底层依赖 核心优势 缺点
LLaMA Factory 通用微调 (SFT) DeepSpeed / FSDP 一站式、WebUI、适配 500+ 模型 架构较重,深度定制困难
Easy R1 推理强化 (GRPO) veRL / DeepSpeed 极致省显存、专为逻辑推理(R1)优化 功能相对单一,专注 RLVR
OpenRLHF 分布式 RL (PPO) Ray / DeepSpeed 支持 70B+ 模型全量训练、极致并行 部署门槛高,需要 Ray 集群知识
SWIFT 国产模型 (Qwen/Yi) DeepSpeed / PEFT 阿里生态适配最快、集成了大量量化插件 某些非国产模型适配优先级略低
Axolotl 极客定制 (YAML) Transformers / PEFT 配置极度灵活、支持各种前沿算法组合 无 UI、YAML 配置上手有门槛
Alignment Handbook 标准化 (DPO) Transformers / TRL 代码最干净、教学级、HF 官方血统 偏学术,大规模工业优化略少
  • 普通微调 (SFT) 选 LLaMA Factory:它是最强全能王,上手即用,验证数据质量的第一首选。

  • 逻辑推理强化 (GRPO) 选 Easy R1:如果你想复刻 DeepSeek-R1 的“思考”能力,它是目前显存优化最好的特种设备。

  • 分布式强化学习 (PPO) 选 OpenRLHF:它是分布式大航海时代的重型航母,专对付 70B 以上的多机训练。

  • 极致标准化 (DPO) 选 Alignment Handbook:它是教科书级的存在,适合需要严格遵循 Hugging Face 标准的生产链路。

  • 国产模型 (Qwen/Yi) 选 SWIFT:阿里系模型的“亲妈”,新模型出炉即适配,插件库异常丰富。

  • 极客定制化 (Expert Mode) 选 Axolotl:发烧友的“乐高”,适合那些需要精细调控每一项微小参数的极客场景。

微调轮次

  1. 数据量的规模(核心指标)

    • 大数据集(>5万条):通常只需要 1-2 个 Epoch。因为数据量够大,模型在看第一遍的过程中已经见过足够多的变体,足以收敛。
    • 小数据集(<5000条):通常需要 3-5 个 Epoch。因为样本少,模型需要多看几遍才能形成深刻记忆。
  2. 学习率 (Learning Rate) 的配合

    • 如果你设置的学习率很小(如 $5e^{-6}$),模型步子迈得小,可能需要更多轮次。
    • 通常采用 Cosine Learning Rate Scheduler,在多轮训练中后期逐渐减小学习率,帮助模型在最后一轮精准落位。
  3. 任务的复杂度

    • 风格对齐(比如让模型说话更客气):1 Epoch 往往就够了。
    • 逻辑重塑(比如你的 NL2SQL):通常需要 3-5 Epoch,因为模型需要纠正原本错误的 SQL 生成逻辑。

验证集 (Validation)

在 2026 年,专业的炼丹师不会预设一个死板的轮次,而是使用 “早停法 (Early Stopping)”

  1. 监控验证集损失 (Val Loss):每隔一定步数(如 100 Steps),在不参与训练的验证集上测一次。
  2. 观察拐点
    • 训练初期:训练集和验证集的 Loss 都在下降(继续练)。
    • 平衡点:验证集 Loss 降到最低点(这是最完美的轮次)。
    • 过拟合期:训练集 Loss 还在降,但验证集 Loss 开始回升(立刻停止,取之前那个最好的点)。

“多轮”不代表“无限轮”。 如果轮次过多(比如 20 轮),模型会产生**“灾难性遗忘”**:它会把 SQL 记得滚瓜烂熟,但你再问它“今天天气怎么样”,它可能也只会回你一段 SELECT weather FROM world

自动提示词优化

自动提示词优化(Automatic Prompt Optimization, APO)或 基于评估反馈的 Prompt 迭代闭环

  • DSPy 思想:面试官说的这一套逻辑几乎就是斯坦福开源项目 DSPy 的核心原理——不再手动调 Prompt,而是通过编译器自动优化提示词。
  • LLM-as-a-Judge:用一个大模型去评估另一个模型。
  • Prompt Flywheel(提示词飞轮):通过自动化的评估和迭代,让 Prompt 性能自我进化。

提示词构成

一个专业、稳定的 Prompt 通常由以下 4 个部分组成。你可以用“角色-任务-上下文-约束”来概括:

  • 角色 (Role/Persona):给 AI 设定一个身份。
    • :“你是一位拥有 20 年经验的资深架构师。”
  • 指令/任务 (Instruction/Task):明确要求 AI 做什么,使用动词开头。
    • :“请重构以下 Python 代码以优化其执行效率。”
  • 上下文/示例 (Context/Few-shot):提供背景背景信息或输入输出样例。
    • :“这是目前的数据库架构图描述……”以及“这是优化前的例子 -> 优化后的例子。”
  • 约束/输出格式 (Constraints/Output Format):限制边界和规定返回形式。
    • :“不要使用任何第三方库”、“必须以 JSON 格式输出”。

模型推理

模型推理三大参数:控制“创造力”与“稳定性”
在大模型(LLM)生成 Token 时,它本质上是在给词库里的所有词打分(概率分布)。这三个参数就是用来从这个分布里“选词”的。

  1. Temperature
  2. Top-K —— “前 K 名选拔”
  3. Top-P (核采样, Nucleus Sampling) —— “动态百分比选拔”

预训练与后训练

维度 预训练 (Pre-training) 后训练 (Post-training)
数据量 极巨量 (万亿级 Tokens) 较少量 (万级到百万级精选数据)
数据质量 杂乱、广泛 (Raw Web Data) 极高质量、人工标注或合成数据
计算成本 极高 (数千张 GPU 跑数月) 相对较低 (数张/数十张 GPU 跑数天)
学习目标 学会“预测下一个字” 学会“遵循指令”与“解决问题”
模型形态 Base Model (如 Llama-3-Base) Instruct/Chat Model (如 Llama-3-Instruct)
决定因素 决定了模型的“智力上限”和“知识深度” 决定了模型的“易用性”、“安全性”和“逻辑推理能力”

OOM 的原因

  1. 模型权重 (Model Weights)
    • 这是最固定的部分。例如一个 7B 模型(16位浮点数 FP16),光存放权重就需要 $7 \times 2 = 14$ GB
  2. 优化器状态 (Optimizer States)
    • 这是显存杀手! 如果使用标准的 AdamW 优化器,它需要为每个参数存储“动量(Momentum)”和“方差(Variance)”。
    • 通常,优化器占用的显存是模型权重的 2 到 3 倍
  3. 梯度 (Gradients)
    • 存储每个参数的梯度值,大小通常与模型权重一致。
  4. 激活值 (Activations)
    • 这是最动态的部分。在前向传播过程中,每一层的计算结果都要存下来,以便在反向传播时计算梯度。
    • 重点:激活值的大小与 Batch Size序列长度(Sequence Length) 成正比。

强化学习

策略梯度法

所有的 DPO、PPO 最终目的都是为了优化策略 $\pi$。

  • 逻辑:如果一个动作获得了高奖励,就通过梯度上升增加该动作出现的概率;反之则降低
  • 痛点:方差极大。模型一旦随机试到了一个“高分但离谱”的答案,整个策略可能被带偏(训练不稳定)

REINFORCE(蒙特卡洛策略梯度)

“REINFORCE 最大的问题是信用分配(Credit Assignment)。如果小明虽然睡觉了(坏动作),但因为他底子好考了高分(正奖励),算法会错误地认为睡觉也有功劳。这导致了高方差(High Variance),模型很难收敛。”

  • 全回合观察(Monte Carlo):REINFORCE 很有耐性,它必须等模型把整句话说完了(Episode 结束),拿到了最终的总分 $G_t$,才回头去更新参数。REINFORCE 使用完整轨迹的回报来更新策略,每个动作的更新权重相同(都是轨迹总回报)。

  • 公式直觉:$$\nabla \theta \approx \sum R \cdot \nabla \log \pi(a|s)$$

    大白话: 如果这一局赢了($R$ 是正的),我就增加这一局里所有动作出现的概率;如果输了,就全体减小。

带基线的策略梯度

引入了 Baseline(基准)

面试话术:“为了降低方差,我们引入了 Baseline。现在我们不看绝对分数,而是看**‘相对优势’**。如果全班平均考 90,小明考 80,即使 80 是高分,对模型来说也是‘惩罚’。这让训练变得更加稳定。”

贝尔曼方程

贝尔曼方程的核心思想是:递归

“当前的价值 = 现在的奖励 + 未来能拿到的总奖励(打个折)”

用数学公式表示(初级版):

$$V(s) = R(s, a) + \gamma V(s’)$$

  • $V(s)$:当前状态的“身价”(价值)
  • $R(s, a)$:你刚做的这个动作给的即时甜头(奖励)
  • $\gamma$(Gamma):折扣因子,表示你有多看重未来(1 表示长远打算,0 表示只顾眼前)
  • $V(s’)$:你做完动作后,跳到的下一个状态的“身价”

Actor-Critic (AC)

AC 架构(以 PPO 为例)画成这样一个关系图:

  1. Actor (策略模型):负责生成 Token。
  2. Critic (价值模型):负责预估当前的 $V(s)$。这个是动态训练的,它才使用贝尔曼方程
    1. Critic 引入了 时序差分 (TD Learning),不需要等到 episode 结束(考完试)才更新,每走一步(每生成一个 token)就可以根据贝尔曼方程更新价值。这解决了 REINFORCE 必须等结局的延迟问题。
  3. Reference Model (参考模型):负责计算 KL 散度,防止 Actor 跑偏。
  4. Reward Model (奖励模型):负责给生成结果打分。通常是静态的。
  5. Advantage Function (优势计算):计算“实际分 + KL 惩罚”与“Critic 预估分”的差值,用来更新 Actor。

近端策略优化

  • $r_t(\theta)$:新旧策略的比例(新动作概率 / 旧动作概率)。
  • $\epsilon$:一个很小的常数(通常是 0.1 或 0.2)。
  • 逻辑:如果新策略跑得太远(比例超过 $1 \pm \epsilon$),公式就会触发 Clip(裁剪),强行把更新幅度拉回来。
  • 面试话术:“PPO 通过这个裁剪机制,确保了训练的单调稳定性。它就像是给模型的学习过程装了一个限速器,防止它在优化的过程中‘用力过猛’掉进无底深渊。”

“我认为强化学习在 LLM 对齐中的演进,本质上是一个‘不断降低方差、提升信用分配精度’的过程:

  1. 起初是 REINFORCE:它最直观,但它是‘全回合’更新。就像一个学生考完试才知道哪做对了,它无法区分一连串动作中哪个是关键,导致训练方差极大。

  2. 随后引入了 Baseline:这是关键的一步。通过引入基准,我们让模型学会了‘相对学习’。我们优化的不再是奖励总和,而是优势(Advantage),这有效地过滤了环境噪声,稳定了梯度。

  3. 真正的质变是 Actor-Critic (AC):这里我们请回了贝尔曼方程。借助 Critic 对未来价值的递归建模(Bootstrapping),我们实现了单步更新。这意味着模型不需要等对话结束,就能通过‘时序差分’学习到每一个 Token 对最终奖励的贡献。

  4. 最后到 PPO 和 GRPO:PPO 是通过裁剪(Clipping)防止更新步子太大;而 DeepSeek 提出的 GRPO 则是更进一步,它巧妙地去掉了显存负担沉重的 Critic,改用‘组内相对分’作为动态 Baseline,在逻辑上回归了策略梯度的简洁,但在工程上解决了显存瓶颈。”

PPO

核心身份:标准的 Actor-Critic (AC) 架构,在线 (Online) 学习的巅峰。

  • 成员:TRPO(祖先)、PPO (核心)、PPO-Max(极致优化版)。
  • 核心原理
    • 近端裁剪 (Clipping):通过限制新旧策略的比率 $r_t(\theta)$ 在 $[1-\epsilon, 1+\epsilon]$ 之间,确保模型更新平滑,不会“跑飞”。
    • 四模型联动:Actor(干活)、Critic(看未来/贝尔曼方程)、Reward(判官)、Reference(防走丢)。
  • 面试吹点
    • “上限最高”:因为是在线探索,模型能通过试错发现训练集里没有的知识。
    • “数学闭环”:完整利用了策略梯度贝尔曼方程
  • 致命弱点
    • 显存吞噬者:同时跑 4 个模型,显存开销极大。
    • 超参地狱:对学习率、KL 系数、裁剪阈值极其敏感,极难调优。

DPO

核心身份Policy-Only 架构,将 RL 转化为分类问题。

  • 成员DPO (标配)IPO(解决过拟合)、KTO(无需成对数据)、SimPO(去掉参考模型)。
  • 核心原理
    • 数学映射:利用数学推导,证明了“最优策略”和“奖励函数”之间存在对数线性关系。
    • 直接对齐:通过一个简单的二分类损失函数,让模型直接在“好回答”和“坏回答”之间做选择。
  • 家族进化(必背点)
    • KTO:基于前景理论,只要告诉模型“这个好”或“这个坏”,不需要对比 A 和 B。
    • SimPO2024-2025 热门。它干掉了 Reference Model,直接在 Logits 上加了一个 Margin(边距),解决了 DPO 容易产生冗余废话的问题,且更省显存。
  • 面试吹点
    • “工程之王”:不需要奖励模型,不需要 Critic,训练像 SFT(微调)一样简单稳定。

KTO

核心身份:基于前景理论 (Prospect Theory) 的单点对齐架构,非对称奖励的最佳实践者。

  • 成员:KTO (核心)、HALO (与之思路相似的家族成员)。
  • 核心原理
    • 人类心理模拟:打破了 DPO 认为“好坏对等”的假设,引入诺贝尔奖得主卡尼曼的前景理论,认为人类对“损失”的敏感度远高于对“收益”的渴望。
    • 效用函数 (Utility Function):通过一个凹凸性不同的效用函数,对“满意 (Desirable)”和“不满意 (Undesirable)”进行非对称加权
    • 单点标签 (Binary Label):不需要 DPO 那种成对的 (A>B) 数据,只需要告诉模型这个回答是 True 还是 False
  • 面试吹点
    • “数据降本之神”:在工业界,收集‘成对数据’极其昂贵。KTO 允许直接利用线上点赞/点踩、甚至是只有单点的‘错题集’进行训练,数据利用率极高。
    • “损失厌恶控制”:它是目前唯一能从数学底层解释并实现“宁可漏掉,不可错报”的算法,非常适合实体匹配、金融风控、医疗诊断等高风险容错场景。
    • “训练极其稳健”:因为它不依赖 Pair 之间的相对概率,所以不像 DPO 那样容易因为 Rejected 样本质量太差而导致模型崩溃或过拟合。
  • 致命弱点
    • KL 散度敏感:如果基座模型本身很烂,KTO 很难通过单点反馈把它带回到正确路径上(相比之下 DPO 有对比引导,起步更容易)。
    • 需要精细调参:非对称因子($\lambda_D$ 和 $\lambda_U$)需要根据业务对错误的容忍度进行反复对齐。

GRPO

核心身份Group-Relative (组内相对) 策略优化,DeepSeek 的成名技。

  • 核心原理
    • 去 Critic 化:它认为 Critic 预估的 $V(s)$ 太占显存且不准。它让模型对同一个 Prompt 吐出 一组(如 64 个) 答案。
    • 相对分计算:直接算这一组答案的平均分和标准差。比平均分高的就是“优势(Advantage)”。
  • 面试吹点
    • “显存奇迹”:在保持 PPO 在线探索能力的平衡下,省去了 Critic 模型庞大的显存开销。
    • “自我进化”:特别适合 DeepSeek-R1 这种推理模型。通过“规则奖励”(比如代码跑通了给 1 分,没跑通给 0 分),模型能自发学会思维链(CoT)和自我纠错。
特性 DPO KTO SimPO
数据要求 必须成对 (Pairwise) 单条正/负样本即可 必须成对 (Pairwise)
参考模型 需要 (多占显存) 需要 不需要 (最省显存)
主要目标 概率分布对齐 效用最大化 (心理学) 奖励差距最大化 (工程向)
解决的问题 强化学习太复杂 标注数据难找 废话多、显存贵

DPO 与 SFT

为什么不能用 DPO 替代 SFT?
什么情况下 DPO 效果会高于 SFT?

“在实际工程中,我们坚持 SFT 是底座,DPO 是升华

从优化目标看,SFT 解决的是‘从无到有’的生成能力,而 DPO 解决的是‘从有到优’的对齐能力。如果没有 SFT 建立的分布基准,DPO 的 KL 散度约束会失效,导致模型输出失去语义。

从数据效率看,SFT 对指令遵循的构建最直接。但在 ChatBI 的鲁棒性优化上,DPO 效果远超 SFT。比如在处理‘歧义查询’时,我们通过 DPO 让模型学会‘澄清意图’(Chosen)而不是‘盲目猜测’(Rejected),这种细粒度的行为对齐,DPO 只需少量数据就能达到 SFT 难以企及的效果。”

奖励函数

稀疏 vs 稠密

  • 稀疏奖励 (Sparse Rewards):只有在任务彻底完成(如:SQL 执行结果完全正确)时才给分。
    • 优点:模型最终目标明确,不容易学坏。
    • 缺点:收敛极慢(模型可能试了几万次都拿不到分)。
  • 稠密奖励 (Dense Rewards/Reward Shaping):在过程中给分(如:SQL 语法正确 +1,关联了正确的表 +2)。
    • 风险:容易引发奖励黑客 (Reward Hacking)。例如,模型可能学会写一段虽然语法正确但逻辑毫无意义的长 SQL 来骗取加分。

主流设计模式:分层奖励
在复杂的 Multi-Agent 场景下,建议将奖励拆解为三个层级:

A. 结果奖励 (Outcome-based) —— “做对了没”
直接衡量最终产出。在 NL2SQL 中,这通常是:

  • 执行准确性 (EX):将生成的 SQL 运行结果与标准结果对比。匹配则奖励 $+1$。
  • 逻辑等价性:利用另一个强模型(如 GPT-5)判断生成的逻辑是否符合需求。

B. 过程奖励 (Process-based / PRM) —— “想对了没”
这是 o1/R1 架构的核心。不再只看结果,而是奖励模型的思维链 (CoT)

  • 推理步奖励:如果模型在思考过程中正确地识别了字段歧义,或者正确地进行了 JOIN 推理,给予每一步的小额奖励。
  • 工具调用奖励:在 Agent 架构中,如果 Agent 正确地调用了 Metadata 查询工具而非凭空猜表名,给予正向反馈。

C. 约束奖励 (Constraint-based) —— “规矩了没”

用于防止危险行为或不合规。

  • 性能惩罚:如果 SQL 包含笛卡尔积(无条件 Join)或全表扫描,给予负奖励 $-0.5$。
  • 安全性惩罚:如果生成的 SQL 包含敏感操作(如 DELETE),直接扣除巨额分数 $-10$。

多模态

ViT

(Vision Transformer)

  • 本质:证明了 Transformer 也可以处理视觉

  • 核心逻辑

    1. 切片(Patching):把图片切成 $16 \times 16$ 的小方块,每个方块看作一个“单词(Token)”。
    2. 线性投影:把像素方块变向量。
    3. 全局注意力:利用 Transformer 的 Self-Attention,让每个像素块都能同时看到全图。
  • 解决了什么

    • 架构统一:让视觉和文本使用完全一样的数学结构(Transformer),为原生多模态扫清障碍。
    • 打破瓶颈:CNN 在大数据下会遇到瓶颈,而 ViT 符合 Scaling Law(数据越多、算力越强,性能越恐怖)。
  • 面试话术

    “ViT 的出现标志着视觉领域**归纳偏置(Inductive Bias)**的隐退。它不再假设像素之间有局部关系,而是通过海量数据让模型自发学习全局特征。这使得视觉模型能直接作为 LLM 的插件,因为大家现在都说同一种‘语言’(向量序列)。”

CLIP

(Contrastive Language-Image Pre-training)

  • 本质:通过对比学习(Contrastive Learning),实现了图像和文字的语义对齐

  • 核心逻辑

    1. 双塔架构:一个 Image Encoder(通常就是 ViT)和一个 Text Encoder。
    2. 连连看训练:给模型数亿对“图片+文字描述”。训练目标是:让对应的图文向量在空间里越靠越近,不对应的越跑越远。
  • 解决了什么

    • 零样本能力(Zero-shot):CLIP 学到了概念。你给它一张从没见过的“宇航员骑马”,它能根据文字理解这张图。
    • 跨模态桥梁:它是 DALL-E、Stable Diffusion 的“导航仪”,也是 LLaVA 等多模态模型的“眼睛”。
  • 面试话术

    “如果说 ViT 给了 AI 一双‘眼睛’,那么 CLIP 就给了 AI 一个‘大脑字典’。它将视觉向量映射到了语言空间,让我们能用文字去检索、去操纵、去理解图像。”

扩散模型

(Diffusion Model)

  • 本质:一种通过迭代去噪生成图像的生成式模型。

  • 核心逻辑

    1. 前向过程(加噪):把一张好图慢慢变成一堆随机雪花(噪声)。
    2. 反向过程(去噪):训练模型(通常是 U-Net 或现在的 DiT)从雪花里一点点把图“猜”回来。
  • 解决了什么

    • 生成质量:比以前的 GAN(生成对抗网络)更稳、画质更高。
    • 多样性:能根据不同的随机噪声生成千变万化的结果。
  • 面试话术

    “扩散模型将生成问题转化为了去噪问题。目前的趋势是 DiT (Diffusion Transformer),即用 Transformer 替换 U-Net 作为去噪主干。这意味着生成模型也开始吃 Scaling Law,Sora 的成功本质上就是 DiT 架构规模化的胜利。”

特性 GAN (生成对抗网络) Diffusion (扩散模型)
核心思想 二人博弈,对抗学习。 迭代去噪,还原真相。
训练难度 极高(平衡难找,容易崩)。 相对稳定(目标函数是确定的)。
生成速度 (一次成像)。 (需要迭代几十次去噪)。
生成质量 容易模糊或细节丢失。 极佳(纹理和光影更真实)。
代表模型 StyleGAN (著名的“不存在的人”)。 Stable Diffusion, Sora, Midjourney。

检索评估

TF-IDF

TF (Term Frequency, 词频) —— 统计的是“局部”信息

  • 用到的统计量:
    1. 某个词在当前文档中出现的次数
    2. 当前文档的总词数
  • 意思: 这个词在这一篇文章里出现的频率高不高?

IDF (Inverse Document Frequency, 逆文档频率) —— 统计的是“全局”信息

  • 用到的统计量:
    1. 语料库(数据库)中的文档总数
    2. 包含这个词的文档数量
  • 意思: 这个词在整个知识库里是不是很稀有?

IDF 到底是怎么算的?(公式拆解)

面试官问“IDF 怎么算”,其实是想看你记不记得那个 Log(对数)

$$IDF(t) = \log \frac{N}{DF + 1}$$

  • $N$:文档总数(比如你的古籍库里总共有 10,000 篇文档)。
  • $DF$:包含该词的文档数(比如“三省六部”这个词在 100 篇文档里出现过)。
  • $+1$平滑处理。防止分母为 0(万一这个词在库里一个都没有,不加 1 就会出错)。
  • 为什么用 $\log$?:为了防止数值爆炸,把巨大的差异拉回到一个合理的范围内。

BM25

BM25 的全称是 Best Matching 25。它的得分由以下三部分相乘/相加:

① IDF (逆文档频率) —— 和 TF-IDF 基本一样

  • 逻辑:如果一个词在所有文档中都很罕见(如“三省六部”),那它就很重要;如果随处可见(如“的”、“了”),那它就不值钱。

② TF (词频) 的“饱和度”控制 —— 核心区别 1

  • TF-IDF 的问题:一个词出现的次数越多,得分就线性增长。如果一个词出现 100 次,得分就是出现 1 次的 100 倍。
  • BM25 的改进:引入了一个参数 $k_1$。随着词频增加,得分会迅速上升,但很快就会达到一个天花板(饱和点)
  • 大白话:在一篇 500 字的文章里,“唐朝”出现 10 次和出现 100 次,对相关性的贡献其实差不多了,BM25 限制了这种无限制的加分。

③ 文档长度归一化 —— 核心区别 2

  • TF-IDF 的问题:长文章天生占便宜,因为长文章里的词多,TF 容易高。
  • BM25 的改进:引入了参数 $b$。它会惩罚那些由于“废话多”而导致关键词多的长文章,奖励那些“短小精悍”且命中关键词的文章。

ROC

  • 真正例率(TPR):实际为正例,被预测为正例的比例,即召回率。
  • 假正例率(FPR):实际为负例,被预测为正例的比例。
  • 阈值(Threshold):根据阈值将概率转换为类别标签。

ROC 曲线(Receiver Operating Characteristic Curve,受试者工作特征)是评估二分类模 型性能的工具,以假正例率(FPR)为横轴,以真正例率(TPR)为纵轴,展示不同阈值下 模型的表现。绘制 ROC 曲线时,从高到低调整阈值,计算每个阈值的 TPR 和 FPR 并绘制 所有阈值的点,形成 ROC 曲线。

AUC

(Area Under Curve) —— 排序的“整体准确度”
AUC 值代表 ROC 曲线下的面积,用于量化模型性能。AUC 值越大,模型区分正负类 的能力越强,模型性能越好。AUC 值=0.5 表示模型接近随机猜测,AUC 值=1 代表完美模 型。

含义:
AUC 指的是 ROC 曲线下的面积。但在实际面试中,最专业的解释是:随机抽取一个正样本和一个负样本,模型给正样本打分高于负样本打分的概率。

  • 特点:
    • 它只关心相对顺序。只要模型给所有正样本的打分都比负样本高,AUC 就是 1.0,即使分值分别是 0.51 和 0.49。
    • 位置不敏感:它不关心正样本排在第 1 名还是第 10 名,只要在负样本前面就行。
  • 应用场景:
    • 传统的 CTR(点击率)预估。
    • 衡量模型区分“点”与“不点”的基础能力。

NDCG

(Normalized Discounted Cumulative Gain) —— 排序的“位置收益”

含义:

归一化折损累计收益。它比 AUC 更精细,专门用来衡量搜索结果的排序质量

  • 核心逻辑(拆解):

    1. Gain (收益):每个结果都有个分值(比如:相关=3, 模糊=1, 不相关=0)。
    2. Cumulative Gain (CG):把前 K 个结果的分值加起来。
    3. Discounted (折损)这是关键! 排名越靠后,分值要除以一个以位置为底的对数 $\log(\text{rank}+1)$。这意味着:好结果排在后面,贡献的分数会大幅衰减。
    4. Normalized (归一化):用你的得分除以“理想状态下的最高分 (IDCG)”,得到 0 到 1 之间的值。
  • 特点:

    • 位置极其敏感:在 RAG 里,如果最正确的答案排在第 1 名,NDCG 会很高;如果排在第 5 名,NDCG 会掉得很厉害。
  • 应用场景:

    • RAG 检索质量评估、搜索系统、精排模型优化。

LangGraph

State

LangGraph 官方推荐三种定义方式,对应的“继承”关系如下:

  • TypedDict (最常用)
    • 继承自typing.TypedDict
    • 特点:轻量级,运行快。但在 Python 运行时不强制校验类型(仅做静态检查)。
  • Pydantic BaseModel (推荐用于生产)
    • 继承自pydantic.BaseModel
    • 特点强类型校验。如果某个节点返回了错误的数据类型,程序会立刻报错。非常适合复杂项目。
  • dataclasses
    • 装饰器@dataclass
    • 特点:Python 原生支持,适合不需要强校验的简单对象。

State共享但互不影响

方案一:基于“增量更新”的节点包装(最推荐,最优雅)

这是利用 Python 函数作用域和 LangGraph 合并机制的方案。

  • 实现逻辑
    1. 只读获取:在 Node 函数中通过 state["key"] 获取所需变量。这在 Python 中相当于获取了一个局部副本(快照)。
    2. 局部处理:在函数内部执行逻辑,产生的中间变量(如 temp_data)仅存在于函数生命周期内。
    3. 定向写回:通过 return {"specific_key": result} 仅更新该 Agent 负责的字段。
1
2
3
4
5
6
7
8
def researcher_node(state: GlobalState):
# 【读】:获取全局查询,但无法在函数外修改它
query = state["raw_query"]
# 【做】:产生的 search_logs 属于局部变量,不进入 GlobalState
search_logs = my_search_tool(query)
# 【写】:定向更新,不干扰其他 Agent 的字段
return {"research_results": "根据日志总结出的核心结论"}

方案二:父子图隔离(Sub-graphs)

这是物理级别的隔离,适用于逻辑极其复杂的子任务(如你研究的实体匹配)。

  • 实现逻辑:将子 Agent 封装为一个独立的 StateGraph,它拥有自己独立的 LocalState
  • 交互方式
    • 输入映射:父图通过调用参数将必要信息传给子图。
    • 输出映射:子图运行结束后,只向父图返回一个最终的 Output 字典。
  • 优点:子图内部成百上千轮的对话和日志对父图完全不可见,彻底避免上下文污染。

方案三:命名空间(Key-spacing)隔离

在同一个 TypedDict 中人为划分领地。

  • 实现逻辑
    • 定义 agent_a_private: dictagent_b_private: dict 字段。
    • Agent A 只准写 agent_a_private,Agent B 同理。
  • 优点:实现简单,不涉及多图嵌套。
  • 缺点:State 对象会随着 Agent 增多变得臃肿,Token 消耗会增加。

Message

如何“自动”添加?

当你的节点(Node)返回一个字典时,LangGraph 会查看返回值里的 Key。

  • 如果返回 { "messages": [new_msg] }: 因为你定义了 add_messages,LangGraph 不会覆盖 原有的消息列表,而是 自动将 new_msg 附加(Append) 到原列表末尾。
  • 如果返回 { "messages": [existing_msg_with_id] }: 如果返回的消息 ID 与库里已有的 ID 相同,add_messages 会自动执行 更新(Update) 操作。

Python

Pytorch 与 TensorFlow

核心哲学:动态 vs. 静态(界限已模糊)

  • PyTorch (Eager First)
    • 原理:天生就是“动态图”,像写普通 Python 代码一样,运行到哪一行就计算到哪一行
    • 2026 现状:通过 torch.compile(PyTorch 2.x+),它现在也能在保持开发灵活性的同时,自动生成极其高效的静态执行图,性能直逼甚至超过原生 TensorFlow
  • TensorFlow (Graph First)
    • 原理:天生倾向“静态图”,先构建整个计算流水线,再统一优化执行。
    • 2026 现状:虽然也有 Eager 模式,但其核心优势依然在于 TFX(TensorFlow Extended)这种严谨的工业流水线

GIL(全局解释器锁)

这是 Python(特指 CPython 解释器)的“原罪”。

  • 定义:GIL 是一把互斥锁,保证同一时刻只有一个线程在 CPU 上执行 Python 字节码
  • 后果:即使你的 L20 集群有几十个 CPU 核心,如果你只开一个 Python 进程,无论你开了多少个线程(Threading),它们都会在这一把锁上“串行”执行。
  • 结论:这导致 Python 无法利用多核 CPU 的并行计算能力

常用库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# ==================== 基础核心库 ====================
import os
import json
import random
import numpy as np
import pandas as pd
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from datetime import datetime

# 深度学习框架
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader, random_split
from torch.cuda.amp import autocast, GradScaler # 混合精度训练

# 分布式训练
from accelerate import Accelerator, DistributedDataParallelKwargs
from accelerate.utils import set_seed, broadcast_object_list

# HuggingFace 生态系统
from datasets import load_dataset, DatasetDict, concatenate_datasets
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
AutoConfig,
PreTrainedModel,
PreTrainedTokenizer,
TrainingArguments,
Trainer,
TrainerCallback,
TrainerState,
TrainerControl,
BitsAndBytesConfig, # 4/8-bit量化
pipeline # 推理管道
)

# 参数高效微调
from peft import (
LoraConfig,
TaskType,
get_peft_model,
get_peft_model_state_dict,
prepare_model_for_kbit_training,
PeftModel,
PeftConfig
)

# 强化学习与对齐训练
from trl import (
DPOTrainer,
DPOConfig,
SFTTrainer,
DPODataset, # 如果使用自定义格式
DPODataCollatorWithPadding,
ModelConfig, # 用于DPO的多模型配置
DPODataCollator
)

# 评估与指标
import evaluate
from evaluate import evaluator
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score


# 推理优化与部署
import onnxruntime as ort # ONNX运行时
from optimum.onnxruntime import ORTModelForCausalLM # HuggingFace ONNX优化
import vllm # 高性能推理
from vllm import LLM, SamplingParams # vLLM引擎
import fastapi # API部署
import uvicorn
from pydantic import BaseModel

# 数据处理与增强
import nltk
from nltk.tokenize import sent_tokenize
from nltk.corpus import stopwords
import re
from bs4 import BeautifulSoup # HTML清洗
import emoji
from langdetect import detect # 语言检测

# 可视化
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 进度显示
from tqdm.auto import tqdm
import logging

拷贝

浅拷贝 (copy.copy())

  • 原理:创建一个新对象,但新对象内部的元素只是对原对象子元素的引用
  • 内存表现:父对象地址变了,但子对象(如列表里的列表)地址没变。
  • 风险:如果你修改了拷贝后对象里的“可变子元素”(比如 list),原对象也会跟着变。

深拷贝 (copy.deepcopy())

  • 原理:递归地拷贝对象中的每一层。它会创建一个完全独立的新对象,包括所有子元素。
  • 内存表现:父对象和所有子对象的地址全部是新的。
  • 注意点:深拷贝会处理循环引用(自己引用自己)的情况,防止进入无限死循环。

Python 垃圾回收机制

引用计数 (Reference Counting) —— 第一道防线

  • 核心:每个对象头里都有一个 ob_refcnt
    • 被引用(赋值、作为参数传递)时,计数 +1
    • 引用失效(变量被删除、离开作用域)时,计数 -1
  • 优点实时性高。计数一归零,内存立刻释放。
  • 致命缺陷:无法处理循环引用(A 引用 B,B 引用 A,两者的计数永远不会归零)。

标记-清除 (Mark and Sweep) —— 破除死锁

  • 原理:为了解决循环引用。Python 会维护两个列表:root(根对象)和所有对象。它从根对象出发,像走迷宫一样遍历所有路径。
  • 结果:能走到的对象被“标记”为存活,走不到的(即便它们互相引用)就是垃圾,直接清除。

分代回收 (Generational Collection) —— 效率加速

  • 原理:基于“弱代假说”——存活时间越久的对象,越不容易变成垃圾。
  • 机制
    • Python 将内存分为 0 代、1 代、2 代
    • 新生成的对象在 0 代。当 0 代满了,触发 GC。
    • 没被清理掉的幸运儿会“晋升”到 1 代。
    • 2 代触发频率最低,从而减少了全量扫描内存的次数,保护了性能。

开源项目

RAGFlow

  • 技术细节:RAGFlow 核心内置了 DeepDoc 模块。它不是简单地调用 OCR,而是通过计算机视觉(CV)模型先对文档进行“版面分析”(Layout Analysis)。

  • 你可以吹“我调研过 RAGFlow,它最令我印象深刻的是其基于视觉的图文结构化能力。它会像人类一样先‘看’一眼页面,识别出哪里是页眉、哪里是跨页表格、哪里是插图说明。这种基于 Vision 的解析逻辑,比单纯解析 PDF 字符流要稳健得多,尤其是在处理我们业务中那些排版极其复杂的出海营销手册时。”

长短期记忆

Mem0 (原 Embedchain) —— 智能体“自传”式记忆

Mem0 是目前最火的、专门为 LLM 设计的长期记忆层。它不仅仅是存储,而是会自适应地更新对用户的认知。

  • 特点:它会像人类一样,将新信息与旧信息合并。比如:第一天你说“我喜欢 Python”,第二天你说“我现在更爱 Rust”,它会自动更新你的偏好,而不是存两条冲突记录。
  • 优点
    • 实体级记忆:非常适合你的“实体匹配”场景,能记住实体的属性演变。
    • 多层级:支持用户级、会话级、甚至是组织级的记忆隔离。
  • 缺点
    • 计算开销:每次写入都会触发一次 LLM 的“记忆提取”动作,增加 Token 消耗。
  • 适用:DTC 场景下的个性化导购 Agent、长期伴侣型 AI。

Zep —— 毫秒级延迟的生产级记忆

如果你的 L20 集群TTFT(首字延迟) 要求极高,Zep 是首选。

  • 特点:它是一个独立的内存存储服务,拥有非常强大的自动总结(Auto-Summarization) 能力。
  • 优点
    • 极速检索:支持向量 + 关键词双路搜索,毫秒级响应。
    • 低损耗:它会自动将历史长对话压缩成摘要,只给模型看精华。
  • 缺点
    • 灵活性略低:相比 Mem0,它的逻辑比较固定,不如 Mem0 那样能进行复杂的语义合并。
  • 适用:高并发的客服系统、需要极低延迟的 RAG 应用。

LangGraph Checkpoints (Checkpointing) —— 状态机“时空穿梭”

这是你正在使用的 LangGraph 原生自带的组件。

  • 特点:它不是语义记忆,而是状态快照。它能记录图运行到每一个 Node 时的完整 State
  • 优点
    • 错误回溯:如果实体匹配出错了,你可以直接跳回到报错前的状态重新跑。
    • 支持中断与继续:用户下线了,第二天上线可以从断点直接继续。
  • 缺点
    • 存储冗余:如果不加清理,存储量会非常大。
  • 适用:多步骤、高逻辑要求的任务(如实体对齐流转)。

RedisVL (Redis Vector Library) —— 极速 KV + 向量

在 2026 年,Redis 已经成为了 AI 内存的标配。

  • 特点:将 Redis 的高速缓存能力与向量搜索结合。
  • 优点
    • 语义缓存 (Semantic Caching):如果用户问了类似的问题,直接返回记忆,根本不走 LLM 推理,省钱省时。
    • 极高性能:在分布式集群中表现极稳。
  • 缺点
    • 成本:全内存存储,对于海量数据的长期记忆来说,硬件成本比磁盘类数据库(如 Milvus)高。
  • 适用:大模型应用的性能优化、热点问题加速。

MemGPT (现更名为 Letta) —— 虚拟内存管理

这是一种模仿操作系统“分页管理”的记忆思想。

  • 特点:它把大模型的 Context Window 当作“内存”,把外部数据库当作“磁盘”。
  • 优点
    • 无限上下文:通过 Agent 自主决定何时将信息从“内存”换出到“磁盘”。
  • 缺点
    • 控制复杂:Agent 有时会产生“幻觉”,忘记把重要的信息换回内存。
  • 适用:需要处理超长文档(如法律、医疗)的专家 Agent。
组件 核心属性 记忆粒度 实时性 推荐场景
Mem0 语义进化 实体/偏好级 个性化营销、DTC 品牌 Agent
Zep 高速摘要 会话/摘要级 极高 生产级 RAG、高并发对话
LangGraph 状态快照 节点/路径级 复杂工作流、容错要求高的任务
RedisVL 语义缓存 句子/匹配级 极高 性能优化、防刷重复请求

协议

MCP 与 A2A

特性 MCP (Model Context Protocol) A2A (Agent-to-Agent) Protocol
发起方 Anthropic (2024年底发布) 行业通用/多社区探索(如 Microsoft AutoGen, Meta 等)
核心解决 模型与数据源/工具的连接 (Model-to-Data) 智能体与智能体的通信 (Agent-to-Agent)
比喻 像电脑的 USB 接口(让模型即插即用各种工具/本地数据) 像人类的 语言/社交礼仪(让两个独立的智能体如何协作)
侧重点 统一数据读取、工具调用(Tool Use)的接口规范 统一任务分发、状态同步、多机协同的通信协议
“MCP 解决的是‘广度’(连接万物),A2A 解决的是‘深度’(协同完成复杂任务)。”
  • 层级关系:A2A 协议位于 应用层/社交层,它规定了 Agent 之间怎么分工;MCP 协议位于 能力层/接口层,它规定了 Agent 怎么去控制外部世界。
  • 协作案例
    1. Agent A 收到任务,通过 A2A 协议 告诉 Agent B:“请帮我查一下去年的销售报表”。
    2. Agent B 接收到指令,通过 MCP 协议 连接到公司内部的 SQL 数据库服务器(MCP Server),读取数据。
    3. Agent B 再通过 A2A 协议 将结果返回给 Agent A

“MCP 的安全风险本质上是 ‘代理人风险’。在我的项目中,我采取了三层防护:

  1. 物理隔离:所有的 MCP Server 都运行在独立的 Docker 容器中,限制了其对主机系统的访问。
  2. 静态审计:就像我在 NL2SQL 中使用 SQLGlot 审计 SQL 一样,对于 MCP 传回的指令,我会增加一层中间件拦截器,对危险指令进行规则匹配。
  3. 人工在环 (Human-in-the-loop):对于涉及‘写’权限或删除类的 MCP 工具,我会强制触发一个审批流,必须由用户点击确认后,MCP Server 才会真正执行。

总结来说,MCP 负责打通连接,而安全策略必须由基础设施层和业务逻辑层共同把关。

技术 核心角色 在 AI 链路中的位置 优点
SSE (Stream) 展示层 模型 $\rightarrow$ 用户 (前端) 逐字蹦出,用户体感最快。
MCP 协议层 模型 $\leftrightarrow$ 外部数据/工具 标准化。一套协议对接所有插件。
WebSocket 传输层 复杂双向交互 (如语音) 极低延迟,支持用户随时插嘴。
HTTP 基础层 所有的 API 调用基础 简单、普适、无状态。
协议 侧重点 连接对象 技术栈 你的项目选型建议
MCP 取数与执行 模型 $\leftrightarrow$ 数据库/工具 JSON-RPC 必选:用于你的 NL2SQL 连库和元数据读取。
A2A 跨界协作 Agent $\leftrightarrow$ 其他公司的 Agent HTTPS / SSE 可选:如果你需要和外部供应商的 AI 系统对接。
ACP 任务编排 Agent $\leftrightarrow$ Agent (内部) REST / HTTP 首选:如果你在构建企业内部的分布式 Agent 团队。
协议 关注点 解决的问题 就像人类的…
MCP 接口与上下文 如何让 AI 稳定、安全地使用你的软件和文件。 手和工具 (扳手、改锥)
ACP 多模态交互 如何让 AI 同时处理声音、画面和数据流。 五感 (视觉、听觉)
A2A 流程协作 如何在一家公司内分工明确、不打架。 公司规章/钉钉群
ANP 网络与价值 如何让不同公司的 AI 安全地做生意、换资源。 国际贸易协议/互联网

技术

ReAct

ReAct = Reasoning(推理)+ Acting(行动)

Cursor 三种模式

上下文驱动开发(Context-Aware Coding)

  • 利用 @ 符号:我不会让 Cursor 瞎猜。我会通过 @Files 引入数据模型定义,用 @Docs 引入 LangGraph 或 vLLM 的官方最新文档,用 @Codebase 让它理解整个 ChatBI 的架构。
  • 结构化 Prompt:在 Composer 里,我会通过描述“职责”来让它写代码,例如:“根据 @mcp_protocol.py,在 @nodes.py 中新增一个处理 SQL 执行的 MCP 节点。”

批量重构与全栈联动

  • Composer (Cmd+I):这是我最常用的功能。我会一次性描述一个跨文件的需求(比如:修改 API 接口的同时,同步更新前端的类型定义和后端的状态校验),Cursor 会自动扫描多个文件并给出 diff。

实时 Debug 与文档学习

  • 报错一键修复:终端报错时,直接点击“Debug with AI”,Cursor 会自动结合当前报错堆栈和上下文给出补丁。

Multi-Agent

AutoGen (微软出品):“自由对话的开发者实验室”

  • 核心逻辑:基于事件驱动的对话(Conversation-Centric)。它认为 Agent 协作本质上就是互相发消息。
  • 特点
    • 高度灵活性:Agent 之间的对话路径不是固定的。它们可以根据任务动态决定接下来该找谁。
    • 代码执行力极强:原生支持在沙盒中自动编写并运行代码(非常适合你的 NL2SQL 场景,自动写 SQL 并测试)。
    • 2.0 时代 (2025-2026):引入了更强的状态管理,不再像早期版本那样容易陷入“死循环”。
  • 缺点:难以预测。因为对话太自由,有时会产生不必要的 Token 消耗。

CrewAI:“像管理公司一样管理 Agent”

  • 核心逻辑:基于角色与流程(Role-Based Process)。它将任务拆分为:Role(角色)、Task(任务)和 Crew(团队)。
  • 特点
    • 强制协作流:你可以定义任务是“线性的(Sequential)”还是“层级制的(Hierarchical)”。
    • 结果导向:比起 AutoGen 的“聊着办”,CrewAI 更强调“按流程办”。它会确保 Agent A 完成后,Agent B 才开始。
    • 2026 现状:它是目前企业内部落地最快的框架,因为它最像人类真实的办公室工作流。
  • 缺点:灵活性不如 AutoGen,如果任务中途需要剧烈转向,预设的流程可能会显得死板。

DeepAgents (深度推理架构):“逻辑至上的思考者”

注:在 2026 年,这通常指以 DeepSeek-R1 或类似架构为核心的智能体方案,强调原生逻辑推理(Reasoning)而非单纯的工程编排。

  • 核心逻辑:基于深度推理链(Chain-of-Thought Native)
  • 特点
    • 内置思考过程:这类 Agent 在行动前会有极长的 Thinking 过程。它们不需要像 AutoGen 那样通过反复对话来纠错,而是在“脑内”已经完成了自我博弈。
    • 极高成功率:在处理复杂的 SQL 嵌套逻辑或实体对齐这种需要严密逻辑的任务时,成功率极高。
    • 自我迭代:这类框架通常带有强化学习(RL)反馈回路,会根据任务成败自动优化提示词策略。
  • 缺点:首字延迟(TTFT)较高,用户需要看着它“思考”很久。
维度 AutoGen CrewAI DeepAgents (推理型)
设计隐喻 自由讨论小组 严谨的公司职能部门 独立思考的专家
任务复杂度 高 (动态变化多) 中/高 (流程清晰) 极高 (逻辑严密)
开发者友好度 中等 (需较多代码控制) 极高 (声明式语法) 中等 (需理解模型思考逻辑)
NL2SQL 表现 适合快速尝试不同解法 适合标准的数据提取流程 目前最强,能处理复杂关联查询

跨页表格

  1. 表格检测:
    • 检测页面底部元素是否为表格
    • 检测下一页顶部元素是否为表格
    • 判断两表格列数是否相同
  2. 连续性判断:
    • 检测表头信息
    • 检测表格边框连续性
    • 分析表格内容逻辑关联
  3. 表格合并策略:
    • 识别列边界
    • 对齐相同列
    • 合并行数据
    • 保留表头信息
  4. 表格内容增强:
    • 表格内包含图片 → 使用VLM(如DeepSeek OCR)提取摘要
    • 复杂表格 → 生成结构化描述
    • 关键信息 → 单独标注
  5. 召回策略:
    • 同时召回表格数据
    • 召回表格摘要
    • 召回表格标题
    • 提供完整上下文
  6. 工具选择:
    • Mathpix:公式解析优秀
    • PaddleOCR/PP-Structure:通用性强
    • DeepSeek OCR:综合性能好
    • Unstructured:新兴选择
  7. 挑战:
    • 合并单元格处理
    • 表格样式复杂
    • 跨页表头重复
    • 表格内嵌图表

LangChain 与 LangGraph 版本迭代

LangChain 的重大版本跨越:走向标准化

  1. v0.1.x → v0.2.x:大解耦时代
    • 核心变化: 彻底将 langchain-core(核心抽象)与 langchain-community(第三方插件)剥离。
    • 面试重点:
      • 架构轻量化:不再是一个“全家桶”,开发者可以按需安装(如只装 langchain-openai),解决了由于依赖过多导致的部署冲突。
      • 标准化工具调用:引入了统一的 .bind_tools() 接口,让模型切换变得极其简单。
  2. v0.2.x → v0.3.x:全面 Pydantic v2 与 异步化
    • 核心变化: 升级底层数据校验框架到 Pydantic v2
    • 面试重点:
      • 性能提升:Pydantic v2 带来了数倍的数据序列化速度提升,降低了复杂 Prompt 模板的预处理延迟。
      • 原生异步流式支持:所有的 Chain 现在都必须通过 astream 接口完美支持流式输出。
  3. v1.0.x → v1.2.x (2025-2026):生产级治理与监控
    • 核心更新:全面集成 LangSmith 2.0 与 模版版本控制。
    • 核心点:
      • Prompt 独立治理:Prompt 彻底从代码中剥离,支持从远程 Hub 动态拉取。
      • 严格类型推导:利用 Python 3.12+ 的类型提示,在编译期就能捕捉模型输入输出的不匹配问题。

LangGraph 的重大演进:从“插件”到“Agent 操作系统”

LangGraph 是目前企业级 Agent 的核心,它的版本跳跃主要解决了可靠性

  1. LangGraph v1.0:持久化与“时光机” (Time Travel)
    • 重大突破:引入 Checkpointer(检查点)。
    • 面试重点:
      • 状态持久化:Agent 运行到一半断电了,重启后可以从最后一步直接恢复。
      • 时光机调试:开发者可以回溯到图中的任意历史节点,修改状态(State)并重新执行,极大降低了 Agent 逻辑的调试难度。
  2. LangGraph v1.2+ (2026):多智能体编排与分布式图
    • 重大突破:Sub-graphs(子图)与 动态并发。
    • 面试重点:
      • 复杂任务拆解:支持在一个大图中嵌套多个子图。例如:一个子图专门管 SQL 生成,另一个管报表绘制,两者独立维护自己的 State。
      • 动态节点路由:Agent 可以根据逻辑动态决定下一步是并行去查 5 个数据库,还是串行执行。
      • Human-in-the-loop 2.0:不仅能“暂停确认”,还支持“编辑后再发送”。

BDI

BDI 的三大核心组件

你可以把 BDI 理解为 Agent 的“心理逻辑”:

  • Belief (信念)Agent 对世界的认知。
    • 包括从环境中感知到的信息、数据库中的事实、以及模型内部的知识。
    • 例子: Agent 认为“实体 A 和实体 B 的 ID 是一致的”。
  • Desire (欲望/目标)Agent 想要达成的状态。
    • 这是 Agent 的终极目标(Objectives)。Desire 可以有很多个,甚至互相冲突。
    • 例子: “完成数据库中所有实体的清洗和匹配。”
  • Intention (意图)Agent 决定去执行的具体行动。
    • 这是从 Desire 中筛选出来的、当前致力于实现的目标。Agent 会为这些意图制定计划(Plan)。
    • 例子: “现在调用 Python 脚本对比这两个实体的文本相似度。”

BDI 的工作流程(推理环)
BDI 模型通常遵循一个循环:感知 -> 更新信念 -> 生成欲望 -> 形成意图 -> 执行计划

  1. 信息输入:Agent 接收新数据。
  2. 信念修正:根据新数据更新它对世界的看法。
  3. 目标选择:从一堆想做的事情(Desires)中,根据当前情况选出最紧迫的一个作为“意图”。
  4. 计划规划:为了达成这个意图,调取合适的工具(Skills)。
  5. 执行与重评估:如果环境变了(信念更新),Agent 可能会放弃当前的意图(Intention),重新选择。

AI Agent 和LLM的区别

维度 大语言模型 AI智能体
本质 一个预测下一个token的超级概率模型。 一个能感知、规划、决策、执行的自治系统。
核心能力 理解与生成:精通语言,能进行对话、总结、创作、推理。 思考与行动:能调用工具(API、代码、搜索)、记忆历史、制定计划并执行。
输入/输出 输入文本/图像,输出文本。 输入复杂目标(如“帮我订一张最便宜的机票”),输出行动结果(如完成订单的确认号)。
状态 无状态:每次对话都是独立的,默认不记得之前说过什么(除非将历史对话作为输入)。 有状态:拥有记忆(短期/长期),能基于历史交互持续学习、优化策略。
主动性 被动响应:等待用户提问,然后生成回答。 主动规划:可以拆解复杂目标,自主决定下一步做什么,甚至主动发起新任务。
边界 局限于其训练数据所蕴含的知识和模式,无法获取实时信息或影响外部世界。 通过工具突破了模型的边界,可以联网搜索、操作软件、控制硬件,与现实世界互动。
类比 一位无所不知但动弹不得的顾问。你问他“怎么订机票”,他会给你一份完美的步骤说明书。 一位拥有手脚和记事本的私人助理。你告诉他“帮我订机票”,他会自己去查价格、比价、填写信息并完成支付,最后把订单发给你。

一个典型的AI智能体系统通常包含以下组件,而LLM只是其中的决策核心:

  1. 规划模块:将大目标分解为可执行的小任务。LLM在此负责推理和制定计划。
  2. 记忆模块:存储过往的经验、对话和知识。这包括向量数据库(长期记忆)和上下文窗口(短期记忆)。
  3. 工具模块:提供一系列API、函数或技能(如计算器、搜索引擎、代码执行器)。LLM在此决定何时、调用哪个工具。
  4. 行动模块:执行工具调用,并获取外部世界的反馈。
  5. 反思模块:评估行动结果,纠正错误,优化后续计划。LLM在此进行自我批评和调整。

Prompt Engineering 和 Context Engineering

Prompt设计的最佳实践:

  1. 结构化设计:使用模板,如LangSmith的PromptTemplate
  2. 角色定义:明确agent的角色、职责和约束
  3. 示例(Few-shot):提供少量高质量示例
  4. 思维链(Chain of Thought):引导模型逐步思考
  5. 输出格式约束:指定JSON、XML等结构化输出格式
  6. 工具使用规范:明确何时、如何使用工具
  7. 迭代优化:通过评估和反馈持续改进
  • Prompt Engineering:
    • CoT
    • Few Shot
  • Context Engineering
    • RAG 检索增强
    • 窗口压缩 / 记忆

提示词维度

结构维度 (Structural Dimension) —— 骨架

我采用 CO-STARLangChain/LangGraph 标准模版。一个生产级的 Prompt 必须包含:

  • Role (角色):定义专家身份(如:资深跨境电商数据分析师)。
  • Context (上下文):提供必要的背景信息。
  • Task (任务):清晰的指令动词(如:Extract, Compare, Summarize)。
  • Constraints (约束):负面提示词(Negative Prompts),规定‘绝对不能做’的事。
  • Format (格式):强制要求输出 JSON 或特定的 Markdown 结构,方便后端解析。”

逻辑维度 (Reasoning Dimension) —— 大脑

为了处理复杂的业务逻辑(如判断两个地理实体是否为同一地点),我会引入:

  • Few-Shot (少样本学习):提供 3-5 个高质量的正负案例,这比任何文字描述都有效。
  • CoT (思维链):要求模型‘Step-by-Step’思考,将推理过程显式化,减少逻辑跳跃导致的幻觉。
  • Self-Reflect (自我反思):在 Prompt 末尾要求模型检查自己的答案是否符合约束。”

动态维度 (Dynamic Dimension) —— 变量

LangGraph 项目中,Prompt 不是死的,而是根据状态动态生成的:

  • Variable Injection (变量注入):动态插入当前 Agent 的 State、历史对话摘要或检索到的 RAG 片段。
  • Few-Shot Dynamic Selection (动态示例):根据当前输入,从向量数据库里检索最相关的例子放入 Prompt(即 RAG-based Few-shot)。”

优化维度 (Optimization Dimension) —— 性能

这是针对 L20 集群 推理效率的优化:

  • Token Efficiency (Token 效率):剔除冗余修饰词,压缩指令,降低首字延迟(TTFT)。
  • Instruction Following (指令遵循度):通过 DPO/KTO 微调后的模型,对不同长度的 Prompt 敏感度不同,我会进行交叉测试。”

安全与稳健维度 (Safety & Robustness) —— 防护

  • Prompt Injection Defense (防注入):防止用户输入恶意指令篡改系统行为。
  • Hallucination Control (幻觉控制):明确告诉模型‘如果不知道,请回答不知道’。

Linux

常用指令

  • grep(过滤)
    • grep -E "Apple|Microsoft" data.json:使用扩展正则同时查找多个关键词。
    • grep -P "\d{4}-\d{2}-\d{2}" train.log:使用 Perl 正则匹配日期格式的日志。
    • grep -v "DEBUG" server.log:反向查找,过滤失掉所有调试信息。
  • sed(流编辑/批量替换)
    • sed -i 's/苹果公司/Apple Inc./g' entities.txt:直接在文件中批量替换。
    • sed -n '100,200p' data.jsonl:只查看文件的第 100 到 200 行。
  • awk(格式化/列处理)
    • awk -F',' '{if($3>0.8) print $1,$2}' result.csv:以逗号分隔,筛选出置信度(第三列)大于 0.8 的前两列。这在处理匹配结果时极常用。
  • nvidia-smi:查看显存占用、功率和温度。
    • watch -n 1 nvidia-smi:每秒刷新一次,观察模型加载或推理时的显存波动。
  • htop / top:查看 CPU 核心占用和内存(RAM)是否溢出,防止数据预处理把内存撑爆
  • df -h / du -sh *:查看磁盘空间。训练大模型产生的 Checkpoints(权重文件)极大,经常会写满磁盘。
  • ps -ef | grep python:查找卡死的训练进程并配合 kill -9 强制清理。
  • tail -f train.log:实时查看训练 Loss 的变化。
  • less -S data.jsonl:在大文件中左右滚动查看长文本,且不会把几十 GB 的文件全部读入内存导致死机。
  • rsync -avP local_path/ user@remote_ip:/remote_path/:比 scp 更安全的文件传输,支持断点续传(传几十 GB 模型文件时必用)。

模糊指代

场景:用户先聊 A(买鞋),中间插播 B(吃饭),最后回过头说“前面那件事(指代 A)”。

问题:传统的向量搜索(RAG)会因为“那件事”语义太模糊,容易抓错成最近的 B(吃饭),导致模型“串台”。

为什么重写会失败?

  • 语义真空:用户只说了“那件事”,而历史记录中有多个未完成话题(买鞋、砍价、售后)。
  • 幻觉风险:LLM 强行从最近的“吃饭”话题中找关联,导致重写为“关于中午吃饭的续聊”。

核心对策:从“单向重写”转向“多维定位”

手段 逻辑描述 作用
话题栈 (Topic Stack) 维护一个类似 LIFO(后进先出)的栈。当用户说“那件事”时,程序优先调取栈顶倒数第二个话题。 物理确定性:不靠猜,靠话题切换的轨迹。
状态过滤 (State Filtering) 只有标记为 Pending(悬而未决)的话题才被纳入重写范围。 排除干扰:既然“吃饭”已经聊完(已结案),就绝不会重写到吃饭上。
置信度校验 (Confidence Threshold) 让 LLM 在重写时输出一个分数。如果分数低于 0.8,说明它也“拿不准”。