未必。
多数人现在的工作流是这样的:把需求塞进 prompt,拿到代码,不满意就改 prompt 再来一轮。反复调,存档,好像 prompt 写对了代码就对。
这等于把地基打在流沙上。
prompt 不可维护。三个月后回头看,你通常根本不知道自己当时为什么要那么写。LLM 版本一换,效果跟着变。prompt 高度依赖某个时间点和某个模型版本的偶然行为。
Unmesh Joshi 上个月在 martinfowler.com 写的东西,核心我想是这个:prompt 不该是你的 source of truth。DSL 和它背后的语义模型才是。
DSL 是一套受限语法,表达的变化少,通常还带着确定性验证器。这两个特点凑在一起对 LLM 很友好。语法受限,生成结果跑偏的空间就小。带验证器,agent 能自己检查生成的东西对不对,不用人盯着。
多数人本能觉得给 LLM 更多自由度,效果越好。
这个直觉通常是错的。自由度大意味着同一个意图能被翻译成无数种写法。变化越多,出错的角落越多。DSL 把表达压窄,反而让生成更可靠。
Joshi 文章里有个细节。Tickloom 框架把每个节点建模成单线程 tick 循环,时间以 tick 计,再用抽象表达复制、广播和 quorum。这些约束把 LLM 实现协议时的决策空间压得很窄。窄是好事。
还有一个点。大型系统的完整设计没法预先确定,初始规范只是一组待修订的假设,真实约束在实现过程中才冒出来。这个观察不新,但 Joshi 往前推了一步:既然设计决策是在实现中揭示的,写代码这个动作本身就是在发现设计问题。
跟 DSL 的关系在这里。如果直接让 LLM 生成一般代码,实现过程揭示的约束散落各处,你抓不住。但如果生成的是 DSL 程序,约束被语法和类型系统强制收拢。非法场景直接编译不过。你不用从一堆乱码里猜哪里不对,编译器替你挡住了。
所以有两件事被搞混了。一是在设计阶段,LLM 帮你发现抽象、迭代 DSL。二是在抽象建立之后,LLM 把人说的话翻译成符合 DSL 词汇表的程序。两个阶段角色完全不同。
多数人只用了第二个,而且用的时候没有 DSL,只有一般代码和 prompt。
这大概解释了为什么很多人觉得 AI 生成的代码"能跑但不敢碰"。没有语义模型在背后兜底,你不知道改一行会不会碰翻什么。
如果我对,接下来值得想的不是怎么把 prompt 写得更好,而是什么东西应该被固化成 DSL,让 prompt 降级成一次性的输入。prompt 是一次性的,DSL 是持久的。把持久的东西当一次性的用,是在浪费 LLM 时代最该建的那层东西。
¹ 前提是 DSL 本身设计得好。糟糕的 DSL 加上 LLM,只会让灾难的产出速度变快。这个前提不是次要的,但那是另一个话题。
