RAG 文本切分与 Chunk Size:如何保留语义边界
文本切分是 RAG 索引阶段最容易被低估的一步。Embedding 模型只能看到你传入的 Chunk,如果一个业务规则的条件在切片边界被截断,后面的向量检索和答案生成都很难补回丢失的信息。
切片的目标不是把文本平均切成固定长度,而是让每个 Chunk 在足够短、可检索的同时,尽量保持一个完整语义单元。具体策略需要根据文档结构、问题类型、Embedding 模型和上下文预算共同确定。
先定义 Chunk 的数据契约
每个 Chunk 至少应包含以下字段:
{
"chunk_id": "doc-2026-v3-0042",
"document_id": "doc-2026",
"text": "正文片段",
"title_path": ["部署指南", "回滚"],
"source_url": "https://example.com/deploy",
"document_version": "2026-08-10",
"start_offset": 18240,
"end_offset": 18892,
"access_scope": ["platform-team"]
}text 用于 Embedding 和生成,其他字段用于过滤、引用、去重、调试和重新索引。只把文本字符串写进向量库,会导致后续无法可靠地展示来源,也很难定位是哪次切片策略产生了问题。
选择切分边界的优先级
推荐从结构到长度逐层降级:
- 先按文档标题和章节切分,保留标题路径。
- 再按段落、列表和引用块切分。
- 代码块、表格和 FAQ 问答尽量作为完整单元处理。
- 只有当语义单元超过长度限制时,才按句子或标点继续拆分。
- 最后才使用字符或 Token 长度作为硬上限。
Markdown 文档不能简单按换行切割。标题是上下文,列表项可能依赖上一段说明,表格的表头也不能和数据行完全分离。可以把标题路径拼接到 Chunk 前面,但要避免重复拼接造成上下文膨胀。
Chunk Size 和 Overlap 怎么定
Chunk Size 决定单个片段的最大长度,Overlap 用来缓解相邻片段之间的信息断裂。两者没有适用于所有语料的固定答案。
| 文档类型 | 起始策略 | 重点观察 |
|---|---|---|
| 产品说明、制度文档 | 按章节和段落,较小硬上限 | 条件和例外是否完整 |
| API 文档 | 按接口、参数和示例 | 请求示例是否与说明在一起 |
| 代码和配置 | 按文件、类、函数或配置段 | 依赖关系和上下文是否丢失 |
| FAQ | 一问一答,必要时保留分类标题 | 问题和答案是否被拆开 |
| 长报告 | 标题优先,长度作为兜底 | 召回片段是否过于宽泛 |
Overlap 不应被当成越大越好。重叠过大会增加索引体积和重复召回,重叠过小则可能截断定义、条件或步骤。更合理的做法是从一组保守参数开始,用固定评估集比较命中率、上下文重复率、Token 成本和端到端答案质量。
不同内容需要不同切片器
Markdown 和普通文章
优先使用标题、段落和列表边界。把标题路径作为元数据或轻量前缀,确保独立召回的 Chunk 仍能表达所在主题。
代码块和配置
不要把代码按普通句子切开。函数、类、接口定义和调用示例通常应该保持关联;超长文件可以按符号切分,并把包名、文件路径和相关类型写入元数据。
表格和结构化数据
表格需要保留表头。可以将每一行转成带字段名的自然语言文本,或按业务主键聚合成记录。不能只保留单元格值,否则召回后模型无法知道每个值对应哪个字段。
PDF 和扫描文档
PDF 解析的难点常常先于切片:页眉页脚、双栏顺序、页码、图片文字和表格布局都可能污染正文。应在切片前保留页码和来源定位,并抽样检查解析结果。
Go 实现时的边界问题
如果按字符数处理中文和英文混合文本,需要注意 Go 的字符串按字节存储。直接用 text[:n] 可能在中文 UTF-8 字符中间截断。按 Rune 遍历可以避免非法 UTF-8,但生产实现还要考虑句子边界、代码块和 Token 数量:字符数并不等于模型 Token 数。
切片函数最好是纯函数,输入文档和策略,输出带稳定 ID 的 Chunk 列表。把索引写入、Embedding 调用和重试放在外层,便于单元测试和幂等重建。
用评估反馈调整策略
切片优化至少要看四类信号:
- 召回命中:问题需要的证据是否出现在 Top-K 候选中。
- 边界完整:答案所需的条件、例外和步骤是否在同一个上下文中。
- 重复程度:Overlap 是否让多个候选片段重复表达相同内容。
- 生成成本:上下文长度、延迟和 Token 消耗是否可接受。
建立一组包含事实查询、跨段落查询、代码查询和条件查询的问题集。每次调整 Chunk Size 或切分器后,记录参数、索引版本和评估结果。不要只凭几条人工问题判断策略优劣。
常见错误
- 只按固定字符数切分,完全忽略标题和段落。
- 把标题、表头和条件拆开,导致 Chunk 缺少语义主体。
- Overlap 设置过大,造成重复召回和成本上升。
- 只保存向量,不保存来源、版本和权限元数据。
- 直接用字符串字节下标切中文,产生非法或残缺文本。
- 用“回答看起来不错”代替可重复的检索和生成评估。
