在构建检索增强生成(RAG)应用时,我们往往将大部分精力集中在提示词工程(Prompt Engineering)或大模型的选择上。然而,决定 RAG 系统下限的关键环节,往往是被忽视的数据预处理阶段。
其中,Chunk Size(块大小)和 Chunk Overlap(块重叠)是两个最基础却最具影响力的参数。今天,我们将深入探讨这两个参数的本质,并展示如何在 Spring AI 和 Spring AI Alibaba 中优雅地配置它们。
一、 什么是 Chunk Size 和 Overlap?
简单来说,RAG 的第一步是将非结构化的长文档“切碎”,变成机器可处理的小片段。这个过程叫作 Text Splitting(文本切片)。
1. Chunk Size(块大小)
定义:每个文本块包含的最大字符数或 Token 数。
它决定了什么?
信息密度:Chunk 越大,包含的上下文越完整,但噪声也越多;Chunk 越小,语义越聚焦,但可能丢失背景信息。
检索精度:如果 Chunk 太大,向量嵌入(Embedding)可能会因为包含过多无关信息而变得“模糊”,导致相似度匹配不准。
模型限制:不同的 Embedding 模型对输入长度有最佳实践区间。例如,某些模型在 256-512 tokens 时表现最佳,超出这个范围效果可能下降。
2. Chunk Overlap(块重叠)
定义:相邻两个文本块之间重复保留的部分。
它解决了什么问题?
想象一下这句话被切断的场景:
“...人工智能是未来的核心驱动力,它将彻底改变...”
如果 Chunk Size 恰好切在“核心驱动力”和“它将”之间:
Chunk A: “...人工智能是未来的核心驱动力”
Chunk B: “它将彻底改变...”
如果没有 Overlap,Chunk B 失去了主语“人工智能”,语义断裂。当用户搜索“人工智能如何改变世界”时,Chunk B 可能因为缺乏关键实体而无法被准确检索。
Overlap 的作用:通过在边界处保留重复内容,确保语义的连贯性,防止关键信息被“腰斩”。通常建议设置为 Chunk Size 的 10%-20%。
二、 为什么这两个参数至关重要?
最佳实践原则:
没有通用的“黄金数值”。你需要根据文档类型(代码、小说、技术文档)、Embedding 模型特性以及**业务场景进行调优。
三、 在 Spring AI 中配置 Chunk Size 和 Overlap
在 Spring AI 生态中,切片逻辑不属于 ChatClient 或 Prompt 的配置范畴,而是属于 Document Processing(文档处理) 层。我们需要通过 TextSplitter 来实现。
1. 原生 Spring AI 配置
Spring AI 提供了多种 splitter,最常用的是 TokenTextSplitter(基于 Token 切割,更适配 LLM)和 CharacterTextSplitter(基于字符切割)。
推荐做法:定义 Bean
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiConfig {
/**
* 配置文本切片器
* @return TokenTextSplitter
*/
@Bean
public TokenTextSplitter tokenTextSplitter() {
// 参数说明:
// 1. chunkSize: 每个块的 Token 上限 (例如 512)
// 2. minChunkSize: 最小块大小 (例如 100,避免产生过碎的块)
// 3. overlap: 重叠 Token 数 (例如 50,约为 chunkSize 的 10%)
// 4. keepSeparator: 是否保留分隔符 (通常设为 true,保持标点完整性)
return new TokenTextSplitter(512, 100, 50, true);
}
}使用切片器处理文档
在将文档存入向量数据库之前,先进行转换:
@Autowired
private TokenTextSplitter textSplitter;
@Autowired
private VectorStore vectorStore;
public void ingestDocuments(List<Document> documents) {
// 1. 切片
List<Document> chunks = textSplitter.apply(documents);
// 2. 存入向量库
vectorStore.add(chunks);
}四、 在 Spring AI Alibaba 中配置
Spring AI Alibaba 兼容 Spring AI 的标准接口,因此配置方式高度一致。无论你底层使用的是阿里云的 DashVector、AnalyticDB 还是其他向量服务,切片逻辑都在客户端完成。
1. 配置 CharacterTextSplitter(示例)
如果你更倾向于按字符数切割(适合中文场景,因为中文 Token 计算较复杂,有时字符数更直观):
import org.springframework.ai.transformer.splitter.CharacterTextSplitter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AlibabaAiConfig {
@Bean
public CharacterTextSplitter characterTextSplitter() {
// 参数说明:
// 1. chunkSize: 字符数 (例如 1000)
// 2. overlap: 重叠字符数 (例如 200)
return new CharacterTextSplitter(1000, 200);
}
}2. 注意事项
中文优化:对于中文文档,建议使用
CharacterTextSplitter或支持中文分词的专用 Splitter,因为标准的 Tokenizer 可能对中文切分不够细腻。向量库侧配置:阿里云的部分向量服务(如 DashVector)在创建 Collection 时可能需要指定维度,但不包含切片逻辑。切片必须在 Java 应用层完成,再调用
vectorStore.add()。
五、 调优建议与总结
从默认值开始:
Chunk Size: 512 - 1024 tokensOverlap: 50 - 100 tokens (或 Chunk Size 的 10-15%)
观察检索结果:
如果检索到的内容缺少上下文,导致 LLM 回答片面 → 增大 Chunk Size 或 增大 Overlap。
如果检索到的内容噪声太多,包含大量无关信息 → 减小 Chunk Size。
针对不同文档类型调整:
代码文档:较小的 Chunk(如 200-300 tokens),因为代码逻辑紧凑,过大容易混入无关函数。
长篇报告/小说:较大的 Chunk(如 1000+ tokens),因为需要更多背景来理解情节或论点。
Spring AI 最佳实践:
将
TextSplitter定义为 Singleton Bean,便于统一管理和后续调优。在开发阶段,可以暴露这些参数为配置文件(
application.yml)中的属性,方便动态调整而不需重新编译。
结语
Chunk Size 和 Overlap 看似简单,却是 RAG 系统的“地基”。地基打不好,再强大的 LLM 也难以发挥实力。通过 Spring AI 提供的灵活组件,我们可以轻松实验不同的切片策略,找到最适合你业务场景的黄金组合。
下一步行动:检查你当前的 RAG 项目,看看是否硬编码了切片参数?尝试将其提取为可配置的 Bean,并进行一次 A/B 测试,观察检索质量的提升!
评论区