把同一句需求分别丢给四个不同的AI模型,可能得到八种写法。这是我在连续两周记vibe-coding日志时印象最深的一件事。所谓vibe-coding,与其说是“靠感觉乱写代码”,不如说是用自然语言给AI下开发指令,让它在描述—反馈—再生成的循环里不断逼近你要的结果。这个词现在几乎和AI编程画了等号,但真正愿意把每天的成败细节摊开记录的人,反而没那么多。这篇日志就是我这两周把vibe-coding塞进SQL生成、前端原型、测试补全和一次完整前后端联调之后,沉淀下来的提示词模板、上下文准备清单,以及从单窗口聊天切换到多AI协作时,真正让项目稳住的那几条工程原则。
1. 先搞明白:vibe-coding到底在替你省哪段功夫
听到vibe-coding这个词,很多人第一反应是“把代码交给AI随便写,我负责验收”,于是争论马上分成两派:一派觉得这是创造力解放,一派觉得这是程序员自废武功。我这两周日志读下来,两派都不完全对。纯靠“随便写”的vibe-coding,在真实项目里根本撑不过两个需求。真正能用的vibe-coding,是把“从模糊想法到第一版草稿”的时间压到十分之一,剩下那九成时间并没有消失,只是转移到了上下文准备、结果验证和边界修正上。
1.1 自然语言替代的是“草稿生成”,不是“方案设计”
记录日志时,我最常做的操作是三类:生成SQL、生成前端组件、补测试用例。以生成SQL为例,传统路线是你想清楚表结构、联表字段、索引和性能边界,然后手写语句。vibe-coding的路线是,你把表结构、业务规则、预期结果直接丢给模型,让它把SQL写出来。这两者的差别在于:模型负责把“描述性语言”转换成“可执行代码”,转换得又快又像样。但模型不会替你回答“这个状态字段应该放在订单表还是订单流水表”,也不该由它回答。一旦需求里藏着这类体系级选择,模型通常会选一个最流行、看起来最合理的方案——但未必适合你的业务。
我日志里有一条特别典型的记录:给一个订单查询接口增加状态筛选。模型很快在筛选条件上加了状态判断,然后当成任务结束。它没有问我状态字段是否存在,也不确认状态枚举值是什么,甚至默认这条记录是物理删除,顺手补了个软删除判断。单看那段代码,语法全对,放到库里一跑,直接报列不存在。原因很简单:当时我给它的上下文里只有接口名和需求描述,没有表结构。这不是模型菜,是我没把最关键的信息交给它。
1.2 分区放权:哪些可以随AI发挥,哪些必须自己拍板
根据日志里踩过的坑,我总结出一个判断方法:在开口之前,先给自己的需求划一条线——哪些是核心逻辑,不允许AI自动脑补;哪些是外围代码,可以放权让它自由发挥。我的分界线大致是这样:
- 放心交给AI:样板代码、数据组装、页面布局、常规增删改查、测试用例初稿。
- 必须攥在自己手里:数据模型、权限边界、事务一致性、系统拆分、升级路径。
- 不要全权交给AI:涉及金额计算、日志脱敏、并发锁、数据库迁移脚本。
这套分法实操下来,AI翻车的概率会直线下降。原因不外乎两个:一是模型擅长生成高概率路线的代码,二是体系级决策一旦交给模型,它只能基于经验统计而不是业务事实来猜。vibe-coding不是不思考,而是学会把思考集中在自己真正有信息优势的地方。想明白这一点,后面所有提示词怎么写、上下文怎么喂、测试怎么卡,就都有了一条主线。
2. 上下文工程:vibe-coding的第一个真实门槛
如果你直接在对话框里写“帮我写一个订单列表页”,大概率会得到一个没什么毛病的模板,但你没法直接用。因为它不知道你的项目叫订单系统,不知道路由写法,不知道字段命名是驼峰还是蛇形,更不知道你用的组件库是哪个。日志里第一个分水岭,就是当我开始给AI喂完整上下文之后,输出质量才从“看起来能用”变成“真的能用”。
2.1 一套能复用的提示词结构
我最终用的提示词结构并不复杂,但有四个部分缺一不可:
背景:我在维护一个订单系统,Python 3.11 + FastAPI,路由文件是 order_router.py。 任务:在 order_query.py 的 get_orders 函数里增加按订单状态筛选的能力。 约束: - 状态枚举定义在 order_status.py,取值是 CREATED、PAID、DELIVERED、COMPLETED、CANCELLED - 不要修改数据库表结构 - 不确定字段名时可以提问,不要自行发明字段 验收标准:筛选结果按 created_at 降序,返回格式与现有接口保持一致把这段和“帮我加个状态筛选”对比,质量差距是断崖式的。背景让模型知道去哪个文件干活;任务明确落点;约束把最容易出问题的命名和表结构提前锁死;验收标准给了它一个明确的“完成定义”。尤其是“不确定字段名时可以提问,不要自行发明字段”这句话,对抑制幻觉特别有效。大模型的错误往往不在语法,而在命名和引用,它把order_state当成status的时候,光靠读代码很难察觉。让它把假设显性化,错误就会少一大半。
2.2 用约定文件替代每次手动贴上下文
手动在提示词里贴上下文,短项目还行,长项目就有两个问题:一是上下文窗口被历史对话占满,二是表结构改了以后,AI还在按旧Schema生成代码。我现在的做法是在项目根目录放三个文件:
ai/context.md:项目结构、技术栈、代码路径、已有约定。ai/schema.md:核心表结构、字段含义、枚举值。ai/todo.md:当前版本目标、已完成任务、下一步计划。
使用时只需要说一句“先读 ai/context.md 和 ai/schema.md,再继续”,很多编码Agent支持自动读文件,这比手动粘贴靠谱得多。另外还有一类方法是靠MCP或者面向代码库的AI工具,让模型自行检索相关文件。日志里我用得最多的是把树状结构和关键函数位置喂给AI,而不是把整个仓库源码全部灌进去。把整库源码丢给模型,经常会在上下文窗口被截断之后,让模型在后面的对话里忘掉前面的约束,这个坑很隐蔽。
2.3 一次只让AI改一个行为
开始的时候我特别贪心,总想一轮对话把页面布局、样式、交互全改到位。实际效果很差:AI经常重写了整块组件,结果新引入三个问题。后来日志里多了一条规则:一轮对话只提一个行为目标。比如“先只改表单校验逻辑”,等这轮通过测试,再开下一轮,“把保存失败的提示加上”。一次一个问题,每个问题可验证,AI的收敛速度反而变快了。这听起来反直觉,因为人会习惯并行处理,但模型在长对话里同时改多个点的时候,很容易改到后面就忘了前面。分批推进这个习惯,直接让我的vibe-coding成功率上了一个台阶。
3. 翻车实录:幻觉、跑偏与无限改版
vibe-coding很爽,但爽完之后炸掉的时刻也不少。我挑三个最典型的坑出来复盘,每一个最后都定位到了根因,并且改成了可复用的规则。
3.1 幻觉字段:根因在上下文,不在运气
还是前面提过的订单筛选案例,我第一次遇到时第一反应是“模型傻了”。冷静下来以后,我把当时喂给它的提示词翻出来看,只有一句“给 get_orders 加状态筛选”。模型没有任何可靠信息能知道状态字段名,只能按常识猜。它猜了status,又顺手补了软删除判断。这个软删除判断就是幻觉的起源。
定位思路其实很简单:先确认上下文是不是完整,再怀疑模型能力。我当时先跑了一条SQL查实际字段:
SELECT column_name FROM information_schema.columns WHERE table_name = 'orders';得到真实字段列表之后,把列清单原样贴回对话,并补充“这张表没有 deleted_at,状态按 order_status 筛选,枚举值是CREATED、PAID、DELIVERED、COMPLETED、CANCELLED”。它重新生成的SQL立刻正确,测试一次通过。这个案例让我总结出一条排查顺序:AI产出的东西一旦不对劲,先回去看提示词里缺了哪些关键信息,再讨论是不是模型能力问题。网上很多人抱怨“AI生成SQL时瞎编字段”,八成根因都是提示词里不给表结构。
3.2 无限改版:长对话会吃光你的可维护性
第二场翻车发生在做一个内部工具前端的时候。我和AI聊了接近700轮,每轮都有一点新需求,它也一直勤勤恳恳地改。但大概到第200轮之后,模型开始“间歇性失忆”:这个版本把一个功能改好了,下一页又退回旧的写法,有些旧需求还被覆盖掉了。到最后代码状态已经不可追踪,我连“它现在到底实现了哪些需求”都说不清楚。
那次我没有继续硬扛,直接推倒重建。新对话里,我把已完成功能逐条固化到ai/todo.md,旧对话只保留含关键决策的片段,其他全部舍弃。这个教训给我定了一条规矩:单条对话超过一定轮数、或涉及多个相互独立的需求时,先把已确认的功能落到代码文件和文档里,然后开启新对话继续,不要让一个聊天窗口无限期活下去。生成物不等于可维护的知识,只有固化到项目文件里的内容,才真正属于项目。
3.3 没有测试的“让它继续改”等于吃回滚焦虑
第三个坑最隐蔽。AI改了一个接口的返回结构,从字符串改成了对象,调用方全都要跟着变。AI很勤快,把每个调用方都同步改了。问题在于,你拿什么确信它没有漏掉某个被字符串拼接的地方?人眼在这种大范围改动里非常不可靠,尤其改动分散在不同文件。
我在日志里给自己加了一条硬规则:任何由AI生成的改动,都要让它同时生成或更新对应的测试。没有测试的改动,必须走一次人工回归环境,否则不允许合并。这个规矩直接让AI的行为发生了变化——它开始主动检查自己的改动范围,而不是改完就收工。测试在这里的作用不只是验证,更是在给AI限定“边界意识”:你的修改是有影响的,影响必须被观察。
4. 从单模型聊天到多AI协作:上限不在模型,在编排
第二周我开始尝试的不再是单个对话框里来回聊,而是把开发任务拆给多个AI角色,让它们协作完成。这从一个角度看是“多AI协作”这个热搜词被验证的过程,从另一个角度看,其实就是把人工团队里的角色分工映射到模型上:规划、编码、审查、测试各司其职。
4.1 为什么单个对话的审查会失灵
单个对话窗口最大的问题,是模型习惯性为自己的输出辩护。你跟它说“这里有bug”,它往往会先解释为什么这样写没问题,而不是立刻去查证。这不怪模型,它的训练目标决定了它倾向于生成连贯的、自洽的答案,而审查恰恰需要一个“外部视角”。人在代码评审时都知道“写的人和审的人最好不是同一个”,AI也一样。同一个模型用同一套温度参数审查自己,作用极其有限。
所以我的做法是让不同模型负责不同角色。开发Agent负责生成代码,审查Agent用另一个模型来做,审查规则固定为三条:引用是否真实存在、是否满足验收标准、是否有明显的安全与并发问题。模型不同,参数不同,输出策略不同,审查时更容易发现开发环节看不到的盲区。这也让我意识到,多AI协作的价值不在“多花模型钱”,而在引入多元视角。
4.2 一个极简的多Agent流水线骨架
我实际搭的并不复杂,没有用到重框架,流程是固定的:
- 人写好需求描述,包含背景、约束、验收标准。
- 规划Agent读取
ai/context.md和ai/schema.md,输出任务拆解清单。 - 开发Agent按清单生成代码,要求它给出改动清单,并标记自己做过的“最危险的假设”。
- 审查Agent用另一个模型执行静态检查,输出问题列表。
- 测试Agent生成测试并运行,失败则回到步骤3。
- 人对最终结果做一次人工评审,然后合并。
这套流程里最大的开销,反而不是模型调用,而是第1步的需求描述。但这一步也正是vibe-coding最容易被低估的地方——需求描述不是给AI看的,是给流程立标准的。如果你连自己要做成什么样都描述不出来,多Agent只会把混乱放大。
4.3 模型部署与上下文的实际考量
不管你是直接调用API还是自托管大模型,多AI协作落地时都有一些实操问题要注意。第一,审查Agent和开发Agent最好放在完全不同的上下文环境里,不要共享同一份长对话历史,否则审查Agent会继承开发Agent的思维定势。第二,自托管模型在做审查这种需要更长链条推理的任务时,延迟和负载都会比单纯生成代码更高,要给足超时时间。第三,别让所有Agent共享同一个系统级提示词。开发Agent的系统提示词强调“产出完整、可运行代码”,审查Agent要强调“严格、但输出结论要给出依据”。这些细节看着琐碎,实际上决定多AI协作是加速还是添乱。
5. 工程护栏:让AI协作的代码能交付、能维护、能回滚
vibe-coding的终点不是跑通一个demo,而是让AI生成的代码能走到生产环境。从我的日志看,至少要过三道护栏:测试、评审、提交规范。
5.1 测试先行:先让AI写失败测试,再让它写实现
与其让AI直接写功能代码,不如调换顺序:先让它写一个会失败的测试,或者让它描述“这个功能如果做错了,最可能影响哪几个文件”。这一步看起来多花了时间,实际上是在逼模型从调用方的角度思考,而不是从实现者的角度自说自话。AI写出来的失败测试,本身就带着它对这个需求的假设,你审这个测试比审最终实现要容易得多。等测试固定下来,再让它写实现,跑到测试通过为止。这个过程相当于把“验收标准”前置,AI的所有后续改动都必须围绕这个标准展开,跑偏的概率低很多。
我还习惯在测试代码里顺手让AI标注每个断言的意图,例如“断言状态为PAID时只返回对应的两条订单”。这样即使过了很久再回看测试,也能知道当初为什么这么测。这个习惯回归起来特别香,尤其是在三个月后排查一个诡异回归的时候。
5.2 人仍然要做一次真正的评审
AI审查能抓逻辑漏洞,但替你做不了产品决策。比如模型可以把代码写得优雅且稳定,但它可能把一个本应只在特定条件生效的改动,不小心扩大成了全局行为。这种问题需要人带着业务直觉去评审。我的评审清单就三行:
- 改动范围是否收在需求描述里面,有没有顺手重构了无关代码。
- 边界条件是否符合业务语义,比如金额是否允许负数,状态流转是否合法。
- 有没有产生无归属的依赖,比如AI引入了一个没人复核的第三方包。
盯住这三条,vibe-coding产生的代码就能保持基本体面。日志里有一段话我写给自己:AI改代码有多容易,把它推回去就有多麻烦。人工评审是所有护栏里唯一能拦住“范围蔓延”的关卡,省不了。
5.3 把翻车上下文留下来,它们是提示词模板的种子
最后一条经验可能很多人不在乎:不要急着删掉那些失败的对话。我每处理完一个翻车场景,就会把“错误的提示词 + 错误结果 + 修复后的提示词”存成一个片段,放进ai/prompt-templates.md。时间长了以后,这个文件变成了一份特别实际的提示词手册,全部都是项目自己的案例,比网上任何教程都贴合实际业务。比如我后来所有涉及数据库的生成任务,都会默认带一句“先读取ai/schema.md,不确定表结构时提问”,这句话就是从第一次SQL幻觉事故里提炼出来的。
同样,凡是涉及金额、并发或者权限的改动,我都会在约束里加一条“列出你的关键假设,并给出验证方法”。这让我明显感觉到,vibe-coding不再是碰运气,而是一个可以在项目里反复使用的稳定流程。
最后聊一点个人的体会。两周日志记下来,最大的变化不是代码量,而是我开口之前的思考方式。vibe-coding让我学会把脑子里的隐性知识成体系地摊到提示词里去,比如字段命名习惯、状态流转规则、哪些文件不能动。一旦摊开了,AI的角色就从“替身”变成了“超级执行者”。如果你也想长期这么干,我建议你从明天开始给自己建一个ai-log的Markdown文件,什么都不用写复杂,记录三样东西就够了:今天让AI做了什么、哪里翻车了、下次提示词要怎么改。两周以后再回头翻,你会明确看到自己是怎么从“跟AI聊天”进化到“跟AI协作了”。