fedorthinks

速成课 · No. 12

RAG 是你把事实交给语言模型、让它据此作答的方式,而不是指望它那模糊的记忆。它是严肃 LLM 应用里最重要的单一模式 —— 而当它出错时,模型几乎从不是元凶。真正的工作和质量都藏在检索里:你如何对要放到模型面前的文本做分块、建索引、检索和排序。

22 个概念 · 每个配一幅图 · 结尾有速查表

§ 01

模型不了解你的数据,也不知道训练截止日期之后的任何事。RAG 就是把事实交给它、让它据此作答的办法 —— 所以先弄懂它要解决的问题,再看机制。

地图:七组共 22 个概念

一张地铁图:先看整张线路网,再一站一站地坐过去。

先是三个基础概念 —— 为什么模型的记忆不够用、RAG 是什么、为什么 grounding 很重要。然后是六组,每章一组:分块、embeddings 与检索、检索质量、grounding、评测,以及把它做好。

之后的每个概念都是同一个结构:英文名(记住它 —— 这就是术语)、一个生活中的画面、一幅图,以及一张带字段的卡片:是什么或问题、原理或思路、例子、注意或代价,还有关联。

BasicsKnowledge cutoffRAGGroundingChunkingChunkStructure-aware splitMetadataEmbeddings & searchEmbeddingVector searchVector databaseSimilar ≠ relevantRetrieval qualityHybrid searchRerankingPrecision / recallGroundingContext-only answerCitationsRefusalEvaluating RAGRetrieval evalFaithfulnessGolden setBuilding it wellPaste firstIndex freshnessCost & latency
上面是基础概念,下面是六个分组 —— 第 2–7 章依次讲它们。

Knowledge Cutoff —— 模型的记忆是冻结的

一位聪明的毕业生,多年前读完了整座图书馆 —— 但没读过你公司的文件,也没读过他毕业之后印刷的任何东西。

LLM 只知道训练数据里有的东西,冻结在某个截止日期 —— 也就是它的 knowledge cutoff。它不了解你的文档、你的产品、你客户的档案,也不知道昨天的新闻。你照样去问它,它就会**凭模糊的记忆作答,或者编出一个听上去合理的答案。**RAG 的存在正是为了解决这件事:不再依赖模型背下来的东西,而是在提问的那一刻把相关事实交给它。

Training dataeverything the model ever readcutoffYour documentsYesterday's newsknown, but frozennever seenask anyway → fuzzy memory or a plausible invention
截止日期之后的内容,以及你公司内部的内容,模型从来没见过。
ConceptKnowledge Cutoff· 训练截止日期
是什么
模型只知道它的训练数据,冻结在某一天。
例子
它不了解你的文档、某位客户的档案,或者昨天的新闻。
注意
模型不知道时并不会沉默 —— 它会凭模糊的记忆作答,或者直接编造。
关联
RAG 补上这个缺口:事实在提问的时刻送到。

RAG —— 先检索,再回答

开卷考试 —— 不靠记忆,先查出相关的几页,再根据眼前的内容写答案。

这就是 Retrieval-Augmented Generation(RAG,检索增强生成) 模式。三步:检索 —— 拿到用户的问题,取回你文档中最相关的片段;增强 —— 把它们放进上下文;生成 —— 让模型据此作答。这样答案来自你真实的数据,而不是模型的回忆。助手就是这样回答关于你的文档、你的政策、你的知识库的问题的 —— 准确而且是最新的。

1 · retrieveQuestionfrom the userRetrievesearch your docsTop-k chunksthe most relevant passages2 · augmentContextquestion + chunksLLManswers from contextAnswerfrom your data3 · generate
RAG 的三步:检索片段、加入上下文、生成答案。
PatternRetrieval-Augmented Generation· RAG
问题
模型不了解你的数据,也不知道截止日期之后的事。
思路
找出文档中相关的部分,让模型据此作答。
例子
客服助手根据知识库里现行的那篇文章,回答退款政策问题。
代价
一整套检索系统:分块、索引、新鲜度、评测。
何时使用
知识量大、经常变化,或者因用户而异。
关联

为 grounding 而存在;建立在分块、embeddings 和向量检索之上。

Grounding —— 真正的收获

每句话都必须注明来源的记者,写出的捏造内容要比凭记忆写作的记者少得多。

RAG 重要的深层原因是 grounding(接地):因为答案取自检索到的文本,你可以要求引用,并检查每个论断是否真的有来源支撑。它不能完全消除幻觉,但能大幅减少,并让漏网的部分更容易被发现。能追溯到某份文档的答案,才是你可以信任 —— 也可以为之辩护的答案。

AnswerRetrieved sourcesClaim A [1]Claim B [2]Claim C — no sourceChunk 1policy.md · §2Chunk 2faq.md · §5nothing backs it → catch it
每个论断都有来源。没有来源的论断一眼就能看出来。
ConceptGrounding
是什么
答案建立在检索到的文本上,而不是模型的记忆上。
原理
每个论断都能追溯到具体的某个片段,并可核对。
例子
“退款需 14 天 [1]”,其中 [1] 是退款政策的某一段。
注意
它大幅减少幻觉,但不能降到零。
关联
通过仅依据上下文作答、引用和拒答来实现;用忠实度来衡量。

Retrieval-first —— 末端挂着一个模型的搜索系统

研究助理的水平取决于他查的那套归档系统 —— 给他一座好图书馆却配一个糟糕的索引,他照样会递给你错误的文件夹。

能帮你省下几个月的思维模型:RAG 主要是一个搜索问题,末端接一个语言模型来组织答案。模型是简单、基本已解决的那一部分。困难、决定质量的部分,是一切决定哪些文本能到达模型的环节 —— 这正是本课其余部分的内容。

Retrieval system — the hard partChunkEmbedSearchRankLLMphrases itdecides which text reaches the modelthe easy part
分块、embedding、检索和排序才是难点。模型只负责把答案说出来。

别去问模型它知道什么。检索出相关事实,让它据此作答 —— 有依据、够新、可引用。

§ 02

在检索之前,你要先把文档切成片段。怎么切,悄悄决定了检索的质量 —— 这是最不起眼的一步,却也是最重要的步骤之一。

Chunk —— 质量的基本单位

一本参考书只有切成可查找的条目才有用 —— 一卷巨大的、没有索引的长卷,或者一千张零碎的纸片,查起东西来都一样没用。

你检索的不是整篇文档,而是 chunk(片段) —— 几百个词长的段落。切出它们的过程叫分块(chunking)。这个 chunk 是搜索所看到的、也是模型所读到的单位,所以它的边界极其重要。好的 chunk 自成一体,只讲一个主题。分块做错了,再巧妙的检索、再聪明的模型都救不回来。

DocumentsplitChunk 1Chunk 2Chunk 3Chunk 4Searchsees chunksLLMreads chunks
文档被切成 chunk。搜索看到的是 chunk,模型读到的是 chunk —— 而不是整篇文档。
ConceptChunk· 段落
是什么
几百个词长的段落 —— 搜索与阅读的基本单位。
原理
文档预先切好;搜索返回 chunk,模型据此作答。
大小
太大会把答案埋掉,太小会丢掉上下文。这个数字要靠测量来找。
注意
糟糕的分块,搜索和模型都救不回来。
关联

用 structure-aware chunking 来切,用元数据来标记,再变成 embedding。

Chunk Size —— 太大会埋掉答案,太小会丢掉上下文

为了回答一行字的问题,递给别人整整一章,他得在噪音里趟水;只递给他一句没有前后文的话,他又看不出这是什么意思。

chunk 切得太大,每一块都把相关事实和好几段无关文字混在一起 —— 搜索变得模糊,模型的注意力也被稀释。切得太小,又会切断让这个事实有意义的上下文。最合适的大小,是装下一个完整的想法,并带着足够的周边内容、能独立成立。不存在通用的 chunk size;它取决于你的文档,要靠测量来调。

Too biganswer buried in noiseJust rightone idea + enough contextToo smallcontext cut off
彩色条是你需要的事实。左边它淹没在噪音里;右边它丢掉了上下文。

Structure-Aware Chunking —— 按含义切,而不是按字符数切

按字数数着切一本书,可能把一句话 —— 或者一道菜谱 —— 从中间劈开。按章节切,每一块都保持完整。

朴素的做法 —— fixed-size chunking(定长分块) —— 每 N 个字符切一刀,会切穿句子、表格和想法。更好的做法是按文档的天然结构来切 —— 标题、小节、段落 —— 让每个 chunk 都是一个完整的意思。相邻 chunk 之间留一点重叠(overlap),避免某个事实掉进两块之间的缝隙。尊重文档的形状,检索就会不费力地变容易。

Fixed size — cut every N characters§1 Refunds§2 Shipping§3 Warranty✗ slices through sentences, tables and ideasStructure-aware — cut on headings and paragraphs§1 Refunds§2 Shipping§3 Warrantyeach chunk is a whole thought · a small overlap at the seams
上:每 N 个字符切一刀。下:按小节切,接缝处留一点重叠。
PracticeStructure-Aware Chunking· semantic chunking,重叠(overlap)
问题
按字符数切分,会把句子和表格从中间劈开。
思路
按标题、小节和段落切分,并留一点重叠。
例子
整个“退款时限”小节成为一个 chunk。
代价
你得解析文档格式:Markdown、HTML、PDF。
关联
改善每一个 chunk 以及之后的一切。

Metadata —— 给每个 chunk 贴上标签

图书卡片记录的不只是文字 —— 还有作者、日期和章节,所以你在搜索之前就能先筛到恰当的那个书架。

存储每个 chunk 时带上元数据(metadata):来源文档、标题、日期、小节、权限。这让你可以在语义检索之前或同时做过滤 —— 只看这个产品的文档、只看现行政策、只看这个用户有权看的内容 —— 它还为引用提供了来源。元数据保存起来很便宜,却能把一堆扁平的文字变成可以精准定位的东西。

Chunksource: refund-policy.pdfsection: Timelinesdate: 2026-03access: supportFilter before searchthis product · current · allowed for this userCitationthe source behind each claim
元数据给你两样东西:搜索前的过滤条件,以及引用的来源。
PracticeMetadata· chunk 元数据
问题
一堆扁平的文字:没法缩小搜索范围,也没有可引用的来源。
思路
每个 chunk 都存上来源、标题、日期、小节和权限。
例子
只在这个用户有权看的现行政策里搜索。
代价
几乎为零 —— 每个 chunk 多几个字段。
关联
给向量检索提供过滤条件,给引用提供来源。

你检索的是 chunk,不是文档。按含义切,让每一块自成一体,并给它贴上标签 —— 分块质量决定了下游一切的上限。

§ 03

要找到与问题匹配的 chunk,你得按含义搜索,而不是匹配字词。Embeddings 正是让“帮我找类似这样的东西”成为可能的那个窍门。

Embedding —— 含义变成坐标

一张地图,每个想法都有一个位置,含义相近的东西彼此靠得很近 —— “狗”挨着“小狗”,两者都离“纳税申报表”很远。

Embedding 是一串数字 —— 一个向量(vector) —— 它表示一段文本的含义,放在高维空间里,让含义相近的文本落在彼此附近。你把每个 chunk 只做一次 embedding,并存下这些向量。这样“含义”有了坐标,“找相关的文本”就变成了“找附近的点” —— 这是计算机能很快解决的问题。

ChunktextEmbedding modelreads the text[0.21, −0.83, …]vectorStoreonce per chunkcoordinates of the meaningsimilar meaning → nearby numbers → nearby points
Chunk → embedding 模型 → 向量。每个 chunk 做一次,然后存进库里。
ConceptEmbedding· 向量
是什么
一串数字,表示一段文本的含义。
原理
embedding 模型输出坐标;含义相近就意味着点靠得近。
例子
“狗”和“小狗”靠得近;两者都离“纳税申报表”很远。
关联
让向量检索成为可能;向量存放在向量数据库里。

Vector Search —— 按相似度找,而不是按关键词

一位按书的内容来找书的图书管理员 —— “类似这样的东西” —— 而不是只匹配你说的那个确切书名。

提问的时候,你用同样的方式给问题做 embedding,然后在库里找向量离它最近的 chunk。这就是向量检索(vector search),也叫语义检索(semantic search):即使用户问的是“把钱要回来”,它也能找到讲“退款政策”的 chunk,因为两者含义很近。关键词检索会漏掉这个;向量检索就是为此而生的。

Vector space (shown in 2D)question: “get my money back”chunk: “refund policy”closeshipping timesoffice hoursfarnearest vectors win — even with zero shared keywords
问题和退款 chunk 没有一个共同的词 —— 但在含义空间里,它们紧挨着。
ConceptVector Search· 语义检索
是什么
找出向量离问题向量最近的那些 chunk。
原理
用同一个模型给问题做 embedding,然后找最近的点。
例子
“把钱要回来”能找到“退款政策”小节。
注意
对确切的代码和名称表现不佳;“近”并不总是“有用”。
关联
运行在向量数据库上;由混合检索和重排序补全。

Vector Database —— 检索引擎

一座仓库,经过精心设计:给它任何一件物品,它都能立刻递给你最相似的一百件 —— 不是靠把每个货架看一遍,而是靠它的组织方式。

**向量数据库(vector database)**存放你的 embeddings,并在毫秒内回答“离这个最近的是什么”这类查询,即使面对几百万个 chunk 也一样,靠的是近似索引(ANN,近似最近邻),而不是全量扫描。它是 RAG 背后的检索引擎。你不需要自己造它 —— 但你得知道你的 chunk 就住在这里,以及它的检索有多快、多准。

Query vectorVector databaseapproximate index (ANN)Nearest kin millisecondsmillions of chunks storedno full scan — the index knows where to look
向量数据库不会全部扫描一遍:近似索引直奔最近的那些。
ToolVector Database· vector store,ANN index
是什么
存放向量、并能快速做最近邻搜索的库。
原理
用近似索引(ANN),而不是全量扫描。
例子
几百万个 chunk —— 毫秒内找到离问题最近的那些。
注意
你不用自己造它,但必须知道它的检索有多快、多准。
关联
存放 embeddings;向量检索运行在它上面。

Similar ≠ Relevant —— 相似不等于相关

两段文字可能主题相同,却回答不同的问题 —— “如何取消”和“人们为什么取消”挨得很近,但只有一个是被问到的。

向量检索返回的是语义上接近(相似)的内容,这通常是相关的,但并不总是。一个 chunk 可能讲的是正确的主题,却不包含答案。这个差距 —— 含义上接近与真正有用之间的差距 —— 就是为什么原始的向量检索是不错的第一轮,却不是最终结论,也是下一节存在的原因。

“How do I cancel?”“How to cancel”near · answers it ✓“Why people cancel”near · doesn't answer ✗similar ≠ relevant: a strong first pass, not the final word
两个 chunk 都离问题很近。只有一个包含答案。
ConceptSimilar ≠ Relevant· 相似度 vs 相关性
是什么
含义上接近的 chunk,不一定包含答案。
例子
“如何取消”和“人们为什么取消”挨得很近;只有前者能回答问题。
注意
原始向量检索把“接近”误当成了“有用”。
关联
用重排序来修正;用检索评测来衡量。

Embeddings 给含义以坐标;向量检索按相似度找 chunk。它很强大 —— 但“含义上接近”并不完全等于“回答了问题”。

§ 04

这一课能修好大多数出问题的 RAG 系统:答案不好时,原因通常在检索。把对的 chunk 送进去,一个像样的模型就能完成剩下的事。

Garbage In, Confident Garbage Out —— 垃圾进,自信的垃圾出

把错误的文件递给别人,让他做总结 —— 他会给你一份无可挑剔的总结,总结的却是完全错误的东西,而且听上去十分肯定。

RAG 的答案,只和交给它的 chunk 一样好。检索到了错误的段落,模型就会忠实地依据错误的上下文作答,带着它一贯的自信。这个 bug 看起来像是“模型错了”,但真正的失败发生在上游的检索。所以答案不好时,先检查检索到了什么,再去动提示词或模型。

real failure is herelooks like “the model is wrong”Retrievalwrong chunksLLMfaithful to contextAnswerconfident — and wronginspect what was retrieved before you touch the prompt or the model
错误出现在答案里,但诞生在检索中。先看 chunk。

Hybrid Search —— 把关键词和含义结合起来

一位搜索者清楚字词的含义,另一位能匹配确切的名称和代码 —— 两人合起来,能抓住任何一人单独会漏掉的东西。

向量检索懂含义,但可能在确切术语上出错 —— 产品代码、名称、罕见的行话。**关键词检索(keyword search)**能精确命中这些,却抓不到换种说法的表述。**混合检索(hybrid search)**把两者都跑一遍并合并结果,互相弥补盲区。对大多数真实语料来说,混合检索都优于任何单一方式,因为真实的问题把概念和具体名称混在一起。

QueryKeyword searchexact codes, names (BM25)Vector searchmeaning, paraphrasesMergeResultscatches “SKU-4471”catches rephrasings
并行两次搜索:一次抓住确切的代码,另一次抓住换种说法的表述。结果合并。
PatternHybrid Search· keyword + vector
问题
向量检索对确切的代码和名称出错;关键词检索抓不到换种说法的表述。
思路
两种搜索都跑,并合并结果。
例子
“退货时报错 SKU-4471” —— 关键词检索找到代码,向量检索找到含义。
代价
两套索引,外加合并逻辑。
何时使用
面对真实语料,几乎总是该用。
关联
是重排序之前那一轮宽泛的初筛。

Reranking —— 给候选短名单重新排序

一场招聘:廉价的初筛先挑出五十份看似合适的简历,然后一位认真的审阅者仔细读过,排出真正的前五名。

第一轮检索又快又粗。**重排序器(reranker)**取前五十个候选,更仔细地逐个对照问题打分,把真正相关的 chunk 推到最前面。先广泛检索,再重排序,留下精准的少数几个。这种两阶段的形态 —— 宽泛廉价的召回,加上锐利的排序 —— 是对一个平庸的 RAG 系统来说杠杆最高的升级之一。

stage 1 · wide, cheap recallstage 2 · sharp rankingFast searchroughTop 50candidatesRerankerscores vs questionTop 5the precise fewretrieve broadly, then rerank to a precise few
第一阶段 —— 快速收集 50 个候选。第二阶段 —— 仔细挑出最好的 5 个。
PatternReranking· two-stage retrieval
问题
第一轮又快又粗:对的 chunk 可能排在第 30 位。
思路
取前 50 个,仔细地逐个对照问题打分。
例子
从检索到的 50 个 chunk 里,重排序器留下最有用的 5 个。
代价
多一步 —— 每个问题都要多花一点延迟和费用。
何时使用
RAG 表现平庸时 —— 最强的升级之一。
关联
修正 similar ≠ relevant;排在混合检索之后。

Precision & Recall —— 两者此消彼长

网眼大的网只能捞到大鱼,会漏掉很多;网眼细的网什么都能捞到,连水草也不放过。你根据需要的渔获来调整网眼。

检索的 chunk 太少,你可能漏掉带有答案的那个(低召回率 recall);检索得太多,答案又被淹没在无关文本里,稀释模型的注意力并浪费 token(低精确率 precision)。合适的 chunk 数量(常叫 k)能平衡两者,而且它取决于你的数据和问题类型。你不是猜出来的 —— 而是测出来的,这正是下一节的内容。

Too fewmiss the answer · low recallSweet spotmeasured, not guessedToo manynoise, tokens · low precisionfewmanyk = chunks retrievedthe right k depends on your data and question types
chunk 太少 —— 漏掉答案。太多 —— 答案被淹没。中间值要靠测量来找。
TermPrecision & Recall· top-k
是什么
召回率 —— 对的 chunk 回来了没有;精确率 —— 同时带回了多少垃圾。
原理
k 越大,召回率越高、精确率越低,反之亦然。
例子
k = 2 会漏掉答案;k = 40 把它埋掉,还白烧 token。
注意
你猜不出合适的 k —— 要在自己的数据上测量。
关联
用检索评测来衡量;决定成本与延迟。

大多数糟糕的 RAG 答案,都是糟糕的检索。把关键词和语义结合起来,给短名单重排序,在怪模型之前先检查 chunk。

§ 05

一旦对的 chunk 进入上下文,接下来的任务是让模型严格依据它们作答 —— 并证明它确实这样做了。这才把检索变成值得信赖的答案。

Context-Only Answering —— 只依据检索到的文本作答

一位被要求只陈述自己亲眼所见的证人 —— 不是他推测的、模糊记得的,或者听别人转述的。

指示模型只依据提供的 chunk 作答,答案不在其中时就说不知道。这是 grounding 的核心:检索到的文本是被允许的事实来源,模型自己的记忆则不在考虑之列。这不会完美 —— 模型仍可能跑偏 —— 但这条指令加上对的上下文,已经完成了大部分工作。

Retrieved chunksallowed source of truthModel's memoryoff the table ✗LLMonly from chunksGrounded answer
chunk 是被允许的来源。模型的记忆不是。
PracticeContext-Only Answering· 依据上下文作答
问题
模型把检索到的事实和自己的记忆混在一起。
思路
一条指令:只依据提供的 chunk 作答,否则就说“我不知道”。
例子
“只依据下面的摘录作答。如果答案不在其中,就直说。”
代价
并不完美:模型仍可能跑偏。
关联
grounding 的核心;由引用和忠实度来检查。

Citations —— 让论断可以被核对

带脚注的论文,让任何读者都能把一个论断追溯到它的来源并加以验证 —— 或者发现它站不住脚的地方。

让模型注明答案的每一部分来自哪个 chunk。**引用(citations)**有两个作用:让用户(和你)能对照来源验证论断;而且光是把每句话都建立在某段检索到的文字上,这个行为本身就会让模型不容易偏离事实。有可追溯来源的答案是你能审计的;没有来源的答案,只是一个自信的猜测。

AnswerRefunds take 14 days. [1]The return label is free. [2]Sale items are excluded. [2][1] refund-policy.md§ Timelines[2] returns-faq.md§ Labelsevery claim can be checked against its source
答案的每一句都指向它的来源 —— 你可以打开来核对。
PracticeCitations· 来源标注
问题
没有来源的答案无法核对 —— 它只是一个自信的猜测。
思路
模型说明每个论断来自哪个 chunk。
例子
“退款需 14 天 [1]”,其中 [1] 是 refund-policy.md 的“时限”小节。
代价
每个 chunk 都需要带有来源的元数据。
关联
建立在元数据之上;让 grounding 可被核对。

Refusal —— 教它说“我不知道”

你最信任的专家,是那个会说“这个不在我手头的资料里”的人,而不是自信地用猜测去填补空白的人。

RAG 最危险的失败,是检索结果为空或偏题时仍然照答不误。所以要让拒答成为一种合法、被预期的输出:如果 chunk 里没有答案,模型就应该这样说,而不是凭记忆即兴发挥。一个承认空白的系统,远比一个把它遮掩过去的系统可信 —— 而且它还会暴露出你的检索哪里需要下功夫。

Retrieved chunksanswerin them?Answer + citations“Not in my sources”valid, expected outputyesno✗ never improvise the gap from memory
两个分支都是正确的输出。只有一件事是错的:凭记忆编造答案。
PracticeRefusal· 诚实的“我不知道”
问题
检索结果偏题,模型却照样作答。
思路
“这不在我的资料里”是一个正常的、被预期的回答。
例子
知识库之外的问题 → “文档里没有涉及这一点。”
代价
有时用户得不到答案 —— 但绝不会得到编造的答案。
关联
属于 grounding;拒答会暴露检索中的缺口。

Grounding 能减少幻觉 —— 但不能终结它

安全带能大幅降低死亡率,但你依然要小心驾驶。一道强力的保障,并不是不再看路的理由。

即使 chunk 完美,模型也可能读错、过度概括,或者把检索到的事实和自己的记忆混在一起。Grounding 大幅减少了幻觉,并让它可被发现;但它不会消除幻觉。所以你仍要验证 —— 用用户能核对的引用,以及衡量忠实度的评测。把 grounding 当作一种强有力的控制手段,而不是保证。

Grounding 意味着答案只来自检索到的文本,并用引用来证明 —— 而且当事实不在时,诚实地说一句“我不知道”。

§ 06

RAG 有两个阶段,它们的失败方式不同,所以要分开衡量。把它们混在一起,你就会连着几周调错了那一半。(Evals 课程讲得更深;这里是 RAG 专属的形态。)

Two stages —— 把检索和生成分开衡量

一家餐厅出了一道坏菜,有两个可能的元凶 —— 送来的食材,或者厨师。你要先尝食材,否则会去培训错误的人。

RAG 的答案失败,可能是因为检索带回了错误的 chunk,也可能是因为生成阶段在对的 chunk 上答得不好。两者需要不同的修法,所以要分开衡量:对的 chunk 回来了吗?以及,给定这些 chunk,答案是否忠实且完整?大多数“没法改进自己 RAG”的团队,只给最终答案打分,然后猜该怪哪一半。

QuestionRetrievalfetch chunksGenerationanswer from chunksRetrieval evalright chunks back?Generation evalfaithful and complete?two meters,two fixes
每个阶段都有自己的度量表 —— 也有自己的修法。

Retrieval Eval —— 对的 chunk 回来了吗?

在评判作文之前,先看看学生拿到的参考页对不对 —— 如果不对,他写的任何东西都不可能是对的。

单独评测检索 —— 这就是检索评测(retrieval eval):对一组已知相关文档的问题,搜索是否在靠前的结果里把它们返回了?这种命中所占的比例常被称为 recall@k。它能直接发现糟糕的分块、薄弱的检索和缺失的重排序 —— 也就是大多数糟糕答案的上游原因。先修检索,因为对提示词或模型做任何改进,都救不了建立在错误 chunk 之上的答案。

PracticeRetrieval Eval· recall@k
问题
从最终答案看不出是不是检索的错。
思路
拿已知正确文档的问题来测:它们回到前 k 名了吗?
例子
50 个真实问题里,有 41 个的正确文档在前 5 名。
能发现什么
糟糕的分块、薄弱的检索、缺失的重排序。
关联
衡量 precision & recall;要在忠实度之前先修好它。

Faithfulness —— 答案忠于 chunk 吗?

一位事实核查员对照引用的来源阅读答案,把来源其实并不支持的每一句都标出来。

检索一旦做好,就要评测答案的忠实度(faithfulness):每个论断是否都有检索到的 chunk 支撑,没有编造,也没有与之矛盾?还要检查它是否真的用上了检索到的内容,并回答了问题。这正是你抓住模型偏离坚实上下文的地方 —— 而且它是可以衡量的,常常由另一个模型当评分员(LLM-as-judge)。

Answer sentence 1Answer sentence 2Answer sentence 3Graderoften another LLMsupported ✓supported ✓not in chunks ✗faithfulness = every claim backed by the retrieved chunks
评分员逐句对照 chunk,把 chunk 不支持的部分标出来。
TermFaithfulness· groundedness
是什么
答案中的每个论断都有检索到的 chunk 支撑。
原理
由评分员 —— 常常是另一个模型 —— 把句子与 chunk 逐一核对。
例子
两句有支撑,第三句没有:它被标记出来。
注意
忠于 chunk 的答案,仍然得回答问题。
关联
衡量 grounding;在做好检索评测之后才有意义。

Golden Set —— 用真实问题搭建评测

你用将要真正驶过大桥的卡车来测试它,而不是用你觉得方便的重量。

你的评测集 —— 常被称为 golden set —— 应该是用户真实会问的真实问题,包括杂乱的和超出范围的,每个问题都配上应当被检索到的 chunk,以及一个已知正确的答案。每次改动都跑一遍,这样你就能看出新的分块策略或重排序器是否真的有帮助。没有这个,你就是在凭轶事调 RAG —— 而轶事会骗人。

questionshould retrievegood answerreal, messychunks 4, 9known answerparaphrasedchunk 12known answerout of scope— none“I don't know”Any changechunking · reranker · promptRun the golden setBetter or worse?measure, don't tune by anecdote
一张表:真实问题、期望的 chunk 和答案 —— 每次改动都跑一遍。
PracticeGolden Set· 评测集(eval set)
问题
凭轶事调优:“现在好像好些了。”
思路
真实问题 + 应该回来的 chunk + 已知正确的答案。
例子

一个杂乱的问题、一个换了说法的问题,以及一个超出范围、期望得到“我不知道”的问题。

代价
搭建和维护这套评测集要花时间。
关联
同时为检索评测和忠实度提供数据。

RAG 会在两个地方失败。把检索和生成分开衡量,先修检索,并用真实问题来搭建评测。

§ 07

RAG 很强大,也常被滥用。真正的功夫在于:在它物有所值的时候才用,保持数据新鲜,并且不为一个更简单的办法本可以省掉的机制付费。

Paste First —— 能直接粘贴的,就别上 RAG

你不会为桌上的三本书建一套图书馆目录 —— 你只是把它们翻开。

如果相关的事实又少又固定 —— 几份文档、一段简短的政策 —— 就直接**放进提示词里。**RAG 只有在知识量大到上下文装不下、经常变化,或者必须按用户过滤时,才配得上它的复杂度。为三页纸搭一条检索管线,就像为一次调用写一个智能体循环那样,属于过度设计。数据逼你用的时候,再去用它。

Your factsPaste into the promptsmall and fixed: a few docs, a short policyRAGtoo big for context · changes often · per-user filtersmallbig
小而稳定 —— 粘进提示词。大、多变或因用户而异 —— 用 RAG。
PracticePaste First· context stuffing
问题
在根本不需要的地方搭了一条检索管线。
思路
小而稳定的事实直接放进提示词。
例子
一份两页的政策放进提示词,不用建索引。
何时用 RAG
知识放不进上下文、经常变化,或者要按用户过滤。
关联
阶梯的最底层一级;RAG 是下一级。

Index Freshness —— 过时的数据就是错误的数据

电话簿只有重新印刷才有用 —— 十年前的号码,是自信而又毫无用处的错误。

RAG 的承诺是最新的事实,这意味着你的索引必须保持最新。源文档变化时,chunk 和 embeddings 也必须更新 —— 即重建索引(reindexing) —— 否则模型会把答案建立在自信的过时文本之上。把重建索引当作系统的一部分来规划,而不是事后补救 —— 新鲜度是一项需要持续维护的功能,不是一次性得到的属性。

Source docsedited · addedReindexre-chunk · re-embedIndexcurrent factsno planStale indexlast month's textOutdated answerconfident and wrong
上:文档变了,索引随之重建。下:没有计划,答案就此过时。
PracticeIndex Freshness· 重建索引(reindexing)
问题
文档变了,索引没变 —— 答案自信地过时了。
思路
按计划对变更的文档重新分块、重新做 embedding。
例子
政策更新了 —— 它的 chunk 当天就重建。
代价
一条需要你维护的重建索引管线。
关联
让 grounding 保持最新;涉及 chunk 和 embeddings。

Cost & Latency —— 盯着它们

管线里每多一步 —— 做 embedding、搜索、重排序、塞进上下文、生成 —— 都会给每一个问题增加一点时间、一点费用。

RAG 增加了若干阶段,每个阶段都要花延迟和 token。检索更多 chunk、重排序、更大的上下文 —— 都会在一定程度内提升质量,同时一路抬高账单。所以要调到能答好的最少 chunk 数,能缓存的地方就缓存,并记住:一个太慢或太贵的好答案,在生产环境里并不是好答案。

Embed+ ms · + $Search+ ms · + $Rerank+ ms · + $Stuff context+ ms · + $Generate+ ms · + $every question pays for every stagefewest chunks that answer well · cache where you can
每个阶段都增加时间和费用 —— 每个问题都要为此买单。
ConceptCost & Latency
是什么
RAG 的每个阶段,都会给每个问题增加时间和 token。
原理

更多 chunk、重排序、更大的上下文 —— 质量在一定程度内变好,成本则始终更高。

例子
重排序之后把 k 从 20 降到 5 —— 答案一样,账单更小。
注意
一个太慢或太贵的好答案,在生产环境里算不上好。
关联
与 precision & recall 和重排序相互拉扯。

RAG 只是一级台阶;模型仍然只是一个组件

好的厨房有储藏室,但储藏室不是厨师 —— 它只是给仍要亲手做出这道菜的人准备的、一份整理得当的输入。

RAG 在阶梯上位于普通提示词之上、工具和智能体之下:模型需要你的事实时就用它,并像对待任何依赖一样,把它放在干净的接口之后。检索是给模型喂料;它并不取代围绕模型的判断。纪律与到处一样 —— 用能行得通的最简单的那一级,并让模型可以替换。

Tools & agentsact, not just answerRAGthe model needs your factsPlain promptfacts fit in the promptstart low,climb onlywhen forcedcomplexsimple
普通提示词 → RAG → 工具与智能体。只有任务逼你时才往上爬。

这些概念如何连在一起

同一间厨房里的两个班次:夜里是备料 —— 把一切切好上架;白天是烹饪 —— 找出来、挑好、端上桌。

本课的一切都是分两个阶段的同一条链。离线(建索引):文档被切成带元数据的 chunk,变成 embeddings,存进向量数据库 —— 文档变化时再重建(index freshness)。查询时:混合检索找出候选,重排序留下最好的,精确率与召回率决定取多少个。然后是 grounding:模型只依据上下文作答,附上引用或诚实的拒答。另外,paste first:如果事实不多,你根本不需要这条链。而评测 —— 检索评测、忠实度、golden set —— 衡量每一个环节。

Indexing — offline, rerun when docs changeDocsChunk+ metadataEmbedVector DBANN indexQuery timeQuestionHybrid searchkeyword + vectorReranktop 50 → top 5Top-k chunksprecision ↔ recallnearestPaste firstskip RAG if facts are smallLLMcontext onlyAnswercited, or refusesgroundingEvals: right chunks? · faithful? · golden set of real questions
上:建索引。中:一个问题的路径。下:衡量整条链的评测。
上线 RAG 功能之前
  • 到底需不需要 RAG —— 还是事实又少又稳定,直接粘进提示词就行?
  • 文档是怎么分块的 —— 按含义、自成一体、带元数据和一点重叠?
  • 检索是混合并重排序的,还是一个你从没测量过的原始向量检索?
  • 模型是否只依据检索到的文本作答、注明来源,并会说“我不知道”?
  • 检索的评测是什么,与生成分开了吗?
  • 索引如何保持新鲜,一次查询要花多少时间和 token?
检索出问题的嗅探信号
  • 答案自信地出错,而你从没看过检索到的那些 chunk。
  • 只有原始向量检索 —— 没有关键词兜底,没有重排序。
  • chunk 按字符数切分,切穿了句子和表格。
  • 你在调提示词和模型,去修其实是检索遗漏的问题。
  • 自源文档变化以来,索引一直没有重建过。
你做得好的迹象
  • chunk 语义完整、自成一体,带有用于过滤和引用的元数据标签。
  • 检索是混合 + 重排序,调到能答好的最少 chunk 数。
  • 答案有依据且有引用,事实没检索到时会诚实地拒答。
  • 你把检索和生成分开衡量,并且先修了检索。
  • 索引有新鲜度计划,RAG 位于一个你随时能替换的接口之后。

速查表:全部 22 个概念

基础

Knowledge Cutoff训练截止日期

模型只知道截止某一天的训练数据 —— 不包括你的文档。

RAGRetrieval-Augmented Generation

检索相关 chunk,放进上下文,据此作答。

Grounding依据来源作答

答案建立在检索到的文本上,而且可以核对。

分块

Chunk段落

几百个词长的段落 —— 搜索的单位;大小靠测量来调。

Structure-Aware Chunking按结构切分

按标题和段落切分,并留一点重叠。

Metadatachunk 标签

来源、日期、小节、权限 —— 用于过滤和引用。

Embeddings 与检索

Embedding向量

一个向量 —— 文本含义的坐标。

Vector Search语义检索

找出含义上离问题最近的 chunk。

Vector DatabaseANN index

存放向量,并在毫秒内找到最近的那些。

Similar ≠ Relevant相似度 vs 相关性

含义上接近的 chunk,不一定包含答案。

检索质量

Hybrid Searchkeyword + vector

同时按字词和含义搜索,再合并结果。

Rerankingtwo-stage retrieval

先广泛收集候选,再仔细挑出最好的几个。

Precision & Recalltop-k

chunk 太少 —— 漏掉答案;太多 —— 答案被淹没。要测量 k。

Grounding

Context-Only Answering依据上下文作答

只依据检索到的 chunk 作答,绝不依据模型的记忆。

Citations来源标注

每个论断都指向它的 chunk,并且可以核对。

Refusal“我不知道”

chunk 里没有答案 —— 诚实地说出来,而不是编造。

评测

Retrieval Evalrecall@k

对的 chunk 回到前 k 名了吗?先修这个。

Faithfulnessgroundedness

答案中的每个论断都有 chunk 支撑。

Golden Seteval set

带期望 chunk 和答案的真实问题 —— 每次改动都跑一遍。

把它做好

Paste Firstcontext stuffing

几条稳定的事实 —— 用提示词,不用 RAG。

Index Freshness重建索引

文档变了 —— 重建索引,否则答案就过时了。

Cost & Latency时间与 token

每个阶段都花时间和 token;取能答好的最小 k。

RAG 是末端挂着一个模型的搜索系统。把 chunk 做对,答案自然随之而来 —— 模型很少是问题所在。

速成课结束 · 7 章 · 22 个概念

接下来是实践:在手头的一小批自己的文档上,搭出最小的真实 RAG —— 按结构分块、做 embedding、检索,并让模型带着引用和诚实的“我不知道”来作答。然后,在调任何东西之前,先写十个真实问题,看看检索到了什么。但要把一个想法放在所有想法之上:答案出错时,先看 chunk。在 RAG 里,模型很少是问题所在 —— 是你的检索,而这正是你能掌控的那一半。