RAG 系统中为什么要进行文档切割?有哪些切割策略?
- 标签:RAG、文档切割
🏛 业务架构师
RAG 文档切割的原因,从三个业务约束讲:
检索粒度决定命中精度:Embedding 是把一段文字压成一个向量——文档越长,向量语义越"平均化",一份数十页的年报压成一个向量,问"净利润"根本区分不出来。切成语义聚焦的小块,才能"一块一义"精准命中——这是检索质量的物理基础;
上下文窗口与成本经济性:命中的内容要进模型上下文,按 token 计费。整篇文档进上下文既贵又稀释注意力(模型被无关内容带偏);分块让进入窗口的是"精准段落",成本可控、答案聚焦;
引用溯源的业务需求:答案要标注"依据第几章第几条",分块是最小可引用单元——合规审计、用户核验都要靠它。
常见切割策略:固定长度+重叠(简单,通用兜底);递归字符切分(段落→句子→字符逐级回退,LangChain 默认);结构化切分(按 Markdown 标题/HTML 标签/PDF 章节,对齐业务结构,制度文档首选);语义切分(按语义突变点,效果最好成本最高);父子分块(小块检索、大块送模型,兼顾精度与上下文)。
我的落地建议:参数没有银弹(一般 300~500 字、10%~20% 重叠起步),按知识形态选策略——FAQ 整条入库、制度按条款、技术文档按章节;上线后靠 badcase 归因迭代,"检索不准"的 case 里一半能追到切割问题。
🏗 系统架构师
文档切割(Chunking)的原因与分块策略,我按架构视角讲——分块本质是 RAG 的"索引设计":
为什么要切割:
- 检索粒度:整篇文档一个向量,语义被平均稀释,检索不精准;粒度合适的 chunk 才能让向量代表一段完整语义;
- 窗口经济学:上下文按 token 计费 + attention 稀释效应(lost-in-the-middle),RAG 的本质是"只送相关的几段"——chunk 是成本与精度的平衡单元;
- 命中效率:几个精准的小 chunk 比一整篇泛化文档效果好且便宜。
切割策略谱系(简单到复杂):
- 固定长度:按 token 数切 + 10~20% 重叠(缓解边界断义)——兜底方案;
- 递归字符切分:按分隔符优先级(段落→句子→词)递归切,保自然语义边界——通用默认(LangChain RecursiveCharacterTextSplitter);
- 结构感知:按 Markdown 标题、HTML 标签、代码函数边界切——生产首选,语义最完整;
- 父子块(Small-to-Big):小块检索(精准命中)、命中后返回父块(完整上下文给 LLM)——解耦检索单元与生成单元,我最推荐的进阶方案;
- 语义切分:相邻句 embedding 相似度找断点——效果上限高但成本高、不稳定。
参数经验:chunk_size 256~512 token 起步,overlap 10~20%;具体用金标集跑 recall@K 对比调优。架构纪律:chunk 必须带元数据(文档 ID、标题路径、页码)——没有溯源和权限过滤的 chunk 体系是半成品。
💻 全栈开发专家
文档切割是 RAG 检索质量的「地基工程」——切得差,检索和生成再强也救不回。
为什么要切:Embedding 有长度上限且长文向量语义被稀释;上下文预算有限;引用要落到段落粒度。
切割策略(按我使用频率排):
- 递归字符切分(默认兜底):按分隔符优先级递归——段落
\n\n→ 换行 → 句号 → 空格,在最大 chunk 内尽量贴自然边界:
python
RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)- 结构化切分(文档有标题层级时首选):Markdown 按
#层级、HTML 按标签切,标题路径(「产品手册/安装/Linux」)存入 metadata——检索可按章节过滤,上下文有归属感; - Token 切分:精确控制 token 预算,配合长文档分块;
- 语义切分:相邻句 Embedding 相似度突变处断开,块大小不均但语义完整(成本高,效果增量看语料);
- 父子块(Small-to-Big):小块(128t)做检索、父块(1024t)做生成,检索准+上下文全,生产推荐;
- 特殊对象单独处理:表格整块不切(或行列展开)、代码按函数边界、FAQ 按问答对。
参数经验:chunk_size 256~1024( Embedding 模型最优区间附近),overlap 10%~20% 防语义被边界截断。不要抄参数——拿评测集跑几组 chunk_size 的 recall@k 对比,不同语料最优解差异很大。