跳到主要内容

把回答钉在文档上 — 检索增强的全流程与它的代价

这一章讲三件事: 怎么让一个从没读过你公司文档的模型照着你的文档回答; 这条流水线的每一步具体在做什么、每一步会怎么坏; 以及一种反过来的形态——不是我们先取好塞给它,而是它开口说「我要调这个函数」。

它在全书链条里的位置: 第 04 章的阶梯到头了,因为提示词治不了「它不知道你家的事」。 这一章是「让它说得准」这一层真正的主力,后面第 06–09 章全都是在修这一章的某一步。

1. 顶层全景:一个问题走完全程

这一章的主走查是一个具体问题:「用礼品卡买的电子产品,退货政策是什么?」

【不接任何外部资料】
问题 ──→ 模型 ──→ 「大多数零售商允许 30 天内退货,不过礼品卡购买可能条款不同。」
听着专业、语气笃定 —— **完全是编的**

【接上外部资料之后】
┌─ 事先做好(建索引):
│ 退货政策 PDF → 载入 → 切成小块 → 每块转成一串数 → 存进一个可查的库

└─ 每次提问时:
问题也转成一串数 → 在库里找最接近的 3 块 → 把这 3 块原文拼进提示词
→ 模型照着写 →
「按我们现行政策,用礼品卡购买的电子产品可在 14 天内退成店铺积分,
或在 30 天内换货。所有退货都需要原始的礼品卡收据。」
→ 而且能指出这句出自哪一份文件

图说:上下两条路,模型是同一个、提示词几乎一样。**变的只是它手上有没有材料。**
上面那两段回答是书里的真实例子,不是我们编的。

这条走查分五步走完,每一步挂在哪一节:

走查在哪一节这一步看什么
第 ① 步第 3 节不接任何资料时,它说了什么
第 ②③④ 步第 4 节「事先做好」那半边:载入 → 切分 → 转成一串数 → 存进可查的库
第 ⑤ 步第 8 节反过来的那种形态,和上面那条路其实在做同一件事

另外四节不占走查的步: 第 2 节讲这套东西为什么非做不可(不能靠「再训一次」代替), 第 5 节把第 ② 步的「切分」单独拆开细讲,第 6 节讲它自己要付的六条代价, 第 7 节点破书里示例项目的一处技术错误。

2. 为什么不能「再训一次让它记住」

这一节回答一个所有人都会先想到的方案,并说清它为什么在两个层面上都不成立。

先看现象:一个模型答不出来的问题

顾客问:「你们那台 55 寸带音响条的 OLED 电视,今天能当日达吗?」1

这句话里没有一个词是它不认识的,可它就是答不了——因为答案取决于此刻的库存和配送范围。

「那就把这些也训进去」为什么行不通

作者给了两条理由,而且这两条的性质完全不同2:

理由具体是什么性质
算不动要把「所有产品 × 所有地点 × 所有配送方式」的组合全塞进去规模问题——理论上不可能穷举
一出厂就过期供应链天天变、库存分分钟变时效问题——哪怕塞得进去,训完那一刻它就已经旧了

第二条才是致命的。 规模问题还能靠「只训重要的那部分」缓解; 时效问题是结构性的:训练是一次性的,而事实是流动的。

书里第二个例子更漂亮,值得记住

「这台 55 寸 OLED 电视,把后排座椅放倒,塞得进我的丰田普锐斯吗?」3

这个问题的妙处在于:它需要同时取到两件事——电视的外箱尺寸、 以及那款车后备箱放倒后的容积——然后做一次比较

任何单独一份文档里都没有这个答案。 (这条线索先记住:它在第 09 章会长成一个专门的手段。)

3. 两步动作,三个部件

这一节给这套做法一个准确的定义,并说清谁干什么。

定义:它就是两步

第 01 章挂过这个名字,这里给它完整的定义:

检索增强 = 两步动作。 第一步,按用户的问题,从最新的外部来源里取回相关的信息; 第二步,把取回的内容当作材料,交给模型去写答案。4

它不是一个产品,不是一个框架,也不是某个厂商的功能。 它就是这两步。 你可以用一百行代码自己实现,也可以买一整套平台——做的都是这两件事

三个部件

部件干什么一句话记住
检索器从数据库、文档、网页或者外部接口里,把和这个问题最相关的几段找出来书叫它「系统的侦察兵」5
生成器就是模型本身。它拿到「原问题 + 取回的内容」,写出回答它不负责找,只负责写
知识源被整理过、可以被快速查找的资料本体注意「被整理过」这四个字

第三行的「被整理过」是这一节唯一的机关:资料必须事先整理成一份能快速查的目录, 这件事就叫建索引——不是等用户问了才临时去翻。6

为什么必须事先做: 用户在等回答。如果每次提问都要把几万份文档从头读一遍, 这一步的时间会比生成答案本身长几个数量级。

走查第 ① 步:不接资料时它说了什么

问: 用礼品卡买的电子产品,退货政策是什么?
答: 「大多数零售商允许 30 天内退货,不过礼品卡购买可能条款不同。」

拆开看这句话:
「大多数零售商」 ← 它在讲行业惯例,不是在讲你家
「30 天」 ← 一个很常见的数,所以它「像样」
「可能条款不同」 ← 一句免责,听着谨慎,其实什么也没说

图说:这就是第 02 章那类幻觉的标准长相——**通顺、稳妥、格式正确、内容是编的。**

4. 「建索引」不是一句命令,是四步

这一节把「事先做好」那半边拆开。四步各有各的坑,后面四章分别去修。

书里的四步7:

① 载入(Load) 从文本文件、结构化数据文件、网页等各种源头,把原始资料读进来

② 切分(Split) 把长文档切成小段

③ 转成一串数(Embed) 每一小段算出一串数字

④ 存起来(Store) 把这些数存进一个能快速按「接近程度」查找的库

图说:①② 决定了「有什么可找」,③④ 决定了「找不找得到」。
第 06–08 章分别去修 ③ 和 ④,这一章负责 ① 和 ②。

第 ③ 步先给一个够用的解释

每一小段文字,会被算出一串数字——常见是几百个数排成一列。

关键不在于「它是一串数」,而在于这串数落在哪里:意思相近的文字,算出来的数也彼此相近。 「狗」和「小狗」的那串数,比「狗」和「猫」的更接近8

这串数的正式名字就叫嵌入——「这段文字的嵌入」,说的就是它对应的那串数。有了它,「两段话意思像不像」就变成了「两串数近不近」—— 机器终于有东西可算了。

书在这里用了一个比方: 给一屋子的书编目,不去记每本书的每个字, 而是给每本书做一张卡片,写上主题、话题和整体气质;卡片比整本书好翻得多这个比方到此为止——它解释了「为什么要压缩成一个索引」, 但解释不了「为什么意思近的就数也近」。那个问题是第 06 章一整章的内容。

走查第 ②③④ 步

① 载入: 退货政策 PDF(假设 12 页)读进来
② 切分: 切成 47 小段
③ 转成数:47 段各算出一串 384 个数
④ 存起来:存进一个能按「接近程度」检索的库,每条记着「它来自第几页」

提问时:
「用礼品卡买的电子产品,退货政策是什么?」也算出一串 384 个数
→ 在 47 条里找最接近的 3 条
→ 命中第 8 段(礼品卡购买条款)、第 3 段(电子产品类目)、第 22 段(收据要求)

图说:**47、384、3 这三个数是为演示编的**,书里没有给具体规模;
但「问题和文档用同一种方式算成数、再比接近程度」这个流程是书里的。

5. 切块:这一步的两难,书说它「最被低估」

这一节讲第 ② 步。它看着最不起眼,却决定了整个系统能不能答对。

把长文档切成小段这件事,叫切块(切出来的每一小段叫一块)。 书的原话是:它可能是检索增强系统设计里最被低估的一环9

先看现象:一个答不出来的问题

书用的是一段真实的政策条文(加州家庭权利法案):

「本法为符合条件的员工提供最多 12 周的工作保障休假…… 要符合条件,员工须在本公司工作满一年,且在休假前 12 个月内工作满 1250 小时。」

用户问:「我符合这个休假的条件吗?」

两种切法,两种错法

切得小(100–200 个词元):
块 A:「本法为符合条件的员工提供最多 12 周的工作保障休假……」
块 B:「要符合条件,员工须在本公司工作满一年,且工作满 1250 小时。」

系统取回块 A(它和「这个休假」最像)

回答:「有这么一项休假政策,最多 12 周。」 ← **答了政策存在,没答你符不符合**

切得大(500 个词元以上):
一块里既有政策名、又有资格条件 —— 好
但这一块里还混着别的三项政策 —— 它和「资格条件」这个问题的相关度被稀释

排序时它可能根本进不了前三

图说:小块把该在一起的切散了;大块把该突出的稀释了。**两头都错,只是错法不同。**

这就是这一步的两难,而且它没有一个「正确答案」。10

书给的两条解法

第一条:按内容的种类切,不要一刀切11。下面这张表里的「内容类型」就是指内容属于哪一类。

内容是什么怎么切为什么
法律、政策条文按条、按节切保住完整的法律概念和定义
叙述性文章按段落切,并设一个最小长度保住行文的连贯
技术文档保住代码块和函数不被切开让例子和它的解释待在一起
其余定长滑窗兜底(比如每块 500 个词元)——

第二条:让相邻的块重叠一部分,当边界的保险。

不重叠:
块 1 |------- 0 ~ 500 -------|
块 2 |------- 500 ~ 1000 -------|
↑ 正好切在「要符合条件」这句话中间

重叠 100 个词元:
块 1 |------- 0 ~ 500 -------|
块 2 |----- 400 ~ 900 -----|
↑ 「要符合条件」这句话在两块里都完整出现

图说:重叠不是浪费,是给「切错位置」买的保险。

书给的经验值:政策类文档按节切 + 约 20% 的重叠12这个数有参照物:500 个词元的块,20% 就是 100 个词元的重叠——大约一两句话的量。

判断(我们的,不是书里的): 切块是这一章里最该先做实验、最不该照抄默认值的一步。 理由是上面那个两难没有通解:它取决于「你的用户问的问题有多细」。 问「有没有这项政策」的系统,和问「我符不符合条件」的系统,最优切法是不一样的。 可行的做法:拿二十个真实问题,只改切块大小跑两遍,看命中率。 如果错,会错在: 如果你的文档本身结构极强(比如每条政策都是独立的一小节), 那按结构切就是唯一合理答案,做实验是白花时间。 判据是:你的文档里,一个完整的意思会不会跨越自然的分节边界。

6. 它不是银弹:六条代价,书自己列的

这一节是这一章最该带走的部分,因为它是唯一不会让你高估这套东西的部分。

作者在讲完好处之后,紧接着列了六条13:

#代价 / 失效模式说人话
1建索引有一次性成本,也有持续成本文档变了就要重做;资料越多越贵
2每次查询都多一段等待「找」这一步的时间,加在「写」之前
3可能漏掉该找的答案在库里,就是没被取出来
4可能捞上来不相关的取回三段,两段没用,还占着提示词的位置
5给对了材料,它照样可能编这一条最要命,单独讲,见下
6多了一整套要运维的东西那个能按接近程度查找的库,得有人管

外加一条实用建议:如果你的知识库又小又稳定,直接把内容写进提示词更简单也更便宜, 不必上一整套流水线。14

第 5 条:给对了材料它照样可能编

这不是一句免责声明,书在同一章里说了两遍15

回到第 02 章那个分类:

那一章的分类这一章能不能治
与世界知识矛盾(没材料,自己编)能治。 这一章整章就是在治它
与所给材料矛盾(有材料,还说错)治不了。 材料就摆在它面前,它仍可能把「14 天」写成「30 天」

为什么治不了: 把材料塞进提示词,改变的是它手上有什么; 没有改变的是它写答案的动作——还是第 02 章那个,一个词元一个词元挑「像样的」。 「30 天」在退货政策的语境里太像样了,而正确答案「14 天」并没有因为出现在材料里就自动占优。

所以这一章不是终点。 「取回来的对不对」要靠第 07 章去修, 「写出来的忠不忠于材料」要靠第 09 章和第 17 章去核。 书自己的话是:检索增强提高了可靠性,但没有消除对监督、护栏和评测的需要。

7. 书里那个示例项目有一处技术错误,我们点破它

这一节不讲原理,讲一件必须说的事:书是未定稿,这一章的示例代码不能照抄。

原书这一章末尾用一套开源工具从零搭了一条完整的流水线(装库 → 载入 → 切分 → 转成数 → 存进库 → 准备模型 → 检索 → 串起来 → 测试)。流程本身是对的,但第 6 步选错了模型。

它选的是一个「抽取式问答」模型16。这类模型的工作方式是: 给它一段话和一个问题,它从这段话里划出一个片段当答案—— 它不会生成任何新的句子

而这条流水线的最后一步需要的恰恰是「生成」: 拿三段材料,写出一段连贯的回答。 把一个只会划片段的模型放在这个位置上,这条流水线在逻辑上就不成立。

这一处我们必须点破,理由有两条:

  1. 照抄它的人会得到一个跑不出正确结果的系统,而且很难看出问题在哪;
  2. 它暴露了一个真实存在的混淆: 「能回答问题的模型」和「能生成回答的模型」不是一回事。 第 06 章会再遇到这个区分——那里有一类模型专门用来判断两段文字像不像,同样不生成任何东西。

8. 反过来的那种形态:它自己开口说要调什么

这一节讲这一章的最后一个机制,而它是后面四章的地基。

先看现象:模型没法自己上网查天气

问它「巴黎现在几度」,它有两种表现:

  • 老实的: 「抱歉,我没法访问实时数据。」
  • 不老实的: 「巴黎现在晴,25°C。」 ← 这是编的,而你看不出来

前面那套做法是我们主动把材料取好塞给它。可有些事我们事先不知道该取什么—— 用户问哪个城市、问哪个订单号,得看他怎么问。

做法:让它开口说

于是有了反过来的一步:我们事先告诉它「有哪些函数可以调、每个函数要什么参数」, 然后它在需要时开口说出「我要调哪个、参数是什么」。

这件事叫函数调用。 三步17:

① 模型判断自己需要外部数据,于是不写答案,改写出一个调用请求:
{"name": "get_weather", "arguments": {"location": "Paris, FR"}}

② **我们的代码**执行这个调用(真的去请求天气服务),拿到结果:
{"temp_c": 20, "condition": "cloudy"}

③ 我们把这个结果塞回对话里,让模型接着写最终回答:
「巴黎现在 20°C,多云。」

图说:**第 ② 步不是模型做的,是你的程序做的。** 这一点是全书最容易被误解的地方之一,
第 14 章会再强调一次。上面这段 JSON 的形状取自书里的示例,具体数值是为演示编的。

上面那两行是一种到处都在用的数据写法:用大括号、引号和冒号,把「名字 → 值」一条条写成文本。 这种写法叫 JSON,你在任何接口文档里都会看到它。

JSON 里 "name""arguments" 这样的「名字」,一个名字加上它对应的值,合起来就叫字段

我们怎么告诉它有哪些函数

在每次请求里,连同用户的问题一起,附上一份对函数的描述。书里的原样长这样18:

{
"name": "get_weather",
"description": "Lookup the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and state, ISO country code, or zip code"
}
}
}
}

注意 description 那两行:它们是写给模型看的。 模型就是靠这段话判断「这个函数是干什么的、什么时候该用它、参数该填什么格式」。 (「工具描述其实是写给模型看的路由指令」这句话在第 14 章会变成一条硬规矩。)

一个顺带的好处,书特意点了出来

函数调用同时把输出的格式钉死成了函数参数的形状。19

这句话的价值超出防幻觉本身。 模型平时输出的是自由文本,你要从里面抠出结构化信息 就得写一堆代码去拆句子(把一段文本按规则拆出结构,这个动作叫解析), 还得处理它偶尔换个格式的情况。 而函数调用的输出天生就是结构化的——因为参数的格式是你规定好的。

走查第 ⑤ 步:两种形态其实在做同一件事

【先取好再给】 用户问题 → 我们去库里找 → 把材料塞进提示词 → 它照着写
谁决定取什么:**我们的检索器**

【它开口要】 用户问题 → 它说「我要调 get_weather(Paris)」→ 我们执行 → 结果塞回去 → 它照着写
谁决定取什么:**模型自己**

图说:两条路的第一步和最后一步完全一样——**都是把回答锚在一份外部真值上**。
唯一的差别是「谁来决定取什么」。

而这个差别,正是后面四章的分水岭:

  • 它只是「取信息」的时候,系统还是被动的;
  • 一旦它能调的函数会真的改变外部世界(真的下单、真的发确认信、真的改日历), 系统就跨过了一条线第 13 章会把这条线讲清楚,第 14 章讲工具多起来之后怎么办。

9. 作者的判断与证据

书里给了证据的:

说法证据是什么
不接资料时它会编一个像样的政策一组真实的前后对照(礼品卡退货那两段回答)
切块的两难一段真实的政策条文 + 两种切法各自的失败路径
六条代价作者自己列的清单,一个数字都没给
「给对了材料它照样可能编」在同一章里说了两遍,但没有给出比例

作者的推测或经验值:

说法它是什么
「按节切 + 20% 重叠」经验值。 书没说这个比例是怎么定的
「小知识库直接写进提示词更划算」经验判断。 没给「多小算小」的门槛
「切块是最被低估的一环」一句立场。 我们认为它成立,但它是作者的排序,不是测出来的

10. 边界与局限

  • 这一章完全没讲「取回来的对不对」怎么判断。 你按上面的流程搭完, 没有任何办法知道它取得好不好——这正是第 09 章的内容,而书把那一块放在了同一章里, 我们把它挪到了嵌入之后(理由见总纲第 5 节);
  • 「转成一串数」只给了效果,没给机制。 为什么意思近的数就近?这是第 06 章;
  • 没有讲取回几段合适。 取 3 段还是 10 段?书这一章不谈,而**「取更多反而更差」 是第 07 章的一条重要结论**;
  • 示例代码有一处技术错误(见第 7 节),另有一处评分函数的做法很粗糙—— 那一处我们留到第 09 章讲,因为它正好是「怎么判断有没有编」这件事的最朴素做法—— 后面所有更好的做法都拿它当参照,这种当参照用的最简做法叫基线;
  • 中文场景的切块一个字没提。 按段落、按句子切在中文里的分界规则和英文完全不同, 书以英文为默认。

11. 可带走的

全章那条走查,一行写完:「用礼品卡买的电子产品退货政策是什么?」→ 不接资料:「大多数零售商允许 30 天内退货」(编的)→ 载入政策 PDF → 切成 47 小段 → 每段算出一串 384 个数 → 存进可查的库 → 提问时也算成数,取回最接近的 3 段 → 拼进提示词 → 「14 天内可退成店铺积分,或 30 天内换货,需原始礼品卡收据」,并能指出出处。 (47、384、3 是为演示编的;两段回答是书里的真实例子。)

  1. 不能靠「再训一次」解决:算不动是规模问题,一出厂就过期是时效问题——后者是结构性的;
  2. 检索增强就是两步动作:先按问题取回相关内容,再把它当材料交给模型写。 不是产品,不是框架;
  3. 三个部件:检索器找、生成器写、知识源是被事先整理过的资料本体;
  4. 建索引四步:载入 → 切分 → 转成一串数 → 存起来。 ①② 决定有什么可找,③④ 决定找不找得到;
  5. 嵌入 = 一段文字对应的一串数,意思相近的文字这串数也相近——机器因此有东西可算;
  6. 切块的两难没有通解: 小块把该在一起的切散,大块把该突出的稀释。 按内容类型切,加 20% 重叠当保险;
  7. 六条代价里最要命的一条:给对了材料它照样可能编。 这一章治不了,第 09、17 章才治;
  8. 知识库又小又稳时,直接写进提示词更划算——别为了用而用;
  9. 书里这一章的示例代码,把一个「只会从原文里划片段」的模型放在了「要写出新句子」的位置上 (会写出新句子的那一类叫生成模型)——不要照抄;
  10. 函数调用是反过来的形态:它开口说「我要调 get_weather,参数是 Paris」,由我们的代码执行;
  11. 函数调用顺带把输出格式钉成了参数的形状——不必再从自由文本里抠结构;
  12. 两种形态都是「把回答锚在外部真值上」,差别只在谁决定取什么。 而一旦它调的函数会改变外部世界,系统就跨过了另一条线(第 13 章)。

12. 原文地图

主题原书章原文位置
当日达那个答不了的问题Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:23(搜「integrated soundbar」)
为什么不能靠预训练解决Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:31(搜「dynamic supply chains」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:33(搜「all possible combinations of products」)
普锐斯那个例子Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:46(搜「Toyota Prius」)
两步动作的定义Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:40(搜「two-stage approach」)
礼品卡退货的前后对照Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:71(搜「Most」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:74(搜「14 days for store」)
六条代价Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:88(搜「not a silver bullet」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:93(搜「small, stable knowledge bases」)
检索器是侦察兵、资料要事先建索引Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:114(搜「information scouts」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:117(搜「indexed beforehand」)
四步流程Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:276(搜「Load: It all begins」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:307(搜「Store: The generated embeddings」)
图书馆卡片那个比方与「狗/小狗/猫」Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:293(搜「huge library of books」) · text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:302(搜「puppy」)
检索增强不消除监督与评测Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:250(搜「sources can be outdated」)
示例项目里的抽取式问答模型Chapter 3: Grounding Outputs with RAGtext/06-ch03-chapter-3-grounding-outputs-with-rag.txt:1422(搜「AutoModelForQuestionAnswering」)
切块是最被低估的一环Chapter 4: Embeddings and Vector Searchtext/07-ch04-chapter-4-embeddings-and-vector-search.txt:1023(搜「most underappreciated」)
切块两难:小块与大块Chapter 4: Embeddings and Vector Searchtext/07-ch04-chapter-4-embeddings-and-vector-search.txt:1041(搜「100-200 tokens」) · text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1048(搜「500+ tokens」)
按内容类型切Chapter 4: Embeddings and Vector Searchtext/07-ch04-chapter-4-embeddings-and-vector-search.txt:1067(搜「section-based chunking」)
重叠与 20% 经验值Chapter 4: Embeddings and Vector Searchtext/07-ch04-chapter-4-embeddings-and-vector-search.txt:1122(搜「appears」) · text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1146(搜「20% overlap」)
函数调用三步与格式钉死Chapter 2: Prompt Engineeringtext/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1197(搜「function calling ensures the output」) · text/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1207(搜「requests a」)
函数描述的写法Chapter 2: Prompt Engineeringtext/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1275(搜「get_weather」) · text/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1282(搜「ISO country code」)

Footnotes

  1. 出处:「Chapter 3: Grounding Outputs with RAG」第 23 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:23,搜「integrated soundbar」)。

  2. 出处:「Chapter 3: Grounding Outputs with RAG」第 31 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:31,搜「dynamic supply chains」)与第 33 段(同文件 :33,搜「all possible combinations of products」)。原文的措辞是:把所有产品、地点、配送方式的组合都预训练进去,不只是算力上不可行,而且塞进去的知识一出厂就过期

  3. 出处:「Chapter 3: Grounding Outputs with RAG」第 46 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:46,搜「Toyota Prius」)。

  4. 出处:「Chapter 3: Grounding Outputs with RAG」第 40 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:40,搜「two-stage approach」)。原文:先按用户的查询从最新的外部来源检索相关信息,再把它喂给模型去生成。

  5. 出处:「Chapter 3: Grounding Outputs with RAG」第 114 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:114,搜「information scouts」)。生成器的定义见第 120 段(同文件 :120,搜「Generators are powerful」)。

  6. 出处:「Chapter 3: Grounding Outputs with RAG」第 117 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:117,搜「indexed beforehand」)。四步系统流程见第 127 段(同文件 :127,搜「The system receives a user query」)。

  7. 出处:「Chapter 3: Grounding Outputs with RAG」第 276 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:276,搜「Load: It all begins」)起的四条,第四条在第 307 段(同文件 :307,搜「Store: The generated embeddings」)。

  8. 出处:「Chapter 3: Grounding Outputs with RAG」第 302 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:302,搜「puppy」)。图书馆卡片那个比方在第 293 段(同文件 :293,搜「huge library of books」);书自己也说了这只是比方,技术细节留到讲嵌入的那一章(同文件 :303,搜「a bit more」)。

  9. 出处:「Chapter 4: Embeddings and Vector Search」第 1023 段(text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1023,搜「most underappreciated」)。这一节在原书里排在第 4 章,我们把它挪到了这里——因为切分本来就是建索引四步里的一步,书把它拖到两章之后才讲。

  10. 出处:「Chapter 4: Embeddings and Vector Search」第 1041 段(text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1041,搜「100-200 tokens」)与第 1048 段(同文件 :1048,搜「500+ tokens」)。

  11. 出处:「Chapter 4: Embeddings and Vector Search」第 1067 段(text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1067,搜「section-based chunking」)起的几条代码注释。书还提到另一条路线:用自然语言处理工具按句子或自然命题切,边界比定长窗口更有意义。

  12. 出处:「Chapter 4: Embeddings and Vector Search」第 1146 段(text/07-ch04-chapter-4-embeddings-and-vector-search.txt:1146,搜「20% overlap」)。重叠让跨边界的信息在两块里都出现,见第 1122 段(同文件 :1122,搜「appears」)。

  13. 出处:「Chapter 3: Grounding Outputs with RAG」第 88 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:88,搜「not a silver bullet」)起的一整段。

  14. 出处:「Chapter 3: Grounding Outputs with RAG」第 93 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:93,搜「small, stable knowledge bases」)。

  15. 出处:「Chapter 3: Grounding Outputs with RAG」第 92 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:92,搜「still hallucinate even」)与第 250 段(同文件 :250,搜「sources can be outdated」)。第二处的完整表述是:检索增强提高可靠性,但没有消除对监督、护栏和评测的需要。

  16. 出处:「Chapter 3: Grounding Outputs with RAG」第 1422 段(text/06-ch03-chapter-3-grounding-outputs-with-rag.txt:1422,搜「AutoModelForQuestionAnswering」)。补充(不在书里,来自通用知识):这一类模型的做法是在给定段落里预测答案的起止位置,输出必然是原文的一个子串;它没有生成新句子的能力,所以放不进这条流水线的最后一步。

  17. 出处:「Chapter 2: Prompt Engineering」第 1207 段(text/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1207,搜「requests a」)起的三步,以及第 1211 段(同文件 :1211,搜「separates responsibilities」)。原文明说:模型负责理解意图和组织语言,真正的信息由外部服务提供

  18. 出处:「Chapter 2: Prompt Engineering」第 1275 段(text/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1275,搜「get_weather」)与第 1282 段(同文件 :1282,搜「ISO country code」)。上面那段 JSON 是书里的原样,我们只做了排版。

  19. 出处:「Chapter 2: Prompt Engineering」第 1197 段(text/05-ch02-chapter-2-generating-trustworthy-responses-with-.txt:1197,搜「function calling ensures the output」)。