切块与元数据
Chunk 大小、重叠、按结构切分,以及用于过滤的元数据。
一句话理解:切块决定“检索的最小单位长什么样”,元数据决定“这个单位是谁、何时有效、谁能看”;两者做不好,再强的检索和模型也找不准。
一份 60 页的《退款政策》,如果整份作为一个检索单位,任何与退款有关的问题都会命中它,但模型要在 60 页里找答案;如果切成一句一段,“已开票订单需先完成发票作废”这一句可能被检索到,但它前面那句“以下规定仅适用于 2026 年 8 月 1 日之后创建的订单”却丢了。
切块(Chunking)看起来是一个技术细节,实际上是 RAG 效果的第一道闸门。元数据(Metadata)则是在语义搜索之外,给每个片段加上的“身份证”。这一课讲清楚两者的设计方法。
为什么要切块,以及切多大
需要切块的原因有两个:
- 检索精度:一个片段只表达一个主题时,它的 Embedding 才能准确代表它的含义。整章内容混在一起,坐标会落在几个主题的“中间地带”。
- 上下文预算:检索到的内容要放进上下文,片段越大,能放的片段越少,干扰信息也越多。
但片段也不能太小:
| 片段太大 | 片段太小 | |
|---|---|---|
| 检索表现 | 主题混杂,相关度打分模糊 | 单句缺少上下文,难以判断是否相关 |
| 生成表现 | 关键信息被淹没 | 缺少前提条件、例外条款 |
| 知识库例子 | 一个片段同时包含“退款时限”“开票订单退款”“换货条件”三节 | “需先完成发票作废”这句话,看不出适用于什么情况 |
没有放之四海皆准的最佳大小。常见的起点是几百 Token 一个片段,再根据评测结果调整。比“大小”更重要的,是 切在哪里。
切分方式:从按长度到按结构
常见的切分方式有四种:
重叠(Overlap) 的作用是缓解“切断”问题:相邻片段共享一小段内容,一句话即使恰好落在边界上,也会完整出现在其中一个片段里。但重叠会增加索引量,也可能导致同一内容被重复召回,需要在组装上下文时去重。
表格是重灾区。 一张价格表被按长度切开后,下半部分的片段里只有数字没有表头,模型根本不知道“38.5”是什么。常见做法是把每一行转写成完整的句子,例如“企业版,51–200 席位,年付,单价 38.5 元/席/月”,并让每一行都携带表格标题。
给片段补上“它来自哪里”
切块最隐蔽的问题是 片段丢失了所在文档的背景。比如某个片段的内容是:
已开具发票的订单,应先完成发票作废,再发起退款。
单看这一句,不知道是哪份文档、哪条产品线、哪个版本。用户问“企业版订单开票后怎么退款”时,它可能排不到前面;用户问“个人版订单开票后怎么退款”时,它反而可能被错误召回。
两种互补的补救方式:
1. 片段标题路径。 在片段前拼上文档名和章节路径:
《退款政策》v3 > 第 4 章 发票与退款 > 4.2 已开票订单的退款
已开具发票的订单,应先完成发票作废,再发起退款。
2. 上下文化片段(Contextual Retrieval)。 Anthropic 在 2024 年提出的方法:索引时,把整份文档和某个片段一起交给模型,让它生成一段简短的说明(通常 50 到 100 Token),描述这个片段在整份文档中的位置和含义,再拼接到片段前面,然后才做 Embedding 和关键词索引。
上下文化片段的索引流程如下:
在 Anthropic 公布的实验中(检索前 20 个片段的失败率):
| 方法 | 检索失败率的降低 |
|---|---|
| 仅对向量检索使用上下文化片段 | 35% |
| 向量检索 + 关键词检索都使用上下文化片段 | 49% |
| 再加上重排序 | 67% |
这是在他们的数据集上的结果,你的业务效果需要自己评测。但它说明了一个普遍规律:片段的可检索性,很大程度上取决于它是否自带足够的背景。 生成说明需要对每个片段调用一次模型,文章中提到可以配合提示缓存(整份文档作为可复用的前缀)大幅降低这部分成本。
元数据:语义搜索做不到的事交给它
元数据是片段附带的结构化字段。它不参与“语义相似度”计算,而是用于 过滤、排序、引用和治理。
一个知识片段的完整样子:
{
"chunk_id": "refund-policy-v3-4.2-01",
"text": "《退款政策》v3 > 4.2 已开票订单的退款\n已开具发票的订单,应先完成发票作废……",
"metadata": {
"doc_id": "refund-policy",
"doc_title": "退款政策",
"section_path": ["第 4 章 发票与退款", "4.2 已开票订单的退款"],
"version": "v3",
"status": "effective",
"effective_from": "2026-08-01",
"business_line": "after_sales",
"region": ["national"],
"doc_type": "policy",
"access_groups": ["support", "finance"],
"source_url": "kb://policies/refund-policy/v3#4.2",
"updated_at": "2026-07-25"
}
}
每一类字段对应一个用途:
| 字段类别 | 例子 | 用途 |
|---|---|---|
| 身份 | doc_id、section_path、source_url |
引用出处、定位原文、去重 |
| 版本与时效 | version、status、effective_from、updated_at |
过滤过期内容,新版优先 |
| 业务范围 | business_line、region、doc_type |
按用户场景缩小检索范围 |
| 权限 | access_groups、租户 ID |
在检索时过滤用户无权查看的内容 |
把片段本身、元数据字段和它们的用途放在一起看:
元数据过滤应该由程序在检索时执行,而不是把所有结果交给模型再让它“注意版本”。例如华东区售后客服提问时,检索条件自动附加 status = effective、region ∈ {national, east}、access_groups ∩ 用户组 ≠ 空。版本与权限的完整设计见 知识保鲜与权限。
元数据的难点不在于设计字段,而在于 谁来填、怎么保证填对。能从文档管理系统自动同步的尽量自动同步;需要人工标注的字段越少越好,并在导入流程里做校验。
常见误区
- “找一个最佳 Chunk 大小就行。” 切在哪里比切多大更重要。按结构切分、保留条款完整,通常比调长度更有效。
- “元数据只是锦上添花。” 没有版本和权限元数据,过期规则与越权内容就只能靠模型自觉,这在生产环境不可接受。
- “表格和正文一样处理。” 表格被按长度切开后几乎不可用。要单独处理,并让每行都带表头。
产品经理检查清单
- 知识库文档是否有稳定的结构(标题、条款编号、问答对)?能否按结构切分?
- 关键信息是否大量存在于表格中?表格怎么处理?
- 片段是否带有文档名和章节路径?是否考虑上下文化片段?
- 元数据有哪些字段?哪些用于过滤、哪些用于引用、哪些用于权限?
- 元数据由谁维护?自动同步还是人工标注?如何校验?
- 修改切块策略后,是否会用评测集验证检索效果?
练习
从你的知识库里挑 2 份结构不同的文档(例如一份制度、一份含价格表的文档):
- 为每份文档设计切分方案:按什么切、多大、是否重叠、表格怎么处理。
- 手工切出其中 5 个片段,为每个片段加上标题路径,并按上文 JSON 的格式填写元数据。
- 找一个片段,试着写出一段 50 到 100 字的“上下文说明”,对比加说明前后,你作为读者能否判断它适用于什么情况。
- 写出 3 条应当在检索时由程序执行的过滤规则。
延伸阅读
- Anthropic:Introducing Contextual Retrieval
下一步
片段切好、元数据补齐之后,下一课「混合检索与重排序」讲如何把关键词检索与向量检索结合起来,再用重排序把最相关的几段挑出来。