最近我在四川稻城的一个商业远程天文台租了一个机位,用于天文摄影。商业远程天文台是指一个企业在无光污染的地方租地,提供稳定的电源和维护服务。天文爱好者将自己的设备寄过去,由公司托管。用户可以远程控制自己的设备进行摄影。天文台的基本结构是顶部可移动的大房子,白天关闭(关顶),晚上打开(开顶)以进行摄影。和国内的很多其他远程台一样,这个天文台的主要沟通方式是通过微信群。我在群里潜水一段时间后发现,很多讨论都是关于天文台有没有开顶,是不是起云了等状态咨询。这些问题占用了台长很多时间。此外,台长的另一个重要职责是在房顶打开时@所有人来提醒微信群里的所有台友,但这条信息作为一条普通提醒,往往会淹没在微信群中,导致很多人错过拍摄机会。
作为一个码农,我对这种可以自动化的事情都是很感兴趣的。为什么我们不实现一个AI系统来解析监控画面,自动回答这些问题,甚至主动提醒用户天文台已经开顶了呢?对于一个有经验的工程师来说,构建这个系统并不特别困难。经过一番思考之后我们可以意识到,如图一所示,这个系统可以分为四个主要模块。在远程天文台,可以部署一个监控端,它利用相机的SDK读取天文相机的监控画面。这个监控画面一方面会被发送到服务器端进行分析和存储传输,另一方面,在经过采样和标注后,会用于构建AI模型的训练和测试数据集。这个数据集将在我们自己的GPU集群上进行训练,以得到一个优化后的神经网络模型,并部署到服务器端。在服务器端,我们运行一个FastAPI应用层来执行三个主要任务:第一,存储和转发监控端传来的图像,以便移动客户端可以查看;第二,使用之前训练好的神经网络对监控图像进行分析,判断是否开顶;第三,与移动客户端和苹果推送服务通信,实现开顶的推送通知服务。
图一. 系统基本架构
这样的服务既不算难,也不算简单,因为它涉及到使用不同技术栈来设计、实现和维护四个在不同位置运行的模块。一个现实的估计是可能需要三四个人(MLE,后端,iOS)用一两天的时间全职开发来完成这个项目。但我想分享的是,最近我确实实现了这个项目。并且在AI的帮助下,我作为一个熟手MLE,半吊子后端,和完全的iOS新手,只用了八个小时就完成了一个完整的工程系统。在这个过程中,我还遵循了良好的工程实践,比如编写单元测试、提供完备的文档,并且通过了苹果的TestFlight平台的审核,让台里的群友们都能使用(界面如图二所示)。即使到半年前我都无法想象这样的效率,但在2023年AI技术的发展下,八小时内完成过去一个团队几天的所有工作变得相当现实。在这篇文章中,我会首先介绍我是如何使用不同的AI技术来构建不同模块的,以及我在利用AI高效完成软件工程开发任务方面的一些心得体会。
图二. 系统示例界面
整个项目构建的过程可以分为两个阶段。第一个阶段主要是人工完成的,包括几个关键步骤。首先是进行opportunity sizing,评估项目的可行性和潜在收益,确保所投入的时间能够为远程台公司或台友用户带来足够的回报。这个决策非常重要,甚至可能比技术细节更为关键。如果估计错误,可能会导致工作量大大超出预期,就像预想的闪电战变成了陷入莫斯科的冬天一样,这种误判的损失远大于代码优化不当的损失。目前AI还无法帮助做出这样的决策或为人类背锅。
第二步是设计架构。我尝试过使用AI来设计一个基本框架,但发现AI虽然能提供一些正确的方案,却缺乏深刻的见解。它就像一个知识渊博的小实习生,记忆力好,但在需要提供深刻见解或启发思考时表现不佳。因此,对于具体的模块规划,我们还是必须依靠人工制定。不过,AI可以在这个过程中提供文书辅助,例如使用口述重整工具快速得到整洁的文档。尽管如此,框架图还是需要人工制作。有了框架图和文档,无论是沟通还是未来回顾项目,都非常有帮助。
第三步是选择技术栈。这一选择非常个性化,因为每个人对不同技术的熟悉程度不同。目前AI还不能代替人类进行这一步骤。但如果将来有一个AI,它了解你的所有信息,包括历史和偏好,那么它或许能在这一步替代人类帮助我们完成工作。
在完成了三项关键决策之后,项目的具体编码和实现主要是由AI来完成的,这一点在五个方面尤为明显。首先,对于监控端,尽管我已经有了可以复用的现成代码,我还是尝试使用AI来编写代码,并且取得了很好的效果。具体来说,我使用的是ZWO的天文相机,它的一个优点是提供了基于Python的SDK,可以用Python直接控制相机的多项功能,如自动白平衡、自动曝光和读取RAW格式等。我所做的就是将这个API的Python接口和示例作为提示输入给GPT-4 Turbo,询问如何实现一个Python后台服务,以连接相机,调整自动平衡和自动曝光,接着每30秒读取一帧RAW格式的图像,并以特定的命名方式保存到硬盘的某个文件夹。尽管这个prompt很长,因为贴进去的SDK Python代码可能有七八百行,但GPT-4 Turbo的上下文窗口很大,它轻松处理了整个提示,并给出了很好的结果。它生成的代码与我手头的代码非常相似,我很快就让它运行起来了。
第二,对于服务器端,我完全依赖GPT来编写代码。我使用明确的prompt告诉它需要使用fast API来实现特定的功能,它接下来就能根据我们的提示写出框架。在此基础上,我使用了Github的Copilot来微调一些功能。例如,我的数据库使用的是MongoDB,GPT假设这个MongoDB没有密码,但我不希望用户信息暴露在互联网服务器上。因此,我还是需要修改一些连接字符串和其他细节。当然,MongoDB的配置工作也是在GPT的指导下完成的,我所做的只是询问如何添加密码,并将其指令在命令行中复制粘贴执行。
第三,对于神经网络的训练,我选择了EfficientNet架构。并且因为我对PyTorch非常熟悉,我使用了非常详细的Prompt指导AI编写了数据加载、训练和测试的代码。我还使用TensorBoard来监控模型的训练过程,并进行超参数的调整。得益于详细的Prompt,AI很快就编写出了高质量的代码。在Copilot的协助下,我只需做了微小的修改,就能在我的GPU机器上运行程序,并成功导出了模型文件和部署代码。
第四,至于iOS客户端,这是我较弱的一环,而且大部分时间也都花在了这上面。我的代码几乎全部是从GPT抄来的,尤其是SwiftUI的实现,基本上复制粘贴后就能直接使用。有时会有一些语法或运行时错误,这时候只要把错误信息贴到GPT里面,两三轮以后也基本可以解决。有个硬骨头是推送通知在iOS中的实现特别复杂,因为它涉及到向苹果申请证书,然后使用OpenSSL命令行将其转换为Python库能读取的格式,最后在FastAPI中使用Python库与苹果的推送服务器通信,触发推送通知。GPT详细地指导了我整个过程,包括申请和转换证书,还帮我写了触发通知的代码。我最初没有意识到开发阶段和产品阶段所需证书的不同,导致用户最初无法收到推送通知。但在询问GPT后,它准确地指出了问题所在,并帮我申请了正确的证书和更新代码。
第五,作为一个码农,我明显没有图像设计方面的天赋。每次提交app时,最让我头疼的一步是设计logo或者app图标。为了解决这个问题,我使用了Mid Journey来进行设计。但问题是,我因为没有相关经验,也不擅长编写mid journey的prompt。最终,我写了一个基于GPT的bot,它可以根据用户的简单指令生成适合Mid Journey的prompt。在这个GPT bot的帮助下,我成功生成了如图三所示的app图标。可以看到,它非常专业,我觉得这样的app图标如果在淘宝上定制,可能要花费几百到上千元。此外,包括这篇文章在内,也是我口述后使用GPT重整语言完成的。它在各种文书和艺术方面为我节省了大量时间,让不可能变成了可能。
图三. app的图标。海豚是南方天文的吉祥物,狐狸是因为这个远程台旁边有个狐狸老来找吃的。
在整个开发过程中,我的代码都有详尽的注释。这主要是因为,第一AI生成的代码都带有详尽的注释和DocStrings;第二为了让Copilot生成准确的代码,我会先写注释,然后依赖它的自动补全功能来完成代码;第三,Copilot还帮我方便地自动生成了DocStrings。此外,AI还帮我快速生成了一些复杂的单元测试,并真正帮我发现了一个bug。由于AI帮我完成了许多繁重的工作,我能够将更多精力投入到最佳的软件工程实践中,加速了开发进程,减少了走弯路的时间成本。
总的来说,当前的AI技术已经能够显著加速软件工程的开发速度,效率提升了数倍,而且效率提升的幅度与工程师的能力成正比。不同用户利用AI的方式确实各不相同。首先,对于小白用户,即那些没有任何基础的人来说,AI可以作为一个个性化的学习工具。这个“老师”非常耐心和博学,能够理解复杂的问题并提供适当的解决方案。但是,如果用户没有任何编程基础或者基础非常薄弱,即使在AI的帮助下,他们也很难达到实际构建一个软件工程产品的水平。其次,对于有一定基础的用户,比如那些会编程但不懂Swift的人,他们从AI中得到的回报最大,往往能够实现以前无法达到的从零到一的工程构建。这主要是因为在现有的工作框架上修改代码比从头编写代码要容易,而且在AI的帮助下,我们还能有余力去践行更好的软件工程实践。最后,对于高手来说,他们对各种技术细节都非常熟悉,可以将繁琐的编码工作交给AI。就像我们之前提到的模型训练一样,通过非常具体的提示,AI能够生成非常接近成品的代码。而我们人类则可以专注于需求分析和架构设计,这样我们就能将精力和创造力集中在最关键的地方,从而在软件开发方面走得更远。
总的来说,目前AI还无法取代人类,但它是一个倍增器,能够显著提升人的工作效率。我觉得这一轮AI和蒸汽革命,电力革命大体上是可以相提并论的。我们可以预见,在未来,低端软件开发工作可能会被AI取代,就像纯体力劳动被电动机和蒸汽机取代一样。那些能够利用蒸汽和电力的人,他们的工作效率会成倍提升,甚至可能实现阶级跃升。
具体来说,我们应该如何使用AI呢?我的建议是:首先,要理解AI的功能限制和能力边界,知道何时该使用它,何时不该使用它。例如,目前我们不能期望把这篇文章扔给AI,然后它立刻就能输出完美无Bug能运行的整个项目代码。其次,在决定使用AI时,要能够提出正确的问题。换句话说,我们可以将更多精力放在提出正确的问题上,尤其是当我们知道这个问题完全在AI的能力范围内时,就不必再花费大量精力去做底层的思维工作,比如将想法翻译成代码。第三,我们在整个过程中需要避免过度依赖AI,因为目前的AI仍在快速发展,可能存在各种偏见。就像过度使用抖音可能会陷入信息茧房一样,过度依赖AI可能会让我们陷入思维定势,这对于在这个快速发展的领域中生存是不利的。第四,我们应该针对AI优化我们的开发和产品流程。例如,以前构建软件开发库时,通常只需要为人类编写一套详尽的文档。但现在,如果我们想让AI更有效地帮助人类使用这个库编程,我们可能需要为AI准备另一套文档,比如OpenAPI Specification或者是更适应AI有限的上下文窗口的精简版本。对于用户而言,我们的软件开发流程当然也可以针对AI进行优化和简化。
这是一个令人激动不已的时代。以前,如果说能在8小时内完成上面说的整个项目,我甚至不敢想象,但现在这已经成为现实。我对所有读者的建议是,请立刻学习如何使用AI。我们正处在一个类似蒸汽或电力革命的十字路口。使用AI就能立即实现效率的数倍提升,对那些不懂AI的人形成压倒性的优势。
Comments