Skip to main content
Open on GitHub

文本分割器

先决条件
  • 文档
  • Tokenization(/docs/concepts/tokens)

概览

文档分割通常是许多应用中的关键预处理步骤。 它涉及将大段文本拆分为更小、更易管理的片段。 这一过程具有多种优势,例如确保对不同长度文档的一致处理、克服模型输入大小限制,以及提升检索系统中使用的文本表示质量。 有多种文档分割策略,每种策略都有其独特的优势。

核心概念

Conceptual Overview

文本分割器将文档拆分为更小的片段,以便在下游应用中使用。

为什么要拆分文档?

拆分文档有几个原因:

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

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

更多阅读
  • 查看 Greg Kamradt 的 chunkviz,以可视化下面讨论的不同分割策略。

方法

Length-based

最直观的策略是根据文档的长度来分割文档。这种简单而有效的方法可以确保每个片段的大小不超过指定的限制。 基于长度分割的主要优势:

  • 直接实现
  • 一致的块大小
  • 易于适应不同的模型需求

基于长度的分割类型:

  • 基于令牌: 根据令牌数量分割文本,这在使用语言模型时非常有用。
  • 基于字符: 根据字符数量分割文本,这在不同类型的文本中可能更加一致。

使用 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)
更多阅读
  • 查看有关基于标记的分割的指南。
  • 查看关于按字符分割的指南。

基于文本结构的

文本自然地组织成段落、句子和单词等层次结构。 我们可以利用这种固有结构来指导我们的分割策略,创建出保持自然语言流畅性、在分割内保持语义连贯性,并能适应不同文本粒度级别的分割。 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: 按对象或数组元素分割
  • 代码: 按函数、类或逻辑块分割
更多阅读

基于语义意义的

与之前的方法不同,基于语义的分割实际上考虑了文本的内容。 与其他方法使用文档或文本结构作为语义含义的代理不同,此方法直接分析文本的语义。 实现这一方法有几种方式,但其概念上是当文本的含义发生显著变化时进行分割。 例如,我们可以使用滑动窗口方法生成嵌入向量,并通过比较嵌入向量来发现显著差异:

  • 从前几句开始并生成嵌入。
  • 移动到下一组句子并生成另一个嵌入(例如,使用滑动窗口方法)。
  • 比较嵌入向量以发现显著差异,这些差异表明语义段落之间可能存在“断点”。

这种技术有助于创建语义上更连贯的文本块,从而可能提升下游任务(如信息检索或摘要生成)的质量。

更多阅读