前言
时至今日,要说什么行业最火,还得是 AI, 自 GPT3.5 破圈进入大众视野,隔三差五就会有朋友问,AI 出来了,你是不是要被取代了。
甚至有一些程序员朋友们在问我。
吓得我连夜开通开通 GPT, 一用,整个人被吓到
- 这玩意还能读懂我的意图?
- 这玩意还能写代码?甚至能我没有完全描述好这个功能都能考虑到
- 写出来的代码改改就能用?
甚至在 GPT4 刚出没多久的时候,我一度产生了这种想法,这玩意是不是要取代我了?
当然,随着使用 GPT4 次数越来越多,对 GPT 也开始祛魅。要问 AI 能不能取代程序员,截止 2024 年 7 月,我的结论是:单纯从技术角度,GPT 是个好帮手,很难取代程序员。
但程序员会不会因此失业,这点却很难说。
不过,正如大家所说的 AI 不一定会取代程序员,但一定会取代不懂 AI 的程序员。
用到的工具
- lobechat 主要以 Claude 3.5 Sonnet 为主
- perplexity.ai (背后是 GPT4 / Claude 3.5 Sonnet)
- GitHub Copilot
AI 提升编程体验
在以下领域,AI 辅助编程表现出色:
- 资料搜索 查找解决方案,查找 API, 编写 POC,
- 开发规划 保持术语一致性和清晰性,定义文档规范
- 代码生成 代码补全,根据注释或要求生成代码,自动补全函数名
- 代码重构 代码合并、拆分、优化
- 文本转换 代码转换
- 质量保证 代码审查和测试用例
还需要补充两点
- 现阶段的 AI 大模型更像是对真实世界的一个压缩,这意味着无法解决前人没有解决的问题。如果你要解决的问题比较冷门,得到答案的概率会很低。 从编程角度,AI 给我带来了什么之前做不到但现在能做到的事情?很少,但以前需要进行大量调研的东西。可能问问 AI 瞬间就有一定几率瞬间解决了。
- AI 的发挥并不稳定,虽有时妙棋,但不乏臭手,对结果务必要进行人工检查
资料搜索
案例
以前,在没有 AI 辅助的情况下,我想使用 python + opencv 将 N 张图片拼接到一起做成一个全景图,我可能会有如下的操作
- 猜测这个问题可能是常见问题,搜索一下 Google, 「python opencv 全景图」
- 找博客/StackOverflow,阅读代码看看是否满足需求。如果不满足需求要求,则继续搜索,比如修改搜索词「python opencv panorama」。
- 找 opencv-python 的 github 仓库,看看 example 是否包含有类似的代码,如果还不满足需求,则看看其他相关仓库。
- 发现 opencv 用起来比较复杂,从微信读书之类的 app 上找本关于 opencv 相关的书籍扫盲。
- 拼接代码进行调试。
而现在,我只需问 AI (Claude 3.5 Sonnet)
我使用云台相机拍摄了 9 图,每张图的边缘可能和其他图有一定交集。
请使用 python + opencv 帮我拼接这九张图成为一张全景图
甚至更进一步
我使用云台相机拍摄了 10 图,其中一张图是总体的图,剩余九张图是局部更加高清的图
请使用 python + opencv 帮我堆叠这九张图到总体图上
于是,你得到了可以快速运行的代码,
import cv2
import numpy as np
import glob
def load_images(folder_path):
"""加载指定文件夹中的所有图片"""
image_files = glob.glob(folder_path + '/*.jpg') # 假设图片是 jpg 格式
images = {}
for file in image_files:
img = cv2.imread(file)
if img is not None:
images[file.split('/')[-1]] = img
return images
def find_homography(img1, img2):
"""找到两张图片之间的单应性矩阵"""
# 初始化 SIFT 检测器
sift = cv2.SIFT_create()
# 找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# FLANN 参数
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# 存储好的匹配点
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
if len(good) > 10:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
return M
return None
def stack_images(base_img, detail_imgs):
"""将局部高清图堆叠到总体图上"""
result = base_img.copy()
for img in detail_imgs:
# 找到单应性矩阵
M = find_homography(img, base_img)
if M is not None:
# 对局部图进行透视变换
h, w = base_img.shape[:2]
warped = cv2.warpPerspective(img, M, (w, h))
# 创建 mask
gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
# 将 warped 图像复制到 result 上
result = cv2.copyTo(warped, mask, result)
return result
# 主程序
if __name__ == "__main__":
folder_path = "path/to/your/image/folder" # 替换为你的图片文件夹路径
images = load_images(folder_path)
if len(images) < 10:
print("图片数量不足")
else:
# 假设总体图的文件名为 "overall.jpg"
base_img = images.pop("overall.jpg")
detail_imgs = list(images.values())
# 堆叠图片
result = stack_images(base_img, detail_imgs)
# 保存结果
cv2.imwrite("stacked_result.jpg", result)
print("堆叠后的图片已保存为 stacked_result.jpg")
# 显示结果
cv2.imshow("Stacked Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
甚至他会很贴心的告诉你「**这个方法假设局部图和总体图之间只有透视变换的差异。如果有其他类型的变形(如旋转、缩放),可能需要更复杂的配准方法 **。」
通过一番搜索,你可能也能找到答案。但在 AI 的加持下,你的效率可能远超你的预期。
只言片语,就能得到答案。
建议
当你检索一些常见的库、依赖或编程语言的基础知识时,预先查一下往往会有奇效。比如:
如果你熟悉 JS,但是此时此刻你得用 Swift UI 写一点代码,你可以问
- swiftui 有没有 类似 js 的 a || "" 的写法
- swift 有没有 optional chaining 的语法
如果你用 rust,但是想问问其他语言/框架中的 api,你可以
- rust 中是否有类似 python opencv 的 drawContour 方法?
- rust 中处理图像的常见库有哪些?
如果你熟悉中文的说法,但是不晓得英文应该怎么问。
- 比如,我知道「划词翻译」这个功能,但是划词翻译所需 API 你让我翻译,可能我会翻译成 draw word translate api。但你直接问 GPT「如果用 mac 实现划词翻译,需要使用哪些 api」基本就能得到答案
- 对于一些较为系统的教程或者较长的代码,LLM 并不能很好的回答。使用 Copilot Chat / ChatGPT 来提供有用的搜索词,然后查阅 Google 搜索结果中的教程和帖子以获得更全面和详细的信息。
开发规划
假设咱做的是一个 Full Stack 的项目,开发规划发生在正式编码前,把业务梳理清楚后,围绕着核心业务开始建模。
我个人的习惯是从核心业务流程开始逐步梳理出数据库表和表字段,后端组件,然后设计 API 和前端页面。
在这个阶段,可以对 AI 反复追问。
- 「购物车 checkout 的数据库字段应该怎么设计会好点?」接着追问「在这个基础上,如何处理退款?」
- 「我现在的数据库表是这样的,你觉得我在此基础上还要满足需求 1/2/3」应该怎么做呢?
- 「像是以图搜图的方案一般有哪些开源替代?」接着依据回答追问「Milvus 以图搜图怎么实现?」
- 「rest 下单接口叫什么比较好?」
- 你可能会得到很多个备选项,POST /orders,POST /checkout,POST /cart/checkout,POST /purchase
通过反复追问,可以陆陆续续确定后端的技术选型/数据库 Schema/接口/服务层/前端路由/前端组件/业务模型的命名。
命名,命名,还是命名
命名的一致性和清晰性对于项目的可维护性和可读性至关重要。
毕竟正如 Phil Karlton 说过:There are only two hard things in Computer Science: cache invalidation and naming things. 即「 缓存失效和命名是计算机科学中最难的两件事」。
代码生成
令程序员最兴奋的环节,就是代码生成。
我这里举一个不是很合适的例子,生成注册页面和登录页面
案例 - 注册页和登录页
使用如下 Prompt
帮我生成登录页面和注册页面,以下是我的技术栈 react react-hook-form zod typescript
Note: 依赖库的 API 可能会过时,但使用 TypeScript 进行类型检查可以极大地降低修改的成本。当然,登录和注册页面的功能远非如此,但这个草稿可以作为一个简单的起点 当我询问依赖库比较老如何解决时,ChatGPT 给了我一些通用的代码修复建议,例如检查语法和检查依赖库是否过期不兼容。但是 Copilot Chat 却给了我另一个过时的版本,所以最终我使用了 Google 并过滤了最近一年的文章来解决这个问题。
使用了 Tailwind CSS 对登录页面进行了优化。在 Copilot 中由于返回结果过长,被过滤掉了,因此转而使用 ChatGPT 进行了优化,现在页面看起来虽然也就那样,但好歹能看了。(不过这明显不如直接套模板了 ahhh)
接着输入生成的代码,并且让代码仿写一个注册页面,要求添加输入密码变化时的校验功能。
为什么说不合适呢?
因为这里只是为了演示代码生成的功能,但真实开发环境中,大家都是套模板/使用 figma 编写注册/登录页。
案例 - 脚本转译
之前写个爬虫,从 github 找到一个百来行的 php 爬虫。我有如下选择。
- 翻阅 php 语法,调试一下。耗时 30min+(不包含环境配置)
- 自己写。耗时 1h+.
- 人肉转译。耗时 30min+.
最后,我把 php 代码投喂给 GPT3.5, 让他转译为 python。改几行代码,调试完毕。
代码补全 TODO
NOTE: 本小节使用 Copilot
记得刚写代码的时候,听过这么一句话
程序员最讨厌的两种人,一种是不写注释的人,另一种是要求自己写注释的人。
但 copilot 让我确实没有那么讨厌写注释了。
- def 名称
- #注释
- #终于,爱上了写注释
- 镜头,二指禅
代码重构
精简代码
- 前端 html 优化「请帮我合并掉多余的 div」
- 请帮我重写这个函数,让它更简洁
合并逻辑
程序员有一个习惯,就是复制一份代码然后自己修改。这样做的好处是,不会破坏原有的代码,但是也会导致代码重复。这时候,可以使用 GPT 来合并代码逻辑。
以聊天窗口的发送消息和接收消息为例。先调试发送消息的样式/TSX,然后复制一份调试接收消息的样式/TSX。调试完毕后,把两段代码丢给 GPT, 让 GPT 合并起来。这样在修改 receive 的样式的时候并不会有搞坏 send 样式的心智负担,只需要专注 receive 的调试,调试完毕一合并,节约了不少琐碎的时间。
样式可以这么合并,业务逻辑也可以?🧐
拆分逻辑
随着发送消息和接收消息的组件/逻辑越来越复杂,将两者合二为一的做法可能会导致代码难以维护。这时候,可以使用 GPT 将对应的代码分开。
适配版本升级
有的时候第三方库写法变了,我们的代码也要跟着变。 例如,Pinia 升级 composition 写法,需要咱手动讲 option 写法转为 setup 写法。
但有 GPT 的情况下,提交代码并提供简单示例,就能省去不少繁琐的文本编辑成本。逗号/对象属性函数转换为闭包函数/this/ref 语法。( 别忘测试)
又比如:Vue 模板语法 批量转成 tsx 语法。
但请注意:转换并非银弹,LLM 有的时候会丢东西。比如这个场景下,针对 if/click/slot 的转换效果良好,但对于 class 属性可能存在重复情况,而对于 ref 属性可能会漏掉 value。(当然,升级大模型版本会一定程度上缓解这种状况,比如升级到 gpt4o / Claude 3.5 sonnet )
文本转换
文本转换指的是一种格式的文本转换为另一种格式的文本。这种转换通常涉及到一些规则和模式的匹配,而 AI 可以帮助我们更快地完成这种转换。
Python 代码格式化
迁移笔记中的代码时经常会出现换行丢失的情况。对于像 Python 这样没有语法的语言 (插一张图,吐槽 Python 没有括号) ,手动断行来恢复原来的代码格式非常烦人。投给 GPT 格式化大大提高效率。 当然,其他语言也是可以格式化的。python 只是难度较大罢了。
import cv2 import numpy as np import glob def load_images(folder_path): """加载指定文件夹中的所有图片""" image_files = glob.glob(folder_path + '/*.jpg') # 假设图片是 jpg 格式 images = {} for file in image_files: img = cv2.imread(file) if img is not None: images[file.split('/')[-1]] = img return images def find_homography(img1, img2): """找到两张图片之间的单应性矩阵""" # 初始化 SIFT 检测器 sift = cv2.SIFT_create() # 找到关键点和描述符 kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) # FLANN 参数 FLANN_INDEX_KDTREE = 1 index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1, des2, k=2) # 存储好的匹配点 good = [] for m, n in matches: if m.distance < 0.7 * n.distance: good.append(m) if len(good) > 10: src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) return M return None
提取信息
片段代码重构加速,如何左侧变为右侧?
"@iconify-json/heroicons": "^1.1.21",
"@iconify-json/simple-icons": "^1.1.106",
"@nuxt/content": "^2.13.0",
"@nuxt/fonts": "^0.7.0",
"@nuxt/image": "^1.7.0",
"@nuxt/kit": "^3.12.2",
"@nuxt/ui-pro": "^1.3.0",
"@vueuse/nuxt": "^10.11.0",
"nuxt-og-image": "^2.2.6"
"@nuxt/eslint": "^0.3.13",
"@nuxthq/studio": "^2.0.1",
"eslint": "^9.5.0",
"nuxt": "^3.12.2",
"vue-tsc": "^2.0.22"
- 人工直接编辑
- 使用支持正则表达式的编辑器,输入命令后补充编辑
用 GPT 来提取代码中的关键信息并且生成你需要的对应代码。而且可以对输出格式做一些要求。
- 帮我从如下的 html 代码中提取 title,descripiton,tags 转成变量,并且提供对应的 vue 模板。
Schema 翻译
django.model 转 json/pydantic model json 转 swiftui view model/typescript model
- model / schema
- sqlachemy model
- django model
- sql table
- create update
- pydantic
- zod / pojo
- vue / react
翻译 - 转另一个
- vue tsx 转 react tsx
- python 逻辑转 golang
- 多语言支持
- PR 帮助
质量保证
检查代码
较短的但存在 bug 的函数,如果一眼看不出问题,可以尝试丢给 GPT-4, 刚修复了一个 Swift 的并发 Bug.....****
Code Review
- 通过代码猜测功能
测试用例生成
- 仿格式生成格式
- 测试数据生成
其他
如果你不知道需要看什么书,你先写两本相同类型的书,接着 Copilot 就会给你补全推荐其他的书籍。🤣
- https://x.com/hylarucoder/status/1752665100488774062
- https://x.com/hylarucoder/status/1740384021451014176
- 如果你使用 SwiftUI 等较为冷门的开发技术,发现 Copilot 和 GPT-3.5 在生成 View/ViewModel/Model 时提供了可用代码,但实现如 macOS 上的拖拽功能则难以实现,使用 JS/TS 则可以快速获取可用代码。所以,在训练语料不够的情况下(GPT 21 年数据对 22 年没有太多), AI 可能并不能帮助你。
一些不足
- 生成的代码依旧需要人工检查
- Swift 代码可能由于网上公开资料
大模型更像是所有世界
语料不足
在使用 AI 辅助编程的时候,也发现了
常有金句爆出,但输出不是很稳定。
- 不同的 LLM 和 LLM 升级之后
- prompt engineering
结尾
- 老婆,你说以后生娃的话,我写个程序,给小孩子起名好不好。
- 操 (哔), 这东西你都要 AI 来做,你怎么不和 AI 过日子去啊
一次性脚本
- 估计
- 批量命名