ChunkViz实验与可视化
上一篇讲了分块策略的理论,但光看文字描述可能还不够直观。
这篇用一个免费的在线工具——ChunkViz,来可视化地展示不同分块策略的效果,让你亲眼看到"切大了"和"切小了"的区别。
ChunkViz是什么
ChunkViz是一个免费的在线分块可视化工具,支持两种分块策略:
- CharacterTextSplitter:固定大小分块
- RecursiveCharacterTextSplitter:递归分块
你可以实时调整chunk_size和overlap参数,页面会用不同颜色高亮显示每个块的范围。
建议你在看下面的实验之前,先自己打开ChunkViz玩一玩。把自己项目中的文档内容粘贴进去,调调参数,感受会更深。
操作步骤
- 打开 https://chunkviz.up.railway.app/
- 在文本框中粘贴你想测试的文本
- 在右侧选择分块策略:
- CharacterTextSplitter:对应固定大小分块
- RecursiveCharacterTextSplitter:对应递归分块
- 调整 Chunk Size 和 Chunk Overlap 的滑块
- 页面会实时用不同颜色高亮显示每个块的范围
ChunkViz界面:
实验准备:测试文本
我们用一段在线教育课程的讲义来做实验:
第一章:Java基础语法
Java是一种面向对象的编程语言,由Sun公司于1995年推出。Java具有跨平台、安全性高、面向对象等特点,被广泛应用于企业级应用开发。
学习Java的第一步是搞懂变量和数据类型。Java是强类型语言,每个变量必须声明其类型。基本数据类型包括:int、long、float、double、boolean、char等。
第二章:面向对象编程
面向对象是Java的核心特性。它包括三大特征:封装、继承和多态。封装是指将数据和操作数据的方法绑定在一起,隐藏内部实现细节。
继承允许一个类获取另一个类的属性和方法。在Java中,使用extends关键字实现继承。多态是指同一个方法调用可以有不同的行为,这通过方法重写和接口实现。
下面做几组对比实验:
| 实验 | 策略 | chunk_size | overlap | 观察重点 |
|---|---|---|---|---|
| 实验1 | CharacterTextSplitter | 100 | 20 | 看块的边界是不是经常切在句子中间 |
| 实验2 | RecursiveCharacterTextSplitter | 200 | 0 | 对比实验1,看是否更倾向于在段落边界切割 |
| 实验3 | RecursiveCharacterTextSplitter | 80 | 0 | chunk_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告诉你什么
通过这几组实验,你应该直观地理解了:
- 固定大小分块的问题:完全不理会文本结构,经常在句子中间切断
- 递归分块的优势:会尽量利用文本中的自然分隔符(换行、句号等)
- overlap的作用:重叠区域能缓解边界处的语义断裂
- chunk_size的影响:太小会切散语义,太大会引入噪音
在确定分块策略之前,建议先拿几段实际的知识库文本在ChunkViz上试一试。调整参数,观察效果,找到最适合你场景的参数组合。这比盲目调参要高效得多。
下一步
ChunkViz只能帮你理解分块原理,真正写代码还得用框架。下一篇讲Spring AI系列的分片代码实战。