真实业务文档往往不是“开箱即用”的干净文本。它们可能包含重复段落、无意义的格式符号、空白字符、广告水印,甚至是多个版本拼凑而成的冗余描述。把这些原始文档直接切片入库,会严重拉低检索质量,让模型看到一堆“噪声”,凭空增加错误引用和幻觉风险。因此,在文档切片之前,通常需要做一轮轻量但关键的清洗,确保知识库内容的整洁与可读。以下四个动作是最常用、见效最快的。
1. 去重:避免相同信息重复入库
重复内容会带来两个直接问题:
- 浪费检索资源:相同或高度相似的片段占据多个检索位,挤占其他有效信息的召回空间。
- 让模型产生偏差:如果同一政策条款在知识库中出现 5 次,检索容易返回一堆雷同段落,模型可能过度强化这个信息,甚至给出“复读机”式的冗余回答。
实用做法:
- 文档级去重:在入库前检查文件名、MD5 哈希,防止同一份文件被重复上传。
- 段落级模糊去重:对每个切片计算哈希值(如 MinHash 或 SimHash),用相似度阈值(如 0.9)判断是否为近似副本,只保留其中一个。实际项目中,直接使用
difflib.SequenceMatcher或简单的 Jaccard 相似度已能解决大部分场景。 - 多版本保留策略:如果两段内容确实相似但日期、小数点、法律条款号等关键细节不同,则需要同时保留,但应当在元数据中标记版本,以防混淆。
效果直击:某团队在处理客户服务知识库时,发现“退换货政策”被 12 个不同格式的文档反复引用,去重后仅保留 2 个权威版本,检索命中率提升约 15%,且回答不再出现“根据 A 版……但 B 版又说……”的自我矛盾。
2. 去噪:清除无意义的干扰信息
文档在流转过程中常混入大量与内容无关的“噪声”。这些信息不仅无益于检索,还容易在下游生成阶段被套用,出现离奇的错误。
常见噪声类型与处理:
- 页眉/页脚/页码:如“第 1 页 / 共 20 页”、“CONFIDENTIAL”、“内部资料,禁止外传”。使用正则匹配(
^\d+\s/\s\d+$)在分块后识别并删除。 - 水印文字:PDF 中提取出的“DRAFT”、“SAMPLE”等。如果这些词出现在每页固定位置,可基于位置特征过滤。
- 特殊字符与乱码:编码转换遗留的控制字符(
\x00等)、繁简混排导致的乱码。用 Unicode 规范化(NFKC)和简单的字符白名单清理。 - 版权声明与免责长串:如“©2023 All Rights Reserved. This document is...”这种几乎每页都出现的固定文本,可以识别重复模式后整段移除。
关键原则:去噪不要过度,避免把文档中的编号、单位、公式等有用符号当作噪声清除。最好在具体数据上抽样检查,确认规则不会误伤。
3. 格式统一:减少排版差异带来的干扰
同一知识库里可能有 Word 文档、Markdown、网页抓取的 HTML 甚至排版混乱的 TXT。如果格式不统一,检索时难以保证一致性,而且生成的引用片段也可能丑陋难读。
统一处理的几个维度:
- 换行与空行:将
\r\n替换为\n,连续空行压缩为单个空行。避免一段话被莫名其妙的换行拆成两截。 - 标题与层级标记:尽量转为通用的 Markdown 标题格式(如
## 标题),使层级结构清晰,便于后续切片时按语义边界切分。 - 列表与表格:HTML 表格转为 Markdown 表格或换行分隔的键值对,无序列表保留缩进。保持可读性同时减少模型理解歧义。
- 日期与单位:统一为“2025‑01‑15”而不是“15/01/2025”、“Jan 15, 2025”等混合写法,对日期敏感场景很有用。
实用工具:可以直接用 Python 的 markdownify 将 HTML 转 Markdown,用 Pandoc 将不同格式转成统一中间格式再做后处理。
4. 冗余内容剔除:让知识更紧凑
有些文档本身包含大量“前言”“修订历史”“附录声明”等元信息,这些内容对问答帮助很小,却会被当作正文检索到,给出无效回答。
常见冗余与剔除策略:
- 修订历史:类似“V1.0 2023‑03‑01 初稿”的长列表,用关键字匹配后整段移除。
- 目录/TOC:页码和纯粹的点线连接对内容无贡献,在切块阶段识别“目录”关键词后跳过。
- 致谢/附录/参考文档列表:通常在文末,定位到标题后整篇切除。
- 超过长度且无实际意义的连续空白段落:直接删除。
注意:剔除动作最好在分块前进行,且保留一份原始文档备份,以便未来需要审计或查阅完整上下文时仍可找回。
把清洗嵌入管线
这四个步骤不是孤立的,常以管道化的方式执行:
- 接收原始文档 → 2. 格式统一转为纯文本/Markdown → 3. 移除噪声与版权声明 → 4. 段落级去重 → 5. 删除冗余章节 → 6. 输出清洗后文档供切片。
在实际项目中,可以先在小批量数据上验证清洗规则,确认召回准确度和回答质量都有提升,再将规则固化到自动化预处理脚本中。清洗不是一次性的艺术,而是随着数据源的增加渐进迭代的过程。但即便只做基础的去重和去噪,也常常能让 RAG 系统的表现上一个台阶。