分块与向量搜索直觉。
RAG 的检索步骤建立在两个机制上:把文档切成片段,以及按含义而非关键词找出相关片段。本文为两者建立直觉——为何要分块、块大小为何是一个权衡、嵌入向量是什么、相似度搜索如何工作,以及决定检索是否真能找到答案的实用旋钮。
到底为何分块。
你无法把"那份文档"作为一个单元来索引,也无法把整份文档塞进提示词。所以在任何东西可被搜索之前,每个来源都被切成更小的段落——片段(chunk)——通常每块几百令牌。两个原因:
- 检索精度。用户问一个狭窄的问题。你想要回答它的那一段,而非一份 40 页 PDF。小单元让搜索能返回聚焦的段落。
- 上下文预算。提示词空间有限且受迷失在中间之害。检索 5 个紧凑片段,胜过检索 3 份挤掉答案的庞大文档。
块大小是权衡,不是设置项。
CHUNK TOO SMALL (e.g. 1 sentence)
+ very precise match
- answer is fragmented across many chunks; each lacks context
- "It supports this" -- "it" = ? the chunk lost the subject
CHUNK TOO LARGE (e.g. whole section)
+ each chunk is self-contained
- one chunk covers many topics -> diluted, weaker match
- wastes context budget; buries the relevant sentence
SWEET SPOT (often a paragraph / heading-bounded passage)
- one coherent idea, enough context to stand alone
实践中要紧的两个改良。重叠:让相邻片段共享一两句话,使横跨边界的答案不被切成两半。结构感知切分:按标题、段落或代码块切分,而非每 N 个字符切一刀,使片段是一个连贯单元而非任意切片。没有放之四海皆准的最佳大小——它取决于你的文档和查询,是你去测量的东西,不是去猜的。
嵌入:把含义化为坐标。
当用户和文档对同一概念用不同词时("reset password" 对 "account recovery"),关键词搜索会失败。解法是把含义用数值表示。嵌入模型把一段文本变成一个向量——比如 1,536 个数字的列表——其位置使含义相近的文本在那个空间里彼此靠近。
"reset my password" -> [ 0.02, -0.91, 0.33, ... ] --.
"recover account access"-> [ 0.04, -0.88, 0.31, ... ] --+-- close together
"chocolate cake recipe" -> [-0.77, 0.12, -0.50, ... ] -- far away
你不去解读单个数字;没有哪一维表示"正式程度"或"主题"。要紧的是相对位置:语义相似的文本聚成簇,无关的文本相距遥远。这与"基础"一节里的嵌入是同一个思想——在这里它是检索的引擎。
向量搜索:最近邻。
检索流水线变成:
- 建索引(离线)。把每份文档分块,为每块做嵌入,把向量连同原文一起存进向量数据库。
- 查询(在线)。用同一个模型嵌入用户的问题,然后找出与它最接近的已存向量。
- 返回。最接近的 top-k 片段的原文成为 RAG 的检索上下文。
"最接近"由一个相似度度量衡量——最常见的是余弦相似度,它比较两个向量的方向(1.0 = 含义相同,0 = 无关)。在规模下,精确最近邻搜索太慢,所以向量数据库用近似最近邻(ANN)索引:略不精确,但快得多,几乎总是对的取舍。
查询和文档必须用同一个模型嵌入。来自不同模型的向量处于不兼容的空间;比较它们会产生无意义的距离。如果你换嵌入模型,就必须重新嵌入整个语料。
为何纯向量搜索不够。
语义搜索有真实的盲区,知道它们正是 demo 与系统之别:
- 精确令牌。产品编号、错误号、人名、某个确切 API 符号——嵌入把这些抹成"大致相似","ERR_4012" 与 "ERR_4021" 看起来会很近。关键词/BM25 搜索在此精确。生产检索常用混合搜索:合并关键词与向量结果。
- top-k 是权衡。太小会漏掉答案片段;太大会用噪声淹没上下文并触发迷失在中间。常见起点是 k=5,再在真实查询上调。
- 重排序。向量搜索快但粗。一个常见升级:用 ANN 检索一个宽裕的候选集,再用一个更慢更准的重排序模型重新排序并留下前几个。用廉价检索保召回,用昂贵重排序保精度。
- 单独评估检索。构建一小组带已知正确片段的问题并测量:正确片段在 top-k 里吗?大多数"AI 给了错误答案"的 bug 实际是"正确片段从未被检索到"——而你只有把检索与生成分开测量才能看到这点。
交付物
你理解为何文档要分块,以及块大小是精度对上下文的权衡,靠重叠和结构感知切分来解决。你能把嵌入解释为文本被映射到一个向量、靠近即含义相似,并把向量搜索解释为用同一模型嵌入查询、按余弦相似度返回其最近邻(规模下用近似)。你知道纯语义搜索会漏掉精确令牌,故生产用混合搜索与重排序——而信任检索的唯一方式,是直接、与生成答案分开地评估它。