链载Ai

标题: RAG系统文本切分算法选型指南 [打印本页]

作者: 链载Ai    时间: 昨天 21:15
标题: RAG系统文本切分算法选型指南

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;display: table;padding: 0px 1em;color: rgb(63, 63, 63);">RAG系统文本切分算法选型指南

简介

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">在构建企业级检索增强生成(RAG)系统时,文本切分算法的选择至关重要。切分策略直接影响检索的质量和生成结果的准确性。本文档将介绍常用的文本切分方法,分析其优缺点,并结合不同检索器给出最佳实践方案。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">RAG系统通常包含两个主要组件:

    ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;color: rgb(63, 63, 63);" class="list-paddingleft-1">
  1. ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;text-indent: -1em;display: block;margin: 0.2em 8px;color: rgb(63, 63, 63);">
    1.ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;color: rgb(15, 76, 129);">索引阶段:加载数据、切分文档、存储向量
  2. ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;text-indent: -1em;display: block;margin: 0.2em 8px;color: rgb(63, 63, 63);">
    2.ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;color: rgb(15, 76, 129);">检索和生成阶段:基于用户输入检索相关内容,利用LLM生成回答

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">其中,文本切分是索引阶段的关键步骤,它将大型文档分割成更小的块,以便于检索和处理。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;display: table;padding: 0px 0.2em;color: rgb(255, 255, 255);background: rgb(15, 76, 129);">文本切分算法概述

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

常用文本切分方法

基于字符的切分

描述

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

LangChain示例

fromlangchain_text_splittersimportRecursiveCharacterTextSplitter

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

优点

缺点

最佳实践

基于令牌的切分

描述

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

LangChain示例

fromlangchain_text_splittersimportTokenTextSplitter

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

优点

缺点

最佳实践

基于语义的切分

描述

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

不同breakpoint_threshold_type的功能与作用

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

1. 百分位数方法(percentile)

2. 标准差方法(standard_deviation)

3. 四分位距方法(interquartile)

4. 梯度方法(gradient)

LangChain示例

百分位数方法:

fromlangchain_text_splittersimportSemanticChunker
fromlangchain_openaiimportOpenAIEmbeddings

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])

优点

缺点

最佳实践

特定格式文档切分

描述

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

LangChain示例

Markdown切分:

fromlangchain_text_splittersimportMarkdownHeaderTextSplitter

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切分:

fromlangchain_text_splittersimportHTMLHeaderTextSplitter

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

代码切分:

fromlangchain_text_splittersimportRecursiveCharacterTextSplitter

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

优点

缺点

最佳实践

最佳实践方案

混合策略

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

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

文档类型与切分方法匹配

检索器选择与优化

结论

文本切分是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







欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5