对应原课:CMU 11-667 Fall 2025 · Lecture 11 · Tue 30-Sep-2025 · Retrieval-augmented generation(客座:Akari Asai,CMU / Ai2) 原课 slides:Retrieval and Retrieval-Augmented Generation(改编自 ACL 2023 教程 Retrieval-based Language Models and Applications(Asai、Min、Zhong、Chen),以及 Graham Neubig 的 Advanced NLP Fall 2024) 阅读材料:Lewis et al. (2020), Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks;Khandelwal et al. (2020), Generalization through Memorization: Nearest Neighbor Language Models(kNN-LM);Mallen et al. (2023), When Not to Trust Language Models: Investigating Effectiveness of Parametric and Non-Parametric Memories;Asai et al. (2024), Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection 配套代码:code/lecture11/(1 个模块 + 5 个演示脚本;第一次运行要训练 5 个模型,共约 3 分钟) 本讲的写法:骨架来自原课 slides 的三部分(文档库、检索器、语言模型与流水线);“花园百科”是补充的,对应原课 HW3 的后半(训练检索器、搭建 RAG)。所有数字都来自配套代码的实际输出。
目录
- 0. 本讲导读
- 1. 参数里的知识:热门的记得住,冷门的记不住
- 2. 检索增强:文档库 + 检索器 + 语言模型
- 3. 文档库:来源、切块、规模
- 4. 检索器:稀疏、稠密、重排序
- 5. 先检索、再阅读
- 6. 其他用法:中间融合与输出插值(kNN-LM)
- 7. 近期进展:让模型自己决定检索和批判
- 8. 小结、常见误区、练习
0. 本讲导读
0.1 这一讲要回答的问题
第 10 讲最后的法律例子说明:给 LLM 接上检索,能大幅减少”编造”。这一讲把这件事讲透:
- 语言模型把知识存在参数里,哪些知识它记得住、哪些记不住?不知道时它会怎样?
- 一个检索增强的语言模型由哪三部分组成?每一部分有哪些设计选择?
- 检索器有哪几类(稀疏、稠密、重排序)?怎样训练、怎样评估?它们各自栽在哪里?
- 检索到的段落怎样交给语言模型——拼进输入、在中间层融合、还是在输出端插值?
- 检索什么时候帮忙、什么时候反而有害?模型能不能自己判断”该不该检索""资料有没有用”?
0.2 学完这一讲你应该能
- 用”知识在预训练语料里出现的次数”解释参数化知识的长尾问题,说出幻觉和知识过时的来源;
- 画出 RAG 的三个部件(文档库、检索器、语言模型),说出 RAG 的三个好处;
- 计算 BM25 和 nDCG@10,写出稠密检索的对比学习损失,比较稀疏、稠密、交叉编码器重排序;
- 区分输入增强(RAG)、中间融合(RETRO)、输出插值(kNN-LM),写出 RAG 的边缘化公式和 kNN-LM 的插值公式;
- 说出简单 RAG 的四个局限(不必要的检索、被无关上下文带偏、输出缺少引用支持、延迟),以及自适应检索和 Self-RAG 怎样应对。
0.3 本讲的实验平台:花园百科
rag_world.py 造了一个”知道每条知识在语料里出现了几次”的世界:
- 400 位园丁,名字是”名 + 独一无二的造词姓氏”(例如 Ines Ronus、Tova Sur);20 个名字被很多人共用,姓则一人一个。每位园丁有三条事实:住在哪个镇(16 个镇,大镇更常见,最大的 Ashby 约占 20%)、种什么(35 种植物)、养什么(8 种动物)。
- 流行度服从 Zipf 定律:排第 r 位的园丁被提到的概率 ∝ 。最热门的 Ines Ronus 的住址出现在 2732 篇文档里,排第 100 位的 20 篇,排第 399 位的 4 篇。
- 预训练语料(“网页”):18000 篇传记 + 24000 篇新闻,随机打乱:
传记:Tova Zind grows fig . Tova Zind keeps dog .
新闻:Rosa Gek sold pumpkin to Ada Kamen .
新闻:Jude Zemal walked rabbit with Ines Ronus . Jude Zemal walked rabbit with Ines Ronus .
新闻里的镇、植物、动物都是随机的,和谁住哪儿、种什么无关——它们是天然的”干扰项”;一半的新闻把那句话原样再说一遍(§5.1 会解释为什么需要它)。COUNTS 记录每条事实出现在几篇传记里,这就是本讲的”流行度”(Kandpal et al. 2023 的做法:数相关文档)。
- 文档库(“百科全书”):85% 的园丁有一篇百科条目(三条事实都在,16 个 token),外加 3000 篇新闻。
- 测试:每 4 位园丁取 1 位(共 100 位)留作”读者训练集”,其余 300 位 × 3 个关系 = 900 条测试事实。按流行度分桶:0 次 23 条、1~2 次 153 条、3~9 次 462 条、10~29 次 166 条、≥30 次 96 条。
模型是第 2 讲的因果 Transformer:small(d=64、2 层,约 10 万参数)和 large(d=128、4 层,857,088 个参数)。和真实 LLM 预训练一样,每篇文档只看一遍,所以”出现几次”就是”见过几次”。
1. 参数里的知识:热门的记得住,冷门的记不住
1.1 参数化语言模型
slides 从最熟悉的图开始:语言模型 在预训练数据上学会 。问它 “ChatGPT is developed by”,它给 OpenAI 0.52、Google 0.31……知识全部存在参数里——这叫参数化记忆(parametric memory)。
问题是,参数里的知识有三个毛病:
- 幻觉(hallucination):slides 里,ChatGPT-4o(2025 年 2 月)被问到 Akari Asai 的论文,列出的论文”不是我的”、发表的会议也是错的;问 “Who is Akari Asai?”,模型可能回答”一位日本声优”(同名的人)。
- 长尾知识:Mallen et al. (2023) 的 PopQA 发现,LM 在冷门实体上的准确率很低——越不出名,越答不对。
- 知识过时:参数停留在训练数据截止的那一刻。问 “Who developed GPT4o?”,2023 年收集数据的模型回答”没有叫 GPT4o 的模型”(RealTimeQA,Kasai et al. 2023)。
1.2 实验:准确率 vs 流行度
代码 01 §2:闭卷问法是给模型 “Ines Ronus lives in”,看它接下来说哪个词(和 LAMA 探针一样)。
| 模型 | 总体 | 0 次 | 1~2 次 | 3~9 次 | 10~29 次 | ≥30 次 |
|---|---|---|---|---|---|---|
| small(约 10 万参数) | 35.9% | 8.7% | 14.4% | 23.6% | 57.8% | 97.9% |
| large(约 85 万参数) | 59.8% | 8.7% | 22.2% | 53.9% | 94.6% | 100.0% |
这就是 Mallen et al. 那张图的形状:一条事实见过 30 次以上,两个模型都几乎全对;见过 1~2 次,大模型也只答对两成多。把模型做大,主要提升的是中间几档(3~29 次)。Kandpal et al. (2023) 统计了真实预训练语料里”问题和答案同时出现的文档数”,看到同样的单调关系,并外推出:要把只出现几次的知识学好,模型得大好几个数量级。
代码 01 §5:多训练几遍呢?
| large | 总体 | 0 次 | 1~2 次 | 3~9 次 | 10~29 次 | ≥30 次 |
|---|---|---|---|---|---|---|
| 1 遍 | 59.8% | 8.7% | 22.2% | 53.9% | 94.6% | 100.0% |
| 3 遍 | 96.2% | 13.0% | 90.8% | 100.0% | 100.0% | 100.0% |
训练 3 遍 = 每条事实多见两次,“见过 1~2 次”那一档从 22% 跳到 91%——决定记不记得住的是”见过几次”。但从没出现过的事实(0 次)怎么训练都学不会,而真实世界里这样的知识要多少有多少(新闻、私有文档、昨天发生的事)。
我写代码时的第一版在同一份语料上训练了 10 遍,结果只出现过一次的事实也全都答对——那其实是”见过 10 次”。真实的 LLM 预训练大多只过一遍数据,才有长尾问题。(代码 README 第 1 条)
1.3 实验:它知道自己不知道吗?
代码 01 §3(large):
| 流行度 | 准确率 | 平均置信度 | 答错且置信度 > 0.5 |
|---|---|---|---|
| 0 次 | 8.7% | 0.31 | 17.4% |
| 1~2 次 | 22.2% | 0.33 | 9.2% |
| 3~9 次 | 53.9% | 0.41 | 3.9% |
| 10~29 次 | 94.6% | 0.70 | 0.0% |
| ≥30 次 | 100.0% | 0.94 | 0.0% |
两件事同时成立:
- 置信度随流行度下降,模型多少”感觉到”自己不熟——这是 §5.4”按置信度决定要不要检索”的依据;
- 但它永远会给出一个答案。见过 0~2 次的住址答错时,它最常说 Ashby(28%)——最大的镇。没见过的事实,它按先验猜,说出来和真的一样流利。例:
Rosa Muxol keeps ▶ goat(置信度 0.42;正确答案 cat)。
这就是幻觉的来源:语言模型的训练目标是”预测最可能的下一个词”,里面没有”我不知道”这个选项。
1.4 实验:世界变了
代码 01 §4:两成园丁搬了家(World.updated(0.2))。测试集里搬了家的 54 位园丁,模型说出旧地址 68.5%、新地址 1.9%。要更新参数里的知识,得重新训练或编辑参数(知识编辑,例如 ROME);而 RAG 只要更新文档库——§7.3 会检验读者是否真的”信”新资料。
2. 检索增强:文档库 + 检索器 + 语言模型
2.1 直觉
slides 的直觉例子:问 “Who is Akari Asai?”,闭卷的 LM 回答”日本声优”;先检索到一段资料(“Akari Asai is a Ph.D. student in the Paul G. Allen School…”),再回答,就说对了。RAG 的三个好处:
- 减少幻觉:答案有资料可依;
- 不重新训练就能更新知识:更新文档库即可(GPT4o 的例子);
- 可验证:答案可以附上出处,用户能核对。
工业界已经大量采用:slides 引用 Databricks 的数据——60% 的 LLM 应用用了某种形式的 RAG。
2.2 三个部件
- 文档库(datastore):大量文档的集合——维基百科、代码、论坛……(§3)
- 检索器(retriever):按相似度 从文档库里取出前 k 篇(§4)
- 语言模型:读 和 ,生成 (§5–7)
slides 的例子:问 “Which company developed GPT4o?”,三篇文档的相似度分别是 0.9(GPT-4o is a pre-trained transformer developed by OpenAI)、0.1(Transformers 系列电影)、0.8(GPT4o was released by OpenAI in May 2024),取前两篇交给 LM,回答 OpenAI。
下面三节按这三个部件展开。
3. 文档库:来源、切块、规模
3.1 用什么做文档库
选对文档库很重要。问”哪家公司开发了 GPT4o”,英文维基百科(Chen et al. 2017、Lewis et al. 2020 等大量工作的选择)就够了;问”怎样用 LlamaIndex 实现 RAG”,需要的是代码片段、官方文档、社区论坛(CodeRAG-Bench,Wang et al. 2025)。
规模:MassiveDS(Shao et al. 2024)把文档库从维基百科的 50 亿 token 扩到 1.4 万亿 token(22 TB),检索增强的语言模型随文档库变大而持续变好——但存储、索引、检索的工程挑战也随之而来。
3.2 怎样处理文档
slides 的三步:
- 整理与预处理:HTML → 纯文本(第 3 讲的清洗流水线);
- 切块(chunking):按段落(换行符)切,或每 k 个词切一块(常见 100~250 个词);
- 后处理:去掉太短的块、去重、过滤乱码。
3.3 实验:同一个文档库,三种切法
代码 02 §1:查询是测试集里有条目的园丁 × 3 个关系 = 768 个问题(例如 “where does Ines Ronus live ?”);“正确的块”= 完整包含答案那句话的块;检索器都是 BM25。
| 切块方式 | 块数 | 平均长度 | 没有正确块的问题 | R@1 | R@5 | nDCG@10 | MRR |
|---|---|---|---|---|---|---|---|
| 整篇文档 | 3340 | 8.8 | 0 | 1.000 | 1.000 | 1.000 | 1.000 |
| 按句子 | 4020 | 7.3 | 0 | 0.333 | 0.990 | 0.707 | 0.608 |
| 每 8 个词 | 3680 | 8.0 | 256 | 0.333 | 0.659 | 0.533 | 0.489 |
- 整篇文档:问题里的姓只在这位园丁的条目里出现三次,BM25 一找一个准。代价是每块更长,读者要读的字更多。
- 按句子:这位园丁的三句话都含有名字,BM25 分不出哪句讲”住址”——问题里的 live 和句子里的 lives 不是同一个词(练习 1 会算出为什么 R@1 恰好是三分之一)。
- 每 8 个词:不顾句子边界,三分之一的问题根本没有完整的答案块。
切块是检索的单位,它决定了检索器能找到什么、读者要读多少。块太碎,相关性信号不够;块太大,读者被块里的其他内容干扰、上下文也更贵(§5.5)。
4. 检索器:稀疏、稠密、重排序
4.1 三类检索器
| 稀疏检索器 | 稠密检索器 | 重排序器 | |
|---|---|---|---|
| 相似度 | 基于词频的向量 | 预训练 LM 编码的稠密向量 | 查询和文档一起编码后打分 |
| 训练 | 不需要 | 需要* | 需要* |
| 例子 | TF-IDF、BM25 | DPR、Contriever、ColBERT | 交叉编码器(cross-encoder) |
(*也有无监督训练的版本。)
4.2 稀疏检索:TF-IDF 与 BM25
最简单的表示是独热向量:每个维度是一个词,查询或文档里出现了就是 1。接着用词频代替 0/1,再用 IDF 给罕见的词更大的权重:
是文档总数, 是含有词 的文档数。BM25(Robertson & Zaragoza 2009)在此基础上加了词频饱和和长度归一化:
- 从 1 到 2 的提升大于从 10 到 11( 控制饱和得多快,常取 1.2);
- 长文档的词频要打折扣( 控制打多少,常取 0.75)。
稀疏检索的局限:它是”词袋”——不懂语义相似(live 和 lives、pet 和 keeps 对它来说毫无关系)。
4.3 稠密检索
把查询和文档各自编码成一个向量,用内积排序:
编码器常取掩码 LM 的 [CLS] 输出(DPR,Karpukhin et al. 2020),或对全部输出向量做均值 / 最大池化(SBERT、SGPT)。文档向量可以预先算好存进索引,查询时只编码查询。
快速近邻搜索:千万级以内,精确搜索(矩阵乘法)仍然很快;再大就用近似搜索(FAISS 的倒排、HNSW 图),用量化压缩索引——拿一点精度换速度和内存。
训练:对比学习(第 10 讲 §5):
负例来自同一批里其他查询的正例(批内负例),以及同一个或另一个模型检索到的困难负例(DPR 用 BM25 的结果)。
无监督训练:Contriever(Izacard et al. 2022)不需要标注的(问题, 段落)对——从同一篇文档里随机截两段(independent cropping)当正例。BEIR 上,无监督训练的检索器在训练分布之外更稳健。
指令微调的检索器(TART,Asai et al. 2023):把任务说明写进查询(“找一段回答这个问题的维基百科段落” vs “找一段相似的代码”),同一个检索器按指令检索不同的东西。
4.4 重排序:交叉编码器
双编码器(bi-encoder)分别编码查询和文档,两者只在最后做一次内积,交互是”浅”的;交叉编码器把查询和文档拼在一起送进模型,每一层都能互相注意,打分更准,但每个(查询, 文档)对都要跑一次模型,无法预先算好。所以实践中是两阶段:稀疏 / 稠密检索召回几百篇,交叉编码器重排序前几十篇。
4.5 评估
- 无序的检索结果:精确率、召回率;
- 有序的结果:Recall@k、MRR,以及 BEIR 的主要指标 nDCG@10:
- 基准:BEIR(Thakur et al. 2021,18 个零样本检索数据集)、MTEB(Muennighoff et al. 2022,嵌入模型的综合基准,有公开排行榜)。slides 总结 BEIR 的结果:加交叉编码器重排序有帮助;稠密检索器在分布外可能很吃力;无监督训练有助于分布外。
4.6 实验:BM25 vs 稠密 vs 混合
代码 02 §2:按句子切块(BM25 最吃亏的那种)。稠密检索器用第 10 讲的 BowEncoder(词向量平均 → 线性层),在 84 位”读者训练集”园丁的 504 个(问题, 正确句子)对上做 InfoNCE 训练,每个关系用两种问法(“where does … live ?”、“which town is home to … ?”)。测试的是另外那些园丁——名字从没在检索器的训练里出现过——分两种问法:训练里见过的第一种,和从没见过的第三种(“in which town does … live ?”、“what animal is kept by … ?”)。
| 检索器 | 新园丁·见过的问法 R@1 / nDCG@10 | 新园丁·没见过的问法 R@1 / nDCG@10 |
|---|---|---|
| BM25 | 0.333 / 0.707 | 0.661 / 0.875 |
| 稠密(64 维) | 0.993 / 0.997 | 0.384 / 0.568 |
| 混合(标准化后相加) | 1.000 / 1.000 | 0.915 / 0.967 |
- 见过的问法:稠密检索器学会了 live ↔ lives in、grow ↔ grows,知道问的是哪个关系;对没见过的名字也找得准——查询和句子里是同一个姓,两边用同一个词向量,点积里天然有”自己和自己”的相似度。
- 没见过的问法:“kept by""planted by”里的新词带着从没训练过的随机词向量,冲淡了名字的信号:稠密检索器有 34% 的问题找到了”讲同一个关系的句子”,却是别的园丁的。BM25 反而变好了:in which town 里的 in 恰好和 lives in 字面重合。
- 两者的错误互补:BM25 锁定了是哪位园丁,稠密检索器补上”问的是哪个关系”,混合检索远好于任何一个。这就是 BEIR 上反复看到的现象:稠密检索器在训练分布之外常常不如 BM25;稀疏 + 稠密的混合是最常用的稳健做法。
第一版实验里,测试问题和训练问题用的是同一种问法,稠密检索器看起来近乎完美(99%)。换成没见过的问法,才看到它的脆弱。评估检索器时,测试查询的分布和训练查询一样重要。(代码 README 第 3 条)
4.7 实验:向量的瓶颈
代码 02 §3:问法都是训练里见过的那种,区别只在于这位园丁有没有在检索器的训练里出现过。
| 向量维度 | 训练集里的园丁 R@1 | 新园丁 R@1 | 新园丁:混合 R@1 |
|---|---|---|---|
| 8 | 87.7% | 52.1% | 91.4% |
| 16 | 98.8% | 80.2% | 97.3% |
| 32 | 99.6% | 91.0% | 98.4% |
| 64 | 100.0% | 99.3% | 100.0% |
一个定长向量要装下整段话的意思。维度够大时,每个姓都能保留自己的方向;维度小了,检索器训练时专门拉开过的名字还分得清,没见过的名字就开始互相混淆。这对应真实世界的观察:稠密检索器在以冷门实体为中心的问题上常常输给 BM25(Sciavolino et al. 2021,“Simple Entity-Centric Questions Challenge Dense Retrievers”)。真实的稠密检索器要把几百个 token 压进 768 维,冷门实体的名字(往往被切成好几个子词)更容易被”挤掉”。
5. 先检索、再阅读
5.1 怎样使用检索结果:三个问题
slides 把检索增强 LM 按三个问题分类:
- 检索什么:文本块(段落)?token?别的东西?
- 什么时候检索:每个问题一次?每隔几个 token?每个 token?
- 怎样使用:
| 输入增强 | 中间融合 | 输出插值 | |
|---|---|---|---|
| 做法 | 把检索结果拼进 LM 的输入 | 修改 LM,在中间层融入检索结果 | 直接修改输出的 token 分布 |
| 优点 | 容易使用(不训练也行)、有效 | 能扩展到很多段落 | 不需要训练* |
| 缺点 | 难以使用很多段落 | 需要重新训练 | 在一些任务上效果有限 |
| 例子 | RAG | RETRO、InstructRETRO | kNN-LM |
这一节讲输入增强,§6 讲另外两种。
5.2 RAG(Lewis et al. 2020)与它的训练
“RAG”这个名字来自 Lewis et al. (2020):检索器(DPR)取出 top-k 段落 ,生成器(BART)在每个段落的条件下生成,按检索分数边缘化:
(这是 RAG-Token 的形式:每个 token 都对段落求和;RAG-Sequence 对整个输出序列求和一次。)训练时最小化 ,检索器的查询编码器和生成器一起更新——检索器从”哪个段落让答案更好生成”里得到信号,不需要段落级的标注。
slides 把 RAG 的训练方式分成三类:
- 独立训练:检索器和 LM 各练各的(DrQA、DPR + 任意阅读器);
- 顺序训练:先固定一个、再训练另一个(REPLUG 用 LM 的反馈训练检索器;Evidentiality Generator);
- 联合训练:RAG、REALM(文档向量异步更新)。
今天人们说”RAG”,多半指”检索 + 现成的 LLM”:不训练任何东西,把检索到的段落写进提示。这之所以可行,是因为大模型本来就会”读”。
5.3 实验:先教会小模型”读”
我们的小模型不会”读”。读者(reader)= 闭卷模型(large)在 7200 条”检索到的资料 + 问题 → 答案”上微调(只用 100 位读者训练集园丁,只在答案上算损失),同时回放 4000 篇预训练文档。输入长这样:
<ctx> Jude Riskem lives in Pebworth . Jude Riskem grows poppy . Jude Riskem keeps pony . <sep> Jude Zemal walked cat with Jude Riskem . </ctx> Jude Riskem lives in ▶ Pebworth
读者起初怎么也学不会读:给了正确条目,准确率也只有 73%。原因是基座没有复制能力(第 6、10 讲反复出现的主题)。先在传记里加”把事实再说一遍”的回顾句——没用,因为事实本来就能从记忆里预测,复制不是必需的;改成让内容随机的新闻带回顾句,预测回顾句就只能靠照抄,基座这才学会复制。只有一种新闻模板(met … in 镇)时,它只学会了抄镇名,于是新闻改成了三种模板。(代码 README 第 2 条)
5.4 实验:RAG 帮了谁
代码 03 §1(BM25 按问题检索整篇文档):
| 总体 | 0 次 | 1~2 次 | 3~9 次 | 10~29 次 | ≥30 次 | |
|---|---|---|---|---|---|---|
| 闭卷(预训练模型) | 59.8% | 8.7% | 22.2% | 53.9% | 94.6% | 100.0% |
| 闭卷(读者) | 54.4% | 17.4% | 21.6% | 47.2% | 86.1% | 95.8% |
| 开卷:BM25 第 1 篇 | 88.0% | 91.3% | 85.6% | 85.9% | 91.6% | 94.8% |
| 开卷:BM25 前 3 篇 | 81.0% | 87.0% | 77.8% | 79.0% | 84.3% | 88.5% |
| 开卷:直接给正确条目 | 99.6% | 95.7% | 99.3% | 99.6% | 100.0% | 100.0% |
- 给了正确条目,读者几乎全对,不管这条知识多冷门——它是在”读”而不是在”记”。
- 开卷让冷门知识的准确率翻了几倍;可最热门那一档,开卷反而比闭卷低——正是 Mallen et al. (2023) 的图(slides:“RAG 在长尾上持续带来提升”,但热门实体上 GPT-3 + 检索不如 GPT-3 自己)。
- 读者的闭卷成绩比预训练模型低了 5.3 个百分点:微调成读者时,参数里的一部分知识被冲掉了(回放预训练文档也没能完全避免——第 6 讲的灾难性遗忘)。
5.5 简单 RAG 的局限
slides 列出四个:
- 不必要的检索:问 “Who is Sam Altman?”,检索器取回了 Samuel Adams(美国开国元勋)的资料,模型照着说”他是美国的开国元勋”——本来模型自己知道答案。
- LM 很容易被无用的上下文带偏(Shi et al. 2023)。
- 输出常常得不到引用的支持:Liu et al. (2023) 评估生成式搜索引擎,相当一部分句子得不到所附引用的支持。
- 延迟:要编码长得多的上下文(RAGCache 等工作专门优化这部分)。
代码 03 §2 演示前两个。测试题里有 132 道题的园丁在文档库里没有条目,BM25 返回的是提到这位园丁的新闻:
资料:Nia Gaskan met Jude Riskem in Larkhill .
问:Nia Gaskan lives in ▶ 读者答 Larkhill(正确答案 Coveton;同一个模型闭卷时答 Coveton)
这些题,读者开卷只答对 21.2%,而它闭卷能答对 40.9%。其中 44 道题的新闻里恰好有一个同类的词(问住址时新闻里有镇名)——读者照抄它的比例 90.9%。热门的(≥10 次)33 道:开卷 42.4%,闭卷 72.7%。读者在训练时”资料里总有答案”,于是学会了几乎无条件地照抄资料里看起来像答案的词。
代码 03 §4:多给几篇资料呢?
| 检索篇数 k | 正确条目在资料里 | 准确率 | 平均输入长度(token) |
|---|---|---|---|
| 0(闭卷) | — | 54.4% | 4.3 |
| 1 | 85.3% | 88.0% | 21.2 |
| 2 | 85.3% | 85.0% | 30.4 |
| 3 | 85.3% | 81.0% | 40.5 |
| 5 | 85.3% | 71.4% | 63.4 |
BM25 第 1 篇就找到了正确条目;多给的几篇只是提到这位园丁的新闻,里面的随机值全是干扰项,准确率随 k 下降,输入长度却成倍增加(自注意力的计算量和长度的平方成正比)。在检索质量更差的场景里,多给几篇能提高”正确资料被检索到”的概率,那时 k 的取舍就是召回率和干扰之间的权衡。
代码 03 §6:答案有资料支持吗?“有支持”= 检索到的资料里有一句”这位园丁 + 这个关系 + 这个答案”。
| 有支持 | 没支持 | |
|---|---|---|
| 答对 | 84.9% | 3.1% |
| 答错 | 0.0% | 12.0% |
有支持的答案全是对的,所有错误都没有支持——如果系统检查”引用是否真的支持答案”,就能把错误挑出来。另有少数答对的答案没有支持:资料没用,读者凭记忆或碰巧答对了。
5.6 实验:自适应检索
Mallen et al. (2023) 的建议:热门知识信模型自己,冷门的才去查。代码 03 §3,每道题二选一:闭卷回答,或检索 1 篇后由读者回答。闭卷那一支可以用读者自己,也可以用没被微调冲掉知识的预训练模型。
| 策略 | 闭卷用读者:检索比例 / 准确率 | 闭卷用预训练模型:检索比例 / 准确率 |
|---|---|---|
| 从不检索(闭卷) | 0.0% / 54.4% | 0.0% / 59.8% |
| 总是检索 | 100.0% / 88.0% | 100.0% / 88.0% |
| 按流行度:出现 < 10 次才检索 | 70.9% / 87.1% | 70.9% / 89.1% |
| 按流行度:出现 < 30 次才检索 | 89.3% / 88.1% | 89.3% / 88.6% |
| 按置信度:闭卷置信度 < 0.5 | 33.2% / 74.9% | 54.3% / 88.6% |
| 按置信度:闭卷置信度 < 0.8 | 60.4% / 85.1% | 77.4% / 88.8% |
| 按置信度:闭卷置信度 < 0.95 | 83.2% / 88.2% | 92.1% / 88.1% |
| 先知(只在闭卷会答错时检索) | 45.6% / 91.4% | 40.2% / 93.8% |
- 闭卷用预训练模型时,“置信度 < 0.5 才检索”只检索一半的题,准确率还略高于总是检索。
- 闭卷用读者时,自适应检索只能和总是检索打平:读者忘掉了一部分热门知识,闭卷那一支不再可靠。
- 真实系统往往不知道一个问题有多”热门”(这里我们作弊地数了预训练语料);用模型自己的置信度来决定(FLARE,Jiang et al. 2023 在生成到低置信度的 token 时才检索)不需要这个信息。
代码 03 §5:文档库的覆盖率(自适应检索 = 闭卷用预训练模型、置信度 < 0.5 才检索):
| 有条目的园丁比例 | 总是检索 | 自适应检索 |
|---|---|---|
| 25% | 42.1% | 62.8% |
| 50% | 62.9% | 74.4% |
| 85% | 88.0% | 88.6% |
| 100% | 99.6% | 95.6% |
文档库每多覆盖一位园丁,开卷就能多答对他的问题(MassiveDS 的结论)。覆盖率低时,总是检索甚至不如闭卷(59.8%),自适应检索要好得多;覆盖率 100%、检索永远可靠时,总是检索几乎全对,自适应检索反而吃亏——它相信了闭卷时”有把握”却答错的那些题。要不要检索,取决于检索有多可靠。
6. 其他用法:中间融合与输出插值(kNN-LM)
6.1 RETRO:在中间层融合
RETRO(Borgeaud et al. 2022)把输入切成每 64 个 token 一块,每块用冻结的 BERT 向量去一个两万亿 token 的文档库里检索近邻,再在 Transformer 的中间层用块交叉注意力(chunked cross-attention)融入这些近邻。好处是能用很多段落(交叉注意力的开销比把它们全拼进输入小);代价是要重新训练模型。Borgeaud et al. 报告,7.5B 参数的 RETRO 在多个语言建模基准上能和大二十多倍的模型相当。
6.2 kNN-LM:在输出端插值
kNN-LM(Khandelwal et al. 2020)完全不改模型:
- 数据库:对语料里每个位置,键 = 模型在该位置的最后一层隐藏状态(“上文的表示”),值 = 那里的下一个词;
- 查询:用当前上文的表示找 k 个最近的键,按 加权它们的值,得到 ;
- :超参数,“信模型”还是”信数据库”。
检索的是 token(每个 token 检索一次),用的方式是输出插值——§5.1 那张表的最右一列。
6.3 实验:把”见过但没记住”的找回来
代码 04 §1:预训练语料 42000 篇、508,729 个 token → 数据库 508,729 条,每个键 128 维。例子:
'Tova Sur lives in'(这条事实在语料里只出现过 1 次;正确答案 Redcliff)
语言模型:Ashby(概率 0.96;正确答案的概率 0.00)
4 个最近邻(距离平方 → 存的下一个词):
0.00 …Tova Sur lives in → Redcliff
46.01 …Jude Stuman lives in → Ashby
46.01 …Jude Stuman lives in → Ashby
46.54 …Jude Stuskin lives in → Ashby
最近的键就是语料里那唯一一次提到这条事实的位置(那篇传记也以 “Tova Sur lives in” 开头,上文一字不差,距离为 0)。语言模型训练时只见过这句话一次,参数没记住;数据库却原样存着它。
代码 04 §2(k = 16):
| 总体 | 0 次 | 1~2 次 | 3~9 次 | 10~29 次 | ≥30 次 | |
|---|---|---|---|---|---|---|
| 语言模型 | 59.8% | 8.7% | 22.2% | 53.9% | 94.6% | 100.0% |
| kNN-LM λ = 0.25 | 91.3% | 4.3% | 84.3% | 93.3% | 99.4% | 100.0% |
| kNN-LM λ = 0.5 | 97.7% | 8.7% | 100.0% | 100.0% | 100.0% | 100.0% |
| 只用 kNN | 97.7% | 8.7% | 100.0% | 100.0% | 100.0% | 100.0% |
只要事实在语料里出现过,哪怕一两次,kNN 就能把它找回来;从没出现过的事实,数据库里也没有——kNN-LM 能”记住”的上限就是它的数据库。论文的标题”Generalization through Memorization”:把记忆交给数据库,模型只负责把上文表示好。
闭卷问答上的效果好得出奇,一部分原因是查询和语料里的上文一字不差。下面在留出文本上看更公平的数字。(代码 README 第 6 条)
6.4 实验:留出文本的困惑度
代码 04 §3:1000 篇新文档(同分布、没参加训练),11,963 个 token。
| λ | 全部 | 传记里的事实 | 新闻里的随机值 | 其他词 |
|---|---|---|---|---|
| 0.00 | 2.36 | 1.36 | 6.14 | 2.36 |
| 0.10 | 2.33 | 1.24 | 6.12 | 2.36 |
| 0.25 | 2.33 | 1.17 | 6.16 | 2.37 |
| 0.50 | 2.40 | 1.09 | 6.46 | 2.46 |
| 0.75 | 2.59 | 1.04 | 7.30 | 2.69 |
整体困惑度只小幅下降(最好在 λ ≈ 0.1~0.25),收益集中在”传记里的事实”——Khandelwal et al. 也发现 kNN-LM 主要帮助罕见的模式(事实、专有名词)。新闻里的随机值本来就不可预测,数据库里”相似上文”后面的词和这里无关,λ 越大越糟;λ 太大时连普通词也变差。slides 说输出插值”在一些任务上效果有限”,正是这个原因。
6.5 实验:换数据库,更新知识
代码 04 §4:两成园丁搬了家;用”新世界”的语料重建数据库,语言模型本身不动。测试集里搬了家的 54 位(热门的 17 位):
| 说出新地址 | 说出旧地址 | 热门的:新 / 旧 | |
|---|---|---|---|
| 语言模型 | 1.9% | 68.5% | 0% / 100% |
| kNN-LM λ = 0.25 | 29.6% | 61.1% | 6% / 94% |
| kNN-LM λ = 0.5 | 100.0% | 0.0% | 100% / 0% |
| 只用新数据库 | 100.0% | 0.0% | 100% / 0% |
不用训练,换掉数据库就更新了知识。但插值时,参数里的旧知识还在”投票”:热门园丁的旧地址模型很有把握,λ 小时旧地址赢。
代价(代码 04 §5):模型 857,088 个参数(3.4 MB),数据库 6500 万个浮点数(260 MB),是模型的 76 倍;而且每生成一个 token 都要做一次近邻搜索(RAG 每个问题只检索一次)。Khandelwal et al. 的数据库有 1 亿多条、每条 1024 维,只能用 FAISS 的近似搜索。
7. 近期进展:让模型自己决定检索和批判
7.1 Self-RAG
slides 把简单 RAG 的根本问题概括为两条:LM 没有在检索的条件下训练过;固定的两阶段流水线(总是检索、总是用)。Self-RAG(Asai et al. 2024)训练 LM 生成反思 token(reflection tokens):
| 反思 token | 问的问题 | 取值 |
|---|---|---|
| Retrieve | 需要检索吗? | 是 / 否 / 继续用已有的证据 |
| IsRel | 这个段落和问题相关吗? | 相关 / 无关 |
| IsSup | 生成的内容有段落支持吗? | 完全支持 / 部分支持 / 不支持 |
| IsUse | 回答有用吗? | 1~5 分 |
推断时:模型先决定要不要检索;要的话,对每个检索到的段落并行生成一段输出,同时生成 IsRel、IsSup;再按反思 token 的概率给各个候选打分、挑最好的那段,进入下一句。slides 的例子:问”推荐展示 LLM 帮助科学家综合文献的论文”,第一句”Certainly!”不需要检索;第二句检索到三个段落,两个被判为无关,相关的那个生成的句子被判为”完全支持”(0.9),另一个”部分支持”(0.5)。
训练数据的反思 token 由一个”批评者”模型标注(批评者本身是用 GPT-4 的判断蒸馏出来的),然后生成器在带反思 token 的数据上做普通的语言模型训练——推断时不需要批评者。
7.2 实验:会说”这份资料没用”的读者
代码 05:一个最简版本,只实现 IsRel。同样的 100 位园丁、同样的 7200 条,四成的资料里没有正确条目:
<ctx> Jude Riskem lives in Pebworth . … </ctx> Jude Riskem lives in ▶ <rel> Jude Riskem lives in Pebworth
<ctx> Jude Zemal met Jude Riskem in Oakridge . </ctx> Jude Riskem lives in ▶ <irr>
推断:先看 。≥ 0.5 就接上”<rel> + 复述的问题”照资料回答;否则丢掉资料、闭卷回答。
反思 token 的判断(BM25 第 1 篇):资料里有正确条目时判为”有用” 99.6%,没有时判为”有用” 0.0%。
| 总体 | 有条目 | 没条目 | 0 次 | 1~2 次 | 3~9 次 | 10~29 次 | ≥30 次 | |
|---|---|---|---|---|---|---|---|---|
| 普通读者:闭卷 | 54.4% | 56.8% | 40.9% | 17.4% | 21.6% | 47.2% | 86.1% | 95.8% |
| 普通读者:BM25 第 1 篇 | 88.0% | 99.5% | 21.2% | 91.3% | 85.6% | 85.9% | 91.6% | 94.8% |
| 会反思的读者:闭卷 | 55.1% | 57.2% | 43.2% | 4.3% | 26.1% | 48.1% | 83.7% | 97.9% |
| 会反思的读者:BM25 第 1 篇 | 91.6% | 99.9% | 43.2% | 95.7% | 87.6% | 89.6% | 95.8% | 99.0% |
资料没用时,普通读者照抄新闻里的随机值;会反思的读者识别出来、退回闭卷,正确率翻了一倍(正好是它自己闭卷的水平)。热门知识不再被检索失败拖累,总体 91.6%,超过了 §5.6 里除”先知”以外的所有自适应检索策略。
这个读者改了三版(代码 README 第 5 条),两次失败都很有教益。第一版在
<irr>后面直接说出正确答案——读者把 100 位训练园丁的事实背了下来,读新园丁的资料时会说出同名训练园丁的住址。第二版在<rel>后面直接给答案,读资料的准确率从 99.6% 掉到 92%:照抄靠的是”找到上文里和当前词相同的位置、抄它后面的词”(induction head,第 6 讲),答案紧跟在 in 后面时,资料里恰好有 “lives in Pebworth” 可以对照;紧跟在<rel>后面就没有了。第三版在<rel>后面先复述问题——和 Self-RAG 在 IsRel 之后生成完整的输出句一样——读资料回到 99.8%。输出格式会影响模型能不能用上它已有的本事。
7.3 实验:逐篇判断 vs 拼在一起
代码 05 §2:检索 3 篇。
| 做法 | 准确率 | 每次前向的输入长度 |
|---|---|---|
| 普通读者:3 篇拼在一起 | 81.0% | 39.5 |
| 会反思的读者:3 篇拼在一起 | 80.2% | 39.5 |
会反思的读者:逐篇判断,挑 P(<rel>) 最高的 | 90.1% | 20.2(× 3 次) |
拼在一起时,多出来的新闻是干扰项;逐篇判断每次只读一篇、挑出”有用”的那篇——Self-RAG 的做法。不过这里它还略低于只读第 1 篇(91.6%):排在第 2、3 位的常常是同名不同姓的园丁的条目,反思 token 偶尔会把它误判为有用、而且打分比正确条目还高。检索器越不可靠,逐篇判断的价值越大;检索器很可靠时,多看的那几篇只是多了几次犯错的机会。
7.4 实验:资料和记忆冲突时,信谁?
代码 05 §3:把正确条目里被问到的那条事实换成一个错误的值,其余不动。
| 跟着资料 | 坚持记忆 | 资料被判为有用 | 跟着资料:0 次 / 1~2 / 3~9 / 10~29 / ≥30 | |
|---|---|---|---|---|
| 普通读者 | 98.9% | 0.3% | — | 100 / 98.7 / 98.7 / 98.8 / 100.0 |
| 会反思的读者 | 98.2% | 0.8% | 99.7% | 100 / 98.7 / 98.5 / 97.0 / 97.9 |
两个读者都几乎总是跟着资料走,连它们最熟悉的热门知识也一样。反思 token 也照样判为”有用”——它学会的是”这段资料是不是在讲这位园丁”(相关性),不是”这段资料说得对不对”(真实性)。
- 好的一面:世界变了,只要更新文档库,读者就会跟着变——搬了家的 45 位园丁,两个读者闭卷都说出新地址 0.0%,开卷分别 100.0% 和 95.6%。
- 坏的一面:文档库里混进了错误或恶意的内容,读者会照单全收(数据投毒、间接提示注入,第 16 讲)。
真实 LLM 介于两者之间:Longpre et al. (2021) 发现模型常常固执于参数里的记忆、无视上下文里的新知识;Xie et al. (2024) 发现资料连贯可信时,LLM 又很容易被说服。
7.5 工具增强的 LM 与深度研究
- 工具增强(第 10 讲):Toolformer 让模型在需要时通过 API 调用搜索,能灵活扩展到其他工具;
- 深度研究(deep research):把推理模型和搜索结合起来,用 SFT / RL 教它规划、多轮搜索、阅读、再推理(例如 WebThinker,Li et al. 2025)。slides 指出它的局限:不能扩展到很多文档(需要”上下文工程”来决定放什么进上下文),输出不严格基于资料。
8. 小结、常见误区、练习
8.1 小结
- 参数化知识的局限:能否闭卷答对,由”在语料里见过几次”决定。见过 30 次以上几乎全对,见过 1~2 次只答对两成(大模型主要提升中间档)。不知道时按先验流利地编(幻觉);知识停在训练截止的那一刻。
- RAG 的三个部件:文档库(来源、切块、规模)、检索器、语言模型;好处是减少幻觉、不重新训练就能更新知识、可验证。
- 检索器:BM25 精确匹配罕见的词但不懂同义;稠密检索器学会改写,但对训练分布之外的问法和冷门实体脆弱;两者互补,混合 + 交叉编码器重排序是常用做法;nDCG@10、BEIR、MTEB。
- 先检索再阅读:读者给了正确资料几乎全对,冷门知识成倍提升;但检索失败时,只在”资料总有答案”的数据上训练的读者照抄无关文档(90.9%),热门知识反被拖累。自适应检索(按置信度)用一半的检索达到同样或更好的准确率,前提是闭卷那一支可靠;多给资料不一定更好。
- kNN-LM:输出插值,把见过但没记住的事实从数据库里找回来;整体困惑度改进小、对不可预测的内容有害;换数据库就能更新知识;代价是巨大的数据库和每个 token 一次搜索。
- Self-RAG:让模型生成反思 token 判断检索和相关性;能识别检索失败、退回记忆;但”相关”不等于”正确”,读者仍会照单全收错误的资料。
8.2 常见误区
- “把模型做大就能记住所有知识”:模型变大主要帮助中间档的知识;从没见过或只见过一两次的事实,靠规模很难补上(§1.2)。
- “模型答得流利,说明它知道”:没见过的事实它照样流利地回答,置信度只是略低(§1.3)。
- “检索总是有帮助”:检索失败时,模型会被无关资料带偏,连本来会的热门知识也答错(§5.5、§5.6)。
- “给的资料越多越好”:多出来的段落是干扰项,还让上下文成倍变长(§5.5)。
- “稠密检索器比 BM25 先进,所以更好”:它在训练分布之外、在冷门实体上常常不如 BM25;两者互补(§4.6、§4.7)。
- “评估检索器时,用和训练一样的问法就够了”:同一个稠密检索器,见过的问法 99%、没见过的问法 38%(§4.6)。
- “RAG 系统会核实资料的真伪”:读者(包括会判断相关性的读者)几乎总是相信资料(§7.4)。
- “kNN-LM 能让模型知道新东西”:它只能找回数据库里有的;数据库里没有的,它和模型一样不知道(§6.3)。
8.3 练习
练习 1(BM25 为什么恰好是三分之一):按句子切块时,“where does Ines Ronus live ?” 只和三句话里的 ines、ronus 两个词匹配。分词时句号被去掉,三句话的长度是 5(lives in Larkhill)、4(grows turnip)、4(keeps cat),avgdl = 6.32,idf(ines) = 1.057、idf(ronus) = 1.127,、。算出三句的 BM25 分数,并解释为什么 R@1 恰好是 1/3。如果给 BM25 加上最简单的词干还原(去掉词尾的 s),R@1 会变成多少?
参考答案(用 rag_world 验证)
每个匹配词的 tf 部分是 。L = 5:分母 ,得 1.0935;L = 4:分母 ,得 1.1768。分数 = (1.057 + 1.127) × tf 部分:lives 那句 2.389,grows、keeps 两句都是 2.570。所以住址那句永远排第三;grows 和 keeps 并列,稳定排序取文档库里在前面的那句(条目里 grows 在 keeps 之前)。于是:问住址 R@1 = 0,问植物 R@1 = 1,问动物 R@1 = 0,平均恰好 1/3(实测:town 0.0、plant 1.0、animal 0.0)。加上词干还原后,live/lives、grow/grows、keep/keeps 都能匹配上,三个关系的 R@1 都是 1,总体 1.000。真实的 BM25 系统(如 Lucene)默认带词干还原,正是为了缓解这种字面不匹配。
练习 2(手算 nDCG@10):一个查询有 2 篇相关文档,检索器把它们排在第 2 和第 5 位。算 R@1、R@5、MRR 和 nDCG@10。
参考答案(用 multi_metrics 验证)
R@1 = 0(第 1 位不相关),R@5 = 1(前 5 里有相关的),MRR = 1/2 = 0.5(第一个相关的在第 2 位)。DCG@10 = ;理想排序把两篇放在第 1、2 位:IDCG = ;nDCG@10 = 0.624。和 R@k、MRR 相比,nDCG 同时考虑了”有几篇相关的”和”它们排得多靠前”。
练习 3(RAG 的边缘化):问 “Ada Brask lives in”,检索到两个段落,、。生成器在 下给 Coveton 0.9,在 下给 Coveton 0.1。(a) 算 。(b) 联合训练时,最小化 会让检索器怎样变化?为什么这不需要”哪个段落是对的”的标注?
参考答案
(a) 。(b) 对检索器的分数求导:, 下答案的概率更高,所以梯度会提高 、降低 ——“哪个段落让正确答案更好生成,就把它排得更靠前”。监督信号来自答案本身,段落的好坏由生成器”投票”决定,这就是 RAG、REALM 和 REPLUG 都不需要段落标注的原因。代价是:如果生成器能不看段落就答对(热门知识),这个信号就很弱。
练习 4(kNN-LM 的温度与插值):§6.3 的例子里,4 个最近邻的距离平方是 0、46.0、46.0、46.5,存的词分别是 Redcliff、Ashby、Ashby、Ashby;语言模型给 Redcliff 0.0004、Ashby 0.959。权重 ∝ 。(a) 分别取 T = 1 和 T = 50,算 。(b) λ = 0.5 时,两种温度下 kNN-LM 各输出哪个词?λ = 0.25 呢?
参考答案(代码验证:k = 16 时结论相同)
(a) T = 1:,Redcliff 的权重几乎是全部,。T = 50:权重 ,总和 2.19,Redcliff 0.456、Ashby 0.544。(b) λ = 0.5,T = 1:Redcliff ,Ashby ,输出 Redcliff(险胜);T = 50:Redcliff ,Ashby ,输出 Ashby。λ = 0.25,T = 1:Redcliff 0.250、Ashby 0.719,输出 Ashby。温度决定”只信最近的那一个”还是”让一群相似的上文投票”;λ 决定数据库的票有多重。模型越有把握(这里 0.96),需要的 λ 越大——这就是 §6.5 里热门园丁在 λ = 0.25 时仍说旧地址的原因。
练习 5(自适应检索的阈值):闭卷用预训练模型,“置信度 < τ 才检索”的检索比例和准确率(代码 03 的数据):τ = 0.3:31.9% / 80.7%;0.4:44.4% / 85.7%;0.5:54.3% / 88.6%;0.6:63.3% / 89.6%;0.7:69.6% / 89.6%;总是检索:100% / 88.0%。假设一次检索的成本相当于答错一题的 1/20,哪个 τ 的总成本最低?
参考答案
总成本 = 错误率 + 0.05 × 检索比例:τ = 0.3:0.193 + 0.016 = 0.209;0.4:0.143 + 0.022 = 0.165;0.5:0.114 + 0.027 = 0.141;0.6:0.104 + 0.032 = 0.136;0.7:0.104 + 0.035 = 0.139;总是检索:0.120 + 0.050 = 0.170。τ = 0.6 最好:它比总是检索准确率更高(89.6% vs 88.0%)、检索少三分之一以上。检索越贵(例如要调用付费的搜索 API、或者延迟要求很严),最优的 τ 越小。注意准确率在 τ = 0.6 之后不再上升:置信度 0.6~0.95 的那些题,闭卷和开卷差不多。
练习 6(切块大小):把 §3.3 的”每 k 个词”换成 k = 8、12、24、48,预测”没有正确块的问题数”和 R@1 的变化,再说说块变大的代价。
参考答案(实测)
| k | 块数 | 没有正确块 | R@1 | nDCG@10 |
|---|---|---|---|---|
| 8 | 3680 | 256 | 0.333 | 0.533 |
| 12 | 2454 | 256 | 0.561 | 0.622 |
| 24 | 1227 | 81 | 0.784 | 0.843 |
| 48 | 614 | 0 | 0.984 | 0.991 |
块越大,句子被切断的概率越小、名字在块里重复的次数越多,检索越准。(注意:条目恰好 16 个 token,k = 16 时窗口和条目完全对齐、全部命中——这是巧合,不说明 16 是好的选择。)代价是:读者要读的上下文变长(延迟、计算量),而且一个 48 词的块里有好几位园丁的事实,读者更容易被块里的其他内容带偏(§5.5 的干扰问题)。所以真实系统常常”检索时用小块、阅读时扩展到周围的大块”,或者按段落 / 句子边界切块再合并到目标长度。
练习 7(思考:为什么普通读者会照抄):§5.5 里,检索到的新闻有同类的词时,普通读者 90.9% 照抄它。从训练数据的角度解释原因,并设计两种不同的修正办法,说出各自的代价。
参考答案
普通读者的 7200 条训练样例里,资料总是含有正确条目,所以”抄资料里看起来像答案的那个词”永远是对的——它没有任何理由学会检查”这段资料讲的是不是我问的那个人”。修正:(1) 鲁棒训练:训练数据里混入没用的资料,目标仍是正确答案(Yoran et al. 2024),让模型学会忽略无关资料;代价是答案要靠记忆给出,模型会被迫背下训练实体的事实(本讲的第一版 robust 读者就因此学会了按名字乱套)。(2) 显式批判(Self-RAG):先输出 <rel> / <irr>,无关时丢掉资料、走闭卷;代价是需要相关性标注(Self-RAG 用 GPT-4 蒸馏的批评者),多一步推断,而且只判断相关性、不判断真伪(§7.4)。另一个思路是在检索端加一个独立的重排序器 / 相关性过滤器,读者不变。
练习 8(思考:RAG 还是微调):一家公司要让 LLM 回答关于自家产品的问题,产品文档每周更新。比较三种做法:(a) 在文档上继续预训练 / 微调;(b) RAG;(c) kNN-LM。用本讲的实验结果支持你的论证。
参考答案
(a) 微调把知识写进参数:§1.2 显示一条事实要见好几次才记得住(见过 1~2 次只对 22%,多训练两遍才到 91%),需要对每条新知识做数据增强(换说法、多次出现);每周更新就要每周重新训练,还有灾难性遗忘(§5.4 读者丢了 5.3 个百分点);答案无法溯源。Ovadia et al. (2024) 的实验也发现,注入新知识时 RAG 明显好于无监督微调。(b) RAG:更新文档库即可(§7.4 搬家实验 100%),答案可以附出处(§5.5 的支持分析),对冷门知识效果最好;代价是检索质量决定上限(覆盖率实验)、检索失败时可能被带偏、上下文更长。(c) kNN-LM:同样能换库更新(§6.5),但每个 token 都要检索、数据库巨大、需要访问模型的隐藏状态(闭源 API 做不到),对问答这类任务不如直接给资料。实践中常见的组合是:用 RAG 提供知识,用(少量)微调教模型怎样读资料、怎样按公司的风格回答——也就是本讲读者微调做的事。
练习 9(思考:文档库的风险与机会):RAG 把知识从参数里搬到了文档库里。列举这带来的两个风险和两个机会(提示:投毒、隐私、版权、可删除性)。
参考答案
风险:(1) 投毒与间接提示注入——§7.4 显示读者几乎总是相信资料,攻击者只要往文档库(网页、维基、共享文档)里写入错误事实或藏着指令的文字,就能操纵输出(第 16 讲讲防御);(2) 隐私泄露——文档库里的个人信息会被原样检索出来交给模型,任何能提问的人都可能拿到。机会:(1) 可删除、可追溯——要删掉一条有版权或隐私问题的资料,从文档库里删掉即可,不用重新训练;每个答案都能指向来源(SILO,Min et al. 2024:参数只在许可宽松的数据上训练,高风险数据只放在推断时的文档库里,可以随时移除并给出归属);(2) 访问控制——不同用户检索不同的文档库(按权限过滤),同一个模型能服务权限不同的人,这是把知识写进参数做不到的。
8.4 延伸阅读
- 原课阅读:Lewis et al. (2020), RAG;Khandelwal et al. (2020), kNN-LM;Mallen et al. (2023), When Not to Trust Language Models(PopQA、自适应检索);Asai et al. (2024), Self-RAG
- 教程与综述:Asai, Min, Zhong & Chen (2023), ACL 教程 Retrieval-based Language Models and Applications(slides 的来源);Gao et al. (2024), Retrieval-Augmented Generation for Large Language Models: A Survey
- 长尾与知识:Kandpal et al. (2023), Large Language Models Struggle to Learn Long-Tail Knowledge;Allen-Zhu & Li (2023), Physics of Language Models: Part 3.1
- 检索器:Karpukhin et al. (2020), DPR;Izacard et al. (2022), Contriever;Khattab & Zaharia (2020), ColBERT;Asai et al. (2023), Task-aware Retrieval with Instructions(TART);Thakur et al. (2021), BEIR;Muennighoff et al. (2022), MTEB;Sciavolino et al. (2021), Simple Entity-Centric Questions Challenge Dense Retrievers
- 架构:Guu et al. (2020), REALM;Borgeaud et al. (2022), RETRO;Shi et al. (2023), REPLUG;Izacard & Grave (2021), Fusion-in-Decoder
- 局限与改进:Shi et al. (2023), Large Language Models Can Be Easily Distracted by Irrelevant Context;Yoran et al. (2024), Making Retrieval-Augmented Language Models Robust to Irrelevant Context;Liu et al. (2023), Evaluating Verifiability in Generative Search Engines;Jiang et al. (2023), Active Retrieval Augmented Generation(FLARE);Longpre et al. (2021), Entity-Based Knowledge Conflicts in Question Answering;Xie et al. (2024), Adaptive Chameleon or Stubborn Sloth
- 规模与数据:Shao et al. (2024), Scaling Retrieval-Based Language Models with a Trillion-Token Datastore(MassiveDS);Min et al. (2024), SILO Language Models
- 本仓库的相关内容:第 6 讲(复制能力与 induction head、灾难性遗忘);第 10 讲(BM25、稠密检索、ANCE);CMU17-630 的 RAG 相关讲次
8.5 下一讲预告
这一讲里,“把模型做大”对长尾知识帮助有限,而 RETRO、MassiveDS 都在问”把参数换成数据库值不值”。第 12 讲回到 LLM 的核心问题:规模定律。给定算力预算,模型该多大、数据该多少?损失能不能在训练之前就预测出来?为什么每家公司都在追逐最大的模型——以及 Chinchilla 怎样证明 GPT-3 时代的模型”太大、数据太少”。我们会在花园世界里训练一系列小模型,亲手拟合幂律、画出 IsoFLOP 曲线。