Posted by: Phodal Huang March 15, 2023, 5:43 p.m.
过去的一个月里,我一直在研究 ChatGPT,也与很多人(普通人、程序员、创业公司、风投等等)进行了交流。不论是业内(编程)还是业外,人们对于 AI 编程的观点都是:未来可期 —— GPT,他好像什么都能干,也好像什么都干不好。
所以,在这篇文章里,我将继续总结与其他人聊天的观点。
对应的思路总结,也可以在 ClickPrompt Flow 上查看:ClickPrompt - Streamline your prompt design
对于 AI 代码生成来说,除了过去的 GitHub Copilot、Codex、Kite、TabNine 等等,新出的免费的 ChatGPT 又让人感觉非常酷。
现在,大家几乎已经习惯了网上的各种暴力 AI 美学 —— 唤出 ChatGPT 写代码:
基于于在最新的 GPT 4.0 里,可以根据图片等一些基本的描述,生成全新的 HTML。
对于,我来说,作为一个开源挖坑专家,我更习惯使用 GitHub 赠送的 Copilot,只需要配合注释、输入、输出、函数名,就可以大力了出奇迹。如下是 ClickPrompt 中的真实代码:
// 1. split promptMatch by comma
// 2. match lora name by regex, lora full name: ,
// 3. push lora name to loras array
我在代码中保留了这个注释,一种很神奇的用法 。
因此,我觉得在 AI 编程时代,人们的编程思维是要发生变化的:
当注释作为 prompt 保存,那么 prompt 便是作为一种代码,保存在代码库中了。而代码还将是代码吗?我们为什么还需要中间生存的代码,是因为审计、安全等原因吗?
而当你尝试过使用 AI 来编写代码之后,你会发现 AI 存在一系列所谓的 “问题” 。让我们来再看一个简单的例子,我们让 ChatGPT 来实现一段代码。
/book/:id
的 N 种方式在不同的语言和架构模式里,实现的方式是有区别的。
第一个 Demo:用 Spring + MyBatis 实现一个 API:/book/:id
。
ChatGPT 会创建 BookMapper.java、Book.java、BookMapper.xml、BookController.java 四个代码段,然后告诉你,你可以启动这个 API 了。
PS:有意思的是,你并不需要一个 BookService.java,因为 AI 也 “觉得” 他是多余的。
但是,要上线这个应用并不是一件容易的事,我们需要手动编译 Java 代码,再运行起来,这速度是非常慢的。除非,我们有类似于几年前的 OSGi 架构,或者 Serverlesss 架构。
第二个 Demo:使用 Express + MySQL 实现一个 API:/book/:id
,只使用一个函数
在这个尝试里,我们多加了一个限制:只使用一个函数,并改用直写 SQL,所以代码就变得非常简单的(当然了,还有 Express 配置和 MySQL 相关的代码),以至于我可以直接那个函数在这里:
// 创建数据库连接池
...
const getBookById = (req, res) => {
const id = req.params.id; // 获取路径参数中的 id
// 从数据库中查询书籍信息
pool.query('SELECT * FROM books WHERE id = ?', [id], (error, results, fields) => {
if (error) throw error;
if (results.length > 0) {
const book = results[0];
res.json(book); // 将书籍信息以 JSON 格式返回给客户端
} else {
res.status(404).send('Book not found');
}
});
};
// 创建路由器并挂载到根路径上
...
// 启动应用程序
...
如果我们认定了 AI 生成的代码是准确的,无需要人类去修改,那么我们就可以直接用上面的代码。
第三个 Demo:使用 AWS Lambda 实现这个 API:/book/:id,只使用一个函数
使用 Express 来实现这个功能,还是有点复杂,我们还需要考虑基础设施,但是当我们考虑使用 Serverless 来实现时,问题就变得非常简单了:
const mysql = require('mysql');
exports.handler = async (event, context) => {
....
}
然后,我们就可以采用 ClickPrompt 类似的方式,直接一键部署到服务器之上。
让 AI 来对比一下,你看吧,显然 AI 也觉得 Java 的实现起来复杂,但是可扩展性高。
优点 / 缺点 | Spring + MyBatis | Express + MySQL | AWS Lambda |
---|---|---|---|
开发效率 | 较高 | 高 | 高 |
部署复杂度 | 高 | 中等 | 低 |
维护成本 | 高 | 中等 | 中等 |
可维护性 | 高 | 中等 | 高 |
架构复杂度 | 高 | 中等 | 低 |
可扩展性 | 高 | 中等 | 高 |
成本 | 中等 | 低 | 低 |
但是,我们真的需要所谓的可扩展性吗?而论部署速度,自然是 AWS Lambda 最快了。经过了几种不同的方式对比,按现有的软件工程来说,Java 写的代码是最好的。可是,AI 都来写代码了,Java 工程化,真的还是最好的吗?
让我们再打开一下思路,我们现有的架构模式、软件工程等软件开发流程都是基于现有的体系磨合过来的。
而 AI 编程的最终目标是实现自动化编程,即由 AI 根据用户的需求和设计,自动生成完整的代码。但是,理论上这不是终点,终点是生成完就可以直接运行。这就意味着,一个想法从想到到上线,可能就在几分钟内可以完成。
然而,在现有的流程里,完全不是行不通的,我们人类做不到这么的敏捷。
过去,我们认为分层架构很重要,因为代码是人来编写,代码是人来维护的。而当代码由 AI 来编写,由 AI 来维护的话,那么现有的软件架构体系还适用吗?
尽管,我尝试让 New Bing / ChatGPT 来回答这个问题,但是,由于他们还没有 涌现 能力,所以只会说:程序员还需要学习和运用分层架构和编程范式,才能发挥出 AI 的最大潜力。
但是,我觉得,从上面的 Java 示例中,你会发现按现有的模式构建的软件架构,特别容易发生冲突。AI 生成的 A 功能和 B 功能,可能在代码上出现重复 —— 因为上下文限制,我们不可能上传所有的代码。
结果,有一天你发现了,一个类里有 10 个重复代码段。然后,你又开发了一个自动重构机器人……。但是,我觉得有点多余了,AI 编程需要新的架构范式。
再再打开一下思路,试着忘记现有的软件架构模式。一个功能对应一个可运行的代码段,由 AI 来自动思考架构模式 —— 当然,我们需要给他一些限制条件和输入。
所以,放在当前的上下文之下,Serverless 是一种更适合的架构模式,即写即上线,即下线即删除。
我觉得不一定是,但是可能是当前最好的一种方案。但是,每个人都会有自己的看法。
现在,我们来变更一个需求吧,过滤一下 “名书”,包含 xx 的不显示。那么,这个时候,我们就遇到一个难题了 —— 全自动编程,还是 ***AI 辅助生成***。
纯 AI 编程,意味着:每次改需求都重新生成代码;而半 AI 编程,则意味着:人可以介入到流程中。两种将会带来不一样的思路。
自动编程 —— 重新生成代码
为了让 AI 写的代码足够的准确,我们需要给 AI 足够详细的需求(Prompt)。一旦需求发生变化的时候,我们回过头去改需求的(Prompt),再重新生成代码即可。我们要做的事情是:
AI 辅助生成 —— 支持手动修改代码
第一次代码,我们是用 AI 生成的,随后当需求变更的时候,我们想可以直接在现有的代码上改,这样可能速度比较快 —— 生成式 AI 可能还意味着:新生成的代码和原来的完全不一样,诸如于行数位置等等。
而为了能再次生成,我们还需要记录新的变更到原来的 prompt。
所以,在这个时候,如何更好地管理原始需求,变成了一个新的挑战。
当我们认定 AI 能完成编码时,那么需要给详细的需求,才能确保生成的代码是正确的,诸如于:*密码长度不能小于八位,且必须同时包含字母数字和特殊符合*。这只是一个示例,更常见的示例还有表单联动:A 字段 xxx,B 字段则 xx。只有我们的需求足够的清楚,那么生成的代码才会准确。
所以,当产品经理借助于 AI 生成足够清晰的验收条件,程序员就会失业吗?这包含了两个问题:
那么,第三个问题就来了,老板是不是可以自己干?
不过,这只是用来搞笑的,我们的下一个挑战还在于需求详细化之后,AI 真的能写对吗?
我相信策略会在今年内再次发生变化,所以,我并不想写太长。
经过大部分人的验证,AI 生成的测试代码质量非常高,大部分情况下可以直接运行。所以,在我们有了需求之后,可以创建诸如于 ClickPrompt 这样的工具,创建工作流,让 AI 逐步往下分析:
而后,我们就可以 GET 到可用的自动化测试代码。当我们有了测试代码之后,就可以验证辅助的代码是否正确。
尽管,在我的尝试中,部分场景下,生成真正的可工作的代码还有些距离(也有可能我的场景比较特别) —— 没法直接用,改一改还可以。当然了,如果你拿网上生成的 Todo 就别来拿我辩论了,烂大街的代码。原因包含了:
所以,它有时在代码上还是瞎编。
诸如于我创建 ClickPrompt ,都是在尝试管理 prompt 工作流,以便于:
在提升效率上,ChatGPT 确实做得很好,每个人都应该去尝试一下。
最后,再让我们尝试做一些思考。
所以,如同 AI 提炼了我的观点,AI 编程存在一定的局限性:
而你发现没有,New Bing 提炼出来的这些局限性,并不是 AI 的问题,而是人的问题。
我们还得考虑的一点是:
尽管,提供更详尽的 prompt 可以帮助 AI 更准确地理解需求,并且避免一些歧义或误解。但是,过于复杂或冗长的 prompt 也可能导致 AI 的困惑或失效。
所以,如何根据 AI 的特点和目标,选择合适的 prompt 长度和格式,以达到最佳的效果?
当涉及到由AI生成的代码时,有时候我们可能需要对其进行审查以确保其合规。而人工是耗时费力的,而且容易出错。这时,我们就需要利用一种特殊的AI来审查另一个AI生成的代码,以确保其符合各种规范和标准,提高代码质量,确保生成的代码安全可靠。
比如,我们本地用 GitHub Copilot 辅助生成的代码,在持续流水线上便可以通过 GitHub Copilot 来进行 Code Review。
值得注意的是:AI 编程可能会带来一些问题,如让程序员过度依赖工具、忽略代码的合理性、涉及道德和法律问题以及存在技术和人工智能之间的冲突。