模板化文本切分策略:可控可解释的分块设计
模板化文本切分策略:可控可解释的分块设计
学习目标
读完本章后,你将能够:
- 理解模板化切分相比纯启发式切分的优势
- 设计基于文档结构的切分模板
- 在 Token 级别精确控制 chunk 大小和重叠
- 选择合适的切分策略应对不同文档类型
前置知识
- RAG 全链路可视化管线 — RAG 管线的索引阶段
- 深度文档理解 — 文档解析后的结构化输出
1. 为什么需要模板化切分
传统的文本切分方法(如按固定字符数或 Token 数切分)面临两个核心问题:
- 语义断裂:在段落中间、句子中间强行切断,导致 chunk 丢失上下文
- 一刀切:不同文档类型(论文、法律合同、手册、简历)有不同的结构,同一套参数无法适应所有场景
模板化切分的核心理念:利用文档的结构信息(标题、段落、表格等)引导切分边界,使每个 chunk 在语义上尽可能完整。
2. 模板化切分的分层设计
2.1 标题感知切分
标题(Heading/Title)是文档最天然的结构边界。标题感知切分的工作流程:
- 从文档解析结果中提取所有标题及其层级(H1 > H2 > H3)
- 以标题为边界,将文档划分为大的段落
- 对过大的段落再进行 Token 级别切分
- 每个 chunk 携带其所属标题路径作为元数据
示例:H1: 第一章 引言 H2: 1.1 背景 [段落内容 - 如果超过 max_tokens,则继续切分] H2: 1.2 目的 [段落内容]
生成的 chunk 元数据:{ "text": "...", "title_path": "第一章 引言 > 1.1 背景", "chunk_index": 0}2.2 Token 级别精确控制
标题切分后,对每个段落进行 Token 级别的精确控制:
| 参数 | 说明 | 典型值 |
|---|---|---|
max_tokens | 单个 chunk 的最大 Token 数 | 512-2048 |
overlap_tokens | 相邻 chunk 的重叠 Token 数 | max_tokens 的 10-20% |
tokenizer | Token 计数器 | tiktoken(OpenAI)或 HuggingFace tokenizer |
重叠窗口的作用:避免切分边界处的语义丢失。相邻 chunk 共享一部分内容,确保跨边界的查询仍能命中相关内容。
2.3 特殊区域处理
文档中的某些区域需要特殊处理:
| 区域类型 | 处理策略 |
|---|---|
| 表格 | TSR 转换为自然语言后独立成一个 chunk |
| 代码块 | 保持完整,不切分(除非超出 max_tokens) |
| 公式 | LaTeX 格式保留,不切分 |
| 列表 | 保持完整列表项 |
| 引用/参考文献 | 独立处理或标记后合并 |
3. 常见切分模板
不同文档类型对应不同的切分模板:
| 模板 | 适用场景 | 核心策略 |
|---|---|---|
| 通用模板 | 普通文档、手册 | 标题切分 + Token 控制 |
| 论文模板 | 学术论文 | 按章节切分,摘要/方法/结果独立,保留引用 |
| 法律模板 | 合同、法规 | 按条款切分,保留条款编号,不跨条款切分 |
| 简历模板 | 简历/CV | 按个人信息、教育、经历、技能分段 |
| 手册模板 | 操作手册、FAQ | 按问题-答案对切分 |
| QA 模板 | 问答对数据集 | 每个 QA 对为一个 chunk |
4. 问题与规避
| 陷阱 | 对策 |
|---|---|
| chunk 过大导致检索噪声 | 降低 max_tokens,启用标题切分确保语义聚焦 |
| chunk 过小丢失上下文 | 增加 overlap_tokens,保留标题路径元数据 |
| 切分后 Token 计数不准 | 使用与 Embedding 模型匹配的 tokenizer |
| 特殊字符(如 Markdown 标记)干扰 | 先清洗格式,再切分 |
| 标题层级嵌套过深 | 限制最大标题深度(如只取 H1-H3) |
5. 设计取舍
固定大小切分 vs 语义感知切分
| 维度 | 固定大小切分 | 语义感知切分 |
|---|---|---|
| 实现难度 | 低 | 中 |
| 语义完整性 | 差(可能在句子中间切断) | 好(在自然边界处切断) |
| 适用场景 | 纯文本、无结构文档 | 有标题/段落结构的文档 |
| chunk 大小分布 | 均匀 | 不均匀(取决于段落长度) |
推荐:优先使用语义感知切分(标题切分),对超大段落回退到固定大小切分。
重叠 vs 不重叠
| 维度 | 有重叠 | 无重叠 |
|---|---|---|
| 存储成本 | 高(重复数据) | 低 |
| 检索质量 | 高(边界查询仍能命中) | 低(跨边界查询可能丢失) |
| 适用场景 | 通用场景 | 存储成本敏感 |
推荐:默认使用 10-20% 的重叠率。如果存储成本是瓶颈,可降低重叠但必须在检索端增加回退策略(如同时检索相邻 chunk)。
参考来源
- LangChain Text Splitters 文档:https://python.langchain.com/docs/modules/data_connection/document_transformers/
- “What Makes Good RAG Chunking?” 研究综述
补充:LlamaIndex 的 MetadataAware 分块架构
来源:LlamaIndex llama-index-core v0.14.22,commit f027669
MetadataAwareTextSplitter:token 预算管理
LlamaIndex 的分块器(MetadataAwareTextSplitter)在计算 chunk 大小时,先从 chunk_size 中减去 metadata 占用的 token 数,确保 “metadata + chunk content” 的总 token 数不超过限制。
常见陷阱:当 metadata 包含完整文件路径、时间戳、自定义标签时,可能占用 50-200 个 token。如果 chunk_size=512,实际可用内容 token 可能只有 300-400。
# LlamaIndex 的内部计算逻辑(伪代码)available_tokens = chunk_size - count_tokens(metadata_str)# 然后用 available_tokens 限制 content chunk 大小SentenceWindowNodeParser:检索-展示分离
LlamaIndex 提供了一种独特的分块策略:存储时用小窗口(单个句子),检索时自动扩展前后文。
适用场景:当 embedding 模型对短句效果更好时,用小粒度索引提高检索精度,用窗口扩展提供充足的上下文给 LLM。
可用分块器一览
| 分块器 | 策略 | 特点 |
|---|---|---|
TokenTextSplitter | 按 token 数量 | 分层分割(separator → backup separator → 字符),默认 1024/20 |
SentenceSplitter | 按句子 | 默认分块器,保持句子完整性 |
SemanticSplitter | 按 embedding 相似度 | 在语义边界处断点,避免跨主题 chunk |
SentenceWindowNodeParser | 句子 + 窗口扩展 | 小粒度索引 + 大粒度上下文 |
CodeSplitter | 按代码语法 | 基于 tree-sitter 的语法感知分块 |