第 52 页 / 共 100 页 / 飞书修订版 9

2.Text chunking strategies

此文档由 学习AI的1000天 翻译制作(抖音,B站,YouTube)

邮箱: szqshan@gmail.com | 微信: szqshan
网址: www.xueai.org

==================================================

Xb7YbZxGMoQBTxxqb0VcB8Bkn7e.bin
AGOzbcqj7o0K56xyZ9mc3Gb8nkg.md
SMHrb8d8Bo77TqxsDvJcrYftnpb.md

文本分块是构建RAG(检索增强生成)管道中最关键的步骤之一。你如何拆分文档直接影响整个系统的质量。糟糕的分块策略可能导致不相关的上下文被插入到你的提示中,从而使AI给出完全错误的答案。

image1.jpeg

考虑这个例子:你有一个包含医学研究和软件工程章节的文档。如果分块不当,用户询问"工程师今年修复了多少个bug?"时,可能会得到关于医学研究的信息而不是软件工程的信息,仅仅因为医学章节恰好在不同语境下包含了"bug"这个词。

image2.jpeg

这就是为什么选择正确的分块策略如此重要。让我们探讨三种主要方法。

Size-Based Chunking

image3.jpeg

基于大小的分块是最简单的方法——你将文本分割成等长的字符串。如果你有一个325个字符的文档,你可能会将其分割成三个大约各108个字符的块。

image4.jpeg

这种方法易于实现且适用于任何类型的文档,但它有明显的缺点:

  • 单词会在句子中间被截断
  • 分块会失去来自周围文本的重要上下文
  • 章节标题可能与其内容分离
image5.jpeg

为了解决这些问题,你可以在分块之间添加重叠。这意味着每个分块都包含来自相邻分块的一些字符,提供更好的上下文并确保单词和句子的完整性。

image6.jpeg

这里是一个基本实现:

def chunk_by_char(text, chunk_size=150, chunk_overlap=20):

chunks = []

start_idx = 0

while start_idx < len(text):

end_idx = min(start_idx + chunk_size, len(text))

chunk_text = text[start_idx:end_idx]

chunks.append(chunk_text)

start_idx = (

end_idx - chunk_overlap if end_idx < len(text) else len(text)

)

return chunks

基于结构的分块

基于结构的分块根据文档的自然结构来划分文本——标题、段落和章节。当你有格式良好的文档(如Markdown文件)时,这种方法效果很好。

image7.jpeg

对于Markdown文档,你可以按标题标记进行分割:

def chunk_by_section(document_text):

pattern = r"\n## "

return re.split(pattern, document_text)

这种方法能给你最干净、最有意义的分块,因为每个分块都代表一个完整的章节。然而,它只有在你能保证文档结构的情况下才有效。许多现实世界的文档都是纯文本或PDF格式,没有清晰的结构标记。

基于语义的分块

基于语义的分块是最复杂的方法。你将文本分割成句子,然后使用自然语言处理来确定连续句子之间的相关性。你从相关句子组中构建分块。

这种方法计算成本较高,但能产生最相关的分块。它需要理解单个句子的含义,实现起来比其他策略更复杂。

基于句子的分块

一个实用的折中方案是按句子进行分块。你可以使用正则表达式将文本分割成单独的句子,然后将它们分组成带有可选重叠的块:

def chunk_by_sentence(text, max_sentences_per_chunk=5, overlap_sentences=1):

sentences = re.split(r"(?<=[.!?])\s+", text)

chunks = []

start_idx = 0

while start_idx < len(sentences):

end_idx = min(start_idx + max_sentences_per_chunk, len(sentences))

current_chunk = sentences[start_idx:end_idx]

chunks.append(" ".join(current_chunk))

start_idx += max_sentences_per_chunk - overlap_sentences

if start_idx < 0:

start_idx = 0

return chunks

选择您的策略

您的选择完全取决于您的使用场景和文档保证:

  • 基于结构的分块:当您能控制文档格式时效果最佳(如内部公司报告)
  • 基于句子的分块:对于大多数文本文档来说是很好的中间选择
  • 基于大小的分块:最可靠的备选方案,适用于任何内容类型,包括代码

带重叠的基于大小分块通常是生产环境中的首选,因为它简单、可靠,并且适用于任何文档类型。虽然可能无法给出完美的结果,但它能持续产生合理的分块,不会破坏您的处理流程。

请记住:没有单一的"最佳"分块策略。正确的方法取决于您的具体文档、使用场景,以及您愿意在实现复杂性和分块质量之间做出的权衡。

==================================================



此文档由 学习AI的1000天 翻译制作(抖音,B站,YouTube)
邮箱: szqshan@gmail.com | 微信: szqshan
网址: www.xueai.org