微信扫码
添加专属顾问
我要投稿
RAG应用中文本切分是提升检索与生成质量的关键,合理分块能显著优化相关性、效率和生成精准度。核心内容: 1. 文本切分对检索相关性的影响与优化策略 2. 分块大小对计算效率和数据库性能的平衡 3. 适配LLM上下文窗口的切分方法与质量保障
在RAG(检索增强生成,Retrieval-Augmented Generation)应用中,文本分块(Text Chunking)是连接“知识存储”与“检索-生成”的核心预处理步骤,其重要性体现在对检索效率、相关性、生成质量及系统灵活性的多维度影响。
首先松哥和大家讨论第一个问题,就是为什么我们要重视文本切分。
RAG 的核心是“先检索、后生成”,而检索的本质是从知识库中找到与用户查询语义最相关的信息。文本分块直接影响检索的精准度:
RAG 依赖向量数据库存储文本的向量表示(通过嵌入模型生成),检索时需计算“用户查询向量”与“文本块向量”的相似度。分块对效率的影响体现在:
LLM(大语言模型)生成回答时,依赖检索到的文本块作为“事实依据”。分块质量直接影响输入 LLM 的上下文有效性:
一般我们通过嵌入模型来生成嵌入向量,而嵌入向量往往也有上下文窗口大小的限制。以常见的 bge-m3 为例,我们可以在介绍文档中看到最大 token 数的限制。
当然,我们也可以直接在模型的配置文件中找到 token 上限:
上图是在 tokenizer_config.json 文件中找到的配置,有的是在 config.json 配置文件中。
现实中,RAG 的知识库常包含长文档(如论文、手册、法律条文等),其长度远超 LLM 的上下文窗口(例如,一本 300 页的技术手册)。文本分块是处理这类文档的核心手段:
分块的核心挑战是“如何划分边界”,而合理分块能在“信息完整”与“聚焦性”间找到平衡:
针对这里第一小点,松哥举个例子。
假设原文是一段关于"气候变化对农业影响"的论证:
①. 全球平均气温上升会导致极端天气事件增加。
②. 干旱和洪涝频率上升会直接破坏农作物生长周期。
③. 这将导致主要粮食产区的产量下降。
④. 最终可能引发全球粮食供应紧张和价格波动。
这四句话构成一个完整的因果链论证:气温上升→极端天气→作物受损→粮食危机。
如果按单句分块存储,当用户查询"气候变化为何会导致粮食价格上涨"时:
这种情况下,过度细碎的分块割裂了语义关联,使检索到的信息失去了上下文支撑,LLM自然无法生成逻辑完整的回答。
因此,优质分块策略(如按语义、段落、标点符号分块)需确保每个块既能独立表达完整信息,又不包含无关内容,这是 RAG 系统性能的关键前提。
那么文本该如何切?
虽然文本切分策略很多,但是 Java 在这块现有框架目前支持的比较少,Spring AI 中仅有一个 TokenTextSplitter,而在 Spring AI Alibaba 中则多支持了一个 SentenceSplitter。
我们来简单看看这两种切分策略。
在 Spring AI 中,TokenTextSplitter 是一个用于文本分割的工具类,主要功能是将长文本按照令牌(Token)数量进行拆分,适用于处理超出大语言模型(LLM)上下文窗口限制的文本内容。它是实现文本分块(Text Chunking)的重要组件,通常在构建检索增强生成(RAG)等应用时使用。
TokenTextSplitter 通常使用与 LLM 一致的令牌化逻辑(通常基于 OpenAI 的 tiktoken 库),确保分割结果与模型的令牌计数一致;并且 TokenTextSplitter 会尽量在自然边界(如句子结束处)进行分割,避免将完整语义拆分到不同文本块中。
我们来看一段简单的示例代码:
List<Document> documents = myTikaDocumentReader.loadText();
TokenTextSplitter splitter = new TokenTextSplitter(30,10,3,2000,true);
List<Document> chunks = splitter.apply(documents);
for (Document chunk : chunks) {
System.out.println("内容块: " + chunk.getText());
System.out.println("元数据: " + chunk.getMetadata()); // 继承原始文档元数据
}
在构建 TokenTextSplitter 的时候,有五个参数,含义分别如下:
TokenTextSplitter 处理流程如下:
以上代码最终切块后的结果如下:
Spring AI Alibaba 的 SentenceSplitter 是一个专为文本分块设计的组件,主要用于优化 RAG(检索增强生成) 流程中的文档预处理阶段。它通过智能拆分长文本为语义连贯的句子组,确保后续向量化处理能保留上下文完整性,从而提升大模型在问答、知识检索等任务中的准确性。
SentenceSplitter 的工作流程分为两步:
代码案例如下:
List<Document> documents = myTikaDocumentReader.loadText();
SentenceSplitter splitter = new SentenceSplitter(128);
List<Document> chunks = splitter.apply(documents);
for (Document chunk : chunks) {
System.out.println("内容块: " + chunk.getText());
System.out.println("元数据: " + chunk.getMetadata()); // 继承原始文档元数据
}
这是目前我们在 Java 相关框架中支持的分块方案。
还有其他一些分块思路,这里也和大家聊聊,大家可以结合自己的项目需求,自行实现。
将文本按照预设的固定长度(如字符数、token 数)进行均匀拆分,不考虑文本的语义、结构或标点等信息,当剩余文本长度不足固定长度时,作为最后一个块保留。
以“先大后小”的层级逻辑分块,优先按大粒度分隔符(如段落、章节)切分,若分块后仍超过预设长度,则递归使用更小粒度的分隔符(如句子、逗号)继续切割,直到所有块的长度符合要求。
根据文本的固有结构特征(如格式标记、逻辑层级)进行分块,将具有相同结构属性的内容划分为一个块。
<h1>
(一级标题)、<p>
(段落)、<table>
(表格)等标签分块,每个标签内的内容作为独立块。#
(标题)、-
(列表项)、(代码块)分块。以标点符号作为分块的主要依据,将标点符号(如句号、问号、感叹号、分号)分隔的内容划分为独立块,通常优先使用表示语义停顿较强的标点。
实际应用中,常结合多种策略(如递归分块中融入标点和结构信息),以适应复杂文本的分块需求。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-08-02
RAG与Agentic RAG:智能AI系统的进化之路
2025-08-02
不止于相似度:混合搜索如何重塑 RAG 的未来
2025-08-02
为什么你的RAG效果总差一点?从RankNet到Qwen,一文读懂Rerank模型的演进
2025-08-02
提升RAG表现的15个实战分块技巧
2025-08-01
96.3%准确率!Routine框架:让企业级Agent告别“不靠谱”
2025-08-01
中小企业AI破局:RAG 部署从 “能用” 到 “能用好” 的 10 条经验
2025-08-01
关于一个RAG功能需求分析案例——、怎么优化RAG的检索精确度
2025-08-01
踩了无数坑后,我终于搞定了RAG系统的"胡说八道"问题
2025-06-06
2025-05-30
2025-06-05
2025-05-19
2025-05-08
2025-05-10
2025-06-05
2025-05-20
2025-06-05
2025-05-09
2025-07-28
2025-07-09
2025-07-04
2025-07-01
2025-07-01
2025-07-01
2025-07-01
2025-06-30