掌握大模型 RAG 优化:深度解析 4 种主流文本分块(Chunking)策略

56 阅读7分钟

在构建基于大语言模型(LLM)的知识库应用时,文本分块(Chunking) 是决定检索精度最关键的环节之一。本文将深入探讨为什么要进行分块,并详细介绍四种主流的分块策略及其代码实现。


一、 为什么“分块”至关重要?

分块是将长文档拆分为更小、更易处理的片段的过程。其核心目标是:在检索时准确找到最相关的内容。

  • 语义独立性:理想的块应尽可能在不依赖上下文的情况下表达完整意思,方便模型理解。
  • 粒度平衡:块太小,有效信息不足,模型难以理解;块太大,包含噪音多,检索相关性下降。
  • 预处理:在分块前,通常需要进行文本清洗、去除停用词等操作。

二、 四种主流分块策略实战

1. 基于标点符号切分(句子级)

通过识别自然语言中的标点符号(如 )进行切分,最大限度保持了语义的完整。

import re

def split_text_by_punctuation(text):
    # 匹配中英文结尾标点
    pattern = r"[。!?。]+"
    segments = re.split(pattern, text)
    return [s.strip() for s in segments if s.strip()]

# 适用场景:对话系统、对短句逻辑敏感的场景。

2. 固定字符数切分

不考虑内容含义,强制按照设定的字符长度进行硬切分。

def split_text_by_fixed_length(text, length):
    return [text[i:i + length] for i in range(0, len(text), length)]

# 优缺点:实现极其简单,但会造成主题和语义的严重断裂。
# 适用场景:日志处理、固定格式的代码块、传感器流数据。

3. 带重叠窗口的固定长度切分

这是对固定长度切分的改良,通过在相邻的块之间保留一部分重叠(Overlap),确保跨块的上下文信息不会丢失。

def split_text_by_fixed_length_with_overlap(text, length, overlap):
    step = length - overlap
    return [text[i:i + length] for i in range(0, len(text) - overlap, step)]

# 意义:如果某个语义被切断,重叠部分能确保它在下一个 Chunk 中以完整形式出现。

4. 递归字符切分(推荐方案)

这是目前 RAG 应用中最常用的策略(如 LangChain 的默认实现)。它通过一组分隔符(如 \n\n, \n, ``)递归地尝试拆分,直到块大小达标。

LangChain 实现示例:

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", " ", ""], # 优先级由高到低
    chunk_size=60, 
    chunk_overlap=12,
    length_function=len
)

text = "..." # 您的长文本 
splits = splitter.split_text(text)

三、 策略效果对比

以以下文本为例,对比不同策略的效果。

春节的脚步越来越近,大街小巷都布满了节日的气氛。商店门口挂满了红灯笼和春联,家家户户都在忙着打扫卫生,准备迎接新的一年。 小明回到家乡,感受到了浓浓的过年氛围。他在街上走着,看到小朋友们手持烟花棒,欢笑声此起彼伏。 夜幕降临,整个城市亮起了五彩缤纷的灯光,映照着人们脸上的喜悦与期待。老人们聚在一起,回忆过去,展望未来。 而年轻人则在夜市享受美食,放松心情。这是一个充满希望和喜悦的时刻,每个人都在以自己的方式庆祝这个特殊的节日。

1、基于标点符号切分(句子级)

Chunk 1: 春节的脚步越来越近,大街小巷都布满了节日的气氛
Chunk 2: 商店门口挂满了红灯笼和春联,家家户户都在忙着打扫卫生,准备迎接新的一年
Chunk 3: 小明回到家乡,感受到了浓浓的过年氛围
Chunk 4: 他在街上走着,看到小朋友们手持烟花棒,欢笑声此起彼伏
Chunk 5: 夜幕降临,整个城市亮起了五彩缤纷的灯光,映照着人们脸上的喜悦与期待
Chunk 6: 老人们聚在一起,回忆过去,展望未来
Chunk 7: 而年轻人则在夜市享受美食,放松心情
Chunk 8: 这是一个充满希望和喜悦的时刻,每个人都在以自己的方式庆祝这个特殊的节日

2、固定字符数切分

Chunk 1: 春节的脚步越来越近,大街小巷都布满了节日的气氛。商店门口挂满了红灯笼和春联,家家户户都在忙着打扫卫生,准备迎接新的一年。小明回到家乡,感受到了浓浓的过年氛围。他在街上走着,看到小朋友们手持烟花棒,欢笑
Chunk 2: 声此起彼伏。夜幕降临,整个城市亮起了五彩缤纷的灯光,映照着人们脸上的喜悦与期待。老人们聚在一起,回忆过去,展望未来。而年轻人则在夜市享受美食,放松心情。这是一个充满希望和喜悦的时刻,每个人都在以自己的
Chunk 3: 方式庆祝这个特殊的节日。

3、带重叠窗口的固定长度切分

Chunk 1: 春节的脚步越来越近,大街小巷都布满了节日的气氛。商店门口挂满了红灯笼和春联,家家户户都在忙着打扫卫生,准备迎接新的一年。小明回到家乡,感受到了浓浓的过年氛围。他在街上走着,看到小朋友们手持烟花棒,欢笑
Chunk 2: 了浓浓的过年氛围。他在街上走着,看到小朋友们手持烟花棒,欢笑声此起彼伏。夜幕降临,整个城市亮起了五彩缤纷的灯光,映照着人们脸上的喜悦与期待。老人们聚在一起,回忆过去,展望未来。而年轻人则在夜市享受美食
Chunk 3: 老人们聚在一起,回忆过去,展望未来。而年轻人则在夜市享受美食,放松心情。这是一个充满希望和喜悦的时刻,每个人都在以自己的方式庆祝这个特殊的节日。

4、递归字符切分(推荐方案)

Chunk 1: 春节的脚步越来越近,大街小巷都布满了节日的气氛。商店门口挂满了红灯笼和春联,家家户户都在忙着打扫卫生,准备迎接新的一年。
Chunk 2: 卫生,准备迎接新的一年。小明回到家乡,感受到了浓浓的过年氛围。他在街上走着,看到小朋友们手持烟花棒,欢笑声此起彼伏。夜幕
Chunk 3: 棒,欢笑声此起彼伏。夜幕降临,整个城市亮起了五彩缤纷的灯光,映照着人们脸上的喜悦与期待。老人们聚在一起,回忆过去,展望未
Chunk 4: 在一起,回忆过去,展望未来。而年轻人则在夜市享受美食,放松心情。这是一个充满希望和喜悦的时刻,每个人都在以自己的方式庆祝
Chunk 5: 个人都在以自己的方式庆祝这个特殊的节日。

四、 策略对比总结

策略灵活性语义保持复杂度推荐使用场景
句子切分极高结构化良好的文学或新闻文本
固定字符极低日志、固定格式数据
重叠窗口追求检索召回率的通用 RAG
递归切分首选策略,适用于复杂文档

五、 结语

分块没有“一劳永逸”的万能公式。对于开发者而言,最有效的做法是:

  1. 分析数据源(是规整的报告还是杂乱的网页?)。
  2. 选择合适的 Splitter(优先尝试递归切分)。
  3. 利用可视化工具(如 LangChain Text Splitter Streamlit App)实时调整 chunk_sizeoverlap