乐于分享
好东西不私藏

LangChain与你的数据对话:文档切分

LangChain与你的数据对话:文档切分
✂️LangChain与你的数据对话:文档切分

在将文档存入向量数据库之前,必须将其切分成更小的块。这不仅是为了适配模型的上下文限制,更是为了让检索到的内容更具"语义相关性"。

1. 为什么切分很困难?

简单的按字符数切分往往会破坏信息的完整性。

• 问题 A:一个句子可能在中间被切断,导致语义丢失。

• 问题 B:段落的上下文关系被剥离。

核心目标:保持具有相似语义的文本块在一起。

2. 切分的核心参数

在 LangChain 的所有切分器中,有两个关键参数:

1. Chunk Size (块大小):每个文本块包含的字符数(或 Token 数)。

2. Chunk Overlap (块重叠):相邻两个块之间共有的字符数。

* 作用:通过重叠来保持上下文的连续性,防止重要信息在切分点丢失。

3. 常见的切分器类型

A. CharacterTextSplitter (字符切分器)

最基础的切分器,按指定的字符(如 \\n\\n)进行切分。

缺点:非常生硬,容易忽略文本的层级结构。

B. RecursiveCharacterTextSplitter (递归字符切分器) —— 推荐使用

这是最常用的通用切分器。它尝试按一组字符(如 ["\\n\\n", "\\n", " ", ""])递归地切分。

• 逻辑:先尝试按段落切,如果块太大,再按句子切,最后按单词切。

• 优势:尽可能地保持段落和句子的完整。

C. TokenTextSplitter (Token 切分器)

按照模型实际处理的 Token 数量进行切分。

适用场景:当你需要严格控制发送给 LLM 的 Token 成本和限制时。

D. MarkdownHeaderTextSplitter (Markdown 标题切分器)

根据 Markdown 的层级标题(#,##,###)来切分。

优势:它能将标题信息自动加入到每个块的 Metadata 中,让模型知道这个块属于哪个章节。

4. 代码实现示例

以下展示了递归切分器的基本用法:

from langchain.text_splitter import RecursiveCharacterTextSplitter  

# 1. 准备长文本 

text = "..."  

# 2. 初始化切分器 

splitter = RecursiveCharacterTextSplitter(    

chunk_size=1000,     # 每个块 1000 字符     

chunk_overlap=150,   # 前后重叠 150 字符     

separators=["\\n\\n", "\\n", "(?<=\\. )", " ", ""] # 优先级排序 )  

# 3. 执行切分 

chunks = splitter.split_text(text)  

print(f"切分后的块数量: {len(chunks)}")

5. 关键点总结

特性

描述

语义维持

优先在自然换行处切分,比硬性数字切分更智能。

重叠的价值

就像滑窗一样,确保第一块结尾和第二块开头的信息是连贯的。

Metadata 传递

切分器通常会保留原始文档的 Metadata,并为每个块生成新的位置信息。

6. 进阶建议

1. 根据内容选工具:如果是代码,使用 Language.PYTHON 对应的切分器;如果是文档,使用递归切分器。

2. 可视化检查:在正式存入数据库前,打印几个块看看切分点是否合理(是否切断了核心论点)。

3. 结合 Metadata:使用 MarkdownHeaderTextSplitter 可以在检索时帮助模型区分"背景介绍"和"核心结论"。

:文档切分是 RAG 系统优化的"杠杆点"。合适的切分策略能显著减少模型的幻觉。