数据的干净度,说到底就是代码的干净度。今天用 GPT-4 跑一批伪原创文章,喂进去的方言语料里混了几个“的地得”乱用的句子,结果 AI 完美复刻了这些错误,生成了一堆语法瘸腿的垃圾。那一刻我意识到,过去十年我写的爬虫、做的数据处理,本质上都在生产“脏数据流水线”,而单元测试是这条流水线上唯一的质检员。
2016年那会儿,谁他妈写单元测试啊。爬虫脚本能跑通、数据能进库就是胜利。我记得为了抢一个新闻站的时效,用多线程暴力请求,根本不管对方反爬的 API 频率限制,脚本跑着跑着就崩,崩了就看日志、改正则、接着跑。数据里一堆 HTML 实体字符没解码,日期格式五花八门,存进 MongoDB 里就像个垃圾场。但当时焦虑啊,SEO 算法一天一变,流量就是命,能抓下来就是“资产”,脏不脏的,后面再说。结果“后面”永远没来,这些数据成了技术债,堆在硬盘角落再也没动过。
到了搞团队那两年,脏数据的毒打才真正开始。手下的小孩写的接口,返回的 JSON 里字段时有时无,一个空值能引发前端一整页的白屏。开会扯皮,前端说后端没给,后端说前端没判,耗掉一下午。那时候才硬性要求关键接口必须上单元测试,用 Jest 搭了个架子,但大家抵触情绪极大。都觉得业务逻辑变太快,测试用例维护成本太高,不如手动点一点。现在回头看,那是管理上的懒惰,用“业务迭代快”当借口,掩盖了工程能力上的薄弱。交付压力大的时候,测试永远是第一个被砍掉的环节,然后半夜就被客户的电话叫醒,因为某个边缘 case 崩了。
疫情把我打回个人状态,我开始接体育健身领域的私活,做饮食计算和训练计划工具。这里的数据干净度直接关系到用户信任。一个卡路里算错,可能就让用户一天白练。我被迫用上 TDD(测试驱动开发),哪怕只是一个计算基础代谢率的函数,也得先把各种边界条件想清楚:体重输入负数怎么办?年龄输入 200 岁怎么办?性别字段传了个“其他”怎么处理?写测试用例的过程,就是在逼自己定义清晰的“数据契约”。这个过程很反直觉,先写断言,再写实现,感觉像戴着镣铐跳舞。但好处是,代码写完,心里特别踏实。这个工具跑了两年,几乎没出过计算错误,用户反馈都说“靠谱”。这让我第一次体会到,干净的数据和可靠的代码,本身就是产品力。
然后 ChatGPT 来了。它用事实告诉我,我以前对“智能”的理解有多肤浅。我以为的智能是写好规则,处理好异常。它的智能是,你喂给它屎,它就学会拉屎。我那个方言伪原创实验就是活生生的例子。我精心调教的提示词,告诉它要模仿市井气息,加入“搞么子”、“蛮扎实”这种词,它学得很快。但我疏忽了,我给的样本里有个句子是“他地车子开得飞快”,它生成的所有文章里,“的得地”全乱套了。垃圾进,垃圾出,放大了十倍。这比任何代码 bug 都可怕,因为这是逻辑层、知识层的污染。我这才疯狂补课大模型,发现业界早就在提“提示词工程”和“RAG(检索增强生成)”。其中 RAG 的核心前提,就是你喂给模型的“知识库”必须是干净的、结构化的。否则,模型会一本正经地胡说八道。
所以现在,我对单元测试的理解升级了。它不仅仅是保证一个函数返回正确数值的工具。它是数据流水线的“第一道净化器”。无论是传统的代码逻辑,还是即将喂给 AI 的语料数据,在进入核心流程之前,必须用严格的断言“洗”一遍。比如,我写了一个数据清洗函数,它的单元测试用例就必须包括:包含 HTML 标签的原始文本、带有乱码的句子、日期格式混乱的字符串。断言它输出的是纯文本、编码正确、日期统一为 ISO 格式。只有这样,这批数据才配进入下一步,无论是存入数据库,还是作为上下文扔给 GPT-4。
调教 AI 的提示词也一样,本质是在为 AI 划定行为边界,这是一种更高级的“测试”。你不能只说“生成活泼的文章”,你得说“生成口语化文章,但必须严格遵守现代汉语语法规范,特别是‘的、地、得’的用法”。你得把“禁止项”写得像测试用例里的异常输入一样明确。这个过程,和我当年写爬虫时,在正则表达式里小心翼翼排除广告 DIV 块,没有本质区别。都是试图在混乱的、充满噪声的现实世界中,提取出一点干净、可用的信号。
窗外夜色浓不浓,咖啡凉没凉,这些都不重要了。重要的是,我桌子上的代码和屏幕里 AI 生成的文本,它们是否经得起下一个凌晨三点,某个未知输入的考验。干净的数据不是洁癖,是生存的底线。从今天起,每一个新项目,哪怕再小,第一件事不是写 Hello World,而是搭测试框架。这个习惯,比我学任何新潮的 AI 框架都重要。














