实时软件生成
传统的软件生成方式需要程序员编写大量的代码,然后进行测试、发布等一系列繁琐的流程。而实时生成技术则是借助人工智能技术,让计算机自动生成代码,并直接运行,从而大大提高了软件生成的效率和质量。
实现实时软件生成的一种方式是 Prompt 编程,可以将自然语言转化为直接运行的软件,而无需生成中间的一次性过渡代码。
引子
从 2019 年,写了那篇《无代码编程》开始,我也一直在思考,诸如于 2021 年 和 2022 年 的前端趋势总结。
先前,我并不看好当前的低代码/无代码方案,先我们来思考一下这个过程:
第一步,业务需求需要在人类脑海里转换一遍,转换为程序逻辑。
第二步,专业人员(如程序员)将这些逻辑转换到无代码系统中,生成应用并直接部署。
第三步,如果这个专业人员是程序员,那么新的需要变更时,他可能直接去修改源码。
那么问题也就来了,更改后的源码无法再与之前的无代码系统同步,这就导致了无代码系统的失效。而这个问题,也是我之前一直不看好无代码的原因。
但随着 ChatGPT 的进一步普及,你会发现你可以很容易将需求转化为形式化格式,进而转化而软件,从而使得软件开发的效率和速度大大提升。这种一次性代码的新型软件工程方法就是实时软件生成,便可以进入真正的 “无代码” 时代。
Prompt 编程:真正的无代码
Prompt 编程是实现实时软件生成的一种方式,可以将自然语言转化为直接运行的软件,而无需生成中间的一次性过渡代码。每当需要运行程序时,只需要再运行一下 prompt 或者触发词,就可以直接运行起某个软件。
我们尝试从编写 Prompt 的经验里,归纳出一套适合于 Prompt 编程的逻辑,方便于大家理解。Prompt 编程有以下特性:
1)从需求到代码的直接转换
2)代码只是临时产物
3)次序化的分解框架
这种一次性代码的新型软件工程方法可以进入真正的 “无代码” 时代。
Prompt 编程特性 1:从需求到代码的直接转换
用户只需要简单输入自己的需求就能够生成符合要求的软件,无需具备专业的编程技能。示例:
我们来玩一个 mul 游戏,当我说 mul 开头,并输入数字时,你应该计算结果。示例:"""当我输入:mul 4,你应该输出:16"""
在这个游戏里,我们使用:
- 触发词。mul 作为街头暗号,告诉程序你要按这个步骤走。类似于编程里的函数名。
- 示例作为输入和输出。即预期输入某个结果时,输出我们想要的结果。
而在其实,已经是一个函数该有的样子:输入、输出、关系。值得注意的是,在简单的问题下,只要我们给定了示例,那么 AI 就会根据示例去计算输入和输出,不关注中间的处理逻辑。
接下来,再看一个隐含性编程的示例,依旧我们还是玩个游戏:
我们能玩一个名为 kfc 的谜语创作游戏,当我说 "kfc",你写一个谜题,要求:
1. 不少于 200 字
2. 谜题不能出现肯德基和星期四
3. 正文可以夹杂小语种语言,如 """他说:Ciao"""
4. 谜底必须是 ###原来今天是肯德基疯狂星期四!!!###
格式类似于:
"""
...
"""
这个例子已经相当的自由,我们也不关心中间的处理逻辑,只关注于结果。
Prompt 编程特性 2:代码只是临时产物
还记得在 Prompt 编写模式 中的 wula
游的例子吗?在 wula 游戏里,用户只需要输入问题,ChatGPT 便会自动给出代码、代码解释和文章。诸如于:wula: 头共10,足共28,鸡兔各几只?
,那么 AI 便会开始自动开始二次编程:
这是一个鸡兔同笼问题,题目给出了头的数量和足的数量,要求求出鸡和兔的数量。通常解决这个问题的方法是,假设鸡和兔的数量分别为 x 和 y,那么可以列出如下方程组:
x + y = 10
2x + 4y = 28
解方程组可以得到 x=4,y=6,即鸡有4只,兔有6只。
鸡兔同笼问题的 JavaScript 代码实现
// 计算鸡兔数量的函数
function calcAnimals(heads, legs) {
.....
在传统的体系之下,我们要关注于中间生成的 JavaScript 代码、代码能不能运行等等,所以我们在设计 wula 的时候,要求了:
第二步. 代码编写:你需要用 JavaScript 编写解决这个问题的代码,并输出对应的代码,并介绍一下你的代码(不少于 200 字)。
第三步. 代码执行:你需要作为 JavaScript Console 执行第二步写的代码,如果没有给出测试数据,你需要自己随机生成测试数据,并将这些数据输入到代码中进行计算。
但是,回到第一个例子里,我们并不需要 JavaScript 代码,我们不需要任何代码。ChatGPT 可以为我们生成这部分的程序!!!
唯一限制我们的是:
- ChatGPT 的上下文能力
- 我们的 Prompt 编写能力
而在复杂的场景之下,Prompt 编写需要足够的形式化,才能让机器理解,也因此,我才把它称为 Prompt 编程。
Prompt 编程特性 3:次序化的分解框架
仅就当前而言 AI 的上下文能力,限制了 AI 解决复杂问题的能力。所以,它无法一次性解决复杂、中大型的问题,甚至于小型项目都存在一定的难度。同样的,对于人类来说,也存在这样的局限性,只是人类的问题是领域知识有限。
步骤详细见:DDD Sample
所以,作为编程核心的人类大脑,需要为机器设计一下工序,即每一步应该怎么做。所以,这个时候,就回到了 DDD(领域驱动设计)擅长的问题:
我们来定义一下 DDD 游戏的步骤,一共有 6 个步骤,步骤如下:
"""
第一步. 拆解场景。分析特定领域的所有商业活动,并将其拆解出每个场景。
第二步. 场景过程分析。选定一个场景,并使用 "{名词}已{动词}" 的形式描述过程中所有发生的事件,其中的名词是过程中的实体,其中的动词是实体相关的行为。
第三步. 针对场景建模。基于统一语言和拆解出的场景进行建模,以实现 DDD 设计与代码实现的双向绑定。
……
"""
对于每一步,我们只要限定好我们的输出(Output),那么在给定输入的情况下,AI 就能给出我们想要的(也有可能跑偏了)结果:
ddd 第二步:场景过程分析。下面是每个场景的过程分析:
用户注册和登录
用户注册:用户填写注册信息,系统验证信息合法性,生成用户账户并保存。
用户登录:用户输入账户名和密码,系统验证账户密码,登录成功后跳转到用户中心。
商品展示和搜索
商品列表展示:系统从数据库中获取商品列表并展示,用户可以进行商品分类和排序。
商品搜索:用户输入关键词进行商品搜索,系统根据关键词从数据库中获取商品列表并展示。
……
在这时,我们就可以引导 AI 生成到 API 粒度:
API名称 | 请求方法 | 请求路径 | 请求体 | 响应体 | 描述 |
---|---|---|---|---|---|
创建商品 | POST | /api/products | 商品信息 | 创建的商品信息 | 创建一个新的商品 |
获取商品列表 | GET | /api/products | 无 | 商品列表信息 | 获取所有的商品列表 |
获取单个商品信息 | GET | /api/products/{id} | 无 | 单个商品信息 | 根据商品 ID 获取单个商品信息 |
更新商品信息 | PUT | /api/products/{id} | 更新的商品信息 | 更新后的商品信息 | 根据商品 ID 更新商品信息 |
删除商品 | DELETE | /api/products/{id} | 无 | 无 | 根据商品 ID 删除商品信息 |
也可以生成代码,甚至于在上下文足够强大的时候,也是能够直接运行和自动优化的。
Prompt 编程特性 4:语言即语言
DSL(领域特定语言)是指专门针对某个特定领域的语言,通常具有严格定义的语法和规则,并且可以用来描述该领域中的问题、概念、过程和数据等。而经过形式化处理的自然语言可以被视为一种 DSL,因为它们具有明确定义的语法和规则,可以用来描述特定领域中的问题、概念、过程和数据等。
所以,简单来说如果我们限定了输入和输出的格式,那么我们的自然语言也是一种 DSL。这就意味着,限制我们进行次序化的关键就是形式化的抽象。
而,我们也可以通过编写 Prompt 来生成新的 DSL:帮我设计一个 DSL,用来写函数
好的,以下是一个简单的DSL设计,可以用来写函数:
1. 函数定义
在这个段落中,定义一个函数,包括函数名、参数和函数体等。
###
函数:
函数名:
描述函数的名称
参数:
参数1:
描述参数1的名称和类型
参数2:
描述参数2的名称和类型
...
函数体:
描述函数的实现细节
###
2.。。。
简单来说,我们可以通过 Prompt :
- 借用 Prompt 设计自然语言式的 DSL
- 将自然语言式的 DSL 融入 Prompt
- 使用次序化的方式来实现 Prompt 自我编程
进而,我们就得到了一个可以自举的 Prompt。
一个问题:重构
重构是指在不改变软件外部行为的前提下,对软件内部结构进行调整,以改进软件的可理解性、降低其未来的维护成本。 而在实时软件生成中,我们的软件是由 AI 生成的,那么,重构是否还有意义?