跳到主要内容

从「会写」到「会办事」 — 四道工序,每道配一组可回核的数

这一章讲四件事: 怎么在不掏 80 GB 显存的前提下给大模型「补课」(微调); 补课时为什么只盯着回答算账(损失掩蔽); 怎么教它在两种答法里认准一种(对齐的两条路); 以及怎么给它装上手——调工具、查资料(智能体的两个形态)。

它在全书链条里的位置: 第 20 章造出了那个只会续写的底座; 这一章是全书的落点:同一句提示词进来,出来的不再是独白,而是一个答案、一次操作或一次查证。

需要的基础: 第 20 章的自回归生产线;第 05 章的交叉熵;第 14 章的冻结(把参数设为不再参与训练)与解耦思想。

1. 先看现象:让它概括,它接着写独白

向第 20 章那个预训练完的模型提出请求:「请用一句话概括《罗密欧与朱丽叶》」—— 它多半不给概括,而是顺着自己的老习惯继续写莎翁式独白1。 这不是故障,是训练目标的忠实执行:它从头到尾只练过「接着写」,从没见过「听指令→作答」这个模式。

补这一课的工序叫监督微调(SFT):在成对的「指令—回答」样本上继续训练, 把「被指令并作答」当成一种新的语言模式塞进它的分布里1。 微调之外还有三道工序各管一件事,全章主线一眼:

全章主走查:同一个模型,过四道闸
═══════════════════════════════════════════════════════════════════
输入 第 20 章那个预训练底座 + 「指令→回答」格式的样本
───────────────────────────────────────────────────────────────────
§3-4 ① 微调 挂窄旁路省显存;大小写转换玩具任务 133 步学会格式
§5 ② 掩蔽 只在回答上算损失;题面的位置全部标成忽略号
§6-7 ③ 对齐 老路三步(RLHF)/新路一步(DPO),教会「哪种更好」
§8-9 ④ 上手 想—做—看的循环调工具;先查资料再作答
═══════════════════════════════════════════════════════════════════

2. 全量补课的价签:80 GB 对 16 GB

动手之前先看清为什么不能蛮干。给一个 70 亿级(Llama-7B)的模型做全量微调, 书里的估价是约 80 GB 显存——梯度和优化器状态都按可训练参数走, 粗算是参数量的好几倍,得靠多张数据中心级的卡2。 这笔账直接逼出了下面那道省法。

3. 窄旁路:冻住主干,只训一条细线

做法名字叫 LoRA——一种低秩(把大矩阵拆成两个瘦长小矩阵的乘积)的适配法:原封不动冻结全部预训练权重 W₀, 在旁边并联一条「先降到 r 维、再升回去」的细路——增量 ΔW 拆成两个瘦长矩阵 B(d×r) 和 A(r×d) 的乘积,r 远小于 d3:

输入 x ──► 冻结的大矩阵 W₀ ──────────────┐
│ ├─► 相加 h = W₀x + BAx
└─► A(r×d) → r 维瓶颈 → B(d×r) ────────┘
▲ 只有这条细路上的 A、B 参与训练

好处有三层:参数量从 d² 掉到 2dr(r 通常取 4、8、16), 对一个 d=4096 的线性层就是从约 1 680 万个压到约 6.5 万个,缩水两百多倍4; 训练完还能把 BA 合并回原矩阵,部署时与原模型毫无区别; 每个下游任务只存几 MB 的小附件,一个底座可以挂上百个任务5

按 Llama-7B 的真实规格把账算死(只对注意力的四个投影矩阵注入,r=8)6:

全量微调 7.0B 个参数 ≈ 80 GB 多张 A100/H100
LoRA(r=8) 8.39M 个参数 ≈ 16 GB 一张 RTX 4090 就够
^ 可训练参数只占 0.120%[^7]
换到书里那个 0.84M 的小模型上:可训 0.025M / 总 0.838M = 2.93%[^8]
对照:QLoRA 再叠一层 4-bit 量化基底,显存进一步压到约 8 GB[^9]

还有一个反直觉的初始化细节,它是整条旁路一开始「不存在」的原因: A 用常规随机方式起步,B 直接置成全零——于是 BA=0, 第一步的前向与原模型完全一致,增量从零慢慢长出来7

现成的实现里同样这么写

补充(不在书里,依据我们的 frontier 书架):工程库 peft 的源码与本节代码逐字对应。 依据: shelf=ai-frontier-reference/peft@src:src/peft/tuners/lora/layer.py:343 @5779b17b9a67d9b07b5be75053cb1932b939fd9f 事实=nn.init.zeros_(self.lora_B[adapter_name].weight)——B 权重一律零初始化,旁边一行注释说明 A 按线性层默认方式初始化;注释还给出这一约定出自 LoRA 原论文的 loralib 实现。

4. 主走查①:小模型学一门「格式课」

书里用一个玩具任务演示整套流程:输入小写单词,输出大写 (固定 14 个词的小词表,比如 neural → NEURAL)8。给训好的 nanoGPT 注入 LoRA (先整体冻结,再把 qkv、proj 两类投影包进旁路)9,然后开训10:

主走查数字
════════════════════════════════════════════════
训练 每步现做 8 条样本,一共 200 步,AdamW 学习率 1e-3
曲线 约 133 步,损失从 7 降到 0.4 以下[^14]

考试 问「Convert: neural:」,温度拧到几乎不冒险,
输出「NEURAL」——一字不差[^15]
前提 词表内的词记住了格式;词表外的新词未必泛化,
书里明说那是更大更多样的微调数据的事[^16]
════════════════════════════════════════════════

这门课在工业文档里还有个别名:指令微调——照着一条条指令学作答,说的就是同一件事。

这道闸的要点不在成绩,在姿态:主干一个数没动,2.93% 的旁路参数就够把行为掰过来。

5. 只在回答上算损失:题面的位置全部标成忽略号

SFT 有个容易踩的坑:题干部分本来就轮不到模型负责——预测用户的提问没有意义, 把损失摊上去等于强迫模型背题面。做法是把目标串里属于提示词的位置统一填 -100, 框架的交叉熵见到 -100 就自动跳过不计(这个名字叫损失掩蔽)11:

「Convert: neural:」+「NEURAL\n」拼成一条序列
目标位:[-100,-100,-100,-100 | N,E,U,R,A,L,\n]
↑ 只有这半边会计入损失[^18]

书里这段是示意伪代码,完整的可运行实现在配套笔记本里——但工业库里就是这么实现的, 这正是那句注释对应的源码本体12

补充(不在书里,依据我们的 frontier 书架):损失掩蔽的工程写法与书同款。 依据: shelf=ai-frontier-reference/trl@src:trl/trainer/sft_trainer.py:112 @67dfbe211a07a8dd6ebc1a5af5b75152e10add8e 事实=F.nll_loss(log_p, lbl, ignore_index=-100, reduction="sum")——ignore_index 指到 -100,紧邻注释写明「一块的尾部可能是 -100 填充,ignore_index 让它们的损失归零」。

6. 标准答案里缺的那味药:「哪种更好」

到这里模型已经听话了。但还有一种活它干不了:同一场合两种都对的说法之间,它不认得哪种更得体。 书里举的例子:「今天天气如何」,它可以答「晴朗」,也可以答「我无法预测天气」—— 单靠 SFT 数据,里面根本没有「哪一种更好」的信号,因为监督微调只见标准答案、不见比较13

教科书式的补法分三步,总称叫基于人类反馈的强化学习(RLHF——Reinforcement Learning from Human Feedback,把人的偏好当反馈信号的强化学习)14

第 ① 步,让人来当裁判——同一个问题配两个答案,标注员勾出哪个更好。

第 ② 步,拿这些两两比较训出一个奖励模型(专门给「答案好坏」打分的机器)。

第 ③ 步,用强化学习算法——代表性的是 PPO——让被训模型去最大化那个打分

书里给的是流程;每一步的工程成本,6、7 两节末尾的补充框里各对着源码说了一句。

强化学习那条老路的工程实体

补充(不在书里,依据我们的 frontier 书架):三步里的第 ③ 步在开源(源码公开、人人可查)训练栈里长什么样。 依据: shelf=ai-frontier-reference/verl#06-algorithms.md 事实=该篇拆解记录了 PPO 的标准形态——clip 版策略损失;并且点出代价:PPO 需要一个 critic 网络估计「状态的期望回报」来当基线,critic 与演员一样大,训练成本翻倍且难训。

这条老路能走通,但三步里没有一步是省油的灯。第 7 节会看到把三步压成一步的新走法。

7. 新路:DPO,把三步压成一个对比损失

书里接着给了一条新路线,DPO(直接偏好优化),关键判断是: 上面三步的背后其实藏着一个可以直写的对比损失——不需要单独训奖励模型,也不需要强化学习算法。说白了就是:原来要养一个裁判、再跑一轮强化;现在直接照着偏好数据算损失15:

DPO 的直觉版
════════════════════════════════════════════════
手里:同一个问题的好答案 y_w、差答案 y_l,外加一个
冻住不动的参考模型 π_ref(通常取 SFT 后的副本)
推力:让待训模型多给 y_w 一些概率、少给 y_l 一些
缰绳:每次挪动都跟参考模型比差值,
偏离太远会被拉回来(强度由旋钮 β 控制)[^24]
════════════════════════════════════════════════

那份「缰绳」是这条新路的灵魂:光会变好不算数,必须以「没忘掉原来那个自己」为前提地变好。 完整训练还有批量化和 KL 估计等工程细节,书里建议生产环境直接用现成的训练器, 不要手搓16——那个现成训练器的损失核心长什么样,上面那只补充框已经对着源码指过一行了。

补充(不在书里,依据我们的 frontier 书架):生产级 DPO 的损失核心。 依据: shelf=ai-frontier-reference/trl@src:trl/trainer/dpo_trainer.py:1465 @67dfbe211a07a8dd6ebc1a5af5b75152e10add8e 事实=per_sequence_loss = -F.logsigmoid(self.beta * delta_score)——beta 乘上「好答案相对参考模型的优势减去坏答案的相对优势」,再过 logsigmoid 取负;正是公式 10.4 的逐行对应。

判断(我们的,不是书里的):第 6、7 节真正教的是一件事的两种记账法——「偏好」怎么变成梯度。 RLHF 把偏好折算成一个外部裁判(奖励模型)的分数,DPO 把同一个偏好折算成内部基准(参考模型)的相对概率。 选哪条路主要是工程成本问题:前者贵在要养一个裁判,后者便宜但要小心 β 这根缰绳松紧。 如果错,会错在: 如果两者优化出的分布存在原理性差异(而不只是实现路径差异),那「同一种记账法」就错了。 判据是:同一份偏好数据下,两路的最终胜率曲线是否可以在各自最优超参下重合——书里与论文界都没有给出这条重合证据,判为我们悬而未决。

8. 装「手」:想一步、做一步、看一眼的循环

会答与会办之间还隔着一堵墙:模型的输出只是文字,动手的是外部世界。 升级成**智能体(Agent)**的关键一步,就是不止产文本,还能去调用搜索引擎、执行代码、查数据库17

这种「模型点名某个工具、由外部世界执行、结果再喂回」的机制,行话叫工具调用。

书里演示的框架每一步轮流做三种动作——这就是行话里的推理与行动模式18:

Question: … ← 问题进场


① Thought 模型自言自语:我该先做什么

② Action 发出一次工具调用,如 Calculator("3+5") 或 Search(...)

③ Observation 工具返回的真实结果,喂回给模型 ← 世界替它校对

└── 不满意就回到 ① 继续想,直到模型写出 Answer 才停
(书里的循环上限:max_steps = 5,防失控兜底)[^29]

书里用一台假装的语言模型(mock)把控制流(程序按什么顺序一步步执行的路径)完整跑了两遍:算术题走计算器、事实查询走搜索19。 要留神的一个真问题:换上真的模型后,稳定性取决于提示词能不能让它每次都规规矩矩按 Thought / Action / Observation 的格式吐字——书里把这个留成了思考题20

循环的骨架在生产里什么样

补充(不在书里,依据我们的 frontier 书架):生产级 agent(能自己调工具干活的程序)库的同款循环。 依据: shelf=ai-frontier-reference/smolagents#01-agent-loop.md 事实=MultiStepAgent 用一个 while 循环串起「记忆→消息→模型→行动→观测→回写记忆」,终止条件有两处——模型产出最终答案、或步数撞到 max_steps;错误由系统捕获回灌而不是直接崩掉。

9. 另一只手:答题之前,先去资料库查一遍

还有一种不动参数的升级路子:检索增强生成(RAG)——生成前先「查资料」, 再把查到的原文拼进提示词,让模型照着事实说话21。四步流程:

① 切块 知识库切成小段(chunks),embedding 模型逐段编码成向量
② 入库 向量存进向量数据库(FAISS、Milvus 一类)
③ 检索 用户的问题也编成向量,捞取最相似的前 k 段
④ 拼装 把这 k 段作为上下文接在提示词里,模型照文作答[^33]

书里那份代码里有一处值得盯住的细节:问题和知识段都要先做 L2 归一化, 然后才敢用内积当相似度——归一之后内积恰好等于余弦相似度,量纲齐了排序才有意义22

切块这一步自身是一门手艺,书里没展开,但值得点名:块太大检索不准、太小语义破碎, 主流切法是尽量按完整句子凑到目标大小、块间留一小段重叠; 重叠的意义在于跨块边界的句子不被一刀两断,召回更稳23。 现成的切块器家族则沿复杂度排成一整条阶梯,从按单位硬切一路到让语言模型参与决定在哪切24

判断(我们的,不是书里的):RAG 在这套书里的角色被位置低估了——它是四道工序里唯一不改任何参数的一道。 微调动旁路、对齐动整模、智能体动环境,RAG 连权重都不碰却解决了「模型不知道最新事实」这类问题; 预算紧张时它应当排在第一位试。 如果错,会错在: 如果任务的核心矛盾是行为风格而非事实新鲜度(比如语气、格式服从), 那 RAG 的收益确实有限,排序就不成立。判据是:把「知识更新」换成「风格纠正」的需求, 看 RAG 是否完全使不上劲。

10. 边界与局限

这一章没覆盖的:

没讲什么依据 / 为什么值得知道
完整的 SFT/DPO 生产管线书明确说本节只是最小演示,批量与 KL 细节交给现成训练器25
真模型的工具循环用的是 mock 语言模型;真模型的格式稳定性留成思考题20
多步规划的复杂 agent只有线性单循环,没有多工具编排(把工具按流程串起来调度的那层)与人工确认
RAG 的评估没有「检索质量好不好」的度量环节
RLHF 三步的实现新路 DPO 之外,老路只讲了流程没有代码

出门会撞见的名字:

  • SFT(监督微调)、指令微调 —— 第 1 节;LoRA、adapter —— 第 3 节35;

  • 损失掩蔽 / ignore_index(-100) —— 第 5 节11;

  • RLHF、奖励模型、PPO —— 第 6 节14;DPO、参考模型、KL —— 第 7 节15;

  • Agent、ReAct(推理与行动)、工具调用 —— 第 8 节18;

  • RAG、chunk(切块) —— 第 9 节;存放并检索这些向量的仓库叫向量数据库(FAISS、Milvus 一类),同样见第 9 节26

  • embedding —— 第 9 节那个「把一段文字变成一串数」的编码动作。

11. 可带走的

  1. 「不会听话」不是 bug,是训练目标的必然——它只学过接着写;
  2. 微调先问价签:70 亿参数全量约 80 GB;挂 LoRA 旁路只要 16 GB、可训参数 0.120%;
  3. 旁路的第二个矩阵必须从零开始——保证第一刻起就是原模型本人;
  4. 只在回答上算损失:题面的目标位填 -100,让交叉熵自动跳过;
  5. 「更好」不在标准答案里——偏好信号要么靠人标的优劣对,要么根本没有;
  6. DPO = 免掉奖励模型和强化学习:拿冻住的参考模型当缰绳,β 管松紧;
  7. agent 循环三拍子:想一步(Thought)、做一步(Action)、看结果(Observation),循环上限是必备的保险丝;
  8. RAG 是不改参数的第三条路:切块→入库→检索→拼装,L2 归一化之后内积才是余弦;
  9. 切纸的手艺决定检索的下限:句子优先、留重叠;
  10. 四道工序的顺序有讲究:预算紧就先试不改参数的那道,再动旁路,最后才考虑动整模。

12. 原文地图

主题原书章原文位置
不听话的现象与 SFT 定义第10章 大语言模型与智能体text/11-ch10.txt:774(搜「并不会“听话”」)
全量微调的显存估价第10章 大语言模型与智能体text/11-ch10.txt:850(搜「80GB」)
LoRA 公式与秩约束第10章 大语言模型与智能体text/11-ch10.txt:779(搜「Low-Rank Adaptation」)
缩减倍数第10章 大语言模型与智能体text/11-ch10.txt:784(搜「100∼ 1000 倍」)
瓶颈结构与 d=4096 的账第10章 大语言模型与智能体text/11-ch10.txt:807(搜「65K」)
LoRA 三条工程优势第10章 大语言模型与智能体text/12-fm.txt:6(搜「推断无开销」)
B 矩阵零初始化第10章 大语言模型与智能体text/11-ch10.txt:799(搜「B 保持全 0」)
Llama-7B 参数账第10章 大语言模型与智能体text/11-ch10.txt:845(搜「0.120%」)
注入小模型的账第10章 大语言模型与智能体text/11-ch10.txt:892(搜「2.93%」)
QLoRA 行第10章 大语言模型与智能体text/11-ch10.txt:866(搜「QLoRA」)
玩具任务词表第10章 大语言模型与智能体text/11-ch10.txt:930(搜「'transformer'」)
注入前的整体冻结第10章 大语言模型与智能体text/11-ch10.txt:888(搜「先冻结整个预训练模型」)
133 步的训练曲线第10章 大语言模型与智能体text/11-ch10.txt:957(搜「第 133 步」)
单次考试通过第10章 大语言模型与智能体text/11-ch10.txt:948(搜「NEURAL」)
泛化边界的坦白第10章 大语言模型与智能体text/11-ch10.txt:951(搜「未必泛化」)
-100 的掩蔽规则第10章 大语言模型与智能体text/11-ch10.txt:905(搜「-100」)
拼 batch 的函数第10章 大语言模型与智能体text/11-ch10.txt:907(搜「build_sft_batch」)
天气例子与信号缺失第10章 大语言模型与智能体text/12-fm.txt:17(搜「无法预测天气」)
RLHF 三步第10章 大语言模型与智能体text/12-fm.txt:22(搜「收集人类偏好数据」)
DPO 关键想法第10章 大语言模型与智能体text/12-fm.txt:26(搜「不再需要单独训练奖励模型」)
参考模型与 β第10章 大语言模型与智能体text/12-fm.txt:31(搜「偏离参考模型的强度」)
生产建议 trl.DPOTrainer第10章 大语言模型与智能体text/12-fm.txt:46(搜「DPOTrainer」)
智能体的关键一步第10章 大语言模型与智能体text/12-fm.txt:51(搜「不止能产文本」)
三种动作的定义第10章 大语言模型与智能体text/12-fm.txt:55(搜「自言自语」)
循环实现与上限第10章 大语言模型与智能体text/12-fm.txt:62(搜「react_loop」)
mock 演示的两个例子第10章 大语言模型与智能体text/12-fm.txt:59(搜「mock LLM」)
真模型的格式思考题第10章 大语言模型与智能体text/12-fm.txt:151(搜「稳定按」)
RAG 的定义与流程第10章 大语言模型与智能体text/12-fm.txt:86(搜「切成小段」)
L2 归一化与内积第10章 大语言模型与智能体text/12-fm.txt:91(搜「L2归一化」)
本章小结速查表第10章 大语言模型与智能体text/12-fm.txt:112(搜「关键技术速查」)

Footnotes

  1. 出处:「第10章 大语言模型与智能体」第 773–777 段(text/11-ch10.txt:774,搜「并不会“听话”」)。原文:预训练完成的语言模型并不会「听话」:让它「请用一句话概括《罗密欧与朱丽叶》」,它多半会继续按训练语料的风格写莎翁式独白,而不是给出概括;要让模型学会「按指令行事」,需要监督微调(Supervised Fine-Tuning,SFT):在「指令-回答」样本对 (x, y) 上继续训练,让模型把「被指令并作答」作为一种新的语言模式纳入分布。 2

  2. 出处:「第10章 大语言模型与智能体」第 778–781 段(text/11-ch10.txt:778,搜「80 GB 显存」)与表 10.3 备注列(text/11-ch10.txt:850,搜「多卡」)。原文:对一个 7B 级别的大模型做全量微调代价昂贵——Llama-7B 大致需要约 80 GB 显存(FP16+AdamW 要存 4× 参数量,通常需要多卡 A100);LoRA 只需约 16 GB,一张消费级显卡(RTX 4090)就能跑。

  3. 出处:「第10章 大语言模型与智能体」第 779–783 段(text/11-ch10.txt:779,搜「Low-Rank Adaptation」)。原文:低秩适配(Low-Rank Adaptation,LoRA)只更新少量参数:冻结预训练权重 W₀,只学习一个低秩增量 ΔW=BA,其中 A∈ℝ^{r×d}、B∈ℝ^{d×r},秩 r≪d;前向变为 h=W₀x+BAx。 2

  4. 出处:「第10章 大语言模型与智能体」第 784–786 段(text/11-ch10.txt:784,搜「100∼ 1000 倍」)与第 807 段(text/11-ch10.txt:807,搜「65K」)。原文:参数量从 d² 降到 2dr,通常缩减 100~1000 倍;r 通常取 4、8、16,对一个 d=4096 的 Llama 线性层来说,参数量从 4096²≈16.8M 降到 2·4096·8=65K——缩小约 256 倍。

  5. 出处:「第10章 大语言模型与智能体」第 3–12 段(text/12-fm.txt:6,搜「推断无开销」)。笔记框原文:LoRA 成功的关键并不只是参数量,还有三个工程优势——推断无开销:训练完成后可以把 BA 合并回 W₀,部署时和原模型完全一样;切换任务零成本:每个下游任务只存一个小 LoRA adapter(约几 MB),同一个底模可以挂上百个任务的 adapter;易组合:多个 LoRA 可以加权叠加(Civitai、HuggingFace 已形成庞大社区)。 2

  6. 出处:「第10章 大语言模型与智能体」第 827–845 段(text/11-ch10.txt:834,搜「lora_r = 8」)。代码与输出:d_model=4096、n_layers=32、vocab=32000;通常只对 attention 的 Q/K/V/O 四个矩阵加 LoRA,每个矩阵参数量=2·d·r;lora_params=n_layers·4·2·d_model·r=8.39M;打印:Llama-7B 全量微调参数 7.0B,LoRA-8 训练参数 8.39M,LoRA/Full=0.120%。

  7. 出处:「第10章 大语言模型与智能体」第 794–799 段(text/11-ch10.txt:799,搜「B 保持全 0」)。代码注释:# B 保持全 0:训练开始时 BA=0,等价于原模型;A 用 kaiming_uniform 方式初始化。

  8. 出处:「第10章 大语言模型与智能体」第 925–934 段(text/11-ch10.txt:925,搜「大小写转换」)。原文与代码:用「大小写转换」玩具任务(输入小写、输出大写)演示 SFT 流程;WORDS 是 ['hello','world','pytorch','transformer','language','model','small','cat','dog','machine','learn','deep','neural','net'] 共 14 个词的固定小词表。

  9. 出处:「第10章 大语言模型与智能体」第 868–891 段(text/11-ch10.txt:888,搜「先冻结整个预训练模型」)。代码:训练完的 model 上加 LoRA 前,先用 for p in model.parameters(): p.requires_grad=False 冻结整个预训练模型,确保只训练注入的 LoRA 增量;apply_lora_to_model 默认 target_names=('qkv','proj')。

  10. 出处:「第10章 大语言模型与智能体」第 936–947 段(text/11-ch10.txt:937,搜「lr=1e-3」)。代码:优化器 AdamW,lr=1e-3,只用 requires_grad 为真的参数;每步 gen_pair() 造 8 条样本,train 200 步。「每步现做 8 条」是对 batch 生成方式的转述。

  11. 出处:「第10章 大语言模型与智能体」第 903–906 段(text/11-ch10.txt:905,搜「-100」)。原文:SFT 训练时只在回答部分计算损失——提示词部分的词元是「输入条件」,让模型预测它没有意义;具体做法是把 targets 里提示词部分的位置填 -100,PyTorch 的 cross_entropy 会自动忽略 -100 的位置。「损失掩蔽」之名借用自社区的通行说法。 2

  12. 出处:「第10章 大语言模型与智能体」第 927–928 段(text/11-ch10.txt:927,搜「示意伪代码」)。原文:以下为示意伪代码,省略分词与 padding 细节,完整可运行实现见配套 notebook。

  13. 出处:「第10章 大语言模型与智能体」第 16–18 段(text/12-fm.txt:17,搜「无法预测天气」)。原文:SFT 让模型「能按指令回答」,但还不能让它在多种风格里表达明确的偏好——例如同样面对「今天天气如何」,模型可能答「晴朗」,也可能答「我无法预测天气」;单纯的 SFT 数据本身并不包含「哪一种更好」的信号。

  14. 出处:「第10章 大语言模型与智能体」第 19–24 段(text/12-fm.txt:22,搜「收集人类偏好数据」)。原文:基于人类反馈的强化学习(RLHF)的经典做法分为三步:收集人类偏好数据 (x, y_w, y_l)(同一个提示词,标注员认为回答 y_w 比 y_l 更好);用偏好数据训练奖励模型 r_φ(x,y);用 PPO 等 RL 算法优化模型最大化奖励。 2

  15. 出处:「第10章 大语言模型与智能体」第 25–27 段(text/12-fm.txt:26,搜「不再需要单独训练奖励模型」)。原文:直接偏好优化(Direct Preference Optimization,DPO)的关键想法是:上述三步背后其实可以推导出一个等价的对比损失——不再需要单独训练奖励模型,也不再需要 RL 算法。 2

  16. 出处:「第10章 大语言模型与智能体」第 44–47 段(text/12-fm.txt:47,搜「最小演示」)。笔记框原文:本节的代码只是 DPO loss 的最小演示;批量化、KL 估计、参考模型管理交给生产工具。

  17. 出处:「第10章 大语言模型与智能体」第 49–52 段(text/12-fm.txt:51,搜「不止能产文本」)。原文:要把语言模型升级为智能体(Agent),关键一步是让它不止能产文本,还能与外部世界交互——例如调用搜索引擎、执行代码、查询数据库等。

  18. 出处:「第10章 大语言模型与智能体」第 53–58 段(text/12-fm.txt:57,搜「Observation」)。原文:推理与行动框架在每一步交替进行三种动作——Thought:模型自言自语推理;Action:调用一个工具(比如 Search(...)、Calculator(...));Observation:工具返回的结果,输入回模型;直到模型输出最终的 Answer 才停下。 2

  19. 出处:「第10章 大语言模型与智能体」第 59–61 段(text/12-fm.txt:59,搜「mock LLM」)。原文:配套 notebook 用一个 mock LLM 演示了推理与行动的完整控制流,覆盖算术题(调用 Calculator)和事实查询(调用 Search)两个示例。

  20. 出处:「第10章 大语言模型与智能体」第 149–152 段(text/12-fm.txt:151,搜「稳定按」)。思考框原文:本章使用模拟大语言模型演示推理与行动;如果换成真实模型(例如本地 ollama 托管的 Llama 3),该如何设计提示词,才能让模型稳定按 Thought/Action/Observation 格式输出? 2

  21. 出处:「第10章 大语言模型与智能体」第 82–89 段(text/12-fm.txt:84,搜「查资料」)。原文:主动调工具之外,智能体的另一种常见模式是检索增强生成(RAG)——在生成前先「查资料」,再把检索到的内容拼回提示词,让模型基于事实作答;随后列出四步流程。

  22. 出处:「第10章 大语言模型与智能体」第 90–96 段(text/12-fm.txt:91,搜「L2归一化」)。代码注释:# 为了用内积衡量余弦相似度,先做 L2 归一化;q_vec=F.normalize(embed_model(question), dim=-1);kb_embeddings 入库时也统一做过 L2 归一化;sims=kb_embeddings @ q_vec 后 topk。「内积即余弦」是我们按归一化性质的补充说明。

  23. 补充(不在书里,依据我们的 frontier 书架):切块的取舍与重叠写法。依据: shelf=ai-frontier-reference/llamaindex#02-ingestion-chunking.md 事实=SentenceSplitter 尽量按完整句子凑到目标 token 数,开新 chunk 时从上一个 chunk 末尾回填一段作为 overlap;重叠的意义是跨块边界的句子不至于被一刀两断,检索召回率更稳;该篇开头同时给出「块太大检索不精准、块太小语义破碎」的两难。「主流切法」一句取材于它。

  24. 出处:同上(shelf=ai-agent-reference/chonkie#01-chunkers.md)。事实=Chonkie 提供 11 种切块器覆盖从 token 切块到语义/LLM 决策的完整阶梯,共享 BaseChunker 骨架。

  25. 出处:「第10章 大语言模型与智能体」第 145–147 段(text/12-fm.txt:146,搜「100∼200 行」)与实战提示框(text/12-fm.txt:139,搜「trl.SFTTrainer」)。原文:本章把这些技术的核心思想各自抽出来,用 100~200 行代码完整呈现——读者把原理走通后再切换到工业级框架(trl、LangChain、LlamaIndex 等)即可;实战提示:生产环境的 SFT 通常使用 trl.SFTTrainer 或基于 Trainer 自定义循环;DPO 建议使用 trl.DPOTrainer;RAG 常配合 LangChain、LlamaIndex 以及 FAISS、Milvus、Chroma 等向量库。

  26. 出处:「第10章 大语言模型与智能体」第 86–101 段(text/12-fm.txt:86,搜「切成小段」)。原文与代码:把知识库切成小段(chunks),用 embedding 模型逐段编码成向量;向量入库(FAISS、Milvus 等);用户提问时把问题也编码,从向量库中检索 Top-k 相似 chunks;把检索结果作为上下文拼到语言模型的提示词中。