企业级 RAG 多路召回智能客服实战:第 3 章,文档解析与切分

上一章我们讲了知识库数据治理:数据来源、清洗、元数据、权限、版本和 FAQ/工单治理。

这一章继续往下走,讨论 RAG 系统里一个非常容易被低估的问题:文档解析与切分。

很多 RAG Demo 里会直接把文档按固定长度切成 chunk,比如每 500 字一段、重叠 50 字。这个方法能跑,但一旦进入企业客服场景,很快会出现问题:

  • 一个完整流程被切成好几段,模型只看到其中一步;
  • 标题和正文分离,召回时不知道这段内容属于哪个功能;
  • 表格被拆坏,套餐对比、错误码说明全乱了;
  • 图片、代码、接口字段没有被保留;
  • 同一篇文档不同版本混在一起;
  • chunk 没有元数据,权限过滤和引用来源做不起来。

RAG 的召回效果,很大程度取决于 chunk 质量。切得太碎,语义不完整;切得太大,召回不精确、上下文成本高。企业级系统要做的是“结构化切分”,而不是简单按字数切。

一、解析和切分要分开看

文档入库通常有两个步骤:

原始文件 -> 格式解析 -> 结构化文档 -> 切分 chunk -> 建索引

格式解析解决的是“文档里有什么”。切分解决的是“哪些内容应该作为检索单元”。

不要在解析阶段就急着切 chunk。更好的做法是先把文档解析成结构化对象,例如:

{
  "title": "账号权限管理",
  "sections": [
    {
      "path": ["账号权限管理", "管理员权限", "报表导出"],
      "level": 3,
      "text": "报表导出需要同时满足角色权限和功能开通状态。",
      "tables": [],
      "images": []
    }
  ]
}

有了结构,后面才能按标题、段落、表格、代码块和业务含义切分。

二、不同格式的解析重点

1. Markdown

Markdown 最适合做知识库,因为标题、列表、代码块都比较清楚。

解析重点:

  • 保留标题层级;
  • 保留代码块语言;
  • 保留表格原始结构;
  • 保留链接和图片 alt 文本;
  • 不要把 front matter 当正文。

2. HTML

帮助中心、官网文档和内部知识库通常是 HTML。

解析重点:

  • 删除导航、页脚、侧边栏、推荐文章;
  • 保留正文区域;
  • 保留标题层级;
  • 把表格转成 Markdown 表格;
  • 把内部链接转成可追溯来源。

网页解析最怕把无关区域一起入库。一个简单原则:用户不会问“上一篇、下一篇、点赞、收藏”,这些内容就不应该进入 chunk。

3. PDF

PDF 是企业知识库里最麻烦的格式。

常见问题:

  • 换行被打断;
  • 多栏排版顺序错乱;
  • 页眉页脚重复;
  • 表格解析失败;
  • 扫描件需要 OCR;
  • 图片里的关键文字丢失。

PDF 入库前要做抽样检查。不要看到能提取文本就直接上线,否则后面召回到的可能是一堆断裂句子。

4. Word

Word 文档通常有比较清楚的标题样式,但也可能有批注、修订痕迹和内嵌表格。

解析重点:

  • 使用样式识别标题;
  • 清理批注和修订;
  • 保留表格;
  • 识别图片说明;
  • 保留文档属性里的作者、部门和更新时间。

三、chunk 不是越短越好

一个常见误区是:chunk 越短,召回越精确。

这只对一部分场景成立。客服问答里很多问题需要完整步骤、条件和例外说明。如果切得太短,模型会漏掉关键上下文。

例如文档里写:

报表导出需要满足两个条件:
1. 当前账号拥有“报表导出”角色权限;
2. 当前租户已经开通“高级报表”功能。
如果仍提示无权限,请检查成员是否加入正确组织。

如果切成三段,召回时只拿到第一条条件,答案就会不完整。

更合理的 chunk 单元应该是“一个最小可回答单元”,而不是固定字数。

四、推荐的切分策略

企业客服知识库可以采用“标题层级 + 长度控制 + 语义边界”的混合策略。

1. 先按标题切

标题天然代表语义边界。

例如:

账号权限管理
  - 管理员权限
  - 报表导出权限
  - 成员角色配置

每个二级或三级标题下的内容,可以优先作为候选 chunk。

2. 再按段落和列表切

如果一个章节太长,再按段落、列表、表格进行二次切分。

切分时要避免把列表拆散。流程步骤、条件列表、错误码表通常应该保持完整。

3. 最后按 token 限制兜底

如果内容仍然太长,再按 token 限制切分,并保留 overlap。

推荐做法:

  • 普通说明类 chunk:300 到 800 中文字;
  • 操作步骤类 chunk:尽量保持完整步骤;
  • 表格类 chunk:按表格整体或按行组切分;
  • FAQ 类 chunk:一个问答对就是一个 chunk;
  • 工单案例类 chunk:一个案例就是一个 chunk。

五、chunk 要带标题路径

很多系统只把正文拿去 embedding,这会损失大量上下文。

例如正文只有一句:

该功能仅专业版和旗舰版支持。

如果没有标题路径,模型不知道“该功能”是什么。

更好的 chunk 文本应该拼上标题路径:

文档:报表中心使用手册
章节:权限说明 > 报表导出
正文:该功能仅专业版和旗舰版支持。

这样 embedding 和关键词检索都更容易命中。

六、表格怎么处理

企业文档里大量关键信息在表格里,比如套餐对比、错误码、接口字段、权限矩阵。

表格不能简单按行拼文本,否则会丢失列含义。

推荐把表格转换成 Markdown 或行级结构:

表格:套餐权限对比
列:套餐、是否支持报表导出、是否支持 API 调用
行:标准版,不支持,支持基础 API
行:专业版,支持,支持高级 API
行:旗舰版,支持,支持高级 API 和专属限流

如果表格很大,可以按业务主题或行数分组,但每个 chunk 都要保留表头。

七、代码和接口文档怎么切

如果客服系统服务的是开发者,代码和接口文档也会进入知识库。

接口文档建议按接口切分:

接口:POST /v1/orders/query
用途:查询订单状态
参数:order_id、user_id
返回:status、tracking_no、updated_at
错误码:ORDER_NOT_FOUND、NO_PERMISSION

代码示例建议和说明绑定在一起,不要把代码单独切出去。否则用户问“怎么调用查询订单接口”,召回到一段孤立代码,很难解释适用条件。

八、版本和 chunk 的关系

chunk 必须继承文档版本。

不要只在文档表里记录版本,chunk 里也要带上:

{
  "doc_id": "report-manual",
  "version": "v3.2",
  "status": "published",
  "section_path": "权限说明 > 报表导出"
}

当文档从 v3.2 更新到 v3.3 时,新版本 chunk 应该重新生成。旧版本可以归档,但不再参与线上召回。

九、切分质量怎么评估

不要只看 chunk 数量,要看它能不能回答问题。

可以准备一组真实问题:

  • 管理员为什么不能导出报表?
  • E102 报错怎么处理?
  • 专业版支持哪些 API?
  • 发票开错了能重开吗?

然后检查 TopK 召回:

  • 是否召回了正确章节;
  • chunk 是否包含完整答案;
  • 是否有标题路径;
  • 是否混入无关内容;
  • 是否包含过期版本;
  • 是否能引用来源。

如果召回到了正确文档但答案不完整,通常是切分太碎。如果召回结果总是很大段说明,通常是切分太粗。

十、这一章的结论

企业级 RAG 的文档切分,不是“每 500 字切一刀”,而是围绕业务语义构造最小可回答单元。

核心原则:

  • 先解析结构,再切分 chunk;
  • chunk 要保留标题路径;
  • 流程、表格、FAQ、工单案例不要随便拆散;
  • chunk 必须带元数据、权限和版本;
  • 用真实问题评估切分质量。

下一章我们进入 Embedding 与向量库选型,看看召回效果、成本、更新能力和权限过滤之间如何取舍。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐