【LangChain】langchain.text_splitter 模块:文本分割器

在 LangChain 中,langchain.text_splitter 模块提供了一系列工具类,用于将长文本分割成较小的块(chunks),以便于处理、嵌入生成或存储到向量数据库。该模块是构建检索增强生成(RAG)系统、文档索引或其他需要文本预处理的场景中的关键组件。

本文基于 LangChain 0.3.x,全面介绍 langchain.text_splitter 模块中的所有文本分割器,列出其功能、参数、适用场景,并提供代码示例,展示如何在 RAG 系统中使用不同分割器(以 RecursiveCharacterTextSplitter 为例,扩展 CharacterTextSplitter)。


langchain.text_splitter 模块概述

langchain.text_splitter 模块包含多种文本分割器(TextSplitter 的子类),用于将长文本或文档分割为适合嵌入模型(如 OpenAIEmbeddings)或语言模型(LLM)处理的块。分割器的核心目标是:

  • 适配输入限制:确保每个块的长度适合嵌入模型或 LLM 的输入限制(通常 500-2000 字符或 token)。
  • 保留上下文:通过重叠(chunk_overlap)或其他语义分割策略,防止信息丢失。
  • 支持多样性:处理不同类型的文本,如纯文本、代码、Markdown、HTML 等。

核心类

  • TextSplitter:所有分割器的基类,提供 split_textsplit_documents 方法。
  • 具体分割器:如 CharacterTextSplitterRecursiveCharacterTextSplitter 等,针对不同场景优化。

主要方法

  • split_text(text: str) -> List[str]:将字符串分割为块列表。
  • split_documents(documents: List[Document]) -> List[Document]:将 Document 对象分割为更小的 Document 对象。
  • create_documents(texts: List[str], metadatas: Optional[List[dict]] = None) -> List[Document]:从文本列表创建并分割 Document 对象。

典型应用

  • 文档预处理:将长文档分割为小块,生成嵌入向量,存储到向量数据库(如 Chroma、FAISS)。
  • RAG 管道:为检索提供合适的文本块,确保相关性。
  • 文本分析:将大文本分解为可管理的部分。

langchain.text_splitter 模块中的所有分割器

以下是 langchain.text_splitter 模块中的所有文本分割器(截至 LangChain 0.3.x),共 12 种,基于源码(langchain/text_splitter.py)和官方文档(Text Splitters)。按类型分类,详细说明功能、参数、适用场景,并指出推荐使用的分割器。

1. 通用文本分割器

这些分割器适用于通用文本,基于字符或 token 计数。

  1. CharacterTextSplitter

    • 功能:按字符数或指定分隔符(如 \n)分割文本。
    • 参数
      • chunk_size(默认 1000):最大块大小(字符)。
      • chunk_overlap(默认 200):块间重叠字符数。
      • separator(默认 \n):分隔符。
      • strip_whitespace(默认 True):去除首尾空白。
      • length_function(默认 len):长度计算函数。
    • 适用场景:简单文本分割,不需要复杂语义。
    • 局限性:可能截断句子或段落,语义不连续。
    • 示例
      from langchain.text_splitter import CharacterTextSplitter
      splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=20, separator="\n")
      
  2. RecursiveCharacterTextSplitter

    • 功能:递归尝试多种分隔符(如段落、句子、单词),优先保留语义边界。
    • 参数
      • chunk_size(默认 1000):最大块大小。
      • chunk_overlap(默认 200):重叠大小。
      • separators(默认 ["\n\n", "\n", " ", ""]):分隔符列表,按顺序尝试。
      • length_function(默认 len):长度计算函数。
      • is_separator_regex(默认 False):分隔符是否为正则表达式。
    • 适用场景:通用文本(如文章、书籍),需要保留语义边界。
    • 推荐:最常用的分割器,适合大多数 RAG 场景。
    • 示例
      from langchain.text_splitter import RecursiveCharacterTextSplitter
      splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
      
  3. TokenTextSplitter

    • 功能:按 token 计数分割,基于指定的分词器(如 tiktoken)。
    • 参数
      • chunk_size(默认 1000):最大 token 数。
      • chunk_overlap(默认 0):重叠 token 数。
      • encoding_name(默认 cl100k_improved):分词器编码(如 OpenAI 的 tiktoken)。
    • 适用场景:严格遵循 LLM 的 token 限制(如 GPT 模型)。
    • 局限性:需要安装 tiktoken,对非 token 化文本不直观。
    • 示例
      from langchain.text_splitter import TokenTextSplitter
      splitter = TokenTextSplitter(chunk_size=200, chunk_overlap=50, encoding_name="cl100k_improved")
      
2. 代码分割器

这些分割器针对编程语言或代码文件优化。

  1. LanguageTextSplitter

    • 功能:根据编程语言的语法(如 Python、JavaScript)分割代码。
    • 参数
      • language(必填):语言类型(如 python, javascript)。
      • chunk_size(默认 1000):最大块大小。
      • chunk_overlap(默认 200):重叠大小。
    • 适用场景:处理代码文件,保留函数、类等结构。
    • 支持语言:Python, JavaScript, Java, C++, Go 等(见 langchain.text_splitter 文档)。
    • 示例
      from langchain.text_splitter import LanguageTextSplitter
      splitter = LanguageTextSplitter(language="python", chunk_size=500, chunk_overlap=100)
      
  2. PythonCodeTextSplitter

    • 功能:专为 Python 代码优化,基于语法树分割(如函数、类)。
    • 参数
      • chunk_size(默认 1000):最大块大小。
      • chunk_overlap(默认 200):重叠大小。
    • 适用场景:Python 代码分析、文档生成。
    • 示例
      from langchain.text_splitter import PythonCodeTextSplitter
      splitter = PythonCodeTextSplitter(chunk_size=500, chunk_overlap=100)
      
3. 格式化文档分割器

这些分割器针对特定格式(如 Markdown、HTML、LaTeX)。

  1. MarkdownHeaderTextSplitter

    • 功能:基于 Markdown 标题(如 #, ##)分割,保留标题作为元数据。
    • 参数
      • headers_to_split_on(必填):标题和分隔符列表(如 [("#", "Header 1"), ("##", "Header 2")])。
      • strip_headers(默认 True):是否移除标题内容。
    • 适用场景:Markdown 文档(如 GitHub README、文档站点)。
    • 示例
      from langchain.text_splitter import MarkdownHeaderTextSplitter
      splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("#", "Header 1"), ("##", "Header 2")])
      
  2. MarkdownTextSplitter

    • 功能:继承 RecursiveCharacterTextSplitter,使用 Markdown 特定的分隔符(如 \n# , \n- )。
    • 参数
      • RecursiveCharacterTextSplitter,分隔符默认为 Markdown 结构。
    • 适用场景:Markdown 文件,保留结构化信息。
    • 示例
      from langchain.text_splitter import MarkdownTextSplitter
      splitter = MarkdownTextSplitter(chunk_size=500, chunk_overlap=100)
      
  3. HTMLTextSplitter

    • 功能:基于 HTML 标签(如 <p>, <div>)分割,保留标签作为元数据。
    • 参数
      • chunk_size(默认 1000):最大块大小。
      • chunk_overlap(默认 0):重叠大小。
      • tags_to_split_on(默认 ["p", "div", "h1", ...]):分割标签。
    • 适用场景:网页内容、HTML 文档。
    • 示例
      from langchain.text_splitter import HTMLTextSplitter
      splitter = HTMLTextSplitter(chunk_size=500, chunk_overlap=100)
      
  4. LatexTextSplitter

    • 功能:基于 LaTeX 命令(如 \section, \subsection)分割。
    • 参数
      • RecursiveCharacterTextSplitter,分隔符为 LaTeX 特定(如 \n\\section, \n\\subsection)。
    • 适用场景:学术论文、LaTeX 文档。
    • 示例
      from langchain.text_splitter import LatexTextSplitter
      splitter = LatexTextSplitter(chunk_size=500, chunk_overlap=100)
      
4. 语义分割器

这些分割器基于语义或嵌入进行分割。

  1. SemanticChunker
    • 功能:使用嵌入模型(如 OpenAIEmbeddings)计算语义相似性,分割为语义相近的块。
    • 参数
      • embeddings(必填):嵌入模型实例。
      • breakpoint_threshold_type(默认 "percentile"):分割阈值类型(如百分位、标准差)。
      • breakpoint_threshold_amount(默认 95):阈值大小。
    • 适用场景:需要语义连续的场景,如长篇文章。
    • 局限性:计算开销高,依赖嵌入模型。
    • 示例
      from langchain.text_splitter import SemanticChunker
      from langchain_openai import OpenAIEmbeddings
      splitter = SemanticChunker(OpenAIEmbeddings(), breakpoint_threshold_type="percentile")
      
5. 其他专用分割器

这些分割器针对特定用例。

  1. SpacyTextSplitter

    • 功能:使用 SpaCy 分词器按句子分割。
    • 参数
      • chunk_size(默认 1000):最大块大小(字符)。
      • chunk_overlap(默认 0):重叠大小。
      • pipeline(默认 "en_core_web_sm"):SpaCy 模型。
    • 适用场景:需要按句子分割的自然语言处理任务。
    • 局限性:需要安装 SpaCy 和模型(如 pip install spacypython -m spacy download en_core_web_sm)。
    • 示例
      from langchain.text_splitter import SpacyTextSplitter
      splitter = SpacyTextSplitter(chunk_size=500, pipeline="en_core_web_sm")
      
  2. NLTKTextSplitter

    • 功能:使用 NLTK 的句子分词器分割。
    • 参数
      • chunk_size(默认 1000):最大块大小。
      • chunk_overlap(默认 200):重叠大小。
      • separator(默认 \n):分隔符。
    • 适用场景:基于句子的文本分割,适合学术或通用文本。
    • 局限性:需要安装 NLTK(pip install nltk)并下载分词器(如 nltk.download('punkt'))。
    • 示例
      from langchain.text_splitter import NLTKTextSplitter
      splitter = NLTKTextSplitter(chunk_size=500, chunk_overlap=100)
      

推荐与选择指南

  • 通用推荐RecursiveCharacterTextSplitter 是最通用的分割器,适合大多数文本类型(如文章、文档),优先保留段落、句子等语义边界。
  • 代码PythonCodeTextSplitterLanguageTextSplitter 适合代码文件。
  • 格式化文档MarkdownHeaderTextSplitter(Markdown)、HTMLTextSplitter(网页)、LatexTextSplitter(学术)。
  • 语义分割SemanticChunker 适合需要语义连续的场景,但计算成本高。
  • 按 tokenTokenTextSplitter 适合严格遵循 LLM token 限制。
  • 按句子SpacyTextSplitterNLTKTextSplitter 适合 NLP 任务。

参数建议

  • chunk_size:500-2000 字符或 token,适配嵌入模型(如 text-embedding-3-small 的 8192 token 限制)。
  • chunk_overlap:10-20% 的 chunk_size(如 50-200),确保上下文连续性。
  • 分隔符:根据文本类型选择(如 Markdown 用 #,代码用函数边界)。

结合 RAG 系统的使用

在RAG 系统中构建多轮对话的知识库问答系统。langchain.text_splitter 的分割器用于预处理文档,生成适合向量存储的块。以下示例使用 RecursiveCharacterTextSplitter(推荐的通用分割器),并迁移到 LCEL 链,延续 CharacterTextSplitter 示例。

LCEL RAG 示例

以下代码展示如何使用 RecursiveCharacterTextSplitter 分割文档,结合 LCEL 链实现 RAG,包含问题浓缩(模拟 condense_question_llm)和对话历史管理。

import os
os.environ["OPENAI_API_KEY"] = "Your OpenAI API Key"

from operator import itemgetter
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.documents import Document

# 原始文档
texts = [
    """人工智能(AI)是计算机科学的一个分支,专注于创建智能系统。
机器学习是 AI 的子领域,涉及从数据中学习模型。
深度学习是机器学习的一种,使用神经网络进行复杂模式识别。
生成式 AI 是 AI 的新兴领域,专注于生成文本、图像等内容。"""
]

# 使用 RecursiveCharacterTextSplitter 分割文档
splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20,
    separators=["\n\n", "\n", " ", ""]
)
documents = [Document(page_content=text) for text in splitter.split_text(texts[0])]

# 初始化嵌入模型和向量存储
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(documents, embeddings)

# 初始化 LLM
main_llm = ChatOpenAI(temperature=0, model="gpt-4")
condense_llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo")

# 问题浓缩提示模板
condense_prompt = ChatPromptTemplate.from_messages([
    ("system", "给定以下对话历史和当前问题,重写当前问题为一个独立的、上下文无关的问题。"),
    MessagesPlaceholder(variable_name="history"),
    ("human", "当前问题:{question}\n独立问题:")
])

# 回答提示模板
answer_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个助手,根据以下上下文和对话历史回答问题:\n上下文:{context}"),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{question}")
])

# 创建浓缩链
condense_chain = (
    {
        "question": itemgetter("question"),
        "history": itemgetter("history") | RunnablePassthrough()
    }
    | condense_prompt
    | condense_llm
    | StrOutputParser()
)

# 创建 LCEL 链
runnable = (
    {
        "context": condense_chain | vectorstore.as_retriever(search_kwargs={"k": 2}),
        "question": itemgetter("question"),
        "history": itemgetter("history") | RunnablePassthrough()
    }
    | answer_prompt
    | main_llm
    | StrOutputParser()
)

# 初始化消息历史存储
store = {}
def get_session_history(session_id: str) -> ChatMessageHistory:
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

# 创建带历史的链
qa = RunnableWithMessageHistory(
    runnable,
    get_session_history,
    input_messages_key="question",
    history_messages_key="history"
)

# 调用链
session_id = "user1"
response = qa.invoke(
    {"question": "什么是人工智能?", "history": []},
    config={"configurable": {"session_id": session_id}}
)
print(response)
response = qa.invoke(
    {"question": "它包含哪些子领域?", "history": []},
    config={"configurable": {"session_id": session_id}}
)
print(response)

输出示例

人工智能(AI)是计算机科学的一个分支,专注于创建能够执行需要人类智能的任务的系统,例如学习、推理和决策。
人工智能包含子领域,如机器学习、深度学习和生成式 AI。
代码说明
  1. 文本分割
    • RecursiveCharacterTextSplitter 使用分隔符(\n\n, \n, )递归分割,优先保留段落和句子。
    • chunk_size=100chunk_overlap=20 适合小规模测试。
    • 每个块转换为 Document 对象。
  2. 向量存储
    • Chroma.from_documents 为每个块生成嵌入向量。
    • 检索器返回 2 个相关块(k=2)。
  3. 浓缩链
    • condense_chain 使用 gpt-3.5-turbo 生成独立问题。
    • 输入:{"question": "...", "history": [...]}
  4. 回答链
    • answer_prompt 结合上下文、历史和原始问题。
    • main_llmgpt-4)生成答案。
  5. 输入处理
    • itemgetter("question")itemgetter("history") 确保正确提取字段。
  6. 历史管理
    • ChatMessageHistory 存储对话历史,session_id 区分会话。

改进

  • 使用 RecursiveCharacterTextSplitter 替代 CharacterTextSplitter,提高语义连续性。
  • LCEL 链替代 ConversationalRetrievalChain,避免废弃警告。

注意事项

  1. API 密钥
    • 使用 .env 文件:
      from dotenv import load_dotenv
      load_dotenv()
      
    • 确保密钥支持 text-embedding-3-smallgpt-3.5-turbogpt-4
  2. 依赖
    • 安装:
      pip install --upgrade langchain langchain-community langchain-openai langchain-core chromadb
      
  3. 分割优化
    • 生产环境建议 chunk_size=500-1000chunk_overlap=100-200
    • 对于复杂文档,测试 SemanticChunker 或特定分割器(如 MarkdownHeaderTextSplitter)。
  4. Ollama 替代
    • 使用 langchain_ollama
      from langchain_ollama import ChatOllama, OllamaEmbeddings
      main_llm = ChatOllama(model="qwen3:7b")
      condense_llm = ChatOllama(model="qwen3:1.7b")
      embeddings = OllamaEmbeddings(model="nomic-embed-text")
      
  5. 迁移
    • 使用 langchain migrate CLI:
      pip install langchain-cli
      langchain migrate
      

常见问题

Q1:如何选择合适的分割器?
A:根据文本类型选择:

  • 通用文本:RecursiveCharacterTextSplitter
  • 代码:PythonCodeTextSplitterLanguageTextSplitter
  • Markdown/HTML/LaTeX:MarkdownHeaderTextSplitter, HTMLTextSplitter, LatexTextSplitter
  • 语义:SemanticChunker
  • 按 token:TokenTextSplitter

Q2:chunk_sizechunk_overlap 如何设置?
A:chunk_size 设为 500-2000(适配嵌入模型),chunk_overlap 为 10-20%(如 100-200),测试效果后调整。

Q3:CharacterTextSplitterRecursiveCharacterTextSplitter 的区别?
A:CharacterTextSplitter 按固定字符数或单一分隔符分割,可能截断语义;RecursiveCharacterTextSplitter 递归尝试多级分隔符,保留段落/句子边界。

Q4:如何调试分割结果?
A:打印 splitter.split_text(text) 检查块内容和长度;用 langchain.debug = True 查看 RAG 管道日志。


总结

langchain.text_splitter 模块包含 12 种分割器:

  • 通用CharacterTextSplitter, RecursiveCharacterTextSplitter, TokenTextSplitter
  • 代码LanguageTextSplitter, PythonCodeTextSplitter
  • 格式化文档MarkdownHeaderTextSplitter, MarkdownTextSplitter, HTMLTextSplitter, LatexTextSplitter
  • 语义SemanticChunker
  • 其他SpacyTextSplitter, NLTKTextSplitter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值