跳至正文

我被AI生成的内容坑了一下

今天真是被AI狠狠教育了一课。

事情是这样的。早上我在写一个关于RAG检索增强生成的技术教程,想偷个懒,就扔给Claude 3.5 Sonnet一段代码,让它帮我写个文档说明。那家伙写得那叫一个漂亮,结构清晰、注释完整、连代码里的变量命名都帮我分析得头头是道。我几乎没怎么改就直接发到了公司内部技术群里。

结果半小时不到,后端的小王就私聊我:“猫哥,你这段代码里有个bug。”

我一愣,赶紧打开看。小王截了个图,标红了一行:`retriever.top_k = 10`。他说,你这行赋值在LangChain 0.3.2版本里已经废弃了,现在要用`retriever.search_kwargs = {“k”: 10}`。我当时脸就有点发热。确实,我最近在用的还是0.2.x的旧版本,Claude生成的时候按最新API写了,但我压根没注意到这个变化。

这还不是最坑的。

下午我处理一个更离谱的事。有个读者在公众号后台问我,说按我上周发的教程配置Qwen2.5-7B的本地部署,结果模型加载到一半就报OOM。我心想这不可能啊,我测试过的,RTX 3090 24G显存带7B模型量化到4bit完全没问题。我就让他把日志发过来。

一看日志,我人傻了。

他在执行我教程里的代码时,模型加载用的是`AutoModelForCausalLM.from_pretrained(“Qwen/Qwen2.5-7B-Instruct”, torch_dtype=torch.float16, device_map=”auto”)`。问题出在这个`device_map=”auto”`上。我当初写教程的时候,用的是Transformers 4.44.0版本,这个参数在当时的版本里会自动把模型层分配到多个GPU或者CPU上,但前提是你安装了accelerate库。我教程里写了要装accelerate,但没强调版本号。

这哥们儿装的是accelerate 0.34.0,而他的Transformers是4.45.2。这两个版本搭配在一起,`device_map=”auto”`的处理逻辑变了,导致模型的一部分层被错误地分配到了CPU上,然后CPU内存爆了。更坑的是,这个错误日志里只显示“CUDA out of memory”,但实际上根本不是显存的问题。

我花了将近两个小时远程帮他排查,最后发现是版本兼容性导致的。我那个教程写于两个月前,当时这两个库的搭配是没问题的。但AI模型生态发展太快了,两个月时间,Transformers从4.44跳到4.45,accelerate也跟着改了一堆内部逻辑。我教程里写的那些参数和用法,有些已经悄悄过时了。

这让我想起上周一个更尴尬的事。

我在测试GPT-4o新出的图片生成功能,想写一篇评测。我让GPT-4o帮我生成一张“戴着帽子的小猫”的图片。它生成出来了,效果还不错。我就直接发到了朋友圈,配文“AI绘画进步真快”。结果评论区有个朋友说:“猫哥,这图里猫的右前爪怎么有六根脚趾?”

我放大一看,确实,那只猫的右前爪明显多了一根脚趾。而且整个爪子的位置也不太对,像是从肩膀直接长出来的。我当时就觉得自己像个傻子。我天天给别人讲“AI生成的内容要仔细验证”,结果自己随手就发。

那天晚上我反思了很久。我意识到一个很严重的问题——我已经开始对AI生成的内容产生一种“默认信任”了。这种感觉很微妙。当一个工具大部分时候都给你正确的结果,你就慢慢放松了警惕。尤其是文字内容,AI写的文档、代码、说明,看起来那么专业,那么流畅,你就很容易跳过验证这一步。

今天下午那个代码bug让我更深刻地体会到这一点。Claude写的那段RAG代码,从整体架构到函数命名,从导入模块到异常处理,都写得比我好。但就是那一个参数的变化,让整段代码在新版本里跑不起来。如果我是个刚入门的开发者,照着这个代码去写项目,可能debug一整天都找不到原因——因为错误信息根本不会告诉你“这个参数已经废弃了”,它只会说“AttributeError: ‘VectorStoreRetriever’ object has no attribute ‘top_k’”。但你查官方文档的时候,发现top_k确实还在文档里,只是被标记为deprecated了。

这种坑最要命的地方在于,它让你在“信”和“不信”之间摇摆。太信任AI,你会被这些细节坑;太不信任,你又得事事手工,那用AI的意义何在?

我现在养成了一个习惯,AI生成的代码或者文档,我会先让它自己解释一遍它是怎么写的。比如我让Claude写了一段数据清洗的pipeline,我会追问:“你这里为什么用`fillna(method=’ffill’)`而不是`fillna(value=0)`?这两种策略分别适用于什么场景?”如果它能把背后的逻辑讲清楚,我才会放心用。如果它支支吾吾或者给出一个很表面的理由,我就知道它可能只是从训练数据里拼凑出来的。

还有个更实用的办法,我最近开始用了。就是让AI给自己生成的内容做“自我审核”。比如一段代码生成完后,我会加一句:“请检查这段代码是否使用了任何已经废弃的API,并列出所有可能在新版本中不兼容的地方。”有时候它能发现,有时候它发现不了——这就说明它自己也不确定。

今天下班前,我把那篇RAG教程重新改了一遍。把所有的API调用都标注了版本号,还在开头加了一个大写的警告:“本教程基于LangChain 0.2.8,如果你使用的是0.3.x版本,请参考附录中的迁移指南。”附录里我甚至把每个变更的commit链接都贴上了。

改完之后我又检查了一遍,发现还是有个地方写错了。我在附录里引用了一个GitHub issue的链接,结果链接打不开——那个issue已经被关闭并标记为“已过时”了。

我盯着屏幕,沉默了几秒钟。

算了,今天就到这吧。明天再改。反正这篇博客发出去之后,肯定又会有读者来告诉我哪里错了。到时候我再更新。

这种被自己打脸的感觉,说实话挺上头的。它逼着你去直面一个事实:AI再强,也强不到能替你承担判断的责任。你可以让它写代码、写文章、画图、做PPT,但最后把关的那个人还是你自己。而且这个把关的动作,随着AI能力的提升,只会越来越难——因为错误越来越隐蔽,越来越像真的。

我关了电脑,去冰箱拿了瓶啤酒。喝了一口,突然想到一个问题:如果有一天,AI生成的内容里混进了一个我完全看不出来的错误,而这个错误恰好被读者当成了真理,那算谁的锅?

算我的。因为是我发的。

行吧,今天就记这么多。明天继续跟AI斗智斗勇。


📎 延伸阅读

看完这篇,如果你想:

  • 直接拿工具 → 回复”13“,我把跨境获客工具包发给你
  • 系统学习 → 点击菜单”AI训练营”,从0开始跑通AI变现

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注