跳到主要内容

01-outline — rag-python-cookbook 节级大纲

这是第二段的产出:一页纸的结构。不是正文。

原书 11 章、536k 字符、60 多个配方,转码成 39 段(第 8 章被拆成 24 个文件)。 切成 19 章 + 总纲,按新词密度切。一行一节:「进来时以为… → 出去时知道…」。 每章标出:主走查(一条具体输入贯穿全章)与 承重词(去掉它整章就塌,单开一节从现象讲起,一章一到两个)。

0. 这一本的位置(动笔前必须先定,否则会和书架上另一本重复)

书架上已有 docs/hands-on-rag-for-production-design/(16 章),地盘几乎完全重合: 解析切块、嵌入、向量检索、混合与重排、评测、agent、多模态、知识图谱。

差异化写死一句:那一本讲「怎么设计一套生产系统」,这一本讲「每个零件的参数、代价、 和什么时候别用它」。 凡是这一本没有具体数、具体参数、具体反面判据的地方, 就是那一本已经讲过的地方,我们从简;凡是这一本给了数和反面判据的地方,就是我们的正文。

作者利益相关(总纲第 2 节必须写): Dominik Polzer 是 Siemens Energy 的采购 AI 负责人, 全书跑例——采购分析师、供应商合同、质量文件比对 ISO 标准——都来自这个岗位。 这不是中立视角,是「大企业内部文档处理」视角。

正名写死(一词一义,全书不许改口): 同一件事在初稿里有三个名字——距离、夹角、相似度, 而三者不是同义词,是反向关系(距离越小 = 相似度越大),读者一定会读岔。写死:

层次全书只用这个名字在哪里用
现象层相近程度(越大越像)02 主走查、06071012 讲「找出最像的几块」时
机制层余弦相似度(出门会撞见的名字,必须留)08 §3 讲清它量的是方向偏差、值越大越像;之后各章直呼其名
反面距离(越小越像)只在明说「它是相近程度的反面」时用;07 §5、09 讲索引时各出现一次,当场点明

据此改两处:02 主走查写成「算出与每块的相近程度 → 取最近三块」; 07 §5 写成「靠相邻句子的相近程度掉得最狠的地方断开」。

出处的一个坑: 第 8 章每个配方的 Solution / Discussion / See Also 各是一个独立文件 (11-fm-solution.txt33-fm-see-also.txt),文件名看不出是哪一节。 这一章的每条脚注都必须补「第 8 章 · 配方 8.x」,否则人读不出来。 另外第 8 章所有 Problem 段丢失、配方 8.7 的标题整个丢失,引用时只能写「第 8 章 · MCP 那一节」。

1. 全书一条主线(总纲第 3 节的骨架)

只读这一节、不看任何拆解章,也能把这本书的主张复述出来。写的时候只留效果句,机制退回章节。

  1. 模型有三个改大也治不好的缺陷:碰不到你的私有资料 · 一次读不完长文档 · 缺信息时会编。 一次治三个的办法只有一个:提问时先去外部资料里搜,再把搜到的东西连同问题一起交给它。
  2. 先看「交给它」那一头,因为它窄得出人意料。 这一头要做的只有三件: 挑一个模型、把角色与指令与材料与问题拼成一段话、按这段话的长度付钱。 能拧的就这么几个旋钮,而且拧到头也就那样——所以后面九步的力气,全花在「先去搜」那一头。
  3. 可要不要搜,还有一条硬判据:一条正则或一句 SQL 能覆盖 95% 的情况,就别上。 它拿简单性换灵活性,而规则式做法的失败方式是可预测的。
  4. 决定上了,第一个障碍是资料不长成能喂的样子:Word、PDF、Excel、录音、录像、扫描件。 所有非文字的东西只有一条出路——先变成文字;而干这件事的工具本身就是模型。 于是有了一条贯穿全书的暗线:模型不只在回答时用,更多是在入库时用。
  5. 变成文字还不够。检索是把每一块孤立地取出来的,取出来的那一块脱离原文还得站得住—— 于是入库时还要给它补上它自己说不清的东西,并且重新决定这一刀该切在哪里。
  6. 块准备好了,「意思相近」怎么变成能算的东西?把文本换算成一串数,拿方向的偏差当相近程度。
  7. 数多了要存、要搜、要快 → 向量库,以及索引换来的六倍速度和它换掉的那点精度。
  8. 到这里能跑了,但答不准。而**「改进检索这一步,是提高准确率最有效的办法」**—— 于是有三类补救:检索前改查询、检索时缩范围、检索后补上下文与挑结果。
  9. 可这些补救每一种都要人事先挑,而真实问题千变万化事先挑不了。让模型在运行时自己决定调哪个工具、查哪个源。 这一步兑现的是第 1 章开头就埋下、书自己从没回头点破的那句话: 「现代系统常常用多个检索器……模型自己决定该调哪个。」
  10. 即便如此,靠「意思相近」还剩一类死穴:实体之间的关系。 孤立的块不知道这条条款属于哪份合同、下一条是哪条、这家供应商花了多少钱 → 知识图谱。
  11. 到此为止所有选择都只是「作者说这样更好」。怎么知道一次改动是让它变好了还是变坏了? → 三个不需要标准答案也能算的指标。
  12. 最后让真实用户碰得到它——而**「大多数生成式 AI 项目从未上生产」**, 所以原型阶段该优化的是前期投入,不是可扩展性。

落点在第 8 章(我们的第 13–14 章),不在最后一章。 三条证据: ① 第 1 章开头就埋了多检索器;② 第 7 章的查询路由已经是半成品 agent; ③ 全书最后一个技术建议(11.4)是「第 8 章的 agent 做法能更好地处理这些情况…… 生产系统从 agent 做法开始」——最后一章指回第 8 章。

书从没命名过的三条暗线,是我们最大的增量,收在第 19 章: ① 「什么时候别用它」才是这本书的正文; ② 「先简后繁,而且方向不可逆」——书说了九遍,一次都没命名; ③ 每一步都标了价,全书没有一处汇总。


2. 章节切分(19 章)

01 为什么要先检索,以及什么时候别检索

01-why-retrieve.md — 原书 ch1 导言 + 1.1 + 1.6(有意舍弃 1.2/1.3/1.4/1.7,理由见第 4 节)

  • §1 进来时以为「答不上是模型不够大」→ 出去时知道那是三个改大也治不好的结构性缺陷:碰不到你的私有资料、一次读不完长文档、缺信息时会编而不是承认不知道
  • §2(承重词)进来时以为上下文窗口就是「一次能读多少字」→ 出去时知道它同时是成本和速度的闸门:模型没有记忆,每问一次整段对话都要重发一遍,越长越贵越慢
  • §3(承重词)进来时以为模型编造是偶发故障 → 出去时知道它是「照上文续写」这个机制的必然产物,以及为什么「只用给你的材料回答、没覆盖就说没有」这条指令压得住它
  • §4 进来时以为 RAG 是一种产品或一个框架 → 出去时知道它只是一个动作顺序,最简形态只有两件:一个搜你自己文档的检索器 + 一个照材料写答案的模型
  • §5 进来时以为「有文档就该上」→ 出去时知道硬判据:正则或 SQL 能覆盖 95% 就别上;它换来的是能听懂「因天气延误」和「发货改期」说的是同一件事,付出的是可预测性
  • §6 进来时以为场景好坏靠感觉 → 出去时知道五档适配度里 5 分的共同点是「量大 + 输出可核对 + 单条价值低但总量高」,1–2 分的共同点是「单份、低量、通用模型已覆盖」;一天 10 份不值得建,一天 1000 份值得
  • §7 进来时以为「先挑个框架再说」→ 出去时知道依赖数的代价(2–3 个 vs 50+),以及方向不可逆:往框架走容易,从框架退回难得多(第 19 章把这条收成全书一条原则)

主走查: 「一万份供应商合同里,哪些含自动续约条款」——先写一条正则试(同一件事的十几种写法在哪一条上断掉),再换成检索走一遍,最后在五档适配度上给它定位。自造的合同措辞要当场标明是为演示编的。 承重词: 上下文窗口 · 幻觉(它为什么会编)

02 一套 RAG 长什么样

02-two-pipelines.md — 原书 ch1 §1.5 + ch2 导言 + ch5 导言

  • §1 进来时以为它是「问一次、搜一次、答一次」一条线 → 出去时知道是两条时间上分开的线:离线的入库线和在线的问答线
  • §2(承重词)进来时以为文档是整份喂进去的 → 出去时知道它被切成「块」,块是检索的最小单位,也是后面六章所有麻烦的源头
  • §3(承重词)进来时以为「意思相近」是模型现场判断的 → 出去时知道每块文本在入库时就被换算成一串数,查询也换算成一串数,相近变成了一个可算的量(怎么算出来的,第 08 章讲)
  • §4 进来时以为两条线各用各的工具 → 出去时知道一条铁律:两条线必须用同一个模型来做这个换算,换模型等于整库重来
  • §5 进来时以为模型只在最后回答时出现一次 → 出去时知道它在入库时出现得更多:抽文字、转写、写摘要、补元数据(第 04、05、06 章全靠这一点)
  • §6 进来时以为「答得泛」是模型不行 → 出去时知道排障法则:先单独测检索再调生成;答案听着泛且和你的文档无关,问题几乎总在检索
  • §7 进来时以为这套基础形态能一路用到底 → 出去时知道它有两个明确的失效点:需要多步推理的问题、不同数据类型需要不同检索策略(正好是第 11–14 章的入口)

主走查: 哈利波特知识库问答一次走完——原文切成 N 块(每块 1000 字符、重叠 200)→ 每块换成 1536 个数 → 问书里那句原问题「弗农姨父为什么把全家带到海边小屋」→ 算出与每块的相近程度 → 取最近三块 → 拼进提示 → 出答案。这条走查同时是全书的顶层全景,后面每一章都在改它的某一步。 承重词: 块 · 嵌入(只讲到现象层:一串数、夹角小就是意思近)

03 挑模型、写提示、别信排行榜

03-choosing-models-and-prompts.md — 原书 ch2 §2.1–2.7 + Warning

  • §1(承重词)进来时以为按字数计价 → 出去时知道计价和窗口都按 token 算,以及为什么输出比输入贵得多:输入是一次并行算完的,输出必须一个一个生成、每生成一个都要回看前面全部
  • §2 进来时以为提示就是把问题发过去 → 出去时知道 RAG 的提示是四件套(角色 + 指令 + 检索到的上下文 + 输出要求),以及那条让每个答案都能追回来源的关键指令
  • §3(承重词)进来时以为模板越严越好 → 出去时知道两头都会坏:太松会掺训练数据、编造引用;太紧会拒答那些部分落在材料之外的边缘情况;而且模板本身每次调用都要付一遍钱
  • §4 进来时以为该「选最好的模型」→ 出去时知道选的是「仍然满足要求的最小模型」,而且是逐个流水线步骤地选;从延迟倒推(用户很少愿意等超过 10 秒),标准聊天场景高效档就够
  • §5 进来时以为四家接口各写各的 → 出去时知道三家共用一套写法只改地址,只有一家必须换;以及各自的选择理由和反向理由(长文档和多模态选那一家,短请求上它反而更慢)
  • §6 进来时以为「本地跑一个」只是省钱的花招 → 出去时知道它有两条硬理由(数据受监管不能出网 / 每月百万次调用时自建成本才低于接口费)和三个硬门槛(8B 模型至少 8GB 显存、13B 要 16GB 以上、70B 级别笔记本装不下),以及什么时候别自己跑(要最新推理能力、或开发速度比成本重要);顺带纠一处:书里那张开源模型表停在 2023–2025,示例命令拉的是两年多前的模型,而同一节的代码又拉了一个新的
  • §7 进来时以为模型只能吐一段文字、要自己解析 → 出去时知道可以拿一份字段清单把生成过程约束住、直接拿到带类型的对象,代价是延迟增加、以及正确答案是「看情况」时会被硬逼二选一
  • §8 进来时以为排行榜第一就该选它 → 出去时知道它只能当筛选工具:题目可能已经进了训练数据、厂商会专门为它调、而且和你自己的提示与检索质量不匹配

主走查: 采购分析师问「这份合同的解约通知期是多少天」+ 三块检索到的上下文——同一个提示的 token 构成、四档模型各自的价与延迟、最后用字段清单把答案收成一个带类型的对象。 承重词: token · 提示模板 纠: 表 2-1(标 "January 2026")与 §2.4 正文的型号跨了两代,代码里三种型号混用。正文只写档位,型号一律标明会变。

04 把资料变成文字(上):文档、表格、数据库

04-into-text-documents.md — 原书 ch3 §3.1–3.4

  • §1(承重词)进来时以为「文件里有字就是有数据」→ 出去时知道非结构化的意思是:字在那儿,但「这行是标题还是正文、这个数属于哪一列」没人记着;而检索器只吃一致的文本
  • §2 进来时以为读 Word 就是把段落拼成一个长字符串 → 出去时知道多留下的结构各买到什么:标题能加权或单独建索引做两段式检索、列表项能抽问答对、修改时间能挡住过时信息;以及什么时候不值得(文档短或同质)
  • §3 进来时以为 PDF 都能抽出文字 → 出去时知道分水岭是「文字是字符还是像素」:数字生成的能抽,扫描件必然失败,那条路在第 05 章;页级元数据换来的是能跳回原文那一页去核
  • §4(承重词)进来时以为表格也切块嵌入就行 → 出去时知道表有三条根本不同的路,分界线是问题的类型:查单条 / 要全表语境 / 要聚合;而聚合类问题只有让模型写查询语句这一条路走得通
  • §5 进来时以为三条路要选一条 → 出去时知道生产里按表的大小与查询模式混用:小参考表塞进提示、中等查找型每行改写成一句话、大分析型必须走查询语句
  • §6 进来时以为数据库只是数据来源 → 出去时知道它在 RAG 里身兼二职:既装应用数据,又能靠扩展当向量库,省掉两套库(这是第 09、10 两章的入口)
  • §7 进来时以为格式越多越要各写一套 → 出去时知道一条有争议的工程建议:先全部转成 PDF、只养一条流水线;以及它的前提——转换别把结构弄丢

主走查: Census Income 那张 15 列 48000 行的表,三个问题走三条路:「Sarah 的职位是什么」(改写成句子能答)/「这张表里谁工资最高」(整表塞提示,48000 行塞不下,当场暴露上限)/「工程师里多少比例年薪过 10 万」(只有生成查询语句这条路能答对)。 承重词: 非结构化数据 · text-to-SQL(让模型写查询语句) 补/纠: ① 全书代码用的那个读 PDF 的库(PyPDF2)早已停止维护、改名并入 pypdf,书自己在表 1-2 里两个都列了——先翻书架的 clone 源码再上网核,读者照着装会踩坑;② 章开篇那句「企业信息约 80% 是非结构化」书没给出处,查不到就照实写「书里没交代,而且这个数长期没有可靠来源」,不许当事实用

05 把资料变成文字(下):图、音、视频

05-into-text-multimodal.md — 原书 ch3 §3.5–3.11

  • §1(承重词)进来时以为 PDF 里的图表也能被搜到 → 出去时知道文本嵌入只处理文本,视觉元素在语义搜索里是隐形的;要么先把它变成文字,要么它就不存在——书给这件事起了个名字
  • §2(承重词)进来时以为扫描件交给传统文字识别就行 → 出去时知道它和多模态模型的分工线是钱:每页差 100 倍;所以按文档类型和月处理量分诊,不是二选一
  • §3 进来时以为多模态模型全面更好 → 出去时知道它多买到的是版面(能输出带标题、项目符号、表格的结构),多付的是「低质量扫描件上可能编造数字或漏掉内容」,以及关键文档要交叉验证
  • §4 进来时以为图片只能存成图片 → 出去时知道「给盲人描述这张图」这个角色设定就是整条路的支点:存进库的是描述加元数据,不是原件
  • §5 进来时以为表格转成文字就丢了信息 → 出去时知道原始表格串和摘要各抓住一半,由此得到一条纪律:摘要负责被搜到,原件负责被读懂(第 15 章会再撞见同一条)
  • §6 进来时以为音频转写就是全部 → 出去时知道通用转写缺的三样(实时流式、谁在什么时候说的、自定义词表),缺哪一样决定要不要换专门服务
  • §7 进来时以为视频是一种资料 → 出去时知道它是两种:一个片段至少产出音频转写和首帧的图像理解两条文本;四种切段法各对应什么内容;而段级元数据换来的是一个能跳到那一刻的链接

主走查: 一份混排 PDF 的一页(叙述段落 + 一张柱状图 + 一张季度收入表),查询「季度销售趋势」:三种元素各走一条路进库,最后命中的是表摘要("每季度增长 20%,从 Q1 的 1 亿到 Q3 的 1.4 亿")而不是原始表格串 "Q1: 100, Q2: 120, Q3: 140"另起一处: 视频五步(讲者每张幻灯片约 30 秒、代码按 10 秒切段)。 承重词: 模态转换 · 文字识别(OCR) 补/纠: 视频那一节的代码把 2.x 的导入写法配了 1.x 的方法名(from moviepy import VideoFileClip + clip.subclip(...)),两者不能同时成立——照实写「书里这段代码跑不起来」,别替它圆。

06 让每一块脱离上下文也能被看懂

06-standalone-chunks.md — 原书 ch4 导言 + §4.1–4.3

  • §1 进来时以为块只要别切坏句子就行 → 出去时知道判据狠得多:每块恰好装一条信息、不靠周围上下文也站得住——因为检索是把块孤立地取出来的,模型只看得见块里面那些词
  • §2(承重词)进来时以为元数据是文件属性、可有可无 → 出去时知道它是在算相似度之前把搜索空间缩小的那道闸;三层来源(文件自带 / 算出来 / 让模型从正文里读出来),以及最后那层的价钱:1000 份文档几分钟、1–5 美元
  • §3 进来时以为「意思近」就该被检索到 → 出去时知道语义近而语境无关是最常见的假阳性,而这道闸在语义搜索之前就把它们分开
  • §4 进来时以为缩写不影响检索 → 出去时知道块里可用的信号本来就少、缩写又砍掉一截;保留缩写与展开式并存能让三种查法都命中;以及什么时候别展开(缩写本身就是标准形式)
  • §5 进来时以为清晰度是文风问题 → 出去时知道它是四条可操作的动作:补上下文句、消解代词、保留实体全名、把含糊词换成具体数
  • §6(承重词)进来时以为只能拿用户的问题去比对文档 → 出去时知道可以反过来:入库时给每块生成「它能回答的问题」并存这些问题,用问句比问句,命中后把原块交给模型
  • §7 进来时以为这一招和后面的查询改写是一回事 → 出去时知道方向相反:这一招在入库时对齐、只付一次,第 11 章那一招在查询时对齐、每次都付;可以只用一个也可以都用

主走查: 一句真实的块文本 "The NLP model improved it by 40% since the release."——原样为什么被检索到也没用(它指什么、NLP 是什么、什么时候的事)→ 补元数据 → 展开缩写 → 消解代词与含糊词 → 生成假设性问题 → 最后看用户问「我们的检索为什么变快了」能不能命中。 另起一处: 「抗氧化剂」在医学与环境工程里都成立的那个假阳性(元数据过滤那一步的放大镜)。 承重词: 元数据 · 假设性问题

07 五种切法:从数字符到让模型重写

07-five-ways-to-chunk.md — 原书 ch4 §4.4–4.8

  • §1(承重词)进来时以为切块就是「每 N 个字切一刀」→ 出去时知道刀口落在哪里决定了这块还能不能回答问题;重叠是干什么的——但书里四个示例给了 0、20、50、200 四个值,一次都没解释(这是书的缺口,照实写);并且知道切多大不是纯自由:上限由后面那个把文字换算成数的模型定,常见是八千 token 上下,超了会被截断(08 §5 再回扣一次)
  • §2 进来时以为定长切分太笨没人用 → 出去时知道它有明确的适用面(原始转写、拼起来的日志、快速原型),坏在哪里也很具体:从中间撕开词和句子
  • §3 进来时以为「按段落切」就是递归切分 → 出去时知道它是一张按优先级排的分隔符表,到了长度上限就用当前能用的最高一级;它是格式未知时的默认选择,而它对中文日文泰文可能切错词
  • §4 进来时以为文本就是文本 → 出去时知道格式自身带语法时(标题符号、函数定义、标签),照语法切胜过照长度切,代价是要先认出格式、按格式配解析器
  • §5 进来时以为话题边界就是段落边界 → 出去时知道它们经常不重合;这一种靠相邻句子的相近程度掉得最狠的地方断开,阈值取全文所有相邻句「掉了多少」的第 90 百分位——只有跌幅超过全文九成的地方才断,代价是每段文字要嵌入两遍
  • §6(承重词)进来时以为最聪明的切法是「切得最准」→ 出去时知道最后一种根本不是在切:它让模型把文本重写成一条条只讲一件事、且把代词换成实体全名的陈述;它是唯一一种主动消解指代的方法
  • §7 进来时以为越聪明越该用 → 出去时知道它比上一种贵 10–20 倍(500 块要 30–60 分钟、15–40 美元);而且这五级框架不是公认术语,「代理式切分」这个叫法出自一篇博客

主走查: 一段约 600 字符、带小标题、中间有一次明显话题转折的说明文,五种切法各切一遍,每次写出切成几块、每块的首尾字串、哪一块坏了、坏在哪。 另起一处: "Sarah bought a new book. She enjoys reading fantasy novels." → 两条陈述,She 变成 Sarah(第 6 节那一步的放大镜;第 17 章会再见到同一个手法)。 承重词: 重叠(overlap) · 命题(proposition) 补: 五级框架与「代理式切分」这个叫法的出处;命题最早出自哪篇论文。

08 意思怎么变成数

08-embeddings.md — 原书 ch5 §5.1–5.5 + ch3 §3.8 的回扣

  • §1(承重词)进来时以为「给每个词编个号」就算变成数了 → 出去时知道随意指派的编号把语义全丢了(学士、硕士、博士成了三个互不相干的坐标,看不出它们是同一个阶梯),而这正是嵌入要解决的
  • §2 进来时以为向量是个数学名词 → 出去时知道它就是一串数、每一位是一个刻度;拿书里那个三维玩具例子把加减法逐位走一遍(减掉男性那一维、加上女性那一维,年龄和地位不动),再交代真实的是 1536 维、而且每一维没有名字
  • §3(承重词)进来时以为比较两串数就是逐位相减 → 出去时知道默认量的是夹角不是长度:四个字的查询和三百字的说明书方向相同就该拿高分,否则长文档会仅仅因为长而压过排名
  • §4 进来时以为分数 0.31 就等于不相似 → 出去时知道这个数只在同一次比较里有意义,它是那一组里最高的;以及什么时候该换成别的算法(向量长度本身有意义时、追速度时)
  • §5 进来时以为嵌入好不好只能看排行榜 → 出去时知道可以把 1536 个数压成 2 个画在纸上、亲眼看见同类句子聚成堆(这一步叫降维),但它只是开发期的验收手段、不是生产诊断——压到 2 维显示不出全部关系,生产里该盯的是「取回的前 k 块里有几块真有用」;顺带知道三种压法的取舍(一种快且每次结果一样,另两种更能保住局部结构但慢、参数没调好会画出误导人的图案)
  • §6 进来时以为嵌入模型也要追新 → 出去时知道它的演进比生成模型平缓得多、选型基本是一次性决定;七步选型流程,两个必看的参数(维数、以及能吃多长——那正是 07 §1 那条块长度上限的出处),以及最硬的一条:别把它选大了,85% 换 87% 很少值得成本和延迟翻倍——力气该花在切块和检索上
  • §7(先补后纠)进来时以为书里讲的训练过程就是今天的做法 → 出去时知道今天是怎么做的(整句话一次读进去、每个词都看过同一句里的其他词之后,再把整句压成一串数),知道书讲的是 2013 年那一代的图景(每个词一个输入神经元、预测下一个词、隐藏层权重就是嵌入),以及这个差别为什么要紧:旧图景里一个词永远是同一串数,今天同一个词在不同句子里得到的数不同
  • §8 进来时以为图和文只能靠中转文字才能一起搜 → 出去时知道还有一条路让它们直接进同一个空间(第 05 章埋的那条岔路),以及它的两个硬伤:候选之外的东西照样被硬分进某一类、图片里的文字它看不见;所以书自己的建议是多数 RAG 别走这条

主走查: 查询 "reset password" 对两条候选(一段三百字的重置流程说明、一句密码强度要求)——从编号的反面 → 三维玩具例子 → 算余弦相似度 → 把 1536 维压成 2 维画出来看一眼 → 换成一张图会怎样。 承重词: 向量(维度) · 余弦相似度 另需就地讲透(不列为承重词,本章已有两个,再多会把力气撒平): 降维 · 归一化 补: 两个嵌入排行榜是谁做的、怎么读;用书架上的 sentence-transformers 补 §7 前半那一段。

09 存到哪儿、搜得多快

09-vector-stores-and-indexes.md — 原书 ch6 导言 + §6.1–6.4、6.6

  • §1 进来时以为这一章讲的是「挑个数据库」→ 出去时知道它其实在回答两个连着的问题:这堆数该跟谁待在一起、以及一次查要等多久(20 万条全算一遍已经要 85 毫秒);顺带把两个天天撞见、其实不是一回事的说法分开——「找空间里靠得近的向量」是技术操作(相似度搜索),「按意思搜」是面向用户的能力(语义搜索),后者用前者实现
  • §2 进来时以为得先挑一个向量数据库 → 出去时知道先答四个问题:是不是线上应用的一部分 / 要不要和业务数据待在一起 / 会不会长到几千万条 / 数据能不能出网;多数团队的错是照着基准选而不是照着工作流选
  • §3 进来时以为这些库是同一类东西 → 出去时知道它们是四类,而三级阶梯每一级多给了什么:内存里的索引 → 加上持久化和基本过滤 → 加上完整查询、事务、权限
  • §4 进来时以为选错了就得推倒重来 → 出去时知道迁移要重建索引但不必重新生成嵌入,而嵌入才是贵的那部分——这是「先简后繁」在这一侧最硬的一条依据
  • §5 进来时以为把向量塞进关系库只是权宜 → 出去时知道向量成了一种列、相似度成了查询语句里的一个操作符(四个操作符各对应一种算法),于是用户表、文档元数据、嵌入能在一条查询里连起来;维数必须和嵌入模型对上
  • §6(承重词)进来时以为搜索就是把每条都算一遍 → 出去时知道 20 万条全表扫描已经要 85 毫秒,再往上就得靠索引;而索引换来的速度是拿精度换的,所以有两条明确的门槛:不到 10 万行常常根本不必建,超过 100 万行则必须建
  • §7 进来时以为索引就是「建好了就更快」→ 出去时知道第一种做法是先把空间分片:建索引时把所有点分成若干片、每片记一个中心点,查询时先比中心点找到最近的那一片,再只在片内找;快在哪很清楚,坏在哪也很清楚——真正的最近邻可能就落在分界线那边的邻片里(这一族的名字在 pgvector 文档里写作 IVFFlat,读者会撞见)
  • §8(承重词)进来时以为另一种索引只是「更快的同一件事」→ 出去时知道它换了个思路:建一张多层的图,高层路少但每条跨得远、当捷径用,越往下路越多越细,最底层才是每一条小街;以及三个旋钮各拧动什么(每个点最多连几个邻居 m、建索引时候选表多大 ef_construction、搜索时看几个候选 ef_search)

主走查: 20 万条职位描述 + 查询「我在找柏林的数据科学家工作」:全表扫描 85.582 毫秒 → 分片索引(30 片、每次探 3 片)约快一倍 → 多层图索引(每点最多连 16 个邻居、搜索时看 50 个候选)13.927 毫秒承重词: 索引 · 多层图索引(HNSW)

10 当「意思相近」不够用

10-beyond-semantic-search.md — 原书 ch5 §5.6–5.7 + ch6 §6.5、6.7 + ch7 §7.1 + ch7 §7.4(只取「选源的三条路与它们的延迟」这一半)

  • §1 进来时以为按意思搜是万能的 → 出去时知道它有三类固定的失手:精确串(型号、法条编号、端点路径)、语境串台(同一个词在两个领域)、以及这个问题根本不该问这个库
  • §2 进来时以为过滤是把结果筛一遍 → 出去时知道它发生在算相近程度之前;在查询语句里就是把条件加在排序之前,以及一条性能忠告:别在同一条查询里做复杂的多表连接,先在子查询里过滤。启动条件:所有人都能看所有文档、也不按时间和主题分的时候,不加过滤更简单也更快
  • §3(承重词)进来时以为关键词检索是被语义搜索淘汰的老办法 → 出去时知道它管的是语义抓不住的那一半:字面命中,而且长文档不会因为长而占便宜;它有个名字,叫 BM25。启动条件就写在这一行末尾:先只用语义搜索,直到你在检索日志里看见精确串没命中,才加它
  • §4(承重词)进来时以为两个榜怎么合并是个细节 → 出去时知道有两种合法做法:按名次融合(公式里那个数控制多偏向榜首)和按分数加权(先五五开,再照用户抱怨的方向调);法律与技术类偏字面,对话类偏语义
  • §5 进来时以为照书里那段查询语句抄就行 → 出去时知道它把关键词那一半硬编码成了另一个词,还顺手把结果先过滤成必须含那个词的行——这个例子跑出来的东西和它声称在演示的不是一回事
  • §6 进来时以为把所有资料放一个库里最省事 → 出去时知道多个库要先选源,而「选源」和「在一个源里缩范围」是两件事,可以叠加。启动条件:资料只有一个源时这一节整节不必看
  • §7 进来时以为选源当然让模型来判断 → 出去时知道三条路差两个数量级:让模型判断加 500–2000 毫秒、全都搜一遍再投票延迟不变但算力翻倍、训一个小分类器只加 10–50 毫秒;而分类器错了会彻底丢掉相关文档,语义搜索至少还能返回次优结果。启动条件:先用让模型判断那条验证选源逻辑对不对,等延迟成问题、且各源主题分得清,再换分类器;源之间大量重叠时只能吃下那个延迟

主走查: "How do I configure SSL for endpoint /api/v2/users?"——纯语义命中一堆讲 SSL 的通用文档、漏掉那个端点 → 加关键词检索精确命中 → 写出两个榜的名次和融合分 → 加元数据过滤先缩范围 → 如果资料分成三个源,先选源再过滤。 另起一处: 「谁是史上最强球员?」——不知道是哪项运动就没法答(元数据过滤那一步);以及问「市场表现」却被体育版的「球队表现」捞上来(选源那一步)。 承重词: BM25(关键词检索) · 排名融合 原 §8 已删(与 19 §4 撞句): 那一节原本要说「每一招的启动条件形状相同」,而把九处并排放在一起点出形状,正是收束章 19 §4 的活。现在每一招各自的启动条件写在 §2–§7 各自的行尾,19 §4 才第一次把它们摆到一起。

11 改查询:检索之前先把问题改一遍

11-query-rewriting.md — 原书 ch7 导言 + §7.2、7.3、7.8

  • §1 进来时以为该在生成那一头调 → 出去时知道全书最该记住的一句:改进检索这一步是提高准确率最有效的办法;而能改的只有三个位置——检索前改查询、检索时缩范围、检索后补上下文与挑结果(后两个在第 10、12 章)
  • §2 进来时以为用户问什么就拿什么去搜 → 出去时知道问句和文档天生长得不一样;第一招是先让模型编一段「看起来像你库里文档」的假答案,拿它去搜,而这段假的不进最终提示
  • §3(承重词)进来时以为编出来的东西不可靠所以没用 → 出去时知道它不追求事实正确,它换来的是风格对齐:相似度从「只比主题」变成「比主题 + 比文体」;风险也很具体——模型不熟的领域里,那段假文会把检索带偏
  • §4(承重词)进来时以为搜一次就够 → 出去时知道把同一个问题变出几种问法各搜一次能提高召回率(书自己给了定义:该找到的里面找回了多少),代价是检索时间和算力约三倍
  • §5 进来时以为「多问几遍」和「拆成几个问题」是一件事 → 出去时知道产出的中间物完全不同:一个是同一问题的近义变体,一个是各自需要独立回答、之后再合并的子问题
  • §6 进来时以为拆解只是把问题切碎 → 出去时知道它能回答任何单次检索都答不好的问题(比较型、多跳型),代价是多两次模型调用外加多次检索;而提示里必须写明「问题本来就简单就原样留着」
  • §7 进来时以为三招可以随便挑 → 出去时知道分界清楚:用词风格对不上用第一招、召回不够用第二招、问题里含多个独立事实点用第三招

主走查: 「和化石燃料相比,可再生能源有什么好处?」在三招下各变成什么——一段假文的头一句 / 三条近义问法(共四次检索)/ 五个子问题;各多花多少。 承重词: HyDE(假设性文档嵌入) · 召回率 补: HyDE 原论文的题名与年份;查询拆解那条线的血缘。

12 补上下文与挑结果

12-context-expansion-and-rerank.md — 原书 ch7 §7.5–7.7

  • §1(承重词)进来时以为块越小越好、或者越大越好 → 出去时知道这是一个两难:搜索要小块才够聚焦,生成要大块才有上下文;后面两种补法都是为了同时拿到这两样
  • §2 进来时以为补上下文就是多取几块 → 出去时知道第一种是按结构补:小块只用来搜,同一个父块下命中够多个小块,就把整个父块交给模型
  • §3 进来时以为第二种是同一件事 → 出去时知道它是按位置补:命中哪块就固定带上前后各 N 块,更简单但不会随机应变;隐含前提是入库时块的编号必须反映原文顺序
  • §4 进来时以为补上下文只有好处 → 出去时知道代价可算:一块 1000 个 token 扩到三块就是三倍上下文,成本和延迟一起涨
  • §5(承重词)进来时以为初检的分数已经是相关性排名 → 出去时知道初检是把查询和文档各自独立打分的,快但粗;第二遍把查询和候选放在一起看,慢但准——所以是两阶段,不是替代
  • §6 进来时以为第二遍是锦上添花 → 出去时知道它的真正用途是收拾烂摊子:第 11 章那几招和 agent 会同时产出几十个候选,没有第二遍就只能瞎切;「合并后取前五」胜过「每个来源各取前五」
  • §7 进来时以为三招该一起上 → 出去时知道各自的触发条件:文档有明确层级用第一招、答案的背景常被切在隔壁块用第二招、候选超过 20 条用第三招

主走查: 一份有章有节的手册,叶块约 250 字符、四叶合成一个约 1000 字符的父块。一次查询命中叶 1、2、5 → 父块 1 下有两个叶命中,整段取回;叶 5 那边只有一个,只取它 → 换成按位置补会取到什么(约 750 token 的窗口)→ 与别的来源合并成 20 条候选 → 打分 5、4、2、1 → 只留前三。 承重词: 父块与子块 · 重排(两阶段)

13 让模型自己决定

13-tools-and-agent-loop.md — 原书 ch8 导言 + §8.1、8.2、8.4、8.5 + ch7 §7.4(只借它当「路由已经是半成品 agent」这一层论证,三条路已在 10 §6–§7 讲完,这里不许重讲)

  • §1 进来时以为前面那些招数装好就完事了 → 出去时知道它们每一种都要人事先挑,而真实问题千变万化事先挑不了——这就是让模型在运行时自己决定的理由,也是第 02 章那句「多个检索器、模型自己决定调哪个」的兑现;论据是 10 §7 那件已经讲完的事:那里已经让模型在运行时选源了,只是选完就停手;把「选完接着干」补上,就是这一章
  • §2(承重词)进来时以为模型能自己算数 → 出去时知道它算不准,所以把该算的交出去:模型只负责决定调哪个函数、传什么参数,程序负责执行;而模型的判断依据只有一样——函数的说明文字
  • §3 进来时以为一次调用就能拿到答案 → 出去时知道一次只走一步,所以必须放进循环:执行结果按固定格式追加回对话,再问一次,直到模型不再要求调工具
  • §4(承重词)进来时以为 agent 是个玄乎的说法 → 出去时知道它就是「让模型当决策者」的那类系统:观察 → 规划 → 挑工具执行 → 拿结果修正计划;这个循环有个名字,而它就是上一节那个 while 循环
  • §5 进来时以为 agent 就该完全自主 → 出去时知道更常见的是五种固定形状的工作流(串行链、选路、并行、协调者带工人、起草者带评审),以及分界线:可靠性比灵活性重要就用固定形状
  • §6 进来时以为并行只是快一点 → 出去时知道收益可算(一份长扫描件逐页抽取,串行几小时、并行几分钟),约束是接口的每分钟 token 上限
  • §7 进来时以为异步是免费的加速 → 出去时知道代价是调试:错误可能发生在同时跑的多个任务里,还必须处理「部分失败」

主走查: (5.0 + 3.0) * 2.0——工具字典三件(名、说明、参数清单)→ 第一次调用只返回「把 5.0 和 3.0 相加」,得 8.0,还没回答用户的问题,但那是正确的第一步 → 把结果按 {"role": "tool", ...} 追加回对话 → 第二次调用「把 8.0 乘 2.0」得 16.0 → 不再要求调工具 → 出最终答案。 另起一处: 扫描版发票三页并发抽取——19、34、38 秒的三件活总共只花 49 秒,串行至少 90 秒。 承重词: 工具调用(函数调用) · agent(以及那个循环的名字) 补: 那篇论文的真实年份(书写 2023,预印本实为 2022 年 10 月);五种工作流模式的出处。

14 框架、MCP 与锁定的代价

14-frameworks-mcp-lockin.md — 原书 ch8 §8.3、8.6、8.7、8.8

  • §1 进来时以为选框架是选顺手的 → 出去时知道先要定在哪一层:不写代码的、写代码但有框架的、从零搭的;三层各自换来什么、各自在哪种情形下是对的
  • §2(承重词)进来时以为框架帮你干活总归是赚的 → 出去时知道两条实打实的账:每加一层抽象都遮蔽行为、让调试更难,每加一个依赖都扩大攻击面;而且锁定会随时间复利
  • §3 进来时以为图框架把 agent 变复杂了 → 出去时知道它换来的是把状态和控制流写成显式的东西:节点干活、边规定合法的转移、条件边决定还要不要再来一圈——画出来正好就是第 13 章那个循环;不该用它的情形也很明确(固定顺序、没有分支)
  • §4 进来时以为多个 agent 协作要写一套调度 → 出去时知道有个更省的手法:把 agent 本身包装成工具,主持人像调函数一样调它们;每个 agent 只暴露「进文本、出文本」,因而可互换、可单独测
  • §5 进来时以为 agent 越多越强 → 出去时知道每一次交接都是一次完整的模型调用,多轮对话的成本线性累加;只是简单的任务委派,直接调函数或选路更划算
  • §6(承重词)进来时以为工具就该写在自己的代码里 → 出去时知道同一个查数据库的工具换个框架要重写一遍,于是有了一份协议把「模型和工具怎么打交道」标准化,三件:客户端、服务器、协议本身
  • §7 进来时以为接上协议只有好处 → 出去时知道两条代价:服务器是独立进程,要部署、要监控,连不上、超时、返回畸形数据都得自己处理;而且它接受网络请求,认证授权输入校验一样不能少
  • §8 进来时以为通用协议总是值得 → 出去时知道它只有在工具要跨项目跨团队复用时才划算,单一用途的 agent 上它就是纯开销

主走查: 同一个「天气助手」需求在三层上各实现一遍——从零搭的那个循环(第 13 章已走完)→ 轻量框架里一个装饰器把函数变成工具 → 图框架里的一个状态、两个节点、一条条件边接回起点;每一层各自锁定了什么、迁走要重写什么。 另起一处: 议价 agent(客户要 15 台笔记本、每台不超过 950 欧元,零售 1299,销售给 12% 折扣,客户说别家能给 1000)——三个 agent 怎么分工,以及为什么延迟关键时别用这个模式。 承重词: 状态图(状态 / 节点 / 边) · MCP 补: 书架上的 MCP 规范与本书架已有的 MCP 拆解;书架上 openai-agents-python 里装饰器和「把 agent 变成工具」的真实写法(书正文和代码自相矛盾)。

15 当关系本身就是答案

15-knowledge-graph.md — 原书 ch9 全章

  • §1 进来时以为检索不到就是嵌入不够好 → 出去时知道有一类问题根本没有可以拿去比意思的句子:它问的是实体之间怎么连
  • §2(承重词)进来时以为知识图谱是个高级说法 → 出去时知道它就是把资料写成「点」和「点之间带名字的线」:哪条条款属于哪份合同、下一条是哪条、这家公司在哪个国家、这条条款是哪一类
  • §3 进来时以为建图是自动的 → 出去时知道这一版书里的条款分类靠一张关键词表,匹配不上就打成「其他」;全章的检索质量建在这条脆弱规则上,而书从没讨论过它的失效率
  • §4 进来时以为图里只该放文档 → 出去时知道第二个维度才是企业级的分界:把业务实体和它们的属性(支出、国家、行业)也放进来,于是合同正文和实体属性能出现在同一条查询里;代价是这些属性会变、必须和源系统同步,数据陈旧会导致过滤错误
  • §5(承重词)进来时以为查图要写程序 → 出去时知道有一种专门的查询写法,而三种检索姿势对应三种问题:知道是哪份文档就直接查、要跨文档比同类内容就从类型出发、业务规则优先就先按属性筛
  • §6 进来时以为有了图就不需要按意思搜了 → 出去时知道两者是接力:先按意思搜出候选锚点,再顺着线走回去按业务属性过滤;而标签本身可靠时,一条纯图查询更简单也更快
  • §7 进来时以为优化就是加索引 → 出去时知道三种优化都是把工作从查询时挪到入库时(给条款写摘要、把计数先算好、给整份合同也建索引),以及那条纪律——摘要只用来过滤和排序,最终答案永远取回完整正文(和第 05 章那条是同一条,书隔了六章没点破)

主走查: 「哪些高支出的供应商缺少解约条款?」——先说清为什么按意思搜答不了它 → 图长什么样 → 从表格灌进每家公司的年度支出 → 那条「支出超过阈值、但一条解约条款都没有」的查询怎么写 → 再换成「给我看德国医疗行业公司的数据保护条款」,看按意思搜和图怎么接力。 承重词: 知识图谱(点与带名字的线) · 图查询语句(Cypher) 补: 本书架已有的《Essential GraphRAG》拆解(书自己在延伸阅读里点名)。

16 评测(上):题从哪来、谁来判、它判不了什么

16-evaluation-setup.md — 原书 ch10 导言 + §10.1–10.3

  • §1 进来时以为改完试几个问题、觉得好就是好 → 出去时知道没有评测优化就是猜;而这件事和传统机器学习不是一回事:系统不学习,问题不在「有没有学到模式」,在「有没有检索到对的信息、有没有生成有用的答案」
  • §2 进来时以为测试题从数据里切一部分出来就行 → 出去时知道那样出的题恰好最没用:题要覆盖真实意图、又不能逐字出现在库里、还得能从现有资料答出来;所以是改写真实查询,不是切分已有样本
  • §3 进来时以为一套系统只有一个准确率 → 出去时知道它有几个可以各自独立坏掉的部件(选源、转查询语句、按意思检索、生成),每个都要有自己的指标才找得到瓶颈
  • §4 进来时以为想测什么就能测什么 → 出去时知道能测什么取决于你手上有什么标注数据(有标准答案 / 有标注过的检索结果 / 两样都没有);以及那条纪律:选两三个覆盖不同部件的指标,防止优化了一个把另一个悄悄弄坏
  • §5(承重词)进来时以为判卷需要标准答案 → 出去时知道让模型当法官在这里成立的理由很具体:它不需要知道正确答案,它只判「这条主张有没有被材料支持」「这个答案有没有回应问题」
  • §6 进来时以为让模型判就够了 → 出去时知道它的盲区是有名字的:语气和品牌声音判不了,答案太啰嗦、措辞让人困惑、该反问却没问也抓不到;这些只能人评,而人评有它自己的节奏(每月一次、每次 20–30 条、两三个人一起)
  • §7(承重词)进来时以为可以让模型自己出题省事 → 出去时知道合成题保证了「答得出」但系统性地偏易:它们派生自干净聚焦的块,抓不住真实用户那条又长又含糊的尾巴;所以它是基线不是标尺——答不出就是坏了,答得出不代表好

主走查: 一个具体的改动——「把每次取回的块数从 10 降到 3」。在书里那套时装电商系统(一个装结构化数据的库 + 一个装时尚博客片段的向量库)上,要拿什么题、谁来判,才说得清这个改动是变好还是变坏。 承重词: 让模型当法官 · 合成测试数据

17 评测(下):三个不需要标准答案的指标

17-three-metrics.md — 原书 ch10 §10.4–10.6

  • §1 进来时以为三个指标是三个角度看同一件事 → 出去时知道它们各针对一种彼此独立的失效:检索回来的是不是都有用、答案有没有守住材料、答案有没有回应问题;而且三个会各自独立地动
  • §2(承重词)进来时以为「相关的块占几成」一句话就能算 → 出去时知道要先决定拿什么当判据:比对一份标好的黄金检索集 / 比对系统自己生成的答案 / 不用模型的字面重叠;不需要黄金集的那条是本书用的
  • §3 进来时以为检索只有一个准确率 → 出去时知道这是从搜索引擎借来的一整族:担心混进噪声看精确率、担心漏掉信息看召回率、两者平衡看 F1;而只要模型主要吃前几块,排名进不进公式就是两个不同的指标——第一个相关结果出现得多早、相关结果越靠前权重越高,各有各的名字
  • §4 进来时以为「四块里两块相关就是 0.5」→ 出去时知道书里的文字算的是这一族里不带排名的那个,而它的公式和代码算的是带排名加权的平均精度,两者不是一个东西——这是全书最实质的一处概念错误,而且出在最技术的一章
  • §5 进来时以为这个数低就该去调检索 → 出去时知道要和答案质量交叉着看:高分低质是生成端的问题,低分高质说明第一块就够了、该把取回数调小
  • §6(承重词)进来时以为「有没有编」只能人看 → 出去时知道可以先把答案拆成一条条不带代词的独立主张,再逐条查有没有被材料支持;而这个拆法正是第 07 章那个把文本重写成命题的手法,只是用在了评测上(书自己没点破)
  • §7 进来时以为分数高就够 → 出去时知道这是全书唯一给了明确数值判据的地方(80% 以上算合格、70% 以下就要当成可能在编),以及它换掉的是什么:守得紧的模型是保守的,只说材料里明确写着的
  • §8 进来时以为「答得对」和「答得切题」是一件事 → 出去时知道第三个指标反过来算:从答案倒推出几个问题,看它们像不像原问题;它抓得住答非所问,抓不住答得不全;而「我无法提供实时股价」这类回答会被一刀切判成彻底失败
  • §9 进来时以为测完就完了 → 出去时知道节奏是自动指标每次改动都跑、人评每月一次;以及为什么读评测框架的源码才是弄清一个指标到底怎么算的最可靠办法

主走查: 「法国的首都是哪」+ 三块上下文(讲法国并提到巴黎 / 讲巴黎是法国首都 / 讲亚马逊雨林),三个指标各算一遍,写出每一步的判定值。 另起一处: 「巧克力饼干的主要原料有哪些」那个答案拆成七条独立主张(第 6 节那一步的放大镜)。 承重词: 上下文精确率 · 忠实度 补: 用书架上的 ragas 源码核对拆主张那个类的真实实现——书自己说读源码是最可靠的办法,还点了这个类的名字,这是全书最该做的一处核对。

18 上线,以及还缺的三层

18-shipping-it.md — 原书 ch11 全章

  • §1 进来时以为做出来就等于上线 → 出去时知道大多数生成式 AI 项目从未上生产,所以原型阶段该优化的是前期投入,不是可扩展性
  • §2 进来时以为检索一定是向量搜索 → 出去时知道全书最直白的一次反例:一个能跑的 RAG,它的「检索器」是两次普通的接口调用
  • §3 进来时以为快速搭界面的工具只是省事 → 出去时知道它省事的原因也正是它的天花板:每一次用户交互都把整个脚本重跑一遍;50 个并发就是瓶颈,把重活卸载出去能撑到 100–500,再往上得整个重写
  • §4 进来时以为单人测通了就行 → 出去时知道最要命的坑是状态在用户之间泄漏:A 上传了文档、B 刷新页面会不会看到;要用两个浏览器窗口测才抓得到
  • §5 进来时以为把整份 PDF 交给多模态模型最省心 → 出去时知道它统一了流水线也统一了账单:100 页文档,抽文本层 0.05 美元、走多模态 0.50–2.00 美元;而且必须配字段校验和人工复核队列
  • §6 进来时以为让模型写查询语句是终点 → 出去时知道它有三种可预测的失效(含糊问题猜错指标、五张表以上的连接超时、文档不足就编出不存在的列名);而书自己给的更好做法是把查询做成带参数的模板让模型选——全书最后一个技术建议是指回 agent 那一章的
  • §7(承重词)进来时以为部署就是把代码传上去 → 出去时知道要先把「在我机器上能跑」固定下来:应用和依赖打包成一个到处都能跑的东西,再交给按用量计费的托管运行时;一个常驻的小实例每月 30–40 美元,自动扩缩容必须设上限
  • §8(承重词)进来时以为上线之后就是维护 → 出去时知道还缺三层,每一层挡的都是一种具体事故:手工点控制台改配置导致环境慢慢分岔、手工部署忘了跑测试或从错的分支构建、密钥硬编进镜像后轮换要重建每一个镜像

主走查: 天气 RAG 一次提问走完——从问题里抽出城市和国家 → 地名转成经纬度 → 调接口拿天气 → 连同问题塞进提示生成;然后把这同一个应用打包、推上云、算出每月账单。 承重词: 容器 · 基础设施即代码

19 走到哪一级就该停

19-when-to-stop.md — 我们的收束章(材料全部出自书,轴是书没命名的)

  • §1 进来时以为这是一本按需查的配方书 → 出去时知道每个配方后面那段「什么时候别用它」才是它的正文,而且彼此不重复;收在一起就是一张「别做什么」的清单
  • §2(承重词)进来时以为「先简单后复杂」是句正确的废话 → 出去时知道它在这本书里是九处具体建议,而且有一条硬理由让它不可逆:往上走容易、往回走难——换库不必重算嵌入(而嵌入才是贵的那部分),但从框架退回自己实现要整个重来
  • §3 进来时以为每一级的代价说不清 → 出去时知道书在十二处标了价,只是从没汇总:100 倍、10–20 倍、3 倍、500–2000 毫秒对 10–50 毫秒、85.6 毫秒对 13.9 毫秒
  • §4 进来时以为什么时候该上一级凭经验 → 出去时知道书给的启动条件形状完全相同:先从最简单的那一级开始,只有当你在日志里看到那一类具体失败时才加下一级
  • §5 进来时以为书里的建议有实验支撑 → 出去时知道全书没有一次对照实验,唯二的实测数字是索引耗时和异步耗时,其余全是作者的从业经验;而他的岗位决定了全书跑例的形状
  • §6 进来时以为它讲全了 → 出去时知道它明确不覆盖十几处,其中三处是张力而不只是空白:块该多大和重叠该设多少(示例里四个值、一次没解释)、长上下文能不能替代检索(一边说窗口有限一边说支持百万 token)、以及文档改了怎么重新入库和删除

主走查: 第 1 章那个真实场景——制造商每天收供应商几千份质量文件,要比对标准查合规,某个参数不合规就查出联系人、起草跟进邮件。从第 0 级(一条正则)一路加码到第 4 级(图谱),每一级旁边写三样:这本书在哪里说过「先别急着上这一级」、这一级标了多少价、它买到了什么。 承重词: 「先简后繁,方向不可逆」——这是我们给它起的名,书里说了九遍、一次没命名,正文必须当场点明这是我们的命名,不是书里的术语。


3. 许诺兑现表(草稿,写正文时逐条加,总纲末尾放正本)

许诺在哪应兑现在哪
index.md §主线 第 6 步「怎么算出来的」08 §2–§3
01 §7「方向不可逆」19 §2
02 §3「怎么算出来的,第 08 章讲」08 §2
02 §7「两个失效点」1114 各自的第 1 节
04 §3「扫描件那条路在第 05 章」05 §2
04 §6「数据库身兼二职」09 §5
05 §5「摘要负责被搜到、原件负责被读懂」15 §7
06 §7「查询时对齐那一招」11 §2–§3
07 §1「块长度的上限由嵌入模型定」08 §6(选型的两个参数:维数与能吃多长)
07 §6「命题」17 §6
08 §8「第 05 章埋的那条岔路」回指 05 §4(向后不欠债)
09 §7「分片索引会漏掉分界线那边的最近邻」19 §3(这一笔计进成本总表)
10 §7「选源那三条路」13 §1 只借它当论据,不重讲
11 §1「后两个位置」10(缩范围)· 12(补上下文与挑结果)
13 §1「第 02 章那句多检索器」回指 02(兑现,不是欠债)
13 §4「那个循环的名字」14 §3(图框架画出来就是它)
18 §8「密钥该放哪儿」兑现 01 有意舍弃清单里那条(1.4 的 .env 留到这里讲)

4. 自查(结构层,五分钟能看出来的)

  • 没有两节的「出去时知道」是同一句。 逐行比对过四组最容易撞的: ① 06 §2–§3(元数据是什么 / 它挡住哪一类假阳性)与 10 §2(它在查询语句里长什么样)——三处不同; ② 11 §4 与 12 §2(都在「多拿一点」,但一个是多搜几次、一个是多取几块); ③ 13 §5 的五种工作流与 14 §3 的图——一个是形状分类、一个是把形状写成代码; ④ 1617——一个管题和判官,一个管三个指标怎么算。
  • 每章都有一条主走查,且每个承重机制在它上面占一步。 050710131417 各另起一处或两处,不超过上限。
  • 承重词每章一到两个,全书 30 个,没有一个重复出现在两章。 「嵌入」在 02 只到现象层、在 08 才到机制层,这是有意的一次分层,02 已记进兑现表。
  • 新词密度按节控: 概念引进最密的是 08(向量、维度、余弦、归一化、降维、跨模态)、09(分片、中心点、多层图、三个旋钮)与 17(检索指标那一族 + 三个核心指标),三章分别拆到 8、8、9 节,每节不超过五张生面孔。09 是这一轮补上的——上一版自查漏掉了它,一节里塞了两族索引加三个旋钮、至少八张生面孔。
  • 有意舍弃(不是漏,写清理由;总纲第 5 节与书卡 notCovered 直接吃这份清单): ① 原书 1.2(挑 IDE 与编码助手)、1.3(在编辑器里用交互式笔记本)、1.7(跑本书代码仓)—— 是本地开发环境的搭建步骤,与 RAG 的机制无关,拆解一行不写; ② 原书 1.4(用 .env 存密钥)——不在这里讲,留到 18 §8 的三层里一起讲, 那里正好有「密钥硬编进镜像后轮换要重建每一个镜像」,放在一起才讲得完整。
  • 篇幅估计: 19 章,每章 14k–22k 字符,全书约 32 万字符(原书正文约 45 万英文字符)。
  • 为什么是 19 章不是 11 章: 原书第 3、8、10 章各自 49k–66k 字符且新词成堆,一章塞不下; 而「混合检索 / 元数据过滤」这同一件事被原书拆散在第 5、6、7 三章,收拢成 10
  • 两处刻意的重排,交稿时要说明: ① 原书 5.5(CLIP)并进 08 而不是单独成章——它只有一个配方的量, 单列会不足 10k;② 原书 6.5(在数据库里做相似度搜索)被拆开:操作符和写法放 09 §5, 条件过滤和性能忠告放 10 §2,两章不重复。