RAG--分块

问题1:为什么要分块?

在基于 Transformer 架构的向量化模型中,每个词汇都会被映射为一个高维向量。为了表示整段文本的语义,通常采用对词向量取平均,或使用特殊标记(如 [CLS])位置的向量作为整体表示。

  • 然而,当直接对过长的文本进行向量化时,会面临以下挑战:
  • 语义信息稀释:长文本往往涵盖多个主题或观点,整体向量难以准确捕捉细节语义,导致语义信息被稀释,无法充分体现文本的核心内容。
  • 计算开销增大:处理长文本需要更多的计算资源和存储空间,增加了模型的计算复杂度,影响系统的性能和效率。
  • 检索效率降低:过长的向量在检索过程中可能会降低匹配精度,导致检索结果的相关性下降,同时也会降低检索的速度和效率。

问题2:分块前要注意什么?

分块前要做的一件事是指代消解

问题3:分块的方法有哪些?

3.1 固定大小块的分割方法

常见方法: LangChain 提供了 RecursiveCharacterTextSplitter,其中包含Overlap

使用示例:

from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=50,
    length_function=len,
    separators=["\n", "。", ""]
)
text = "..."  # 待处理的文本
texts = text_splitter.create_documents([text])
for doc in texts:
    print(doc)

原理:

  • 初步切分:使用第一个分割符(如 "\n",表示段落分隔)对文本进行初步切分。
  • 检查块大小:如果得到的文本块长度超过了 chunk_size,则使用下一个分割符(如 "。",表示句子分隔)进一步切分。
  • 递归处理:依次使用剩余的分割符,直到文本块长度符合要求或无法再切分。
  • 合并块:如果相邻的文本块合并后长度不超过 chunk_size,则进行合并,确保块的长度尽可能接近 chunk_size,同时保留上下文完整性。

3.2 句子级别分割方法

按照句子级别进行划分、略

3.3 Late-chunking分割方法

常规的RAG文本切块如左下图所示,先进行文本切分,分别过Transformer处理,通过meaning pooling得到每个chunk的句向量。

transformer最终输出的是每个token的embedding,如下所示。如果想用一个embedding对整个句子进行表征,主要有两大流派(Transformer encoder架构),一派是对所有token的embedding取平均;另一派是用[CLS]位置的token embedding表示句子,因为大部分文本向量化模型是双向注意力的,[CLS]位置的embedding能感知到全局文本信息。

某一个模型到底是用CLS embedding表示句子,还是用所有token embedding的平均值表示句子是由训练时候决定,并不能随意切换。如果一个模型在训练时用CLS embedding表示句子,那么推理时用所有token embedding平均表示句子效果会非常差。目前使用CLS embedding表示句向量的模型占大多数,比如被大家广泛使用的BGEBCE模型等。只有少部分模型,比如GTE系列的个别模型、JINA的模型等才用mean pooling token embedding的方式表征句子。而late chunking技术只有那些用mean pooling token embeding表征句子的模型才能用。

Late Chunking技术需要先对文本进行embedding,再进行分段,因此比常规的文本向量化需要模型有更强的长文本处理能力。

3.4 自定义分隔符分割方法

在构建需求文档时手动添加分隔符,进而进行分割,略

3.5 特定文档(Markdown、Word)分割

LangChain 为用户提供了针对多种特殊格式文本的切块类,方便用户处理不同类型的文本。

 

### RAG 架构中的文本分块技术 RAG(Retrieval-Augmented Generation)是一种结合检索生成模型的方法,用于增强自然语言处理任务的效果。在实际应用中,为了提高效率并减少计算资源消耗,通常会采用 **文本分块(text chunking)** 技术来分割文档内容。 #### 文本分块的目的 文本分块的主要目的是将长篇文档拆分为更小的单元以便于存储、索引以及后续的检索操作。通过这种方式可以显著降低内存占用率,并提升检索速度[^1]。 #### 常见的文本分块方法 以下是几种常见的文本分块策略: 1. **固定长度切片** 这种方式按照固定的字符数或者词数量对原文档进行切割。例如,如果设定每段的最大长度为500个单词,则当达到该限制时就会创建一个新的片段。 2. **基于语义边界划分** 考虑到单纯依赖字数可能导致某些重要信息被截断的情况发生,因此也可以利用句法分析工具识别出合适的断点位置来进行更加合理的分区。比如,在完成一段描述之后再做进一步分离而不是随意打断句子结构[^2]。 3. **滑动窗口机制** 使用大小可调的滑动窗体沿输入序列移动,并从中提取子串作为候选答案区域之一;这种方法能够捕捉上下文中可能存在的关联关系从而改善最终效果表现。 #### 实现细节示例 下面给出一个简单的 Python 函数用来演示如何根据指定最大长度实现基本版本的定长切片功能: ```python def split_text(text, max_length=500): """Split a long string into chunks with maximum length.""" words = text.split(' ') current_chunk = [] result = [] for word in words: if len(' '.join(current_chunk)) + len(word) + 1 <= max_length: current_chunk.append(word) else: result.append(' '.join(current_chunk)) current_chunk = [word] if current_chunk: result.append(' '.join(current_chunk)) return result ``` 此函数接受两个参数:待处理字符串`text` 希望设置成多大的单个chunk 的近似值 `max_length`. 它先按空格把整个文字分解成一个个词语列表形式储存起来; 接着逐一考察这些词汇是否能加入当前正在构建的小段落里而不超出预定界限——一旦发现无法满足条件就立即停止累加并将已积累的部分保存下来形成新的独立项存入结果集中去.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值