前言
在前面的学习中,我们已经掌握了LangChain的文档加载器(Document Loaders)功能,它能够从多种来源(包括本地文件、网页、数据库等)加载文档并提取内容。文档加载只是处理长文本的第一步,为了更好地与大语言模型交互,我们还需要解决长文本的分割问题
本文将深入探讨LangChain中的文本分割器(Text Splitters)组件,学习如何将长文本智能分割为适合模型处理的小块
文本分割器 (Text Splitters)
文本分割器作用将长文本分割成适合语言模型处理的小块,解决大模型上下文窗口限制的问题
可以用在文档处理、RAG系统、代码分析等场景
RAG系统(Retrieval-Augmented Generation)是一种结合了检索和生成的模型,用于回答用户问题。它通过从外部知识库中检索相关信息,然后使用这些信息来生成回答
字符分割器
最基础的分割器,按照固定的分隔符进行分割,简单直接,但可能不够智能,有时会切断语义
例如下面代码使用 CharacterTextSplitter 函数创建分割器
splitter.split_text 用于将文本分割成多个块,返回一个数组
# 导入所需的库
from langchain_text_splitters import CharacterTextSplitter # 字符分割器
# 示例文本数据
SAMPLE_TEXT = """
人工智能(Artificial Intelligence,AI)是计算机科学的一个分支,致力于创建能够执行通常需要人类智能的任务的系统。
机器学习是人工智能的一个子集,它使计算机能够在没有明确编程的情况下学习和改进。机器学习算法通过分析数据来识别模式,并基于这些模式做出决策或预测。
深度学习是机器学习的一个子集,它使用人工神经网络来模拟人脑的学习过程。深度学习在图像识别、自然语言处理和语音识别等领域取得了突破性进展。
自然语言处理(NLP)是人工智能的一个重要分支,专注于计算机与人类语言之间的交互。NLP技术使计算机能够理解、解释和生成人类语言。
计算机视觉是另一个重要的AI分支,专注于使计算机能够从数字图像或视频中获取有意义的信息。计算机视觉技术广泛应用于自动驾驶、医疗诊断和安防监控等领域。
"""
def main():
"""
主函数:演示字符分割器的使用
"""
print("🚀 字符分割器演示")
print("=" * 60)
# 创建分割器实例 - 使用双换行作为分隔符
splitter = CharacterTextSplitter(
separator="\n\n", # 使用双换行作为分隔符,按段落分割
chunk_size=300, # 每个块的最大字符数
chunk_overlap=50, # 块之间的重叠字符数
length_function=len # 计算长度的函数
)
print("分割器配置:")
print(f"- 分隔符: '\\n\\n' (双换行)")
print(f"- 块大小: {splitter._chunk_size} 字符")
print(f"- 重叠大小: {splitter._chunk_overlap} 字符")
# 分割文本
chunks = splitter.split_text(SAMPLE_TEXT)
print(f"\n原始文本长度: {len(SAMPLE_TEXT)} 字符")
print(f"分割后块数: {len(chunks)}")
print(f"每个块的内容:")
# 显示每个分割块的内容
for i, chunk in enumerate(chunks):
print(f"\n--- 块 {i+1} (长度: {len(chunk)}) ---")
# 如果块太长,只显示前100个字符
if len(chunk) > 100:
print(chunk[:100] + "...")
else:
print(chunk)
# 演示不同分隔符的效果
print(f"\n🔧 不同分隔符对比演示:")
# 使用句号作为分隔符
sentence_splitter = CharacterTextSplitter(
separator="。",
chunk_size=200,
chunk_overlap=30
)
sentence_chunks = sentence_splitter.split_text(SAMPLE_TEXT)
print(f"- 句号分隔: {len(sentence_chunks)} 个块")
# 使用空格作为分隔符
space_splitter = CharacterTextSplitter(
separator=" ",
chunk_size=100,
chunk_overlap=20
)
space_chunks = space_splitter.split_text(SAMPLE_TEXT)
print(f"- 空格分隔: {len(space_chunks)} 个块")
# 不使用分隔符(强制按长度分割)
force_splitter = CharacterTextSplitter(
separator="", # 空分隔符,强制按chunk_size分割
chunk_size=150,
chunk_overlap=0
)
force_chunks = force_splitter.split_text(SAMPLE_TEXT)
print(f"- 强制分割: {len(force_chunks)} 个块")
...
代码示例运行效果可以看到数据被分成了一段段的
Markdown分割器
Markdown分割器专门用于分割Markdown文档,会保持Markdown的结构完整性,会识别标题、列表、代码块等Markdown元素,确保分割不会破坏文档结构
就像按章节分割书籍,保持每个章节的完整性
# 导入所需的库
from langchain_text_splitters import MarkdownTextSplitter # Markdown分割器
# Markdown示例文本
MARKDOWN_TEXT = """
# LangChain文本分割器指南
## 什么是文本分割器?
文本分割器是将长文本分割成更小、更易管理块的组件。这在处理长文档、提高检索质量、控制token使用等场景非常重要。
## 为什么需要文本分割?
### 1. Token限制
语言模型有输入长度限制,长文本需要分割才能处理。
### 2. 检索质量
小块文本更容易精确匹配,提高检索准确性。
### 3. 处理效率
小块文本处理更快,节省计算资源。
"""
def main():
"""
主函数:演示Markdown分割器的使用
"""
print("🚀 Markdown分割器演示")
print("=" * 60)
# 创建分割器实例
splitter = MarkdownTextSplitter(
chunk_size=200, # 每个块的最大字符数
chunk_overlap=30 # 块之间的重叠字符数
)
print("分割器配置:")
print(f"- 块大小: {splitter._chunk_size} 字符")
print(f"- 重叠大小: {splitter._chunk_overlap} 字符")
print(f"- 专门处理: Markdown文档")
# 分割Markdown文本
chunks = splitter.split_text(MARKDOWN_TEXT)
print(f"\n原始Markdown文本长度: {len(MARKDOWN_TEXT)} 字符")
print(f"分割后块数: {len(chunks)}")
print(f"每个块的内容:")
# 显示每个分割块的内容
for i, chunk in enumerate(chunks):
print(f"\n--- 块 {i+1} (长度: {len(chunk)}) ---")
print(chunk)
print("--- 块结束 ---")
# 分析Markdown结构保持情况
print(f"\n📊 Markdown结构分析:")
...
代码执行后的输出
Python代码分割器
专门用于分割Python代码,会保持代码的语法结构完整性。会识别函数、类、导入语句等Python语法元素,确保分割不会破坏代码结构
使用 langchain_text_splitters 中的 PythonCodeTextSplitter 类来实现Python代码的分割,其他操作和上面列子类似
由于代码没有什么特殊的地方,从这里开始以及后面的内容就不贴了
递归字符分割器演示
最常用的文本分割器,会递归地尝试不同的分隔符来分割文本。例如句号、换行符、问号等。按照分隔符的优先级顺序进行分割,确保文本块的完整性
使用 langchain_text_splitters 中的 RecursiveCharacterTextSplitter 类来实现递归字符分割
Token分割器
Token分割器基于Token数量而不是字符数来分割文本。这对于控制语言模型的输入长度非常重要,因为大多数LLM都有Token限制
Token是语言模型的基本处理单位,通过控制Token数量可以更精确地控制模型的输入长度,避免超出限制
使用 langchain_text_splitters 中的 TokenTextSplitter 类来实现Token分割
语义分割方法
基于嵌入相似度的语义分割方法。通过计算文本块之间的语义相似度,可以更智能地进行文本分割和聚类。
通俗理解就像按主题相关性来分段,而不是简单的按长度,相似的内容放在一起,不相关的分开,基于语义理解,而不是表面字符
这种需要语义理解的部分需要模型的支持
小结
不同的分割器适用于不同的场景,需要根据具体需求选择合适的分割器,在实际场景中处理时也需要比较不同文本分割器的性能表现,包括分割时间、生成块数、平均块大小等指标
文本分割器相关内容就到这里了,接下来学习嵌入(Embeddings)
欢迎留言交流,如果觉得有帮助,可以
点个赞支持一下公众号:草帽lufei