掌握RAG Chunk切分秘籍:从入门到进阶,提升大模型召回率,小白必看!收藏版
掌握RAG Chunk切分秘籍:从入门到进阶,提升大模型召回率,小白必看!收藏版
本文深入剖析了RAG系统中Chunk切分的关键作用,通过对比三版切分方案(固定长度、句子级、语义感知),详细阐述了V3方案的实现细节,包括文档结构识别、超长章节递归细切、表格和列表项的特殊处理等。强调Chunk切分对召回率提升的显著影响,并介绍了切分质量的量化评估方法和进阶优化方向,如语义切分、Late Chunking和动态Chunk Size。最后,提供了面试中如何回答RAG Chunk切分策略的实用建议,强调打好基础的重要性。
最近有个做了半年 RAG 项目的学员,最近面阿里,聊到知识库系统的切分模块。
面试官问:“你的 chunk 怎么切的?”
他说按固定长度,512 个 token 切一刀,overlap 50。
面试官皱眉:“固定 512,保险条款里一个’保险责任’章节有三千字,切完之后每个 chunk 里都是半截话,你的召回率是多少?”
他说不太高,大概 60% 多。
面试官追问:“60% 多就这么上线了?那些跨页的大表格,第一页有表头,第二页只有数据,切完之后下半段的 chunk 是什么?”
他卡了一下:“表头丢了……就是一堆数字……”
面试官又问:“用户问’核辐射在不在承保范围’,这个 query 要召回’责任免除’章节里的一条。你的 chunk 切的时候有没有把前导句’以下情形不在承保范围’带进去?还是只切了’(3)核辐射’这一条?”
他没回答上来——不是不懂,是根本没想过这个问题。
面试官又问:“你说 overlap 50,这个数字怎么来的?拍脑袋还是有实验数据?”
他沉默了几秒,说没有做过实验对比。
面试官最后说了一句:“你切 chunk 就是在决定 LLM 能看到什么。切错了,后面做再多的优化,全是在地基不稳的楼上加砖。”
这五轮追问把一个问题暴露得很清楚:切分不只是"设置一下 chunk_size",它是一个需要分析文档特点、设计处理策略、用量化指标验证的工程模块。
回来之后他跟我说,这是他觉得准备最不够的一个模块——因为他以为切分是最简单的那一步。
Chunk 切分是 RAG 系统里最被低估的环节。大部分人调了一周的 Embedding 模型、换了好几个 Rerank,但切分始终是最开始的那个固定长度,改都没改过。今天把切分从原理到工程实现全部拆开讲。
一、为什么切分是 RAG 系统的地基?
先说一个结论:我们在项目里做了三版切分方案,V1 到 V3,召回率从 67% 提升到 91%。这 24 个百分点的提升,没有换 Embedding 模型,没有调检索策略,就是切分方式变了。
这个数字说明一件事:切分不对,检索不可能好。
原因很简单。向量检索的本质是:把用户的 query 和知识库里的 chunk 分别编码成向量,算余弦相似度,找最近的 k 个。如果一个 chunk 里的文本语义不完整——只有一半内容、表头丢失、前导句不见了——那这个 chunk 的向量就是一个"信息残缺"的向量,和任何 query 都不可能对上。
知识库有 5000 份保险文档,平均每份 80 页,如果 30% 的 chunk 是信息残缺的,那这 30% 里藏的知识,无论召回策略怎么调,都找不到。
二、三代方案对比:从 67% 到 91% 的演进路径
第一代:固定长度切分(召回率 67%)
实现最简单:按 token 数量切,每个 chunk 不超过 512 token,相邻 chunk 重叠 50 token。
问题很直观:
# 第一代:纯固定长度 def chunk_v1(text: str, chunk_size: int = 512, overlap: int = 50) -> list[str]: tokens = tokenizer.encode(text) chunks = [] start = 0 while start < len(tokens): end = min(start + chunk_size, len(tokens)) chunks.append(tokenizer.decode(tokens[start:end])) start += chunk_size - overlap return chunks
这种切法对结构化文档是灾难性的。一份三千字的"保险责任"章节被切成六个 chunk,每个 chunk 都在句子中间断开,用户问"失业了保费能缓缴吗",对应的答案在第三个 chunk 的中段,但那个 chunk 里既没有前文的章节标题,也没有后文的结论句,向量相似度算出来根本排不到前几名。
我们用 200 份文档、每份 10 个问题构建了 2000 个 QA 对的测试集,V1 的 Recall@5 是 0.67。
第二代:句子级切分(召回率 74%)
改进思路:不在句子中间切,只在句号、问号、分号等自然边界切。
import re def chunk_v2(text: str, max_size: int = 512, overlap_sentences: int = 2) -> list[str]: # 按句子边界分割 sentences = re.split(r'(?<=[。!?;\n])', text) chunks = [] current_chunk = [] current_len = 0 for sent in sentences: sent_len = len(tokenizer.encode(sent)) if current_len + sent_len > max_size and current_chunk: chunks.append("".join(current_chunk)) # overlap:保留最后 N 句 current_chunk = current_chunk[-overlap_sentences:] current_len = sum(len(tokenizer.encode(s)) for s in current_chunk) current_chunk.append(sent) current_len += sent_len if current_chunk: chunks.append("".join(current_chunk)) return chunks
句子级切分解决了"在句子中间截断"的问题,召回率提升到 0.74。但还有两个核心问题没解决:一是不理解文档层级结构,把一级标题和二级标题下的正文混在一个 chunk 里;二是没有处理表格和列表这种特殊结构——列表项"(1)核辐射""(2)战争"被拆开,每条都变成只有几十字的 chunk,信息密度极低。
第三代:语义感知切分(召回率 91%)
V3 的核心思路是:先识别文档的层级结构,按语义边界切,超长章节递归细切,特殊元素单独处理。
这一版的测试结果:Recall@5 = 0.91,比 V1 提升了 24 个百分点。
三、V3 的技术细节
3.1 文档结构识别:多策略融合
保险文档的编号体系异常复杂——有的用数字(1. → 1.1 → 1.1.1),有的用中文(第一条 → (一) → 1.),有的混用(第3条 保险责任 → 3.1 基本责任 → (1)身故保险金)。纯规则无法统一处理这些情况。
我们的方案是多策略融合:
import re from enum import Enum class HeaderLevel(Enum): H1 = 1 # 第X章/第X条 H2 = 2 # X.X 或 (X) H3 = 3 # (1)/a) 等子条款 def detect_header_level(line: str) -> HeaderLevel | None: patterns = [ (HeaderLevel.H1, r'^第[一二三四五六七八九十百\d]+[章条节]'), (HeaderLevel.H1, r'^\d+\.\s+[\u4e00-\u9fa5]'), # 1. 中文标题 (HeaderLevel.H2, r'^\d+\.\d+\s'), # 1.1 小节 (HeaderLevel.H2, r'^([一二三四五六七八九十\d]+)'), # (一) (HeaderLevel.H3, r'^(\d+)|^\d+)|^[a-z]\)'), # (1)子条款 ] for level, pattern in patterns: if re.match(pattern, line.strip()): return level return None
识别出层级之后,切分的基本原则是:同一个章节下的内容尽量放在同一个 chunk 里,跨章节绝不合并。
3.2 超长章节的递归细切
章节粒度是正确的,但保险文档里"保险责任"这类核心章节经常超过 3000 字,远超模型上下文窗口的合理使用范围。
对超长章节,V3 做递归细切:
def split_section(section_text: str, section_path: str, max_size: int = 1024) -> list[dict]: """ 单个章节的递归切分 max_size: 普通章节 1024,关键条款(责任/免责)用 1536 """ tokens = tokenizer.encode(section_text) if len(tokens) <= max_size: return [{"text": section_text, "section_path": section_path}] # 超长:按子小节边界细切 sub_sections = split_by_sub_headers(section_text) if len(sub_sections) > 1: result = [] for sub in sub_sections: result.extend(split_section( sub["text"], f"{section_path} > {sub['title']}", max_size )) return result # 没有子小节:按句子边界切,做语义完整性检查 return sentence_aware_split(section_text, section_path, max_size)
关键点:对不同类型的章节,max_size 不同。"保险责任"和"责任免除"这两类关键条款,设置了更大的 max_size = 1536,因为这类内容的任何截断都会导致语义丢失。
3.3 表格的专项处理
这是 V1 和 V2 都没解决的问题。保险文档里的表格分两种:
小表格(≤300 token): 整体作为一个 chunk,不切分。
大表格(跨页或超过 300 token): 按行切分,但每个 chunk 都要复制表头。
def split_table(table_text: str, table_title: str, max_size: int = 300) -> list[dict]: """ 大表格切分:每个 chunk 保留完整表头 """ rows = parse_table_rows(table_text) # 解析行数据 header_rows = rows[:2] # 表头(通常1-2行) data_rows = rows[2:] header_text = "\n".join(header_rows) header_tokens = len(tokenizer.encode(header_text)) chunks = [] current_rows = [] current_tokens = header_tokens for i, row in enumerate(data_rows): row_tokens = len(tokenizer.encode(row)) if current_tokens + row_tokens > max_size and current_rows: chunk_text = header_text + "\n" + "\n".join(current_rows) chunks.append({ "text": chunk_text, "metadata": { "type": "table", "title": table_title, "part": f"{len(chunks)+1}/{(len(data_rows)//10)+1}" } }) current_rows = [] current_tokens = header_tokens current_rows.append(row) current_tokens += row_tokens if current_rows: chunks.append({ "text": header_text + "\n" + "\n".join(current_rows), "metadata": {"type": "table", "title": table_title} }) return chunks
表头必须复制到每个 chunk 的原因很简单:如果 LLM 收到的 chunk 是"人身意外伤害:50万元""疾病住院:10万元"这样没有表头的数据,它不知道这是什么的费用,也不知道单位是什么,只能胡编。
3.4 列表项的处理:前导句不能丢
这是我们项目里遇到的高频 badcase 来源。
保险文档里大量的内容是这种结构:
本保险以下情况不在承保范围之内: (1)核辐射及核污染 (2)战争、军事冲突 (3)被保险人故意行为 ...
V1 和 V2 的切法会把"(1)核辐射及核污染"切成一个独立 chunk。用户问"核辐射在不在保障范围",这个 chunk 的向量里没有"不在承保范围"这个关键语义,会导致系统找到了这个 chunk 但 LLM 给出错误答案:看到"核辐射"出现了,以为是承保的。
V3 的做法:识别列表结构,把前导句和所有列表项合并为一个 chunk。如果合并后超长,至少保留前导句到每个切分出来的 chunk 里。
3.5 Overlap 策略的量化验证
"设置 overlap 100"这个决策背后我做了实验对比。
先说理论:Overlap 解决的是"关键信息恰好落在两个 chunk 边界处"的问题。比如用户问"战争是否在保障范围",相关内容是"本保险承保意外伤害(第 N 行),除以下情况:(N+1 行)战争……"。如果这两行被切在不同 chunk 里,每个 chunk 单独算向量都不能完整表达语义,加了 overlap 之后第二个 chunk 会包含第一行,语义就完整了。
实验结果:
| Overlap 大小 | Recall@5 | 存储增加 |
|---|---|---|
| 0 token | 0.81 | 基准 |
| 50 token | 0.86 | +5% |
| 100 token | 0.89 | +10% |
| 200 token | 0.90 | +20% |
| 300 token | 0.90 | +30% |
100 token 是性价比最优点:召回率提升显著(+10% vs 无 overlap),存储只增加 10%,再往上收益递减但存储成本持续上升。
在 100 token 的基础上,我还加了一个优化:基于句子边界的智能 overlap。
固定 overlap 有个问题:可能恰好切在句子中间,上一个 chunk 的最后一段话只保留了半句。智能 overlap 在确定重叠区域后,向后扫描到最近的句子结尾才真正截断。
效果:避免了 87% 的"句子在 overlap 区域被截断"问题,召回率从 0.89 进一步提升到 0.91。

RAG 三代切分方案召回率对比
四、Chunk 的元数据设计
Chunk 的文本内容切好了,元数据同样重要。我们在每个 chunk 里存了以下字段:
@dataclass class ChunkMetadata: doc_id: str # 文档ID(对应原始PDF) chunk_id: str # chunk的唯一ID section_path: str # 层级路径:"第3条 保险责任 > 3.2 责任免除" chunk_type: str # "text" | "table" | "list" is_key_clause: bool # 是否是关键条款(责任/免责/费率) prev_chunk_id: str # 前一个chunk的ID next_chunk_id: str # 后一个chunk的ID token_count: int # token数量 page_range: str # 来源页码范围
这几个字段的用途:
section_path:用于答案溯源。用户问"核辐射在不在保障范围",系统能回答"根据第3条保险责任 > 3.2 责任免除 > (2),核辐射不在保障范围。"这比直接回答更有说服力,也更容易让用户验证。
is_key_clause:在检索时给关键条款加 1.5 倍权重。识别方法是关键词匹配(“责任”“免责”“费率”“赔付”)加章节标题判断,准确率 94%。
prev/next_chunk_id:上下文扩展。如果检索到的 chunk 语义不完整(比如只检索到了"以下情况除外:"这半句),自动拉取相邻 chunk 补全上下文。
五、切分质量怎么评估?
切分质量的评估不能靠人眼看,必须量化。我们用的核心指标是召回完整率:对一个问题,正确答案所需的 chunk 是否都在 Recall@5 里。
具体流程:
- 构建 QA 测试集:200 份保险文档,每份人工编写 10 个问题,总计 2000 个 QA 对。每个问题标注了"正确答案应来自哪个 Chunk"。
- 跑端到端检索:对每个 query,看系统返回的 Top 5 Chunk 是否包含标注的 ground truth chunk。
- 分维度拆解:表格类问题的召回率多少?列表类问题多少?超长章节类问题多少?哪类场景是短板?
这种分维度的评估暴露了一个问题:V2 在表格类问题上的召回率只有 0.51,在文本类问题上是 0.82。这直接指导了 V3 的优化方向——先解决表格问题。
构建测试集是有成本的——2000 个 QA 对,我们花了两个人一周的时间标注。但这个投入是一次性的,后续每次改切分方案,跑评估只需要 10 分钟,立刻知道有没有提升。很多团队不愿意做这个前置投入,导致改了方案之后"感觉更好",但说不清好了多少。项目答辩或者面试时被追问"你怎么知道这个方案更好",只能含糊其辞——这是很减分的回答。
六、实际踩过的三个坑
坑一:chunk_size 太小,语义不完整
我们最初 chunk_size 设 512,是参考了大量博客文章。但保险文档的平均句子长度是通用文档的 1.5 倍(条款表达通常更复杂),512 token 切出来的 chunk 经常只有半个段落。
后来改到 1024(关键条款 1536),召回率提升了 7 个百分点。这件事说明 chunk_size 不是一个通用参数,它应该和文档类型挂钩。通用中文文档平均句子 20-30 字,512 token 大约够 2-3 段;但保险条款每句平均 40-50 字,同样 512 token 经常只有一段话的开头和中间,上下文完全断掉了。
坑二:表格表头丢失导致 LLM 答错
这是最高频的 badcase 类型之一。在我们第一轮上线的系统里,表格类问题的正确率只有 43%——不是因为检索没找到表格,而是找到的表格 chunk 里没有表头,LLM 看不懂数字对应的是什么字段。
加了"每个 chunk 复制表头"的逻辑之后,表格类问题正确率提升到 78%。
坑三:列表项被孤立切分
“(1)核辐射”“(2)战争"这类列表项单独成 chunk 之后,向量编码时完全不知道这两条的语义背景是"责任免除"还是"特别约定”,导致否定性查询(“哪些情况不赔”)的召回率格外低——测试集里这类问题的召回率只有 0.58。
加了前导句合并逻辑后,否定性查询的召回率提升到 0.83。

切分策略对不同类型问题的影响分析
七、进阶优化方向:切分技术的前沿
掌握了 V3 的方案之后,面试官有时候还会问:"还有哪些改进空间?"这是考察技术视野的问题。以下三个方向值得了解。
语义切分(Semantic Chunking)
思路是用 Embedding 模型来判断切分点:计算相邻句子的向量相似度,相似度突变的地方(语义跳跃点)就是自然的切分边界。比如"保险责任"讲完了,开始讲"责任免除",这两段的句子向量之间的相似度会显著下降。
理论上比规则方法更精准,但在实践中有两个问题:第一,计算成本高(每次切分都要跑 Embedding 推理);第二,对短文本段落效果不稳定。目前我们的项目里还是用 V3 的规则方案,Semantic Chunking 作为候选放在迭代计划里。
如果面试官追问"为什么不直接用 Semantic Chunking",可以这样回答:对我们 5000 份文档、平均 80 页的 PDF 来说,全量 Embedding 切分一次需要几十分钟;而新文档上线需要在几分钟内完成建库——规则方案切分一份文档只需要 2-3 秒,Semantic Chunking 要 30-40 秒。工程上不是"哪个更好",是"在当前的时延约束下,规则方案是目前唯一能用的方案"。
Late Chunking
这是 2024 年底出现的一个新方向。基本思路是:先用长文本 Embedding 模型对整个文档(或章节)编码,获取每个 token 在完整上下文下的向量表示;再在向量层面做切分,而不是在文本层面切。
好处是每个 token 的向量里都带有全文的上下文信息,不存在"切断了就丢失了前文语义"的问题。缺点是对模型的上下文长度有要求(需要支持长文档输入),且目前支持这种编码方式的开源模型还不多。
从工程可行性角度来看,Late Chunking 目前处于研究向阶段。我们评估过 jina-embeddings-v3 的 Late Chunking 实现,在单文档上效果确实有提升,但多文档批量处理时的内存占用是传统方案的 8-10 倍,暂时没法用在生产环境里。值得追踪,等硬件成本下来或者出现更高效的实现,这个方向可能是下一代 RAG 切分的标准答案。
动态 Chunk Size
不同类型的内容应该有不同的 chunk_size。我们目前的实现是对关键条款用 1536、普通文本用 1024,还比较粗糙。更细粒度的做法是:根据章节的语义密度(信息量/token 数)动态调整,高密度章节用更大的 size,低密度的简介类内容用更小的 size。
这个方向我们在 A/B 测试阶段,初步结果显示对多跳推理类问题的召回率有 3-5 个百分点的提升。具体判断"语义密度"的方式是:先用 LLM 给章节内容打一个信息密度评分(0-10分),高于 7 分的章节用 1536,低于 4 分的用 512,中间区间用 1024。目前这个评分本身也需要推理时间,成本和收益还在权衡中。
八、面试怎么答 RAG Chunk 切分策略?
这个问题是面试官筛选候选人深度的常用手段。很多人卡在第一层就出不来。
先讲演进路径(30 秒)。 “我们做了三版方案。V1 是固定长度切分,Recall@5 是 0.67;V2 换成句子级切分,提升到 0.74;V3 设计了语义感知切分,最终达到 0.91。每一版都是被 badcase 推着走的。”
讲 V3 的核心设计(60 秒)。 “V3 有四个核心改进:第一,用多策略融合的层级分类器识别文档结构,按章节边界切而不是 token 数切;第二,超长章节递归细切,普通章节 1024 token,关键条款用 1536,保证语义完整;第三,表格专项处理,每个切分后的 chunk 都复制表头,大表格按行切分;第四,列表项合并前导句,避免’(1)核辐射’这种孤立 chunk 丢失语义背景。”
讲 Overlap(20 秒)。 “Overlap 我做了实验对比,100 token 是性价比最优点,比无 overlap 提升 10 个召回率点,存储只增加 10%。同时加了基于句子边界的智能 overlap,避免了 87% 的句子在重叠区域被截断的问题。”
讲元数据(20 秒)。 “每个 chunk 存了 section_path、is_key_clause、前后 chunk ID 等元数据。section_path 用于答案溯源,is_key_clause 用于检索加权(关键条款权重 1.5 倍),前后 chunk ID 用于检索到半截信息时自动扩展上下文。”
讲评估方法(20 秒)。 “评估用 2000 个 QA 对,分文本、表格、否定查询、多跳推理四类分别看召回率,找到 V2 的主要短板是表格类(0.51)和否定查询(0.58),这直接指导了 V3 的优化方向。”
写在最后
Chunk 切分是 RAG 系统里最不起眼但最基础的环节。很多人上来就研究 Embedding 模型哪个好、Rerank 用什么算法,但知识库里有 30% 的 chunk 是残缺的,后面的一切优化都是在残缺的地基上建楼。
我在项目里见过的反例是:换了最好的 Embedding 模型,Recall@5 从 0.67 提升到 0.71;把切分方案从 V1 升级到 V3,Recall@5 从 0.67 直接到 0.91。这 4 个点和 24 个点的差距,说明了一件事:先把地基打实,再去调上层。
面试官问切分策略,本质上是在问你有没有真正做过工程——会不会分析 badcase、有没有量化指标、知不知道不同类型的内容需要不同的处理方式。这些细节,是调包调不出来的。
最后
近期科技圈传来重磅消息:行业巨头英特尔宣布大规模裁员2万人,传统技术岗位持续萎缩的同时,另一番景象却在AI领域上演——AI相关技术岗正开启“疯狂扩招”模式!据行业招聘数据显示,具备3-5年大模型相关经验的开发者,在大厂就能拿到50K×20薪的高薪待遇,薪资差距肉眼可见!

业内资深HR预判:不出1年,“具备AI项目实战经验”将正式成为技术岗投递的硬性门槛。在行业迭代加速的当下,“温水煮青蛙”式的等待只会让自己逐渐被淘汰,与其被动应对,不如主动出击,抢先掌握AI大模型核心原理+落地应用技术+项目实操经验,借行业风口实现职业翻盘!
深知技术人入门大模型时容易走弯路,我特意整理了一套全网最全最细的大模型零基础学习礼包,涵盖入门思维导图、经典书籍手册、从入门到进阶的实战视频、可直接运行的项目源码等核心内容。这份资料无需付费,免费分享给所有想入局AI大模型的朋友!

👇👇扫码免费领取全部内容👇👇

部分资料展示
1、 AI大模型学习路线图

2、 全套AI大模型应用开发视频教程
从入门到进阶这里都有,跟着老师学习事半功倍。

3、 大模型学习书籍&文档

4、 AI大模型最新行业报告
2025最新行业报告,针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

5、大模型大厂面试真题
整理了百度、阿里、字节等企业近三年的AI大模型岗位面试题,涵盖基础理论、技术实操、项目经验等维度,每道题都配有详细解析和答题思路,帮你针对性提升面试竞争力。


6、大模型项目实战&配套源码
学以致用,在项目实战中检验和巩固你所学到的知识,同时为你找工作就业和职业发展打下坚实的基础。

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
- 👇👇扫码免费领取全部内容👇👇

这些资料真的有用吗?
这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。
资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多推荐



所有评论(0)