LangChain文本分割器详解

一、基础准备

from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter, RecursiveCharacterTextSplitter

# 加载文档
file_path = "./file/常见问题.txt"
text_load = TextLoader(file_path=file_path, encoding="utf-8")
docs = text_load.load()

# 假设常见问题.txt内容如下:
"""
欢迎使用我们的产品!

常见问题汇总:

问:如何注册账号?
答:点击首页右上角的注册按钮,填写手机号和验证码即可完成注册。

问:忘记密码怎么办?
答:在登录页面点击"忘记密码",通过手机验证码重置密码。

问:如何联系客服?
答:可以通过在线客服、客服电话400-123-4567或发送邮件到support@example.com联系我们。

技术支持电话:400-123-4567
服务时间:周一至周日 9:00-21:00
"""

二、CharacterTextSplitter的两种分割方式

方式1:禁用分隔符的字符级分割

for doc in docs:
    splitter = CharacterTextSplitter(
        chunk_size=50,
        chunk_overlap=5,
        separator=""  # 空字符串,禁用分隔符
    )
    contents = splitter.split_text(doc.page_content)
    for e, content in enumerate(contents):
        print(f"{e+1}{content}")

# 输出示例:
# 1、欢迎使用我们的产品!
# 
# 常见问题汇总:
# 
# 问:如何注册
# 2、册账号?
# 答:点击首页右上角的注册按钮,填写
# 3、写手机号和验证码即可完成注册。
# 
# 问:忘记密码
# 4、码怎么办?
# 答:在登录页面点击"忘记密码",通过
# 5、过手机验证码重置密码。
# 
# 问:如何联系
# 6、系客服?
# 答:可以通过在线客服、客服电话400-
# 7、-123-4567或发送邮件到support@exa
# 8、ample.com联系我们。
# 
# 技术支持电
# 9、电话:400-123-4567
# 服务时间:周一至周日 9:00-21:00

特点:简单粗暴,按字符数硬切,可能切断完整句子(如"注册"被切成"册"和"账号")

方式2:指定分隔符的段落级分割

for doc in docs:
    splitter = CharacterTextSplitter(
        chunk_size=150,  # 调小以便看到分割效果
        chunk_overlap=20,
        separator="\n\n"  # 按段落分割
    )
    contents = splitter.split_text(doc.page_content)
    for e, content in enumerate(contents):
        print(f"块 {e+1} (长度: {len(content)} 字符):")
        print(content)
        print("-" * 40)

# 输出示例:
# 块 1 (长度: 47 字符):
# 欢迎使用我们的产品!
# 
# 常见问题汇总:
# ----------------------------------------
# 块 2 (长度: 122 字符):
# 问:如何注册账号?
# 答:点击首页右上角的注册按钮,填写手机号和验证码即可完成注册。
# ----------------------------------------
# 块 3 (长度: 96 字符):
# 问:忘记密码怎么办?
# 答:在登录页面点击"忘记密码",通过手机验证码重置密码。
# ----------------------------------------
# 块 4 (长度: 148 字符):
# 问:如何联系客服?
# 答:可以通过在线客服、客服电话400-123-4567或发送邮件到support@example.com联系我们。
# 
# 技术支持电话:400-123-4567
# 服务时间:周一至周日 9:00-21:00
# ----------------------------------------

特点:先按段落切,保持语义完整,超过阈值才进一步切分

三、RecursiveCharacterTextSplitter递归分割

for doc in docs:
    splitter = RecursiveCharacterTextSplitter(
        chunk_size=100,  # 调小以便看到递归效果
        chunk_overlap=20,
        separators=["\n\n", "\n", "。", "?", ",", " ", ""],
        keep_separator=True,
        length_function=len,
    )
    contents = splitter.split_text(doc.page_content)
    for e, content in enumerate(contents):
        print(f"块 {e + 1} (长度: {len(content)} 字符):")
        print(content)
        print("-" * 40)

# 输出示例:
# 块 1 (长度: 47 字符):
# 欢迎使用我们的产品!
# 
# 常见问题汇总:
# ----------------------------------------
# 块 2 (长度: 98 字符):
# 问:如何注册账号?
# 答:点击首页右上角的注册按钮,填写手机号和验证码即可完成注册。
# ----------------------------------------
# 块 3 (长度: 96 字符):
# 问:忘记密码怎么办?
# 答:在登录页面点击"忘记密码",通过手机验证码重置密码。
# ----------------------------------------
# 块 4 (长度: 97 字符):
# 问:如何联系客服?
# 答:可以通过在线客服、客服电话400-123-4567或发送邮件到support@example.com联系我们。
# ----------------------------------------
# 块 5 (长度: 49 字符):
# 技术支持电话:400-123-4567
# 服务时间:周一至周日 9:00-21:00
# ----------------------------------------

在这里插入图片描述

特点:智能递归,优先按段落切,段落超长再按句子切,保持语义完整性

四、其他分割方式(补充)

1. TokenTextSplitter(按token数分割)

from langchain_text_splitters import TokenTextSplitter

text = "LangChain is a framework for developing applications powered by language models."
splitter = TokenTextSplitter(chunk_size=5, chunk_overlap=1)
chunks = splitter.split_text(text)

for i, chunk in enumerate(chunks):
    print(f"Chunk {i+1}: {chunk}")

# 输出示例:
# Chunk 1: LangChain is a framework for
# Chunk 2: for developing applications powered by
# Chunk 3: by language models.

2. MarkdownHeaderTextSplitter(保留层级)

from langchain_text_splitters import MarkdownHeaderTextSplitter

markdown_text = """
# 第一章:引言
这是引言内容...

## 1.1 背景
背景介绍...

## 1.2 目标
目标说明...

# 第二章:方法
方法介绍...
"""

headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
]

splitter = MarkdownHeaderTextSplitter(headers_to_split_on)
chunks = splitter.split_text(markdown_text)

for chunk in chunks:
    print(f"元数据: {chunk.metadata}")
    print(f"内容: {chunk.page_content[:30]}...")
    print("-" * 30)

# 输出示例:
# 元数据: {'Header 1': '第一章:引言'}
# 内容: 这是引言内容......
# ------------------------------
# 元数据: {'Header 1': '第一章:引言', 'Header 2': '1.1 背景'}
# 内容: 背景介绍......
# ------------------------------
# 元数据: {'Header 1': '第一章:引言', 'Header 2': '1.2 目标'}
# 内容: 目标说明......
# ------------------------------
# 元数据: {'Header 1': '第二章:方法'}
# 内容: 方法介绍......
# ------------------------------

3. PythonCodeTextSplitter(代码分割)

from langchain_text_splitters import PythonCodeTextSplitter

python_code = """
def hello_world():
    print("Hello, World!")
    
class Calculator:
    def add(self, a, b):
        return a + b
    
    def subtract(self, a, b):
        return a - b

# 主程序
if __name__ == "__main__":
    calc = Calculator()
    result = calc.add(5, 3)
    print(f"5 + 3 = {result}")
"""

splitter = PythonCodeTextSplitter(chunk_size=50, chunk_overlap=10)
chunks = splitter.split_text(python_code)

for i, chunk in enumerate(chunks):
    print(f"代码块 {i+1}:")
    print(chunk)
    print("-" * 30)

# 输出示例:
# 代码块 1:
# def hello_world():
#     print("Hello, World!")
# ------------------------------
# 代码块 2:
# class Calculator:
#     def add(self, a, b):
#         return a + b
# ------------------------------
# 代码块 3:
#     def subtract(self, a, b):
#         return a - b
# ------------------------------
# 代码块 4:
# # 主程序
# if __name__ == "__main__":
#     calc = Calculator()
#     result = calc.add(5, 3)
# ------------------------------
# 代码块 5:
#     print(f"5 + 3 = {result}")
# ------------------------------

五、优缺点对比

分割方式优点缺点适用场景
CharacterTextSplitter简单易用,控制精确语义完整性差测试、简单文本
RecursiveCharacterTextSplitter语义保留好,智能灵活性能略低通用场景(最常用)
TokenTextSplitter匹配LLM token限制可能切词LLM精确控制
MarkdownHeaderTextSplitter保留文档结构仅限markdown技术文档
CodeTextSplitter符合代码结构仅限代码代码处理

六、推荐使用

RecursiveCharacterTextSplitter 是最常用、最通用的选择,智能平衡语义和长度限制,适合大多数文本处理场景。从输出示例可以看出,它能较好地保持句子和段落的完整性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐