引言
将一个长文档分割为多个小块是RAG系统中一个必不可少的步骤。合理的分块能够在query检索的过程中减少噪声的影响,增强检索效果。
目前的文本分块方法有基于规则的分块,例如按照固定长度大小、按照分隔符分块、递归分块等,更进一步的是基于文本语义的分块。
本篇文章主要探讨了目前使用的基于语义分块的方法。
语义分块
基于naive-Bert的分块方法
在BERT 的预训练过程中,其中的一个二元分类任务 ------ "下一个句子预测(Next Sentence Prediction,NSP)" 是为了让模型理解两个句子之间的关系而设计的。在这种情况下,同时输入两个句子到 BERT 中,模型会预测这两个句子是否连续。
如果 BERT 模型对这两个句子的预测得分低于预设的阈值,则表明两个句子之间的语义关系较弱。
这种方法的优点是可以直接使用,无需进一步训练或微调。
然而,这种方法在确定文本分割点(text segmentation point)时只考虑了紧随在当前句子之后的句子 ,忽略了更多距离较远段落的信息。此外,这种方法的预测效率相对较低。
Cross Segment Attention
《Text Segmentation by Cross Segment Attention》这篇论文提出了三种基于 Cross Segment Attention 的文本分割模型: 图 (a)中的 cross-segment BERT 模型,将文本分割定义为逐句分类任务 (sentence-by-sentence classification task,逐句判断其是否是文本分割点 )。潜在文本分割点附近的局部上下文(两侧的 k 个 tokens)被输入到模型中。与 [CLS] 相对应的隐藏状态(hidden state)被传递给 softmax 分类器,由其决定是否在潜在断句处进行分割。
这篇论文还介绍了另外两个模型。其中一个使用 BERT 模型获取每个句子的向量表征 。将连续的多个句子转换为向量表征输入到 Bi-LSTM 模型(图(b))或另一个 BERT 模型(图(c))中,以预测每个句子是否是文本分割点的位置。
基于embedding的聚类方法
传统的聚类方法对文本分句,使用聚类方法将不同的句子聚在一起作为分块,但是这种方法可能将文章里面距离较远/非连续的句子划分成同一分块,这显然是不合直觉的做法。
于是乎,改进的方案出现了,
- 还是先简单粗暴按照句号、分号、问好、感叹号、换行符等分割文本,形成一个个的句子,用sen1、sen2、sen3. ... senN表示
- 从sen1开始,以此和前后一个句子组合,形成combined_sentence,比如sen1+sen2 = combined_sentence1,sen1+sen2+sen3=combined_sentence2,sen2+sen3+sen4=combined_sentence3,以此类推
- 以此计算combined_sentence1、combined_sentence2、combined_sentence3 ..... combined_sentenceN之间的相似度,如果相似度突然变化,那么新加入sen的语义肯定不同,从这里截断!举例如下:前面三个combined_sentence的距离都比较近,第4个combined_sentence和第三个的距离突然增加很多,说明sen4和sen1 ~ sen3之间的语义肯定差异较大,可以从sen4开始分割,sen1 ~ sen3合并成一个chunk!
基于命题proposition的分块方式
将文档拆分以命题为单位的块。其中命题的定义原则是:
-
每个命题应对应文本中的一个独特意义片段,所有命题的组合应代表整个文本的语义。
-
命题应是最小化 的,即不能进一步分割为单独的命题。
-
命题应包含上下文情境和自身。命题应包括来自文本的所有必要上下文(例如指代关系),以解释其含义。
以下是一个划分的示例:
在原始段落中包含三个命题,每个命题对应比萨斜塔的三个独特事实:修复前的角度、当前角度和水平位移。
具体的实现
作者微调了一个文本生成模型 ------"命题生成器" 。命题生成器接受段落作为输入,并生成段落内的 命题列表 。作者通过 两步蒸馏过程 来训练命题生成器。
(1)使用一个包含命题定义和one-shot的示例的指示来引导GPT-4生成 42k条(passage -> propostion)的数据对;
(2)使用得到的数据对来微调一个FlanT5-large模型;
利用大模型进行语义分块
待更新。。