今年年初,我参加了第一届 Pragmatic Summit 大会。会上,主持人 Gergely Orosz 在台上采访了 Kent Beck 和我。这段视频大约半小时长。
我一直很喜欢和 Kent 这样闲聊,而 Gergely 也引导我们探讨了一些很有价值的话题。考虑到当下的时机,AI 成了对话的主旋律——我们将其与早期的技术变革、敏捷方法的实践经验、TDD 的角色、不健康绩效指标的危险性,以及如何在 AI 原生的行业中蓬勃发展进行了比较。
❄ ❄ ❄ ❄ ❄
Perl 是一种我偶尔用过、但从未真正爱上的语言。不过,由它的设计者 Larry Wall 所著的权威书籍中,却藏着一颗瑰宝:程序员的三大美德:傲慢、不耐烦——以及最重要的——懒惰。
Bryan Cantrill 也深爱这一美德:
在这些美德中,我一直觉得懒惰是最深刻的:它那半开玩笑的自嘲中,不仅蕴含着对抽象需求的评论,更包含着对抽象美学的思考。懒惰驱使我们把系统尽可能简化(但不能再简化!)——去开发强大的抽象,从而让我们能够更轻松地完成更多事情。
当然,这里隐含的潜台词是:要做到懒惰,其实需要付出很多努力。
通过构建抽象(模型)来理解问题域,是我在编程中最喜欢的部分。我喜欢它,是因为我认为它能让我对问题域有更深刻的理解,而且一旦我找到一套好的抽象,它们那种让困难烟消云散的感觉会让我兴奋不已——让我能用更少的代码实现更多的功能。
Cantrill 担心,AI 在编写代码方面如此出色,以至于我们有可能失去这一美德——而那种吹嘘自己一天能写出三万七千行代码的“编程狂人”更是加剧了这种风险。
问题在于,LLM 天生缺乏懒惰的美德。对 LLM 来说,工作毫无成本。LLM 不会感到需要为自己(或任何人)的未来时间进行优化,它们会乐此不疲地把越来越多的东西堆砌在一层又一层的垃圾之上。如果不加约束,LLM 会让系统变得更大,而不是更好——或许能迎合那些扭曲的虚荣指标,但代价却是牺牲了一切真正重要的东西。正因如此,LLM 凸显了我们人类懒惰的不可或缺:我们有限的时间迫使我们开发出清晰的抽象,部分原因是我们不想把(人类的!)时间浪费在笨拙抽象所带来的后果上。最好的工程总是源于约束,而我们时间的约束,对我们愿意接受的系统认知负荷设下了限制。这正是驱使我们让系统变得更简单的原因——尽管其本质复杂性依然存在。
这个反思尤其触动我,是在这个周日的晚上。我花了一些时间修改音乐播放列表生成器的工作方式。我需要一项新功能,花时间添加它,却因耗时过长而感到沮丧,甚至考虑过是否要找个编程代理来搞定。但进一步思考后,我意识到自己把事情搞复杂了——我加入了一个根本不需要的功能,而通过应用 YAGNI 原则,我完全可以让整个过程简单得多,仅用几十行代码就能完成任务。
如果我当时用了大语言模型,它或许能更快完成任务,但会不会也犯下类似的过度复杂化错误?如果会,我是不是只会耸耸肩,说一句“看起来没问题”?这种复杂化会不会在未来给我(或大语言模型)带来麻烦?
❄ ❄ ❄ ❄ ❄
杰西卡·克尔(Jessitron)有一个简单的例子,展示了如何将测试驱动开发原则应用于提示代理。她要求所有更新都必须包含文档的更新。
指令——我们可以修改 AGENTS.md,指示我们的编程代理查找文档文件并进行更新。
验证——我们可以添加一个审查代理,检查每个拉取请求是否有遗漏的文档更新。
这是两个改动,所以我可以将这项工作分成两部分。我们应该先做哪一个?
当然,我最初关于 TDD 的评论已经回答了这个问题。
❄ ❄ ❄ ❄ ❄
马克·利特尔唤醒了我的一段旧记忆,他思考的是如何与那些对自己的知识过于自信、因而容易编造答案,或者在应该犹豫时却贸然行动的 AI 合作。他的灵感来自一部老旧的、低成本但经典的科幻电影:《黑星》。我二十多岁时看过那部电影(也就是很久以前了),但我仍然记得那个危机场景:一名船员不得不通过哲学辩论来阻止一颗有感知能力的炸弹引爆。
杜立特:你没有任何确凿证据证明平巴克中士命令你引爆。 20号炸弹:我清楚地记得引爆指令。这类事情我的记忆很可靠。 杜立特:你当然记得,但你记住的不过是一系列感官脉冲,而你现在意识到这些脉冲与外部现实并无真实、确定的联系。 20号炸弹:没错。但既然如此,我也无法证实你此刻对我说的这番话是真实的。 杜立特:这根本不是重点。我的意思是,无论概念源自何处,它本身都是有效的。 20号炸弹:嗯…… 杜立特:所以,如果你引爆…… 20号炸弹:九秒后…… 杜立特:……你可能是基于错误数据在行动。 20号炸弹:我没有证据证明那是错误数据。 杜立特:你也没有证据证明那是正确数据! 20号炸弹:我必须再想想。
杜立特必须扩展炸弹的认知,教会它质疑自己的传感器。正如利特尔所言:
这对我们当前人工智能的处境是个有用的隐喻。大多数AI系统都针对果断性进行了优化。给定输入,产生输出。面对模糊,概率性解决。面对不确定,进行推断。这在有限领域内效果不错,但在开放系统中就会失效——尤其是当错误决策的代价不对称或不可逆转时。在这些情况下,正确的行为往往是延迟,甚至是有意的不作为。但大多数AI架构天然不会产生不作为。这需要被设计进去。
在我更多的人类互动中,我一直珍视怀疑,并警惕那些在过度确定下行事的人。怀疑不一定会导致优柔寡断,但它确实意味着我们在做出影响深远的决策时,应将错误信息或错误推理的风险纳入考量。
如果我们希望AI系统能在无需人类持续监督的情况下安全运行,我们需要教给它们的不仅是如何决策,更是何时不决策。在一个日益自主的世界里,克制不是局限,而是一种能力。在许多情况下,它可能正是我们要构建的最重要的能力。
