文本分割器
先决条件
- 文档
- 分词 (/docs/concepts/tokens)
概述
文档分割是许多应用程序中至关重要的预处理步骤。它涉及将大型文本分解成较小的、易于管理的部分。此过程具有多个优点,例如确保对不同文档长度进行一致的处理、克服模型的输入大小限制以及提高检索系统中使用的文本表示的质量。有几种分割文档的策略,每种策略都有其自身的优点。
主要概念
文本分割器将文档分割成较小的块,以便在下游应用程序中使用。
为什么要分割文档?
分割文档有以下几个原因
- 处理不均匀的文档长度:现实世界的文档集合通常包含大小不同的文本。分割可确保对所有文档进行一致的处理。
- 克服模型限制:许多嵌入模型和语言模型都有最大输入大小限制。分割使我们能够处理那些原本会超出这些限制的文档。
- 提高表示质量:对于较长的文档,当它们尝试捕获过多信息时,嵌入或其他表示的质量可能会下降。分割可以使每个部分具有更集中和更准确的表示。
- 提高检索精度:在信息检索系统中,分割可以提高搜索结果的粒度,从而更精确地将查询与相关的文档部分进行匹配。
- 优化计算资源:使用较小的文本块可以更节省内存,并允许更好地并行处理任务。
现在,下一个问题是如何将文档分割成块!有几种策略,每种策略都有其自身的优点。
进一步阅读
- 请参阅 Greg Kamradt 的 chunkviz,以可视化下面讨论的不同分割策略。
方法
基于长度
最直观的策略是基于文档长度来分割文档。这种简单而有效的方法可确保每个块不超过指定的大小限制。基于长度分割的关键优点
- 实现简单
- 一致的块大小
- 易于适应不同的模型要求
基于长度的分割类型
- 基于标记:基于标记的数量来分割文本,这在处理语言模型时很有用。
- 基于字符:基于字符的数量来分割文本,这在不同类型的文本之间可以更一致。
使用 LangChain 的 CharacterTextSplitter
进行基于标记的分割的示例实现
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
encoding_name="cl100k_base", chunk_size=100, chunk_overlap=0
)
texts = text_splitter.split_text(document)
API 参考:CharacterTextSplitter
基于文本结构
文本自然地组织成层次单元,如段落、句子和单词。我们可以利用这种内在结构来指导我们的分割策略,创建保持自然语言流、保持分割内的语义连贯性并适应不同文本粒度的分割。LangChain 的 RecursiveCharacterTextSplitter
实现了这个概念
RecursiveCharacterTextSplitter
尝试保持较大的单元(例如段落)完整。- 如果某个单元超出块大小,则会移动到下一级别(例如句子)。
- 如果需要,此过程会继续到单词级别。
以下是示例用法
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
texts = text_splitter.split_text(document)
进一步阅读
- 请参阅 递归文本分割 的指南。
基于文档结构
某些文档具有内在结构,例如 HTML、Markdown 或 JSON 文件。在这些情况下,根据文档的结构来分割文档是有益的,因为它通常自然地将语义相关的文本分组。基于结构分割的关键优点
- 保留文档的逻辑组织
- 保持每个块内的上下文
- 对于检索或摘要等下游任务可能更有效
基于结构分割的示例
- Markdown:基于标题(例如 #、##、###)进行分割
- HTML:使用标签进行分割
- JSON:按对象或数组元素进行分割
- 代码:按函数、类或逻辑块进行分割
进一步阅读
- 请参阅 Markdown 分割 的指南。
- 请参阅 递归 JSON 分割 的指南。
- 请参阅 代码分割 的指南。
- 请参阅 HTML 分割 的指南。
基于语义含义
与之前的方法不同,基于语义的分割实际上会考虑文本的内容。虽然其他方法使用文档或文本结构作为语义含义的代理,但此方法直接分析文本的语义。有几种方法可以实现此目的,但从概念上讲,该方法会在文本含义发生重大变化时分割文本。例如,我们可以使用滑动窗口方法来生成嵌入,并比较嵌入以查找重大差异
- 从前几个句子开始,生成一个嵌入。
- 移动到下一组句子,并生成另一个嵌入(例如,使用滑动窗口方法)。
- 比较嵌入以查找重大差异,这表明语义部分之间可能存在“中断点”。
这项技术有助于创建语义上更连贯的块,从而可能提高检索或摘要等下游任务的质量。
进一步阅读
- 请参阅 基于语义含义分割文本 的指南。
- 请参阅 Greg Kamradt 的 notebook,其中展示了语义分割。