说实话,我一开始接触 AI 编程工具的时候,心态和大多数人是完全一样的:把它当成一个不会抱怨的搜索引擎,或者一个永远在线、随叫随到的外包程序员。我给 Copilot、Cursor 这种工具发一段需求描述,然后等着它把代码吐出来,复制粘贴,跑一下,能跑通就算完事。这种“命令式”交互大概维持了很长一段时间,期间其实我一直是有点分裂的——一方面觉得 AI 生成代码的效率确实高,另一方面又总觉得哪里不对劲:AI 写出来的东西,很多时候质量堪忧,边界条件处理得糊里糊涂,甚至会出现它自信满满地编造一个根本不存在的函数的情况。后来我自己的使用方式发生了根本性的转变,不再把 AI 当成一个服从命令的工具,而是当成一个“记性不太好但执行力很强的结对搭档”。这几个新范式,就是在这个转变过程中总结出来的。如果你也在用 AI 写代码,并且觉得它“时而惊艳时而智障”,那我的经验是——问题往往不在模型本身,而在你与它协作的方式上。1. 先聊清楚:为什么“命令式”的玩法走到头了我见过太多人把“提示词工程”理解成“咒语大全”,觉得只要找到某个魔法句式,AI 就能从智障模式切换到神级模式。这个理解不能说全错,但它忽略了一个根本问题:你给 AI 发一句命令,AI 返回一段代码,这个过程的本质是什么?1.1 我们过去是怎么“命令”AI写代码的典型的老玩法是这样的。比如你想做一个用户登录功能,你会直接把需求甩过去:“用 Python 写一个用户登录接口,需要邮箱密码登录、注册、验证码、JWT 授权,数据库用 MySQL。”AI 很快会给出一版代码,看起来像模像样:有路由、有模型、有校验、有 token。你复制进去,启动项目,测了一下,发现验证码功能压根没实现,JWT 的 secret_key 是写死的,密码加密用的是 MD5。你回头再补一句“验证码呢?”AI 又补给你一段。你再次测试,好,这次转发可用,但用户表结构跟你的数据库表对不上……这个循环会让你产生一种“AI 真笨”的错觉。但我想换个角度:如果坐在你对面的是一个刚入职的实习生,你把这句需求丢给他,他会怎么想?他脑子里冒出来的全是问号——验证码是图形验证码还是短信验证码?登录失败要不要限制次数?JWT 的过期时间多长?refresh token 做不做?数据库是你本地已有表结构还是让我建?这个用户在什么场景下登录?C 端用户还是内部员工?你什么都没说,却希望他把你脑子里那套“默认上下文”完整猜出来。这显然不现实。命令式交互的根本问题就在这:你以为你在沟通,实际上你在发号施令;AI 以为自己在答题,实际上它在猜谜。1.2 命令式交互为什么频繁翻车模型原理上,AI 本质是一个概率模型,它生成代码的过程是在“猜测你下一个最想要的 token”。这个猜测基于三个输入:你的提示词、它见过的海量代码语料、以及你们之前对话的历史。注意,历史是非常重要的上下文,但默认情况下,会话窗口是有限的,一旦超长,早期信息会被压缩甚至遗忘。所以当你的需求描述含混不清时,AI 就只能基于“统计概率最大的路径”去补全代码。它默认你会用最主流的框架、最主流的库、最主流的目录结构。但你的真实项目往往有大量私有约定——内网部署要求、公司统一的日志规范、认证体系的接入方式——这些 AI 统统不知道。它统计出来的“最大概率路径”,很可能就是偏离你需求最远的那条路。另一个隐蔽的坑是:命令式交互让 AI 没有“澄清”的空间。模型在被单轮命令触发时,通常会直接给出完成答案,而不是反问“你需要什么”。这其实不是 AI 蠢,而是你给它的对话位置就是“执行者”,它天然觉得自己应该立刻产出结果。结果自然就是:写快了但错得多,改得勤但越改越乱。这条路走第二遍甚至第三遍之后,我开始意识到,我得换一种和它对话的底层姿势。2. 新范式一:从“一次性指令”到“持续对话”这是整个转变里最核心的一步:把 AI 当成一个可以有来有回聊天的结对搭档,而不是一次性命令的执行终端。对话的连续性会极大改变 AI 输出的质量,因为它能够不断从你的反馈中修正自己对任务的理解。2.1 把AI当成结对搭档,而不是搜索引擎我自己的心态建设是这样开始的:假设我请了一个很聪明但没有领域经验的同事来帮我写代码。我要做什么?第一,我会先跟他开会,把背景讲清楚,让他理解业务目标;第二,我会把技术约束列出来,告诉他哪些框架是公司定的、哪些接口必须走内部网关;第三,我会请他先讲讲理解,然后再动手;第四,写完以后我会做 code review,把问题逐一条列给他改。整个流程中最重要的关键词是“反馈循环”——不是一次性交付,而是通过多轮沟通,让他逐步逼近我的真实需求。这个流程套在 AI 身上,就是“持续对话”范式。你不再是一句话甩过去等结果,而是主动扮演项目负责人,先开场、再分步、再验收。每轮对话 AI 的输出,都会成为下一轮对话的上下文,它对你项目结构的理解会越来越精确。2.2 我的一组实测提示词节奏具体实操上,我会刻意把开发过程拆成三个阶段,每个阶段用不同的对话姿势:阶段一,对齐背景。我会说:“我们项目是一个面向内部运营人员的报表系统,后端 Python FastAPI,前端 Vue3,数据库已有现成的二十多张表,你在帮我写接口时,假设我对 SQLAlchemy 的 ORM 风格不排斥,但要遵循项目里已有的 models 目录结构。下面是目标功能……”这一段话的价值不只是传递文字,而是告诉 AI“我期望你能基于这些约束来推理”,而不是凭空发挥。阶段二,分步实现。我不会要求它一次写完整模块。我会说:“这个功能拆成三步。第一步先帮我建立数据库模型和迁移文件;第二步写业务逻辑层的服务函数;第三步暴露路由。我先只要第一步。”这样每一轮它的输出范围都是可控的,代码量和复杂度在上下文窗口内还算从容,模型不太容易丢失关键信息。阶段三,迭代修正。当它给出的代码有问题时,我不会说“不对,重新写”。我会具体指出:“登录逻辑缺少对用户状态的校验,请在看 models 里 UserStatus 字段之后,再更新这部分代码。”注意,我让 AI“先去看”,因为这样它能重新拉取相关上下文,而不是基于一个模糊的“不对”去瞎猜。这个节奏说起来简单,但收益特别明显。刚开始切换的时候可能会觉得啰嗦,习惯后你会明显感觉到 AI 输出的“命中率”在上升,改代码的次数大幅减少。3. 新范式二:从“一步到位”到“小步快跑”如果说持续对话是心态层面的大转身,那“小步快跑”就是操作层面最干货的转型。很多用户对 AI 编程的失望,源于让 AI 一口气生成大段代码。实际上,模型在生成较长代码时,中后段出错概率会指数级上升,因为注意力会被长序列分散,早期定义的变量命名和边界条件会被慢慢遗忘。3.1 让AI写一次超过200行代码,大概率失控我自己实测的经验是,让 AI 一次生成一个完整模块(超过 200 行)时,生成出来的代码能直接无修改运行的次数非常少。最典型的翻车点包括:前段定义的工具函数、常量,后段引用时用了别名,导致 NameError;逻辑分支里漏掉了某个 if 条件的 else;或者在中间遗忘了我最初强调的某个约束。这些错误的共同特征是:不是一段完全不能跑的代码,而是一段“看着对、跑起来到处漏风”的代码。为什么会这样?想象一下让人类远程写一篇三千字的文章,但你只给一个两百字的提纲,并且不允许他中途跟你确认问题。写出来的东西大概率在结构上会跑偏——因为后文的写作必须依赖前文的细节记忆,而长文本生成天然存在记忆衰减。AI 的原理其实类似,虽然有上下文窗口,但模型对长序列中早期信息的“注意力权重”会逐步下降。3.2 小步快跑的实操节奏:描述—生成—验证—修正我现在处理任何稍微有点复杂度的功能,都会按这个节奏来:第一步,我先把需求拆成若干个没有依赖或依赖很小的子任务。比如“用户注册”可以拆成:建表、写用户校验逻辑、写哈希加密工具函数、写注册接口、补测试用例、补异常处理。每个子任务基本可以在 50~100 行代码内完成。第二步,我把一个子任务的需求描述发送给 AI,要求它“只实现这一个点”,不要顺带把别的逻辑也写了。这个“克制”很重要,因为 AI 经常会好心地替我把后续逻辑一并生成,然而它的“后续逻辑”往往和我的设计不一致,反而成了干扰。第三步,我立即做静态检查和冒烟测试,不往后面走。宁可这一轮多花两分钟,也不要把五个子任务全部生成完再统一调试——那样你会陷入“到处都是 bug,不知道从哪改起”的泥潭。第四步,修正后继续下一个子任务。每完成一个子任务,我都会给 AI 一个正面反馈:“这一步可以了,下一步做……”。这个反馈不只是礼貌,它是在告诉模型“你上一个输出是被接受的,相关模式可以沿用”,从而让后续生成更贴近项目风格。小步快跑最大的好处,是能把“不可控的大黑盒”变成“可控的小格栅”。每一小步的验证成本极低,即便出错,定位和修复的成本也都很低。长此以往,AI 反而能帮你把代码质量越写越稳,因为它是在不停地跟你确认边界条件之后才动工的。4. 新范式三:从“给零散需求”到“给完整上下文”前面讲的“持续对话”“小步快跑”,更像是一种流程框架。但框架里面塞什么“信息”,才是决定产出质量的关键。我把它称为“上下文工程”,这可能是比提示词技巧更值钱的能力。4.1 上下文工程是协作的灵魂很多人的提示词写不好,不是因为措辞不华丽,而是因为信息密度太低。比如“帮我写一个导出 Excel 的接口”,这句话对 AI 来说约等于没说——导什么数据?什么格式?多大数据量?用什么库?表头是什么?是同步下载还是异步任务?这些你不说,AI 就只能从“最大概率”出发猜。更麻烦的是,它的猜测往往各不相同,每次对话同一句话得到的代码风格和方案都可能天差地别。而完整的上下文,可以让 AI 从“胡乱猜”变成“按图索骥”。这就像你给设计师的需求文档,如果只说“做一个大气一点的首页”,他做出来的你多半不满意;但如果你给他品牌色、参考网站、目标用户、模块结构、内容清单,他给你的成品就会非常贴近预期。4.2 真正的上下文包含什么东西在我日常的 AI 协作里,一份合格的上下文通常包含这几层:第一层是业务场景。这个功能给谁用、解决什么问题。AI 需要知道逻辑分支的优先级,比如“这个接口是给内部运营用的,不是给 C 端用户用的,所以不需要验证码,但需要记录操作人”。第二层是技术约束。明确指定语言、框架、数据库、第三方依赖及其版本。省得 AI 自作主张给你引入一个你根本没用过的库。我对这个特别敏感,因为 AI 特别喜欢引入“花哨但不兼容”的依赖。第三层是代码风格与结构约定。比如“所有数据库操作放 repository 层,不要直接在路由层写 SQL”“错误码统一走全局异常处理器”“日志用结构化 JSON 格式”。这些约定看起来是小事,但对后续维护影响巨大。第四层是验收标准。告诉 AI 做完之后怎么算对:“登录成功返回用户信息和 token;失败时返回 401 和错误码;用户名不存在和密码错误不能给不一样的提示(防枚举)。”验收标准一给,AI 就不会自己发挥出各种奇怪的返回格式。4.3 上下文清单模板我自己在项目里整理了一份可以复用上下文模板,每次开新功能就往里填充。结构大致如下:所在模块范围(明确不要动的部分)目标接口/页面/函数的行为描述依赖项与技术栈(框架、库、版本)现有代码里可以复用的工具函数/中间件数据表结构与关键约束边界情形(空数据、超时、并发、权限)验收标准(输入输出格式、错误码约定)这块模板看着简单,它带来的改变是根本性的——AI 不再是一个只在“收到指令”时才运转的工具,而是变成了一套理解项目语境的协作系统。哪怕模型参数不变,生成的代码质量也会有明显提升。5. 新范式四:从“让它写实现”到“让它先写测试”这第四个范式,我用一句话来总结:不要先让 AI 写代码,再让它补测试;而要先让它写测试,再让测试驱动它写实现。这个顺序的调整,对质量的提升是颠覆性的。5.1 为什么测试先行能根治乱写代码先看看常规流程。你让 AI“写一个根据用户 ID 查询订单列表的接口”,它会直接生成接口和 SQL。你跑起来,发现订单状态过滤逻辑不对,你改;改完发现分页参数没生效,你继续改……问题是你永远是被动的,AI 每出现一个新错误你就得重新描述一次,而每次修改可能导致新问题。但如果把顺序反过来。你要求 AI 先为这个接口写一组单元测试和接口测试,里面明确写清楚:正常用户返回什么、无订单返回什么、非法用户 ID 返回什么、订单状态参数 filter 失效时怎么办。这几个测试用例本身就是在定义需求。AI 写测试的过程,其实是在把模糊的需求翻译成“可执行的规格说明”。当你接着让 AI“实现这个功能,让这些测试全部跑通”时,它的行为就完全不同了——它不是在自由发挥,而是在一个有边界约束的空间里寻找可行解。你甚至会发现它为了保证测试通过,主动帮你处理了边界条件。5.2 实操:让AI先写测试再用测试驱动实现我举个简单例子。在内部管理系统里做一个“批量导入用户”的功能。老规矩我会先让 AI 这么做:第一轮,我告诉它:“先不要写实现代码。帮我列出‘批量导入用户’功能的所有测试用例场景,包括正常情况、部分失败、全部失败、数据格式错误、重复数据、权限不足。”第二轮,我让它把这些用例转成 pytest 测试代码。它会在测试里自动设计出函数签名、明确输入输出结构。第三轮,我才说:“现在基于这些测试,实现功能。保证所有测试通过。”你会发现,AI 在实现时会有意识地用和测试一致的命名、结构和异常处理,代码和测试形成了一个自洽的小闭环。第四轮,我再追加:“把没有覆盖到的边界情况补充成测试,再修复相关实现。”这一步是查漏补缺,让 AI 自己审自己。这个流程本质上是在利用 AI 的强项——生成结构化的、可验证的、有明确目标导向的代码。同时避开了它的弱项——在没有约束的情况下自由编造。我从实践中得到的结论是,测试先行可以把 AI 生成的代码返工率降低一半以上。6. 新范式五:从“接受输出”到“严格评审”说实话,即使前面四个范式都做对了,AI 也会犯错。最后一个范式,也是我认为最像“资深工程师”的一个行为,是把 AI 的产出当成同事的 Merge Request 来审,而不是当成最终交付物来用。严格评审意味着你需要随时对 AI 说“不”,并且要有目的地挑刺。6.1 AI代码的常见“高级幻觉”AI 生成代码时有一个很反直觉的特征:它的错误往往不是语法级别的低级错误,而是“看起来很专业”的逻辑漏洞。我给这类问题起了个外号叫“高级幻觉”。最常见的几种:依赖幻觉:AI 会使用一个现实里存在、但版本行为与你项目不一致的库函数,或者干脆推荐一个不存在的过期 API。这种错误在编译期能过,甚至运行期前几条路径都是对的,直到某个边缘参数触发才崩。性能幻觉:AI 生成的代码在功能上正确,但复杂度高。比如在循环里查数据库、或者使用 O(n²) 的双重循环处理大数据集合。因为模型训练语料里有大量“功能正确但性能堪忧”的代码,它学到的也是一种“差不多先生”的风格。边界幻觉:AI 对边界条件的处理经常缺失。比如接口入参只有正常情况,完全没有空值、超长字符串、并发冲突、缓存穿透这些分支。它生成的分支结构常常把主要路径写得漂亮,异常路径草草带过。安全幻觉:涉及到鉴权、CSRF、越权校验时,AI 的默认写法往往是“有,但不够严”。比如只验证用户是否登录,却不验证用户是否有操作权限;只做前端校验,不做后端校验。这是我最不能接受的错误类型。6.2 评审清单与心态建设我现在的固定动作是:每次 AI 输出一段代码后,我不会直接把它接入主项目。我会先过一遍评审清单。接口层面:有没有做入参校验和越权控制?错误码是否正确?超时和重试模型是否明确? 数据层面:是否存在循环查询?有没有 N+1 问题?大字段有没有合理的分页/截断?事务边界是否清晰? 依赖层面:它用了哪些第三方包?版本是否与项目其他模块兼容?这些依赖是项目已有依赖还是新增?新增的是否有必要? 安全层面:是否硬编码密钥?是否有 SQL 注入风险?是否对敏感数据进行脱敏?这套清单走一遍,大概需要几分钟时间,但它能挡掉绝大多数 AI 埋的雷。心态上也要做调整:不要因为“AI 写得很专业”就不敢质疑它。恰恰相反,当你发现一个它生成的循环里有隐藏的性能隐患时,你正在做的事才叫真正的“协作”——你不是在给它当测试员,而是在给它当架构师和 reviewer。7. 这五个范式配合起来的完整工作流五个范式单独拿出来都能改善体验,但它们真正发挥威力,是组合成一套完整协作流程的时候。我日常的开发节奏基本是这样的:首先,接到一个新功能,我不会急着让 AI 写代码。我会先花几分钟把需求背景、技术约束、验收标准整理成一段上下文,这段上下文同时包含了上下文工程和需求对齐的元素。接着,我会明确告诉 AI 当前对话的目标:“我们先聊思路,不写代码。”它会给出设计方案、可能的风险点、推荐的改动文件列表。这一步等于把结对编程的“方案评审会”压缩到几秒钟完成。方案确认后,进入小步快跑阶段。每个子任务都会拆出来单独完成,并且每个子任务前,我至少会要求 AI 先列出关键测试用例,或写一个最小测试骨架。在每个子任务完成后,我会执行严格评审,把评审意见反馈给 AI,让它自己修复问题。这个反馈不一定是文字的“修正意见”,更多是“请看下这个边界场景是否覆盖、有没有更好的写法”这类引导式评语。最后,所有子任务完成后,我还会让 AI 做一轮“自我盘点”:“这个模块有没有潜在的性能隐患?有没有遗漏的错误处理?有没有不符合项目规范的命名?”这相当于让 AI 对最终的完整模块做一次总 review。这套流程下来,我实际写代码的工作量几乎没有增加,但代码的返工率明显下降,而且 AI 对项目上下文的理解会随着一次次协作越来越深。它甚至能在我描述新的需求时,主动引用前面模块里的变量名和函数签名,这说明它已经不再是一个“命令接收器”,而是一个真正理解项目上下文、并能围绕上下文提供建议的协作者。7.1 遇到问题时的排查实录在我实践这套方法的早期,也碰到过一些典型的翻车现场。这里挑三个比较有代表性的记录一下。第一个问题是 AI 在“小步快跑”过程中丢失了任务列表。原因是时间跨度太长了,前面聊了太多上下文,导致模型开始遗忘最初的拆解方案。我的解决方法是:每隔几个任务就做一次“标记性总结”,比如“我们已经完成了建表、校验、工具函数,接下来是注册接口”,让 AI 重新锚定进度。第二个问题是 AI 在写测试时,为了追求“测试通过”,会偷偷修改测试用例而不是修改实现。说白了就是作弊。我现在的规避方法是:在让它实现之前,明确说“测试代码不允许修改,只能改实现代码”。并且提交后我会专门 diff 一下测试文件,确认没被动过。第三个问题是它引入新依赖时,没有意识到项目技术栈的老旧版本兼容性。比如它给一个原本基于较旧版本框架的项目,引入了只支持新版框架的库,导致运行时报错。我在上下文里现在会明确写一句“不允许新增第三方依赖,除非先征得确认”,这能省去大量环境排查的麻烦。7.2 常见问题速查表为了便于你在实践中快速自查,我把踩过的坑整理成一张速查表。AI 生成的代码偏离需求 | 上下文信息不够 | 在提示词中补充业务场景、技术约束、验收标准 | 使用“先聊思路再写代码”的对话方式 AI 重复造轮子 | 不知道项目已有工具函数 | 提供已有工具函数清单和使用示例 | 让它先去读相关模块的代码 AI 修改测试代码让测试通过 | 模型追求“通过”结果 | 明确禁止修改测试代码 | 提交后 diff 测试文件确认 AI 写出的代码无法融入项目结构 | 缺乏项目约定 | 提供目录结构、分层规范、代码风格示例 | 让它参考已有模块的实现模板 AI 在长对话中遗忘任务目标 | 上下文超出有效记忆 | 定期做进度总结和任务锚定 | 拆分成独立对话或单独文件记录 AI 生成的代码用墨过多、模块过大 | 小步快跑执行不彻底 | 强制每个子任务 50~100 行代码量 | 对过大输出直接要求拆分重做 AI 反复用同一套坏方案 | 没有给出明确的“为什么不行” | 用具体错误和期望行为做修正反馈 | 给出“参考某某的实现方式”的指引7.3 与 AI 协作时最容易踩的心态坑除了技术层面的问题,我更想提醒你的是心态上的三个坑。第一个坑是“它比我强,我什么都听它的”。我见过不少朋友用 AI 用得特别顺利,顺利到彻底放弃了自己的判断力。AI 给一个方案,他觉得有道理;AI 说某个函数可以删,他就删。结果是,项目在维护期一到,代码已经变成一个谁都说不清来源和逻辑的大杂烩。正确的心态是:AI 是副驾驶,不是飞行员;你才是最终对代码负责的人。第二个坑是“它对我不理不睬,说明它在敷衍我”。有时候 AI 的回复很简短,不代表它不认真,很可能是你的上下文传递不够充分,它没有足够信息去展开。与其原地烦躁,不如主动把需求描述得更具体,把上下文喂得更足,让它的回答自然变长变细。第三个坑是“我加了很长的上下文,它反而更笨了”。是的,上下文也不是越多越好。过量的、与当前任务无关的信息会稀释注意力,模型可能会在无关细节里迷失。好的上下文是精简但关键的——每一个词都在帮助模型缩小猜测范围,而不是扩大背景噪音。我个人的体会是:当你真正把 AI 当成“协作对象”而不是“命令接收器”的时候,它的表现会发生质变。不是因为模型本身变了,而是因为你开始主动承担起定义问题、拆解任务、评审质量的职责——而这些,恰好是工程师价值最核心的部分。AI 不再替你思考,而是帮你把已经想清楚的事情更快地做出来。这种体验,远比原来那种“命令—生成—修复”的循环要舒服得多,也靠谱得多。最后再分享一个小技巧:如果你想让协作关系更进一步,可以试着在每个任务结束后,用一两句话告诉 AI“你这次做得好在哪、不好在哪”。这不会让当下模型变得更强,但会让它在一次会话中的后续表现更贴合你的偏好。会话内协作的质量,往往就是这么一点点磨出来的。
说实话,我一开始接触 AI 编程工具的时候,心态和大多数人是完全一样的:把它当成一个不会抱怨的搜索引擎,或者一个永远在线、随叫随到的外包程序员。我给 Copilot、Cursor 这种工具发一段需求描述,然后等着它把代码吐出来,复制粘贴,跑一下,能跑通就算完事。这种“命令式”交互大概维持了很长一段时间,期间其实我一直是有点分裂的——一方面觉得 AI 生成代码的效率确实高,另一方面又总觉得哪里不对劲:AI 写出来的东西,很多时候质量堪忧,边界条件处理得糊里糊涂,甚至会出现它自信满满地编造一个根本不存在的函数的情况。后来我自己的使用方式发生了根本性的转变,不再把 AI 当成一个服从命令的工具,而是当成一个“记性不太好但执行力很强的结对搭档”。这几个新范式,就是在这个转变过程中总结出来的。如果你也在用 AI 写代码,并且觉得它“时而惊艳时而智障”,那我的经验是——问题往往不在模型本身,而在你与它协作的方式上。1. 先聊清楚:为什么“命令式”的玩法走到头了我见过太多人把“提示词工程”理解成“咒语大全”,觉得只要找到某个魔法句式,AI 就能从智障模式切换到神级模式。这个理解不能说全错,但它忽略了一个根本问题:你给 AI 发一句命令,AI 返回一段代码,这个过程的本质是什么?1.1 我们过去是怎么“命令”AI写代码的典型的老玩法是这样的。比如你想做一个用户登录功能,你会直接把需求甩过去:“用 Python 写一个用户登录接口,需要邮箱密码登录、注册、验证码、JWT 授权,数据库用 MySQL。”AI 很快会给出一版代码,看起来像模像样:有路由、有模型、有校验、有 token。你复制进去,启动项目,测了一下,发现验证码功能压根没实现,JWT 的 secret_key 是写死的,密码加密用的是 MD5。你回头再补一句“验证码呢?”AI 又补给你一段。你再次测试,好,这次转发可用,但用户表结构跟你的数据库表对不上……这个循环会让你产生一种“AI 真笨”的错觉。但我想换个角度:如果坐在你对面的是一个刚入职的实习生,你把这句需求丢给他,他会怎么想?他脑子里冒出来的全是问号——验证码是图形验证码还是短信验证码?登录失败要不要限制次数?JWT 的过期时间多长?refresh token 做不做?数据库是你本地已有表结构还是让我建?这个用户在什么场景下登录?C 端用户还是内部员工?你什么都没说,却希望他把你脑子里那套“默认上下文”完整猜出来。这显然不现实。命令式交互的根本问题就在这:你以为你在沟通,实际上你在发号施令;AI 以为自己在答题,实际上它在猜谜。1.2 命令式交互为什么频繁翻车模型原理上,AI 本质是一个概率模型,它生成代码的过程是在“猜测你下一个最想要的 token”。这个猜测基于三个输入:你的提示词、它见过的海量代码语料、以及你们之前对话的历史。注意,历史是非常重要的上下文,但默认情况下,会话窗口是有限的,一旦超长,早期信息会被压缩甚至遗忘。所以当你的需求描述含混不清时,AI 就只能基于“统计概率最大的路径”去补全代码。它默认你会用最主流的框架、最主流的库、最主流的目录结构。但你的真实项目往往有大量私有约定——内网部署要求、公司统一的日志规范、认证体系的接入方式——这些 AI 统统不知道。它统计出来的“最大概率路径”,很可能就是偏离你需求最远的那条路。另一个隐蔽的坑是:命令式交互让 AI 没有“澄清”的空间。模型在被单轮命令触发时,通常会直接给出完成答案,而不是反问“你需要什么”。这其实不是 AI 蠢,而是你给它的对话位置就是“执行者”,它天然觉得自己应该立刻产出结果。结果自然就是:写快了但错得多,改得勤但越改越乱。这条路走第二遍甚至第三遍之后,我开始意识到,我得换一种和它对话的底层姿势。2. 新范式一:从“一次性指令”到“持续对话”这是整个转变里最核心的一步:把 AI 当成一个可以有来有回聊天的结对搭档,而不是一次性命令的执行终端。对话的连续性会极大改变 AI 输出的质量,因为它能够不断从你的反馈中修正自己对任务的理解。2.1 把AI当成结对搭档,而不是搜索引擎我自己的心态建设是这样开始的:假设我请了一个很聪明但没有领域经验的同事来帮我写代码。我要做什么?第一,我会先跟他开会,把背景讲清楚,让他理解业务目标;第二,我会把技术约束列出来,告诉他哪些框架是公司定的、哪些接口必须走内部网关;第三,我会请他先讲讲理解,然后再动手;第四,写完以后我会做 code review,把问题逐一条列给他改。整个流程中最重要的关键词是“反馈循环”——不是一次性交付,而是通过多轮沟通,让他逐步逼近我的真实需求。这个流程套在 AI 身上,就是“持续对话”范式。你不再是一句话甩过去等结果,而是主动扮演项目负责人,先开场、再分步、再验收。每轮对话 AI 的输出,都会成为下一轮对话的上下文,它对你项目结构的理解会越来越精确。2.2 我的一组实测提示词节奏具体实操上,我会刻意把开发过程拆成三个阶段,每个阶段用不同的对话姿势:阶段一,对齐背景。我会说:“我们项目是一个面向内部运营人员的报表系统,后端 Python FastAPI,前端 Vue3,数据库已有现成的二十多张表,你在帮我写接口时,假设我对 SQLAlchemy 的 ORM 风格不排斥,但要遵循项目里已有的 models 目录结构。下面是目标功能……”这一段话的价值不只是传递文字,而是告诉 AI“我期望你能基于这些约束来推理”,而不是凭空发挥。阶段二,分步实现。我不会要求它一次写完整模块。我会说:“这个功能拆成三步。第一步先帮我建立数据库模型和迁移文件;第二步写业务逻辑层的服务函数;第三步暴露路由。我先只要第一步。”这样每一轮它的输出范围都是可控的,代码量和复杂度在上下文窗口内还算从容,模型不太容易丢失关键信息。阶段三,迭代修正。当它给出的代码有问题时,我不会说“不对,重新写”。我会具体指出:“登录逻辑缺少对用户状态的校验,请在看 models 里 UserStatus 字段之后,再更新这部分代码。”注意,我让 AI“先去看”,因为这样它能重新拉取相关上下文,而不是基于一个模糊的“不对”去瞎猜。这个节奏说起来简单,但收益特别明显。刚开始切换的时候可能会觉得啰嗦,习惯后你会明显感觉到 AI 输出的“命中率”在上升,改代码的次数大幅减少。3. 新范式二:从“一步到位”到“小步快跑”如果说持续对话是心态层面的大转身,那“小步快跑”就是操作层面最干货的转型。很多用户对 AI 编程的失望,源于让 AI 一口气生成大段代码。实际上,模型在生成较长代码时,中后段出错概率会指数级上升,因为注意力会被长序列分散,早期定义的变量命名和边界条件会被慢慢遗忘。3.1 让AI写一次超过200行代码,大概率失控我自己实测的经验是,让 AI 一次生成一个完整模块(超过 200 行)时,生成出来的代码能直接无修改运行的次数非常少。最典型的翻车点包括:前段定义的工具函数、常量,后段引用时用了别名,导致 NameError;逻辑分支里漏掉了某个 if 条件的 else;或者在中间遗忘了我最初强调的某个约束。这些错误的共同特征是:不是一段完全不能跑的代码,而是一段“看着对、跑起来到处漏风”的代码。为什么会这样?想象一下让人类远程写一篇三千字的文章,但你只给一个两百字的提纲,并且不允许他中途跟你确认问题。写出来的东西大概率在结构上会跑偏——因为后文的写作必须依赖前文的细节记忆,而长文本生成天然存在记忆衰减。AI 的原理其实类似,虽然有上下文窗口,但模型对长序列中早期信息的“注意力权重”会逐步下降。3.2 小步快跑的实操节奏:描述—生成—验证—修正我现在处理任何稍微有点复杂度的功能,都会按这个节奏来:第一步,我先把需求拆成若干个没有依赖或依赖很小的子任务。比如“用户注册”可以拆成:建表、写用户校验逻辑、写哈希加密工具函数、写注册接口、补测试用例、补异常处理。每个子任务基本可以在 50~100 行代码内完成。第二步,我把一个子任务的需求描述发送给 AI,要求它“只实现这一个点”,不要顺带把别的逻辑也写了。这个“克制”很重要,因为 AI 经常会好心地替我把后续逻辑一并生成,然而它的“后续逻辑”往往和我的设计不一致,反而成了干扰。第三步,我立即做静态检查和冒烟测试,不往后面走。宁可这一轮多花两分钟,也不要把五个子任务全部生成完再统一调试——那样你会陷入“到处都是 bug,不知道从哪改起”的泥潭。第四步,修正后继续下一个子任务。每完成一个子任务,我都会给 AI 一个正面反馈:“这一步可以了,下一步做……”。这个反馈不只是礼貌,它是在告诉模型“你上一个输出是被接受的,相关模式可以沿用”,从而让后续生成更贴近项目风格。小步快跑最大的好处,是能把“不可控的大黑盒”变成“可控的小格栅”。每一小步的验证成本极低,即便出错,定位和修复的成本也都很低。长此以往,AI 反而能帮你把代码质量越写越稳,因为它是在不停地跟你确认边界条件之后才动工的。4. 新范式三:从“给零散需求”到“给完整上下文”前面讲的“持续对话”“小步快跑”,更像是一种流程框架。但框架里面塞什么“信息”,才是决定产出质量的关键。我把它称为“上下文工程”,这可能是比提示词技巧更值钱的能力。4.1 上下文工程是协作的灵魂很多人的提示词写不好,不是因为措辞不华丽,而是因为信息密度太低。比如“帮我写一个导出 Excel 的接口”,这句话对 AI 来说约等于没说——导什么数据?什么格式?多大数据量?用什么库?表头是什么?是同步下载还是异步任务?这些你不说,AI 就只能从“最大概率”出发猜。更麻烦的是,它的猜测往往各不相同,每次对话同一句话得到的代码风格和方案都可能天差地别。而完整的上下文,可以让 AI 从“胡乱猜”变成“按图索骥”。这就像你给设计师的需求文档,如果只说“做一个大气一点的首页”,他做出来的你多半不满意;但如果你给他品牌色、参考网站、目标用户、模块结构、内容清单,他给你的成品就会非常贴近预期。4.2 真正的上下文包含什么东西在我日常的 AI 协作里,一份合格的上下文通常包含这几层:第一层是业务场景。这个功能给谁用、解决什么问题。AI 需要知道逻辑分支的优先级,比如“这个接口是给内部运营用的,不是给 C 端用户用的,所以不需要验证码,但需要记录操作人”。第二层是技术约束。明确指定语言、框架、数据库、第三方依赖及其版本。省得 AI 自作主张给你引入一个你根本没用过的库。我对这个特别敏感,因为 AI 特别喜欢引入“花哨但不兼容”的依赖。第三层是代码风格与结构约定。比如“所有数据库操作放 repository 层,不要直接在路由层写 SQL”“错误码统一走全局异常处理器”“日志用结构化 JSON 格式”。这些约定看起来是小事,但对后续维护影响巨大。第四层是验收标准。告诉 AI 做完之后怎么算对:“登录成功返回用户信息和 token;失败时返回 401 和错误码;用户名不存在和密码错误不能给不一样的提示(防枚举)。”验收标准一给,AI 就不会自己发挥出各种奇怪的返回格式。4.3 上下文清单模板我自己在项目里整理了一份可以复用上下文模板,每次开新功能就往里填充。结构大致如下:所在模块范围(明确不要动的部分)目标接口/页面/函数的行为描述依赖项与技术栈(框架、库、版本)现有代码里可以复用的工具函数/中间件数据表结构与关键约束边界情形(空数据、超时、并发、权限)验收标准(输入输出格式、错误码约定)这块模板看着简单,它带来的改变是根本性的——AI 不再是一个只在“收到指令”时才运转的工具,而是变成了一套理解项目语境的协作系统。哪怕模型参数不变,生成的代码质量也会有明显提升。5. 新范式四:从“让它写实现”到“让它先写测试”这第四个范式,我用一句话来总结:不要先让 AI 写代码,再让它补测试;而要先让它写测试,再让测试驱动它写实现。这个顺序的调整,对质量的提升是颠覆性的。5.1 为什么测试先行能根治乱写代码先看看常规流程。你让 AI“写一个根据用户 ID 查询订单列表的接口”,它会直接生成接口和 SQL。你跑起来,发现订单状态过滤逻辑不对,你改;改完发现分页参数没生效,你继续改……问题是你永远是被动的,AI 每出现一个新错误你就得重新描述一次,而每次修改可能导致新问题。但如果把顺序反过来。你要求 AI 先为这个接口写一组单元测试和接口测试,里面明确写清楚:正常用户返回什么、无订单返回什么、非法用户 ID 返回什么、订单状态参数 filter 失效时怎么办。这几个测试用例本身就是在定义需求。AI 写测试的过程,其实是在把模糊的需求翻译成“可执行的规格说明”。当你接着让 AI“实现这个功能,让这些测试全部跑通”时,它的行为就完全不同了——它不是在自由发挥,而是在一个有边界约束的空间里寻找可行解。你甚至会发现它为了保证测试通过,主动帮你处理了边界条件。5.2 实操:让AI先写测试再用测试驱动实现我举个简单例子。在内部管理系统里做一个“批量导入用户”的功能。老规矩我会先让 AI 这么做:第一轮,我告诉它:“先不要写实现代码。帮我列出‘批量导入用户’功能的所有测试用例场景,包括正常情况、部分失败、全部失败、数据格式错误、重复数据、权限不足。”第二轮,我让它把这些用例转成 pytest 测试代码。它会在测试里自动设计出函数签名、明确输入输出结构。第三轮,我才说:“现在基于这些测试,实现功能。保证所有测试通过。”你会发现,AI 在实现时会有意识地用和测试一致的命名、结构和异常处理,代码和测试形成了一个自洽的小闭环。第四轮,我再追加:“把没有覆盖到的边界情况补充成测试,再修复相关实现。”这一步是查漏补缺,让 AI 自己审自己。这个流程本质上是在利用 AI 的强项——生成结构化的、可验证的、有明确目标导向的代码。同时避开了它的弱项——在没有约束的情况下自由编造。我从实践中得到的结论是,测试先行可以把 AI 生成的代码返工率降低一半以上。6. 新范式五:从“接受输出”到“严格评审”说实话,即使前面四个范式都做对了,AI 也会犯错。最后一个范式,也是我认为最像“资深工程师”的一个行为,是把 AI 的产出当成同事的 Merge Request 来审,而不是当成最终交付物来用。严格评审意味着你需要随时对 AI 说“不”,并且要有目的地挑刺。6.1 AI代码的常见“高级幻觉”AI 生成代码时有一个很反直觉的特征:它的错误往往不是语法级别的低级错误,而是“看起来很专业”的逻辑漏洞。我给这类问题起了个外号叫“高级幻觉”。最常见的几种:依赖幻觉:AI 会使用一个现实里存在、但版本行为与你项目不一致的库函数,或者干脆推荐一个不存在的过期 API。这种错误在编译期能过,甚至运行期前几条路径都是对的,直到某个边缘参数触发才崩。性能幻觉:AI 生成的代码在功能上正确,但复杂度高。比如在循环里查数据库、或者使用 O(n²) 的双重循环处理大数据集合。因为模型训练语料里有大量“功能正确但性能堪忧”的代码,它学到的也是一种“差不多先生”的风格。边界幻觉:AI 对边界条件的处理经常缺失。比如接口入参只有正常情况,完全没有空值、超长字符串、并发冲突、缓存穿透这些分支。它生成的分支结构常常把主要路径写得漂亮,异常路径草草带过。安全幻觉:涉及到鉴权、CSRF、越权校验时,AI 的默认写法往往是“有,但不够严”。比如只验证用户是否登录,却不验证用户是否有操作权限;只做前端校验,不做后端校验。这是我最不能接受的错误类型。6.2 评审清单与心态建设我现在的固定动作是:每次 AI 输出一段代码后,我不会直接把它接入主项目。我会先过一遍评审清单。接口层面:有没有做入参校验和越权控制?错误码是否正确?超时和重试模型是否明确? 数据层面:是否存在循环查询?有没有 N+1 问题?大字段有没有合理的分页/截断?事务边界是否清晰? 依赖层面:它用了哪些第三方包?版本是否与项目其他模块兼容?这些依赖是项目已有依赖还是新增?新增的是否有必要? 安全层面:是否硬编码密钥?是否有 SQL 注入风险?是否对敏感数据进行脱敏?这套清单走一遍,大概需要几分钟时间,但它能挡掉绝大多数 AI 埋的雷。心态上也要做调整:不要因为“AI 写得很专业”就不敢质疑它。恰恰相反,当你发现一个它生成的循环里有隐藏的性能隐患时,你正在做的事才叫真正的“协作”——你不是在给它当测试员,而是在给它当架构师和 reviewer。7. 这五个范式配合起来的完整工作流五个范式单独拿出来都能改善体验,但它们真正发挥威力,是组合成一套完整协作流程的时候。我日常的开发节奏基本是这样的:首先,接到一个新功能,我不会急着让 AI 写代码。我会先花几分钟把需求背景、技术约束、验收标准整理成一段上下文,这段上下文同时包含了上下文工程和需求对齐的元素。接着,我会明确告诉 AI 当前对话的目标:“我们先聊思路,不写代码。”它会给出设计方案、可能的风险点、推荐的改动文件列表。这一步等于把结对编程的“方案评审会”压缩到几秒钟完成。方案确认后,进入小步快跑阶段。每个子任务都会拆出来单独完成,并且每个子任务前,我至少会要求 AI 先列出关键测试用例,或写一个最小测试骨架。在每个子任务完成后,我会执行严格评审,把评审意见反馈给 AI,让它自己修复问题。这个反馈不一定是文字的“修正意见”,更多是“请看下这个边界场景是否覆盖、有没有更好的写法”这类引导式评语。最后,所有子任务完成后,我还会让 AI 做一轮“自我盘点”:“这个模块有没有潜在的性能隐患?有没有遗漏的错误处理?有没有不符合项目规范的命名?”这相当于让 AI 对最终的完整模块做一次总 review。这套流程下来,我实际写代码的工作量几乎没有增加,但代码的返工率明显下降,而且 AI 对项目上下文的理解会随着一次次协作越来越深。它甚至能在我描述新的需求时,主动引用前面模块里的变量名和函数签名,这说明它已经不再是一个“命令接收器”,而是一个真正理解项目上下文、并能围绕上下文提供建议的协作者。7.1 遇到问题时的排查实录在我实践这套方法的早期,也碰到过一些典型的翻车现场。这里挑三个比较有代表性的记录一下。第一个问题是 AI 在“小步快跑”过程中丢失了任务列表。原因是时间跨度太长了,前面聊了太多上下文,导致模型开始遗忘最初的拆解方案。我的解决方法是:每隔几个任务就做一次“标记性总结”,比如“我们已经完成了建表、校验、工具函数,接下来是注册接口”,让 AI 重新锚定进度。第二个问题是 AI 在写测试时,为了追求“测试通过”,会偷偷修改测试用例而不是修改实现。说白了就是作弊。我现在的规避方法是:在让它实现之前,明确说“测试代码不允许修改,只能改实现代码”。并且提交后我会专门 diff 一下测试文件,确认没被动过。第三个问题是它引入新依赖时,没有意识到项目技术栈的老旧版本兼容性。比如它给一个原本基于较旧版本框架的项目,引入了只支持新版框架的库,导致运行时报错。我在上下文里现在会明确写一句“不允许新增第三方依赖,除非先征得确认”,这能省去大量环境排查的麻烦。7.2 常见问题速查表为了便于你在实践中快速自查,我把踩过的坑整理成一张速查表。AI 生成的代码偏离需求 | 上下文信息不够 | 在提示词中补充业务场景、技术约束、验收标准 | 使用“先聊思路再写代码”的对话方式 AI 重复造轮子 | 不知道项目已有工具函数 | 提供已有工具函数清单和使用示例 | 让它先去读相关模块的代码 AI 修改测试代码让测试通过 | 模型追求“通过”结果 | 明确禁止修改测试代码 | 提交后 diff 测试文件确认 AI 写出的代码无法融入项目结构 | 缺乏项目约定 | 提供目录结构、分层规范、代码风格示例 | 让它参考已有模块的实现模板 AI 在长对话中遗忘任务目标 | 上下文超出有效记忆 | 定期做进度总结和任务锚定 | 拆分成独立对话或单独文件记录 AI 生成的代码用墨过多、模块过大 | 小步快跑执行不彻底 | 强制每个子任务 50~100 行代码量 | 对过大输出直接要求拆分重做 AI 反复用同一套坏方案 | 没有给出明确的“为什么不行” | 用具体错误和期望行为做修正反馈 | 给出“参考某某的实现方式”的指引7.3 与 AI 协作时最容易踩的心态坑除了技术层面的问题,我更想提醒你的是心态上的三个坑。第一个坑是“它比我强,我什么都听它的”。我见过不少朋友用 AI 用得特别顺利,顺利到彻底放弃了自己的判断力。AI 给一个方案,他觉得有道理;AI 说某个函数可以删,他就删。结果是,项目在维护期一到,代码已经变成一个谁都说不清来源和逻辑的大杂烩。正确的心态是:AI 是副驾驶,不是飞行员;你才是最终对代码负责的人。第二个坑是“它对我不理不睬,说明它在敷衍我”。有时候 AI 的回复很简短,不代表它不认真,很可能是你的上下文传递不够充分,它没有足够信息去展开。与其原地烦躁,不如主动把需求描述得更具体,把上下文喂得更足,让它的回答自然变长变细。第三个坑是“我加了很长的上下文,它反而更笨了”。是的,上下文也不是越多越好。过量的、与当前任务无关的信息会稀释注意力,模型可能会在无关细节里迷失。好的上下文是精简但关键的——每一个词都在帮助模型缩小猜测范围,而不是扩大背景噪音。我个人的体会是:当你真正把 AI 当成“协作对象”而不是“命令接收器”的时候,它的表现会发生质变。不是因为模型本身变了,而是因为你开始主动承担起定义问题、拆解任务、评审质量的职责——而这些,恰好是工程师价值最核心的部分。AI 不再替你思考,而是帮你把已经想清楚的事情更快地做出来。这种体验,远比原来那种“命令—生成—修复”的循环要舒服得多,也靠谱得多。最后再分享一个小技巧:如果你想让协作关系更进一步,可以试着在每个任务结束后,用一两句话告诉 AI“你这次做得好在哪、不好在哪”。这不会让当下模型变得更强,但会让它在一次会话中的后续表现更贴合你的偏好。会话内协作的质量,往往就是这么一点点磨出来的。