吴恩达《LangChain LLM 应用开发精读笔记》9-Document Splitting 文档拆分
·

大家好,我是飞哥!👋
欢迎来到吴恩达《LangChain:Chat with Your Data》系列课程的第三讲。上一讲我们把文档加载进来了,今天我们要进行关键的一步:Document Splitting (文档拆分)。
1. 为什么:切不好,AI 就吃不消 🍽️
💡 场景锚定
你给 AI 喂书,不能整本塞进去。
- 胃口有限:大模型的上下文窗口(Context Window)是有限的(比如 GPT-3.5 只有 4k/16k token)。
- 消化不良:就算塞进去了,太长的文本会让 AI 抓不住重点(Lost in the Middle 现象)。
⚠️ 核心痛点
所以,我们必须把长文档切成小块(Chunks)。但切分不是简单的“数数”。
- 切坏了:把“我爱”和“你”切到了两个块里,AI 就不知道谁爱谁了。
- 切好了:既要块小,又要保持句子的语义完整性。
2. 是什么:LangChain 的拆分策略 ✂️
LangChain 提供了多种拆分器(Text Splitters),核心参数通常有两个:
- chunk_size: 每个块的大小(字符数或 Token 数)。
- chunk_overlap: 重叠部分的大小。这是关键!就像接力赛跑的交接棒区,确保上下文不会在切分点丢失。
🦴 骨架图
原始文档: "人工智能(AI)是模拟人类智能过程的计算机系统。这些过程包括..."
|
v
[拆分器 (Splitter)] --(Size=20, Overlap=5)-->
|
|-- 块1: "人工智能(AI)是模拟人类智能过程的计算机系统"
|
|-- 块2: "过程的计算机系统。这些过程包括..." <-- 注意这里的重叠!
3. 怎么用:实战代码 💻
3.1 基础字符拆分 (CharacterTextSplitter) 🔡
最简单粗暴的方法,按字符数硬切。
from langchain_text_splitters import CharacterTextSplitter
text = "人工智能(AI)是模拟人类智能过程的计算机系统。这些过程包括学习、推理和自我修正。"
# 初始化拆分器
splitter = CharacterTextSplitter(
separator="。", # 分隔符:尝试按中文句号切分
chunk_size=20, # 块大小:每个块最大字符数
chunk_overlap=5 # 重叠大小:相邻块之间重叠的字符数(保持上下文)
)
chunks = splitter.split_text(text)
# 输出:
# 块 0: 人工智能(AI)是模拟人类智能过程的计算机系统
# 块 1: 这些过程包括学习、推理和自我修正
3.2 递归字符拆分 (RecursiveCharacterTextSplitter) 🔄 (推荐)
这是最常用的拆分器。它很聪明,会尝试按顺序使用一组分隔符 ["\n\n", "\n", " ", ""] 来切分。
- 先看能不能按段落(双换行)切?
- 不行就按句子(单换行)切?
- 还不行就按单词(空格)切?
这样能最大程度保留语义的完整性。
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_long = """
第一章:什么是大模型?
大模型是基于深度学习的海量参数模型。它们在自然语言处理领域取得了巨大成功。
第二章:大模型的核心技术
大模型的核心是 Transformer 架构。通过自注意力机制,模型可以理解长距离的上下文关系。
"""
# 初始化递归拆分器
recursive_splitter = RecursiveCharacterTextSplitter(
chunk_size=50, # 每个块的目标大小
chunk_overlap=10, # 块之间的重叠大小
separators=["\n\n", "\n", " ", ""] # 拆分优先级:段落 -> 句子 -> 空格 -> 字符
)
chunks = recursive_splitter.split_text(text_long)
# 输出: 保持了段落的完整性
3.3 Token 拆分 (TokenTextSplitter) 🪙
大模型是按 Token 计费和处理的。如果你对 Token 数限制很严格,可以用这个。
注意:中文在 Tokenizer 里可能会被切成乱码,使用时需小心。
3.4 Markdown 拆分 (MarkdownHeaderTextSplitter) 📑
如果你的文档是 Markdown 格式,这个神器可以按标题(Header)来切分,并且把标题保留在 Metadata 里!这对于 RAG 检索非常有帮助,因为标题往往包含了关键的上下文。
from langchain_text_splitters import MarkdownHeaderTextSplitter
markdown_document = "# 标题1\n\n## 章节1.1\n内容A\n\n## 章节1.2\n内容B"
# 定义要拆分的标题级别和对应的 Metadata 键名
headers_to_split_on = [
("#", "Header 1"), # 一级标题 -> Metadata['Header 1']
("##", "Header 2") # 二级标题 -> Metadata['Header 2']
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
splits = splitter.split_text(markdown_document)
print(splits[0].page_content) # 输出: 内容A
print(splits[0].metadata) # 输出: {'Header 1': '标题1', 'Header 2': '章节1.1'}
📝 飞哥总结
- Recursive 是首选:90% 的情况下,直接用
RecursiveCharacterTextSplitter,它最懂人类语言的结构。 - Overlap 不能省:一定要设置
chunk_overlap,否则切分边缘的信息会丢失。 - 结构化拆分:如果文档有结构(如 Markdown, HTML),尽量用对应的结构化拆分器,把标题信息存入元数据。
一句话记住它 💡:文档拆分就像切牛排,切得大小适中且不切断纹理(语义),AI 才能吃得香、消化好!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)