今天下午又删掉了一行因为逻辑冲突而报错的 JSON 源码,这已经是本周第三次了。不是 RAG 系统本身的问题,是我喂给它的数据里,混进了两个字段名一模一样但结构完全不同的对象,一个来自 2018 年的老爬虫,一个来自 2022 年的新 API,它们在我的向量库里和平共处了半年,直到一个非常具体的业务查询触发了这场内战。垃圾进,垃圾出,这句话在 AI 时代被放大了十倍,以前做 SEO 时数据脏点顶多影响排名,现在数据脏直接导致你的智能体胡言乱语,甚至系统崩溃。
2016 年那会儿搞爬虫,对“干净”的理解就是能跑通、别被封。用 BeautifulSoup 硬怼 DOM 树,正则表达式写到眼花,抓下来的数据里经常混着 HTML 标签、乱码和广告文本,存进 MySQL 前用几个 replace() 和 strip() 函数糊弄一下就算清洗了。那时候焦虑的是流量和收录,数据是燃料,脏一点烧起来烟大,但引擎好歹能转。现在引擎换成了大模型,它对燃料纯度的要求是分子级别的。你当年随手塞进数据库的那段“产品详情:
”,在今天被嵌入成向量后,会跟一段正常的“产品价格:199元”产生诡异的语义相似度,导致检索结果完全跑偏。这种历史债务,正在疯狂反噬。
所以我建立了一套近乎偏执的清洗流水线,就部署在 n8n 上,完全自动化。第一步是格式强拆,不管来源是 PDF、网页、Word 还是乱七八糟的 API 返回,全部用 Pandas 和自定义解析器打成结构化的表格,哪怕损失一些边缘信息也要保证骨架一致。第二步是冲突检测,我写了个脚本专门扫描字段名,对同名不同构的字段进行自动重命名并打上来源和时间戳标签,就像今天下午干掉的那个 JSON 冲突一样。第三步最耗时,语义去噪,用一个小型的本地 embedding 模型先跑一遍,把那些明显是导航栏、版权声明、广告话术的文本块通过余弦相似度过滤掉,这步的阈值调了不下五十次,太严了伤及正文,太松了等于没清。
这套逻辑的核心就一条:在数据进入向量库之前,把它当成要生吃下去的食材来处理,你得自己先洗三遍、焯遍水。很多人觉得 RAG 就是“文档切块 – 嵌入 – 检索”,猛堆上下文长度和 embedding 维度,但源头的水是浑的,你下游修再大的水库也没用。2023 年刚接触大模型时我也迷信算力,后来发现,喂给 GPT-4 一堆结构混乱、充满矛盾的客户需求历史邮件,它生成的方案照样是四不像。问题不出在模型,出在喂料的人。
这其实是一种“数据品位”。就像你没法跟一个天天吃重油重盐的人解释食材本味有多重要,你也很难让一个习惯了“跑通就行”的开发者理解,为什么要在数据清洗上花掉项目三分之一的时间。但业务上限就在这里分野了。你的智能体能否精准理解行业黑话、能否从历史案例中提炼出真正有效的策略、能否避开那些由脏数据埋下的逻辑陷阱,不取决于你用了多贵的 API,而取决于你有多嫌弃“差不多”这三个字。我现在宁可让流程卡在清洗环节报警,也绝不放一条未经审视的数据进去。这种死磕,是过去十年被各种“野路子”毒打后,身体里长出来的免疫系统。














