Skip to content

Vibe Coding 怎样写好提示词

提示词不是咒语,是对齐工具。写得好,AI 是你的 senior engineer;写得烂,AI 是你的 junior intern 还不敢提问。


一、核心原则:先对齐,再动手

Section titled “一、核心原则:先对齐,再动手”

Vibe coding 最大的陷阱是”说完需求就转身”。你不会对一个新来的同事说”帮我写个导出功能”然后走开,AI 也一样。

焚诀模板(直接复制进你的 CLAUDE.md / .cursorrules / AGENTS.md):

在我们开始之前:
1. 先用你自己的话说说你理解的——我要解决什么问题、交付物是什么。
标出你拿不准但自己做了假设的地方。如果你觉得有更好的技术方案,直接说,我来决定。
2. 然后向我提问——每次最多 3 个最关键的问题,直到你对以下三点有 100% 的把握:
- 我真正想要达成的目标是什么(而不是我字面上说的)
- 有哪些我没说出口的约束或偏好(技术栈、性能要求、不能动的部分)
- 你计划怎么实现——核心思路是什么、为什么选这个方案
3. 在没有得到我明确的「可以开始」之前,不要写任何代码或修改任何文件。

这个模板把一次性的”扔需求”变成了双向确认。根据 Anthropic 的官方实践,让 AI 先复述需求再动手,代码错误率下降 40% 以上。

示例:不对齐 vs 对齐

❌ 不对齐:

“帮我加一个用户搜索功能。”

AI 直接开写,结果用了前端模糊匹配,你的数据量在 100 万条,页面卡死。

✅ 对齐后:

“我要加一个用户搜索功能。数据量在 100 万左右,用户表在 PostgreSQL。搜索需要支持拼音和模糊匹配,但首屏必须在 200ms 内返回。你先说说你的方案,我再决定。”

AI 回复:

“理解:你需要一个高性能的用户搜索,支持拼音 + 模糊匹配,100 万数据量,200ms 响应。

方案:PostgreSQL 用 pg_trgm + 拼音映射表做后端搜索,前端用 debounce 300ms + loading 态。或者上 Elasticsearch,但会增加部署复杂度。

问题:

  1. 你的 PostgreSQL 版本是多少?pg_trgm 在 9.1+ 才有。
  2. 用户名字段是否已经有索引?
  3. 拼音映射是实时生成还是预计算?”

你回答完三个问题,AI 再动手,结果一次到位。


好的提示词由三层构成,缺一不可。少了任何一层,AI 都会做假设,而假设是 bug 的温床。

AI 不知道你的环境。你不说,它就猜。猜错是常态。

必须包含的信息

  • 语言和框架(“用 Python 3.11 + FastAPI”)
  • 已有代码的位置(“相关代码在 src/services/auth.py”)
  • 不能动的部分(“不要改 UserModel 的字段定义”)
  • 代码风格(“遵循项目已有的 PEP 8,类型注解必须写”)

示例:

我们在写一个电商订单模块,基于 Python 3.11 + FastAPI + SQLAlchemy 2.0。
约束:
- 数据库用 PostgreSQL,已有模型定义在 src/models/order.py,不要改字段
- 所有新函数必须有类型注解和 docstring
- 错误处理统一用自定义的 AppException,不要直接抛 HTTPException
- 单元测试用 pytest,覆盖率不能低于 80%

不要给实现方案,给用户故事。让 AI 自己推导实现方案,它的方案往往比你预想的更合理。

反模式 vs 正确写法:

❌ 给实现方案:

“写一个函数,用 Redis 缓存用户订单,缓存 5 分钟,key 是 order:user_id。”

✅ 给用户故事:

“用户在我的订单页面需要看到最近 30 天的订单列表。数据来自 PostgreSQL 的 orders 表。这个页面访问量很大,需要保证首屏加载在 300ms 以内。你觉得怎么优化?”

AI 可能会给出比你更完整的方案:Redis 缓存 + 数据库索引优化 + 分页 + 预加载关联数据。

复杂需求要拆分:

一个 prompt 解决一个原子问题。不要一次让 AI 做五件事。

❌ 过大的 prompt:

“帮我写一个完整的用户系统,包括注册、登录、找回密码、OAuth、权限管理、审计日志。”

✅ 拆分为多个 prompt:

  1. “先写注册接口,需求:邮箱 + 密码,密码要 bcrypt,发验证邮件用 SMTP。”
  2. 注册验证通过后:“基于刚才的注册接口,写登录接口,返回 JWT,token 有效期 24 小时。”
  3. 登录完成后:“写 OAuth2 的 Google 登录集成,复用已有的 User 模型。”

每一步都小、可验证、可回滚。

AI 默认写 happy path。如果你不提醒边界情况,它就不处理。

标准问法:

“这个接口有哪些边界情况需要处理?先列出清单,我再决定哪些必须处理。”

示例:订单查询接口

你让 AI 列边界情况,它可能回复:

  1. 用户不存在 → 404
  2. 用户存在但没有订单 → 200 返回空数组
  3. 分页参数非法(page=-1)→ 400
  4. 时间范围超过 30 天 → 400 或自动截断
  5. 数据库连接超时 → 500 + 日志
  6. 并发查询同一用户 → 缓存击穿风险

你勾选 1、2、3、5 必须处理,AI 再动手写代码。这样你得到的是 production-ready 的代码,不是 demo。


❌ 烂提示:

“重构这个文件。”

✅ 好提示:

“这个文件是 3 年前写的,现在需要重构。目标:

  • 把 200 行的 process_order 函数拆成 5 个以内的小函数,每个不超过 30 行
  • 消除所有 any 类型,补全 TypeScript 类型
  • 把回调改成 async/await
  • 保留所有现有行为,不要改业务逻辑
  • 写完后对比原函数的输入输出,确保一致性

文件路径:src/legacy/order-processor.ts

先给出重构计划,我确认后再动手。“

❌ 烂提示:

“给这个函数写测试。”

✅ 好提示:

“给 src/services/payment.py 里的 process_refund 函数写 pytest 单元测试。

要求:

  • 覆盖成功路径、金额非法、订单不存在、重复退款、网络超时
  • pytest-mock mock 外部 API 调用,不要真的发请求
  • 每个测试用例必须有 Arrange-Act-Assert 三段注释
  • 测试数据用 fixture,不要硬编码在测试函数里
  • 运行 pytest src/services/test_payment.py -v 必须全绿

先给我测试用例清单,我确认后再写代码。“

❌ 烂提示:

“这段代码报错了,帮我看看。”

✅ 好提示:

“生产环境日志显示这个接口偶发 500 错误,大约 1% 的请求会触发。

错误栈:

KeyError: 'user_id'
File 'src/api/orders.py', line 45, in get_order
user_id = request.headers['user_id']

相关代码:

src/api/orders.py
@router.get("/orders/{order_id}")
def get_order(order_id: str, request: Request):
user_id = request.headers['user_id']
...

上下文:

  • 这个接口通过 Nginx 反向代理,Nginx 会把 X-User-Id 头转成 user_id
  • 但直接访问(绕过 Nginx)时没有这个头
  • 需要兼容两种情况:有 user_id 头时用 user_id,没有时用 X-User-Id,都没有时 401

先分析根因,给出修复方案,我确认后再改代码。“

❌ 烂提示:

“写一个登录表单。”

✅ 好提示:

“写一个 React 登录表单组件,路径 src/components/LoginForm.tsx

技术栈:React 18 + TypeScript + Tailwind CSS + React Hook Form + zod

功能:

  • 邮箱 + 密码输入,邮箱要正则验证,密码最少 8 位
  • 提交时调用 POST /api/auth/login,用 axios
  • 登录成功跳转到 /dashboard,失败显示错误信息(toast 用 sonner
  • 加载状态:按钮显示 spinner,禁用输入
  • 记住我:勾选后把 token 存 localStorage,不勾选存 sessionStorage

设计约束:

  • 使用项目已有的 ButtonInput 组件(在 src/components/ui/
  • 表单宽度最大 400px,居中,移动端适配
  • 不要引入新的依赖

先给我组件的 props 接口定义和状态管理思路,我确认后再写完整实现。“


四、工具适配:不同工具的提示词写法

Section titled “四、工具适配:不同工具的提示词写法”

Claude Code 支持 CLAUDE.md 放在项目根目录,作为全局系统提示。这是 vibe coding 中最重要的配置文件。

CLAUDE.md 最佳实践:

# 项目规范
## 技术栈
- Python 3.11, FastAPI, SQLAlchemy 2.0, PostgreSQL
- 前端: React 18, TypeScript, Tailwind
## 代码规范
- 所有函数必须有类型注解
- 错误处理统一用 `AppException`
- 不要直接修改 migration 文件
## 工作流
1. 动手前先复述需求,列出你的理解
2. 复杂任务先给方案,我确认后再写代码
3. 每次修改后运行相关测试,确保通过
4. 提交信息用 Conventional Commits 格式

Claude Code 的 /ask 模式适合先讨论方案,/code 模式适合执行。养成习惯:复杂任务先用 /ask,确认后再切 /code

Cursor 用 .cursorrules 文件。支持 JSON 格式,可以定义多组规则。

示例 .cursorrules:

{
"rules": {
"naming": "变量用 camelCase,类用 PascalCase,常量用 UPPER_SNAKE_CASE",
"testing": "所有新函数必须配单元测试,用项目已有的测试框架",
"documentation": "公共 API 必须有 JSDoc / docstring",
"error_handling": "不要吞异常,所有异常必须记录日志",
"imports": "禁止循环依赖,工具函数优先放 `src/utils/`"
}
}

Cursor 的 @ 符号可以引用文件和代码块,善用 @src/services/auth.ts 来限定上下文,比粘贴代码更高效。

Aider 是纯终端工具,没有 GUI。它的优势是自动 git commit 每个 AI 修改。

Aider 提示词技巧:

  • /ask 模式讨论方案,不修改文件
  • /code 模式执行修改
  • 复杂任务分多次对话,每次聚焦一个文件
  • aider --commit-prompt "自定义提交信息格式" 规范 commit message

示例 Aider 对话:

> /ask 我需要给订单系统加缓存。订单表 100 万数据,查询频率高。
> 你觉得用 Redis 还是 PostgreSQL 的物化视图?各自优缺点是什么?
[AI 分析两种方案的优劣]
> 选 Redis。用 aider 改 /src/services/order.py,加 Redis 缓存层,缓存 5 分钟。
> 注意:不要改 OrderModel 的定义,缓存 key 用 `order:list:{user_id}`。
[AI 修改代码并自动 commit]

以下这些写法会让 AI 输出质量断崖式下跌,坚决避免。

❌ “优化一下这个函数” ❌ “看看这里有没有问题” ❌ “改得更好一点”

AI 不知道”优化”是指性能、可读性还是减少代码量。给它明确的验收标准。

✅ “把这个函数的循环复杂度从 15 降到 10 以下,保持现有行为不变。“

❌ “重写整个模块,加测试,改文档,再部署”

AI 的上下文窗口有限(即使 200k token,有效注意力也集中在前面)。任务越多,遗漏越多。

✅ 拆成 4 个独立的 prompt,每个完成后验证再下一个。

❌ “写一个用户注册接口”

AI 可能用明文存密码、不做邮箱验证、返回敏感字段。你必须说不要做什么

✅ “写用户注册接口。约束:密码必须 bcrypt,不返回 password_hash,邮箱要发验证链接。“

这是人的问题,不是 AI 的问题。AI 生成的代码必须:

  1. 自己读一遍,理解逻辑
  2. 运行测试,确保通过
  3. 检查边界情况是否处理
  4. 确认没有引入新依赖(除非批准)

vibe coding 不等于无脑复制粘贴。

每次新开对话,AI 就失忆了。不要在对话 A 里讨论架构,对话 B 里让 AI 实现,然后抱怨它没按架构来。

解决方案:

  • CLAUDE.md / .cursorrules 存持久上下文
  • 长任务用一个对话完成,不要切来切去
  • 关键决策(架构选型、接口定义)写成文档,让 AI 读取

在 AI 写实现代码之前,让它先列出所有测试用例。这有两个好处:

  1. 你确认测试用例覆盖了所有场景,AI 就不会漏
  2. AI 写代码时以测试用例为目标,质量更高

Prompt:

“在写实现之前,先列出这个函数的所有测试用例,包括 happy path 和边界情况。我确认后你再写代码和测试。“

不要接受 AI 的第一个方案。让它给出 2-3 个选项,你选。

Prompt:

“这个需求有两种实现方式:A 用数据库触发器,B 用应用层事件。各写一段伪代码对比优缺点,包括性能、可维护性、扩展性。我选方案后你再写完整实现。“

让 AI 在提交代码前自检,能发现大量低级错误。

Prompt:

“写完后不要立即提交。先自检以下清单:

  • 所有变量都有明确含义,没有单字母命名(除了 i, j 循环变量)
  • 没有 console.log / print 调试语句
  • 所有外部调用都有错误处理
  • 没有硬编码的魔法数字或字符串
  • 类型注解完整,没有 any
  • 检查完毕后告诉我结果,有问题的先修复再提交。“

Aider 自动 commit 每个修改,但 Cursor/Claude Code 不会。养成习惯:让 AI 在一个独立的 git 分支工作

Prompt:

“基于当前代码创建一个分支 ai/feature-login,所有修改在这个分支上做。完成后给我 diff 概览,我确认后再合并。“

提示词本身也可以用 AI 优化。把草稿给 AI,让它按三层结构重组。

Prompt:

“帮我优化这个提示词,按’技术上下文 + 功能需求 + 边界情况’三层结构重组,删除模糊表达,补充具体的验收标准。“


假设你要用 vibe coding 实现一个”订单导出 Excel”功能,完整的提示词流程如下:

Step 1:对齐需求

我要加一个订单导出功能。用户在订单列表页点击"导出",下载一个 Excel 文件,包含最近 90 天的订单。
约束:
- 后端 Python + FastAPI,前端 React
- 订单表 50 万数据,不能一次全查出来
- Excel 用 openpyxl 生成,不要引入新依赖(已有)
- 导出是异步的,用户点完显示"正在生成",好了通知下载
你先复述理解,再列出边界情况,最后给我实现方案。

Step 2:确认方案

AI 给出方案:

  • 后端:Celery 异步任务,分批查询(每次 1000 条),生成 Excel 存 S3/本地,返回任务 ID
  • 前端:轮询任务状态,完成后自动下载
  • 边界:大数据量超时、用户重复点击、生成失败重试

你确认后说”可以开始”。

Step 3:分步实现

先写后端 Celery 任务,路径 `src/tasks/export_orders.py`。
要求:
- 分批查询,每批 1000 条,用 yield 减少内存
- Excel 写入用 streaming,不要全部加载到内存
- 任务完成后更新数据库记录,存文件路径
- 失败时记录日志,前端可查询失败原因
写完后运行 `pytest src/tasks/test_export_orders.py -v`,必须全绿。

后端完成后:

再写前端下载组件,路径 `src/components/ExportButton.tsx`。
要求:
- 点击后调后端接口获取任务 ID
- 用 setInterval 轮询状态,3 秒一次,最多 5 分钟
- 状态:pending → processing → completed(自动下载)/ failed(显示错误)
- 加载中禁用按钮,防止重复点击
- 用项目已有的 Button 和 Loading 组件

Step 4:集成测试

写一个端到端测试,模拟用户点击导出 → 等待生成 → 下载文件 → 验证 Excel 内容。
用 pytest + Playwright,测试数据用 fixture 准备 100 条订单。

Step 5:代码审查

review 刚才的所有修改,按以下清单检查:
- 是否有 SQL 注入风险?
- 大文件下载是否做了流式传输?
- 错误处理是否完整?
- 是否有性能瓶颈?
- 测试覆盖率是否达到 80%?
有问题直接修复,没问题告诉我。"

写好 vibe coding 提示词,记住这 8 个字:具体、分层、迭代、验证

维度烂提示好提示
目标”做个搜索""用户搜索,支持拼音模糊匹配,200ms 响应”
约束不说”不要改 UserModel,用已有 Redis,pytest 覆盖 80%“
范围”重写整个模块""先重构 process_order,拆成 5 个函数”
边界不提”先列边界情况清单,我确认后再写”
验收”看看行不行""运行测试全绿,复杂度降到 10 以下”

最后一条建议:把这篇的核心原则写成你自己的 CLAUDE.md.cursorrules,每次打开项目 AI 就自动加载。提示词工程的最高境界,是你不再需要想提示词技巧——因为规则已经刻进了 AI 的默认行为里。