加载中

文本分块策略

第 33 课10 分钟

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

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

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

基于大小的分块

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

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

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

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

这是一个基本实现:

python
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文件)时,这种方法效果很好。

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

python
def chunk_by_section(document_text):
    pattern = r"\n## "
    return re.split(pattern, document_text)

这种方法为您提供了最清晰、最有意义的块,因为每个块都代表一个完整的章节。但是,它只在您对文档结构有保证的情况下才有效。许多现实世界中的文档是没有明确结构标记的纯文本或PDF。

基于语义的分块

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

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

基于句子的分块

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

python
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

选择您的策略

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

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

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

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