
探矿行业的RAG落地十次有八次死在数据清洗上。我接手过不少地质勘查单位的知识库项目最初大家以为把一堆TXT、Word、PDF和网页扔给向量库就行结果检索出来的内容要么是乱码、要么是截断的表格、要么是答非所问的段落。后来才明白这些看起来不起眼的“脏数据”才是决定RAG系统能不能用的生死线。这篇内容我就把探矿业务里最常见的文本清洗套路完整盘一遍照着做至少能把检索精度从“没法用”拉到“能干活”。1. 先搞清楚探矿业务的RAG到底在解决什么问题1.1 为什么探矿行业的数据那么难啃地质勘探是一个极其依赖历史资料的行业。一个矿区从预查、普查到详查往往要经历数年甚至十几年期间产生的地质报告、钻孔柱状图、物化探数据、岩矿鉴定记录、储量估算说明分散在不同年代、不同格式、不同人员手里。老工程师手头可能还保留着上世纪八十年代打印的纸质报告扫描版新项目组则习惯把电子版整理成Word和PDF。至于网页端的数据通常是内部系统里的项目简报、地灾通报或者规范条文随时需要引用。把这些资料喂给RAG系统做检索增强目标很明确当业务人员提问“某矿区ZK301钻孔的矿体厚度是多少”或者“该区域有没有关于硅化蚀变的描述”时系统能快速定位到对应文档、对应段落还能给出原文出处。听起来是标准的知识库问答但难点恰恰在于输入数据的复杂度。文稿年代跨度大字体编码混乱中文GB2312、GBK、UTF-8混用打开就是乱码。大量钻探记录、分析化验单以表格形式存在直接转文本会把行和列的关系彻底打散。报告图片多扫描件多不用OCR或者OCR质量不高文字就进不了检索环节。网页数据虽然能用爬虫抓下来但导航栏、页脚、脚本代码混在一起不清洗就是一堆噪音。这些问题不解决后面无论用多强的embedding模型、多先进的向量检索算法都是白搭。数据进得去、出得来还必须出得对这是RAG项目的第一道分水岭。1.2 RAG流程中“脏数据”的典型症状我习惯把RAG的数据清洗看成“从物理世界到语义世界”的搬运。物理世界里的数据是文件、是扫描图片、是网页结构语义世界需要的是干净、连续、有边界的自然语言文本块。如果搬运过程中“语义”被破坏检索端就会出现各种典型症状。最明显的是乱码。TXT文件用了错误的编码读取整篇内容变成“锟斤拷”或者方块符号embedding之后自然是垃圾向量怎么检索都查不到。其次是表格结构丢失。Word里的钻孔柱状表被解析成一行行的文字深度、岩性、厚度、采取率这些字段混在一起检索模型根本不知道哪个数据对应哪个列。再次是OCR噪声。PDF扫描件经过OCR会把“Fe2O3”识别成“Fe2O3”或者“Fe2O3 ”小数点变成句号化学符号里的下标全部丢失。最后是网页抓取的杂质。一个网页抓下来里面一半是导航菜单和广告一半才是正文直接切分会影响检索精度。在探矿业务里这些问题尤其致命因为地质术语本身就精确而敏感。你说“矿体厚度3.2米”和“矿体厚度32米”语义差距不大但数值整整差了十倍。搜索召回如果召回的是OCR错别字版本下游的问答系统根本无从判断正确数值。所以清洗工作必须有“地质语义意识”不光要做通用文本清洗还要针对勘查术语做定制处理。2. 四种常见格式的清洗思路与实操细节2.1 TXT文本编码识别与基线清洗TXT是探矿业务里最古老但也最顽固的格式。很多早期的物化探数据、化探采样结果、测井记录都是以纯文本形式保存的。这类文件的问题不在于格式复杂而在于编码混乱。中文Windows系统默认ANSI也就是GBKLinux系统默认UTF-8老的地质软件可能还会输出GB2312或者Big5。一个TXT文件从一个系统拷贝到另一个系统编码标签丢了读取时按错编码就是满屏乱码。我的做法是先用工具做编码检测以Python的chardet库最为常用。它会根据字节分布推测出最可能的编码然后统一转成UTF-8。这里有个坑chardet对短文件或纯数字文本的猜测并不准确所以我会结合文件头部字节序标记和业务上下文综合判断。比如一份采样数据如果前几行是“采样号,经度,纬度,Cu,Zn,Au,Ag”那明显是CSV/TSV风格直接按常见编码试读就行不必依赖模型。清洗TXT时还要处理几类常见噪声行尾多余空格、全角半角混用。地质报告中经常混入全角逗号、括号、空格在切分时会影响语义片段完整性需要统一转半角。制表符和多个连续空格。这类字符会干扰后续的段落切分建议统一收敛为单个分隔符。乱码特征字符。像“锟斤拷”“烫烫烫”“??__”这类二进制转文本产生的垃圾串直接用正则过滤。页眉页脚和重复段落。很多老报告每一页都有相同的报告名称或页码这种重复内容会严重污染切分结果。对于探矿行业的数据还有一类特殊的噪声就是“数据说明”和“实际数据”混排。比如一个TXT文件前半段是表格说明后半段才是数值阵列如果一刀切全部切开检索时很容易把说明文字当成数据或者反过来。我建议先做“数据块分离”把说明性段落和数值型表格段落分开存储分别打不同的元数据标签这样检索的时候可以按类型过滤。基线清洗的产出物是一份干净的纯文本这时候才轮到切分和向量化。清洗过程一定要保留原始文件路径和清洗后的文件路径对应关系方便追溯。后期发现某个检索结果异常时可以回溯到清洗前原始文件对比是哪一步出了问题。2.2 Word文档表格结构、公式与样式噪声处理Word文档是探矿业务的核心载体。储量报告、勘查设计、工作总结、技术规范绝大多数正式文档都是Word生成的且很多还套用了单位的标准模板。对Word的清洗我总结了三个核心痛点表格结构提取、公式与特殊字符、样式噪声。先说表格。地质报告里的关键信息往往都在表格里钻孔一览表、样品分析结果表、储量计算表。Word的底层XML结构里表格是有行列逻辑的但直接用python-docx读取时很多人会把每个单元格当作独立段落输出——行与行的关联性就丢失了。我的做法是自定义表格解析函数识别表格范围逐行读取单元格内容把一行数据用分隔符拼接成一条记录。比如一个钻孔记录表一行代表一个钻孔的多个属性拼接后变成“ZK301|深度125.6米|岩性花岗闪长岩|矿体厚度3.2米|采取率92%”。这样前后关系保留检索时能精准命中。这里有一个关键参数要处理就是单元格合并和换行。Word表格里经常有跨行合并单元格如果简单按行列遍历会出现重复值和空值。我通常会对第一行做表头识别后续行做数据映射跨行单元格则取合并区域的首值特殊标记出来。这样清洗后的记录才具备表格语义。再说公式。探矿报告里涉及品位计算、储量估算、元素分析结果经常嵌入公式。Word里的公式分为两类一类是Word 2007以后的原生公式OMML格式一类是老旧的公式编辑器对象如MathType产生的OLE对象。OMML可以直接解析为文本但需要转换成LaTeX或者MathML语义表达OLE对象则很难直接处理比较靠谱的方案是用宏或者把文档转成PDF后再识别。考虑到RAG场景我不推荐把公式原样转成复杂符号传入向量库因为公式的语义本身依赖上下文。更好的做法是把公式转成自然语言描述比如“Fe2O3品位计算公式Fe2O3 (Fe含量系数 1.286)”这样检索系统才真正理解这段文本在说什么。样式噪声是Word清洗中被低估的问题。标准模板会让每一页出现同样的单位名称、报告编号、密级标识还有大量空行和分页符。这些内容如果不处理切分时会产生大量冗余片段白白浪费向量库容量也会干扰检索的相关性排序。我一般会先用python-docx遍历段落删除空段落、仅有分页符的段落、纯页眉页脚继承下来的重复文本。但要小心不要随意删除正文字段——同一段落里的文本必须保留原始顺序。Word清洗还需要注意“修订模式”和“批注”。地质报告经常多人协作Word文档里可能残留修订痕迹或批注框。批注内容通常分布于页边区域直接导出文本会把批注和正文混在一起。处理方法是先接受所有修订消除痕迹再导出正文内容如果有必要可以将批注单独存储为“注释副本”不要混入正文索引。2.3 PDF文档三种类型的差异化处理PDF是探矿业务里最让人头疼的格式。严格来说PDF并不是一种适合做文本抽取的格式它的设计目标是“保持版面不变”而不是“保持语义结构”。我把探矿行业常见的PDF分成三类分别采用不同的处理路线。第一类是电子生成的PDF原生PDF文件里包含文本层可以直接抽取文字。这类PDF多来自电脑生成的报告或扫描后叠加了文字层的文档。抽取工具我用pdfplumber和PyMuPDFfitz结合pdfplumber擅长处理表格和版面布局PyMuPDF速度快适合批量抽取。对于原生PDF核心工作是重建阅读顺序。PDF的文本对象在物理上可能按页内位置随机存储直接抽取常出现文字错乱。我的做法是先定位文本块的坐标信息再按照从左上到右下、从左到右的顺序重排文本块。如果文档本身是多栏排版还需要先做分栏识别否则两栏文字会交叉混排抽出来没法读。第二类是扫描件PDF也就是纯图片PDF必须走OCR。扫描件在探矿业务里非常多尤其是老一辈工程师保存的历史图件和原始记录。OCR环节我推荐PaddleOCR它在中文识别上的准确率比Tesseract高不少尤其对表格和混合文字版面效果好。但OCR终究是识别过程必然后引入字符错误。针对地质行业我建议做自定义词典增强把单位名称、矿种名称、地层代号、常见化学式、人名地名加进OCR模型的词典或后处理纠错词表中能显著降低专有名词的错误率。第三类是“表格型PDF”包括各类分析报告单、测试结果表。这类PDF即便有文本层表格的框线结构也经常导致抽取错行。我一般会上多一层策略如果常规文本抽取后表格记录错乱严重就先把PDF页面转成高清图片再用目标检测模型定位表格区域用PaddleOCR的表格结构识别能力还原为HTML表格再转成Markdown或结构化表格保存。这个方法比较重但对于高价值资料值得投入。处理高精度检索时表格结构完整性和数值准确性远高于处理速度。OCR后的文本必须做置信度筛选。PaddleOCR会输出每个识别文字的置信度分数我通常设定阈值0.85低于该阈值的结果不直接入索引而是单独存放并打上“待人工校对”标记。这样能避免OCR错字污染向量库同时保留人工复核的入口。这个机制在我们做数据清洗时很关键因为向量检索对错字敏感度很高一个字的错位可能把整个句子的语义带歪。2.4 网页数据正文提取与页面噪声处理探矿业务的网页数据来源主要是单位门户、行业数据库、政策文件发布页以及内部项目管理系统。网页数据清洗的核心问题是“正文抽取”。抓取网页时单纯用requests拿HTML再剥离标签得到的结果往往惨不忍睹导航栏、页脚、版权信息、相关推荐、广告几乎都会混进来。现代网页结构又复杂大量内容在JavaScript渲染后才会出现。所以我建议第一步先确认抓取内容的完整性如果需要渲染后的页面就得用Playwright或Selenium这类无头浏览器加载后再抽取DOM结构中的正文节点。正文抽取有两个方案。轻量级的是用Python库trafilatura它专门针对新闻类、文章类页面做正文提取返回干净正文和元数据。重量级的是用可配置的爬虫框架比如Scrapy配合XPath选择器精确定位正文容器节点。探矿类网站基本属于内容型页面trafilatura的表现已经不错如果遇到复杂的门户系统就得手写抽取规则。网页清洗的另一层是去重。很多站点会转载同一篇规范性文件的不同版本正文相同但页面框架不同。全文哈希对比可以去掉完全重复的页面语义级去重需要用MinHash或SimHash对文本向量做相似度计算设定相似度阈值0.9以上视为重复只保留一篇。探矿知识库里如果塞入大量重复内容不仅浪费存储空间还会导致检索结果排序异常——同一条信息占了多个位置真正的关联内容反而被挤下去。对网页正文的处理还需要统一链接、图片和表格的表示方式。正文中的图片如果不能提取文字至少要保留alt属性或相邻文本作为说明表格数据仍然遵循“尽量结构化”的原则。另外网页正文经常包含“发布时间”“来源”“作者”等信息这些建议提取为元数据字段在检索后处理阶段可以用来做时间过滤或来源过滤能明显提升业务场景下的召回精度。3. 清洗后的切分策略与元数据管理3.1 切分不是机械截断而是语义边界识别数据清洗完成后下一步是切分Chunking。切分策略直接决定检索粒度。如果我切得太粗比如整个文档一个块向量检索的目标不明确召回段落太长切得太细比如按句子切又会丢失上下文。对探矿业务我推荐按“章节-段落-表格记录”三级混合切分策略。一篇文章先按章节一级标题、二级标题划分大块再把每个大块内部的自然段落作为检索候选块。表格则独立处理每一行数据作为一条记录。标题和段落之间的归属关系要保留也就是每个段落要带上所属章节的路径比如“第三章 矿区地质|3.2 地层|3.2.1 第四系|段落原文”。这样切分的好处是用户问“矿区地层特征”时系统能召回3.2整节下的多个段落并准确展示层级路径。切分时还要注意重叠overlap的设置。我的经验是块长度取500到800字时块间重叠150字左右能兼顾语义完整性和向量区分度。这个参数不是固定的需要结合embedding模型建议的最大输入长度和文档类型微调。如果文档以短表格为主块长度可以下调到300字重叠100字如果文档是长篇叙述块长度上调到1000字也不过分。3.2 元数据检索精度的隐藏加速器清洗过程中的元数据关联经常被忽视但我觉得这是高精度检索的关键。元数据就是“关于数据的数据”对检索效果的影响非常直接。探矿业务里每条文本块至少应关联这些字段文档名称、文档类型报告/规范/数据表/网页、所属项目或矿区。来源文件路径TXT/Word/PDF/网页方便回溯。生成日期或发布时间支持时间过滤。作者/编制单位/部门支持权限过滤。清洗批次和清洗方式含OCR置信度标记便于质量追踪。有了这些元数据检索环节可以做很多高级操作。比如用户限定“只看XX矿区的详查报告”系统就能在metadata层面直接过滤只检索对应矿区的文档不但速度更快还避开了不同矿区同名术语的干扰。另一个场景是“我要2020年以后发布的储量规范”时间过滤能把十年前的老版本规范排除在外防止过期内容干扰判断。向量相似度检索是一种近似检索本质上是“语义空间里的距离度量”它不像数据库那样支持精确的字段过滤。如果我们把元数据和向量一起存入并在检索时叠加filter条件就能把“语义检索”和“结构化过滤”结合起来这正是探矿业务需要的高精度检索路径。从实现层面说Chroma、Qdrant、Milvus等向量数据库都支持“标量字段向量字段”的混合检索模式。我的建议是嵌入内容时就把元数据以结构化字段方式写入而不是把元数据拼在文本里。把元数据拼进文本会让embedding向量被无关信息污染降低语义纯度检索时反而不准。4. 从清洗到高精度检索的验证闭环4.1 用真问题测试检索质量清洗完切分完向量化入库这只是开始。后面要做的就是“检索质量验证闭环”通俗地讲就是要用业务人员会问的真实问题去检验系统效果。我的经验是从业务部门收集至少50个真实问题覆盖几种典型类型事实型“某矿区普查报告中ZK201孔的见矿深度是多少”范围型“过去十年该地区做过哪些物探工作”比较型“A矿段和B矿段的平均品位哪个更高”规范型“固体矿产地质勘查规范中关于详查阶段工程间距的要求是什么”每个问题关联一个标准答案和对应的原始文档路径。量化指标方面我主要看三个召回率TopK返回的结果中包含正确文档的比例、命中位置正确内容排在返回列表第几位、答案完整性正确内容是否被一个文本块完整覆盖还是被切碎成多块。前两项指标反映检索精度第三项反映切分策略是否合理。如果答案完整性问题突出就需要调整切分长度或重叠度。实测下来很多团队在清洗后不测试直接上线结果用户提问后得到七零八落的片段还以为模型不行。实际上问题大概率出在切分粒度上或者文档抽取时把表格结构打散了。所以建议先拿小批量数据做“清洗→切分→入库→检索测试”的小闭环迭代稳定后再上全量数据。4.2 常见问题与排查思路速查做一个表格方便对照这些都是我用真金白银踩坑踩出来的问题现象可能原因排查与解决检索结果里出现乱码片段TXT编码识别错误或Word特殊字符未转换回溯清洗日志定位乱码源文件改用UTF-8编码检测人工抽检表格数据检索时数值张冠李戴Word/PDF表格结构解析出错行列对应关系丢失检查表格抽取环节保证每行记录能对应表头必要时转图片做表格结构识别扫描型PDF检索结果大量错字OCR识别质量差专业词汇错误率高增加地质行业自定义词典做OCR置信度过滤和人工校对流程网页抓取内容包含大量导航和页脚正文抽取规则不准确改用trafilatura或自定义XPath抽取正文容器删除重复模板节点同一问题检索出大量重复相似段落源文档存在重复内容切分后产生冗余块增加全文哈希或SimHash去重设定合适相似度阈值检索结果中关键段落被截断切分粒度太大或太小语义边界不匹配调整块长度和重叠度针对文档类型做参数微调带有时间限制的问题召回旧版本规范元数据时间字段缺失或过滤条件未生效补充规范类文档的发布时间和版本号检索时强制叠加时间过滤条件4.3 建立清洗规则库沉淀领域专属方案不同矿区的数据形态千差万别但如果每次从零开始写清洗脚本效率太低。我建议把清洗规则沉淀为规则库按文档类型分类维护形成一套可持续迭代的pipeline。规则库至少包含三类规则编码修复规则常见编码识别表、乱码特征正则、全角半角转换映射。格式抽取规则Word表格解析配置、PDF版面重建参数、OCR词典表和置信度阈值。领域清洗规则地质术语纠错表、化学式规范转换表、矿区名称归一化表。这套规则库既是代码资产更是业务知识资产。新矿区接入时先跑一轮通用清洗再把矿区特有的地名、地层代号、工程编号补进词典就能快速适配。我见过太多项目在做完一个矿区后把脚本丢在角落下一个矿区来了又重写一遍白白浪费积累。还有一点要强调清洗规则的变更会影响整个索引的效果。如果后续修改了清洗规则建议建立“版本对照”记录每个版本的清洗时间、规则说明、索引范围。老的索引是否需要重新生成要根据变更的严重程度来判断。比如OCR词典更新对已有索引基本无影响但如果表格抽取逻辑变了就必须对新数据重新处理和索引否则新旧数据格式不一致检索结果会非常不稳定。5. 探矿领域RAG清洗的独有难点与实战建议如果说通用RAG的清洗是“把文本弄干净”探矿业务的清洗更像是“把专业数据变回原意”。这个领域有几个独有的难点值得单独拿出来讲。第一是地层代号和专业符号。地质报告里充斥着大量代号比如“Pt2q”古元古代滹沱群、“ε”见矿化、“Au”“Cu”“Fe2O3”。清洗时不能粗暴地删除这些符号也不能替代成普通汉字否则检索“金矿化”就找不到含“Au矿化”的段落。我建议把化学元素、地质代号统一规范为标准表达形式元素符号保持大小写规范地层代号的大写字母连写识别为专有名词模型应将其作为整体切分而不是拆成字母。第二是多模态内容的结合。探矿文档中图件的重要性不亚于文字。一张钻孔柱状图表达的信息量可能超过上千字文字描述。RAG如果想要更好地处理这类数据必须在清洗阶段就把“图件识别”纳入链路。至少要做到提取图件中的图名、图例说明、坐标信息连同图中OCR识别的文字一并作为图件的文本描述内容和原图一起存入知识库。这样后续做多模态检索时图件内容也能被文本召回而不是单纯的图片盲区。第三是数据安全与权限管理。探矿数据往往涉及商业机密和国家资源数据清洗和检索过程必须在受控环境内完成。推荐在内网部署数据不出域。向量库和索引库做好独立部署检索服务根据用户部门的权限进行文档级别的访问控制。这一点在清洗流程设计时就要考虑比如对敏感文档做脱敏预处理不让清洗脚本将涉密内容写出到公共服务器否则后续追责非常麻烦。关于工具链我用得比较顺手的组合是编码检测与基础清洗Python chardet regexWord解析python-docx复杂样式转PDF后二次抽取PDF解析pdfplumber PyMuPDF扫描件走PaddleOCR 自定义词典网页抽取trafilatura Playwright动态渲染表格还原PaddleOCR的表格结构识别模型切分与向量化按文档类型自定义切分器embedding用BGE或同类中文模型向量库Qdrant或Milvus启用元数据过滤功能这个组合的好处是每层都有替换空间。如果后续某个环节效果不佳可以单独替换对应组件不会导致整条链路推倒重来。而且各个组件的日志都很清晰便于排查问题。6. 几条实操心得和避坑记录最后分享几条我在实践中的心得谈不上系统性理论但每一条都是花过时间的。清洗不是越干净越好。过度清洗可能把有用信息也删掉。比如把所有的空行、制表符、特殊符号全部清除看起来是干净了但表格的列对齐信息和段落结构信息也丢了。我后来养成的习惯是清洗前先标记数据形态再决定清洗策略。纯文本段落可以做激进清洗表格类数据必须保留分隔符代码片段或公式区域要单独处理。抽样式验证是清洗流程的必备环节。无论清洗脚本多完善都要定期人工抽检清洗后的文本。我一般按1%到3%的比例随机抽取人工阅读确认内容完整性。探矿报告中数值精确到小数点后两位如果OCR或表格抽取少了一个零这在业务上可能就是重大事故。抽检虽然是笨办法但在高精度要求场景下成本最低也最可靠。不要把所有文档都一股脑切分。有些文档需要整篇保留比如规范条文有些文档只需要拆出核心数据比如冗长的测试报告。我的做法是先做文档分级把文档按“整篇结构化文本”“表格核心数据”“图文混合内容”分成三类用不同的清洗和切分流程处理。这样虽然前期多一点配置工作但后期检索质量会明显更稳定。探矿业务的RAG清洗本质上是一个“业务理解工程实现”的双重任务。只懂技术不懂地质语境清洗出来的文本就是一堆“看起来干净但没灵魂”的文字只懂业务不会用工具面对成千上万份图件和报告又无从下手。最好的状态是团队成员分工协作地质人员参与词典梳理和结果抽验技术人员负责流程实现和性能调优。这样搭建的RAG知识库才能从“能回答”走向“答得准”。