Skip to main content
Open on GitHub

文本分割器

Prerequisites
  • 文档
  • 分词(/docs/concepts/tokens)

概述

文档分割通常是许多应用程序中关键的预处理步骤。 它涉及将大文本分解为更小、更易管理的块。 这个过程提供了几个好处,例如确保对不同长度的文档进行一致的处理,克服模型的输入大小限制,并提高检索系统中使用的文本表示的质量。 有几种分割文档的策略,每种策略都有其自身的优势。

关键概念

概念概述

文本分割器将文档分割成更小的块,以便在下游应用中使用。

为什么要分割文档?

有几种原因需要拆分文档:

  • 处理非统一文档长度:现实世界的文档集合通常包含不同大小的文本。分割确保所有文档的一致处理。
  • 克服模型限制:许多嵌入模型和语言模型都有最大输入大小的限制。分割使我们能够处理那些原本会超出这些限制的文档。
  • 提高表示质量:对于较长的文档,嵌入或其他表示的质量可能会下降,因为它们试图捕获过多的信息。分割可以导致每个部分的表示更加集中和准确。
  • 提高检索精度:在信息检索系统中,分割可以提高搜索结果的粒度,使得查询与相关文档部分的匹配更加精确。
  • 优化计算资源:处理较小的文本块可以更节省内存,并允许更好地并行化处理任务。

现在,下一个问题是如何将文档分割成块!有几种策略,每种策略都有其自身的优势。

Further reading
  • 查看 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 Reference:CharacterTextSplitter
Further reading

基于文本结构的

文本自然地组织成层次结构单元,如段落、句子和单词。 我们可以利用这种固有结构来指导我们的分割策略,创建保持自然语言流程的分割,保持分割内的语义连贯性,并适应不同层次的文本粒度。 LangChain的RecursiveCharacterTextSplitter实现了这一概念:

  • RecursiveCharacterTextSplitter 尝试保持较大的单元(例如,段落)完整。
  • 如果一个单元超过了块大小,它将移动到下一个级别(例如,句子)。
  • 如有必要,此过程将继续向下到单词级别。

以下是示例用法:

from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
texts = text_splitter.split_text(document)
Further reading

基于文档结构的

一些文档具有固有的结构,例如HTML、Markdown或JSON文件。 在这些情况下,基于文档的结构进行分割是有益的,因为它通常自然地分组语义相关的文本。 基于结构的分割的主要好处:

  • 保留文档的逻辑组织
  • 在每个块中保持上下文
  • 对于检索或摘要等下游任务可能更有效

基于结构的分割示例:

  • Markdown: 根据标题分割(例如,#, ##, ###)
  • HTML: 使用标签进行分割
  • JSON: 按对象或数组元素分割
  • 代码: 按函数、类或逻辑块分割
Further reading

基于语义的意义

与之前的方法不同,基于语义的分割实际上考虑了文本的内容。 虽然其他方法使用文档或文本结构作为语义的代理,但这种方法直接分析文本的语义。 有几种方法可以实现这一点,但从概念上讲,当文本意义发生显著变化时,该方法会分割文本。 例如,我们可以使用滑动窗口方法来生成嵌入,并比较嵌入以找到显著差异:

  • 从最初的几句话开始并生成一个嵌入。
  • 移动到下一组句子并生成另一个嵌入(例如,使用滑动窗口方法)。
  • 比较嵌入以找到显著差异,这些差异表示语义部分之间的潜在“断点”。

这种技术有助于创建语义上更连贯的块,可能提高下游任务(如检索或摘要)的质量。

Further reading

这个页面有帮助吗?