尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

RAG 切分策略选型:fixed / structural / semantic 的原理与适用边界

RAG 切分策略选型:fixed / structural / semantic 的原理与适用边界 切分chunking是 RAG 检索的地基。固定长度、按结构、按语义–三种主流策略没有绝对优劣只有适合什么文档的差别。本文从原理出发讲清每种策略的机制、优势、局限和适用场景并给出选型决策框架。一、chunking 在 RAG 链路里的位置RAG 的链路是摄入 - 索引 - 检索 - 生成。切分发生在摄入阶段但它的影响会一路传导到最终答案切得太碎一个语义单元被切成两半检索命中了半句话生成时缺上下文。切得太长一个 chunk 包含多个话题召回后噪声多还浪费 token 预算。切得不对把表格/定义拦腰切断或把代码块拆散语义直接损坏。切分策略一旦定下来后续索引、检索、评估都建立在它之上。这就是为什么 chunking 通常在项目早期就定好、后期很少动–改切的代价极大要重建索引、重生成评估集、重跑所有实验。所以选对切分策略比后续调检索参数更值得投入。三种主流策略的切分依据各不相同策略切分依据核心问题fixed固定字符窗口不感知语义边界structural文档章节标题层级依赖文档有结构semantic相邻句向量的相似度突降不依赖结构但慢且不可解释下面分别讲清每种策略的原理、优势、局限和适用场景。二、fixed固定长度切分原理用RecursiveCharacterTextSplitter按chunk_size如 512 字chunk_overlap如 50 字切按分隔符优先级段落 换行 句号 空格尽量在自然边界切但不保证语义完整。self.splitterRecursiveCharacterTextSplitter(chunk_sizesettings.chunking.chunk_size,# 512chunk_overlapsettings.chunking.chunk_overlap,# 50)优势行为可预期chunk 长度落在[chunk_size-overlap, chunk_size]区间token 预算好控制。实现简单、ingest 快不依赖文档结构不调用 embedding 模型切分本身几乎零成本。适合作为基线任何新策略都该和 fixed 对比证明改进的必要性。局限会拦腰切断语义单元表格、定义、代码块可能被切到两个 chunk 里两边都不完整。无章节上下文chunk 的heading_path为空丢失了这段话属于哪个章节的信息生成时少了上下文锚点。适用场景纯文本、无显式结构的文档日志、对话记录、纯散文快速搭建原型、需要一条基线对比的场景对切分质量要求不高、优先保证 ingest 速度的场景三、structural按文档结构切分原理利用文档本身的章节层级让一个 chunk 一个标题下的完整语义单元。不同文档类型用不同方式识别标题Markdown按#的数量定层级构建heading_path树DOCX按paragraph.style的 Heading 1~6 层级PDF按 span 字号识别字号 ≥ 中位数 ×1.1 且短行视为标题TXT按连续空行分段长段落用 fixed 兜底再切标题层级用截断-追加策略保持层级树# 遇到 level 级标题截断到当前层级再追加保持层级树iflevel0:heading_pathheading_path[:level-1][text]长段落超过chunk_size仍用RecursiveCharacterTextSplitter兜底再切避免单 chunk 过大。优势不切断语义单元表格、定义、代码块完整保留在一个 chunk 里。自带章节上下文heading_path如第三章 3.2 配置说明让检索结果带上下文锚点生成时能引用这段话出自哪一节。ingest 快只解析文档结构不调用 embedding 模型。局限依赖文档有清晰结构对没有标题的纯文本退化为按段落切优势消失。兜底再切会抹平优势长段落仍用 fixed 逻辑再切这部分行为和 fixed 一样。文档的长段落越多structural 相对 fixed 的优势越小。标题层级太碎时 chunk 过小标题层级很深每小节就几句话会切出大量小 chunk语义不完整还增加索引噪声。PDF 标题识别靠字号启发式字号阈值中位数 ×1.1对排版不规范的 PDF 会误判把正文当标题或漏识别标题。适用场景有清晰章节结构的技术文档、制度文档、说明书表格、定义、代码块密集的文档需要保留这段话属于哪一节上下文的场景四、semantic按语义切分原理相邻句向量的余弦相似度低于分位阈值处断开。句子在 embedding 空间里相似度突降往往意味着话题切换在切换点断开能让一个 chunk 的话题更聚焦。# 相邻句余弦相似度向量归一化后点积即余弦sims(vecs_n[:-1]*vecs_n[1:]).sum(axis1)thresholdfloat(np.percentile(sims,self.percentile))# 25 分位# 在相似度 threshold 处断开否则继续累积chunk 大小自适应min_size chunk_size // 2max_size chunk_size * 2话题长的段落切大些短的切小些。优势不依赖文档结构适合没有标题、但话题会切换的长文FAQ、对话记录、长篇散文。切分点更懂语义在话题切换处断开比 fixed 的硬切更能保持话题聚焦。chunk 大小自适应不像 fixed 那样机械等长。局限1. ingest 慢。每个句子都要编码切分阶段就要跑一遍 embedding。相比 structural/fixed 几乎零成本的切分semantic 的切分本身就要几分钟到十几分钟。这是它最大的工程代价。2. 切分结果不可解释。没有heading_pathchunk 不知道自己属于哪个章节生成时少了上下文锚点。3. 对超长无标点段落代码块处理失效。句子切分按标点。\n.!?断句但代码块...内没有标点整段被当作一个句子。单句超过max_size时会被整个 emit 成一个 chunk产生超大 chunk。这是 semantic chunker 的实现缺陷–遇到代码块密集的文档它不可用。4. 长 chunk 导致 embedding 内存爆炸。semantic 的max_size是 fixed 的 2 倍一次性编码多个长 chunk 会 OOM。本质是bge-m3 的 attention 内存随 batch 和 seq_len 增长长文本必须分批编码。适用场景无显式结构但话题会切换的长文FAQ、客服对话、长篇评论不适合代码块密集的技术文档会切出超大 chunk对 ingest 速度不敏感、愿意为切分质量付出计算代价的场景五、评估切分质量的方法论陷阱比较切分策略时有一个隐蔽的陷阱评估集与 chunking 策略耦合。常见的评估流程是让 LLM 基于切出的 chunk 生成 QA 对把evidence_chunk_ids绑定为该 chunk 的 IDrecords.append({evidence_chunk_ids:[chunk.chunk_id],# 绑定该策略切出的 chunk_id})问题在于每种策略各自生成评估集三套评估集非同源问题完全不同。semantic 切出的大 chunk 包含更多信息基于它生成的问题更宽泛、更容易在该 chunk 集里命中。三组数字根本不是在同一把尺子上量出来的不可直接横比。这会导致一个反直觉现象切出更大 chunk 的策略如 semantic评估数字反而更高但这不是策略更优而是评估集偏向了它的粒度。唯一严谨的横向对比用一套人工问题集三套索引都评估同一批问题并手动标注每个问题在各索引下的证据 chunk_id。工作量极大但这是唯一能公平对比的方式。另一个评估细节若评估集每条问题只有 1 个证据 chunk|relevant|1则 RecallK 与 HitRateK 数值恒等命中即 1不命中即 0只有 MRR 对排序位置敏感。此时对比排序质量重点看 MRR。六、选型决策框架根据上面的优势/局限给出选型决策文档有清晰章节结构标题/字号可识别 ├─ 是 - structural保留语义单元 heading_path 上下文 │ └─ 文档大量长段落- 注意兜底再切会抹平优势优势有限 └─ 否 - 文档里有代码块/无标点长段落 ├─ 是 - fixedsemantic 会切出超大 chunk └─ 否 - 文档话题会切换、对 ingest 速度不敏感 ├─ 是 - semantic按话题切换断开 └─ 否 - fixed简单可靠的基线补充约束ingest 速度敏感排除 semantic切分阶段要编码每个句子慢 10 倍代码块密集排除 semantic超大 chunk 缺陷需要这段话属于哪一节上下文排除 fixed 和 semantic都无heading_path项目早期不确定先上 fixed 作基线有评估集后再试 structural用数据决定七、要点总结没有最优切分只有适合场景。三种策略各有明确的适用边界脱离文档类型谈优劣会得出错误结论。fixed适合无结构纯文本、快速基线。优势是简单快、行为可预期局限是会切断语义单元、无章节上下文。structural适合有章节的技术/制度文档。优势是不切断语义单元 heading_path 上下文局限是依赖文档有结构、兜底再切抹平优势、标题太碎时 chunk 过小。semantic适合无结构但话题切换的长文。优势是切分点懂语义、大小自适应局限是 ingest 慢、无 heading_path、代码块会切出超大 chunk、长 chunk 导致 embedding OOM。评估集与 chunking 策略耦合是切分消融最隐蔽的陷阱。每种策略各自生成评估集三组数字不可直接横比。唯一严谨的对比是用一套人工问题集三套索引都评估。全部单证据时 RecallK HitRateK只有 MRR 对排序敏感。embedding 长文本必须分批编码bge-m3 attention 内存随 batch 和 seq_len 增长长 chunk 一次性编码会 OOM。chunking 消融成本远高于 retrieval 消融每次改切分都要重建索引 重生成评估集。这是工程上 chunking 要早定的根本原因。
返回列表