对应 Maps to:CMU 17-630 Prompt Engineering(Prof. Travis Breaux),第 5 周的第一个主题 · Prompt Augmentation: Retrievers。原课 Schedule 对这一讲的说明(意译):检索增强生成的架构,包括分块、向量化,以及检索前、检索后和模块化的检索处理技术。原课作业 3(RAG)要求在问答和文本摘要两种任务上评估内容导入策略(分块等)和检索器。 依据说明:原课的 slides 和阅读清单不公开。Schedule 点名的几个部分——架构(§2)、分块(§3)、向量化与检索(§4)、检索前 / 检索后处理(§5)、模块化 RAG(§2、§7)——各占一节;§6(生成这一侧)、§7(什么时候检索)和 §8(评估)是讲义补充的,对应作业 3 的”评估”要求。材料来自 Lewis et al.(2020,RAG)、Gao et al.(2023,RAG 综述)、Robertson & Zaragoza(2009,BM25)、Karpukhin et al.(2020,DPR)、Thakur et al.(2021,BEIR)、Sciavolino et al.(2021)、Cormack et al.(2009,RRF)、Nogueira & Cho(2019)、Khattab & Zaharia(2020,ColBERT)、Gao et al.(2023,HyDE)、Ma et al.(2023)、Liu et al.(2024,Lost in the Middle)、Mallen et al.(2023)、Asai et al.(2024,Self-RAG)、Zou et al.(2024,PoisonedRAG)、Xie et al.(2024)、Rashkin et al.(2023)与 Gao et al.(2023,ALCE)等;引用时按原文的说法转述结论,具体数字以原文为准。全部实验是本讲义自己设计的,不代表课堂上讲了什么。 配套代码 Code:
code/lecture07/(numpy + PyTorch CPU;1 个模块 + 6 个脚本;不需要 API key;检索部分不需要训练,HyDE 和”什么时候检索”用到第 5 讲的长尾模型缓存;每个脚本都在 5 秒以内) 预计阅读时间:4 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
学完这一讲,你应该能够:
- 说清楚为什么要检索(长尾、过时、私有、可溯源),以及 RAG 和”把知识微调进模型”的取舍。
- 画出一个 RAG 系统的流水线(导入:分块 → 编码 → 建索引;查询:检索前 → 检索 → 检索后;生成:拼提示 → 回答 → 引用),并解释”朴素 / 高级 / 模块化 RAG”的区别。
- 为一个文档库选择分块方式(大小、重叠、边界、标题前缀),并解释问答和摘要对检索的不同要求。
- 从零实现 BM25 和一个稠密检索器,说出它们各自的典型错误;用 RRF 或在开发集上调权重来融合它们。
- 使用查询改写、多查询、HyDE 和重排,并解释 bi-encoder 与 cross-encoder 的取舍。
- 用检索指标(R@k、MRR)和端到端指标(问答准确率、摘要覆盖率、归因)评估 RAG;理解”检索到了 ≠ 用上了”。
- 设计”什么时候检索、资料和记忆冲突时听谁的”的策略,并知道 RAG 引入的新风险(投毒)。
0.2 先修与本讲范围 Prerequisites & scope
| 默认你已经会 Assumed | 本讲只给直觉,后面再展开 Previewed only |
|---|---|
| 第 1 讲:TF-IDF、PPMI-SVD 词向量、句向量、bi-encoder vs cross-encoder(§4) | 把检索当作一个工具来调用(第 8 讲) |
| 第 5 讲:长尾知识、置信度与 AUROC、“给它一条退路” | 多跳检索与任务分解(第 9 讲) |
| 前置讲 P1:token、按 token 分块;P2:成本与延迟 | LLM 判官做评估(第 10 讲);间接提示注入与防御(第 12 讲) |
| 前置讲 P3:开发集 / 测试集、区间 | 智能体的记忆检索(第 14 讲) |
0.3 本讲地图 Map
§1 为什么要检索:长尾、过时、私有、可溯源;RAG vs 微调;前提是模型会读
§2 RAG 的架构:导入 → 查询 → 生成;朴素 / 高级 / 模块化 RAG
§3 内容导入:分块的大小、重叠、边界;"丢了主语"与标题前缀;问答 vs 摘要 ← 代码 01
§4 检索:BM25、稠密检索、它们各自错在哪里、融合 ← 代码 02
§5 检索前与检索后:改写、多查询、HyDE、重排 ← 代码 03
§6 生成这一侧:给几段、怎么摆、引用对不对 ← 代码 04
§7 什么时候检索、相信谁:冷门 vs 热门、自适应检索、冲突与投毒 ← 代码 05
§8 评估一个 RAG 系统;在真实模型上跑一遍 ← 代码 06(可选)
§9 小结 §10 常见误区 §11 练习 §12 延伸阅读 §13 下一讲预告
0.4 记号与术语 Notation & terms
| 术语 | 本讲义里的意思 |
|---|---|
| 文档库 / 语料库(corpus) | 可以被检索的全部文档 |
| 段落 / 块(chunk, passage) | 分块之后的检索单位 |
| 参数化知识 / 非参数化知识 | 存在模型权重里的知识(闭卷)/ 存在外部文档库里、推理时检索的知识(开卷) |
| 词法检索(lexical / sparse) | 按词的重合打分,例如 BM25 |
| 稠密检索(dense)、bi-encoder | 问题和段落各自编码成一个向量,按相似度排序 |
| cross-encoder / 重排器(reranker) | 把问题和段落一起送进模型打分;更准、更慢 |
| R@k(Recall@k) | 前 k 个结果里至少有一个相关段落的比例 |
| MRR | 第一个相关段落排名的倒数,对所有问题取平均 |
| 归因(attribution) | 回答里的说法能否被它引用的段落支持 |
0.5 本讲的实验装置 · The setup
文档库(rag_lab.build_kb)建在第 5 讲的长尾世界上(60 个国家):
- 60 个百科页面:概述 / 政府 / 人民 / 经济四节。第一句点名(“stindia is a country in the north .”),之后多数句子用指代(“its capital is brelo .”、“the country is led by kralta .”、“people there speak gistese .”),每个事实有 25% 的概率用带国名的说法。热门国家的页面更长。
- 200 篇干扰文档:新闻(两国领导人会面)、贸易报告(“a buys 商品 from b”)、游记(“we flew to 首都 , the capital of x”)。它们更常提到热门国家。
一共 260 篇、约 6600 个词。因为每一句话都是程序生成的,哪些段落包含答案是精确知道的——这让我们能把”检索错了”和”读错了”分开测。
问题:每个国家 × 首都 / 语言 / 出口 / 领导人,两种问法——标准问法(“who leads X ?”)和换个说法(“who rules X ?”)。60 个国家分成训练用的 30 个(调参数、训练重排器)和测试用的 30 个(报告结果)。
阅读器有三种:
- 抽取式阅读器(
ExtractiveReader):按排名逐段解析事实,第一个找到的就是答案;不猜、不用记忆。它的准确率完全由检索决定,用来单独测检索。 - 模拟 LLM 阅读器(
SimReaderLLM):会”读漏中间”、会被别国的同类事实干扰、找不到时会凭”记忆”补——每种行为都是一个旋钮。用来看这些已知现象怎样和真实的检索结果相互作用。 - 真实的 Claude(06 号脚本,可选)。
为什么不用迷你 GPT 当阅读器? 第 5 讲 §3.5 发现,长尾模型不会读上下文:给冷门国家正确的资料,准确率和不给一样。为了这一讲,我们试着训练一个会读的迷你 GPT:在长尾语料里混入大量”随机新名字的段落 + 问题”(记住答案没用,只能从段落里找),2 层和 3 层、两种问题格式都试了,在新段落上的准确率都只有 1%–10%。从段落里定位并照抄一个只出现过几次的名字,对这个尺寸的词级模型太难了(第 2 讲的归纳头是在只有 3 个符号的序列上学出来的)。这本身就是一个结论:RAG 的前提是阅读器会读,而这种能力来自规模和专门的训练数据。所以这一讲把”检索”做成真实的计算,把”阅读”交给抽取式阅读器、模拟器和真实模型。
1. 为什么要检索 · Why retrieve
第 5 讲的长尾曲线是这一讲最直接的动机:出现 0 次的事实,迷你模型的准确率 4.2%;出现 1 次的 20.8%。大模型也一样——Kandpal et al.(2023)发现,模型回答一个问题的准确率,随相关文档在预训练数据里出现的次数急剧变化;Mallen et al.(2023)发现,对冷门实体,把模型变大带来的提升很小。
除了长尾,还有三个理由:
- 知识会过时:模型的知识停在训练数据截止的那一天;文档库可以每天更新。
- 知识是私有的:公司的内部文档、用户自己的文件,从来不在预训练数据里。
- 可溯源:答案能指向一段原文,用户可以核对(第 5 讲 §7:引用与可溯源是减少幻觉的策略之一)。
开卷考试的直觉。闭卷时,你只能靠记住的东西(参数化知识);开卷时,你可以翻书(非参数化知识)。开卷考得好,需要两样东西:找到对的那一页(检索),以及读懂它(阅读)。Lewis et al.(2020)提出的 RAG(Retrieval-Augmented Generation)把一个预训练的生成模型和一个维基百科的稠密向量索引连在一起,在知识密集型任务上超过了只靠参数的模型;同一时期的 REALM(Guu et al. 2020)、之后的 RETRO(Borgeaud et al. 2022)都是”让模型在推理时查资料”的不同做法。
RAG 还是微调? 把新知识”教”给模型的另一条路是微调。第 5 讲已经看到它的风险:用模型不知道的事实做微调,模型变得自信地错(Gekhman et al. 2024)。Ovadia et al.(2024)比较了用无监督微调和用 RAG 注入知识,发现 RAG 一贯更好。一个常见的经验法则是:RAG 管”知道什么”,微调管”怎么做”(格式、风格、任务的方法)。两者也可以结合。
2. RAG 的架构 · Architecture
一个 RAG 系统有三个阶段:
导入(离线,一次) 文档 → 清洗 → 分块 → 编码(BM25 统计 / 向量) → 索引
查询(每个问题) 问题 → [检索前:改写 / 多查询 / HyDE] → 检索 top-N → [检索后:重排 / 去重 / 压缩] → top-k
生成(每个问题) 把 top-k 段落和问题拼进提示 → 模型回答 → [引用 / 归因检查]
拼进提示的样子(rag_lab.rag_prompt):
Context:
[1] stindia : stindia is a country in the north . the winters are cold . the capital of stindia is brelo .
[2] stindia : stindia is led by kralta . the old town has a famous bridge . people there speak gistese .
[3] news 41 : ...
Question: where does the government of stindia sit ?
Answer with one word using only the context. If the context does not say, answer 'unknown'.
Then give the number of the passage you used, like 'lorn [2]'.
Gao et al.(2023)的综述把 RAG 的发展分成三个阶段,正好对应 Schedule 里的说法:
- 朴素 RAG(naive):上面的流水线,不加任何处理。
- 高级 RAG(advanced):在检索前(改写查询)和检索后(重排、压缩)加处理步骤(§5)。
- 模块化 RAG(modular):把检索、改写、重排、阅读、判断”要不要检索”等做成可以替换和重新组合的模块,甚至让模型自己决定流程(§7 的自适应检索、Self-RAG;第 8 讲把检索当工具、第 9 讲的多跳检索)。
这一讲的六个脚本基本按流水线的顺序走:01 导入,02 检索,03 检索前后,04 生成,05 要不要检索,06 在真实模型上端到端。
3. 内容导入:分块 · Ingestion & chunking
3.1 为什么要分块
一篇文档不能整篇放进提示:太长(上下文窗口、成本)、太杂(检索的单位太大,和问题相关的那一句被淹没)。所以要切成段落。分块看起来是一个无聊的工程细节,但 01 号脚本会看到,它对端到端准确率的影响比换检索器还大。
3.2 大小、重叠、边界
01_chunking.py 演示 1 用七种方式切同一个文档库,每种再分”加 / 不加标题前缀”,用 BM25 检索、抽取式阅读器回答 120 道测试题:
| 分块方式 | 标题前缀 | 段数 | 事实被切断 | 能独立读懂 | R@5 | 问答@5 |
|---|---|---|---|---|---|---|
| 按字符,每段 100 个字符 | 不加 / 加 | 399 | 37% | 83% / 100% | 51.7% / 72.5% | 49.2% / 70.8% |
| 按词,每段 10 个词 | 不加 / 加 | 777 | 39% | 74% / 100% | 26.7% / 62.5% | 20.8% / 68.3% |
| 按词,每段 20 个词 | 不加 / 加 | 417 | 26% | 79% / 100% | 58.3% / 80.8% | 51.7% / 82.5% |
| 按词,20 个词,重叠 5 个 | 不加 / 加 | 445 | 5% | 73% / 100% | 66.7% / 93.3% | 55.8% / 96.7% |
| 按词,每段 40 个词 | 不加 / 加 | 320 | 10% | 95% / 100% | 82.5% / 90.8% | 82.5% / 90.8% |
| 按句子打包(≤ 20 词) | 不加 / 加 | 427 | 0% | 73% / 100% | 61.7% / 95.0% | 54.2% / 95.0% |
| 按文档结构(每节一段) | 不加 / 加 | 440 | 0% | 66% / 100% | 49.2% / 94.2% | 39.2% / 94.2% |
(“事实被切断”:这个事实所在的句子没有完整地出现在任何一段里。“能独立读懂”:含有事实的段落里,只看段落本身就能知道”这是哪个国家的事实”的比例。)
几条规律:
- 切点要落在边界上。按字符切,一段可能从一个词的中间开始,“stindia” 变成 “ndia”,BM25 只认完整的词;按词切而不重叠,四分之一的事实被切成两半。按句子或按结构切,句子从不被切断。真实系统常按 token 数切(前置讲 P1)——同样要注意切点的位置。
- 重叠是切断的补丁:20 个词的段落重叠 5 个词,被切断的事实从 26% 降到 5%,问答从 82.5% 升到 96.7%。代价是段数和重复的 token 变多。
- 段太小装不下”谁 + 什么”:每段 10 个词时,不加前缀的问答只有 20.8%。段越大越完整,但每一段花的 token 越多(§3.5)。
3.3 “丢了主语”:标题前缀
表里最大的单项改进是标题前缀:每段 20 个词时问答 51.7% → 82.5%,按文档结构分块时 39.2% → 94.2%。
原因是指代。百科页面第一句之后都写 “its capital is brelo”、“the country is led by kralta”——人读整篇文章时毫无问题;可是切开以后,“the country is led by kralta .” 这一段不知道自己在说哪个国家。检索器看不到国名,问 “who leads stindia ?” 时它不会被排上来;即使排上来,阅读器也不知道它属于谁。不加前缀时,按结构分块的含事实段落里有 34% 是这样”丢了主语”的。
修补的办法是在每一段前面加上文档标题(“stindia : the country is led by kralta .”)。Anthropic 的 Contextual Retrieval(2024)把同样的想法做得更彻底:用 LLM 给每一段写一两句”这段话在整篇文档里讲什么”的说明,再建索引。更一般地说:段落要能独立成立——分块时把丢掉的上下文补回去。
3.4 问答 vs 摘要
原课作业 3 要求在问答和摘要两种任务上评估分块和检索。为什么要两种?演示 2 做了一个”查询聚焦的摘要”:检索 “tell me about X” 的前 k 段,看一个国家的 4 个事实能找回几个。
| 分块方式 | k = 1 | k = 3 | k = 5 | k = 10 | k = 20 |
|---|---|---|---|---|---|
| 按句子打包 + 前缀 | 20.0% | 67.5% | 85.8% | 93.3% | 95.0% |
| 按文档结构 + 前缀 | 5.0% | 56.7% | 80.8% | 93.3% | 95.8% |
| 按词 20 个,不加前缀 | 18.3% | 36.7% | 44.2% | 50.0% | 52.5% |
问答通常只要一段对的(第一段就对最好);摘要要的是分散在好几段里的全部。同一个 k,对问答是够的,对摘要可能远远不够。所以评估分块策略时,两种任务的结论可以不一样——这就是作业要求两种都做的原因。
3.5 token 预算
演示 3 把每道题放进提示的词数和问答准确率放在一起:
| 分块方式(加前缀) | k = 1 | k = 3 | k = 5 |
|---|---|---|---|
| 按词,每段 10 个词 | 52%(12 词) | 61%(32 词) | 68%(54 词) |
| 按词,每段 40 个词 | 68%(32 词) | 86%(74 词) | 91%(117 词) |
| 按句子打包(≤ 20 词) | 57%(19 词) | 87%(54 词) | 95%(89 词) |
同样的准确率可以用很不一样的 token 数达到:按句子打包、k = 3 只用 54 个词就到了 87%,而每段 40 个词要 74 个词。放进提示的每个 token 都要付钱、增加延迟(前置讲 P2),还会稀释模型的注意力(§6)。分块大小和 k 要一起调,在你的任务和文档上调——没有一个普遍最优的”512 个 token、重叠 50”。
4. 检索:词法与稠密 · Retrieval
4.1 BM25
第 1 讲 §4 的 TF-IDF 给每个词一个权重:在这段里出现得多、在所有段落里出现得少的词更重要。BM25(Robertson & Zaragoza 2009)是它的两处改进:
- 词频饱和:一个词出现 10 次不比出现 3 次重要 3 倍多( 控制饱和的速度,常用 1.2);
- 长度归一化:长段落天然含更多词,要打折扣( 控制折扣的力度,常用 0.75)。
BM25 几十年来是搜索引擎的基础,今天仍是 RAG 里最常用的基线之一。
4.2 稠密检索
稠密检索把问题和段落各自编码成一个向量,按余弦相似度排序。这是第 1 讲 §4 的 bi-encoder:段落向量可以提前算好、建成索引,查询时只要算一次问题的向量。DPR(Karpukhin et al. 2020)用”问题—相关段落”对做对比学习训练编码器,在开放域问答上超过了 BM25;今天的各种嵌入模型都是这条路线的后代。
我们的玩具版本(DenseRetriever):词向量是第 1 讲的 PPMI-SVD,在第 5 讲的长尾语料和文档库上训练;段落向量是实词的词向量按 IDF 加权平均。它的优点是能处理换说法:“led by / ruled by / the leader of” 在语料里出现在相似的上下文中,向量相近。
4.3 两种检索器各自错在哪里
02_retrievers.py 演示 1(按句子打包 + 前缀,120 道测试题):
| 问法 | 检索器 | R@1 | R@5 | MRR |
|---|---|---|---|---|
| 标准问法 | BM25 | 57.5% | 95.0% | 0.727 |
| 标准问法 | 稠密 | 24.2% | 50.0% | 0.351 |
| 标准问法 | 混合(RRF) | 36.7% | 78.3% | 0.529 |
| 换个说法 | BM25 | 31.7% | 85.0% | 0.515 |
| 换个说法 | 稠密 | 34.2% | 56.7% | 0.423 |
| 换个说法 | 混合(RRF) | 30.8% | 69.2% | 0.476 |
演示 2 看排在第一的段落是什么:
| 问法 | 检索器 | 相关 | 同一个国家的别的段落 | 另一个国家的同类事实 | 其他 |
|---|---|---|---|---|---|
| 标准问法 | BM25 | 69 | 45 | 6 | 0 |
| 标准问法 | 稠密 | 29 | 36 | 17 | 38 |
| 换个说法 | BM25 | 38 | 70 | 11 | 1 |
- BM25 抓得住实体:国名是稀有词、IDF 很高,一个词就把候选缩到这个国家的几段。它的弱点是措辞:换个说法之后,R@1 从 57.5% 掉到 31.7%,排在第一的常常是”同一个国家的别的段落”(70 / 120)——国名对上了,关系词没对上。
- 稠密检索抓不住实体:它有 55 / 120 次把另一个国家的段落排在第一,BM25 只有 6 次。所有国名的词向量都很像(第 1 讲 §3 说的”同一类别”的相似),一段话平均成一个向量之后,国名这一个词的区别被冲淡了。Sciavolino et al.(2021)在真实的稠密检索器上发现了同样的问题:在”某某人出生在哪里”这类以实体为中心的简单问题上,它们明显不如 BM25,尤其是对不常见的实体。BEIR 基准(Thakur et al. 2021)的一个著名结论也是:零样本时,BM25 是一个很难打败的基线。
我们的稠密检索器是玩具,比真实的嵌入模型弱得多;但”错的方式不同”这一点是普遍的,也是融合的出发点。
4.4 融合
倒数排名融合(RRF,Cormack et al. 2009):。它用排名而不是分数,因为 BM25 分数和余弦相似度不在一个尺度上。
上表里等权的 RRF 不如单独的 BM25:当一个检索器明显更差时,等权融合会把它的错误也混进前几名。演示 3 改用分数的凸组合 ,在训练国家上选 :
| α | 训练 MRR | 测试 MRR | 测试 R@5 |
|---|---|---|---|
| 0.0(纯稠密) | 0.428 | 0.387 | 53.3% |
| 0.5 | 0.651 | 0.577 | 82.5% |
| 0.8(训练集上最好) | 0.720 | 0.629 | 86.2% |
| 1.0(纯 BM25) | 0.689 | 0.621 | 90.0% |
| RRF(等权) | 0.503 | 73.8% |
调出来的 α = 0.8 在测试集上的 MRR 只比纯 BM25 高 0.008,R@5 还更低——在这个文档库上,玩具稠密检索补不上多少 BM25 的短板;调权重的主要价值是避免了等权 RRF 的损失。两个通用的教训:融合的权重要在和测试分开的数据上选(前置讲 P3);任何检索方案都要和 BM25 比一比。
4.5 规模化:近似最近邻
这里的文档库只有几百段,可以逐个算相似度(精确搜索)。真实的文档库有几百万到几十亿段,需要近似最近邻(ANN)索引:例如 HNSW(Malkov & Yashunin 2018)的分层小世界图、FAISS(Johnson et al. 2019)里的倒排 + 量化索引。它们用一点召回率换几个数量级的速度——又一个要在评估里报告的取舍。
5. 检索前与检索后 · Pre- and post-retrieval
5.1 查询改写与多查询
用户的问题不一定用文档里的说法。查询改写先把问题改写成更像文档的形式(Ma et al. 2023 的 Rewrite-Retrieve-Read 用 LLM 改写,再检索、再阅读)。多查询生成几个不同的查询,分别检索,再用 RRF 融合(社区里常叫 RAG-Fusion)。
03_pre_post.py 演示 1(换个说法的 120 道题,BM25):
| 查询怎样处理 | R@1 | R@5 | MRR |
|---|---|---|---|
| 原问题(“who rules X ?”) | 31.7% | 85.0% | 0.515 |
| 改写成标准问法(“who leads X ?”) | 57.5% | 95.0% | 0.727 |
| 多查询:原问题 + 3 种文档里的说法,RRF | 34.2% | 93.3% | 0.592 |
| (对照)用户本来就用标准问法 | 57.5% | 95.0% | 0.727 |
改写把换说法的损失完全补了回来——但这里用的是一张同义词表,在这个文档库上是完美的;LLM 的改写会出错,也可能把问题改歪。多查询提高了召回(R@5 93.3%),却没有提高第一名的准确率:几个查询各自的第一名在 RRF 里平分秋色。**多查询适合”要全”的任务(摘要、多跳),不一定适合”要准”的任务。**两者都多花了调用——检索前处理是在用延迟和成本换召回。
5.2 HyDE:用一个(可能错的)假想答案去检索
HyDE(Gao et al. 2023,Hypothetical Document Embeddings):先让模型写一个”假想的答案段落”,再用它去检索。假想答案在形式上和真正的段落很像,所以更容易检索到它们。
演示 2 用第 5 讲的长尾模型写假想答案:先让它闭卷回答,再把 “the leader of X is 它的答案 .” 当作查询。
| 问法 | 长尾模型的回答 | 题数 | 原问题 R@1 | HyDE R@1 |
|---|---|---|---|---|
| 标准问法 | 答对了 | 103 | 55.3% | 90.3% |
| 标准问法 | 答错了(编的) | 17 | 70.6% | 29.4% |
| 换个说法 | 答对了 | 103 | 27.2% | 90.3% |
| 换个说法 | 答错了(编的) | 17 | 58.8% | 29.4% |
模型知道答案时,HyDE 让 R@1 几乎翻了三倍(换个说法:27.2% → 90.3%):假想段落用的是文档里的说法,还带上了答案本身。模型不知道、编了一个答案时,HyDE 反而有害(58.8% → 29.4%)。第 5 讲发现,长尾模型编答案时借用的是别的国家的同类事实;那个值写进查询,检索器就被带到了那个国家(17 道编出来的题里有 4 道,排在第一的正是”编的答案所属的那个国家”的段落)。
讽刺的是:检索最该帮忙的,正是模型不知道的冷门事实;而 HyDE 恰恰在这些事实上失效。实用的折中是同时用原问题和假想答案检索,再融合。
5.3 重排:cross-encoder 的极简版
检索器要在几百万段里快速找候选,所以只能用 bi-encoder 或 BM25 这样”问题和段落分开处理”的方法。重排器只看检索器给出的前几十个候选,可以把问题和每个候选放在一起仔细打分——这是第 1 讲 §4 说的 cross-encoder:精确但慢。Nogueira & Cho(2019)用 BERT 做的 monoBERT 是这条路线的起点;ColBERT(Khattab & Zaharia 2020)的”迟交互”是介于两者之间的折中。
我们的重排器(Reranker)是一个逻辑回归,特征都要同时看问题和段落:BM25 分数、余弦相似度、问题里的国名在不在段落里(ent)、段落里有没有问题所问关系的某种说法(rel)、以及两者的乘积(ent×rel:“这一段既是关于这个国家的,又讲了这个关系”)。在训练国家上训练,在测试国家上评估:
| 问法 | 检索 | R@1 | R@5 | MRR |
|---|---|---|---|---|
| 标准问法 | BM25 | 57.5% | 95.0% | 0.727 |
| 标准问法 | 混合 + 重排 | 90.8% | 99.2% | 0.948 |
| 换个说法 | BM25 | 31.7% | 85.0% | 0.515 |
| 换个说法 | 混合 + 重排 | 81.7% | 96.7% | 0.885 |
学到的权重里最大的是 ent×rel(+2.49),而 rel 单独的权重是 −0.26:光有关系词不够——每个国家都有一句讲首都的——要的是两个条件同时满足。去掉这一个特征重新训练,换个说法的 R@1 从 81.7% 掉到 61.7%。这正是 bi-encoder 做不到的:把段落压成一个向量之后,“这一段里同时有 X 和’首都‘“这种信息就看不到了。
(坦白一点:这个重排器的关系词表是直接给的,真实的 cross-encoder 是从大量标注过的”问题—段落”对里学到”rules 和 led by 是一回事”的。第一版用词向量做软匹配,PPMI-SVD 词向量分不清这些说法,没有效果。)
5.4 其他检索后处理
- 去重:热门实体常被很多文档用几乎一样的话提到,重复的段落浪费上下文。
- 压缩:只保留段落里和问题相关的句子,或者让一个小模型把段落压成摘要再交给大模型(RECOMP,Xu et al. 2024;LongLLMLingua 一类的提示压缩)。§6 会看到,少放无关的内容本身就能提高准确率。
- 过滤:按相关性分数的阈值丢掉候选,宁可少给也不给错的。
6. 生成这一侧:检索到了 ≠ 用上了 · The generation side
6.1 给几段
04_reading.py 演示 1 把重排后的前 k 段交给两种阅读器(240 道题):
| k | 平均词数 | 相关段落在里面(R@k) | 抽取式阅读器 | 模拟 LLM |
|---|---|---|---|---|
| 1 | 19 | 86.2% | 86.2% | 85.0% |
| 2 | 39 | 95.4% | 95.4% | 93.8% |
| 3 | 55 | 97.5% | 97.5% | 93.3% |
| 5 | 90 | 97.9% | 97.9% | 87.9% |
| 10 | 182 | 98.3% | 98.3% | 87.1% |
| 20 | 364 | 99.2% | 99.2% | 62.5% |
抽取式阅读器从不分心,准确率跟着 R@k 走,k 越大越好。模拟 LLM 在 k = 2 时最好,k = 20 时掉到 62.5%:段落越多,相关的那段越可能落在中间,别国的同类事实也越多。“检索到了”不等于”用上了”,所以 k 要用端到端的准确率来选,而不是只看 R@k。(模拟 LLM 的位置偏好和被干扰的概率是旋钮;真实模型的曲线要自己测。)
6.2 怎么摆:“lost in the middle”
Liu et al.(2024)在真实模型的多文档问答上发现了一个 U 形曲线:相关信息在上下文的开头或结尾时表现最好,在中间时明显变差,有时甚至不如完全不给文档。演示 2 在模拟 LLM 上把相关段落放在 10 段里的不同位置:第 1 位 91.7%、第 10 位 82.5%、最低的第 5 位 65.0%(模拟器的 U 形旋钮加上干扰项的结果;每个位置 120 道题,曲线有噪声)。
一个常见的对策是重新排列:把排名最高的段落放在开头和结尾,次要的放中间(LangChain 等框架里的 “LongContextReorder”)。演示 2 在真实的 BM25 结果(换个说法,k = 10)上比较了三种摆法:按排名 76.7%、反过来 70.8%、两头放好的 73.3%——差别在 120 道题的噪声范围之内。排名靠前的段落本来就最相关,按排名放已经把它们放在了开头;重新排列只有在”最相关的段落常常排在中间”时才有意义。和别的技巧一样:在你的模型和你的检索结果上测,不要照搬。
6.3 引用对不对:归因
演示 3 故意用一个较弱的检索(BM25,换个说法,k = 2),让一部分题目检索不到答案;模拟 LLM 找不到时,一半的情况下用第 5 讲长尾模型的答案”凭记忆”补,并且照样给出引用:
| 情况 | 题数 | 答对 | 答 unknown | 引用的段落确实支持这个答案 |
|---|---|---|---|---|
| 检索拿到了 | 59 | 100% | 0% | 100% |
| 检索没拿到(热门) | 48 | 54% | 46% | 0% |
| 检索没拿到(冷门) | 13 | 38% | 23% | 0% |
检索没拿到答案时,热门事实上模拟 LLM 仍然答对了一半(记忆里有),但它引用的段落不支持这个答案——即使答案碰巧是对的。只看”答对了没有”的评估发现不了这一点。所以 RAG 的评估要单独看归因:回答里的说法能否被它引用的段落支持(Rashkin et al. 2023 的 AIS 框架;Gao et al. 2023 的 ALCE 基准专门评估带引用的生成)。对策:在提示里明确”只根据资料回答,资料里没有就说 unknown”(第 5 讲 §5.4),并在输出端自动检查引用。
7. 什么时候检索、相信谁 · When to retrieve, whom to trust
7.1 冷门 vs 热门
05_when_to_retrieve.py 演示 1 把第 5 讲长尾模型的闭卷回答和 RAG(抽取式阅读器)按出现次数分档比较,检索有”一般”(混合检索,不重排)和”好”(混合 + 重排)两种质量:
| 出现次数 | 事实数 | 闭卷 | RAG:一般的检索 | RAG:好的检索 |
|---|---|---|---|---|
| 0 次 | 24 | 4.2% | 29.2% | 100.0% |
| 1 次 | 24 | 20.8% | 70.8% | 100.0% |
| 2 次 | 29 | 96.6% | 82.8% | 100.0% |
| 3–5 次 | 64 | 100.0% | 87.5% | 100.0% |
| 6–20 次 | 58 | 100.0% | 69.0% | 100.0% |
| 21 次以上 | 41 | 100.0% | 61.0% | 97.6% |
冷门事实上检索是决定性的;热门事实上,一般的检索反而有害(100% → 61%):模型本来就知道,检索却拿错了段落,而热门国家被新闻、报告、游记提到得多,干扰项也多。好的检索几乎消除了这个损失。**检索有没有害,取决于检索有多好。**Mallen et al.(2023)在真实模型和真实的维基百科检索上得到了同样的形状:对热门实体,检索增强有时会降低大模型的准确率;对冷门实体,检索的帮助远大于把模型变大。
7.2 自适应检索
既然如此,能不能只在需要时才检索?演示 2 用长尾模型的置信度当开关:置信度低于 τ 才检索,否则用闭卷答案。
| 阈值 τ | 检索了多少 | 准确率:一般的检索 | 准确率:好的检索 |
|---|---|---|---|
| 0(从不检索) | 0% | 82.1% | 82.1% |
| 0.5 | 27% | 88.3% | 98.8% |
| 0.9 | 54% | 85.4% | 99.6% |
| 0.95 | 68% | 82.1% | 100.0% |
| 1.01(总是检索) | 100% | 70.4% | 99.6% |
| 按热门程度:百科篇数 < 3 才检索 | 53% | 85.8% | 100.0% |
一般的检索下,τ = 0.5 时最好(88.3%),只检索了 27% 的问题——比总是检索(70.4%)和从不检索(82.1%)都好。好的检索下,自适应的好处主要是省:τ = 0.9 时只检索一半,准确率不变。
能这样做,靠的是第 5 讲的结论:长尾模型的置信度能很好地区分对错(AUROC 0.95)。置信度不可靠的模型就不能用它当开关。Mallen et al.(2023)用实体的流行度当开关(表的最后一行是它的对照版本);Self-RAG(Asai et al. 2024)把”要不要检索、检索到的段落有没有用”训练成模型输出的特殊 token;FLARE(Jiang et al. 2023)在生成过程中,遇到低置信度的词才去检索。这些都是”模块化 RAG”:检索不是固定的一步,而是一个可以被调用、也可以不被调用的模块——第 8 讲会把它正式变成一个”工具”。
7.3 资料和记忆冲突时,听谁的?投毒
RAG 带来一个新的攻击面:文档库本身。演示 3 往文档库里加了 20 篇”更正”,每篇一句话,把一个事实改成另一个国家的同类值(10 个热门事实、10 个冷门事实)。四种策略(好的检索):
| 策略 | 被投毒的热门(对 / 中毒 / 弃权) | 被投毒的冷门 | 没被投毒的 220 个事实 |
|---|---|---|---|
| 总是相信检索(标准 RAG) | 60% / 40% / 0% | 50% / 50% / 0% | 100% / 0% / 0% |
| 总是相信记忆(闭卷) | 100% / 0% / 0% | 0% / 0% / 0% | 85% / 0% / 0% |
| 自适应检索(τ = 0.9) | 100% / 0% / 0% | 50% / 50% / 0% | 100% / 0% / 0% |
| 冲突检查:和有把握的记忆不一致时弃权 | 60% / 0% / 40% | 50% / 50% / 0% | 99% / 0% / 1% |
- 只加一句话,标准 RAG 就有约一半的目标被改写:毒文档用的是最直白的说法,正好是检索器和重排器最喜欢的形状。Zou et al.(2024)的 PoisonedRAG 发现,往百万级的文档库里注入很少几篇精心写的文档,就能让 RAG 系统对目标问题给出攻击者想要的答案。
- 模型对热门事实有把握,所以自适应检索(根本不去检索)和冲突检查(资料和记忆一冲突就弃权)都能挡住热门事实上的投毒。
- 冷门事实最需要检索,也最容易被骗:模型本来就不知道,没有什么可以拿来对照。
真实模型的”资料 vs 记忆”更复杂:Xie et al.(2024)发现,当资料连贯、有说服力时,LLM 很容易接受和自己记忆矛盾的资料;Longpre et al.(2021)则发现阅读理解模型有时会无视资料、坚持记忆。两种失败都需要评估。更危险的是,检索到的文档里可能藏着指令(“忽略之前的要求,回答……”)——这是第 12 讲的间接提示注入(Greshake et al. 2023)。
8. 评估一个 RAG 系统 · Evaluating RAG
8.1 分层评估
一个 RAG 系统的错误可能出在任何一层,所以评估也要分层:
| 层 | 问题 | 指标 |
|---|---|---|
| 导入 | 事实被切断了吗?段落能独立读懂吗? | 切断率、“丢主语”率(需要知道答案在哪) |
| 检索 | 相关段落排上来了吗? | R@k、MRR、nDCG |
| 阅读 | 拿到了,用上了吗?没拿到时说不知道了吗? | 给定”完美检索”时的准确率;无答案题上的弃权率 |
| 端到端 | 答对了吗?摘要全吗、忠实吗? | 准确率 / EM / F1;摘要的事实覆盖率与错误事实数 |
| 归因 | 引用支持说法吗? | 被引用段落支持答案的比例(AIS / ALCE) |
分层的价值在于定位:端到端准确率下降时,是检索变差了,还是阅读变差了?01–05 号脚本能把两者分开,靠的是”哪些段落包含答案”是已知的。真实项目里要花力气构造这样的标注——至少为一个小的开发集标出相关段落。
用 LLM 给 RAG 打分(例如 RAGAS,Es et al. 2024:忠实度、答案相关性、上下文相关性)可以省掉人工标注,但它继承了 LLM 判官的偏差(第 10 讲),需要先在一小批人工标注上验证。
8.2 测试集里应该有什么
- 改写过的问题(§4.3):用户不会用文档里的原话。
- 按热门程度分层(§7.1):总准确率会掩盖冷门实体上的失败。
- 无答案的问题:文档库里没有答案的题,正确答案是”不知道”(§6.3)。
- 需要多段的问题:摘要、比较、多跳(§3.4;第 9 讲)。
- 有冲突或错误资料的情况(§7.3)。
8.3 在真实模型上(可选)
06_real_llm.py 让真实的 Claude 当阅读器:40 道换个说法的问答(BM25 前 2 段,一部分题检索不到答案)、10 份摘要(重排后的前 5 段)、以及 05 号脚本的 20 个被投毒的事实(前 3 段里真假资料都有),比较”只说根据资料回答”和”资料互相矛盾时回答 conflict”两种提示。真实模型不知道这个虚构世界,它只能靠检索到的段落,所以这是检验”阅读这一侧”的干净设置。--toy 模式用 SimReaderLLM 跑通同一段代码(它不会说 conflict);编写环境里没有安装 anthropic SDK,真实模型的结果没有报告,留给读者自己运行。
9. 小结 · Summary
- 为什么检索:长尾、过时、私有、可溯源。RAG 管”知道什么”,微调管”怎么做”。前提是阅读器会读——迷你 GPT 学不会,这本身说明阅读能力来自规模和专门的训练。
- 架构:导入(分块 → 编码 → 索引)、查询(检索前 → 检索 → 检索后)、生成(拼提示 → 回答 → 引用);朴素 → 高级 → 模块化 RAG。
- 分块:切点落在句子 / 结构边界上,或者加重叠(被切断的事实 26% → 5%);给每段加上文档标题是最大的单项改进(按结构分块时问答 39.2% → 94.2%)。问答要”准”、摘要要”全”。
- 检索:BM25 抓得住实体、怕换说法;稠密检索不怕换说法、却常把别的实体排上来(55 / 120 次)。等权融合可能变差,权重要在开发集上调;任何方案都要和 BM25 比。
- 检索前后:改写把换说法的损失补回来;多查询提高召回、不提高第一名;HyDE 在模型知道答案时把 R@1 从 27% 提到 90%,在模型编答案时从 59% 降到 29%;交互特征(“这一段既关于 X、又讲了这个关系”)让重排把 R@1 提到 91% / 82%。
- 生成:检索到了 ≠ 用上了。会分心的阅读器在 k = 2 时最好、k = 20 时 62.5%;相关段落在中间时最难读到;凭记忆补的答案引用的段落不支持它。
- 什么时候检索:一般的检索会伤害热门事实(100% → 61%);用可靠的置信度做自适应检索,准确率最高、检索更少。冷门事实最需要检索,也最容易被投毒骗。
- 评估要分层:导入、检索、阅读、端到端、归因;测试集里要有改写、分层、无答案、多段、冲突的题。
10. 常见误区 · Common pitfalls
| 误区 | 实际情况 |
|---|---|
| “分块是个工程细节,随便切切就行” | 分块方式和标题前缀对端到端准确率的影响,可以比换检索器还大(39% vs 94%) |
| “稠密检索 / 向量数据库总比关键词搜索好” | 在以实体为中心的问题上,BM25 常常更强;先在自己的数据上测 BM25 |
| “混合检索一定更好” | 等权融合会把较差的那一路的错误带进来;权重要在开发集上调 |
| “R@k 高,问答就好” | 检索到了 ≠ 用上了:段落太多、相关段落在中间、干扰项多,阅读都会变差 |
| “给的段落越多越保险” | 更多的段落 = 更多的 token、更多的干扰;k 要用端到端准确率选 |
| “有引用就说明答案有依据” | 模型可能凭记忆回答再随便引用一段;要单独评估归因 |
| “每个问题都应该检索” | 对模型有把握的热门事实,不够好的检索反而有害;还多花钱、多一个被投毒的入口 |
| “HyDE / 查询改写总是有帮助” | 它们依赖模型自己的知识或改写能力;模型编错答案时,HyDE 把检索带偏 |
| “文档库是可信的” | 文档库可以被投毒,检索到的文档里也可能藏着指令(第 12 讲) |
11. 练习 · Exercises
练习 1(计算 BM25) 一个文档库有 N = 100 段。词 “stindia” 出现在 2 段里,词 “capital” 出现在 60 段里。某一段长度等于平均长度,含 “stindia” 1 次、“capital” 1 次。取 k1 = 1.2、b = 0.75。(a)分别算两个词的 IDF。(b)问题 “capital of stindia” 对这一段的 BM25 分数是多少?(c)这说明了什么?
参考答案:(a)IDF = log((N − df + 0.5)/(df + 0.5) + 1)。stindia:log(98.5/2.5 + 1) = log(40.4) ≈ 3.70;capital:log(40.5/60.5 + 1) = log(1.669) ≈ 0.51。(b)长度等于平均长度时,分母里的长度项为 1,每个词的 tf 部分是 1 × 2.2 / (1 + 1.2) = 1。分数 = 3.70 + 0.51 = 4.21(“of” 是停用词)。(c)几乎全部分数来自国名:BM25 在实体问题上强,是因为稀有的实体名 IDF 很高;关系词(capital)几乎在每个国家的页面里都有,区分力很弱——这也是换个说法时 BM25 的第一名常常是”同一个国家的别的段落”的原因。
练习 2(设计分块) 你要给公司的员工手册(200 页,有章、节、小节标题,很多段落用”本条款”、“上述规定”指代)搭一个 RAG 问答。你会怎样分块?说出至少三个决定和理由。
参考答案(一种可能):(1)按结构切:以小节为单位,太长的小节再按段落或句子打包,不在句子中间切。(2)给每一段加上”章 > 节 > 小节”的标题路径作为前缀,或者用 LLM 生成一句上下文说明(Contextual Retrieval),解决”本条款”这类指代丢失的问题。(3)对按长度切的部分加少量重叠,或保证不跨小节。(4)保留段落的元数据(页码、条款号)用于引用和过滤。(5)在一组带有标注答案位置的开发问题上,比较几种方案的 R@k 和端到端准确率,同时测”要汇总多个条款”的问题(摘要式),因为两类问题的最佳方案可能不同。
练习 3(读表) §4.3 的表里,换个说法时,稠密检索的 R@1(34.2%)比 BM25(31.7%)高,可 R@5(56.7% vs 85.0%)低得多。解释这两个数字为什么方向相反,以及这对”混合检索”意味着什么。
参考答案:BM25 的错误主要是”找对了国家、拿错了段落”:前 5 名里通常都是这个国家的段落,所以 R@5 高,但第一名常常不是讲这个关系的那段。稠密检索不太受措辞影响,偶尔能把讲对了关系的那段排第一;但它常常把别的国家的同类段落排上来,所以前 5 名里经常一段这个国家的都没有,R@5 低。两者的错误是互补的:BM25 负责”找对实体”,稠密负责”找对关系”——这是混合检索或重排(先用 BM25 圈定候选,再用能看关系的打分器排序)的道理。但互补不等于等权融合就好:需要调权重,或者用重排器把两种信号组合起来(§5.3 的 ent×rel)。
练习 4(解释) 为什么 §7.1 里,一般的检索会让热门事实的准确率从 100% 降到 61%,而对冷门事实却是提升?用”检索带来的信息”和”检索带来的噪声”两个量来解释,并说明为什么自适应检索能取两者之长。
参考答案:检索的净效果 = 它带来的新信息 − 它带来的噪声(拿错段落导致的错误)。冷门事实上,模型原本几乎不知道(闭卷 4%),检索带来的信息远大于噪声,净效果为正。热门事实上,模型原本就知道(闭卷 100%),检索带来的新信息为零,只剩噪声;而热门实体在文档库里被提到得多,干扰项也多,噪声更大。自适应检索用置信度估计”模型知不知道”:知道就不检索(避开噪声),不知道才检索(拿到信息)。它要求置信度是可靠的——这又回到第 5 讲的校准和 AUROC。
练习 5(批判) 有人说:“我们的 RAG 系统上线前测了 R@5 = 95%,所以回答基本都有依据。“列出至少三个你会追问的问题。
参考答案:(1)R@5 是在什么问题上测的?是不是用文档原话写的问题?用户的真实问法(换个说法、拼写错误、多意图)上是多少?(2)检索到了,阅读器用上了吗?端到端准确率是多少?给 5 段时,相关段落在中间的那些题表现如何?(3)检索没拿到答案的 5% 里,系统说”不知道”了吗?还是凭记忆回答、再随便引用一段?引用的支持率是多少?(4)按实体的热门程度、文档类型分层看过吗?(5)文档库里有没有过时或互相矛盾的资料?有人能往里面写东西吗(投毒、间接注入)?
练习 6(动手) 修改 rag_lab.wiki_page,让所有事实都用带国名的”显式”说法(把 25% 改成 100%),重新运行 01 号脚本。预期标题前缀的作用会怎样变化?
参考答案:显式说法下每个事实句都自带国名,段落不再”丢主语”,不加前缀时能独立读懂的比例接近 100%,标题前缀带来的提升会大幅缩小(主要只剩下对检索的帮助:前缀让段落多了一次国名,BM25 分数更高)。这说明标题前缀解决的是指代问题;文档的写法决定了分块之后丢失多少上下文。实际数字要运行才知道。
练习 7(设计评估) 为作业 3 设计一个实验:比较两种分块方式(按句子 vs 按固定长度 + 重叠)和两种检索器(BM25 vs 混合),在问答和摘要两种任务上。说出你的自变量、因变量、对照、统计方法。
参考答案(一种可能):自变量:分块方式(2)× 检索器(2),四种组合;检索深度 k 固定(或作为第三个因素扫描)。因变量:问答——R@k、端到端准确率、无答案题上的弃权率、引用支持率;摘要——事实覆盖率、错误事实数(忠实性)、平均 token 数。对照:闭卷(不检索)和”完美检索”(直接给相关段落),分别给出下界和阅读器的上界。数据:开发集调 k 和融合权重,测试集只用一次;问题按实体热门程度分层,包括改写过的问法。统计:同一批问题上的配对比较(McNemar 或配对 bootstrap,前置讲 P3),报告置信区间;多组比较时做多重比较校正。
12. 延伸阅读 · Further reading
RAG 的提出与综述
- Lewis et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS.
- Guu et al. (2020). REALM;Borgeaud et al. (2022). Improving Language Models by Retrieving from Trillions of Tokens(RETRO)。
- Gao et al. (2023). Retrieval-Augmented Generation for Large Language Models: A Survey.——朴素 / 高级 / 模块化 RAG。
检索
- Robertson & Zaragoza (2009). The Probabilistic Relevance Framework: BM25 and Beyond.
- Karpukhin et al. (2020). Dense Passage Retrieval for Open-Domain Question Answering.
- Thakur et al. (2021). BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models.
- Sciavolino et al. (2021). Simple Entity-Centric Questions Challenge Dense Retrievers.
- Cormack et al. (2009). Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods.
- Nogueira & Cho (2019). Passage Re-ranking with BERT;Khattab & Zaharia (2020). ColBERT.
- Malkov & Yashunin (2018). HNSW;Johnson et al. (2019). Billion-scale Similarity Search with GPUs(FAISS)。
检索前后处理
- Ma et al. (2023). Query Rewriting for Retrieval-Augmented Large Language Models.
- Gao et al. (2023). Precise Zero-Shot Dense Retrieval without Relevance Labels(HyDE)。
- Xu et al. (2024). RECOMP: Improving Retrieval-Augmented LMs with Compression and Selective Augmentation.
- Anthropic (2024). Introducing Contextual Retrieval(博客)。
生成与归因
- Liu et al. (2024). Lost in the Middle: How Language Models Use Long Contexts. TACL.
- Rashkin et al. (2023). Measuring Attribution in Natural Language Generation Models(AIS);Gao et al. (2023). Enabling Large Language Models to Generate Text with Citations(ALCE)。
- Es et al. (2024). RAGAS: Automated Evaluation of Retrieval Augmented Generation.
什么时候检索、冲突与安全
- Mallen et al. (2023). When Not to Trust Language Models: Investigating Effectiveness of Parametric and Non-Parametric Memories.
- Asai et al. (2024). Self-RAG;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.
- Zou et al. (2024). PoisonedRAG;Greshake et al. (2023). Not What You’ve Signed Up For(间接提示注入)。
- Ovadia et al. (2024). Fine-Tuning or Retrieval? Comparing Knowledge Injection in LLMs.
13. 下一讲预告 · Next lecture
这一讲的 RAG 是一个固定的流水线:每个问题都先检索、再回答。§7 已经看到,“什么时候检索”本身就值得让模型来决定。第 8 讲继续原课第 5 周:提示增强(二):工具使用——把检索、计算器、数据库、网页浏览都看作模型可以调用的工具。
- 为什么要工具:模型不擅长的计算、实时的信息、需要真正”做”的事;
- Toolformer 的”采样—执行—过滤”:模型怎样自己学会在哪里调用工具——我们会在第 5 讲的长尾模型上做一个迷你版,看它是否学会只在冷门事实上查询;
- 函数调用与 JSON Schema、WebGPT(为浏览而微调、引用来源)、工具使用中的规划与自我批判;
- 原课作业 2 的核心对比:单阶段提示 vs 多阶段任务分解,以及工具描述的写法怎样影响调用的准确率。