跳到主要内容

ChunkViz实验与可视化

上一篇讲了分块策略的理论,但光看文字描述可能还不够直观。

这篇用一个免费的在线工具——ChunkViz,来可视化地展示不同分块策略的效果,让你亲眼看到"切大了"和"切小了"的区别。

ChunkViz是什么

ChunkViz是一个免费的在线分块可视化工具,支持两种分块策略:

  • CharacterTextSplitter:固定大小分块
  • RecursiveCharacterTextSplitter:递归分块

你可以实时调整chunk_size和overlap参数,页面会用不同颜色高亮显示每个块的范围。

推荐先动手试试

建议你在看下面的实验之前,先自己打开ChunkViz玩一玩。把自己项目中的文档内容粘贴进去,调调参数,感受会更深。

操作步骤

  1. 打开 https://chunkviz.up.railway.app/
  2. 在文本框中粘贴你想测试的文本
  3. 在右侧选择分块策略:
    • CharacterTextSplitter:对应固定大小分块
    • RecursiveCharacterTextSplitter:对应递归分块
  4. 调整 Chunk Size 和 Chunk Overlap 的滑块
  5. 页面会实时用不同颜色高亮显示每个块的范围

ChunkViz界面:

ChunkViz界面

实验准备:测试文本

我们用一段在线教育课程的讲义来做实验:

第一章:Java基础语法

Java是一种面向对象的编程语言,由Sun公司于1995年推出。Java具有跨平台、安全性高、面向对象等特点,被广泛应用于企业级应用开发。

学习Java的第一步是搞懂变量和数据类型。Java是强类型语言,每个变量必须声明其类型。基本数据类型包括:int、long、float、double、boolean、char等。

第二章:面向对象编程

面向对象是Java的核心特性。它包括三大特征:封装、继承和多态。封装是指将数据和操作数据的方法绑定在一起,隐藏内部实现细节。

继承允许一个类获取另一个类的属性和方法。在Java中,使用extends关键字实现继承。多态是指同一个方法调用可以有不同的行为,这通过方法重写和接口实现。

下面做几组对比实验:

实验策略chunk_sizeoverlap观察重点
实验1CharacterTextSplitter10020看块的边界是不是经常切在句子中间
实验2RecursiveCharacterTextSplitter2000对比实验1,看是否更倾向于在段落边界切割
实验3RecursiveCharacterTextSplitter800chunk_size较小时,复杂文本会被怎样切散

实验1:固定大小分块

配置:CharacterTextSplitter,chunk_size=100,overlap=20

固定大小分块效果

观察结果

你会发现,每个分块的字符数都是固定的100字,完全不管文本结构。有些块可能从句子中间开始,读起来很突兀。

注意观察:

  • 粉色、蓝色、荧光绿色、黄色等不同颜色代表不同的分块
  • 墨绿色是重叠区域的标识,表示相邻块共享的部分
  • "Java基础语法"这个标题可能被切成两半,语义不完整

问题:固定大小分块完全不理会文本结构,经常在句子中间切断。

实验2:递归分块

配置:RecursiveCharacterTextSplitter,chunk_size=200,overlap=0

递归分块效果

观察结果

这次切割结果和上一次明显不同。递归分块会尽量在段落边界(双换行符 \n\n)处切割。

对比两种策略

策略切割位置语义完整性
CharacterTextSplitter数够字符就切,不管在哪差,经常切断句子
RecursiveCharacterTextSplitter优先在段落/句子边界切好,尽量保持完整

实验3:复杂文本的困境

如果文本的语义跨度更大,比如同一个知识点包含好几句话,递归分块也可能切得不够完美。

测试文本

Spring事务的传播机制详解

当一个事务方法调用另一个事务方法时,Spring需要决定如何处理事务边界,这就是事务传播机制。默认的传播级别是REQUIRED,它的含义是:如果当前已经存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。这种方式在大多数业务场景中都能满足需求,比如订单服务调用库存服务时,两者的操作应该在同一个事务中,要么一起成功,要么一起回滚。

但有些场景需要不同的处理方式。比如日志记录功能,即使主业务失败回滚了,日志也应该被保存下来,这时候就需要使用REQUIRES_NEW传播级别。REQUIRES_NEW会挂起当前事务,创建一个全新的独立事务,新事务的提交或回滚不受外层事务的影响。还有一种常见的场景是嵌套事务,使用NESTED传播级别,它会在当前事务内创建一个保存点,如果内层事务失败,只回滚到保存点,不影响外层事务已经完成的操作。

理解这些传播机制的关键是搞清楚"事务边界在哪里"和"谁控制提交回滚"这两个问题。

配置:RecursiveCharacterTextSplitter,chunk_size=80

复杂文本分块效果

观察结果

即使是递归分块,当chunk_size设置太小时,也会把本应属于同一语义单元的内容切散。

比如"REQUIRED的含义是..."这句话可能被切成两块,第一块只有"REQUIRED",第二块是后面的解释,单独看第一块完全不知道在说什么。

结论:这就是为什么还需要语义分块或父子分块的原因——有些知识点天然就跨越多个句子,靠规则很难切好。

ChunkViz告诉你什么

通过这几组实验,你应该直观地理解了:

  1. 固定大小分块的问题:完全不理会文本结构,经常在句子中间切断
  2. 递归分块的优势:会尽量利用文本中的自然分隔符(换行、句号等)
  3. overlap的作用:重叠区域能缓解边界处的语义断裂
  4. chunk_size的影响:太小会切散语义,太大会引入噪音
实践建议

在确定分块策略之前,建议先拿几段实际的知识库文本在ChunkViz上试一试。调整参数,观察效果,找到最适合你场景的参数组合。这比盲目调参要高效得多。

下一步

ChunkViz只能帮你理解分块原理,真正写代码还得用框架。下一篇讲Spring AI系列的分片代码实战。

🎁优惠