Ch13 RAG修订于 二〇二六年七月一日

分块策略(深挖)

这篇是进阶内容,涉及搜索系统的技术细节。如果你刚接触 AI,先读 第13章 · RAG 进化树 了解基本概念。

检索增强生成(RAG)需要把长文档切成小块。切法不对,检索全废。这篇深入四种分块策略的优劣和选型。

为什么分块重要

不分块会怎样?把一整本 300 页的书一次塞给 Embedding 模型——整本书变成一个向量。你搜”第三章的内容”,系统不知道该匹配书的哪一页。整本书的向量太”稀”了——信息被平均化了。

分块的目的是:把长文档切成一段段独立的”知识点”。 每段有自己的向量,检索时可以精确命中。

切得太粗:一段包含多个不同主题,检索不精确。切得太细:一段只包含半句话,丢失上下文。

策略一:固定长度分块

最简单的方式——按字符数或 token 数切。

text = "很长的文档..."
chunk_size = 500  # 每段 500 个字符
overlap = 50      # 段与段之间重叠 50 个字符

overlap 很关键。如果完全无重叠,一句话可能被切在两段的边界上——“张三的老板”在一段的末尾,“是李四”在下一段的开头。检索时两段都搜不到完整的”张三的老板是李四”。有 overlap 可以缓解这个问题。

优点:简单、快。缺点:切的位置可能正好在句子中间,破坏语义完整性。

建议 overlap:chunk_size 的 10%-20%。500 字符的 chunk,overlap 50-100 字符。

策略二:语义分块

不按固定长度切,按语义边界切——在段落结束、话题转换的地方下刀。

工具:LangChain 的 RecursiveCharacterTextSplitter + 分隔符优先级:

["\n\n", "\n", "。", "!", "?", " ", ""]

先尝试在段落分隔符(\n\n)处切。如果切成的一段还是太长,再用句号(。)切。再长就用空格切。最后的兜底方案是强制按字符数切。

优点:保持语义完整性。缺点:段落长度不均匀——有的段落 50 字,有的 2000 字。对向量存储不友好(向量库喜欢等长的向量)。

策略三:Late Chunking

前面两种都是在 Embedding 之前分块——先切,再向量化。Late Chunking 反过来:先向量化整篇文档,再切。

Jina AI 2024 年提出 1。原理:

  1. 整篇文档输入长上下文 Embedding 模型(如 jina-embeddings-v3,支持 8192 tokens)
  2. 模型输出每个 token 的向量,而不是整篇文档的一个向量
  3. 然后按语义边界切——第一段对应 token 1-100 的向量,第二段对应 token 101-200 的向量
  4. 每段用其对应 token 的向量做池化(pooling),得到段向量

优点:避免了分块→Embedding 的信息丢失。模型在编码时看到了完整的上下文。段向量更准确。

代价:需要长上下文 Embedding 模型。传统模型(如 text-embedding-ada-002)最大 8191 tokens,长文档放不下。

策略四:Agentic Chunking

2025-2026 年新趋势——让 AI 自己决定怎么切。

Agent:
  Thought: 这篇文档包含三个独立主题:法律条款、赔偿标准、生效日期
  Action: 在第 15 段和第 28 段处下刀
  Output: "已切成 3 个 chunk"

优点:最智能——AI 理解文档结构,知道哪里是话题边界。缺点:贵——每次切文档都要调用 LLM。只适合重要文档,不适合批量处理。

最优实践:分块大小怎么定

没有标准答案。取决于你的场景:

场景chunk_sizeoverlap策略
一般 FAQ256-512 tokens50-100语义分块
长文档问答512-1024 tokens100-200Late Chunking
代码搜索整个函数(不计长度)无语义分块(按函数边界)
法律/合同500-800 tokens50-100Agentic Chunking
多语言混合512 tokens100固定长度(不同语言语义边界不一致)

2026 年默认推荐:语义分块,512 tokens 一段,overlap 100 tokens。不够好再换成 Late Chunking。

分块之后的坑

相同内容出现在多个 chunk(因为 overlap)。检索时同一个文档的不同 chunk 可能都被召回,AI 会看到重复信息。解决:检索后去重——同一个文档的多个 chunk,只保留最相关的那个。

chunk 之间缺少全局上下文。每个 chunk 不知道自己在整篇文档中的位置。解决:给每个 chunk 加上”元数据”——[文档标题] [第 N 段/总共 M 段] [前一段摘要]。

相关笔记

来源

注释

  1. Jina AI, “Late Chunking”, 2024, https://jina.ai/news/late-chunking-in-long-context-embedding-models/ ↩

关联5

知识图谱

局部图谱 · 点节点跳转