| name | document-chunking |
| tier | meta |
| description | 把文档切成块供下游处理。在批量观察样本、给抽取工作流喂数据、或把长篇监管文档 切成 worker LLM 装得下的块时使用。涵盖:用于快速探索的便宜方法(按页 / 定长 / 按标题),以及用于结构化长文档生产级分块的"洋葱剥离"层次策略 + "楔入法"兜底 (借鉴 pdf2skills)。也涵盖最核心的平衡问题:块太大 —— 关键信息淹没在一堆草料里; 块太小 —— 语义连续性被打断。
|
文档分块处理
把文档切成块供下游处理,分两套:
- 便宜分块 —— 探索性、批量处理样本时用的快速方法。
- 层次分块 —— 长结构化文档用的"洋葱剥离"策略(借鉴 pdf2skills 方法论),加上对无标题段落的"楔入法"兜底。
跨两套都最关键的问题:块应该多大? 见下文"找到平衡"一节再决定具体尺寸。
便宜方法
按页切分 —— 最简单的方式。每页即为一个块。适用于大多数遍历文档的场景,例如初步观察样本、统计页数分布。不依赖文档内部结构,鲁棒性最高。
定长分块 —— 按字符数或 token 数切分,相邻块之间保留少量重叠。适合构建检索索引或做初步观察。重叠的作用是避免边界处的语义被切断导致后续匹配漏检。
按标题切分 —— 识别章节标题、在标题边界处切分。能保留语义完整的章节单元。前提是文档有一致的标题约定,能用正则表达。
洋葱剥离法 —— 层次策略(长结构化文档的首选)
基于标题层级的分级分解。叫"洋葱剥离"是因为你从最外层结构一层层向内剥。
工作方式
- 解析文档的标题层级。 按级别识别所有标题(H1、H2、H3 —— 或文档自身格式中的等价物:"第一编"、"第一章"、"第 1.1 节"、 "第一条")。
- 构建一棵树。 每个标题是一个节点。标题之间的内容归属于最近一个上级标题所在节点。
- 检查大小。 遍历整棵树。若某个节点的内容(包括其所有子节点)在处理上限以内,就停在这里 —— 这个节点就是一个分块。
- 必要时才拆分。 若某节点超出上限,向下进入其子节点。只有当节点过大且确实有子标题可拆时才拆。
- 仍然过大的叶子节点交给"楔入法"兜底(见下文)。
为什么有效
- 尊重文档自身的语义结构。"第三章:风险揭示"分块严格对应作者本来的章节意图。
- 将信息损失降到最低。绝不会在一个意思的中间一刀切。
- 产出的分块大小不一致 —— 而这是好事。一个短章节作为一个完整分块,远胜于被强行劈成两半。
模式发现的捷径
在搭建完整解析器之前,先在几份样本文档上探索结构模式:
- 所有章节标题是否都以 "Chapter X" 或 "第X章" 开头?
- 节号是否一致编号(1.1、1.2、1.3)?
- 是否存在视觉标记(粗体、特定字体、横线分隔)?
如果你发现了稳定的模式,基于正则的分块器比基于 LLM 的结构识别更快、更可靠。例如:
^第[一二三四五六七八九十百]+章 匹配中文章节标题
^Chapter \d+ 匹配英文章节标题
^\d+\.\d+ 匹配编号小节
在投入使用前,对多份文档验证正则的正确性。
楔入法 —— 兜底(无清晰标题结构时)
适用于密集的法律文本、连绵的散文,或洋葱剥离后仍然过大、又没有可用子标题可拆的叶子节点。
工作方式
使用滚动上下文窗口,让算法对任意长度的文档都能伸缩。
- 窗口化内容。 将剩余未处理文本中的至多 MAX_TOKENS 载入一个窗口(数值可配置;选你的 LLM 能舒服读完的大小)。
- 让 LLM 标出切分点。 提示 LLM 在窗口里识别 1–3 个主题或议题发生变化的自然断点。对每个切分点,LLM 返回:
tokens_before:切分点之前约 K 个 token(默认 K=50),逐字摘自原文。
tokens_after:切分点之后约 K 个 token,逐字摘自原文。
chunk_title:为切分点之前的分块写一句 5–10 字的标题。
- 通过模糊匹配定位切点。 LLM 引用的 tokens 与原文不会完全一致(轻微改写、空白差异、编码痕迹)。用 Levenshtein 距离找最佳匹配位置;如果
tokens_after 匹配不上,退回仅依据 tokens_before 推出的位置。
- 滑动并重复。 把第一个已确认切点之前的文本切出作为一个分块。向前滑动窗口:新窗口从最后一个切点开始。重复,直到剩余文本可作为单一分块为止。
为什么有效
- LLM 识别的是语义边界,而不是任意字符位置。
- LLM 不重新生成文本 —— 它只引用位置。没有幻觉风险。
- 基于 K-token 引用 + Levenshtein 匹配的方法与语言无关。对中文、英文及多语种混合文档都同样适用。
- 滚动窗口意味着任意长度的文档都能增量处理 —— 算法不受上下文窗口大小限制。
- 模糊匹配能处理 LLM 引用文本与真实原文之间不可避免的小差异。
何时使用
- 仅在洋葱剥离法无法继续拆分(没有可用子标题)时使用。
- 用于完全没有结构化标记的文档。
- 成本考量:本方法需要调用 LLM。选用能完成主题边界识别的最便宜的模型即可。
找到平衡 —— 何时停止切分
两种失败模式:
- 分块过大:相关信息淹没在 LLM 上下文里的一堆草料中。即便在 LLM 的窗口之内,注意力也会在长输入上稀释 —— 块越长,真正的证据越容易被忽略。
- 分块过小:语义连续性断裂。一条需要"公司是银行" + "贷款额超阈值 X"两个事实合在一起才能触发的规则,可能看到它们被切到不同分块里,丢掉了关键合取关系。
如何找到平衡:
- 以下游任务为锚,而非以 LLM 上下文窗口为锚。 分块要足够大,能把下游规则所需证据完整放在一处。一条要比较两个条款的规则,这两个条款必须落在同一分块里。
- 优先用语义边界,而不是固定大小。 在章节边界切的块比硬撞 target token 数中途断句的块更有用。洋葱剥离在文档自然结束的地方停止 —— 利用这一点。
- 用真实下游消费方做测试。 在分块输出上跑一段抽取或判定。如果消费方漏掉了源文档里存在的证据,你的分块形状不对 —— 通常是太大或在错的地方切了。
- 关注方差,不止平均尺寸。 在一堆小块里夹几个巨型块比所有块均匀分布更糟,因为信息丢失就发生在那几个巨型块里。
- 别盲目朝 LLM 上下文窗口尺寸去优化。 一个 128K 上下文的模型技术上能吞 100K 的块;但能不能从这个块里精准取出证据是另一个问题。更小、边界更清晰的分块通常更胜一筹。
实践要点
- 分块大小取决于下游任务。 给编程智能体做规则抽取时,分块可以很大。给 worker LLM 处理时,分块必须能舒服装进它的上下文,再留出 prompt + 响应的空间。
- 保留上下文。 拆分时把父级标题链作为上下文带上。来自"第二编
第三章 > 第 3.2 节"的分块应包含这些标题,让下游处理知道内容所处的位置。
- 缓存分块树。 一旦文档结构已被解析,把树保存下来。多条规则可能需要同一文档的内容,重复解析就是浪费。
- 记录分块决策。 使用了哪种策略、产出多少分块、各自的大小。有助于排查下游问题。
与 tree-processing 的关系
本技能讲分块方法。tree-processing 讲为生产核查工作流设计精确、可编码的分块脚本 —— 在那里分块必须确定性、可复现、可测试。当上面的便宜方法满足不了生产路径的控制需求时,转用 tree-processing。