介绍
RecursiveCharacterTextSplitter 是 LangChain 文本分割器的首选款,核心解决 长文本拆分时保证语义完整 的问题:
原理
按「优先级分隔符列表」递归拆分文本——先尝试用高优先级分隔符(如空行、段落)拆分,若拆分后的片段仍超过指定长度,再用低优先级分隔符(如标点、空格)拆分,直到所有片段符合长度要求。
优点
尽可能按 自然语义边界 拆分(而非生硬截断),避免“2025年销售额500万”被拆成“2025年销售额”和“500万”,适配大模型上下文窗口的同时保证语义连贯。
使用场景
- RAG 知识库构建(拆分长文本,提升检索精度);
- 文本长度超过大模型上下文窗口(如 GPT-3.5 4k tokens);
- 需按段落/固定长度拆分文本。
语法
RecursiveCharacterTextSplitter()
参数详解
| 参数 | 作用 | 中文场景推荐值 |
|---|---|---|
chunk_size |
每段文本的最大长度(按 length_function 计算) |
2000-4000(字符) |
chunk_overlap |
相邻段落的重叠长度(避免拆分切断语义) | 100-300(字符) |
length_function |
长度计算函数(中文用 len() 按字符数,英文可按 tokens 算) |
len(中文) |
separators |
拆分分隔符列表(优先级从高到低) | 见上方代码(中文专属) |
add_start_index |
是否在元数据中添加片段在原文的起始索引 | True(便于溯源) |
常用方法
split_documents()
拆分 Document 对象列表,返回拆分后的小 Document 列表。
特点:
- 保留原
Document的所有元数据(如文件路径、来源),并新增「片段在原文的起始索引」; - 完全遵循初始化时的拆分规则(字符长度、重叠数、分隔符)。
适用场景:
- RAG 知识库构建(文件加载器加载后直接拆分,无缝接入向量库);
- 需保留元数据的文本拆分(如溯源文本来源、文件路径);
- 通用长文本拆分(Word/PDF/CSV 加载后的
Document处理)。
split_text()
拆分纯文本字符串,返回纯文本片段列表(无元数据)。
特点:
- 仅输出文本片段,无任何元数据和索引信息;
- 操作极简,无需封装
Document,直接处理字符串。
适用场景:
- 无元数据需求的纯文本拆分(如日志、简单笔记);
- 快速验证拆分效果(仅看文本片段,不关注来源);
- 纯文本批量处理(如文本统计、简单摘要)。
split_text_with_overlaps()
拆分文本并返回「片段内容+起始/结束索引+重叠长度」等精准信息。
特点:
- 不仅返回文本,还提供片段在原文的位置、重叠部分的长度;
- 便于精准溯源和语义校验。
适用场景:
- 文本溯源(定位片段在原文的具体位置);
- 语义完整性校验(检查重叠部分是否覆盖关键信息);
- 企业级精准处理(如法律文档、合同拆分后的定位)。
方法选择
| 场景 | 首选方法 | 核心原因 |
|---|---|---|
| RAG 知识库构建(加载器后拆分) | split_documents() | 保留元数据,适配向量库/大模型生态 |
| 纯文本拆分(无元数据需求) | split_text() | 极简操作,仅关注文本片段 |
| 纯文本转标准化 Document | create_documents() | 自定义元数据,统一格式 |
| 文本溯源/精准定位 | split_text_with_overlaps() | 提供索引/重叠信息,便于精准管理 |
例子
本例为了便于理解,对字符串进行拆分
from langchain_text_splitters import RecursiveCharacterTextSplitter
text = """
本报告旨在总结2025年度XX科技有限公司(以下简称“公司”)的经营情况、核心成果、存在问题及2026年度发展规划,为公司管理层决策、员工认知及合作方了解提供依据。2025年,公司围绕“数字化转型、提质增效”核心目标,稳步推进各项业务,实现营收、利润双增长,圆满完成年度既定目标。
"""
# 初始化递归字符分割器(中文场景核心配置)
splitter = RecursiveCharacterTextSplitter(
chunk_size=20, # 每段最大字符数
chunk_overlap=10, # 段落重叠字符数(保证语义连贯)
length_function=len, # 长度计算方式(中文用 len() 按字符数算)
# 中文专属:分隔符优先级(从高到低,优先按自然语义拆分)
separators=[
"\n\n", # 空行(优先按段落拆分)
"\n", # 换行(按行拆分)
"。", # 句号(按完整句子拆分)
"!", # 感叹号
"?", # 问号
";", # 分号
";", # 分号
",", # 逗号
"、", # 顿号
" ", # 空格
"", # 最后兜底:硬截断
]
)
# 3. 拆分文本(返回多个小 Document)
split_docs = splitter.split_text(text)
print("返回结果类型:", type(split_docs))
print(f"原始文本字符数:{len(text)}")
print(f"拆分后片段数:{len(split_docs)}")
for i, item in enumerate(split_docs):
print(f"---第{i}段字符数:{len(item)}")
print(f"第{i}段内容:{item}")
执行结果
前几段有重复、后面无重复 的原因
这个问题不是参数设置错误,而是文本本身的「语义边界+长度分布」导致的正常现象,核心原因有3类:
最后几段文本长度不足:
当拆分到最后几个片段时,剩余文本的总长度 ≤ chunk_size + chunk_overlap,分割器会直接将剩余文本作为最后一段,不再强制重叠(否则会导致片段重复/长度超限)。
例:chunk_size=3000、chunk_overlap=200,最后剩余文本仅 2500 字符 → 最后一段直接取 2500 字符,无后续片段,因此无重叠。文本末尾无匹配的语义分隔符:
分割器优先按「高优先级分隔符(空行/句号)」拆分,文本末尾若为无分隔符的连续文本,分割器会硬截断,导致重叠逻辑无法触发(仅按字符数拆分时,末尾易出现无重叠)。重叠长度超过剩余文本长度:
若剩余文本长度 < chunk_overlap,分割器会放弃重叠(否则会导致片段内容完全重复)。
例:chunk_overlap=200,最后剩余文本仅 150 字符 → 无足够内容支撑重叠,因此无重复。
案例
适配 Docx2txtLoader 拆分大文本,中文场景最优配置
from langchain_community.document_loaders import Docx2txtLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载大 Word 文件,传入Word文件路径
loader = Docx2txtLoader("../企业报告.docx")
doc = next(loader.lazy_load()) # 大文件用 lazy_load() 更友好
# 2. 初始化递归字符分割器(中文场景核心配置)
splitter = RecursiveCharacterTextSplitter(
# 核心参数
# chunk_size=3000, # 每段最大字符数(适配 GPT-3.5 4k tokens)
chunk_size=200, # 每段最大字符数(适配 GPT-3.5 4k tokens)
# chunk_overlap=200, # 段落重叠字符数(保证语义连贯)
chunk_overlap=50, # 段落重叠字符数(保证语义连贯)
length_function=len, # 长度计算方式(中文用 len() 按字符数算)
# 中文专属:分隔符优先级(从高到低,优先按自然语义拆分)
separators=[
"\n\n", # 空行(优先按段落拆分)
"\n", # 换行(按行拆分)
"。", # 句号(按完整句子拆分)
"!", # 感叹号
"?", # 问号
";", # 分号
";", # 分号
",", # 逗号
"、", # 顿号
" ", # 空格
"", # 最后兜底:硬截断
]
)
# 3. 拆分文本(返回多个小 Document)
split_docs = splitter.split_documents([doc])
print("返回结果类型:", type(split_docs))
print(f"原始文本字符数:{len(doc.page_content)}")
print(f"拆分后片段数:{len(split_docs)}")
for i, item in enumerate(split_docs):
print("-"*50)
print(f"第{i+1}段字符数:{len(item.page_content)}")
print(f"第{i+1}段内容:{item.page_content}")
执行结果
使用技巧
1. 按 Token 数计算长度(适配大模型)
若需精准适配大模型的 tokens 限制(如 GPT-4o 的 128k tokens),可自定义长度函数:
import tiktoken
# 定义按 tokens 计算长度的函数
def count_tokens(text: str) -> int:
encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
return len(encoding.encode(text))
# 初始化分割器(按 tokens 拆分)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=4000, # 4000 tokens(GPT-3.5 上限)
chunk_overlap=200,
length_function=count_tokens, # 改用 tokens 计算长度
separators=["\n\n", "\n", "。", "!", "?", ",", ""]
)
2. 拆分纯文本(非 Document 对象)
若仅需拆分字符串(而非 Document),用 split_text() 方法:
# 拆分纯字符串
long_text = full_doc.page_content
split_texts = text_splitter.split_text(long_text)
print(f"拆分后文本片段数:{len(split_texts)}")
3. 保留片段索引(便于溯源)
开启 add_start_index,可在元数据中看到每个片段在原文的起始位置:
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=3000,
chunk_overlap=200,
add_start_index=True, # 开启起始索引
separators=["\n\n", "\n", "。", ""]
)
split_docs = text_splitter.split_documents([full_doc])
# 查看元数据中的起始索引
for doc in split_docs[:2]:
print(f"起始索引:{doc.metadata['start_index']}")
print(f"内容:{doc.page_content[:100]}...")
与其他分割器的对比
| 分割器类型 | 核心特点 | 适用场景 | 缺点 |
|---|---|---|---|
| RecursiveCharacterTextSplitter | 按语义递归拆分,适配中文 | 通用长文本、Word/PDF/CSV | 配置稍多(需指定分隔符) |
| CharacterTextSplitter | 简单按字符数硬截断 | 无结构纯文本 | 易切断语义 |
| TokenTextSplitter | 按 tokens 硬截断 | 精准适配大模型 tokens | 不考虑语义边界 |
| MarkdownHeaderTextSplitter | 按 Markdown 标题拆分 | Markdown 文档 | 仅适配 MD 格式 |
常见问题
| 问题 | 解决方案 |
|---|---|
| 中文拆分切断语义 | 配置中文专属 separators(优先按句号、换行拆分) |
| 拆分后片段仍过长 | 减小 chunk_size,或补充更低优先级的分隔符(如空字符串) |
| 重叠字符导致冗余 | 适当降低 chunk_overlap(如从 300 降到 100) |
| 计算长度不准确 | 改用 tiktoken 按 tokens 计算长度(而非字符数) |
总结
- 核心定位:
RecursiveCharacterTextSplitter是 LangChain 处理长文本的「通用最优解」,尤其适配中文场景; - 核心配置:重点调
chunk_size(适配大模型)、chunk_overlap(保证语义)、separators(中文分隔符); - 核心优势:按「自然语义边界」递归拆分,避免硬截断,是 RAG 场景拆分长文本的首选;
- 使用场景:搭配
Docx2txtLoader/PyPDFLoader/CSVLoader等加载器,拆分大文件文本后接入向量库。

