深入理解LangChain文本分割器:从原理到实践

59 阅读7分钟

前言

在前面的学习中,我们已经掌握了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