草根AI:超越登月计划
本文批判了当前AI领域追求完全自主代码生成的“登月计划”式目标,回顾了历史上类似的失败尝试(如XML、UML、低代码/无代码),指出自然语言规范无法取代代码作为唯一真理,并警告AI生成规范的方法存在数据到信息再到情报的误差累积问题。
在人工智能领域,似乎每个人都想追求所谓的“登月计划”——一种神奇的组合,能让代码自主、可靠、可持续且廉价地编写。这并非新想法,而且它并不奏效。
我理解登月计划的诱惑:开疆拓土、创造新范式、成为《时代》杂志封面上的英雄。毕竟,如果你不颠覆一个行业,你还能做什么?我明白,如果能创建出一个在无人监督下编写代码的系统,那将是巨大的胜利。但软件历史中的无数警示故事让我几乎无法原谅这种尝试。
“我们不再需要查看代码”的历史
XML于1998年首次发布。当时它被认为是一场革命,带来了各种工具:XSL、XPath、XSLT……XML文档本应是可组合的,愿景是互联网上的文档相互连接,形成互联的信息景观。那时我们开始谈论语义网。未来是光明的。
事实上,XML很笨重,没有人真正喜欢它,但这没关系——因为它不是为人类设计的,而是为机器设计的。你不应该阅读或编写XML文档,只需处理解释和修改XML内容的图形界面。几十年后,XML在很大程度上被JSON和YAML取代,它们对程序员更友好。事实证明,人们确实喜欢直接阅读和操作文件。
大约在同一时间,出现了KDevelop和Eclipse等最早的图形化IDE。它们有大量插件和图形界面,显示项目的多个视图:一个面板用于Ant命令,另一个面板用于列出可用方法等。再加上当时较小的屏幕和较低的分辨率,导致代码面板只是中间的一个小窗口,几乎只能显示15-20行代码;但这没关系——因为你实际上不需要看代码,你只与图形元素交互。创建一个方法意味着File -> Add -> Method(或类似的步骤),然后会弹出一个对话框,你输入名称、参数等。向Maven添加依赖项也有自己的对话框。你不与代码交互——那是为机器准备的。你与UI交互。
早期的Eclipse IDE版本。没有太多空间留给代码;但这并不重要。
如今,IDE将代码面板尽可能放大,甚至并排显示两个或更多代码面板。还有一些极简主义选项,如Sublime,去掉了所有图形元素,让你完全专注于代码。
那时也是Poseidon出现的时候。UML风靡一时,面向对象编程正在兴起,Poseidon将这一切与一个新的承诺结合起来:你使用UML绘制构成程序的实体,指出关系和属性,它为你生成代码。因为你是一位高价值的工程师,不应该浪费时间和才能去编写代码。不,先生。
海神显然非常擅长编程。
不用说,这并没有成功。他们的辩护者会说:“初级工程师读代码,高级工程师读图。”他们把自己比作处理蓝图而非砖块的建筑师。但最终,我们回到了代码。
ETL、低代码、无代码……我可以一直列举下去。梦想从未改变:我们不再需要查看代码。每次像我这样的末日预言者会咕哝“我们以前试过”。每次我们都会听到“但这次不同”。每一次,它又变成了另一个破碎的梦。每一次,我们回到了代码。
事实上,历史教给我们的不仅是不会放弃直接操作代码,反而加倍下注!我们将通常通过配置、设置和UI管理的活动也变成了代码,从而诞生了基础设施即代码、GitOps,最终是万物即代码。
代码即规范
在今天“但这次不同”的阵营中,理论是你编写所需内容的详细规范,AI创建代码。以至于人们将AI规范与编译器相提并论,称这只是另一个抽象层。他们声称AI生成代码的批评者就像早期不喜欢高级语言而继续使用汇编的程序员。然而,这一类比经不起推敲。
编程语言通常由BNF文法描述,可用于验证其语法是否正确。它还有一个编译器,以数学精度将源语言转换为目标语言。“数学”一词在此绝非夸张:编译器确实可以被描述为一个数学函数,以定义明确且可预测的方式将输入转换为输出。事实上,这种特性从一开始就威胁到了软件专利的概念:所有软件都可以使用lambda演算重写为数学公式,而数学公式不能申请专利。但我说远了,重点在于,当你编译源代码时,你确切知道会得到什么(或者至少应该得到什么)。
AI并非如此;或者说,LLM并非如此。自然语言无法被正式定义。自然语言混乱、模棱两可,最糟糕的是,它的含义随着时间、地点和文化而变化。或者正如维特根斯坦所说,“一个词的意义在于它在语言中的用法”。这就是为什么律师在起草协议时要费尽心思以防日后反噬。理论上,你可以用自然语言编写一个指示你想要的规范。实际上,该规范有可能被误解,可能遗漏隐性知识,或者基于未沟通的假设。AI会顺从地尝试生成匹配你的规范的程序,但必然会出现幻觉、遗漏和偏差。此外,考虑到LLM本质上是非确定性的,连续两次使用相同的输入调用它会得到不同的输出。总体行为可能得以保留,但会引入细微的漂移。这与人类期望相冲突:没有人喜欢按钮被随意移动,即使它们功能完全相同。
解决方案据称非常简单:确保你的规范包含所有相关细节、所有需求、所有边缘情况、所有知识。确保它的编写方式不留歧义。确保它明确排除了任何潜在的误解。确保所有利益相关者都已审查并批准了它。简而言之,确保你的规范是良好定义的。好啊,再来一份薯条吧。良好定义的规范自从软件开发成为一个行业以来就一直是个圣杯。它从未实现过。良好定义的规范是软件领域的球形奶牛。
但让我们继续假设我们可以创建一个包含项目细节的良好定义规范,现在我们发现自己面临着完美地图悖论:要毫无错误地指定代码必须做的一切,唯一的方法是以与代码本身一样多的细节来指定它。地图变得和它试图描述的领土一样大。规范变得冗余,因为它不再是代码的抽象,而是变成了代码的副本,而对于代码,我们已经有了实际的代码。
最终,代码是唯一的真理源。
毕竟,这是基本熵的问题,完美地体现在柏拉图的理型论中:你可以从特殊中构想抽象,但从抽象中创造特殊总是有缺陷的。
用AI创建规范
在可预见的“AI万物化”风格中,新兴的规范驱动开发的捍卫者认为,你可以将AI嵌入所有业务交互中,这样规范就会自动编写(听起来耳熟吗?)。你有一个会议?启用AI记笔记,会议结论自动可用。你录制了一次用户研究会议?让AI提取要点。你现在拥有的文档多得一辈子都处理不完?使用AI分析并提炼要点。这些信息是否稀疏、矛盾且可能错误?AI会为你修复。
此时,我们需要向那些处理潜在不可靠数据数十年的机构——情报界,即CIA、NSA、SIS及其朋友们——学习。首先,我们需要区分三个概念:数据、信息和情报。
数据:事实,不带任何判断或分析。例如“伯尼斯说了X”或“三月份售出了200个玩具”。
信息:结构化数据,以在特定上下文或目的下变得相关的方式组织和过滤。例如“玩具销量持续下降”。
情报:从目标、价值观和环境的视角分析信息,以生成可操作的指令。例如“由于竞争对手更有效的营销,他们正在蚕食我们的市场份额”。
AI可以轻松提供大量表面数据,其中大部分是正确的。AI可以尝试从数据中生成信息,但这往往会遗漏重要的细微差别,这些细微差别没有写在任何地方,因为它们属于集体的、不言而喻的知识(共同假设、制度惯性、文化暗示等)。如果你再次尝试使用AI进入下一步,所有微小的错误会累积,产生看似不错但足够不准确的情报,使其无法使用。有点像复印件的复印件。
“你们这些信心渺小的人!这有一个简单的解决方案,只需要让人审查并在必要时纠正AI生成的所有内容。所以会议后,人们审查并批准会议记录。然后,在AI整合后,人们审查并批准摘要。然后,当规范被编写时……”
继续,我让你说完,你可以自己写反驳。
但暗工厂!
啊,是的,暗工厂。如果你还没听说过,暗工厂(或熄灯工厂)是高度自动化以至于不再需要人类的工厂。而且,既然不需要人类,他们甚至不需要开灯,所以它们在黑暗中运行。很酷。这个想法让一些人兴奋不已,引发了下一个科幻类比:AI是我们的暗工厂,你释放一堆代理,它们在没有人类干预的情况下创建代码。“我在溜狗时建了一个加密货币交易平台。”诸如此类。
让我们退几步。首先,时间尺度问题。工业革命开始于大约250年前,直到现在才开始谈论完全自动化、没有人类参与的工厂。整个软件行业存在时间不超过70年,AI更短;期望在这么短的时间内将高度手动的工作变成完全自动化是过于乐观的。
其次,制造业和软件之间有一个根本区别:在制造业中,你生产多个完全相同的副本。而在软件中,每次构建都是独一无二的。