支持私有化部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


RAG系统文本切分算法选型指南

发布日期:2025-06-15 15:04:08 浏览次数: 1534
作者:锐编程

微信搜一搜,关注“锐编程”

推荐语

RAG系统文本切分算法选型指南:解析不同切分方法的适用场景与优化策略,助你提升检索质量与生成效果。

核心内容:
1. 文本切分在RAG系统中的关键作用与核心目标
2. 基于字符和基于令牌的切分方法对比分析
3. 不同检索器搭配切分算法的最佳实践方案

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家

 

RAG系统文本切分算法选型指南

简介

在构建企业级检索增强生成(RAG)系统时,文本切分算法的选择至关重要。切分策略直接影响检索的质量和生成结果的准确性。本文档将介绍常用的文本切分方法,分析其优缺点,并结合不同检索器给出最佳实践方案。

RAG系统通常包含两个主要组件:

  1. 1. 索引阶段:加载数据、切分文档、存储向量
  2. 2. 检索和生成阶段:基于用户输入检索相关内容,利用LLM生成回答

其中,文本切分是索引阶段的关键步骤,它将大型文档分割成更小的块,以便于检索和处理。

文本切分算法概述

文本切分算法的主要目标是将长文本分割成语义连贯的小块,使其既能保持上下文完整性,又能有效地用于检索和传递给模型。理想的切分算法应该能够:

  • • 保持语义完整性
  • • 适应不同类型的文档
  • • 产生大小适中的文本块
  • • 确保检索效率
  • • 减少冗余信息

常用文本切分方法

基于字符的切分

描述

基于字符的切分是最简单的切分方法,它根据字符数量将文本切分成固定大小的块。

LangChain示例

from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,  # 每个块的字符数
    chunk_overlap=200,  # 相邻块之间的重叠字符数
    separators=["\n\n""\n"" """]  # 优先按照这些分隔符切分
)
docs = text_splitter.split_documents(documents)

优点

  • • 实现简单,易于理解
  • • 处理速度快
  • • 适用于各种类型的文本
  • • 可以通过分隔符列表优化切分位置

缺点

  • • 可能在语义边界处不精确切分
  • • 不考虑内容的语义结构
  • • 固定大小的块可能会分割重要的上下文信息

最佳实践

  • • 结合使用BM25Retriever或简单的向量检索
  • • 增加块重叠以减少信息丢失
  • • 使用更有意义的分隔符(如段落分隔符)
  • • 对于较短的文档,建议使用较小的chunk_size(500-1000)
  • • 对于长文档,考虑分层检索策略

基于令牌的切分

描述

基于令牌的切分根据LLM的令牌(token)计数来切分文本,这更符合模型处理文本的方式。

LangChain示例

from langchain_text_splitters import TokenTextSplitter

text_splitter = TokenTextSplitter(
    chunk_size=500,  # 每个块的最大令牌数
    chunk_overlap=50   # 相邻块之间的重叠令牌数
)
docs = text_splitter.split_documents(documents)

优点

  • • 直接与LLM的上下文窗口大小相关联
  • • 可以精确控制每个块的令牌数
  • • 减少模型处理时的截断问题

缺点

  • • 计算令牌数需要额外处理
  • • 可能在语义不完整处切分
  • • 不同模型的分词器可能导致不同结果

最佳实践

  • • 结合VectorStoreRetriever使用
  • • 令牌大小设置应考虑目标LLM的上下文窗口
  • • 对于GPT模型,可以设置chunk_size为1024-2048
  • • 重叠部分建议为块大小的10%-20%
  • • 适合需要精确控制令牌用量的场景

基于语义的切分

描述

基于语义的切分通过计算文本嵌入并识别语义边界来切分文本,确保每个块的语义连贯性。

不同breakpoint_threshold_type的功能与作用

SemanticChunker提供了四种不同的阈值类型(breakpoint_threshold_type),用于确定文本的切分点:

1. 百分位数方法(percentile)

  • • 功能:基于文本嵌入向量之间的距离分布,使用百分位数作为划分边界的阈值
  • • 原理:计算相邻句子嵌入向量之间的距离,找出距离分布中特定百分位(如95%)的值作为阈值,超过该阈值的位置被视为语义边界
  • • 适用场景:适合结构相对规律、语义转换明显的一般文本
  • • 参数调整:通过调整breakpoint_threshold_amount(0-100之间的值)控制切分的粒度,值越高切分越少,默认为95.0
  • • 特点:能够有效识别主题转换点,保持语义连贯性

2. 标准差方法(standard_deviation)

  • • 功能:使用距离分布的平均值加上一定倍数的标准差作为切分阈值
  • • 原理:计算所有相邻句子嵌入向量距离的平均值和标准差,将"平均值+n倍标准差"作为阈值
  • • 适用场景:适合语义变化程度差异较大的文档,如包含多个不同主题的论文或报告
  • • 参数调整:通过breakpoint_threshold_amount设置标准差的倍数,默认为1.0
  • • 特点:对异常值(语义突变点)更敏感,能够适应文档内部语义变化程度的差异

3. 四分位距方法(interquartile)

  • • 功能:使用四分位距(IQR)来确定语义边界的阈值
  • • 原理:计算距离分布的第一四分位数(Q1)和第三四分位数(Q3),将"Q3 + n倍IQR"作为阈值,其中IQR = Q3 - Q1
  • • 适用场景:适合语义高度相关但需要在自然边界处切分的文档,如专业论文、技术文档
  • • 参数调整:通过breakpoint_threshold_amount调整IQR的倍数,默认为1.5
  • • 特点:对极端值不敏感,提供更稳健的切分方式,减少噪声影响

4. 梯度方法(gradient)

  • • 功能:结合梯度分析和百分位数方法,特别适用于语义高度相关的专业领域文档
  • • 原理:计算相邻向量距离的变化率(梯度),然后对梯度分布应用异常检测,找出语义变化显著的点
  • • 适用场景:特别适合法律、医学等专业领域文档,这类文档往往语义高度相关、术语密集
  • • 参数调整:与百分位数方法类似,通过breakpoint_threshold_amount设置百分位阈值,默认为95.0
  • • 特点:能够在语义高度相关的文本中识别出细微的主题转换,使分布更宽,边界更容易识别

LangChain示例

百分位数方法:

from langchain_text_splitters import SemanticChunker
from langchain_openai import OpenAIEmbeddings

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="percentile",  # 使用百分位数方法
    breakpoint_threshold_amount=95.0  # 95百分位数
)
docs = text_splitter.create_documents([text])

标准差方法:

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="standard_deviation",  # 使用标准差方法
    breakpoint_threshold_amount=1.5  # 1.5倍标准差
)
docs = text_splitter.create_documents([text])

四分位距方法:

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="interquartile",  # 使用四分位距方法
    breakpoint_threshold_amount=1.5  # 1.5倍四分位距
)
docs = text_splitter.create_documents([text])

梯度方法:

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="gradient",  # 使用梯度方法
    breakpoint_threshold_amount=95.0  # 95百分位数
)
docs = text_splitter.create_documents([text])

优点

  • • 保持语义的完整性和连贯性
  • • 更符合人类理解文本的方式
  • • 可以适应不同类型和结构的文档
  • • 能够识别自然的主题转换点
  • • 提高检索相关性和准确性

缺点

  • • 计算成本高,处理速度慢
  • • 需要嵌入模型支持
  • • 参数调整可能需要实验
  • • 对于某些特定领域文本效果可能不一致
  • • 对嵌入模型的质量依赖较高

最佳实践

  • • 与MMR(最大边际相关性)检索策略结合使用
  • • 对于长文档或结构化文档效果更好
  • • 百分位数方法适合一般文档和初始尝试
  • • 标准差方法适合语义变化较大的混合文档
  • • 四分位距方法适合需要稳健切分的专业文档
  • • 梯度方法适合专业领域文档(如法律、医学、学术论文)
  • • 考虑使用HyperRetrieverSelfQueryRetriever增强语义检索能力
  • • 为不同类型的文档集合选择不同的阈值类型
  • • 进行A/B测试比较不同方法的检索效果

特定格式文档切分

描述

针对特定格式的文档(如Markdown、HTML、代码等)的专用切分器,能够理解文档结构。

LangChain示例

Markdown切分:

from langchain_text_splitters import MarkdownHeaderTextSplitter

headers_to_split_on = [
    ("#""Header 1"),
    ("##""Header 2"),
    ("###""Header 3"),
]
markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on
)
md_docs = markdown_splitter.split_text(markdown_text)

HTML切分:

from langchain_text_splitters import HTMLHeaderTextSplitter

html_splitter = HTMLHeaderTextSplitter(tags_to_split_on=["h1""h2""h3"])
html_docs = html_splitter.split_text(html_text)

代码切分:

from langchain_text_splitters import RecursiveCharacterTextSplitter

python_splitter = RecursiveCharacterTextSplitter.from_language(
    language="python",
    chunk_size=1000,
    chunk_overlap=200
)
code_docs = python_splitter.split_text(code_text)

优点

  • • 尊重文档的结构和层次
  • • 保留标题和内容的关系
  • • 适合结构化文档的处理
  • • 能够根据文档特性进行优化

缺点

  • • 仅适用于特定格式的文档
  • • 可能需要额外的预处理
  • • 对格式错误的文档处理效果不佳
  • • 需要针对不同文档类型选择不同分割器

最佳实践

  • • 结合使用ParentDocumentRetriever保持文档层次结构
  • • 对于Markdown文档,按标题分割可提高检索精度
  • • 对于HTML文档,可以结合CSS选择器进行更精细的控制
  • • 对于代码文档,考虑按函数或类进行分割
  • • 使用元数据存储文档结构信息,便于检索时重建上下文

最佳实践方案

混合策略

在企业级RAG系统中,可以考虑采用混合策略,结合多种切分方法的优势:

  1. 1. 分层切分:先使用结构化切分(如按标题、段落),再使用细粒度切分(如基于令牌)
  2. 2. 动态切分:根据文档类型和长度自动选择适合的切分算法
  3. 3. 并行切分:同时使用多种切分方法,在检索时合并结果

文档类型与切分方法匹配

  • • 长文本文档(如论文、报告):语义切分 + 分层检索
  • • 结构化文档(如Markdown、HTML):特定格式切分器 + 层次检索
  • • 代码库:代码专用切分器 + 函数级别切分
  • • 对话记录:基于对话轮次切分 + 上下文感知检索
  • • 表格数据:专用表格处理 + 结构化检索

检索器选择与优化

  • • 向量存储检索器:适合语义相似性查询,与语义切分配合使用
  • • BM25检索器:适合关键词查询,与基于字符的切分配合使用
  • • 混合检索器:结合关键词和语义检索,提高召回率
  • • 自查询检索器:允许文档自描述,与语义切分配合良好
  • • 父文档检索器:保持文档结构,与特定格式切分器配合使用

结论

文本切分是RAG系统的关键环节,直接影响检索质量和生成结果。在企业级应用中,应根据具体需求、文档特性和资源限制选择合适的切分策略。

理想的切分方案应该:

  • • 保持语义完整性
  • • 适应不同类型的文档
  • • 与检索器协同工作
  • • 根据需求动态调整
  • • 考虑计算资源与性能平衡

建议在实际部署前进行充分测试,并根据反馈持续优化切分策略。

额外内容

文本切分预处理

文本切分可以先通过一些预处理来获得更好的检索效果

  1. 1. 预设问题:通过大模型对切分后的文本进行扩充,补充1-2个预设问题来增加chunk召回概率,例如text切分成10个chunk,每个chunk通过大模型生成1-2个问题,然后更新chunk为问题+chunk文本
  2. 2. 保存chunk位置信息,检索到chunk后取出上下n个chunk一起参与模型问答,例如搜索到chunk3,将chunk1,chunk2,chunk4,chunk5一起填入context
  3. 3. 存储chunk与原文关系,检索到chunk后使用原文,剔除chunk
  4. 4. context拼接:由于大模型注意力机制,prompt的头尾两部分数据被关注权重比中间高,因此检索到的chunk按分数从高到低排序后,使用头尾交替法插入prompt,例如排序12345,插入prompt后顺序13542

 


53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询