奥卡姆剃刀原则是越体会越精妙的,这东西简直到处都能解释得通。诡异的是,在提示词工程里恰恰相反。你少说一句,结果就差一句重点,你改成“不要怎样”,反而比“要怎样”更管用。所以提示词工程真的是很恼人的一个工程。至少对我而言。
前两天有希群有个群友pnpm i报错,报的是内存溢出的错,内存正常大小,ai支招加改限参数,改环境变量配置,不知道也是不是幻觉出来的配置键,未果。后来说是更新nodejs,也不知果没果。
我很讨厌完全把工作交给ai的一大要素是ai不懂得“最小改动”和“一劳永逸”之间的平衡,或者类似的处事哲学。举例来说,ai为了在同一上下文留下“处理了xxx情况”这一标志,不惜动用大量代码重复地在调用链的各个位置处理同一个情况。其次,上下文不足的ai通常难以合理地模块化,即使它有模块化的想法,但它无法一锤定音,敲死模块的职责界限,比如在一个实现XXX依赖职责界限模糊的容器且未大规模引用的模块中,一个人类进行引用时合理的做法是在模块中新增注释明确该容器的XXX职责范围,并查找其引用确保所有引用当前是符合规范的,这将以注释与同事或者未来的自己进行约定。但以上下划线部分完全由经验总结而成的具体行为准则,ai至今不能彻底无师自通(因为这只是大量不同经验场景行动中的一小部分),又不能将其塞进上下文,塞进提示词又琐碎,塞进skills它也不一定会去看。
于是“冗余”诞生了。
AI的“对而不好”的操作下,代码行数成了注水的统计指标。一个人干出cloc统计五位数甚至六位数行数的项目,总能给项目带来点面子。我曾经也是这样。前端项目一个人一个月一个AI从零写破万行已不是什么新鲜事。冗余自带指标色彩,而指标一旦成为目标,就不再是好的指标。
适当的冗余对安全是有好处的。但当冗余过度,大量的无意义修改性注释压倒性地扑灭真正有价值的标记,代码库堆满了完全重复但又有点细节不同的逻辑,重复的轮子遍地跑,性能爆炸不提,bug无法稳定复现,拙劣的局部全局设计模式,外行的需求驱动的编程没有任何原则,在ai自己写出自信的注释里连ai自己也找不出bug在哪,看着代码里的人机聊天记录说是不是你环境有问题,每个边缘情况都被粗暴地打上补丁而非根治。项目维护成本飙升,新人入职光看代码就得半年。不对还看什么代码,当然是继续用ai往里边堆史啊哈哈哈哈😅
这时,有人会说:既然如此,干脆否定程序员的价值,让Agent全权接管。反正AI能写代码,能修bug,虽然写得冗余,但架不住写得快啊。
你别说,我无法反驳。谁知道再过两年世界会变成什么样……反正我可不想进这种地方干活。
给得够另说。扯远了。
抛开AI底层不谈,现在成品Agent如cc,codex,trae这类产品基本都能在人类不参与下在提示词层做出测试闭环。
一种思路在闭环中增加关于可维护性、或者说专门用于决策方案合理性的子环在应用层是可行的。
AI不能很快就做到这一点,它和现在相比半年前已经实现的测试闭环相比不是一个明确的概念,而是几句话不可能解释明白的改动方案甚至注释级别的平衡。而这种平衡本身在世界上也没能统一标准,因为一个改动经常要在解决眼下问题和从长远计划之间做一些选择。当然,这个问题即使是以前程序员来决策也是个问题,只不过学习和代码成本能使其主动下降到最优的方案,原始的懒惰驱动的最优化(?)在AI上不可行,因为AI一大特征就是快,快到可以先全写完再看能不能跑。甚至写完之后就会认为这件事解决了,哪怕没解决也会认为这么多的代码原本就是有用的,抑或是人类根本没发现这个冗余的甚至可能性能代价极大的代码,然后去尝试下一个方案。
唉,一代人有一代人的屎山。
Mizuki主题存在一个很诡异的《强力滚动保护.js》,三百多行代码是仅用于保护Twikoo评论按钮点击导致的异常滚动问题的。这文件肯定是AI写的,从输出到控制台这事就能看出来。而同期同上游的Firefly主题,通过修改Twikoo源码重新构建从源头解决。从奥卡姆剃刀来看,将问题消除,而非新增解决方案。*但Firefly的问题是twikoo更新还需要再去自己构建,最终源头是解决twikoo,比如新增可选修复项。
这一点上来说,我可能更注重代码库本身的逻辑量。解决一个库带来的问题成为不可或缺的逻辑和为了引入这个库,维护这个库的微修改版本哪个更好,还有待讨论。
Mizuki正在水深火热重构中。原因是8.3引爆了某个惊天大雷导致样式全炸。后来有希决定拆分,这当然不再是堆史了,不过这个工作上来说仍然是AI可能完成的范围。
AI同时负责开发和维护使得代码始终人类可读或许也是一种和AI和解的方式?
