RAG Chunk 策略怎么定?固定长度 vs 语义分块 vs Agent 分块
chunk 方式不对embedding 模型再强也白费。你的 RAG 系统里90% 的检索失败是 chunk 切出来的问题不是搜的问题。一个花了三天才定位到的 bug有个团队做了个论文阅读 RAG 系统。工程师花了大量精力调 embedding 模型、试各种向量数据库、优化 prompt……但检索质量始终上不去。问题出在哪用户问的问题检索出来的文档片段要么不完整、要么夹杂不相关信息。我让他们随便找一篇 PDF 原文看看 chunk 结果。一看就发现了问题——他们的 PDF 解析器按固定 500 字符切分切到图片/表格/公式时直接从中间拦腰切断。结果呢Chunk 42: ...而 Transformer 架构的核心创新在于自注意力机 Chunk 43: 制和位置编码。我们提出了一种新的训练方 Chunk 44: ...法在 WMT2014 英德语对上获得了 28.4 BLEU一个完整的核心段落被切成三块。用户的 query 如果恰好匹配的是 chunk 43 里的内容这个 chunk 去检索它既没有开头也没有结尾信息量少了一大半。换了三种 chunk 策略跑了一轮对比策略Recall5有效回答率固定 500 字无重叠0.5241%固定 500 字20% 重叠0.6153%语义分块按段落切0.7876%关键信息有时候问题不在向量检索在 chunk 切错了。为什么 chunk 如此重要RAG 系统的检索链条是文档 → chunk → embedding → 向量检索 → LLM 生成。chunk 在这条链上处于地基的位置——后面的每一步都建立在你切出来的 chunk 上。chunk 的好坏影响三个方面1. 语义完整性每个 chunk 应该是一个自包含的语义单元。如果一段逻辑拆到两个 chunk 里检索时只命中其中一个LLM 得到的信息就是残缺的。2. Chunk 数量切得太碎 → chunk 数量爆炸 → 向量数据库膨胀 → 检索耗时增加 → 召回质量下降。切得太粗 → 每个 chunk 包含太多无关信息 → embedding 向量被平均化 → 相似度计算不准确。3. LLM 上下文窗口chunk 过大会挤占 LLM 的上下文窗口。比如 GPT-4 Turbo 有 128k 的窗口但你塞 50 个 2000 字的 chunk一下子就填满了留给 system prompt 和对话历史的空间就少了。这是 RAG 工程中最经典的取舍问题。下面我们看几种主流的 chunk 策略。策略一固定长度分块Fixed-size Chunking一句话最简单但容易出错。原理按照固定的字符数或 token 数从头到尾切通常会加上重叠窗口。这是所有方法里最无脑的。deffixed_size_chunktext: str, chunk_size: int 500, overlap: int 50liststr 固定长度分块带重叠窗口。 0lenwhilemin# 滑动步长 chunk_size - overlapreturn这是一篇很长的文档。20030030printf总长度: {len(text)} 字 → {len(chunks)} 个 chunkprintfChunk 0 长度: {len(chunks[0])} 字printfChunk 0: {chunks[0][:50]}...LangChain 实现fromimport# 虽然叫 Recursive实际上默认行为也是固定 token 数切50050\n\n\n。 优点实现简单零思考速度快O(n)任何语言/格式都能用缺点可能从句子/段落中间切断对文档结构无感知重叠窗口虽然缓解了边界问题但引入了重复数据最佳实践# 如果你要用固定长度分块至少要做到# 1. 在段落边界上切\n\n# 2. 只对足够大的段落做二次分割# 3. 选择合适的分隔符优先级500100# 推荐 chunk_size 的 10-20%\n\n\n。len什么时候用快速原型、数据格式统一如纯日志文本、你知道内容结构规整。策略二递归字符分块Recursive Character Chunking一句话LangChain 默认方案兼顾简单和效果。原理递归分块和固定长度分块的区别在于它不是无脑切而是尝试在段落/句子边界上切如果一段太长才递归地切小。defrecursive_chunk_by_separators text: str, chunk_size: int 500, chunk_overlap: int 50, separators: list[str] Noneliststr 递归分块优先在高级分隔符段落上切 不行再降级到低级分隔符句子。 ifisNone\n\n\n。# 从第一级段落分隔符开始0forin# 如果这一段太长递归到下一级分隔符iflenif# 用下一级分隔符递归切分1eliflenlen0else# 带上重叠内容if0else0ifreturn实际使用直接用 LangChain 就好fromimport# 中文推荐的分隔符优先级50050\n\n\n。 Falsewithopendocument.mdrasprintf生成了 {len(chunks)} 个 chunk# 效果比固定长度好 15-20%关键参数chunk_size: 500 是最常用的起点。英文按 token 算~~200-300中文按字符算~~500-800。chunk_overlap: chunk_size 的 10-20%。太小边界信息丢失太大量太大。separators: 中文要加上。 “” “作为句子分隔符否则递归会退化到按字符切”。什么时候用绝大多数 RAG 场景的默认选择。如果不知道用什么先用递归分块。策略三语义分块Semantic Chunking一句话不要按字符数切要按逻辑段落切。原理语义分块的思想是embedding 模型来判断两段文本是否属于同一个话题。如果两段文本的语义距离超过某个阈值就在那里切开。fromimportimportasdefsemantic_chunk text: str, model_name: str BAAI/bge-small-zh-v1.5, threshold: float 0.65, min_chunk_size: int 100, max_chunk_size: int 1000liststr 语义分块按句子之间的语义变化点来切分。 # 1. 先按句子分割importr(?[。\n])forinififlen1return# 2. 计算相邻句子的语义相似度Trueforinrangelen11# 3. 在相似度下降超过阈值的地方切分0forinrange1len# 语义变化超过阈值且当前 chunk 足够长if1andleneliflenlenelse# 超长了强制切ifreturn# 使用示例Transformer 架构是 2017 年提出的序列建模方法。它完全基于注意力机制不使用循环和卷积。自注意力机制可以捕捉任意两个位置之间的关系。这使得它能够有效处理长距离依赖问题。BERT 是基于 Transformer 的预训练模型。GPT 也是基于 Transformer 的。这两种模型在应用上有显著差异。BERT 使用编码器架构适合理解类任务。GPT 使用解码器架构适合生成类任务。0.6forinenumerateprintf\n--- Chunk {i} ({len(chunk)} 字) ---print100跑一下看看效果——这个例子里Transformer 架构介绍和BERT/GPT 对比两个主题会在语义变化点自动切分开。优点尊重语义边界——chunk 内话题一致自适应——不需要预设 chunk_size 参数召回质量通常比固定长度高 10-20%缺点需要额外的 embedding 调用来判断切分点阈值需要针对你的文档类型调优0.5-0.75 常见范围处理短文本时容易切出过多小 chunk什么时候用文档结构松散、话题变化频繁的场景如论文、新闻、技术文档。语义分块在这些场景下碾压固定长度。策略四Agent 分块LLM-based Chunking一句话让 LLM 决定怎么切效果最好但最贵。原理既然 LLM 能理解文档内容为什么不直接让 LLM 来切分给 LLM 一个 prompt告诉它「把这份文档切成语义完整的段落」它会在真正的内容边界上切分。fromimportdefagent_chunktext: str, model: str gpt-4o-miniliststr 用 LLM 进行智能分块。 f你是一个文档分块专家。请分析以下文档将其切分为语义完整的段落。 切分规则1. 每个 chunk 应该是一个自包含的语义单元2. 不要切分表格、代码块、公式3. 如果某一段特别长20句可以在逻辑转折点切开4. 每个 chunk 保持 300-1500 字之间5. 保留标题层级输出格式每个 chunk 用 ---CHUNK_BOUNDARY--- 分隔文档内容{text}roleusercontent0.1# 低温度保持一致性0---CHUNK_BOUNDARY---returnforinif进阶结构化分块更常见的 Agent chunking 用法是结构化方式——不是让 LLM 切分而是根据文档的结构标记来确定分块边界fromimportdefmarkdown_semantic_chunkmarkdown_text: str 基于 Markdown 结构的分块保留标题层级和上下文。 #H1##H2###H3False# 每个 doc 保留了标题上下文metadataforin3printf标题路径: {doc.metadata}printf内容前100字: {doc.page_content[:100]}print---return如果你要处理 HTML、LaTeX、代码文档结构化分块是最好的——它完全保留文档原来的逻辑结构。优点分块质量最高——LLM 理解文档语义后切分可定制——可以加业务规则“不要分拆合同条款”结构化输出——可以附带元信息标题、标签缺点慢——每个文档要一次 LLM 调用贵——大规模文档处理成本高不一致——相同输入可能得到不同切分结果什么时候用高质量要求的小规模数据 1 万条文档、法律/医疗等对语义完整性要求严格的场景。策略五按文件类型特异化分块不同的文件类型最好的 chunk 方式完全不同代码文档fromimportfromimport# Python 代码分块按函数/类切分1000100# Markdown 分块按标题切分50050PDF / 论文# 论文建议按章节标题 段落分块# 不要按页切PDF 页数和逻辑段落没有关系# 用 PyMuPDF 解析后每个段落作为基本单元import# PyMuPDFopenpaper.pdfforin# 提取文本块不是逐行blocksforin4\n# 然后用递归分块或语义分块处理表格 / CSV# 表格数据每条记录作为一个 chunkimportasproducts.csvforin# 把一行数据格式化成自然语言描述f产品名: {row[name]}价格: {row[price]}类别: {row[category]}终极对比表维度固定长度递归分块语义分块Agent 分块结构化分块实现难度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐速度快快中慢快成本免费免费低1次embedding高LLM调用免费语义完整性差中好最好好依赖结构自适应❌部分✅✅✅表格/代码支持差差中好好适用场景原型默认选择松散文档高质量要求结构化文档实战分块 检索的完整评估流程理论讲完了来点实际的。没有评测的选择都是瞎选。这里给一个可运行的评估脚本fromimportfromimportimportasfromimportListDictdefevaluate_chunk_strategy documents: Dict[str, str], test_queries: List[tuple], chunk_size: int 500, chunk_overlap: int 50, embedding_model: str BAAI/bge-small-zh-v1.5, top_k: int 5float 评估不同 chunk 参数的 RecallK。 test_queries: [(query_text, [relevant_doc_ids])] \n\n\n。# 生成所有 chunk# 记录每个 chunk 来自哪个文档forinlenifnotreturn0.0# 编码所有 chunkTrue0forinTrue1setforinifset1returnlen# 使用示例doc_1Transformer 架构完全基于注意力机制...doc_2Pgvector 是 PostgreSQL 的向量检索扩展...注意力机制和 RNN 有什么关系doc_1PostgreSQL 怎么做向量检索doc_2forin3005008001000int0.1printfchunk_size{size}, overlap10% → Recall5: {recall:.3f}最佳实践从你的真实数据中抽 50-100 条 query 对应 ground truth 文档用上面的脚本自动跑 chunk_size 200/300/500/800/1000 五组选 recall 曲线的拐点——一般是 recall 不再明显增长的 chunk_size最后在这个 chunk_size 附近微调 overlap 比例5%/10%/15%/20%写在最后我见过的 RAG 项目踩的最大的坑就是在 chunk 策略上花的时间 1 小时。很多人花一周选 embedding 模型花三天选向量数据库然后 chunk 策略用了一个默认参数就上线了。这是倒过来的。在 RAG 系统的优化优先级里chunk 策略的影响力 embedding 模型 向量数据库。道理很简单——chunk 决定了你喂给检索系统的基本单元是什么。如果这个基本单元本身就切错了后面的每一步都在放大这个错误。几个经验送给你从递归分块开始——chunk_size500, overlap50跑起来再说一定要做 recall 评测——用你的真实数据不要凭感觉不同文件类型用不同策略——代码用函数边界切论文用段落切Markdown 用标题结构切chunk_size 和 embedding 维度要匹配——维度高的模型可以用更大 chunk信息更多维度低的模型 chunk 小一点最后一句大实话先随便切跑通全流程再去优化 chunk。有 benchmark 数据的优化才是真优化没有 benchmark 的优化叫调参娱乐。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】