一、文本分割的核心逻辑与关键参数

无论哪种分割方法,核心都是通过参数控制文本块的大小和关联性,先理清这几个核心参数,后续方法理解会事半功倍:

  • chunk_size:单个文本块的最大长度(字符 / Token 数),核心作用是适配大模型上下文窗口,避免单块内容过长;
  • chunk_overlap:相邻文本块的重叠长度,通常设为 chunk_size 的 10%-20%,目的是保证语义连续,避免分割后上下文断裂;
  • separators:分割符列表(优先级从高到低),决定文本 “从哪里拆”,支持普通字符(如。、\n)或正则表达式;
  • length_function:长度计算方式,默认按字符数(len),也可自定义为按 Token 数计算,适配不同模型需求。

二、5 种常用分割方法:场景化选型指南

1. 纯句子分割(适配中文语义)

这是最贴合中文表达习惯的分割方式,以中文句子结束符(。!?)为核心分割依据,优先保证每个文本块是完整的句子或句子组。

  • 核心特点:按语义单位拆分,避免切断完整句子,适合新闻、文章、对话等以句子为核心语义单元的文本;
  • 参数技巧:中文场景下 chunk_overlap 可设为 5-10 个字符,既保证关联又不冗余;is_separator_regex 设为 False,避免正则解析干扰普通分隔符匹配。

2. 按段落分割(适配结构化文本)

以空行、换行符(\n)为分割依据,优先保留完整段落语义,适合有明确段落划分的文本(如文档、论文、排版规整的文案)。

  • 核心特点:保留段落完整性,分割粒度比句子大,适合对上下文完整性要求高的场景;
  • 参数技巧:chunk_overlap 建议设为 20% 左右,因为段落间语义关联度通常更高,需更多重叠保证衔接。

3. 递归字符分割(推荐:通用最优解)

这是 LangChain 官方推荐的通用方法,本质是 “多优先级分层分割”—— 先按段落(\n)拆,拆不开再按句子(。!?)拆,还拆不开再按字符拆。

  • 核心特点:兼顾 “语义完整” 和 “长度限制”,适配 90% 以上的通用场景,尤其是无固定格式的长文本;
  • 分割优先级:段落符 → 句子符 → 普通字符,最大程度保留语义完整性的同时满足长度要求。

4. 按 Token 分割(精准适配大模型)

直接按 Token 数分割(而非字符数),是适配大模型的精准方案 —— 因为大模型的上下文窗口是按 Token 计算的,字符数无法精准对应模型处理能力。

  • 核心特点:精准匹配模型 Token 限制,避免因字符 / Token 换算偏差导致的超限问题;
  • 实用技巧:中文场景下可通过 “字符数 ×1.5” 近似估算 Token 数,正式使用时需指定编码(如 cl100k_base)保证精准度。

5. 固定字符长度分割(兜底方案)

无特定分割符,强制按固定字符数拆分,是所有分割方式的 “兜底选项”。

  • 核心特点:简单粗暴,完全不考虑语义,仅保证文本块长度符合要求;
  • 适用场景:无固定格式的杂乱文本(如日志、无标点的纯数据文本),或需要严格控制文本块长度的场景。

三、实战选型建议

  1. 中文通用场景(文章、文档、知识库):优先选递归字符分割,兼顾语义和长度;
  2. 追求精准语义(问答、摘要):选纯句子分割,保证每个块是完整语义单元;
  3. 结构化文本(论文、排版文案):选按段落分割,保留段落级上下文;
  4. 大模型落地(RAG、对话):选按 Token 分割,精准适配模型上下文窗口;
  5. 无格式杂乱文本:选固定字符长度分割,保证长度合规即可。

四、避坑指南

  1. 分割符优先级:列表中越靠前的分割符优先级越高,需按 “大粒度→小粒度” 排序(如先段落再句子);
  2. is_separator_regex 参数:中文普通分隔符(。!?)建议设为 False,避免正则转义导致匹配失败;
  3. 重叠长度控制:chunk_overlap 不宜超过 chunk_size 的 20%,否则会导致文本块冗余,增加处理成本。

总结

  1. 文本分割的核心是平衡语义完整性长度限制,优先选择能保留语义的分割方式(递归字符 / 句子分割);
  2. 不同场景需匹配不同分割策略:中文优先句子 / 递归分割,大模型落地优先 Token 分割,结构化文本优先段落分割;
  3. 关键参数需根据文本类型调整:chunk_overlap 设为 chunk_size 的 10%-20%,中文分隔符匹配时关闭正则解析。

看看代码如何实现:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

# -*- coding: utf-8 -*-

from langchain_community.document_loaders import TextLoader

from langchain_text_splitters import (

    CharacterTextSplitter,

    RecursiveCharacterTextSplitter,

    TokenTextSplitter

)

# ===================== 1. 加载文本 =====================

loader = TextLoader("./txt/1.txt", encoding="utf8")

docs = loader.load()

raw_text = docs[0].page_content

print("✅ 文本加载成功!")

print("======= 原始文本(前300字符)=======")

print(raw_text[:300], "...\n")

# ===================== 2. “按句子分割”=====================

# 方法1:纯句子分割(仅按。!?拆分)

    # 1. separators:分割符列表(优先级从高到低)

    #    作用:指定文本拆分的依据,按列表顺序优先匹配

    #    取值:字符串/正则表达式(需配合is_separator_regex使用)

    #    本场景:仅用中文句子结束符(。!?)作为分割依据

    # 2. chunk_size:单个分割块的最大字符数

    #    作用:限制每个文本块的长度,避免块过大(适配大模型上下文窗口)

    #    取值:正整数,单位为“字符数”(中文/英文均按1个字符计算)

    #    本场景:每个句子块最多150个字符,超过则继续拆分

    # 3. chunk_overlap:相邻分割块之间的重叠字符数

    #    作用:保证分割后相邻块有部分内容重叠,避免语义断裂

    #    取值:0 ~ chunk_size的20%(推荐),本场景设为5个字符重叠

    #    注意:句子分割时可设为0,段落/长文本分割建议设为10%-20%

    # 4. length_function:计算文本长度的函数

    #    作用:指定如何计算文本块的长度(字符数/Token数等)

    #    取值:默认len(按字符数计算),也可自定义函数(如按Token数)

    #    本场景:用内置len函数,按字符数统计长度

    # 5. is_separator_regex:是否将separators视为正则表达式

    #    核心说明:

    #    - True:separators中的字符串会被当作正则表达式解析(如r"。\n?"匹配“句号+可选换行”)

    #    - False(默认):separators中的字符串会被当作“普通字符串”精确匹配

    #    本场景:设为False,仅精确匹配“。”“!”“?”这三个普通字符,不解析正则

# 方法1:纯句子分割(仅按。!?拆分)

sentence_splitter = RecursiveCharacterTextSplitter(

    separators=["。""!""?"],  # 仅用中文句子分隔符

    chunk_size=150,                # 每个句子块最大字符数

    chunk_overlap=5,               # 块间重叠字符

    length_function=len,

    is_separator_regex=False

)

sentence_chunks = sentence_splitter.split_text(raw_text)

print("======= 按句子分割结果=======")

for idx, chunk in enumerate(sentence_chunks):

    print(f"句子块 {idx+1}(字符数:{len(chunk)}):")

    print(chunk.strip())

    print("-" * 60)

# ===================== 3. 其他分割方法 =====================

# 方法2:按段落分割(空行\n\n分隔)

paragraph_splitter = CharacterTextSplitter(

    separator="\n",

    chunk_size=150,

    chunk_overlap=20,

    is_separator_regex=False

)

para_chunks = paragraph_splitter.split_text(raw_text)

print("\n======= 按段落分割结果 ========")

for idx, chunk in enumerate(para_chunks):

    print(f"段落块 {idx+1}:{chunk.strip()[:100]}...")

# # 方法3:递归字符分割(推荐,段落→句子→字符优先级)

recursive_splitter = RecursiveCharacterTextSplitter(

    separators=["\n""。""!""?""\n"],  # 拆分优先级

    chunk_size=150,

    chunk_overlap=15

)

recur_chunks = recursive_splitter.split_text(raw_text)

print("\n======= 递归字符分割结果(推荐)=======")

for idx, chunk in enumerate(recur_chunks[:2]):

    print(f"递归块 {idx+1}:{chunk.strip()[:80]}...")

# 方法4:按Token分割(适配大模型)

token_splitter = TokenTextSplitter(

    encoding_name="cl100k_base",

    chunk_size=100,

    chunk_overlap=10

)

token_chunks = token_splitter.split_text(raw_text)

print("\n======= 按Token分割结果 ========")

for idx, chunk in enumerate(token_chunks[:2]):

    approx_tokens = len(chunk) * 1.5  # 中文近似Token数

    print(f"Token块 {idx+1}(近似Token数:{approx_tokens:.0f}):{chunk.strip()[:80]}...")

# 方法5:固定字符长度分割

fixed_splitter = CharacterTextSplitter(

    separator="",  # 无分隔符,强制按字符数拆分

    chunk_size=80,

    chunk_overlap=5

)

fixed_chunks = fixed_splitter.split_text(raw_text)

print("\n======= 固定字符长度分割结果 ========")

for idx, chunk in enumerate(fixed_chunks[:2]):

    print(f"固定块 {idx+1}(字符数:{len(chunk)}):{chunk.strip()}")

# chunk_size=1  chunk_overlap=0 强制分隔符分割

print("\n======= 强制按照分隔符分割 ========")

sentence_splitter = RecursiveCharacterTextSplitter(

    separators=["。""!""?"],  # 仅用中文句子分隔符

    chunk_size=1,                  # 每个句子块最大字符数

    chunk_overlap=0,               # 块间重叠字符

    length_function=len,

    is_separator_regex=False

)

sentence_chunks = sentence_splitter.split_text(raw_text)

print("======= 按句子分割结果=======")

for idx, chunk in enumerate(sentence_chunks):

    print(f"句子块 {idx+1}(字符数:{len(chunk)}):")

    print(chunk.strip())

    print("-" * 60)

 结果输出:

✅ 文本加载成功!
======= 原始文本(前300字符)=======
    文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切割、按关键词切割、按固定长度切割三种。
    按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割则需要提前设定核心关键词,当文本中出现该关键词时进行切割,适合针对性提取特定内容;按固定长度切割则不考虑文本语义,仅根据设定的字符数或字数进行拆分,适用于对文本长度有明确要求的场景。
    无论是哪种切割方式,核心目的都是为了降低文本处理的难度,方便后续的文本分析、语义理解、数据提取等操 ...

======= 按句子分割结果=======
句子块 1(字符数:94):
文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切割、按关键词切割、按固定长度切割三种
------------------------------------------------------------
句子块 2(字符数:147):

    按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割则需要提前设定核心关键词,当文本中出现该关键词时进行切割,适合针对性提取特定内容;按固定长度切割则不考虑文本语义,仅根据设定的字符数或字数进行拆分,适用于对文本长度有明确要求的场景
------------------------------------------------------------
句子块 3(字符数:80):

    无论是哪种切割方式,核心目的都是为了降低文本处理的难度,方便后续的文本分析、语义理解、数据提取等操作,广泛应用于智能客服、文本检索、机器翻译等领域。
------------------------------------------------------------

======= 按段落分割结果 ========
段落块 1:文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切割、按关键词切割、按固定长度切割三种。...
段落块 2:按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割则需要提前设定核心关键词,当文本中出现该关键词时进行切割,适合针对性提取特定内容;按固定长度切割则...
段落块 3:无论是哪种切割方式,核心目的都是为了降低文本处理的难度,方便后续的文本分析、语义理解、数据提取等操作,广泛应用于智能客服、文本检索、机器翻译等领域。...

======= 递归字符分割结果(推荐)=======
递归块 1:文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切割、按关...
递归块 2:按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割则需要提前设定核心关键词,当文本中出现该关键词时进行切割,...

======= 按Token分割结果 ========
Token块 1(近似Token数:138):文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切割、按关...
Token块 2(近似Token数:135):�切割、按固定长度切割三种。
    按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割则需要提前设定核心关...

======= 固定字符长度分割结果 ========
固定块 1(字符数:76):文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落。
    常见的切割方式包括,按标点符号切
固定块 2(字符数:80):标点符号切割、按关键词切割、按固定长度切割三种。
    按标点符号切割是最常用的方式,通常以句号、问号、感叹号作为切割节点,适用于大多数通用文本;按关键词切割

======= 强制按照分隔符分割 ========
======= 按句子分割结果=======
句子块 1(字符数:58):
文本切割是自然语言处理中的基础操作,主要用于将较长的文本内容拆解为更小的、可处理的单元,比如句子、短语或段落
------------------------------------------------------------
句子块 2(字符数:40):

    常见的切割方式包括,按标点符号切割、按关键词切割、按固定长度切割三种

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐