大模型RAG问答中的文档分段策略回顾:兼并看LumberChunker动态分块思想
今天是2024年6月27日,星期四,北京,天气晴。

今天咱们来深入聊聊RAG里一个很关键的问题——文档分段。先快速过一遍现有的几种主流分段思路,再重点看看基于大模型做动态分块的新方案,也就是LumberChunker。这个话题挺有意思,值得花点时间拆解清楚。
问题1:文档分段的现有几个思路回顾
昨天聊过句子分段,今天把段落级的分段方法也一并理一理。目前业界已经有好几套方案了,下图来自一篇不错的博客(Mastering RAG: Advanced Chunking Techniques),一张表就把各自优劣势说清楚了:
1、递归分块
RecursiveCharacterTextSplitter函数就是典型实现。本质上是先按最大的分隔符(比如段落)分割,如果块还是太大,再按下一级分隔符递归切割,直到满足长度要求。简单粗暴,但容易把语义连贯的内容拦腰截断。
2、语义分块
text-ada-embedding-002把每个段落块嵌入成向量,然后计算相邻块嵌入之间的距离。如果距离超过某个阈值,就认为这里发生了语义切换,在此处设断点。关键在于阈值怎么定——设大了可能漏分,设小了又容易过度分割。一旦断点确定,文本就被切成语义相对独立的块。这个方法的好处是能捕捉到内容主题的自然变化,但阈值调参是个头疼事。具体实现可以参考GitHub上的semantic-split项目。
3、命题分块
问题2:基于大模型进行动态分块的LumberChunker思想
针对长篇叙事文本,最近有一篇新工作值得关注——《LumberChunker: Long-Form Narrative Document Segmentation》。它提出了一种利用LLM动态分割长篇叙事文档的方法,让每个块在语义上独立、连贯,又与相邻块有所区别。直接说几个重点。
1、实现思想
核心逻辑很简单:不再固定块大小,而是让块的大小随着内容的语义自然变化。具体流程分三步走:
第一步
第二步
第三步
来看prompt的设计细节:
``` You are an expert text analyzer. Given the following sequence of consecutive paragraphs (delimited by markers), identify the paragraph where a significant topic shift occurs compared to the content before it. Output the paragraph ID. ```文档就是这样一圈一圈地被切成语义块的。每个新的Gi+1组的起始点,就是上一次迭代中识别出的那个"转折段落"。
2、实现效果
为了验证效果,作者构建了一个新基准测试——GutenQA,从Project Gutenberg上的100本叙事书籍中手动提取了3000对问答数据。RAG的设计框架也有不少可借鉴之处:
查询路由与文档集成
文档重排序与重排名
最终答案生成
实验结果很亮眼——LumberChunker在检索性能上比所有竞争基线高出7.37%(DCG@20指标),并且当集成到RAG流程中时,比Gemini 1.5 Pro等方案更有效。
3、方案评价
当然,缺点也很明显。作者自己也坦承:LumberChunker需要调用LLM,比传统方法更昂贵、更慢。而且它是为叙事文本设计的——那些结构松散、依赖语义理解的长篇内容。如果换到法律合同这种高度结构化的文本,LumberChunker就有点杀鸡用牛刀了,反而可能过于复杂。
代码已在GitHub开源,感兴趣可以自行参考。
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名