指定一个块长度和一组分隔符(默认的字符列表是["\n\n", "\n", " ", ""]),根据分隔符的优先顺序对文本进行预分隔,然后将小块进行合并,将大块进行递归拆分,直到获得所需的块大小,最终这些块的大小并不完全相同,但它们仍然会逼近指定的块长度。
递归字符文本分割器工作流程简述
递归字符文本分割器包含预分割、合并、递归拆解等步骤要素,下面给到一个更加完成的流程图。
其中关键要素:
- 分隔符的优先级别:在一开始,程序尝试以最有把握的分隔符将文本进行分割,分割之后若还存在长文本,则此时只能使用其他分隔符,分隔符的优先级和语言习惯有关,中文场景下,第一优先级的分隔符是换行符,第二优先级是句号、问好、感叹号,第三优先级是分号,最后是逗号。
- chunk_size:预先指定的块大小,最终分割的块都应该逼近这个大小,chunk_size会作为预切分之后每个块合并还是再拆分的依据。
- 暂存集合:程序会创建一个暂存集合,它按照顺序的将不超过的chunk_size的块暂存在其中,直到循环到某个超过chunk_size的块,程序以这个为信号开始一次批处理,该批处理包含暂存集合合并和大块拆解两个动作,这个暂存集合记录了本次批处理中的合并环节需要用的所有子块,这些子块可以合并为一个或者多个中等规模的块。
- 重叠预留:最简单的情况是将暂存集合合并写入结果集,然后暂存集合清空,当chunk_overlap=0时就是这种情况,而当chunk_overlap>0时,暂存集合会保留下一部分最右侧的文本,该文本会和后面的块合并,相当于会有一块重叠部分,既存在在A块,也存在在B块。
- 递归拆分的停止条件:当某块超过chunk_size,它理应被再拆解,但是前提条件是存在可用的分隔符号,我们举例最次要的分隔符是逗号,如果块中连逗号的没有则就算超长也无法再拆分,此时直接加入最终集合,更一般的情况是有分隔符可用拆分成小块,再执行合并的逻辑写入最终集合。
对于合并操作也存在一个操作流程,同样采用循环每个块来决定如何操作,期望在不超过chunk_size的情况下聚合更多的子块,当某个块加入导致超过chunk_size时触发之前所有的块合并,额外的这些块会预留下右侧部分和之后的块合并,预留的大小由chunk_overlap控制。
每个块上的数字代表块长度大小,我们令chunk_size=50,则前4个块合并成一个中块,因为最后一个块25加入进来已经超过50,而在5,8,17,3合并之后,会从左弹出块,知道剩余的长度小于chunk_overlap,我们设chunk_overlap为5,则当退出到只剩3时满足,因此3这个块会和后面的25块以及其后的块进行合并,3块在上下两个组合中出现了2次,这样做的目的是能够更好地保留上下文,防止不合适的短句切分了语义。