在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个非常关键的预处理步骤。LangChain 提供了多种灵活的文本切分器(TextSplitter
),可以帮助开发者根据实际需求对文本进行合理划分。
本文将围绕你在实际项目中使用的 TextSplitter
类型展开讲解,并结合具体代码示例,帮助你更好地理解如何选择和配置不同的文本切分策略。
TextSplitter
是 LangChain 中用于将长文本分割成小块(chunks)的一个工具类。它的核心作用是:
LangChain 提供了多种类型的 TextSplitter
,每种适用于不同的场景:
类名 | 说明 |
---|---|
RecursiveCharacterTextSplitter |
按照指定字符递归切分,默认按 [“\n\n”, “\n”, " ", “”] 切分 |
SpacyTextSplitter |
基于 SpaCy 的语言模型进行句子级切分 |
MarkdownHeaderTextSplitter |
专门用于 Markdown 格式文档,根据标题层级切分 |
TokenTextSplitter |
基于 Token 数量进行切分,常用于 GPT 系列模型 |
为了方便切换不同的切分器,我们可以先定义一个映射字典:
SPLITTER_CLASS_MAP = {
"RecursiveCharacterTextSplitter": RecursiveCharacterTextSplitter,
"SpacyTextSplitter": SpacyTextSplitter,
"MarkdownHeaderTextSplitter": MarkdownHeaderTextSplitter,
"TokenTextSplitter": TokenTextSplitter,
}
这样可以根据字符串名称动态获取对应的切分器类。
from_tiktoken_encoder
构建切分器TextSplitter = SPLITTER_CLASS_MAP["RecursiveCharacterTextSplitter"]
text_splitter = TextSplitter.from_tiktoken_encoder(
encoding_name=text_splitter_dict["RecursiveCharacterTextSplitter"]["tokenizer_name_or_path"],
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
这段代码使用的是 tiktoken
编码器来计算 token 数量,适用于 GPT-3/4 等 OpenAI 模型。其中:
encoding_name
: 指定使用的编码器(如 "cl100k_base"
);chunk_size
: 每个 chunk 的最大 token 数;chunk_overlap
: 相邻 chunk 的重叠 token 数。RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
这是最常用的方式,适用于大多数中文文本的切分任务,不依赖特定的 tokenizer,而是通过字符方式进行切分。
from transformers import GPT2TokenizerFast
from langchain.text_splitter import CharacterTextSplitter
tokenizer = GPT2TokenizerFast.from_pretrained("gpt2")
text_splitter_1 = TextSplitter.from_huggingface_tokenizer(
tokenizer=tokenizer,
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
这种方式适用于需要与 HuggingFace 模型配合使用的场景,比如 LLaMA、Bloom 等开源模型。它会根据 tokenizer 来精确控制每个 chunk 的 token 数量。
切分方式 | 特点 | 推荐场景 |
---|---|---|
RecursiveCharacterTextSplitter |
快速简单,支持自定义切分符 | 通用文本处理 |
SpacyTextSplitter |
支持多语言语义切分 | 英文为主、语义敏感任务 |
MarkdownHeaderTextSplitter |
按标题层级切分 | 文档类 Markdown 处理 |
TokenTextSplitter |
基于 token 数量切分 | 适配 GPT、LLM 输入限制 |
✅ 建议:如果你在处理中文文本,推荐优先使用
RecursiveCharacterTextSplitter
,并搭配合适的 chunk_size(如 512 或 1024)和 overlap(如 64)。
你提到的三个 TextSplitter
实例虽然都来自 LangChain 的 RecursiveCharacterTextSplitter
类,但它们使用了不同的初始化方式(构造方法),因此在底层处理文本的方式上也有所不同。下面我将详细分析这三者的区别:
你定义了一个映射字典:
SPLITTER_CLASS_MAP = {
"RecursiveCharacterTextSplitter": RecursiveCharacterTextSplitter,
...
}
然后通过字符串名称获取类并创建实例:
TextSplitter = SPLITTER_CLASS_MAP["RecursiveCharacterTextSplitter"]
text_splitter = TextSplitter.from_tiktoken_encoder(...)
接着又分别使用了三种不同方式创建了三个 splitter
实例:
text_splitter
: 使用 .from_tiktoken_encoder(...)
splitter
: 直接使用默认构造函数 RecursiveCharacterTextSplitter(...)
text_splitter_1
: 使用 .from_huggingface_tokenizer(...)
这三个 splitter 都是 RecursiveCharacterTextSplitter
的实例,但它们的底层分词逻辑和 chunk 大小控制机制不同。
text_splitter = TextSplitter.from_tiktoken_encoder(...)
text_splitter = TextSplitter.from_tiktoken_encoder(
encoding_name="cl100k_base",
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
chunk_size
是以 token 数量 为单位;⚠️ 注意:tiktoken 的 token 划分方式不同于传统的空格或句子划分,它会将中英文混合切分为 subwords 或 bytes。
"你好 world" -> ["你", "好", "Ġworld"]
splitter = RecursiveCharacterTextSplitter(...)
splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
\n\n
, \n
, " "
, ""
);text = "这是一个很长的段落..."
splitter.split_text(text)
# 输出:["这是...", "...下一段"]
text_splitter_1 = RecursiveCharacterTextSplitter.from_huggingface_tokenizer(...)
tokenizer = GPT2TokenizerFast.from_pretrained("gpt2")
text_splitter_1 = RecursiveCharacterTextSplitter.from_huggingface_tokenizer(
tokenizer=tokenizer,
chunk_size=CHUNK_SIZE,
chunk_overlap=OVERLAP_SIZE
)
chunk_size
也是以 token 数量 为单位;⚠️ 注意:这种方式需要安装 transformers 库,并且加载 tokenizer 可能较慢。
属性 | from_tiktoken_encoder(...) |
__init__(...) |
from_huggingface_tokenizer(...) |
---|---|---|---|
切分依据 | token 数量(tiktoken 编码器) | 字符长度 | token 数量(HuggingFace tokenizer) |
是否依赖 tokenizer | 是(tiktoken) | 否 | 是(transformers) |
chunk_size 单位 | token | char | token |
中文支持 | 视 encoding 而定(一般较好) | ✔️ 很好 | 视 tokenizer 而定 |
典型用途 | GPT-3/4 类模型适配 | 通用文本处理 | 开源 LLM(如 LLaMA、GPT-Neo)适配 |
性能 | 快速 | 极快 | 较慢(需加载 tokenizer) |
场景 | 推荐方式 |
---|---|
使用 OpenAI GPT-3/4 API | from_tiktoken_encoder |
中文文档处理、快速构建本地知识库 | __init__() |
使用开源 LLM(如 LLaMA、Bloom、GPT-Neo) | from_huggingface_tokenizer |
需要严格控制 token 数量 | 后两者均可(根据 tokenizer) |
如果你使用的是中文场景,推荐如下组合:
splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "\n", "。", "!", "?", ",", " ", ""],
chunk_size=512,
chunk_overlap=64
)
你可以自定义 separators
,让它更适合中文语义断句。