【AI】RAG 数据分块(Chunk)策略与实践

👨‍💻程序员三明治个人主页
🔥 个人专栏 : 《设计模式精解》 《重学数据结构》
《AI探索日志》 《从0带你学深度强化学习》

🤞先做到 再看见!


目录

    • 为什么不能把整份知识库直接交给大模型?
      • [1. 上下文窗口限制](#1. 上下文窗口限制)
      • [2. 检索精度问题:信息越多,噪声也越多](#2. 检索精度问题:信息越多,噪声也越多)
    • 分块到底在做什么?
      • [1. 分块在 RAG 流程中的位置](#1. 分块在 RAG 流程中的位置)
      • [2. 两个关键参数:chunk_size 与 overlap](#2. 两个关键参数:chunk_size 与 overlap)
        • [2.1 如何理解 chunk_size?](#2.1 如何理解 chunk_size?)
        • [2.2 overlap 是什么,为什么需要它?](#2.2 overlap 是什么,为什么需要它?)
        • [2.3 用字符还是 token 作为单位?](#2.3 用字符还是 token 作为单位?)
    • 主流分块策略详解
    • [1. 固定大小分块(Fixed Size Chunking)](#1. 固定大小分块(Fixed Size Chunking))
      • [1.1 原理](#1.1 原理)
      • [1.2 Java 代码实现](#1.2 Java 代码实现)
      • [1.3 优缺点](#1.3 优缺点)
    • [2. 重叠分块(Overlapping Chunking)](#2. 重叠分块(Overlapping Chunking))
      • [2.1 原理](#2.1 原理)
      • [2.2 Java 代码实现](#2.2 Java 代码实现)
      • [2.3 优缺点](#2.3 优缺点)
    • [3. 递归分块(Recursive Chunking)](#3. 递归分块(Recursive Chunking))
      • [3.1 原理](#3.1 原理)
      • [3.2 优缺点](#3.2 优缺点)
    • [4. 语义分块(Semantic Chunking)](#4. 语义分块(Semantic Chunking))
      • [4.1 原理](#4.1 原理)
      • [4.2 Embedding 语义分块与 LLM 辅助分块对比](#4.2 Embedding 语义分块与 LLM 辅助分块对比)
      • [4.3 优缺点](#4.3 优缺点)
    • [5. 混合分块(Hybrid Chunking)](#5. 混合分块(Hybrid Chunking))
    • 使用可视化工具对比分块效果
      • [CharacterTextSplitter 示例观察](#CharacterTextSplitter 示例观察)
      • [RecursiveCharacterTextSplitter 示例观察](#RecursiveCharacterTextSplitter 示例观察)
    • 分块策略怎么选?
      • [1. 不同文档类型的推荐策略](#1. 不同文档类型的推荐策略)
      • [2. chunk_size 与 overlap 的经验参考](#2. chunk_size 与 overlap 的经验参考)
    • 企业级实践中的注意事项
    • 文末总结

本文面向正在建设 RAG 知识库问答系统的开发者,围绕"为什么需要分块、如何设置 chunk_size 与 overlap、常见分块策略如何选择"展开说明。示例场景统一替换为在线教育平台的课程预约与教务服务知识库;技术链路、参数权衡和性能优化思路保持不变。

为什么不能把整份知识库直接交给大模型?

假设一个在线教育平台正在建设智能教务助手。平台内部有一份 200 页左右的《课程服务知识库》,内容覆盖课程预约规则、调课与取消政策、课时权益、班主任服务、直播课说明、发票与售后流程等。学员提出"预约的课程开课前多久可以取消?"这类问题时,系统需要从知识库中定位相关条款,并生成准确回答。

最直接的做法似乎是:把整份知识库文本一次性放进大模型上下文,然后让模型回答。

这个思路在小规模示例中看起来可行,但在真实系统中通常会遇到两个核心问题。

1. 上下文窗口限制

大模型处理文本时存在上下文窗口限制。可以把它理解为模型一次能够"看到"的工作区大小:输入文本、检索内容、系统提示词、用户问题和模型输出都会占用这个窗口。

以当前主流模型为例,上下文窗口通常从 128k token 到 1M token 不等。token 可以粗略理解为模型处理文本时的基本单位,中文场景下常常接近一个汉字或一个词片段。128k token 听起来很多,但一份 200 页的课程服务知识库,纯文本量很容易超过几十万字。如果还包含表格、FAQ、政策说明和历史版本内容,直接塞入模型不仅可能超出长度限制,也会带来显著的成本和延迟。

因此,直接输入整篇文档的后果通常包括:

  • 文本无法完整输入,触发长度限制或被截断;
  • 单次请求成本明显增加;
  • 响应延迟变长;
  • 并发吞吐能力下降。

即使未来模型上下文窗口继续扩大,这个问题也不会完全消失。上下文越长,模型需要处理的信息越多,实际业务系统仍然要在成本、延迟、稳定性和回答质量之间做取舍。

2. 检索精度问题:信息越多,噪声也越多

即便假设模型拥有足够大的上下文窗口,直接提供整份知识库仍然会带来检索精度问题。

例如,学员问:"体验课结束后还能改约正式课吗?"如果系统把几十万字的课程规则、合同条款、教师排班、售后流程都交给模型,模型需要在大量信息中找出最相关的几段。上下文越长,噪声越多,模型越容易把不相关条款混入回答,或者忽略真正关键的限制条件。

这也是 RAG 架构仍然重要的原因。RAG 的核心做法不是把所有文本直接交给模型,而是先检索出与问题最相关的几个文本片段,再把这些片段作为上下文提供给模型。这样模型拿到的是更干净、更聚焦的证据,回答质量和稳定性都会更好。

但要做检索,首先需要把文档拆成可以被检索的单元。整份知识库作为一个检索单元粒度过粗,既不利于召回,也不利于排序。系统需要把长文本切成若干相对完整的小段,每个小段围绕一个知识点或业务规则展开。

这就是分块(Chunking)的作用。

分块到底在做什么?

1. 分块在 RAG 流程中的位置

在数据准备阶段,通常会先使用 Apache Tika 等工具从 PDF、Word、HTML 等文件中提取纯文本。但纯文本还不能直接进入向量数据库,原因是文本太长、结构复杂,而且不同段落之间的语义边界不一定清晰。

一个典型的数据准备流程如下:

latex 复制代码
原始文档
  ↓
文本抽取(如 Apache Tika)
  ↓
文本清洗与结构修复
  ↓
分块(Chunking)
  ↓
向量化(Embedding)
  ↓
写入向量数据库
  ↓
检索增强生成(RAG)

分块之后,下一步通常是向量化。系统会把每个文本块转换为向量,后续根据用户问题与文本块向量之间的相似度进行检索。

因此,分块质量会直接影响检索质量。块切得合理,检索结果通常更聚焦;块切得过大,会引入噪声;块切得过小,又可能丢失上下文。分块一旦质量较差,后续即使调整向量模型、召回数量或重排策略,也很难完全弥补。

2. 两个关键参数:chunk_size 与 overlap

在设计分块策略之前,需要先理解两个核心参数:

  • chunk_size:每个文本块的长度上限;
  • overlap:相邻两个文本块之间保留的重叠长度。

为了完成命名风格脱敏,下文代码示例将原本常见的 camelCase 写法改为 snake_case,例如 chunkSize 改为 chunk_size。虽然 Java 社区通常使用 camelCase,但这里的命名调整不影响示例逻辑。

2.1 如何理解 chunk_size?

chunk_size 表示每个块的最大长度。比如设置 chunk_size = 200,意味着每个块最多包含 200 个字符,或者最多包含 200 个 token,具体取决于系统采用的计量单位。

chunk_size 没有固定标准,但需要理解它背后的权衡:

设置情况 影响
块太大,例如 2000 字 单个块包含更多信息,但检索结果容易混入不相关内容,精度下降。例如学员只问"开课前多久能取消预约",结果召回整章"预约、调课、退款、发票"说明,模型还要再次从中筛选。
块太小,例如 50 字 单个块更精准,但容易把完整规则切断。例如"开课前 24 小时可免费取消"被拆成两段,单独看任何一段都不完整。

在许多中文知识库问答场景中,chunk_size 可以先从 200 到 1000 个字符之间试起。课程预约、退课规则、FAQ 这类问答型知识,通常适合偏小的块;课程体系介绍、长篇说明、教学方案摘要等场景,则可以适当增大块大小。

2.2 overlap 是什么,为什么需要它?

overlap 指相邻两个块共享的文本长度。它的作用是缓解边界切割带来的语义断裂。

例如,课程服务知识库中有如下规则:

latex 复制代码
直播课程开课前 24 小时以上,学员可以在学习中心自助取消预约,系统会自动返还对应课时。开课前 24 小时以内取消,需联系班主任人工处理;如教师已完成课前准备,该课时可能不予返还,具体以课程协议为准。

如果 chunk_size = 40 且不设置 overlap,可能切成:

latex 复制代码
块 1:直播课程开课前 24 小时以上,学员可以在学习中心自助取消
块 2:预约,系统会自动返还对应课时。开课前 24 小时以内取消,需联系
块 3:班主任人工处理;如教师已完成课前准备,该课时可能不予返还
块 4:,具体以课程协议为准。

此时,"取消预约""返还课时"等关键含义被切散。用户搜索"开课前多久取消预约可以返还课时"时,任何一个块都可能不够完整。

如果设置 overlap = 15,相邻块之间保留一部分重复内容,切分效果会更好:

latex 复制代码
块 1:直播课程开课前 24 小时以上,学员可以在学习中心自助取消
块 2:心自助取消预约,系统会自动返还对应课时。开课前 24 小时以内
块 3:前 24 小时以内取消,需联系班主任人工处理;如教师已完成
块 4:师已完成课前准备,该课时可能不予返还,具体以课程协议为准。

通过重叠,边界处的关键信息更容易在某个块中完整出现。

overlap 并不是越大越好。重叠越大,重复文本越多,向量化成本、存储成本和检索计算成本都会增加。常见经验是将 overlap 设置为 chunk_size 的 10% 到 25%。

2.3 用字符还是 token 作为单位?

chunk_size 可以按字符计算,也可以按 token 计算。两者并不等价。

字符是人眼看到的符号数量。例如,"预约课程"是 4 个字符,Hello World 是 11 个字符,包括空格。

token 是模型处理文本时的基本单位。英文中,一个常见单词通常接近 1 个 token,较长单词可能拆成多个 token;中文中,一个汉字可能对应 1 个或多个 token,具体取决于模型的分词器。

文本 字符数 大约 token 数
取消课程预约 6 6 ~ 10
Hello World 11 2
课时返还规则 6 6 ~ 10

大模型的上下文窗口按 token 计算,因此基于字符的 chunk_size 只是近似控制。对于入门阶段或简单系统,按字符分块通常足够;当系统对成本、上下文长度和多语言兼容性要求更高时,更推荐使用基于 token 的分块方式。

主流分块策略详解

下面使用同一段在线教育课程服务知识库示例,说明几类常见分块策略。

latex 复制代码
一、课程预约规则
学员可在学习中心预约直播课程。普通课程最早可提前 14 天预约,最晚需在开课前 2 小时完成预约。热门班课名额有限,系统会按照预约时间顺序锁定席位。预约成功后,学员会收到短信、站内信和学习中心提醒。

二、取消与改约规则
直播课程开课前 24 小时以上,学员可以自助取消预约,系统会自动返还对应课时。开课前 24 小时以内取消,需联系班主任人工处理;如教师已完成课前准备,该课时可能不予返还。因平台故障或教师原因导致课程无法正常进行的,课时将原路返还。

三、学员权益
基础学员每月可预约 4 次答疑课。进阶学员每月可预约 8 次答疑课,并享受作业优先批改服务。尊享学员每月可预约 12 次答疑课,享受专属学习顾问、阶段测评报告和学习路径调整建议。

四、上课通知与直播安排
课程默认使用平台直播教室。开课前 30 分钟,系统会自动生成直播入口,并通过站内信和短信提醒学员。若课程需要使用第三方会议工具,班主任会在开课前至少 2 小时发送会议链接和注意事项。

五、教务支持与发票服务
学员可在学习中心提交教务工单,咨询课程安排、课时记录、发票开具和学习资料下载等问题。工作日 9:00 至 21:00 提交的工单通常会在 4 小时内处理;非工作时间提交的工单会在下一个工作日优先处理。

这段文本包含 5 个相对独立的章节,每个章节对应一个业务规则。下面对不同分块策略进行说明。

1. 固定大小分块(Fixed Size Chunking)

1.1 原理

固定大小分块是最直接的方式:不理解文本结构,也不识别段落或句子边界,只按固定字符数切割。

假设 chunk_size = 100overlap = 0,系统会这样切:

latex 复制代码
块 1:从第 1 个字符开始,取 100 个字符
块 2:从第 101 个字符开始,再取 100 个字符
块 3:从第 201 个字符开始,再取 100 个字符
......

这种方式实现简单、性能稳定,但容易把一句话、一个条款甚至一个关键词从中间切断。对于课程预约知识库这类有明确章节和规则边界的文本,固定大小分块通常只能作为兜底方案。

1.2 Java 代码实现

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class fixed_size_chunker {

    /**
     * 固定大小分块:按字符数量进行硬切分。
     */
    public static List<String> split_text(String source_text, int chunk_size) {
        List<String> chunk_list = new ArrayList<>();
        int start_index = 0;

        while (start_index < source_text.length()) {
            int end_index = Math.min(start_index + chunk_size, source_text.length());
            chunk_list.add(source_text.substring(start_index, end_index));
            start_index = end_index;
        }

        return chunk_list;
    }

    public static void main(String[] arguments) {
        String source_text = "直播课程开课前 24 小时以上,学员可以在学习中心自助取消预约,"
                + "系统会自动返还对应课时。开课前 24 小时以内取消,需联系班主任人工处理;"
                + "如教师已完成课前准备,该课时可能不予返还,具体以课程协议为准。";

        List<String> chunk_list = split_text(source_text, 40);

        for (int index = 0; index < chunk_list.size(); index++) {
            System.out.println("=== 块 " + (index + 1) + " ===");
            System.out.println(chunk_list.get(index));
            System.out.println();
        }
    }
}

这段代码会严格按照 40 个字符切分。切割位置不考虑句子边界,因此部分块的开头或结尾可能读起来不完整。

1.3 优缺点

维度 说明
优点 实现简单,性能好,不依赖 NLP 处理或额外模型。
缺点 完全忽略文本结构,容易切断句子、段落和规则条件,导致语义不完整。
适合 日志、纯数据文本、格式混乱但无需精细语义边界的内容;也可作为其他策略失败时的兜底方案。
不适合 课程规则、协议条款、操作手册、FAQ 等结构清晰且语义边界重要的知识库。

2. 重叠分块(Overlapping Chunking)

2.1 原理

重叠分块是在固定大小分块基础上的改进。核心思想是:相邻块之间保留一段重复文本,降低边界切割造成的信息丢失。

假设 chunk_size = 100overlap = 25

latex 复制代码
块 1:从第 1 个字符开始,取 100 个字符
块 2:从第 76 个字符开始,取 100 个字符
块 3:从第 151 个字符开始,取 100 个字符
......

每次向前移动的步长不是 100,而是 chunk_size - overlap,也就是 75。这样相邻块之间会共享 25 个字符。

与固定大小分块相比,重叠分块仍然不理解语义,但可以显著缓解边界断裂问题。

2.2 Java 代码实现

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class overlapping_chunker {

    /**
     * 重叠分块:在固定大小分块基础上,为相邻块保留重叠区域。
     */
    public static List<String> split_text(String source_text, int chunk_size, int overlap) {
        if (overlap >= chunk_size) {
            throw new IllegalArgumentException("overlap 必须小于 chunk_size");
        }

        List<String> chunk_list = new ArrayList<>();
        int step_size = chunk_size - overlap;
        int start_index = 0;

        while (start_index < source_text.length()) {
            int end_index = Math.min(start_index + chunk_size, source_text.length());
            chunk_list.add(source_text.substring(start_index, end_index));
            start_index += step_size;
        }

        return chunk_list;
    }

    public static void main(String[] arguments) {
        String source_text = "直播课程开课前 24 小时以上,学员可以在学习中心自助取消预约,"
                + "系统会自动返还对应课时。开课前 24 小时以内取消,需联系班主任人工处理;"
                + "如教师已完成课前准备,该课时可能不予返还,具体以课程协议为准。";

        List<String> chunk_list = split_text(source_text, 40, 10);

        for (int index = 0; index < chunk_list.size(); index++) {
            System.out.println("=== 块 " + (index + 1) + " ===");
            System.out.println(chunk_list.get(index));
            System.out.println();
        }
    }
}

这段代码的关键是 start_index += step_size。当 step_size = chunk_size - overlap 时,下一块会从上一块结束位置之前开始,从而形成重叠。

2.3 优缺点

维度 说明
优点 实现简单,能够有效缓解边界处的语义断裂。
缺点 仍然不识别文本结构;重叠区域会带来重复存储和额外向量化成本。
适合 通用知识库的入门方案,尤其适合结构不稳定、段落边界不可靠的文本。
不适合 对条款完整性要求极高的内容,例如课程合同、合规声明或收费协议。

3. 递归分块(Recursive Chunking)

3.1 原理

递归分块是实际 RAG 项目中非常常用的策略。它的核心思想是:先尝试使用更大的语义边界切分,如果切出来的块仍然超过 chunk_size,再使用更细的边界继续切分。

常见的分隔符优先级如下:

latex 复制代码
["\n\n", "\n", "。", ",", " ", ""]

切分过程可以概括为:

latex 复制代码
先按空行切分章节
  ↓
章节仍然过长,则按换行切
  ↓
片段仍然过长,则按句号切
  ↓
句子仍然过长,则按逗号或空格切
  ↓
最后才按字符兜底切分

这种方式的优势在于,它尽量尊重文档结构。能按章节切,就不按句子切;能按句子切,就不按字符硬切。

以课程预约知识库为例,如果 chunk_size = 200,递归分块通常会先按章节之间的空行切分。"取消与改约规则"这一节如果没有超过 200 字,就会作为一个完整块保留;如果超过上限,再继续按句号拆分。

3.2 优缺点

维度 说明
优点 兼顾语义完整性和块大小控制,是多数文本型 RAG 系统的稳妥默认选择。
缺点 依赖文本中存在合理分隔符;分隔符列表需要根据语言和文档格式调整。
适合 课程知识库、操作手册、帮助中心、教学说明、政策类文档等结构清晰的文本。
不适合 代码文件、复杂表格、扫描 OCR 结果、条款跨页严重的 PDF 等需要专门解析的内容。

4. 语义分块(Semantic Chunking)

4.1 原理

固定大小分块、重叠分块和递归分块都属于规则驱动方法。它们主要依赖长度、标点和段落结构,并不真正理解文本内容。

语义分块则使用 Embedding 模型判断文本含义,在语义发生明显变化的位置切分。典型流程如下:

latex 复制代码
1. 将长文本切成句子或短段
2. 为每个句子生成 Embedding 向量
3. 计算相邻句子之间的向量相似度
4. 当相似度低于阈值时,判断为主题切换点
5. 在主题切换点进行分块

例如,在课程服务知识库中,"取消与改约规则"内部的几句话都围绕课程取消、课时返还和人工处理展开,相邻句子的向量相似度通常较高。当文本从"取消与改约规则"切换到"学员权益"时,话题发生明显变化,相似度会下降,适合作为分块边界。

语义分块的好处是文本块内部主题更加内聚,不容易把多个不相关主题混在一个块里。但它需要额外调用 Embedding 模型,或者使用大模型辅助判断切分位置,因此成本和延迟都更高。

4.2 Embedding 语义分块与 LLM 辅助分块对比

维度 Embedding 语义分块 LLM 辅助分块
原理 计算相邻句子或段落的向量相似度。 让大模型直接理解文本并判断切分位置。
分块质量 依赖 Embedding 模型质量和阈值设置。 通常更能处理复杂语境、隐含主题和跨段关系。
速度 较快,适合批量处理。 较慢,通常以秒级计。
成本 较低。 较高。
适用场景 大批量文档处理、通用知识库优化。 高价值文档、复杂条款、需要人工级别边界判断的内容。

4.3 优缺点

维度 说明
优点 切分依据更接近真实语义,文本块主题内聚性更强,检索精度通常更高。
缺点 需要额外模型调用;阈值需要调参;对模型质量和文本预处理质量有依赖。
适合 合同条款、收费协议、课程服务协议、合规文档、高价值知识库。
不适合 文档量特别大且对处理延迟敏感的场景;或者文本结构已经非常清晰、递归分块足够有效的场景。

5. 混合分块(Hybrid Chunking)

5.1 原理

真实项目中,单一策略往往无法覆盖所有文档。在线教育平台的知识库可能同时包含课程说明、FAQ、直播操作指南、合同条款、发票规则、教师排班说明和客服工单模板。不同内容适合不同切分方式。

混合分块的思路是根据文档类型、文本结构和业务用途选择不同策略,必要时进行后处理。

常见组合方式包括:

方式一:递归分块 + 语义分块

先用递归分块按章节和段落粗切,再对过长或主题复杂的块使用语义分块细切。这样可以兼顾速度和分块质量。

latex 复制代码
长文档
  ↓
按章节/段落递归粗切
  ↓
识别过长或主题复杂的片段
  ↓
使用 Embedding 或 LLM 进行语义细切
  ↓
输出最终 chunk

方式二:按文档类型路由

根据文档类型选择分块器:

文档类型 推荐策略
课程帮助中心 递归分块
FAQ 问答对 按问答对切分
课程服务协议 语义分块
直播故障日志 按行切分或固定大小分块
HTML 帮助页面 先清洗标签,再递归分块
OCR 扫描文本 清洗修复后使用重叠分块或语义分块

方式三:分块后处理

先用基础策略生成初始块,再做一轮质量修正:

  • 合并过短块;
  • 拆分过长块;
  • 为每个块补充元数据,例如课程类型、章节标题、文档来源、版本号、生效日期;
  • 对相邻块做语义检查,避免一个规则被拆散;
  • 对 FAQ 保持问答成对,不让问题和答案分离。

以在线教育平台为例,一个可落地的混合方案可以是:

内容类型 策略
课程预约、取消、改约等规则正文 递归分块,优先按章节和条款切分。
FAQ 问答 每个 Q&A 作为一个块,必要时补充所属课程和适用范围。
课程详情页 提取结构化字段,例如价格、课时、适用年级;描述文本再用重叠分块。
课程协议和退款条款 语义分块或人工复核后的混合分块。
教务工单模板 按模板类型或业务流程节点切分。

5.2 优缺点

维度 说明
优点 灵活度高,可针对不同内容选择最合适的策略,整体检索效果通常最好。
缺点 实现复杂度较高,需要维护多套分块逻辑、路由规则和质量评估机制。
适合 企业级 RAG 系统、多类型知识库、对回答准确率和可解释性要求较高的场景。
不适合 简单 demo、POC 或文档量很小的试验项目。

使用可视化工具对比分块效果

仅靠文字描述不够直观。实践中可以使用 ChunkViz 等可视化工具,观察不同分块策略对同一段文本的切割效果。

推荐做几组对比实验:

实验 策略 chunk_size overlap 观察重点
实验 1 CharacterTextSplitter 100 0 观察边界是否频繁切在句子中间。
实验 2 CharacterTextSplitter 100 20 观察重叠区域是否缓解边界断裂。
实验 3 RecursiveCharacterTextSplitter 100 0 对比固定大小分块,观察递归策略是否更倾向于在段落或句子边界切分。
实验 4 RecursiveCharacterTextSplitter 200 0 增大块大小,观察块数量和语义完整性的变化。

在课程规则类文本中,通常可以观察到:

  • 固定大小分块容易切断规则条件;
  • 加入 overlap 后,边界信息更容易被保留;
  • 递归分块更倾向于保留章节或句子完整性;
  • chunk_size 过大时,召回内容可能包含多个主题;
  • chunk_size 过小时,规则上下文可能不完整。

CharacterTextSplitter 示例观察

配置如下:

latex 复制代码
Chunk Size: 100
Chunk Overlap: 20

这种配置可以缓解部分边界问题,但仍然不理解课程规则本身。如果一个取消政策包含多个条件,例如"开课前 24 小时以上""开课前 24 小时以内""因平台原因取消",固定字符分割仍可能把条件和处理结果拆开。

RecursiveCharacterTextSplitter 示例观察

配置如下:

latex 复制代码
Chunk Size: 200
Chunk Overlap: 0

对于标题清晰、段落稳定的课程知识库,递归字符分割通常能得到较好的结果。它会尽量按章节、段落或句子边界切分,减少语义断裂。

但当一个章节内部包含多个互相依赖的业务条件时,递归分块仍可能不够精细。例如"取消与改约规则"中同时包含自助取消、人工处理、平台责任和课时返还,简单按句子切分可能会把条件和例外说明分开。此时可以考虑增加 overlap,或者对关键章节使用语义分块与人工复核。

分块策略怎么选?

1. 不同文档类型的推荐策略

文档类型 推荐策略 理由
课程帮助中心 / 教务知识库 递归分块 通常具有清晰标题、段落和条款结构,递归策略能利用这些边界。
FAQ / 问答对 按问答对切分,必要时结合递归分块 每个 Q&A 是天然知识单元,不应把问题和答案拆开。
课程协议 / 退款条款 语义分块 条款边界和例外条件需要精确识别,规则分块容易切错。
直播故障日志 固定大小分块或按行切分 日志通常按记录组织,结构简单。
代码文件 专用代码分块器,按类、函数或方法切分 通用文本分块不理解代码结构。
HTML 帮助页面 先清洗 HTML 标签,再递归分块 标签、导航栏和脚注会干扰分块,需要先处理。
OCR 扫描文本 清洗修复后使用重叠分块或语义分块 OCR 文本分隔符不可靠,先做去噪和结构修复更稳妥。
多类型企业知识库 混合分块 不同内容采用不同策略,整体效果更稳定。

2. chunk_size 与 overlap 的经验参考

以下参数不是标准答案,而是常见起点:

参数 推荐范围 说明
chunk_size 200 ~ 1000 字符 问答型知识偏小,例如 200 ~ 500;摘要或长说明偏大,例如 500 ~ 1000。
overlap chunk_size 的 10% ~ 25% 例如 chunk_size = 500 时,overlap 可从 50 ~ 125 之间试起。

一个实用调参路径:

latex 复制代码
初始配置:chunk_size = 500,overlap = 50
  ↓
准备 20 ~ 50 个真实用户问题
  ↓
观察 Top-K 检索结果
  ↓
如果召回内容噪声太多:减小 chunk_size
  ↓
如果答案上下文经常断裂:增大 overlap 或改用递归/语义分块
  ↓
如果不同文档表现差异大:引入混合分块和文档类型路由

企业级实践中的注意事项

真实项目里,分块效果不好往往不只是 chunk_size 没调对,也可能是上游文本抽取已经产生了噪声。尤其是 PDF、扫描件和复杂网页,常见问题包括:

  • 页眉、页脚、目录、页码混入正文;
  • 表格被拆成错位字段;
  • 换行错误导致一句话被切成多段;
  • 课程名称、价格、适用人群等结构化字段丢失;
  • 历史版本规则与当前规则混在一起;
  • 免责声明、版权信息、导航菜单干扰正文。

因此,稳定的流程不应是"抽取完成后立刻分块",而应是:

latex 复制代码
文本抽取
  ↓
去噪与结构修复
  ↓
版本识别与元数据补充
  ↓
分块
  ↓
向量化
  ↓
质量评估
  ↓
必要时人工二次编排

对于中小规模但高价值的课程知识库,还可以在基础分块之后加入人工二次编排。做法是先用递归分块或语义分块生成初稿,再由运营、教务或知识库维护人员检查关键块,对不完整、不准确或过长的块进行合并、拆分和补充。

这种方式能够解决单纯调参难以解决的问题。例如:

  • 某条退款规则需要和例外说明合并;
  • 某个 FAQ 的答案依赖前置适用范围,需要补充元数据;
  • 某段课程协议跨页,需要人工恢复完整条款;
  • 某个知识块需要标记生效日期,避免召回过期规则。

对于 Dify、RAGFlow 等标准 RAG 平台,基础分块能力通常可以覆盖大多数入门场景。但在企业级系统中,单一分块策略容易出现"顾此失彼":

  • chunk_size 变大,完整上下文更容易召回,但噪声可能增加;
  • chunk_size 变小,检索更精确,但规则更容易被切断;
  • overlap 增大,边界信息保留更好,但存储与向量化成本增加;
  • 只依赖递归分块,结构清晰的文档效果好,但复杂条款仍可能切错;
  • 只依赖语义分块,质量可能更高,但批量处理成本和延迟更高。

因此,更稳妥的工程方案通常是:文本清洗打底,递归分块作为默认策略,关键文档引入语义分块,重要知识块允许人工校正,并通过真实查询集持续评估效果。

文末总结

分块是 RAG 数据准备阶段的关键步骤。文本抽取之后,系统不能直接把长文档整体用于检索,而需要将其拆成大小合适、语义相对完整的文本块,再进行向量化和相似度检索。

常见分块策略各有定位:

策略 核心特点
固定大小分块 最简单,性能好,但容易切断语义。
重叠分块 在固定分块基础上保留重叠区域,缓解边界断裂。
递归分块 逐层使用段落、句子、标点等边界,是多数文本知识库的默认选择。
语义分块 基于 Embedding 或 LLM 判断主题变化,质量高但成本更高。
混合分块 针对不同文档类型组合多种策略,适合复杂企业知识库。

参数上,可以从 chunk_size = 500overlap = 50 开始,用真实用户问题评估检索效果。如果结果噪声多,适当减小 chunk_size;如果上下文断裂,适当增大 overlap 或切换到更能保留结构的策略。

分块之后,每个文本块仍然只是人类可读的文本。要让计算机进行相似度检索,还需要将文本块转换为向量表示,这一步就是 Embedding。分块质量越高,后续向量检索、重排和生成回答的上限也越高。

如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家!!

相关推荐
方也_arkling1 小时前
【Java-Day17】API篇-BigInteger和BigDecimal
java·开发语言
ghie90901 小时前
基于图像处理的铁路裂缝检测系统
图像处理·人工智能
EnCi Zheng1 小时前
09abb-SwiGLU激活函数
人工智能
星辰_mya1 小时前
ThreadLocal之微服务链路追踪
java·开发语言·前端
菜鸡旭旭1 小时前
【AI培训中台项目介绍】
人工智能
Elastic 中国社区官方博客1 小时前
Hacknight Beijing:基于阿里云与 Elastic 构建 AI Agents
大数据·运维·人工智能·elasticsearch·搜索引擎·阿里云·云计算
松仔log1 小时前
Jetpack——DataStore
java·kotlin
咸鱼翻身小阿橙1 小时前
文件读写 + Qt Model/View + 自定义分页+搜索过滤
java·数据库·qt
柏舟飞流1 小时前
大数据与 AI 融合:高阶架构与实践
大数据·人工智能·架构