LangChain 文本分块详解
·
LangChain 文本分块详解
本文介绍为什么要对文本进行分块,以及如何使用 LangChain 实现文本分割。
1. 为什么需要文本分块?
1.1 上下文窗口限制
大语言模型(LLM)有固定的上下文窗口限制,例如:
- GPT-3.5 Turbo: 16,385 tokens
- GPT-4: 128,000 tokens
- Claude 3: 200,000 tokens
1.2 分块的优势
| 优势 | 说明 |
|---|---|
| 适应上下文限制 | 超过窗口限制的文本无法处理 |
| 提高检索精度 | 小块文本更容易匹配用户问题 |
| 降低 Token 成本 | 按需加载,减少不必要的消费 |
| 增强语义相关性 | 每块内容更聚焦,主题更明确 |
2. 安装依赖
!pip install langchain_text_splitters
3. 代码解析
3.1 完整代码
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档
loader = TextLoader("./demo.txt", encoding="utf-8")
docs = loader.load()
# 2. 创建分块器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块的最大字符数
chunk_overlap=40, # 块之间的重叠字符数
separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
)
# 3. 执行分块
texts = text_splitter.split_documents(docs)
结果:
3.2 核心参数详解
| 参数 | 说明 | 推荐值 |
|---|---|---|
chunk_size |
每块的最大字符数 | 300-1000 |
chunk_overlap |
相邻块之间的重叠字符数 | chunk_size 的 10-20% |
separators |
分隔符列表,按优先级排列 | 见下文 |
4. 分块策略
4.1 递归字符分块 (RecursiveCharacterTextSplitter)
RecursiveCharacterTextSplitter 是最常用的分块器,它会按顺序尝试每个分隔符:
separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
分隔符优先级:
| 优先级 | 分隔符 | 说明 |
|---|---|---|
| 1 | \n\n |
段落分隔(优先) |
| 2 | \n |
换行符 |
| 3 | 。 |
句号 |
| 4 | ! |
感叹号 |
| 5 | ? |
问号 |
| 6 | , |
逗号 |
| 7 | 、 |
顿号 |
| 8 | "" |
单字符(最后兜底) |
工作原理:
- 先按
\n\n分段 - 如果某段超过
chunk_size,按\n继续分割 - 如果还超限,按句子分隔符继续切割
- 最后按单字符分割
4.2 chunk_overlap 的作用
块1: [段落1 ....................] 500字符
块2: [..........40字符重叠.......段落2 ....] 500字符
块3: [..........40字符重叠.......段落3 ....]
为什么需要重叠?
- 避免上下文丢失
- 重要信息可能被切开,重叠能保证连续性
5. 其他分块器
5.1 简单字符分块
from langchain_text_splitters import CharacterTextSplitter
splitter = CharacterTextSplitter(
separator="\n",
chunk_size=500,
chunk_overlap=40
)
5.2 按 Token 分块(更精确)
from langchain_text_splitters import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=100, # 按 token 计算
chunk_overlap=20
)
5.3 Markdown 分块
from langchain_text_splitters import MarkdownTextSplitter
splitter = MarkdownTextSplitter(chunk_size=500)
6. 分块大小选择
6.1 根据用途选择
| 用途 | 建议 chunk_size | 说明 |
|---|---|---|
| 问答系统 | 500-1000 | 答案通常在几句话内 |
| 摘要生成 | 1000-2000 | 需要更多上下文 |
| 语义搜索 | 300-500 | 主题集中,检索更准 |
6.2 根据文档类型选择
| 文档类型 | 建议 chunk_size | 建议 overlap |
|---|---|---|
| 短文/新闻 | 300-500 | 20-50 |
| 技术文档 | 500-1000 | 50-100 |
| 书籍/长文 | 1000-2000 | 100-200 |
7. 完整示例
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档
loader = TextLoader("./demo.txt", encoding="utf-8")
docs = loader.load()
# 2. 配置分块器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=40,
separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
)
# 3. 执行分块
texts = text_splitter.split_documents(docs)
# 4. 查看结果
print(f"共分成 {len(texts)} 个块")
print(texts[0].page_content)
8. 常见问题
Q1: chunk_size 设置多大合适?
从 500 开始,根据实际效果调整。太小丢失上下文,太大检索不精准。
Q2: chunk_overlap 必须设置吗?
不是必须的,但建议设置。0-20% 的重叠能保证语义连续性。
Q3: 如何选择分隔符?
- 中文文档:使用中文标点符号
- 英文文档:使用
\n\n,\n, - 代码文件:使用
\n, 函数/类定义分隔符
Q4: 分割后如何查看每块内容?
for i, text in enumerate(texts):
print(f"=== 块 {i+1} ===")
print(text.page_content)
print()
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)