父子分块
父子分块是一种两级层次结构的分块策略,通过创建小的子块和大的父块,实现检索精度和上下文完整性的完美平衡。
核心概念
父子分块将文档分成两个层级:
- 子块(Child Chunks): 较小的文本片段,用于精确的语义检索
- 父块(Parent Chunks): 较大的文本片段,包含多个子块,提供完整上下文
文档
├─ 父块 1 (1024 tokens)
│ ├─ 子块 1.1 (256 tokens) ← 用于检索
│ ├─ 子块 1.2 (256 tokens) ← 用于检索
│ ├─ 子块 1.3 (256 tokens) ← 用于检索
│ └─ 子块 1.4 (256 tokens) ← 用于检索
├─ 父块 2 (1024 tokens)
│ ├─ 子块 2.1 (256 tokens)
│ └─ 子块 2.2 (256 tokens)
...
工作原理
1. 父块如何分割?
父块是通过标题层级和Token 数量两个维度进行切分的:
切分规则:
-
优先按标题切分
- 根据
parent_split_level参数确定切分层级 - 例如:
parent_split_level=2表示在 H1 和 H2 标题处切分 - 保证每个父块在语义上是完整的章节或段落
- 根据
-
控制父块大小
- 目标大小由
parent_chunk_size控制(默认 1024 tokens) - 如果单个章节超过目标大小,会进一步切分
- 如果章节过小,会合并到下一个章节
- 目标大小由
-
添加重叠内容
- 相邻父块之间有
parent_chunk_overlaptokens 的重叠(默认 100 tokens) - 重叠区域确保跨块信息不会丢失
- 相邻父块之间有
示例:
# 第一章 系统概述 ← 父块边界(Level 1)
## 1.1 系统架构 ← 父块边界(Level 2)
系统采用三层架构...
(约 500 tokens)
## 1.2 核心组件 ← 父块边界(Level 2)
系统包含以下核心组件...
(约 600 tokens)
# 第二章 安装指南 ← 父块边界(Level 1)
...
如果 parent_split_level=2, parent_chunk_size=1024:
- 父块 1: "第一章 系统概述" 整章(1100 tokens,略超但保持完整)
- 父块 2: "第二章 安装指南" 开始...
2. 子块如何获取?
子块是通过**智能分块(Smart Chunking)**方法从父块中切分出来的:
生成过程:
-
从父块提取内容
- 父块已经确定边界,内容固定
-
应用智能分块算法
- 使用 Markdown AST 解析父块内容
- 识别段落、列表、表格、代码块等语义单元
- 尽量保持语义单元的完整性
-
控制子块大小
- 目标大小:
chunk_token_num(默认 256 tokens) - 最小大小:
min_chunk_tokens(默认 10 tokens) - 自动合并过小的片段,拆分过大的片段
- 目标大小:
-
建立父子关联
- 每个子块记录其所属的父块 ID
- 数据库中存储关联关系
示例:
父块内容(约 800 tokens):
## 1.1 系统架构
系统采用三层架构设计:
1. **展示层**: 负责用户界面展示
2. **业务层**: 处理业务逻辑
3. **数据层**: 数据持久化
### 展示层详解
展示层采用 React 框架...
(约 200 tokens)
### 业务层详解
业务层基于 Spring Boot...
(约 250 tokens)
### 数据层详解
数据层使用 PostgreSQL...
(约 180 tokens)
切分后的子块:
- 子块 1 (256 tokens): "## 1.1 系统架构\n\n系统采用三层架构设计...\n\n### 展示层详解\n展示层采用..."
- 子块 2 (250 tokens): "### 业务层详解\n业务层基于 Spring Boot..."
- 子块 3 (180 tokens): "### 数据层详解\n数据层使用 PostgreSQL..."
3. 父子关系存储
{
"parent_chunk": {
"id": "parent_001",
"content": "## 1.1 系统架构\n\n系统采用三层架构设计...(完整内容)",
"tokens": 800,
"page": 5,
"coordinates": [5, 50, 550, 100, 700]
},
"child_chunks": [
{
"id": "child_001",
"parent_id": "parent_001",
"content": "## 1.1 系统架构\n\n系统采用三层架构设计...",
"tokens": 256,
"coordinates": [5, 50, 550, 100, 300]
},
{
"id": "child_002",
"parent_id": "parent_001",
"content": "### 业务层详解\n业务层基于 Spring Boot...",
"tokens": 250,
"coordinates": [5, 50, 550, 300, 500]
}
]
}
检索模式
父子分块支持三种检索模式,可根据场景灵活选择:
模式 1: 仅返回父块 (retrieval_mode="parent")
工作流程:
用户查询 → 向量检索子块 → 返回子块对应的父块
特点:
- ✅ 提供最完整的上下文
- ✅ LLM 能看到更多相关信息
- ⚠️ 可能包含部分无关内容
- ⚠️ 消耗更多 Token
适用场景:
- 需要完整背景理解的问题
- 多步推理问题
- 需要跨段落信息的查询
示例:
用户问题: "系统的业务层使用什么技术?"
检索到子块: "### 业务层详解\n业务层基于 Spring Boot..."
↓
返回父块: "## 1.1 系统架构\n\n系统采用三层架构...(包含展示层、业务层、数据层的完整描述)"
模式 2: 仅返回子块 (retrieval_mode="child")
工作流程:
用户查询 → 向量检索子块 → 直接返回子块
特点:
- ✅ 精确匹配用户查询
- ✅ Token 消耗少
- ⚠️ 可能缺少必要的上下文
- ⚠️ 不适合需要背景理解的问题
适用场景:
- 事实性查询(定义、数据、步骤)
- 单一概念解释
- Token 预算有限
示例:
用户问题: "业务层使用什么框架?"
检索到子块: "### 业务层详解\n业务层基于 Spring Boot..."
↓
直接返回子块: "### 业务层详解\n业务层基于 Spring Boot...(仅该段落)"
模式 3: 同时返回父块和子块 (retrieval_mode="both")
工作流程:
用户查询 → 向量检索子块 → 返回子块 + 对应父块
特点:
- ✅ 兼顾精度和上下文
- ✅ LLM 可以根据需要选择信息
- ⚠️ Token 消耗最多
- ⚠️ 可能有冗余信息
适用场景:
- 复杂问题需要多层次信息
- 不确定需要多少上下文
- Token 预算充足
示例:
用户问题: "业务层在整个系统架构中的作用?"
检索到子块: "### 业务层详解\n业务层基于 Spring Boot..."
↓
返回:
1. 子块(精确匹配): "### 业务层详解\n业务层基于 Spring Boot..."
2. 父块(完整上下文): "## 1.1 系统架构\n\n系统采用三层架构...(三层架构完整介绍)"
配置参数
完整配置示例
{
"chunk_token_num": 256, // 子块目标大小
"min_chunk_tokens": 10, // 最小子块大小
"parent_config": {
"parent_chunk_size": 1024, // 父块目标大小
"parent_chunk_overlap": 100, // 父块之间的重叠
"retrieval_mode": "parent", // 检索模式: parent | child | both
"parent_split_level": 2 // 父块切分的标题层级
},
"enable_heading_in_content": false, // 是否在子块中包含标题层级
"enable_vision_enhancement": false, // 是否启用图片理解
"vision_description_format": "[图片描述]: {desc}",
"vision_batch_size": 3
}
参数详解
子块配置
chunk_token_num (默认: 256)
- 子块的目标大小
- 推荐范围: 128-512 tokens
- 较小值(128-256): 检索更精确,但上下文少
- 较大值(256-512): 上下文更多,但检索精度降低
min_chunk_tokens (默认: 10)
- 最小子块大小
- 小于此值的块会被合并或丢弃
- 避免产生无意义的碎片
父块配置
parent_chunk_size (默认: 1024)
- 父块的目标大小
- 推荐范围: 512-2048 tokens
- 通常设置为子块的 4-8 倍
- 过小: 上下文不足
- 过大: Token 消耗大,可能超出 LLM 限制
parent_chunk_overlap (默认: 100)
- 相邻父块之间的重叠区域
- 推荐: 父块大小的 5-10%
- 作用: 避免重要信息被切分到两个父块边界
parent_split_level (默认: 2)
- 父块按哪些标题层级切分
- Level 1: 仅 H1
- Level 2: H1 和 H2 (推荐)
- Level 3: H1、H2、H3
retrieval_mode (默认: "parent")
- parent: 返回父块
- child: 返回子块
- both: 返回父块和子块
产品使用指南
1. 在 KnowFlow 中配置
步骤 1: 创建知识库
- 登录 KnowFlow 系统
- 点击"创建知识库"
- 填写知识库名称和描述
步骤 2: 选择分块策略
- 在知识库设置中,找到"分块方法"
- 选择"父子分块(Parent-Child)"
- 点击"高级配置"
步骤 3: 配置参数
![父子分块配置界面示意]
基础配置:
子块大小: 256 tokens
最小块大小: 10 tokens
父块配置:
父块大小: 1024 tokens
父块重叠: 100 tokens
分割层级: Level 2 (H1 和 H2)
检索模式: 返回父块
高级选项:
□ 包含父标题
□ 启用图片理解
步骤 4: 上传文档
- 点击"上传文档"
- 选择 PDF、DOCX 或 Markdown 文件
- 等待解析完成
步骤 5: 预览分块效果
- 在文档列表中点击文档名称
- 查看"分块预览"
- 检查父块和子块的大小和内容
- 如不满意,调整参数后重新解析
2. 调试和优化
检查分块质量
父块检查:
- 每个父块是否语义完整?
- 父块大小是否合理(800-1500 tokens)?
- 父块之间的重叠是否有效?
子块检查:
- 子块是否保持了段落/列表的完整性?
- 子块大小是否均匀(200-300 tokens)?
- 是否有过小的子块(<50 tokens)?
常见问题和调整
问题 1: 父块过大(>2000 tokens)
原因: 单个章节内容太长,且没有子标题
解决方案:
{
"parent_split_level": 3, // 增加切分层级
"parent_chunk_size": 1536 // 适当增加父块大小上限
}
问题 2: 父块过小(<500 tokens)
原因: 文档标题层级过细
解决方案:
{
"parent_split_level": 1, // 减少切分层级,仅在 H1 切分
"parent_chunk_size": 2048 // 增加父块大小
}
问题 3: 子块不均匀
原因: 文档中有大表格或代码块
解决方案:
{
"chunk_token_num": 512, // 增加子块大小
"min_chunk_tokens": 50 // 提高最小块大小
}
问题 4: 检索返回结果不精确
尝试:
{
"retrieval_mode": "child" // 改为返回子块
}
问题 5: 检索返回结果上下文不足
尝试:
{
"retrieval_mode": "both", // 同时返回父块和子块
"parent_chunk_size": 1536 // 增加父块大小
}
3. 最佳实践
推荐配置模板
通用文档(推荐):
{
"chunk_token_num": 256,
"min_chunk_tokens": 10,
"parent_config": {
"parent_chunk_size": 1024,
"parent_chunk_overlap": 100,
"retrieval_mode": "parent",
"parent_split_level": 2
}
}
长文档/书籍:
{
"chunk_token_num": 256,
"min_chunk_tokens": 20,
"parent_config": {
"parent_chunk_size": 2048,
"parent_chunk_overlap": 200,
"retrieval_mode": "parent",
"parent_split_level": 1
}
}
技术文档(需要精确检索):
{
"chunk_token_num": 128,
"min_chunk_tokens": 10,
"parent_config": {
"parent_chunk_size": 768,
"parent_chunk_overlap": 50,
"retrieval_mode": "child",
"parent_split_level": 3
}
}
法律文档(需要完整上下文):
{
"chunk_token_num": 256,
"min_chunk_tokens": 20,
"parent_config": {
"parent_chunk_size": 1536,
"parent_chunk_overlap": 150,
"retrieval_mode": "both",
"parent_split_level": 2
},
"enable_heading_in_content": true
}
使用场景
适合的场景
✅ 技术文档和用户手册
- 需要精确定位具体步骤
- 同时需要了解整体流程
- 示例: API 文档、安装指南
✅ 学术论文和研究报告
- 需要精确引用某个论点
- 需要理解论点的完整论证过程
- 示例: 学术文献、专利文档
✅ 法律文档和合同
- 需要精确定位某个条款
- 需要理解条款的完整语境
- 示例: 法律法规、合同协议
✅ 多层级结构化内容
- 文档有清晰的章节层级
- 每个章节相对独立但又相互关联
- 示例: 教材、操作手册
不适合的场景
❌ 扁平结构文档
- 没有标题层级
- 使用智能分块或正则分块更合适
❌ 简短文档(<5 页)
- 文档本身已经很短
- 不需要复杂的层级结构
❌ 实时性要求高
- 父子分块处理速度较慢
- 建议使用智能分块或标题分块
❌ 存储空间有限
- 父子分块占用约 1.5-2 倍存储空间
- 建议使用其他分块策略
技术原理(简要说明)
算法流程
1. PDF 解析
↓
2. 提取 Markdown 内容
↓
3. 父块生成
├─ 按标题层级切分
├─ 控制块大小
└─ 添加重叠区域
↓
4. 子块生成
├─ 对每个父块应用智能分块
├─ 维护父子关联
└─ 向量化子块
↓
5. 存储到数据库
├─ 父块表
├─ 子块表
└─ 关联关系表
检索流程
用户查询
↓
向量化查询文本
↓
在子块向量库中检索 (相似度匹配)
↓
获取 Top-K 子块
↓
根据 retrieval_mode 决定:
├─ parent: 通过关联表获取父块
├─ child: 直接使用子块
└─ both: 获取父块 + 子块
↓
返回结果给 LLM
存储开销
假设文档大小为 X tokens:
- 智能分块: ~X tokens 存储
- 父子分块: ~1.8X tokens 存储
- 父块: X tokens
- 子块: X tokens
- 重叠部分: ~0.1X tokens
- 关联信息: ~0.05X tokens
常见问题
1. 父块和子块的大小比例如何设置?
推荐比例: 1:4 到 1:8
parent_chunk_size = chunk_token_num × 4 ~ 8
示例:
- 子块 256, 父块 1024 (1:4)
- 子块 256, 父块 2048 (1:8)
2. 什么时候使用哪种检索模式?
| 检索模式 | 使用场景 | Token 消耗 |
|---|---|---|
| parent | 需要完整上下文、多步推理 | 高 |
| child | 事实查询、定义解释 | 低 |
| both | 复杂问题、不确定上下文需求 | 最高 |
3. 父子分块比智能分块慢多少?
大约慢 1.5-2 倍:
- 需要两次分块(父块 + 子块)
- 需要建立和存储关联关系
- 向量化的数据量更大
4. 如何减少存储空间占用?
- 减小
parent_chunk_overlap - 使用
retrieval_mode="child"(可以不存储父块向量) - 增大
min_chunk_tokens过滤小块
5. 父子分块适合所有文档吗?
不适合:
- 扁平结构文档(无标题层级)
- 非常短的文档(<10 页)
- 实时性要求高的场景