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=16到r=64比较平衡。如果r=256甚至更高,且训练数据量小于 5000 条,极易过拟合。
架构层面
核心逻辑:降低自由度,锁死大部分参数。
- 3.1 参数高效微调 (PEFT/LoRA):
- 原理:冻结 99%+ 的原参数,只训练极少数(<1%)的新增参数(Adapter/Rank 矩阵)
- 防过拟合优势:
- 限制自由度:参数极少,模型难以“背诵”微调数据
- 保留通用性:原始底座知识被锁死,防止“灾难性遗忘”和针对特定任务的过拟合
正则化
正则化(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 代表模型分辨正负样本的能力越强。
- ROC 是以假正率(FPR)为横轴,真正率(TPR)为纵轴的曲线。
回归任务指标 (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 三元组” 的四个评估维度:
- Faithfulness (忠实度):生成的回答是否完全来自检索到的上下文?(防止幻觉)。
- Answer Relevance (答案相关性):生成的回答是否直接回答了用户的问题?
- Context Precision (检索精准度):检索到的片段中,真正有用的信息是否排在前面?
- 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步骤
- 全局潜空间投影 (Global Latent Projection)
- 步骤: 传统的 $K$ 和 $V$ 矩阵,首先被投影到一个低维的潜空间中。
- 作用: 这是一个“信息浓缩”**的过程,捕捉原始 Key/Value 中的核心信息。
- 潜空间融合 (Latent Space Aggregation)
- 步骤: 随着序列的增长,新的 Query 进来,它对应的 Key 和 Value 也会被投影到这个低维潜空间。然后,所有这些低维的潜 Key/Value 向量会被聚合起来。
- 作用: 相当于在低维空间中维护一个“浓缩的历史上下文”,而不是存储每一个原始的 KV 向量。这个聚合可以是一个简单的求和,或者更复杂的递归操作。
- 解压缩与局部注意力 (Decompression & Local Attention)
- 步骤: 当一个 Query 需要计算注意力时,它不会直接和低维的潜 KV 向量进行点积。
- 从低维潜空间中解压缩出一个近似的、高维的 Key 和 Value 矩阵。
- 然后使用这个近似的 KV 矩阵与当前的 Query 进行标准的注意力计算。
- 作用: 确保了最终的注意力计算依然是高维的,但存储和传输的 KV Cache 始终是低维的,极大地减少了显存开销。
- 步骤: 当一个 Query 需要计算注意力时,它不会直接和低维的潜 KV 向量进行点积。
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)中广泛采用的、用于提升性能与效 率的关键结构之一
- 核心优势 (Pros) —— “大而快”
- 计算效率 : 推理时仅激活 Top-K 专家,FLOPs(计算量) 显著降低
- 能以较小的活跃参数量实现巨大的总参数量(Total Params)性能
- 高扩展性: 模型容量暴力扩张,而训练/推理成本不随之翻倍
- 任务特化: 专家会自发分工(如代码、数学、文案专家),提升复杂长尾任务的上限
- 计算效率 : 推理时仅激活 Top-K 专家,FLOPs(计算量) 显著降低
- 核心挑战 (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 适配:它是 Transformer 和 BERT 架构的基础,能完美处理不同长度的句子。
- 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} }$$
核心特性(面试必背):
- 绝对的形式: 每个词根据自己的位置 $m$ 独立旋转,不依赖别人,推理快。
- 相对的效果: 两个词点积的结果只由它们的夹角差(相对距离 $m-n$) 决定
- 远程衰减: 随着距离拉长,点积结果会自然衰减
代表: Llama 系列、Qwen、DeepSeek。
| 维度 | 绝对位置编码 (Learned) | 相对位置编码 (T5 Bias) | 旋转位置编码 (RoPE) |
|---|---|---|---|
| 实现方式 | nn.Embedding 查找表 |
Attention Score 加偏置项 | 向量旋转变换 |
| 是否可学习 | 是 | 是 | 否 (函数固定) |
| 长度外推 | 极差 (有硬上限) | 较好 | 极好 (支持插值扩展) |
| 推理效率 | 极高 (加法运算) | 较低 (每步重算距离) | 高 (硬件友好) |
| 主流地位 | 早期模型 (BERT) | 特定模型 (T5) | 现代模型标配 |
Transformer

Milvus 索引
- 稠密向量索引 (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),这会增加索引文件大小,但能显著提升检索时的路径寻找效率。
- 稀疏向量索引 (Sparse Vector Indexes)
主要用于处理 BM25 关键词特征或词袋模型生成的向量。
SPARSE_INVERTED_INDEX:类似于搜索引擎的倒排索引,专门针对非零元素极少的稀疏向量进行优化。
SPARSE_WAND:一种弱与(Weak AND)算法加速的稀疏索引,用于在大规模稀疏数据中快速过滤。
- 标量索引 (Scalar Indexes)
用于处理非向量字段(如用户 ID、订单日期、商品类别等)的过滤查询。
INVERTED (倒排索引):最推荐,适用于字符串、整数等,支持精确匹配和前缀搜索。
BITMAP (位图索引):适用于基数(Unique values)较少的字段,如“性别”、“是否在售”。
STL_SORT:利用排序进行二分查找,适用于数值型的范围查询。
Trie (字典树):专门优化字符串的前缀匹配。
- 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 场景) | 最低 (环境依赖极度严苛) |
- 研发效率与后训练(DPO)的完美契合
- 痛点回避:TRT-LLM 每次 DPO 训练后都需要半小时编译,这会中断我们的“训练-评估”闭环。
- vLLM 优势:支持直接加载 HuggingFace 格式权重。在 L20 集群上,我们可以实现分钟级的模型版本切换,极大地加速了 NL2SQL 模型的迭代速度。
- L20 显存特性的极致利用
- 显存灵活性:L20 有 48GB 显存,虽然充裕但并非无限。
- vLLM 表现:相比 TRT-LLM 必须写死
Max_Length导致的显存预占(浪费),vLLM 的 PagedAttention 允许我们在同一张卡上动态处理不同长度的 SQL 请求。在处理复杂的、长短不一的数据库 Schema 时,vLLM 的显存利用率更高,支持的实际并发数往往超过了静态配置的 TRT-LLM。
- 分布式运维的“减负” (基于 Ray)
- 选型逻辑:在 L20 集群中,我们经常需要从单卡扩展到多卡 TP(张量并行)。
- vLLM 胜出:基于 Ray 的分布式架构让我们只需通过一个参数(
--tensor-parallel-size)即可完成扩容。Ray 自动处理了多进程间的资源竞争、健康检查和失败自愈。 - 对比 MPI:放弃 TRT-LLM 的主要原因之一就是它依赖 MPI,在容器化部署和动态扩缩容时,MPI 的网络配置和静态引擎分发是极大的运维负担。
- 工业级稳定性与 FP8 生态
- 硬件匹配:L20 的核心优势是 FP8。
- 实测结论:2026 年的 vLLM 对 FP8 推理的支持已经非常成熟。在我们的实测中,vLLM 的 FP8 吞吐量已经能够满足业务高峰需求,而 TRT-LLM 带来的额外性能提升(15%左右)并不足以抵消它在维护和开发上的巨大成本。
“在 L20 集群的部署选型中,我最终选择了 vLLM。我的决策核心在于:‘用最成熟的工业方案,换取最高的研发周转率’。
避开 TRT-LLM 的‘静态陷阱’:它虽然快,但‘静态编译’和‘MPI 依赖’严重阻碍了我们 DPO 训练后的快速验证,不符合 NL2SQL 这种需要频繁迭代 Prompt 和权重的业务逻辑。
对比 SGLang 的‘稳健考量’:虽然 SGLang 的前缀缓存很诱人,但在大规模集群生产环境下,vLLM 的社区支持更完备,对于各种量化格式(尤其是 L20 擅长的 FP8)的兼容性更稳。
拥抱 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。
- 改进点:
- 多层注入:学 Prefix Tuning,在每一层都加提示向量。这让它在 1B-10B 的小模型上也能爆发。
- 分类头改进:不再用复杂的 Verbalizer(词表映射),直接在输出层加线性层,更符合传统微调习惯。
- 多任务共享:支持不同任务间共享 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 | |
模型蒸馏
蒸馏的核心三要素
- 教师模型 (Teacher):大而强,它是知识的源头。
- 学生模型 (Student):小而快,它是被训练的对象。
- 知识 (Knowledge):教师模型输出的“软目标(Soft Targets)”——即模型不仅告诉学生什么是对的,还告诉学生错误选项之间的相似性(这就是所谓的“暗知识”)。
蒸馏的具体做法(三类主流路径)
A. 响应蒸馏 (Response-based) —— 模仿结论
这是最常用的方式,让学生模型去拟合教师模型的 Logits(输出层概率分布)。
- 操作:
- 用同一个样本输入两个模型。
- 计算学生输出与教师输出(软标签)之间的 KL 散度(Kullback-Leibler Divergence)。
- 结合原始的硬标签(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 | |
LLaMA-Factory 参数
通用核心参数(无论哪种模式都要配)
这些参数决定了数据的来源、模型的位置以及基础训练策略:
model_name_or_path: 基础模型路径(如Qwen/Qwen2.5-32B)。dataset: 训练数据集名称(在dataset_info.json中注册的名字)。template: 模型对应的提示词模板(如qwen、llama3),选错会导致模型学不会对话。finetuning_type: 微调模式,可选lora、full(全量)、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 显存即可启动)。
详细参数设置手册
- 基础模型设置 (Model Arguments)
- Model Name/Path: 选
Qwen2.5-32B-Instruct。 - Finetuning Method: 选
lora。 - Quantization Bit:
- LoRA: 选
None(或者不选)。 - QLoRA: 选
4。这是开启 QLoRA 的开关。
- LoRA: 选
- Model Name/Path: 选
- LoRA 核心参数 (Adapter Settings)
- LoRA Rank (r):
- 推荐:
16或32。 - 说明:数值越大,可训练参数越多,表达能力越强,但显存占用也随之增加。
- 推荐:
- LoRA Alpha ($\alpha$):
- 推荐:
32或64。 - 说明:通常设置为 $2 \times r$,用于缩放学习率。
- 推荐:
- LoRA Dropout:
- 推荐:
0.05或0.1。 - 说明:防止过拟合,若数据集很小,建议保持 0.05。
- 推荐:
- LoRA Target Modules:
- 推荐:填写
all。 - 说明:在 QLoRA 论文中证明,覆盖所有线性层(q, k, v, o, gate, up, down)能达到接近全量微调的效果。
- 推荐:填写
- LoRA Rank (r):
- 训练超参数 (Training Arguments)
- Learning Rate:
- LoRA: 推荐
1e-4。 - QLoRA: 推荐
2e-4(量化后学习率可以稍微大胆一点)。
- LoRA: 推荐
- Compute Type:
- 推荐:
bf16(如果使用 L20 显卡,务必选 bf16,性能和稳定性最优)。
- 推荐:
- Gradient Checkpointing:
- 推荐:开启 (
True)。 - 说明:极大地节省显存,代价是训练速度慢约 20%。
- 推荐:开启 (
- Learning Rate:
训练框架
| 框架名称 | 核心武器 (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:发烧友的“乐高”,适合那些需要精细调控每一项微小参数的极客场景。
微调轮次
数据量的规模(核心指标)
- 大数据集(>5万条):通常只需要 1-2 个 Epoch。因为数据量够大,模型在看第一遍的过程中已经见过足够多的变体,足以收敛。
- 小数据集(<5000条):通常需要 3-5 个 Epoch。因为样本少,模型需要多看几遍才能形成深刻记忆。
学习率 (Learning Rate) 的配合
- 如果你设置的学习率很小(如 $5e^{-6}$),模型步子迈得小,可能需要更多轮次。
- 通常采用 Cosine Learning Rate Scheduler,在多轮训练中后期逐渐减小学习率,帮助模型在最后一轮精准落位。
任务的复杂度
- 风格对齐(比如让模型说话更客气):1 Epoch 往往就够了。
- 逻辑重塑(比如你的 NL2SQL):通常需要 3-5 Epoch,因为模型需要纠正原本错误的 SQL 生成逻辑。
验证集 (Validation)
在 2026 年,专业的炼丹师不会预设一个死板的轮次,而是使用 “早停法 (Early Stopping)”:
- 监控验证集损失 (Val Loss):每隔一定步数(如 100 Steps),在不参与训练的验证集上测一次。
- 观察拐点:
- 训练初期:训练集和验证集的 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 时,它本质上是在给词库里的所有词打分(概率分布)。这三个参数就是用来从这个分布里“选词”的。
- Temperature
- Top-K —— “前 K 名选拔”
- 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 的原因
- 模型权重 (Model Weights):
- 这是最固定的部分。例如一个 7B 模型(16位浮点数 FP16),光存放权重就需要 $7 \times 2 = 14$ GB。
- 优化器状态 (Optimizer States):
- 这是显存杀手! 如果使用标准的 AdamW 优化器,它需要为每个参数存储“动量(Momentum)”和“方差(Variance)”。
- 通常,优化器占用的显存是模型权重的 2 到 3 倍。
- 梯度 (Gradients):
- 存储每个参数的梯度值,大小通常与模型权重一致。
- 激活值 (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 为例)画成这样一个关系图:
- Actor (策略模型):负责生成 Token。
- Critic (价值模型):负责预估当前的 $V(s)$。这个是动态训练的,它才使用贝尔曼方程。
- Critic 引入了 时序差分 (TD Learning),不需要等到 episode 结束(考完试)才更新,每走一步(每生成一个 token)就可以根据贝尔曼方程更新价值。这解决了 REINFORCE 必须等结局的延迟问题。
- Reference Model (参考模型):负责计算 KL 散度,防止 Actor 跑偏。
- Reward Model (奖励模型):负责给生成结果打分。通常是静态的。
- Advantage Function (优势计算):计算“实际分 + KL 惩罚”与“Critic 预估分”的差值,用来更新 Actor。
近端策略优化
- $r_t(\theta)$:新旧策略的比例(新动作概率 / 旧动作概率)。
- $\epsilon$:一个很小的常数(通常是 0.1 或 0.2)。
- 逻辑:如果新策略跑得太远(比例超过 $1 \pm \epsilon$),公式就会触发 Clip(裁剪),强行把更新幅度拉回来。
- 面试话术:“PPO 通过这个裁剪机制,确保了训练的单调稳定性。它就像是给模型的学习过程装了一个限速器,防止它在优化的过程中‘用力过猛’掉进无底深渊。”
“我认为强化学习在 LLM 对齐中的演进,本质上是一个‘不断降低方差、提升信用分配精度’的过程:
起初是 REINFORCE:它最直观,但它是‘全回合’更新。就像一个学生考完试才知道哪做对了,它无法区分一连串动作中哪个是关键,导致训练方差极大。
随后引入了 Baseline:这是关键的一步。通过引入基准,我们让模型学会了‘相对学习’。我们优化的不再是奖励总和,而是优势(Advantage),这有效地过滤了环境噪声,稳定了梯度。
真正的质变是 Actor-Critic (AC):这里我们请回了贝尔曼方程。借助 Critic 对未来价值的递归建模(Bootstrapping),我们实现了单步更新。这意味着模型不需要等对话结束,就能通过‘时序差分’学习到每一个 Token 对最终奖励的贡献。
最后到 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。
- SimPO:2024-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 也可以处理视觉。
核心逻辑:
- 切片(Patching):把图片切成 $16 \times 16$ 的小方块,每个方块看作一个“单词(Token)”。
- 线性投影:把像素方块变向量。
- 全局注意力:利用 Transformer 的 Self-Attention,让每个像素块都能同时看到全图。
解决了什么:
- 架构统一:让视觉和文本使用完全一样的数学结构(Transformer),为原生多模态扫清障碍。
- 打破瓶颈:CNN 在大数据下会遇到瓶颈,而 ViT 符合 Scaling Law(数据越多、算力越强,性能越恐怖)。
面试话术:
“ViT 的出现标志着视觉领域**归纳偏置(Inductive Bias)**的隐退。它不再假设像素之间有局部关系,而是通过海量数据让模型自发学习全局特征。这使得视觉模型能直接作为 LLM 的插件,因为大家现在都说同一种‘语言’(向量序列)。”
CLIP
(Contrastive Language-Image Pre-training)
本质:通过对比学习(Contrastive Learning),实现了图像和文字的语义对齐。
核心逻辑:
- 双塔架构:一个 Image Encoder(通常就是 ViT)和一个 Text Encoder。
- 连连看训练:给模型数亿对“图片+文字描述”。训练目标是:让对应的图文向量在空间里越靠越近,不对应的越跑越远。
解决了什么:
- 零样本能力(Zero-shot):CLIP 学到了概念。你给它一张从没见过的“宇航员骑马”,它能根据文字理解这张图。
- 跨模态桥梁:它是 DALL-E、Stable Diffusion 的“导航仪”,也是 LLaVA 等多模态模型的“眼睛”。
面试话术:
“如果说 ViT 给了 AI 一双‘眼睛’,那么 CLIP 就给了 AI 一个‘大脑字典’。它将视觉向量映射到了语言空间,让我们能用文字去检索、去操纵、去理解图像。”
扩散模型
(Diffusion Model)
本质:一种通过迭代去噪生成图像的生成式模型。
核心逻辑:
- 前向过程(加噪):把一张好图慢慢变成一堆随机雪花(噪声)。
- 反向过程(去噪):训练模型(通常是 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, 词频) —— 统计的是“局部”信息
- 用到的统计量:
- 某个词在当前文档中出现的次数
- 当前文档的总词数
- 意思: 这个词在这一篇文章里出现的频率高不高?
IDF (Inverse Document Frequency, 逆文档频率) —— 统计的是“全局”信息
- 用到的统计量:
- 语料库(数据库)中的文档总数
- 包含这个词的文档数量
- 意思: 这个词在整个知识库里是不是很稀有?
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 更精细,专门用来衡量搜索结果的排序质量。
核心逻辑(拆解):
- Gain (收益):每个结果都有个分值(比如:相关=3, 模糊=1, 不相关=0)。
- Cumulative Gain (CG):把前 K 个结果的分值加起来。
- Discounted (折损):这是关键! 排名越靠后,分值要除以一个以位置为底的对数 $\log(\text{rank}+1)$。这意味着:好结果排在后面,贡献的分数会大幅衰减。
- 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 合并机制的方案。
- 实现逻辑:
- 只读获取:在 Node 函数中通过
state["key"]获取所需变量。这在 Python 中相当于获取了一个局部副本(快照)。 - 局部处理:在函数内部执行逻辑,产生的中间变量(如
temp_data)仅存在于函数生命周期内。 - 定向写回:通过
return {"specific_key": result}仅更新该 Agent 负责的字段。
- 只读获取:在 Node 函数中通过
1 | |
方案二:父子图隔离(Sub-graphs)
这是物理级别的隔离,适用于逻辑极其复杂的子任务(如你研究的实体匹配)。
- 实现逻辑:将子 Agent 封装为一个独立的
StateGraph,它拥有自己独立的LocalState - 交互方式:
- 输入映射:父图通过调用参数将必要信息传给子图。
- 输出映射:子图运行结束后,只向父图返回一个最终的
Output字典。
- 优点:子图内部成百上千轮的对话和日志对父图完全不可见,彻底避免上下文污染。
方案三:命名空间(Key-spacing)隔离
在同一个 TypedDict 中人为划分领地。
- 实现逻辑:
- 定义
agent_a_private: dict和agent_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 | |
拷贝
浅拷贝 (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 怎么去控制外部世界。
- 协作案例:
- Agent A 收到任务,通过 A2A 协议 告诉 Agent B:“请帮我查一下去年的销售报表”。
- Agent B 接收到指令,通过 MCP 协议 连接到公司内部的 SQL 数据库服务器(MCP Server),读取数据。
- Agent B 再通过 A2A 协议 将结果返回给 Agent A。
“MCP 的安全风险本质上是 ‘代理人风险’。在我的项目中,我采取了三层防护:
- 物理隔离:所有的 MCP Server 都运行在独立的 Docker 容器中,限制了其对主机系统的访问。
- 静态审计:就像我在 NL2SQL 中使用 SQLGlot 审计 SQL 一样,对于 MCP 传回的指令,我会增加一层中间件拦截器,对危险指令进行规则匹配。
- 人工在环 (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)反馈回路,会根据任务成败自动优化提示词策略。
- 内置思考过程:这类 Agent 在行动前会有极长的
- 缺点:首字延迟(TTFT)较高,用户需要看着它“思考”很久。
| 维度 | AutoGen | CrewAI | DeepAgents (推理型) |
|---|---|---|---|
| 设计隐喻 | 自由讨论小组 | 严谨的公司职能部门 | 独立思考的专家 |
| 任务复杂度 | 高 (动态变化多) | 中/高 (流程清晰) | 极高 (逻辑严密) |
| 开发者友好度 | 中等 (需较多代码控制) | 极高 (声明式语法) | 中等 (需理解模型思考逻辑) |
| NL2SQL 表现 | 适合快速尝试不同解法 | 适合标准的数据提取流程 | 目前最强,能处理复杂关联查询 |
跨页表格
- 表格检测:
- 检测页面底部元素是否为表格
- 检测下一页顶部元素是否为表格
- 判断两表格列数是否相同
- 连续性判断:
- 检测表头信息
- 检测表格边框连续性
- 分析表格内容逻辑关联
- 表格合并策略:
- 识别列边界
- 对齐相同列
- 合并行数据
- 保留表头信息
- 表格内容增强:
- 表格内包含图片 → 使用VLM(如DeepSeek OCR)提取摘要
- 复杂表格 → 生成结构化描述
- 关键信息 → 单独标注
- 召回策略:
- 同时召回表格数据
- 召回表格摘要
- 召回表格标题
- 提供完整上下文
- 工具选择:
- Mathpix:公式解析优秀
- PaddleOCR/PP-Structure:通用性强
- DeepSeek OCR:综合性能好
- Unstructured:新兴选择
- 挑战:
- 合并单元格处理
- 表格样式复杂
- 跨页表头重复
- 表格内嵌图表
LangChain 与 LangGraph 版本迭代
LangChain 的重大版本跨越:走向标准化
- v0.1.x → v0.2.x:大解耦时代
- 核心变化: 彻底将
langchain-core(核心抽象)与langchain-community(第三方插件)剥离。 - 面试重点:
- 架构轻量化:不再是一个“全家桶”,开发者可以按需安装(如只装
langchain-openai),解决了由于依赖过多导致的部署冲突。 - 标准化工具调用:引入了统一的
.bind_tools()接口,让模型切换变得极其简单。
- 架构轻量化:不再是一个“全家桶”,开发者可以按需安装(如只装
- 核心变化: 彻底将
- v0.2.x → v0.3.x:全面 Pydantic v2 与 异步化
- 核心变化: 升级底层数据校验框架到 Pydantic v2。
- 面试重点:
- 性能提升:Pydantic v2 带来了数倍的数据序列化速度提升,降低了复杂 Prompt 模板的预处理延迟。
- 原生异步流式支持:所有的 Chain 现在都必须通过
astream接口完美支持流式输出。
- v1.0.x → v1.2.x (2025-2026):生产级治理与监控
- 核心更新:全面集成 LangSmith 2.0 与 模版版本控制。
- 核心点:
- Prompt 独立治理:Prompt 彻底从代码中剥离,支持从远程 Hub 动态拉取。
- 严格类型推导:利用 Python 3.12+ 的类型提示,在编译期就能捕捉模型输入输出的不匹配问题。
LangGraph 的重大演进:从“插件”到“Agent 操作系统”
LangGraph 是目前企业级 Agent 的核心,它的版本跳跃主要解决了可靠性。
- LangGraph v1.0:持久化与“时光机” (Time Travel)
- 重大突破:引入 Checkpointer(检查点)。
- 面试重点:
- 状态持久化:Agent 运行到一半断电了,重启后可以从最后一步直接恢复。
- 时光机调试:开发者可以回溯到图中的任意历史节点,修改状态(State)并重新执行,极大降低了 Agent 逻辑的调试难度。
- 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 模型通常遵循一个循环:感知 -> 更新信念 -> 生成欲望 -> 形成意图 -> 执行计划。
- 信息输入:Agent 接收新数据。
- 信念修正:根据新数据更新它对世界的看法。
- 目标选择:从一堆想做的事情(Desires)中,根据当前情况选出最紧迫的一个作为“意图”。
- 计划规划:为了达成这个意图,调取合适的工具(Skills)。
- 执行与重评估:如果环境变了(信念更新),Agent 可能会放弃当前的意图(Intention),重新选择。
AI Agent 和LLM的区别
| 维度 | 大语言模型 | AI智能体 |
|---|---|---|
| 本质 | 一个预测下一个token的超级概率模型。 | 一个能感知、规划、决策、执行的自治系统。 |
| 核心能力 | 理解与生成:精通语言,能进行对话、总结、创作、推理。 | 思考与行动:能调用工具(API、代码、搜索)、记忆历史、制定计划并执行。 |
| 输入/输出 | 输入文本/图像,输出文本。 | 输入复杂目标(如“帮我订一张最便宜的机票”),输出行动结果(如完成订单的确认号)。 |
| 状态 | 无状态:每次对话都是独立的,默认不记得之前说过什么(除非将历史对话作为输入)。 | 有状态:拥有记忆(短期/长期),能基于历史交互持续学习、优化策略。 |
| 主动性 | 被动响应:等待用户提问,然后生成回答。 | 主动规划:可以拆解复杂目标,自主决定下一步做什么,甚至主动发起新任务。 |
| 边界 | 局限于其训练数据所蕴含的知识和模式,无法获取实时信息或影响外部世界。 | 通过工具突破了模型的边界,可以联网搜索、操作软件、控制硬件,与现实世界互动。 |
| 类比 | 一位无所不知但动弹不得的顾问。你问他“怎么订机票”,他会给你一份完美的步骤说明书。 | 一位拥有手脚和记事本的私人助理。你告诉他“帮我订机票”,他会自己去查价格、比价、填写信息并完成支付,最后把订单发给你。 |
一个典型的AI智能体系统通常包含以下组件,而LLM只是其中的决策核心:
- 规划模块:将大目标分解为可执行的小任务。LLM在此负责推理和制定计划。
- 记忆模块:存储过往的经验、对话和知识。这包括向量数据库(长期记忆)和上下文窗口(短期记忆)。
- 工具模块:提供一系列API、函数或技能(如计算器、搜索引擎、代码执行器)。LLM在此决定何时、调用哪个工具。
- 行动模块:执行工具调用,并获取外部世界的反馈。
- 反思模块:评估行动结果,纠正错误,优化后续计划。LLM在此进行自我批评和调整。
Prompt Engineering 和 Context Engineering
Prompt设计的最佳实践:
- 结构化设计:使用模板,如LangSmith的PromptTemplate
- 角色定义:明确agent的角色、职责和约束
- 示例(Few-shot):提供少量高质量示例
- 思维链(Chain of Thought):引导模型逐步思考
- 输出格式约束:指定JSON、XML等结构化输出格式
- 工具使用规范:明确何时、如何使用工具
- 迭代优化:通过评估和反馈持续改进
- Prompt Engineering:
- CoT
- Few Shot
- Context Engineering
- RAG 检索增强
- 窗口压缩 / 记忆
提示词维度
结构维度 (Structural Dimension) —— 骨架
我采用 CO-STAR 或 LangChain/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,说明它也“拿不准”。 |