LLM 面试备考
首页/RAG

分块策略 Chunking Strategies

所属:01-fundamentals / 03-rag
面试权重:★★★
来源:通用领域知识(B站「RAG 面试」合集高频);未做一手考证

一句话#

Chunking 决定检索的最小语义单元:切得太大,向量被稀释成「主题平均」,召回不准、还挤占生成上下文;切得太小,一句半句缺主语,召回了也没用 —— 它本质是在检索粒度与生成上下文完整性之间找一个平衡点,而且这个平衡点由 embedding 模型的长度上限、文档结构与问题类型共同决定。

为什么重要(面试角度)#

Chunking 是 RAG 里最高杠杆、最容易被忽略的一个决策。很多「RAG 效果差」的真实根因就在切分上,但因为症状出现在检索或生成,大家会先去调 prompt、换模型,绕一大圈。

面试官想看的不是「我用 RecursiveCharacterTextSplitter,chunk_size=512, overlap=50」这串配置(虽然要能报出来),而是:

  • 你知不知道 chunk size 和 embedding 模型的 max sequence length 是耦合的(超过就被截断,尾部内容形同没有)
  • 你能不能说出固定 / 递归 / 语义 / 父子四种策略各自的适用场景与代价
  • 你理解 overlap 是「用冗余换召回」,代价是索引膨胀与近重复结果
  • 你意识到结构信息(标题、表格、代码块)比字数更重要 —— 切在句子中间几乎总是错的

核心内容#

四种策略#

策略 做法 优点 代价 / 适用
固定长度(fixed-size) 按 token/字符数硬切,可加 overlap 简单、可预测、快 会切断句子/表格/代码;只适合纯散文且无结构信息
递归切分(recursive) 按分隔符优先级递归切:\n\n → \n → 句号 → 空格,直到 ≤ 目标长度 尽量保句完整,最通用的默认选择 仍是「长度优先」,对表格/代码无能为力
语义分块(semantic) 句子两两算 embedding 相似度,在相似度骤降处断开 按语义边界切,跨主题段落可分干净 索引阶段要额外跑一遍 embedding,慢且贵;阈值难调;效果提升并非总是稳定,取决于语料
父子 / 层次分块(hierarchical / parent-child / small-to-big) 存小 chunk 用于检索,返回时上层大块(或邻近窗口)喂给生成 同时兼顾检索精度与上下文完整,缓解边界切断 存储与实现更复杂;父块太大会稀释上下文

「结构感知」是横切的一层:Markdown 按标题层级切、按表格/代码块边界切、按 PDF 的版面切。规则是 优先切在语义/结构边界,长度只是保底手段。真实系统通常是组合式:先按文档结构(H1/H2)分段,段内再递归切,必要时加语义边界修正。

尺寸与 overlap 的取舍#

chunk size:

  • 太小(如 < 128 token):embedding 的语义被上下文缺失搅浑(「它的价格是 300 元」里「它」指谁?),召回语义模糊;且一条完整答案被拆到多个 chunk,命中一个也答不全。
  • 太大(如 > 1024 token):embedding 被多主题平均化,向量落在「主题重心」上,具体问题的分辨力下降;同时 top-n 注入的 token 暴涨,噪声增多、成本上升、lost-in-the-middle 更容易发生。
  • 常见起点在 256–1024 token 量级、相邻块重叠 10%–20% —— 但这是经验值,随语料、embedding 模型、问题类型大幅变化,面试里别当结论背,要说「靠评测集扫出来」。

    ⚠️ 口径统一说明:本文此前写「200–512」,而 02-interview/design/01-enterprise-rag.md 写「~500–1000」,两处上界差了一倍,被追问「为什么是 512 不是 1024」时会露怯。现统一为 256–1024 / overlap 10%–20%(与《深入理解 AI Agent》第 3 章的实践口径一致),并明确:这个区间的意义是「在这里起步」,不是「答案在这里」 —— 最终值必须由评测集扫出来。

overlap:

  • 作用:防止答案正好落在切点上被腰斩,让边界信息在两个 chunk 里都出现。
  • 代价:索引体积与 embedding 成本按 1/(1-overlap_ratio) 放大;检索结果里出现近重复 chunk,浪费 top-n 名额。
  • 经验值 overlap 常取 chunk size 的 10%–20%;overlap 太大等于变相缩小有效 chunk size。

chunk size 与 embedding 模型的 max length 耦合#

这是最容易被忽略、也最能区分候选人的一点:

  • 每个 embedding 模型有 max sequence length(如 512 token,或因位置编码外推而更长的 512/8192 等,具体上限随模型不同,必须查该模型的 model card)。
  • 如果 chunk 的 token 数超过这个上限,编码器会截断(多数实现保留前 N 个 token)或池化出退化表示 —— 结果是你以为 chunk 包含的信息,其实尾部根本没进向量。文档里明明写着的答案,检索永远找不到。
  • 所以 chunk size 必须 ≤ embedding max length(一般取 0.8 倍留余量),否则 chunking 再讲究也白搭。
  • 反过来,用长上下文 embedding 模型(支持几千 token)时,chunk 可以更大,但要注意:模型支持的长度 ≠ 在该长度上语义分辨力好,长文本 embedding 普遍存在「细节被平均掉」的问题。

与检索/生成的张力#

同一个 chunk 要同时服务两个目标,而它们偏好相反:

目标 偏好 原因
检索(retrieval) 小 chunk 向量语义更聚焦、匹配更准、top-n 里放得下更多候选
生成(generation) 大 chunk 答案需要完整论述、步骤、表格;上下文越完整越不容易断章取义

父子分块(small-to-big)正是为解这个矛盾而生:用小 chunk 去匹配查询(检索精度),返回父块或邻近窗口给 LLM(生成完整性)。这也是面试里最值得主动抛出的解法。

怎么选:一个可操作的流程#

  1. 先看文档结构:有标题/表格/代码就先做结构感知切分,别一上来就按字数。
  2. 定上界:chunk size ≤ 0.8 × embedding max length。
  3. 在评测集上扫参:准备带 gold chunk 标注的问答集,扫 chunk size ∈ {128, 256, 512, 1024} × overlap ∈ {0, 10%, 20%},看 Recall@k(检索侧)与 Faithfulness(生成侧)的联合变化,而不是拍脑袋。
  4. 必要时上父子分块:检索用 256、喂生成用 1024(或整节)。
  5. 增量为维护留口:新增文档要能只重切/重嵌变化的 chunk,所以 chunk id 要可稳定生成。

常见坑的归类#

症状 可能的 chunking 根因
答案总差一句、缺条件 固定切分切断了条件句/表格行
检索到的都是「相关但不对」的 chunk chunk 太大,向量被主题平均
同一文档的相邻 chunk 反复挤占 top-n overlap 太大导致近重复
答案就在文档里却永远召不回 chunk 超过 embedding max length 被截断,或答案被切散
表格类问题普遍答错 未做结构感知,表格被打散成碎片

常见面试问法#

Q:你的 chunk size 怎么定的? A:不是拍脑袋。先保证 chunk ≤ 0.8×embedding 模型 max length 不被截断;再在有 gold chunk 标注的评测集上扫 {128/256/512/1024}×{10%/20% overlap},用 Recall@k 和 Faithfulness 联合选。除此之外先做结构感知切分(标题/表格/代码),长度是保底手段而非首选。

Q:chunk 越小检索越准吗?那是不是越小越好? A:不是。太小的 chunk 缺上下文,embedding 语义模糊(指代、省略都解不了),而且一条完整答案被拆散、命中也不完整。小 chunk 的优势在检索分辨力,但会牺牲生成所需的完整性 —— 正确做法是用父子分块把两者分开满足。

Q:overlap 有什么用?开大点是不是更保险? A:overlap 防止答案正好落在切点被腰斩,让边界信息在两块中都出现。但代价是索引与 embedding 成本按 1/(1-r) 放大,且产生近重复 chunk 挤占 top-n。常用 10%–20%,不是越大越好。

Q:为什么 chunk size 会和 embedding 模型相关? A:每个 embedding 模型有 max sequence length,超长会被截断或池化退化,导致 chunk 尾部根本没进向量 —— 文档里有的内容永远检索不到。所以 chunk size 的上界由 embedding 模型决定,长上下文 embedding 可以放宽这个上界,但不代表长文本的语义分辨力同样好。

Q:语义分块听起来更高级,为什么不是默认选择? A:它以「相邻句 embedding 相似度骤降」为切点,确实更贴语义边界,但代价是索引阶段要多跑大量 embedding、阈值对语料敏感、效果提升并不总是稳定(取决于文本是否本来就有清晰的主题切换)。所以在结构清晰的文档上,结构感知 + 递归切分往往性价比更高。

易错点#

  • ❌ 只报一个 chunk_size=512 的数字,说不出为什么、也没提评测依赖。
  • ❌ 忽略 chunk size 与 embedding max length 的耦合 —— 超长被截断是「内容存在但召不回」的经典隐形杀手。
  • ❌ 把 overlap 当「越大越保险」,不承认它的索引膨胀与近重复代价。
  • ❌ 认为存在普适最优 chunk size(它高度依赖语料与问题类型,必须靠评测选)。
  • ❌ 只按字数切,无视标题、表格、代码这些天然边界。
  • ❌ 断言语义分块一定优于递归分块 —— 这是依赖语料的经验判断,不是定论。
  • ❌ 忘了增量:文档更新时要能重建受影响的 chunk,而不是全量重嵌。

自测#

1. 一个用户说「文档里明明写了答案,RAG 就是检索不到」。除了换 embedding 模型,chunking 上有哪两个最值得先查的假设?

答案

①chunk 是否超过 embedding 模型的 max length 被截断 —— 答案落在 chunk 尾部时根本没进向量,怎么检索都找不到;查该模型的 model card 确认上限,把 chunk size 压到 0.8 倍以内。②答案是否被切点腰斩 —— 关键句被拆到两个 chunk,各自语义都不完整,两个都召不回;对策是结构感知切分 + overlap,或父子分块(小 chunk 检索、父块返回)。

2. 为什么说父子分块(small-to-big)能缓解检索粒度与生成上下文的矛盾?

答案

因为检索与生成对 chunk 大小的偏好相反:检索要小(语义聚焦、分辨力高、top-n 能放更多候选),生成要大(答案需要完整论述、步骤、表格)。父子分块把二者解耦 —— 用小 chunk 建索引去匹配查询,命中后返回其父块/邻近窗口给 LLM 生成。这样既保住检索精度,又不让模型看到断裂的上下文。代价是存储与实现的复杂度。

3. overlap 从 10% 提到 50%,会发生什么?

答案

好处:切点腰斩的风险进一步降低。坏处:①索引体积与 embedding 计算量按 1/(1-0.5)=2 倍膨胀;②大量近重复 chunk,检索后 top-n 里同义内容反复占位,实际信息多样性下降,还浪费生成上下文;③有效 chunk size 被压缩。结论是 overlap 是「用冗余换召回」的边际递减手段,10%–20% 通常够用,不是越大越好。

4. 什么样的语料适合语义分块,什么样的不适合?

答案

适合:主题切换平滑但边界不靠格式标记的连续文本(如访谈稿、会议记录、长论述),语义分块能把跨主题段落分干净。不适合:结构本来就清晰的文档(Markdown 有标题层级、有表格/代码块)—— 直接按结构切更准更便宜;也不适合本身句子间高度同质的文本(相似度没有明显骤降点,阈值难定)。注意语义分块的收益是依赖语料的经验结论,需实测,不能默认更优。

5. 如果面试官让你「现在就定一个 chunk 方案去做 POC」,你会怎么说?

答案

「先按文档结构做结构感知切分(标题/表格/代码边界);chunk size 初值取 256–1024 token(常见起点 512 左右),且必须 ≤ 0.8×embedding max length 以免截断;overlap 取 10%–20%。然后我准备一个带 gold chunk 标注的小评测集(几十到上百题),扫几组 chunk size × overlap,用 Recall@k 选检索侧最优、用 Faithfulness 确认生成侧没退化;如果发现答案跨块,就上父子分块。参数最终由评测决定,而不是我拍脑袋。」—— 关键是体现先约束、后扫参、以评测为准的方法论。