LangChain教程:RecursiveCharacterTextSplitter文本分割器(搭配Docx2txtLoader拆分word)

介绍

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类:

  1. 最后几段文本长度不足:
    当拆分到最后几个片段时,剩余文本的总长度 ≤ chunk_size + chunk_overlap,分割器会直接将剩余文本作为最后一段,不再强制重叠(否则会导致片段重复/长度超限)。
    例:chunk_size=3000、chunk_overlap=200,最后剩余文本仅 2500 字符 → 最后一段直接取 2500 字符,无后续片段,因此无重叠。

  2. 文本末尾无匹配的语义分隔符:
    分割器优先按「高优先级分隔符(空行/句号)」拆分,文本末尾若为无分隔符的连续文本,分割器会硬截断,导致重叠逻辑无法触发(仅按字符数拆分时,末尾易出现无重叠)。

  3. 重叠长度超过剩余文本长度:
    若剩余文本长度 < 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 计算长度(而非字符数)

总结

  1. 核心定位:RecursiveCharacterTextSplitter 是 LangChain 处理长文本的「通用最优解」,尤其适配中文场景;
  2. 核心配置:重点调 chunk_size(适配大模型)、chunk_overlap(保证语义)、separators(中文分隔符);
  3. 核心优势:按「自然语义边界」递归拆分,避免硬截断,是 RAG 场景拆分长文本的首选;
  4. 使用场景:搭配 Docx2txtLoader/PyPDFLoader/CSVLoader 等加载器,拆分大文件文本后接入向量库。

原文出处:/show_1GW2rPemHeV1.html