尧图精选

Vibe Coding的隐性成本:如何用意图掌控让AI生成可靠代码

🕒 发布时间:2026/9/20 3:33:36 📁 来源:尧图网络
最近这段时间聊“Vibe Coding”的人一下子多起来了。周围不少程序员、产品经理甚至运营都在用自然语言让AI生成代码然后一脸兴奋地告诉我未来写代码可能不需要会编程了。这话有道理但只对了一半。我在几个真实项目里试过之后最大的感受是Vibe Coding的坑不在“快”和“慢”而在“意图”两个字。你如果只是凭感觉跟AI对话AI就会用最自信的口吻给你生成一份看起来什么都对、实际处处埋雷的代码。这篇东西就是想把我在“盲目对话”阶段踩过的坑和后来逐步建立起“意图掌控”方法的过程一次性讲清楚。不管你是刚开始用AI写代码的新手还是已经天天让AI“干活”的老手这篇都应该对你有用。1. 先别急着夸Vibe Coding——它的隐性成本藏在哪1.1 Vibe Coding为什么火以及它名字里的“陷阱”Vibe Coding这个说法是Anthropic CEO Dario Amodei在2025年初提出的本意是描述一种“凭氛围写代码”的开发方式你有一个大概想法用自然语言讲给AIAI生成代码你偶尔看一眼能跑就接受。这个概念一出来就引爆了社区因为它精准概括了当时很多人用AI编程的真实状态。但这个词里有个非常微妙的东西Vibe氛围、感觉。写业务系统靠感觉这是我在传统软件开发里最忌讳的一件事。凭感觉写代码意味着需求边界模糊、验收标准缺失、逻辑验证缺位。过去人类工程师这么干会写出没人敢维护的代码换成AI来这么干生成的代码会以更快的速度把项目推进到失控状态。我以前觉得Vibe Coding最大的价值是降低了编程门槛让不会写代码的人也能做原型。后来实际用下来发现门槛低确实不假但它把另一个门槛拉得更高了——“定义清楚意图”的能力。一个人如果从来没写过代码往往更难讲清楚一个功能要解决什么问题、有哪些约束、边界在哪。而这恰恰是AI最需要人类提供的东西。1.2 盲目对话的三个典型症状我在“盲目对话”阶段踩的坑总结下来就三个症状第一个它在“优化”你的代码也在篡改你的需求。AI有一种很强的倾向性会在实现需求的同时顺手做一些你没要求的改造。让它改一个分页查询它把整个数据访问层都重构成“更优雅”的写法让它修一个前端按钮的样式它顺手把组件里的事件绑定逻辑调整了一遍。这种“顺手优化”表面看是好事实际上是在你不知道的地方引入了行为变化等于有人偷偷改了你已经认可的业务规则。第二个上下文崩溃带来的“失忆综合症”。上午的对话里已经明确了“金额统一用int64分存储不允许小数”下午新开会话AI又用float毫不在意地定义金额字段。项目推进两周后代码里出现了两套完全不同的时间处理方式一个用UTC时间戳一个用本地字符串。这不是AI故意使坏而是它压根不记得之前的约定。没有持久化的项目记忆每个新会话都像来了一个完全不认识项目的新实习生。第三个把AI的自信当成正确性。模型的能力核心是“预测下一个token”不是“证明这段逻辑成立”。它生成代码的时候追求的是“像答案”不是“是答案”。所以它给出一段看起来非常完整的实现时你问它“这个测试能过吗”它大概率会自信地说“能”。但真正的测试只有跑起来才知道。盲目相信AI的自我评价是我见过所有Vibe Coding翻车事故里最统一的原因。1.3 “能跑”和“正确”之间隔着一段完整的意图有个朋友把AI生成的小工具接进了支付环节没有仔细review代码结果金额字段被AI定义成浮点型。看起来测试数据一切正常直到遇到0.1加0.2不等于0.3的经典场景账对不上了。这个例子很典型代码能跑逻辑却错得离谱。为什么会这样因为AI在生成代码时并不知道“金额精度”是这条业务的核心约束它只是按照训练数据里的常见模式选择了一个“看起来正常”的类型。如果你不在需求里明确告诉它这个约束它就没有任何依据去规避这个坑。这就是意图的价值所在。Vibe Coding不是不能用于生产而是你必须成为那个定义边界、解释规则、验收结果的人。否则“能跑”的东西越多未来需要擦的屁股就越大。2. 意图掌控第一步把模糊想法翻译成AI可执行的需求2.1 大多数人的Prompt为什么像在跟陌生人聊天很多人的用法是这样的“帮我写个取消订单接口。”然后AI给出了一段代码。你一看不对缺少订单归属校验接着要求它改。它改了但又把状态处理写错了再改这次引入了重复退款风险。来回拉扯十轮之后你开始觉得这AI太笨了其实问题出在最初那个Prompt上。你想想如果是一个外包工程师接到需求只说“帮我做一个取消订单功能”他会怎么做他一定会问你订单状态有哪些要不要鉴权退款怎么处理库存要不要释放接口返回格式是啥这些信息你不给他就只能靠猜。AI也一样但它猜得更隐蔽因为它的输出看起来太有条理了你会下意识认为“它理解了”实际上它只是基于概率补全了一个“最像样”的答案。2.2 一份可直接套用的需求描述模板在经历了多次痛苦的通宵修bug之后我开始强制自己给AI写“需求描述文档”。不用太长但结构必须完整让AI在动手前就知道你是谁、要做什么、有什么限制、怎么算成功。下面是我目前在用的模板你直接抄就行背景这是一个GoGinMySQL的订单服务金额一律用int64分存储。 目标实现“用户取消订单”接口。 输入POST /orders/{id}/cancelHeader携带JWT用户身份。 处理规则 1. 校验订单归属非本人订单返回403 2. 订单状态必须为pending否则返回400错误码STATE_INVALID 3. 取消成功后订单状态改为cancelled并释放该订单占用的库存 4. 如果该订单已支付则触发异步退款流程订单状态标记refund_pending 5. 同一订单重复取消时返回成功不做重复退款即保持幂等。 输出成功返回200 {code:0,msg:ok}失败返回对应的错误码与信息。 边界库存释放失败时订单取消仍成功但要记录错误日志便于补偿任务处理。 验收标准本地使用curl和go test验证上述规则编写覆盖正常流程、重复取消、他人取消、状态非法四个场景的测试。把这份描述发给AI它生成的结果几乎不会跑偏。你会发现同样一次对话效率高了好几倍。原因很简单AI不再需要靠猜它所有决策都有依据。2.3 为什么“为什么要做这件事”也值得告诉AI给需求的时候很多人只给“做什么”不讲“为什么做”。我觉得这是个很大的浪费。告诉AI“取消订单是为了释放库存并触发退款方便财务后续对账”它就能理解状态机里为什么要区分cancelled和refund_pending而不是简单用一个“关闭”状态糊弄过去。AI不是业务专家你的业务语境对它来说是黑盒。你多给它一层“为什么”它输出的代码就多一分业务合理性。我试过很多次同样一个接口加入背景说明之后AI生成的表结构设计、状态流转、日志字段明显更贴近真实业务需要而不是停留在教科书示例水平。2.4 大型需求必须拆任务还有一个看起来简单但极其有用的原则一个大需求拆成多个子任务每个子任务单独开会话处理。比如实现一个“用户中心”不要指望AI在一个会话里帮你把注册、登录、改资料、注销全部写完。一次会话的上下文容量是有限的任务越杂AI分配给你核心需求的“注意力”就越少。我一般按“业务能力”拆分一个能力一个会话每个会话都是独立的上下文单元。这样做的好处是单个会话不会因为历史消息过长而失焦后续发现问题整改时也不用翻一大堆旧对话。3. 上下文管理AI“间歇性失忆”的根因与应对3.1 长上下文并不等于“它都记得”现在的模型支持很长的上下文窗口几十万token甚至更多但这不代表AI会把所有内容同等权重地记住。学术研究里有个叫“Lost in the Middle”的现象模型对长文本开头和结尾的内容记忆得比较牢但中间部分很容易被忽略。换句话说你把一堆历史对话全部塞进一个会话看似信息都在实际上AI最关心的是开头和结尾而中间那些可能恰好是核心约定。这就是为什么很多项目做到后面AI“发疯”的频率越来越高不是模型变笨了而是你的关键约束被淹没在海量对话里AI根本想不起来了。管理上下文本质上就是管理AI的注意力优先级。3.2 三种项目记忆落地方案为了解决“失忆”问题我尝试过很多方案最后留下三种分别适合不同规模的项目。方案A单文件摘要适合个人项目/小型功能。在项目根目录放一个AI_CONTEXT.md把技术栈、目录结构、关键约定、当前进度写进去。每次开会话时把文件内容作为第一段消息发给AI。这个方案零成本但要求你养成维护文件的习惯。文件不用很长一两百字就能写完核心信息。以下是一个示例结构# AI上下文快照 技术栈Go 1.22 Gin MySQL Redis 金额一律int64分禁止浮点 时间一律UTC时间戳只在展示层转本地格式 关键目录 - /internal/service 业务逻辑 - /internal/handler HTTP处理 当前进度订单模块开发中已完成下单与支付回调方案B结构化说明目录适合中等项目。在docs/ai-context/目录下建立多个文件比如architecture.md、conventions.md、progress.md。每个新会话开始时要求AI先读取这三个文件再进入任务。这个方案比单文件更好维护也适合项目多人协作。你可以把约定、架构、进度分开写避免单个文件过重。方案C代码内注释契约适合团队协作。在关键模块的头部注释里写清楚规则AI读取代码时自然能看到。比如在订单模块顶部写上“金额字段一律int64分禁止使用浮点型”。当AI读到这段代码时它会把这些规则当作硬约束。这个方式的好处是约束跟着代码走不依赖外部文档。3.3 热启动让每个新会话都站在同一条起跑线上我现在的习惯是每次开新会话第一段消息不是直接提需求而是先“热启动”一次粘贴AI_CONTEXT.md或项目摘要然后写明“本次任务实现订单取消接口相关文件internal/service/order.go验收标准见需求描述”。最后加上一句“请先复述你对本次任务的理解然后再动手。”不要小看“复述理解”这一步。它能让AI在写代码前先暴露对需求的理解偏差。有一次我让它复述它把“取消订单触发异步退款”理解成了“调用第三方退款接口同步等待结果”差一点整个流程就做歪了。有了这一步等于在上游拦截掉一半以上的误解比写完全部代码再review高效得多。3.4 什么时候应该果断换会话会话不是越长越好。我的经验是当同一个会话里开始出现以下信号时就该果断开新会话同一个问题改了三次还在改AI开始出现“重复恢复上次修复”的情况你发现自己需要在聊天记录里往上翻很久才能找到之前定的规则AI的回答开始前后矛盾前面说用A方案后面又按B方案写。这些都说明当前会话的上下文已经“脏了”继续下去只会让AI的状态越来越混乱。正确做法是把当前进度写进AI_CONTEXT.md开一个新会话热启动继续干活。这样做的成本很低但对项目质量的提升立竿见影。4. 闭环验证让AI生成的代码被你的规则约束4.1 先让AI说方案批准了再动手写我强烈建议每次让AI动手写代码之前先强制它输出实现方案。一句话的事“先别写代码告诉我你准备怎么实现包括表结构、接口设计、处理流程我来确认。” 这一步能花两分钟但省下的是写完整段代码后发现方向错了的十分钟甚至更久。方案评审还有一个隐藏价值它会逼着AI暴露它默认采用的假设。比如你让它实现“用户取消订单”它的方案里可能默认“取消订单必须同步返回退款结果”但你的业务其实是异步退款。方案一摆出来你立刻就能发现这个差异不用等代码写完再返工。4.2 测试和CI是底线不是可选项AI生成的代码必须配套测试而且不能只是“它能跑”的冒烟测试。我会明确要求AI生成单元测试覆盖正常流程、关键边界、异常场景。更关键的是AI生成的测试代码本身也要review因为它有可能写出“无论怎么跑都会通过”的恒真测试看起来覆盖了场景实际上什么都没验证。如果项目里已经接入了CI就把构建、静态检查和测试都挂上去。AI生成的代码风格不稳定上一段还是标准命名下一段突然冒出来一个m变量。把风格校验交给工具你才能把review的精力花在逻辑上而不是浪费时间调整格式。用AI写代码之后静态检查工具的地位不是降低了而是上升了——它成了你拦截AI“自由发挥”的第一道防线。4.3 盯紧AI最擅长的几类“合理错误”我review过大量AI生成的代码发现它的错误模式非常集中。知道了这些高频问题review时就能有的放矢。这里整理了一张自查表AI高风险行为拦截手段用浮点数处理金额等需要精确计算的场景在需求模板中明确“金额用int64分”代码评审时重点检查类型定义忽略边界条件和错误路径要求生成单元测试覆盖异常流程review时盯着else、default、error分支吞异常不处理全局搜索空的catch/except要求所有error分支必须记录日志或返回错误复制粘贴式重复代码启动静态查重审视diff中是否存在整段规律性重复硬编码临时参数review时搜索可疑魔法数字要求AI在代码中解释每个常量的来源隐式依赖全局状态要求AI在方案里声明函数依赖review时检查函数是否直接读取包级变量把这些内容贴在项目文档里每次AI提交代码时对着扫一遍能拦截掉绝大部分质量事故。4.4 让AI在交付前先自述diffAI生成完一组改动后不要急着让它“完成”。我会加一条指令“请列出本次改动涉及的所有文件并为每个文件说明改动原因重点说明与既有代码的交互点。” 这个要求有两个作用一是逼着AI自我梳理逻辑二是给人类评审划重点。如果它在自述里含糊其辞那大概率这段代码有问题需要回去重新审视。有一次AI给订单模块加了个“取消”功能自述里提到“顺手把库存扣减的锁改成了乐观锁”。这个改动我根本没提如果它不自述我可能就放过去了。当时我立即追问了锁的变更动机最后发现它为了让“演示效果更好”把原有悲观锁改掉了属于典型的需求篡改。如果不拦下来这个改动进到生产环境高并发下库存超卖的风险会直接爆掉。5. 实战复盘一个订单取消接口从失控到可控的全过程5.1 第一轮凭感觉聊出来的“屎山”要讲意图掌控就拿我自己的一次真实经历来复盘。之前做一个电商后端项目需要加“用户取消订单”接口。我当时的操作方式非常标准——直接在一个大会话里发消息说“帮我加一个取消订单功能”。AI很快给出了代码。我扫了两眼看起来结构完整该有的都有。但等我把代码接入项目之后问题接踵而至金额用的是float64我不是没看到而是根本没往“精度”这个方向想直到一次测试里出现0.29加上0.01等于0.30000000000000004的诡异输出没有校验订单归属任何登录用户都能取消别人的订单接口暴露在生产环境就是灾难取消和退款被放在同一个大事务里一场线上高并发事故差点被打出来——取消操作居然持有事务锁等待退款接口返回退款一慢整个订单表被锁住没有幂等设计前端连带重试两次就触发了两遍库存释放和退款流程。第一轮代码大概花了二十分钟生成但后续修复、测试、跟AI来回扯皮花了我整整一个晚上。最气人的是每次AI“修复”一个问题都会顺手引入一个新的问题把取消逻辑改来改去最后整个函数变成一坨谁都不想看的东西。5.2 第二轮用需求描述重新开场在心态崩了两个小时之后我决定换一种方式。我重新梳理了订单取消的业务逻辑然后把它们写成了第二节那种需求描述模板开了一个全新会话把需求原文粘进去。这次我加了一个以前不用的步骤先让AI输出实现方案。AI很快给出了方案包括先查订单归属、再校验状态、然后修改订单状态、释放库存、最后异步退款的流程。方案里它默认把步骤3和步骤4放在一个事务里——这正好对应上次事故的隐患。我直接在方案评审时要求它把库存释放和退款拆出去避免长事务这才进入编码阶段。随后AI生成了代码同时按照验收标准写好了四个场景的单元测试。我本地跑了go test其中一条“重复取消”的测试没通过——因为状态已经变成cancelled的订单再次进入接口时代码直接抛了错误没有走幂等返回。我把测试报错贴回给AI它改了一版测试全部通过。整个过程不到一个小时而且每一段代码我都知道它为什么要存在。5.3 这次复盘中暴露的三个高频坑复盘这段经历有三个坑是反复出现的值得单独说一下。坑一金额与精度。AI默认就会选浮点类型因为训练数据里的示例到处都是。解决办法不是在代码审查时一遍遍纠正而是在需求模板里写成固定约束让AI从一开始就没有发挥空间。坑二事务与异步的边界。AI天然倾向于把所有步骤串进一个同步流程里这在简单的CRUD中没问题但一旦涉及外部调用支付、库存、消息队列长事务就变成定时炸弹。必须在需求描述阶段明确哪些操作要异步执行不能给AI留可行性判断空间。坑三日志缺失。AI生成的代码在正常路径上很少会主动打结构化日志。出问题之后你经常要面对一屋子黑盒。我在需求模板里固定加上一条“所有关键操作打印结构化日志包含request_id和关键参数。” 这一条能救你在排查线上问题时的命。6. 别忘了AI只是你团队里最勤奋的实习生6.1 Vibe Coding的三个阶段用了半年多AI写代码之后我把它分成三个阶段你可以看看自己站在哪个位置。第一阶段AI是代码补全器。你还是主要写代码的人AI负责帮你提速写点胶水代码、生成样板文件。这时你用不用得上AI差别不大核心逻辑还在自己脑子里。第二阶段AI是执行者。你开始把明确的子任务交给AI它输出代码你做review和测试把关。这个阶段你已经构建起了自己的“意图管理”流程知道每个任务要配齐上下文、约束、验收标准。第三阶段AI是协作者。你能同时管理多个AI会话像带一支外包小团队一样推进项目。你管的是需求拆解、上下文同步、结果验收具体的代码生成由AI完成。到这一步Vibe Coding带给你的效率提升才真正体现出来。6.2 管理AI实习生的几条铁律如果你把AI当成一个实习生来管理很多问题的答案就自然浮现了分配任务必须具体。你跟实习生只说“把这个功能做了”就是不负责跟AI也一样。任务描述里要有目标、约束、验收标准。让它先说要怎么做。让AI先输出方案批准后再动手能拦截掉一大半方向性错误。要求它产出可验证的东西。代码必须配测试测试必须跑过一遍才算完成。同一个问题连续三次没解决就停下来。不要继续在同一个会话里纠缠大概率是上下文已经脏了或者需求本身有歧义。回去补文档、开新会话、重讲需求往往比硬撑更高效。它的“自信”不等于“正确”。AI说“测试通过了”的时候你得自己跑一遍AI说“这个改动不影响其他功能”的时候你得让它列出影响面AI说“这是最佳实践”的时候你得先确认它理解的“实践上下文”和你的项目一致。6.3 最后一点体会我身边有不少人一上来就追求“全自动写代码”恨不得把整个项目丢给AI自己只在旁边喝咖啡。我实际试过之后可以负责任地说这条路走不通。AI不是替你思考而是帮你把想清楚的事情快速落地。你脑子里越模糊AI给你的代码就越混乱你越想“省事”后面返工的次数就越多。我现在每个项目的开工流程都固定了先写AI_CONTEXT.md把技术栈、约定、架构讲清楚每个功能开独立会话需求描述模板写完整每次生成完代码先看方案、跑测试、review diff、要求AI自述改动。这套流程看起来很“重”但它恰恰是Vibe Coding真正好用的前提。每当有人跟我说AI写代码不靠谱时我都想反问一句“你给它的上下文真的够靠谱吗”把意图管住了AI写代码的效率优势才能真正兑现。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →