32|切分与元数据:chunk、重叠、标题、时间、权限标签
本文深入探讨RAG系统中数据切分(Chunking)与元数据(Metadata)的关键作用。通过将长文档切分为语义完整的片段(如按Markdown标题结构切分),并设置重叠区保持上下文连贯,可显著提升检索精度。同时,为每个数据块添加来源、时效、权限等元数据标签,能实现精准的前置过滤,避免返回过期或越权信息。文章提供了工业级切分策略指南,强调"元数据过滤+向量检索"的组合才是解决AI幻觉问题的核心方
在上一篇,我们费了九牛二虎之力,把公司各种 PDF、网页、代码,全部洗成了干净的纯文本(比如几十本十几万字的 Markdown 文档)。
你可能会想:“太好了!现在只要把这 10 万字的《员工手册》转成向量存进数据库,AI 就能回答问题了吧?”
绝对不行!
如果你把一整本 10 万字的书当成一个整体去算“语义相似度”,结果就是:它的语义变成了一锅大杂烩。当用户问“婚假怎么请?”时,系统根本无法从这“一锅粥”里精准捞出写着婚假的那一小段话。
为了让检索精准,我们必须把长文档**“切碎”**。这在 RAG(检索增强生成)工程中,被称为 Chunking(切分)。
同时,为了切碎后还能找到出处,我们必须给每块碎肉贴上标签,这叫 Metadata(元数据)。
本篇,我们就来攻克 RAG 系统里最考验内功的一环:如何切得刚刚好?
1. 切分(Chunking):为什么切,怎么切?
Chunk(数据块/片段)是 RAG 检索的最小单位。
你可以把一本书想象成一根长长的香肠,Chunk 就是你切下来的一片片香肠。当 AI 饿了(用户提问)时,检索系统只会挑最符合口味的 3~5 片香肠喂给它,而不是把整根香肠塞进去。
常见的切分策略(从初级到高级)
-
按固定字符数切分(Fixed-size Chunking)
- 做法:简单粗暴,每 500 个字切一刀。
- 坑点:极其危险!如果刚好在“因为张三没有 / 签字,所以报销被驳回”这句话中间切了一刀,前一个 Chunk 只剩“张三没有”,后一个 Chunk 只有“签字”,AI 看了直接懵逼。
-
按自然段落切分(Recursive Character Text Splitter)
- 做法:优先按双换行符(
\n\n,即段落)切;如果一个段落太长(超过 1000 字),再按单换行符(\n)切;如果还长,再按句号(。)切。 - 优点:这是目前最常用的基线策略,能最大程度保证一句话或一个段落的完整性。
- 做法:优先按双换行符(
-
按文档结构切分(Markdown/HTML Header Splitter) —— (强烈推荐)
- 做法:利用我们在上一步清洗出的 Markdown 标题结构来切。比如把
## 婚假规定下面的所有正文作为一个 Chunk,把## 产假规定下面的作为另一个 Chunk。 - 优点:极度精准!因为同一个标题下的内容,天然具有最强的语义连贯性。
- 做法:利用我们在上一步清洗出的 Markdown 标题结构来切。比如把
关键技巧:重叠(Overlap)
就算按句号切分,有时也会遇到上下文断裂的问题。
比如:
- Chunk 1:
张三是公司的财务总监。 - Chunk 2:
他昨天审批了一笔 100 万的报销。
如果系统只检索到了 Chunk 2,AI 根本不知道“他”是谁。
解决方案:在切分时设置 重叠区(Overlap)。
假设每个 Chunk 长 500 字,我们让相邻的 Chunk 重叠 50 个字。
这样 Chunk 2 的开头就会带上 Chunk 1 的结尾,变成:...张三是公司的财务总监。他昨天审批了一...。有了重叠,上下文就接上了!
2. 元数据(Metadata):碎片的“寻亲记”
当你把一本《员工手册》切成了 500 个 Chunk,并且把它们扔进了由几十万个 Chunk 组成的向量数据库(Vector DB)后,这 500 个片段就像滴入大海的水滴,瞬间失去了身份。
如果这时候系统捞出了一个写着“批准报销上限为 500 元”的 Chunk,AI 会很绝望:
- 这是哪本书里的规定?
- 哪一年发布的?现在还生效吗?
- 这是普通员工的规定,还是高管的规定?
为了回答这些问题,在切分 Chunk 的同时,我们必须给每一个 Chunk 贴上标签,这就是 元数据(Metadata)。
RAG 必备的 5 类元数据标签
| 元数据字段 | 英文名 | 示例值 | 为什么必须要有? |
|---|---|---|---|
| 文档来源 | source_url |
https://wiki/hr/leave |
引用的底气:AI 回答时必须附带来源链接,让用户自己去核实,这是解决幻觉的终极武器。 |
| 文档标题 | doc_title |
2024年员工休假制度 |
防止语义丢失:如果 Chunk 只有“休 3 天”,加上标题后,AI 就知道这是“2024年休假制度里的休 3 天”。 |
| 层级标题 | headers |
['第二章 福利', '2.1 婚假'] |
精确定位:这是按 Markdown 结构切分的好处,能完整保留这块碎肉在原书中的目录位置。 |
| 更新时间 | updated_at |
2024-03-01 |
时效过滤:如果库里有 2023 和 2024 两版制度,检索时可以用时间标签直接把旧版过滤掉。 |
| 权限标签 | access_level |
['public', 'hr_only'] |
安全红线:普通员工提问时,底层检索器会直接带上条件 WHERE access_level CONTAINS 'public',让越权数据根本无法被召回。 |
3. 切分与元数据组合的威力:前置过滤(Pre-filtering)
很多人以为 RAG 里的向量数据库只能做“语义模糊搜索”(查出长得像的句子)。
其实,“元数据过滤 + 向量检索” 才是工业级 RAG 的真正形态。
场景:2024年3月,普通员工王五提问:“我结婚能休几天假?”
糟糕的 RAG(只有向量,没有元数据):
- 向量库算出“结婚、休假”的向量。
- 捞出了 3 个 Chunk:
- 2018年废弃的休假制度(3天)
- 高管的特殊休假制度(10天)
- HR 内部的处理 SOP
- AI 看了这三个矛盾的片段,开始胡言乱语。
优秀的 RAG(向量 + 元数据):
- 系统先根据提问者身份和时间,拼装出检索条件:
WHERE access_level = 'public' AND updated_at >= '2024-01-01'(这叫 前置过滤 Pre-filtering)。 - 在过滤后剩下的安全、最新的数据池里,再去算“结婚、休假”的向量相似度。
- 完美捞出唯一正确的 Chunk,AI 准确回答:“根据《2024年员工休假制度》(附链接),您可以休 3 天。”
4. 本篇产出:切分策略指南(可复用)
搭建知识库时,不要盲目调参。请把这份策略指南保存下来,作为你们团队切分数据的默认基线配置:
# 知识库 Chunk 切分与元数据基线配置 v1.0
## 一、 文本切分参数 (Text Splitter)
- **切分算法**:优先使用 `MarkdownHeaderTextSplitter`(按 H1/H2/H3 切分)。
- **降级算法**:如果 Markdown 某一段过长,降级使用 `RecursiveCharacterTextSplitter`。
- **Chunk 长度 (Chunk Size)**:500 - 800 Tokens(太短缺上下文,太长塞不进 Prompt,800 是兼顾命中率和消耗的甜点位)。
- **重叠长度 (Overlap Size)**:100 - 150 Tokens(通常为 Chunk 长度的 15% - 20%,保证句子不被硬切断)。
## 二、 必须注入的 Metadata 结构
每个送入向量库的 Chunk 必须且仅包含以下 JSON 结构:
{
"chunk_id": "uuid-xxx",
"text": "具体的正文内容...",
"metadata": {
"doc_id": "doc-001", // 溯源:属于哪份原始文档
"source": "https://wiki/...", // 引用:给用户看的点击链接
"title": "2024版报销制度", // 补充语义:大标题
"headers": ["第二章", "交通费"], // 补充语义:所在章节
"updated_at": "2024-03-01", // 过滤条件:时效性
"permission": ["all_staff"] // 过滤条件:可见权限(极其重要!)
}
}
总结与复盘
- 切分(Chunking) 解决了“AI 一口吃不下个胖子”且“容易找错重点”的问题。合理利用 Markdown 结构切分并保留重叠区(Overlap),是保证语义完整的关键。
- 元数据(Metadata) 是数据碎片的“身份证”。没有权限标签、时间标签和来源链接的数据,在企业应用中就是一颗定时炸弹。
- 记住工业级 RAG 的黄金公式:元数据精准过滤 + 向量模糊召回。
下一步路线提示:
现在,带有漂亮标签的碎肉(Chunk)已经整整齐齐地躺在向量数据库里了。当用户抛出一个问题时,系统到底是怎么把最匹配的 Chunk “捞”出来的?仅仅靠相似度就够了吗?下一篇,我们将揭开 RAG 的心脏:《检索:召回、重排、过滤与多路检索》。
更多推荐

所有评论(0)