然后简单介绍一下项目的技术选择吧,当然这也是和 AI
讨论出来的。首先,Typescript 肯定优于
JavaScipt;其次,由于这是一个接近静态网页的 Web
App,我们希望框架框架尽可能的轻量。然而,它并不是一个静态网页,这是因为我们希望获得愉悦的、GUI
的编辑体验,如果为了添加一条评测,我必须要开启
VSCode,撰写条目,打包,然后上传,那门槛就根本没有降下来。所以,首先我们需要一个非常轻量的网页,使用
Astro 作为框架,因为
“它是最适合构建像博客、营销网站、电子商务网站这样的以内容驱动的网站的
Web 框架”,并且在数据库上也选择
Sqlite。然后我们需要一个非常简单的后端 GUI 交互,基于 Electron
以避免引入 Python 或者其他什么语言和库。后台使用 SSH
和服务器通信,避免复杂的鉴权问题。
所以,总结一下这个项目需要完成以下任务:
下面我们来讲其中的问题吧。
问题一: AI
无法准确的处理前端
有一种奇怪的论调是,AI
最先取代的是前端,因为后端有很多复杂的数据关系设计,但是前端只是一个看上去很漂亮的样式就可以了。诚然,如果你只是想要一个还凑合的页面,那可能确实还可以。但是如果你有一些比较精细化的需求,那你会发现
AI
非常难以实现你的目标。甚至可能比后端处理还要麻烦些。因为对于后端而言,一个数据经过处理后如何鉴定正确与否,相对是容易知道的,测试非常的好写。但是前端如果实现不及预期,或者
AI 在实现 Feat B 时破坏了 Feat A 的实现,那你很难通过一个 test 来约束
AI。
这又点像是写作、数学的区别。尽管许多人宣称“AI
首先击败了文科生”,但事实是,直到今天,AI
都不能够写出很美丽的句子。它只能“稳稳的接住你”。如果你的需求只是让 AI
表达出你想表达的意思,那今天的 AI 干得很好。但是如果你希望 AI
能遵从你的风格,使用一些恰当的示例,或者锤炼一些词句,那这个过程就会变得困难重重。你会发现
AI
总是有它自己的想法,它总是会不遵从你的指令,而你没有任何办法去检测这种不遵从,你唯一的办法就是自己读一遍,然后仔细思考如何更改组织结构和格式。
AI 如今在前端领域也是类似的。我其实亲眼见到过不少同学在他们的
presentation 中直接使用 AI 生成的前端或
PPT。但是具体到我们这个项目而言,我还是有一定审美追求的。正如我不可能将上述那个
Readme 直接
publish。而且我们已经有朋友的图片作为参考了,所以我们更不可能端出来一个丑陋的东西出来。
我一开始的做法非常的简单,既然 GPT
有多模态,那么我直接让他读取图片,然后使用代码修改不就好了?我建了一个空仓库,然后让
CODEX5.4 (当时还没有
5.5)去阅读图片,然后制作一个生成器,要求是我可以传进去 JSON
文件,然后它输出卡片给我,结果几乎是完全不可用的。尽管它可以识别得出来图片中的主要元素:分数、标题、优点和缺点、红色和黑色的字体……但是它几乎没有办法正确处理那些细节,例如背景图片的高斯模糊,例如图片比例,如
LOGO 的左边距,文字是否居中等等。当然可以理解 AI
无法猜测对齐方式,但是毫无排版也是事实。
所以我最后采用了另一种方案解决问题,首先,我除了朋友提供的原图,还自己画了一个草稿解释卡片的布局。
图 2
然后要求 AI 只使用 HTML 完成一个最简产品 MVP。我再结合阅读 HTML
源码,实际告诉它缺少了什么元素,或者什么元素存在问题。最后当完成一个可以的卡片的样式以后,再要求它根据这个式样去实现整个项目。如果我不这样做的话,整个工作就会被多个地方卡住:首先,我脑子里的思路能否真的转化成准确而又严谨的文字描述(还好,我们这个项目有朋友的图片直接作为参考)?其二,我的
prompt 是否被 AI 正确理解并实现?其三,AI
的实现出现了问题,如何定位并修改?通过使用
MVP,我们可以避免具体业务逻辑的干扰,减轻前两个问题的压力;通过阅读 HTML
源码,则可以直接辅助 AI 定位问题,是 xx 元素出了问题,而不用靠 AI
猜或者通过“左下角的那个元素”这种含混不清的表达来指代。
API KEY
是用于封面搜索的,但是没有放到和封面相关的部分。反而是将预览和同步塞了过来。并且作为一个很小的,只用配置一次的项,占用了过大版面。
标题没有居中,并将选择项目目录和当前项目目录放在同一个地方。
尽管图片上看不出来,但是 AI 甚至遗漏了删除功能。
也许有人会说这个不叫 AI 做不好
UX。预览大一点还是小一点。这些东西根本没所谓。或者说,在没有给出一个明确的标准之前,AI
本来就只能给出平庸的设计。这种说法我是不能苟同的。我们今天回望 Gen AI
的初期,我们会发现人们在学习各种提示词工程,例如要给 AI 附上示例啦,要
AI 扮演专家啦等等。今天的 AI 或者说 Agent
几乎不需要这样做,通过提高模型智能称呼和 Context Engineering 或者
Harness Engineering 一类的东西,AI
就可以默认给你出一个还不错的水平。而对于这个项目来说,如果我必须要自己一步步设计好
UX,或者在创建后台之后一步步修改 UX,其实是很消耗精力的,你必须退回到
prompt engineering 的时代,逐条列出 AI
的错误,以及如何修改。首先,对与人来说,这就是在设计 UI
的同时还需要顾虑到现有代码做文章,同时,还必须检查 UX
的可用性,不然就总是会在处理其他问题的时候,被打断(例如这里的遗漏删除功能的问题)。其次,对于
AI
来说,它们总是倾向于将已有代码视为既成事实,从而在修改的过程中屎上加屎。写成类似这样的代码:
1 2 3 4 5 6 7 8 9
# before(bad design) a= b c= d # after if enable_ something: a= b c= d else: do_ something_ else()
这里面的每一步 AI 都可以犯错,项目可能实现不正确,DockerFile
可能逻辑不正确,然后 Proxy 或者其他配套使用的
App……每一个都在增加犯错的可能性。要知道,要是部署这些东西本身没有那么多繁杂又细节的操作,也就不会出现“在我电脑上能跑呀”这种哏、或者
CI/CD、Infrastructure Technician 这类术语了。
AI 在处理这个问题上的时候有两种模式。第一种模式是 AI 修
Bug,我执行。这种相对来说会更安全一些(并不太多,因为秉持 VibeCoding
的精神,我几乎不做任何检查)。我会要求 AI
它编写出一个完整的结果,并静态检查一遍(“检查代码,确保不包含任何逻辑错误”),然后我们执行代码的过程之中遇到的任何报错,都直接扔给
AI 去修。理论上来说,这是完全的 VibeCoding
实践,但是实践中感受并不好,因为每一次你都会预期它改好了,但是新的问题总是会源源不断的冒出来。从而出现后面会提到的
AI
工作的简短时间片无所事事的问题。更糟糕的是,在部署这一步中,你还需要应对部署安装流程运行时的简短时间片。你不能走开(否则很容易退出专注的心流状态)但是你也不能做点什么,你已经把所有的工作让渡给
AI 了。有的时候,有些工作你还必须手动处理,因为你没有告诉 AI
相关的上下文。例如你开着代理呢。那你就得自己独立去猜和解决问题,或者再开个网页问问
chat?无论如何,你是在处理既充满重复性又充满不确定性的工作。
当然是有办法解决上述模式的问题的,那就是第二种模式,完全让渡给
AI,要求 AI
全权处理,我们给它通过验证。这种时候就又有几个问题,第一是隐私问题。我们很可能得让渡一些原本不打算让
AI 知道的信息。例如我们真实文字产出、服务器 IP
地址、个人姓名等;其次还有安全问题,我们得允许 AI
执行一些本来在沙箱内不应该能执行的工作,这其中的极端情况甚至包括直接让
AI
与服务器交互!最后,正如上一节所述,在部署的时候,为了稳定可靠地解决某个原因众多的报错,它很有可能会产生一些防御性的代码,从而直接破坏我们在项目的开发过程中一直追求的那种可持续性,更进一步地阻碍人类去阅读,甚至可以说阻碍
AI
去阅读,因为用众多的防御性编程掩盖了真实的生产环境中具体哪一个真正生效,那么后续的
AI 也没有办法检查问题出现在哪。这个问题不是靠提高 AI 的 context
能力能解决的,因为总有一些东西是 AI
无法掌控的,我们也无法掌握的,也就谈不上告诉
AI,这种时候他就需要去猜,然后一步一步的试,然后改正。如果某步试了没有效果,就很容易被被保留形成屎山甚至引入新问题。如果删除呢,又有可能改乱(这时就体现出版本管理的重要性了)。
有人此时可能会说,既然如此,那我们在这段时间去阅读代码,了解具体项目情况不就好了吗。首先,无论你在读什么,你都是在看和刚才的问题没啥相关性的东西;其次,阅读是随时会被中断的,这给人的感觉是非常不好,因为你在在做无用功,你既没有收获快乐,也没有收获认知;此外,你也只能阅读,不能修改或调试,以免发生文件权限冲突或者修改冲突之类的,这就更进一步限制了阅读代码的便利性。还有,由于
VibeCoding
本身确实是快速迭代的,你现在一个小时改的代码可能比以前一天都多,那阅读特定的代码的实用性也就下降了,因为很有可能之后就会因为添加或修改需求,让
AI 把整个逻辑重写。
问题五:我对这个项目一无所知
最后,这个项目开发完了,然后呢?我对它的了解并不比其他任何外人更多。是,是我指定的
Docker,是我指定的 pnpm,是我同意的 Astro
框架……但是也就仅此而已了。我没有对其中的任何细节有深入了解。所以我后期想要调试,二次开发,我仍然得要依赖
VibeCoding,或者花大功夫去把代码读通,然后去做修改。这个过程我必要要忍受
AI 的 trash,包括过度封装、过度防御性编程、遗留代码,以及真正的
bug。总的来说,我该付出的工作一点没少,但是我做出了点什么东西的成就感反倒是被大大稀释了。
总结
所以总的来说,VibeCoding
当然不是没有任何好处的,但是它的代价在这个过程中被隐藏了。作为一个程序员,我希望绝对掌控我的程序;作为一个开发者,我希望能持续专注在开发过程中;作为一个“老板”和
PM,我希望能提高工作效率和代码质量;我希望能作为一个人类,我希望保护我的隐私。这些东西都是绝对纯粹的
VibeCoding 无法带给我的,它们是 VibeCoding 哲学的
tradeoff。现阶段来说,和 AI
配合的最好方式,可能仍然是一半一半的开发吧。