一、引言
你可能有过这样的经历:明明已经详细描述了需求,AI 却返回了一段与期望相去甚远的代码;或者 AI 生成的代码虽然基本符合功能要求,却总是缺少关键细节,需要反复修改才能使用。有的时候还修改不对,最终需要推倒重来。其实可能不是 AI 能力有问题,更可能的是使用方法不对。本文会从 PM 的视角出发,分析为什么会出现这种情况,并提供实用的解决方案,帮助你更有效地利用 AI 进行原型开发与验证。
二、为什么 AI 会“乱写”
2.1 AI 不理解你的需求
AI 不会读心术。虽然它功能强大,但依然依赖于你提供的需求描述来理解任务。当 PM 使用过于宽泛或含糊的描述时,AI 会基于自己的“理解”填补细节空白。比如,当你说“帮我做一个登录页面”时,AI 必须自行假设:需要哪些表单字段?实现什么样的校验逻辑?页面设计风格是什么?这些自行假设的细节很可能与你实际期望的大相径庭,导致生成的代码与你的真实需求不符。
2.2 视角差异
PM 习惯从用户体验和业务价值角度思考,而 RD 则从技术实现和代码结构出发。这种思维方式的差异导致:PM 更关注“做什么”而忽略“怎么做”,倾向于使用业务术语而非技术术语,描述问题的方式往往从结果出发,而非从实现路径出发。
以下是一个典型的思维差异示例:
PM 思维:“我需要一个能展示用户购买历史的页面,可以按月筛选,并显示消费总额。”
RD 思维:“需要实现一个用户订单历史组件,使用 Redux 管理状态,通过 GraphQL 查询按月分组的订单数据,实现过滤逻辑,计算每月总额并在 UI 中展示汇总数据。”
AI 生成优质代码需要明确的技术约束和参数,这恰恰是 PM 的技能盲区。当缺乏这些关键技术参数时,AI 往往会生成“看似正确”但在技术实现上存在深层次问题的代码:代码可能能够运行,但缺乏可扩展性和可维护性;可能没有考虑性能优化和边界情况处理;可能使用过时或不适合项目长期发展的技术方案。
2.3 上下文缺失
AI 对项目的了解仅限于你明确告诉它的内容。它无法自行查看你的整个代码库(Agent 除外),理解你公司的设计规范,知道你团队的编码约定,或了解你产品的历史背景。
这种上下文缺失导致 AI 生成的代码虽然功能上可能正确,但可能不符合项目的技术标准和风格规范。对 PM 来说这个问题尤其棘手,因为可能不完全了解所有技术标准和规范细节,难以识别出这些不符合项目要求的地方,导致后续集成时出现各种兼容性问题。
这三个因素相互影响,导致开发 Prototype 时的困境。理解这些根本原因后,我们就能有针对性地解决“AI 乱写”问题。接下来,我们将探讨具体的解决方法。
三、解决 AI 乱写的方法
在解决方案之前,我们已经理解了为什么 AI 会“乱写”——主要源于三个核心问题:需求不明确、视角差异,以及上下文缺失。现在,我们可以针对性地解决这些问题。
3.1 提示词优化
假期刚好在用 Cursor 克隆一个项目,需要修改配置文件,我已经沟通且修改了一些比如 Supabase 的内容,我不知道 Redis 是不是也要修改,这时候发生了下面的对话。
我 Add to Chat 了对应的代码,并说:“env 文件里的我需要处理吗?”想表达的意思是我还需不需要修改 Redis 啊?

Cursor 没明白<处理>其实是我要问是不是<修改>,因为之前上下文的交互,我会天然以为他能理解,结果并没有,最后是我做了澄清,然后解决了问题。

这个小插曲其实很能说明问题 —— 不是 AI 能力不行,而是我没有“说人话”。AI 不像人类同事,没法通过经验和语境猜测我们真正的意图。当 PM 提供模糊需求时,AI 只能自行填补空白,结果往往偏离我们的预期。那么,如何让 AI 更好地理解我们的意图呢?答案是结构化需求描述。因为结构化的描述可以给到更多的需求信息,也限制了 AI 的“胡乱补全”,这里有两种实用方法:
方法一:结构化模板
想让 AI 帮你写好代码,最好用结构化模板来描述需求。这样做有两个好处:一是逼着我们把脑子里模糊的想法变成具体的细节,二是帮助我们不仅说明“要做什么”,还要说明“怎么做”。用这种方式提供的明确指导大大减少了 AI 需要自行猜测的空间,也就一定程度上避免了 AI “乱写”的问题。下面是一个实用的模板,你可以直接套用:
| |
比如当我们要做一个登录页面的时候,使用不同提示词描述的效果👇
| 提示词 | 结果 | |
|---|---|---|
| 普通提示词 | 做一个登录页面 | ![]() |
| 结构化提示词 | 展开查看【需求背景】业务目标:提高用户账户安全性并简化登录流程 用户痛点:现有登录流程繁琐,缺乏安全性提示,用户经常忘记密码 成功指标:登录成功率提升15%,密码重置请求减少30% 【功能需求】 核心功能: 邮箱/用户名输入字段 密码输入与实时强度检测 “记住我”选项保存登录状态 忘记密码重置流程 第三方账号快速登录选项 用户流程: 用户访问登录页面 输入邮箱/用户名和密码 可选勾选“记住我” 点击登录按钮 系统验证凭据并反馈结果 交互反馈: 输入框即时验证格式,显示错误提示 密码强度实时可视化展示 登录按钮点击后显示加载状态 验证失败时显示具体错误信息和解决建议 成功登录后重定向到首页 边界场景: 用户多次登录失败时的账户保护机制 不同设备同时登录的会话管理 登录超时处理 浏览器自动填充兼容性 【技术参数】 技术栈:React 18 函数组件,TypeScript 组件库:Material UI 表单组件 状态管理:Formik 处理表单状态 验证库:Yup 实现表单验证 认证方案:JWT 认证,支持刷新令牌 数据模型: User: { id, email, username, passwordHash, lastLogin } Session: { id, userId, token, expiresAt, device } 集成点: 认证 API:/api/auth/login, /api/auth/refresh 第三方登录:Google OAuth, Facebook Connect 参考实现: 现有注册页面组件结构 设计系统的表单交互规范 【验收标准】 功能验收: 所有表单字段验证正确工作 密码强度检测准确 “记住我”功能在浏览器关闭后依然生效 第三方登录成功将用户重定向到首页 性能要求: 页面加载时间 < 1.5 秒 登录处理响应时间 < 1 秒 兼容性: 支持 Chrome、Firefox、Safari、Edge 最新两个版本 响应式设计,适配移动端和桌面端 支持键盘导航和屏幕阅读器 | ![]() |
可以直接体验或查看代码,其实仅仅从前端展示的样子就能看出来优劣了。以及不要一句话描述需求,你的同事都猜不出来你要的是啥,更何况是没有上下文的AI。
方法二:让 AI 帮你写需求(套娃法)
上面的模板虽然好用,但对不太懂技术的 PM 来说填起来可能有点吃力。特别是“技术参数”那块,可能完全不知道该写什么。这时,我们可以走个捷径:把最初的粗略想法告诉高级 AI 模型(比如 Claude 3.7),让它帮你转换成结构化需求!
具体怎么操作:
- 先把你的原始想法写下来
- 用下面这个提示词让 AI 帮你转换
- 检查一下 AI 生成的结构化需求,做些必要的调整
- 把这个结构化需求用于 AI Coding
转换提示词:
| |
可以拿一个真实的 case 来试试。
| 详细内容 | 结果 | |
|---|---|---|
| 最初的想法 | 做一个用户可以管理自己订阅的页面,可以看到当前状态,进行续订和升级操作。 | ![]() |
| AI转换后 | 转换后提示词用户订阅管理技术需求文档【需求背景】 业务目标:提供一个集中式界面,让用户便捷地管理其所有订阅服务,提高订阅转化率和续订率。 用户痛点:用户难以追踪多个订阅的状态、到期时间,无法方便地进行续订或升级,导致非主动流失。 成功指标:订阅续订率提升15%,套餐升级转化率达到8%,用户订阅管理相关的客服咨询减少30%。 【功能需求】 订阅总览 以卡片或列表形式展示用户当前所有订阅,包括订阅名称、类型、价格、状态(有效/即将到期/已过期)、到期日期 允许用户筛选和排序订阅(按状态、到期日期、价格等) 提供订阅消费总额统计和每月/年支出预估 订阅详情 点击单个订阅可查看详细信息,包括订阅历史、账单记录、自动续费状态 展示该订阅可用的所有权益和使用情况 显示当前套餐与其他套餐的对比信息 操作功能 续订流程:点击续订按钮→选择续订周期→确认支付方式→完成付款→展示成功状态和新到期日 升级流程:点击升级→展示可升级套餐对比→选择目标套餐→显示差价→确认→完成付款 自动续订管理:开启/关闭自动续订,设置提前提醒时间(默认7天) 订阅取消预约:允许用户提前设置到期不续,但保留随时反悔的选项 边界场景处理 处理降级请求时提供挽留策略(优惠券/折扣/免费延期等) 支持处理订阅支付失败/订阅恢复的状态通知和操作引导 针对即将到期(7/3/1 天)的订阅发送状态提醒和续订建议 订阅权益变更时的通知机制和处理方案 【技术参数】 技术栈推荐 前端:React/Vue 框架,配合 Redux/Vuex 状态管理 后端:REST API 架构,Node.js/Spring Boot 实现 数据库:主数据 MySQL,缓存 Redis,考虑分表存储历史订阅数据 支付集成:Stripe/PayPal API 用于处理续订和升级支付 数据模型设计 用户订阅表(UserSubscription): - id: UUID - userId: 外键关联用户 - planId: 外键关联订阅计划 - status: ENUM(active, expiring, expired, cancelled, payment_failed) - startDate: TIMESTAMP - endDate: TIMESTAMP - autoRenew: BOOLEAN - paymentMethod: VARCHAR - lastBillingDate: TIMESTAMP - nextBillingDate: TIMESTAMP - reminderDays: INT 订阅计划表(SubscriptionPlan): - id: UUID - name: VARCHAR - description: TEXT - price: DECIMAL - billingCycle: ENUM(monthly, quarterly, yearly) - features: JSON/TEXT - rank: INT (用于比较套餐层级) 订阅历史表(SubscriptionHistory): - id: UUID - subscriptionId: 外键关联UserSubscription - action: ENUM(created, renewed, upgraded, downgraded, cancelled) - fromPlanId: UUID - toPlanId: UUID - timestamp: TIMESTAMP - amount: DECIMAL - transactionId: VARCHAR 集成点 用户系统:获取用户信息和认证状态 支付系统:处理续订/升级交易,查询交易历史 通知系统:发送订阅状态提醒和操作确认 权限系统:验证用户对特定订阅的操作权限 分析系统:埋点跟踪用户行为和转化率 【验收标准】 功能测试点 所有订阅状态正确显示,且实时同步支付系统变更 续订流程可完整执行,支持多种支付方式 升级/降级能正确计算价格差异并完成套餐切换 自动续订设置成功后实际按设定执行 提醒通知按用户设置的时间准确推送 性能要求 订阅页面首屏加载时间 < 1.5 秒 订阅列表渲染 (10+ 项) 时间 < 500 ms 支付操作响应时间 < 3 秒 系统需支持每秒 100 次的订阅状态查询 兼容性标准 支持主流浏览器最新两个版本 (Chrome, Safari, Firefox, Edge) 响应式设计,兼容桌面及移动设备 (最小支持 320px 宽度) 支持 iOS 14+ 和 Android 8.0+ 适配暗黑模式和高对比度视觉模式 符合 WCAG 2.1 AA 级无障碍标准 | ![]() |
是不是感觉瞬间清晰了很多?原本模糊的需求被展开成了全面的规格说明,涵盖了 AI 需要的细节。
这种“套娃”方法有几个明显优势。首先,即使你不具备深厚的技术背景,也能创建出 AI 友好的需求文档,这对技术知识有限的 PM 来说非常友好。其次,AI 会自动帮你填补可能忽略的边界场景和技术考量,让需求更加全面。有了这些明确的指导方向,AI 生成的代码质量自然会高很多,不再需要频繁返工。你可以根据自身的情况灵活选择这两种方法,比如你对技术比较了解或你的项目有明确的技术栈,可以直接用模板;如果技术不是很熟,可以用套娃法,当然合并起来使用也完全没问题。关键是避免给 AI 过于模糊的指令,让它不得不自己“脑补”细节。
3.2 为 AI 提供上下文
当谈到使用 AI 去 coding 的时候,一个常被忽视但极其重要的问题就是上下文缺失。AI 可能很擅长单独编写功能,但如果不了解整个项目的架构和约定,它生成的代码往往难以与现有系统集成,甚至技术栈可能也有偏差。解决这一问题的关键是为 AI 提供充分的项目上下文。在不同场景下可以采取不同的策略。
场景一:初次接手项目或者展开一个新的对话
刚接手项目时,如果有 README、Cursor Rules 这类项目文档,直接把它们 @ 给 AI 是最省事有效的方法。AI 能快速了解整个项目的架构设计和代码规范,避免生成的代码和项目风格不匹配。
如果项目中还没有这样的文档,可以使用 Cursor 的 /Generate Cursor Rules 功能,它会自动分析项目并生成规则文件。假期在看「Suna」这个 agent 项目就试了一下,Cursor 直接生成了 4 个 rules 文件,包含了项目结构、LLM配置、数据库和身份验证、部署和环境配置的详细说明。将这些 rules 提供给 AI 后,它立即就能理解整个项目架构。
如果你使用的是其他 coding 工具,也可以先让 AI 浏览项目的关键文件,然后请它总结项目架构。这样 AI 就能建立起对项目的基本认知,后续生成的代码也更容易与项目集成。
| |
结果

场景二:实现具体需求
当你已经比较熟悉项目,在改实际需求的时候,就没必要每次都把整个项目结构告诉 AI 了。这时候直接把与当前需求相关的文件都 @ 出来就够了。
Cursor 的设计主管有这样的说明:
| |
意思就是在解决对应问题或者需求的时候,应该把具体的内容 @ 出来,也可以从控制台把 API 响应数据扒出来,这些都是非常好的方式,可以把 Cursor 的注意力集中在最相关的代码上。比如我在改 AI coding 订阅管理系统的时候,就使用了这种方式:
| |
用这种方式就可以明确告诉 AI 可以在哪里看什么,要怎么增加功能,以及最重要的,先让 AI 别写代码,先来聊方案。这一点是避免 AI 乱写的重要技巧——先确认方案再写代码,可以大大减少返工和调整的时间。
四、总结
AI 在编程过程中“乱写”的问题并非源于能力不足,而是使用方法不当。本文分析了三个核心原因:需求描述不明确、PM 与开发视角的差异、以及项目上下文的缺失。针对这些问题,我们提供了两个解决方案:
首先,通过结构化需求描述,可以大幅提升 AI 的理解准确度。无论是直接使用结构化模板详细说明业务目标、功能需求、技术参数和验收标准,还是采用"套娃法"让 AI 帮你将模糊想法转化为清晰需求,都能显著减少 AI 需要“脑补”的空间,从而降低代码偏离预期的可能性。
其次,为 AI 提供充分的项目上下文同样至关重要。在初次接手项目或展开新对话时,可以直接把 README 或 Cursor Rules 这类项目文档分享给 AI,或使用 “/Generate Cursor Rules” 等功能自动分析项目结构;而在实现具体需求时,则应该把与当前需求相关的文件都 “@” 出来,并坚持“先聊方案再写代码”的原则。这些方法能帮助 AI 更好地理解项目环境,生成与现有系统高度兼容的代码。
通过这些方法,PM 可以更有效地利用 AI 进行原型开发,减少不必要的返工,提高沟通效率。实践证明,AI 并非不能写好代码,关键在于我们是否能够“说人话”——用结构化、明确的方式表达需求,并提供足够的上下文信息。这样,AI 就能成为 PM 高效开发的得力助手,而不是“乱写”代码的困扰源头。



