InterX - 数据预处理
上一篇介绍了 InterX 的整体架构和核心痛点。从这一篇开始,我们逐层拆解每个模块的实现细节。先从最底层的数据预处理 process 开始——毕竟,数据质量是一切的基础。
为什么数据预处理这么重要
赛题给的原始数据是什么样的?没有结构化文件,图文不匹配,OCR 残留各种伪影,页眉被误识别为标题……如果直接把这些脏数据丢进 RAG,后面不管检索和生成做得多花哨,结果都是垃圾。
所以 InterX 在数据预处理上花了很大功夫,构建了一套三层递进的数据清洗体系,加上结构感知的分块策略和多模态向量空间,确保下游拿到的是干净、结构化、可检索的数据。
三层数据清洗体系
第一层:文本规范化清洗
这是最基础的一层,所有输入无条件经过。做的事情很简单:
- 移除 BOM 字符(Windows 文件常见的隐形字符)
- 连续空格合并
- 过多换行压缩
听起来不起眼,但这些"小脏东西"会在后面的解析和嵌入环节引发各种奇怪问题。先清理干净,后面省心。
第二层:AST 结构重建清洗
这一层是核心。基于 markdown-it 的 CommonMark 解析器,把 Markdown 转成 AST(抽象语法树),然后对每种元素类型做规范化处理:
- 表格:重建为标准管道分隔格式,行数不均时填充空列。原始手册里的表格经常七歪八扭,这一层把它们拉回正轨。
- 列表:递归渲染保留嵌套缩进。手册里的操作步骤经常有多级嵌套,缩进乱了语义就乱了。
- 代码块:保留围栏标记到每个片段。
关键是,这一层同时维护原始 Markdown 和纯文本的 双表示。原始 Markdown 保留给需要精确格式的场景,纯文本用于检索和嵌入。两个表示各取所需。
第三层:AI Agent 语义审计清洗
这是最"重"的一层,也是最有意思的一层。用 AI Agent 对每本手册做 9 步审计:
- 读取完整 Markdown + 标题大纲
- 提取每张图片的最近标题 + 前后文本
- 生成缩略图总览(220x160, 3 列布局)
- 逐张视觉检查
- 识别六类错配模式(注释错位、页眉误识别、裁剪图片等)
- 非破坏性修复
- 用户确认边界——删除、替换、改写前必须询问,不能自作主张
- 验证(图片引用完整性、链接可解析性、标题连贯性)
- 总结修复和未解决问题
还有一个辅助工具 ocr-patterns.md,是 OCR 残留模式库,记录了缺空格、拆分词、粘连单位等常见问题,分"可安全修复"和"需先询问"两类。
这一层的效果是:40 本中英文手册、约 3400+ 张图片的全面审计完成,修复了大量图文错配和 OCR 伪影。虽然审计过程需要不少时间,但数据质量的提升是实打实的。
结构感知的三级分块
按元素类型差异化切分
传统 RAG 用固定 token 窗口切分,简单粗暴但问题很大——一个操作步骤被从中间截断,上半截在这 chunk,下半截在那 chunk,LLM 看到的都是残缺信息。
InterX 的做法是 按 Markdown 元素类型差异化切分:
| 元素类型 | 切分策略 |
|---|---|
| 段落 | 句子边界切分(.!?。!?;;) |
| 列表 | 列表项边界切分,保留缩进 |
| 表格 | 数据行切分,每个片段重复表头 |
| 代码块 | 保留围栏标记到每个片段 |
列表按列表项切分,保证每个 chunk 里的操作步骤是完整的;表格每个片段都带表头,不依赖上下文也能看懂;代码块保持完整性不被截断。
图片"粘性"算法
这是一个很有意思的设计。在贪心打包过程中,图片元素 不触发 flush 操作。什么意思呢?正常情况下,chunk 超过 token 上限就要切一刀开始新 chunk。但如果当前元素是图片,就不切,继续往当前 chunk 里塞。
为什么?因为图片通常需要和它的解释文字在一起才有意义。一张电路图配着"如图所示,红圈处为保险丝位置",如果图在一个 chunk、文字在另一个 chunk,检索和回答都会出问题。粘性算法确保图片始终和解释文字在同一个 chunk 里。
三级层次结构
切分完成后,构建三级层次结构:
| 层级 | Token 目标 | 语义定位 |
|---|---|---|
| Big | 900 | 完整章节、背景概述 |
| Mid | 520 | 操作流程、多步骤指南 |
| Small | 220 | 精确事实、型号、安全约束 |
为什么需要三级?因为不同问题需要不同粒度的回答。问"这个产品有哪些安全注意事项"需要 big 级别的完整章节;问"滤网怎么拆"需要 mid 级别的操作步骤;问"最大功率是多少"需要 small 级别的精确事实。
三级之间通过 ID 链关联,检索时从小块命中向上聚合到中块和大块,确保同时拥有精确事实和完整上下文。
几个关键设计细节
标题只注入首个 chunk。 同一个章节下的多个 chunk,只有第一个 chunk 的 retrieval_text 包含章节标题。避免重复标题浪费 token,也让检索结果的去重更干净。
Overlap 机制。 超限元素拆分时带重叠窗口,防止步骤在边界处断裂。比如一个长段落被切成两半,重叠部分确保上下文连续性。
层次化 Prefix 注入。 每个 chunk 的 retrieval_text 包含完整父链前缀:"手册 > 章节 > 大块 > 中块 > 小块"。检索时自动携带结构化上下文,Reranker 看到的不只是 chunk 内容,还有它在整个文档中的位置。
content_hash 增量重建。 每个 chunk 计算 MD5 哈希。手册内容小改之后,只有变更的 chunk 需要重新处理,未变更的直接跳过。后面嵌入和知识图谱构建也复用这个哈希,全链路增量。
多模态统一向量空间
传统 RAG 里图片基本是被丢弃的——要么直接忽略,要么提取 alt text 当文本处理。InterX 用 DashScope 的 qwen3-vl-embedding 模型把文本和图片编码到 同一个 1024 维向量空间。
这意味着什么?用户上传一张故障照片,查询向量和 chunk 向量在同一空间比较,可以直接匹配到包含相同部件图示的手册段落。以图搜图 + 以图搜文,不再是割裂的两个系统。
每个 small chunk 最多关联 1 张图片作为"视觉锚点"。这样文本 chunk 和图片 chunk 都在同一个向量空间里,检索时一视同仁。
嵌入也是增量的:基于 content_hash,内容未变的 chunk 复用缓存向量,不重新调 API。
构建质量保障
数据预处理的最后一道防线是质量保障机制:
- Token 分布统计:min/max/avg/p50/p90,确保分块粒度符合预期
- 缺失图片检测:构建阶段检查图片引用是否断裂,引用了不存在的图片会报警
- 异常检测:big/mid/small 任一数量为 0 时标记异常——一本手册不可能没有某个粒度的 chunk
- 构建报告自动生成 Markdown 表格:一眼看出哪本手册有问题
这些检查不是可有可无的。想象一下,如果一本手册的图片引用全断了,后面检索到相关 chunk 但没有图片,回答质量直接打折。早发现早修复。
小结
数据预处理看起来不如检索和生成那么"酷",但它决定了整个系统的上限。三层清洗保证数据质量,结构感知分块保证语义完整性,多模态向量空间保证图片不被丢弃,增量构建保证迭代效率。
下一篇我们来看检索层——retrieval 模块是如何通过五重分词、双通道召回和领域特化 Rerank 来实现精确检索的。