长 PDF 整页 embedding 会稀释语义,检索时只命中整页噪声。TextSplitter 把 Document 切成更小 chunk,在 上下文长度 与 语义完整 之间折中。LangChain 将切分器独立为 langchain-text-splitters 包,与 Loader、VectorStore 串联。
段末注释:TextSplitter(文本切分器)= 按字符/token/结构把长文本拆成多个 Document 的组件。
1. 一句话定位
| 维度 | 内容 |
|---|---|
| 角色 | 能力层 索引前处理:长 Document → 多个小 Document |
| 输入 → 输出 | list[Document] 或 str → list[Document] |
| 典型调用入口 | splitter.split_documents(docs)、split_text(text) |
| 与 LangGraph | 切分多在离线 ETL;在线 Agent 偶发动态切分 |
2. 实现逻辑
1 | 1. loader.load() → list[Document](可能一页一条) |
字段级变形:
1 | Document(page_content="AAAA...2000字...", metadata={page:1}) |
3. 原理说明
3.1 RecursiveCharacterTextSplitter
RecursiveCharacterTextSplitter(类,langchain_text_splitters)
功能:按分隔符列表从粗到细递归切,尽量在段落边界断开。
| 参数 | 类型 | 默认值 | 最小维度 |
|---|---|---|---|
chunk_size |
int | 1000 |
≥1;须 > chunk_overlap |
chunk_overlap |
int | 200 |
≥0;0=不重叠 |
length_function |
callable | len(字符) |
返回非负 int |
separators |
list[str] | ["\n\n", "\n", " ", ""] |
len≥1,最后常为 "" 保底 |
keep_separator |
bool | False |
— |
is_separator_regex |
bool | False |
— |
split_text(text: str)(方法)
最小输入:任意 str(含空串 → [] 或 [''] 视实现);短于 chunk_size 则返回 len=1。
1 | splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20) |
split_documents(documents)(方法)
功能:切 Document 并复制 metadata 到各 chunk。
最小维度:documents len≥1。
1 | chunks = splitter.split_documents([Document(page_content=text, metadata={"source": "a.md"})]) |
3.2 chunk_overlap
相邻 chunk 共享尾/头部,避免句子在边界被截断。overlap 过大则索引冗余。
最小有意义:0 ≤ overlap < chunk_size;overlap=0 语法合法但易断句。
3.3 结构化切分
MarkdownHeaderTextSplitter(类)
功能:按 Markdown 标题切,标题写入 metadata。
默认值:headers_to_split_on 必填。最小:至少 1 个 (级别, 元数据键),如 [("#", "h1")]。
1 | from langchain_text_splitters import MarkdownHeaderTextSplitter |
代码可用 RecursiveCharacterTextSplitter.from_language(Language.PYTHON, ...),Language 为枚举。
3.4 与 RAG 方法论
切分影响召回率与答案完整性;评测与业务架构不在本篇。本篇只讲 API。
4. 最小可运行示例
1 | pip install -U langchain-text-splitters langchain-core |
1 | from langchain_core.documents import Document |
纯字符串:
1 | parts = splitter.split_text("短文本无需切分。") |
重要配置参数
| 参数(API 名) | 类型 / 默认值 | 功能说明 | 作用与影响 | 参考起点 | 配置指导 |
|---|---|---|---|---|---|
chunk_size |
int,默认 1000 | 单块最大长度(默认按字符,可换 token 计数) | 过大超 embedding 窗;过小语义破碎 | 300~1000 字符 | 代码库偏小;FAQ 可大 |
chunk_overlap |
int,默认 200 | 相邻块首尾重叠多少,避免句子被切断 | 过大索引冗余、存储涨;0 易断句 | chunk_size 的 10%~20% | 必须 < chunk_size |
length_function |
callable,默认 len |
用什么函数量「长度」 | 改成 tiktoken 后 chunk_size 含义变成 token | len / tiktoken | 按 token 切更贴近模型窗 |
separators |
list[str],默认段落→行→空格→空串 | 从粗到细尝试的切分优先级 | 中文可保留 \n\n;最后 "" 保底硬切 |
默认即可 | 不要删掉最后的 "" |
keep_separator |
bool,默认 False | 切分后是否把分隔符留在块里 | True 可保留 Markdown 标题标记 | False | 需标题进 metadata 时另用 Header splitter |
is_separator_regex |
bool,默认 False | 把 separators 当正则而非字面量 | True 写错正则会切出意外块 | False | 复杂结构才开 |
5. 易踩坑
- chunk 过大仍超 embedding 模型输入上限:需在 splitter 层压长度。
- split 丢 metadata:用
split_documents而非split_text+手动组,除非自行复制 metadata。 - overlap=0 且 chunk 边界在表格/代码中间:检索到半表半码,模型胡答。
小结
- RecursiveCharacterTextSplitter 是最常用的通用切分器。
- chunk_size / chunk_overlap 是 RAG 质量的一阶旋钮。
- 切分输出仍是 Document,直接
add_documents。 - 策略评测与业务切分见 RAG 目录。