生成式AI原理与实战(Part 1)学习笔记:给初级开发者的 LLM 入门图解
- 约 16 分钟读完 - 全文 6089 字生成式AI原理与实战(Part 1)学习笔记:给初级开发者的 LLM 入门图解
读完《生成式AI原理与实战 —— Part 1》后,我把 58 个问题整理成这篇文章。目标读者是刚接触 AI 的初中级开发者:你不用会推反向传播,但读完后应该能清楚地说出大模型是怎么“看”文本、怎么生成文本、以及怎么在实际任务里用它。
写在前面:为什么开发者要懂这些?
如果你只是调用 API,可能会觉得大模型就像一个“黑盒 HTTP 服务”。但真到做项目时,很多问题都和底层机制有关:
- 为什么同样的中文输入,不同模型算出来的 Token 数差很多?
- 为什么上下文不能无限长?
- 为什么模型做数学题会错?
- RAG、Agent、微调这些词到底在解决什么问题?
这篇文章会用“概念 + 图 + 生活化类比”来回答。每张图都是帮助你建立直觉,而不是背公式。
一、大模型不是单一结构:三种 Transformer 架构
大模型基本都基于 Transformer。Transformer 最初有编码器 + 解码器,但后来发展出三种形态。
graph LR
subgraph 仅编码器模型
A1[输入文本] --> E1[Encoder<br/>双向 Self-Attention]
E1 --> O1[理解结果/分类]
end
subgraph 仅解码器模型
A2[前缀文本] --> D2[Decoder<br/>Masked Self-Attention]
D2 --> O2[逐字生成<br/>自回归]
end
subgraph 编码器-解码器模型
A3[输入文本] --> E3[Encoder]
E3 --> D3[Decoder<br/>Cross-Attention]
D3 --> O3[翻译/摘要]
end
| 类型 | 代表 | 看上下文的方式 | 典型用途 |
|---|---|---|---|
| 仅编码器 | BERT、RoBERTa | 双向(整句一起看) | 分类、检索、文本匹配 |
| 仅解码器 | GPT、LLaMA、Mistral | 单向(只能看左边) | 续写、对话、代码生成 |
| 编码器-解码器 | T5、BART | 编码器双向 + 解码器单向 | 翻译、摘要、复杂生成 |
GPT 和原始 Transformer 的最大区别:GPT 把解码器单独拿出来,训练目标是“给定前文,预测下一个 token”,也就是自回归语言建模。这让 GPT 系列天然适合生成任务。
1.1 为什么 Transformer 比 RNN+Attention 强?
早期 LSTM/GRU 需要一步一步处理序列,计算是串行的。Transformer 的自注意力可以一次性看到整句话,所有位置并行计算。
- 并行:训练速度大幅提升。
- 长距离依赖:RNN 对很远距离的信息容易“遗忘”,自注意力让任意两个 token 直接建立联系。
- 结构统一:没有复杂的循环状态,更容易扩展成超大模型。
代价是计算复杂度为 O(n²),n 是序列长度。这也是上下文窗口不能无限长的根本原因。
二、从文本到向量:Token 与 Embedding
大模型看不懂“字”,它只能处理数字。所以第一步是分词(Tokenization)。
flowchart LR
T[原始文本] --> Token[Tokenizer 切分]
Token --> ID[Token ID]
ID --> Emb[Embedding 向量]
Emb --> PE[加位置编码]
PE --> In[输入 Transformer]
2.1 大模型分词器 vs 传统中文分词
| 对比 | 大模型 Tokenizer | 传统中文分词 |
|---|---|---|
| 目标 | 给神经网络高效编码 | 切出符合语言学的“词” |
| 粒度 | 子词、字符、字节,视词表而定 | 一般是词 |
| OOV 处理 | 拆成子词/字节,几乎不会失败 | 拆成单字或按规则处理 |
| 例子 | “hello” → [“hell”, “o”] | “人工智能” → [“人工”, “智能”] |
给定一个词表,分词结果通常是唯一的。因为现代 Tokenizer 大多采用贪心最长匹配(BPE、WordPiece、Unigram 等),优先匹配最长的子词。
2.2 字节级 BPE 为什么更通用?
GPT-4、Llama 等模型使用 byte-level BPE:先把文本转成 UTF-8 字节序列,再在字节上做 BPE。
好处:
- 任何语言、Emoji、乱码、代码都能被编码,没有 OOV。
- 不需要为每种语言设计特殊预处理。
- 不同平台对 UTF-8 字节表示一致,迁移更稳定。
2.3 大模型怎么区分“用户说的”和“AI 说的”?
靠特殊 Token 和固定格式。训练时,对话会被包装成类似下面的结构:
<|user|> 今天天气怎么样? <|assistant|> 今天天气很好,晴朗温暖。 <|end|>模型在训练过程中学会了:看到 <|assistant|> 就知道要切换成回答模式。实际调用 ChatGPT、Claude 的 API 时,role: user/assistant/system 也是同样的道理。
2.4 工具调用时,输出怎么和文本回复区分?
模型通过输出格式约定区分:
- 普通回复:生成自然语言文本。
- 工具调用:生成结构化的 JSON / Function Call Schema。
服务端拿到输出后,检查结构:如果是 JSON,就执行工具;如果是文本,就直接返回给用户。训练阶段会通过 RLHF 告诉模型“该调用工具时不要废话,直接输出 JSON”。
三、静态 vs 上下文相关 Embedding
3.1 word2vec 的负例有什么用?
word2vec 有两种训练方式:CBOW 和 Skip-gram。Skip-gram + Negative Sampling 中,负例让训练从“对整个词表做 softmax”变成“对少量正例 + 负例做二分类”。
作用:
- 减少计算量:每次只更新少量向量。
- 学到区分性表示:正确搭配拉近,错误搭配推远。
3.2 静态 Embedding 和上下文相关 Embedding
| 特性 | 静态词嵌入(word2vec/GloVe) | 上下文相关嵌入(BERT/GPT) |
|---|---|---|
| 向量 | 每个词一个固定向量 | 每个词每次出现都不同 |
| 例子 | “bank” 永远是一个向量 | 在 “river bank” 和 “investment bank” 中向量不同 |
| 结构 | 浅层神经网络 | 深层 Transformer |
| 能力 | 捕捉共现关系 | 理解语义、消歧、语法 |
静态 Embedding 仍然有价值:轻量、快速、可解释、适合小数据和边缘设备。很多推荐系统、搜索召回场景仍然用 Embedding 模型。
flowchart LR
subgraph 静态词嵌入
W1[bank] --> V1[固定向量]
end
subgraph 上下文相关嵌入
S1["river bank"] --> C1[向量A]
S2["investment bank"] --> C2[向量B]
end
四、LLM 的内部机制
4.1 模型怎么知道该停下来了?
训练数据每段文本末尾都有一个特殊 token,通常叫 <eos>(End of Sequence)。模型的训练目标是预测下一个 token,所以它会自然学会:当回答完整时,输出 <eos>。
推理时还有辅助规则:
- 达到最大生成长度。
- 输出
<eos>立即停止。 - 检测到重复循环时停止。
4.2 训练时怎么防止偷看未来?
用 Causal Mask(因果掩码)。它是一个上三角矩阵,遮住当前位置右边的 token,让模型只能看到“过去”的信息。
graph TD
subgraph 序列
T1[token1]
T2[token2]
T3[token3]
T4[token4]
end
T1 --> T1
T2 --> T1
T2 --> T2
T3 --> T1
T3 --> T2
T3 --> T3
T4 --> T1
T4 --> T2
T4 --> T3
T4 --> T4
箭头表示“能看到”。token3 看不到 token4,这就是自回归的核心。
4.3 Self-Attention 到底在算什么?
每个 token 都有三个向量:
- Q(Query):我想找什么信息?
- K(Key):我是什么信息?
- V(Value):我的实际内容是什么?
计算步骤:
- Q 和 K 做点积,得到注意力分数。
- 除以
√d_k,防止数值过大导致 softmax 太尖锐。 - softmax 得到权重。
- 用权重对 V 做加权求和。
flowchart LR
X[输入 X] --> Q[Query]
X --> K[Key]
X --> V[Value]
Q --> DOT[Q × K^T]
K --> DOT
DOT --> SCALE[÷ √d]
SCALE --> SOFT[softmax]
SOFT --> MUL[× V]
V --> MUL
MUL --> OUT[输出]
为什么要除以 √d_k? 因为维度越高,点积值越容易变大,softmax 会趋向“只有一个位置是 1,其他都是 0”的极端分布,梯度变小,训练不稳定。
4.4 为什么需要多头注意力?
多个头相当于多个“观察角度”:
- 有的头关注语法结构。
- 有的头关注相邻词。
- 有的头关注长距离依赖。
如果只用一个头,模型只能学一种注意模式,表达能力受限。
4.5 KV Cache:让生成变快的关键
生成文本时,模型是逐 token 生成的。如果没有 KV Cache,每生成一个新 token,都要重新计算前面所有 token 的 Attention,复杂度是 O(L²)。
有了 KV Cache:
- 已经生成过的 token 的 K 和 V 被缓存下来。
- 每次只需要计算新 token 的 Q,再和缓存中的 K、V 做 Attention。
- 复杂度变成
O(L)。
flowchart TB
subgraph 无 KV Cache
A1[生成 token1] --> A2[生成 token2<br/>重算 token1]
A2 --> A3[生成 token3<br/>重算 token1, token2]
end
subgraph 有 KV Cache
B1[生成 token1<br/>缓存 K1,V1] --> B2[生成 token2<br/>只算 Q2 + 读取 K1,V1]
B2 --> B3[生成 token3<br/>只算 Q3 + 读取 K1~V2]
end
为什么只缓存 K 和 V,不缓存 Q? 因为 K、V 来自“已经生成的历史”,是固定的;Q 来自“当前要生成的这个新 token”,每次都要重新算。
4.6 残差连接、LayerNorm、FFN 各有什么用?
- 残差连接(Residual Connection):把子层输入直接加回输出,缓解深层网络梯度消失,让训练更稳定。
- LayerNorm:对每个样本内部做归一化,不依赖 batch 大小,适合 NLP。
- RMSNorm:Llama-3 使用,去掉减均值步骤,计算更快更稳定。
- FFN(前馈神经网络):Attention 负责“看哪里”,FFN 负责“怎么理解”。两者缺一不可。
4.7 为什么大模型做数学题经常不准?
大模型本质是概率模式匹配器,不是计算器:
- 优化目标是“下一个 token 看起来合理”,不是“答案精确”。
- 训练数据里的数学推导质量参差不齐。
- 多步推理会累积误差。
- 没有内建算术引擎。
改善方法:提示工程、CoT(Chain-of-Thought)链式推理、调用外部计算器工具。但无法根治。
4.8 扩展上下文长度会带来的问题
把 8K 模型扩展到 32K,KV Cache 大小会变成 4 倍。同时 Attention 计算量和内存带宽需求也同步增加。
常用做法:
- 位置编码外推:RoPE 可以通过插值扩展范围。
- 继续训练:在长文本上继续训练一段时间,让模型适应新的长度分布。
- 打包训练 + Attention Mask:把多个短样本拼成一条长序列,用块对角掩码阻止它们互相看到。
4.9 Flash Attention 为什么能加速?
Flash Attention 没有减少总计算量,但大幅减少了对 HBM(GPU 显存)的访问。
- 把 Attention 拆成小块,在片上 SRAM 完成计算。
- 融合多个 kernel,减少数据搬运。
- 用 online softmax 增量维护最大值和归一化因子。
4.10 RoPE 比绝对位置编码强在哪?
原始 Transformer 把位置编码加到 Embedding 上,是加法的。RoPE(旋转位置编码)通过旋转 Q、K 向量把位置信息乘进去。
优势:
- 天然编码相对位置信息。
- 具备一定的长度外推能力。
挑战:超长上下文下,旋转角度增长过快,可能出现周期折叠和数值精度问题。
4.11 推测解码:用小模型加速大模型
思路:让小模型快速猜一串 token,大模型一次性批量验证。如果猜对了,直接接受;如果错了,从错的地方用大模型重新生成。
sequenceDiagram
participant User
participant Small as 小模型
participant Large as 大模型
User->>Small: 请生成候选 token
Small->>Large: 提交候选序列
Large->>Large: 一次性验证多个 token
alt 全部正确
Large-->>User: 直接返回候选结果
else 第 k 个错误
Large-->>User: 前 k-1 个接受,从 k 开始重新生成
end
推测解码没有减少总计算量,但减少了“慢的大模型”的运行次数,从而降低延迟。
五、预训练 + 微调:两步范式
大模型不是一开始就会聊天、会做题的。它通常经历两个阶段:
flowchart LR
PT[预训练<br/>海量无标注文本] -->|获得通用能力| FT[微调<br/>指令/人类偏好数据]
FT -->|对齐人类价值观| Model[可用模型]
5.1 预训练让模型获得什么?
- 语言理解与生成能力。
- 世界知识和常识。
- 基本的推理和归纳能力。
- 跨任务泛化能力。
5.2 微调做什么?
- 指令遵循:学会按照用户要求组织答案。
- 问答能力:更准确、简洁、相关地回答问题。
- 对齐人类价值观:减少有害、偏见、违法内容。
这也是 Llama-3 8B 能比 Llama-1 70B 更强的关键原因之一:更好的数据、更优的训练方法、更系统的微调和对齐。
六、文本分类:Embedding 还是生成?
6.1 Embedding + 分类头
流程:
flowchart LR
T[文本] --> M[Embedding 模型]
M --> V[向量]
V --> C[分类头<br/>Linear/MLP]
C --> L[标签]
优点:推理快、成本低、类别可以很多、精度通常稳定。
6.2 生成模型直接分类
把分类任务写成 prompt,让模型直接输出类别文本。例如:
你是情感分析专家。请判断下面电影评论是 positive 还是 negative,只返回标签:
评论:这部电影太精彩了!优点:零样本、少样本能力强,加新类别不用重新训练。 缺点:推理慢、对 prompt 敏感、类别多时容易出错。
6.3 没有标注数据怎么办?
可以把分类变成文本相似度检索:
- 给每个类别写一段自然语言描述。
- 用 Embedding 模型把描述和待分类文本都变成向量。
- 计算余弦相似度,选最相似的类别。
标签描述的技巧:
- 用具体场景描述,而不是抽象词。
- 写成完整短句。
- 包含领域关键词。
- 长度适中(10-20 字左右)。
- 类别之间要有区分度。
6.4 Transformer 为什么比朴素贝叶斯强?
朴素贝叶斯假设:给定类别后,每个词都是条件独立的。这忽略了:
- 词语之间的相关性(如“银行”和“贷款”)。
- 语序信息(“这部电影不好看” vs “这部电影好看”)。
- 否定词、修饰语的语义反转。
Transformer 通过自注意力建模上下文关系,没有强独立性假设,因此表现更好。
七、文本聚类与主题建模
7.1 为什么有了生成式大模型,还需要 Embedding 模型?
生成模型擅长理解和生成,但不擅长:
- 对海量候选做快速相似度检索。
- 低延迟推荐。
- 大规模向量化索引。
推荐系统就是典型例子:先把商品/用户变成向量,再用向量数据库做近邻搜索,效率高、成本低。
7.2 从文档到主题的流程
flowchart LR
Docs[大量文档] --> Prep[预处理]
Prep --> Vec[向量化<br/>TF-IDF 或 Embedding]
Vec --> Cluster[聚类<br/>KMeans / HDBSCAN]
Cluster --> Topic[主题提取<br/>TF-IDF / c-TF-IDF / LLM]
Topic --> Label[人工命名/标签]
7.3 词袋法 vs 文档嵌入
| 特性 | 词袋法 / TF-IDF | 文档嵌入(BERT/SBERT) |
|---|---|---|
| 表示 | 稀疏向量 | 稠密向量 |
| 上下文 | 不考虑 | 考虑 |
| 一词多义 | 不能处理 | 能处理 |
| 资源 | 快速轻量 | 需要模型和算力 |
| 可解释性 | 强 | 弱 |
词袋法在很多简单任务上仍是有效的基线,别急着上深度学习。
7.4 c-TF-IDF 改进在哪?
BERTopic 里的 c-TF-IDF 把统计单位从“文档”改成“主题(簇)”。
- TF:某个词在主题内所有文档合并后的频率。
- IDF:
log(K / df),K 是主题总数,df 是包含该词的主题数。
这样提取出来的关键词更能代表整个主题的共性,而不是单篇文档的特例。
7.5 聚类算法怎么选?
| 算法 | 优点 | 缺点 | 适合 |
|---|---|---|---|
| K-Means | 快、可扩展 | 需指定 K、对噪声敏感、只能找球形簇 | 大规模、簇形状规则 |
| DBSCAN/HDBSCAN | 自动识别噪声、任意形状 | 高维稀疏空间效果差、HDBSCAN 较慢 | 中小规模、噪声多 |
7.6 为什么把聚类和主题表示分开更好?
- 灵活性:聚类方法可以换,主题提取方法也可以换。
- 解释性:先聚类再从每簇提关键词,比联合模型更直观。
- 降噪:聚类只关心语义相似度,主题提取专注于代表性关键词。
7.7 主题关键词重叠怎么办?
可以尝试:
- 用 c-TF-IDF 提升每个主题的代表词独特性。
- 去掉停用词和高频无意义词。
- 合并过细的小簇后重新提取关键词。
- 用 MMR(Maximal Marginal Relevance)兼顾相关性和多样性。
- 换更好的语义嵌入模型。
7.8 BERTopic 离群点太多怎么办?
可能原因:
- 嵌入模型和领域不匹配。
- 文本太短,语义信息不足。
min_cluster_size设置过大。- 语料本身主题分散。
调整方法:减小 min_cluster_size、换 cluster_selection_method='leaf'、使用更适合短文本的嵌入模型(如 SimCSE、MiniLM)。
7.9 检测新兴主题
- 滑动窗口 + 动态聚类:按时间切分数据,追踪主题演化。
- 频率突变监测:统计词频增长率,发现突然火起来的词。
- Embedding 演化分析:新聚类中心远离旧中心,说明出现新主题。
7.10 推荐系统冷启动怎么做?
| 阶段 | 推荐方式 | 方法 |
|---|---|---|
| 冷启动 | 内容理解 | TF-IDF + KMeans / BERTopic |
| 初始推荐 | 主题/相似内容 | 用户兴趣引导 + 主题中心匹配 |
| 有行为数据 | 协同过滤 + 内容 | ItemCF / UserCF + 向量相似度 |
| 数据丰富 | CTR 预估 | FM / DNN / DSSM |
八、写在最后
这篇笔记覆盖了《生成式AI原理与实战 —— Part 1》的 5 个章节。对初级开发者来说,最重要的不是记住每个公式,而是建立下面几个直觉:
- 大模型 = 分词 + 向量 + Transformer + 生成概率。
- Transformer 的核心是 Attention:看哪里(QK)和拿什么信息(V)。
- 生成模型靠自回归逐 token 预测,每次只能看过去,靠 KV Cache 加速。
- 预训练给通识,微调给方向,对齐给安全。
- Embedding 模型在检索、推荐、聚类场景仍然不可替代。
如果你能把这些讲给一位没做过 AI 的后端同事听明白,说明这篇文章的目的就达到了。
参考资料:《生成式AI原理与实战 —— Part 1》