程序员和 AI(人工智能)编程助手最常说的一句话,大概率是:
帮我看看这段代码哪里有问题。
这句话不是不能用,但它太省略了。AI 不知道代码运行环境,不知道预期行为,不知道实际报错,也不知道你希望它输出解释、修复方案、补丁代码,还是排查步骤。
好的 Prompt 不是“咒语”,更像一份简短的技术需求说明。它要把问题交代清楚,让 LLM(大语言模型)可以沿着正确方向推理,而不是靠猜。
一个好 Prompt 至少包含 5 件事
写给 AI 的技术问题,可以固定成一个结构:
背景:我在做什么,技术栈是什么,运行环境是什么。
目标:我希望解决什么问题,最终得到什么结果。
材料:代码、日志、配置、接口返回、数据库表结构等。
约束:不能改什么、必须兼容什么、性能或风格要求是什么。
输出格式:希望 AI 怎么回答,例如步骤、表格、补丁代码、测试用例。
用流程图表示,就是这样:
flowchart TD
A[描述背景] --> B[明确目标]
B --> C[提供材料]
C --> D[写出约束]
D --> E[指定输出格式]
E --> F[得到可检查的结果]
这 5 个部分不一定每次都写满,但调试、重构、代码审查这类任务,缺少其中任何一项都可能让结果跑偏。
通用 Prompt 模板
可以先记住这个通用模板,再按具体场景替换内容。
你现在扮演一名有经验的 {技术方向} 工程师。
背景:
- 项目使用:{语言 / 框架 / 数据库 / 中间件}
- 运行环境:{操作系统 / 版本 / 部署方式}
- 当前场景:{业务或技术背景}
目标:
- 我想要:{最终目标}
- 当前问题:{遇到的异常、性能问题、设计问题}
材料:
```{语言或日志类型}
{代码 / 日志 / 配置 / SQL / 接口返回}
约束:
- 不要改变:{不能动的接口、数据结构、兼容性要求}
- 必须满足:{性能、安全、可读性、测试要求}
- 优先使用:{项目已有库、框架惯例、代码风格}
请按下面格式回答:
- 问题判断
- 原因分析
- 修改方案
- 修改后的代码
- 需要补充的测试用例
这个模板的重点不是“扮演专家”,而是把上下文、目标、材料、约束和输出格式都写清楚。角色设定只能提供回答风格,真正决定结果质量的是信息是否完整。
## 场景一:让 AI 解释代码
很多时候,我们接手一段陌生代码,直接问“解释一下”会得到一段泛泛的说明。更好的做法是要求它按调用链、输入输出、副作用、异常分支来讲。
### 不够好的问法
```text
解释一下这段代码。
更好的问法
请解释这段 Python 代码,重点说明:
1. 函数的输入和输出分别是什么
2. 主流程分为哪几步
3. 哪些地方会产生副作用,例如写文件、改数据库、发请求
4. 哪些异常分支需要注意
5. 如果我要修改它,最容易影响哪里
代码如下:
```python
def sync_user(user_id, client, repo):
user = client.fetch_user(user_id)
if not user:
repo.mark_deleted(user_id)
return False
repo.save(user)
return True
AI 更容易给出这样的结构化结果:
| 关注点 | 应该得到的信息 |
|---|---|
| 输入 | `user_id`、外部客户端 `client`、数据仓库 `repo` |
| 输出 | 布尔值,表示同步是否成功 |
| 主流程 | 拉取用户、判断用户是否存在、保存或标记删除 |
| 副作用 | 调用外部接口、写入存储层 |
| 风险点 | 外部接口失败、`repo.save` 失败、删除标记是否符合业务语义 |
解释代码时,不要只要“中文翻译”。真正有用的是让 AI 帮你建立代码地图:它依赖什么、改变什么、失败时会怎样。
## 场景二:让 AI 排查报错
调试类 Prompt 最常见的问题是只贴一行报错。报错只是结果,不是完整上下文。要让 AI 排查问题,至少需要给出复现步骤、关键代码、完整日志和环境版本。
调试问题可以按这个调用过程组织信息:
```mermaid
sequenceDiagram
participant Dev as 开发者
participant App as 应用程序
participant Dep as 外部依赖
participant Log as 日志
Dev->>App: 执行复现步骤
App->>Dep: 调用接口 / 数据库 / 缓存
Dep-->>App: 返回结果或异常
App->>Log: 输出错误堆栈
Dev->>Dev: 对比预期行为和实际行为
调试 Prompt 模板
我遇到一个运行时报错,请帮我定位原因并给出修复方案。
环境:
- 语言:Python 3.11
- 框架:FastAPI 0.110
- 数据库:PostgreSQL 15
- 运行方式:本地启动,命令是 `uvicorn app:app --reload`
预期行为:
- 请求 `POST /users` 后创建用户,并返回用户 ID。
实际行为:
- 接口返回 500。
复现步骤:
1. 启动服务
2. 执行下面的 curl 命令
3. 查看控制台报错
请求:
```bash
curl -X POST http://localhost:8000/users \
-H "Content-Type: application/json" \
-d '{"name":"alice"}'
关键代码:
@app.post("/users")
def create_user(payload: UserCreate):
user = User(name=payload.name)
db.add(user)
db.commit()
return {"id": user.id}
错误日志:
sqlalchemy.exc.InvalidRequestError: Object '<User at 0x...>' is already attached to session '1' (this is '2')
约束:
- 不要改接口路径和返回格式
- 尽量保持同步写法,不要改成异步
请输出:
- 最可能原因
- 如何验证这个判断
- 推荐修改方式
- 修改后的代码
- 还需要补充哪些测试
这种问法让 AI 有足够证据判断问题,而不是根据一行错误信息猜测。
调试类信息可以按优先级准备:
| 信息 | 作用 | 缺失后的影响 |
|---|---|---|
| 环境版本 | 判断 API、依赖行为是否匹配 | AI 可能给出不兼容写法 |
| 复现步骤 | 确认问题如何触发 | 修复方案无法验证 |
| 预期行为 | 确认正确结果是什么 | AI 只能解释错误,不能判断业务是否正确 |
| 实际行为 | 描述偏差 | 排查方向不明确 |
| 完整日志 | 定位异常源头 | 容易把表层错误当根因 |
| 关键代码 | 分析调用链 | 只能给通用建议 |
## 场景三:让 AI 做代码审查
“看看代码有没有问题”太宽泛。代码审查要把检查维度列出来,例如正确性、并发、安全、性能、可读性、异常处理、测试覆盖。
### 代码审查 Prompt
```text
请对下面这段 Go 代码做代码审查。
审查重点:
1. 是否存在空指针、资源泄漏、并发问题
2. 错误处理是否完整
3. 是否有安全风险
4. 是否有性能明显不合理的地方
5. 命名和结构是否容易维护
要求:
- 不要直接重写全部代码
- 按严重程度排序
- 每个问题都说明原因和修改建议
- 如果没有问题,也明确写“未发现明显问题”
输出格式:
| 严重程度 | 位置 | 问题 | 原因 | 修改建议 |
代码:
```go
func LoadConfig(path string) (*Config, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
data, _ := io.ReadAll(file)
var cfg Config
json.Unmarshal(data, &cfg)
return &cfg, nil
}
这个 Prompt 会引导 AI 检查出几个关键问题:
| 严重程度 | 位置 | 问题 | 原因 | 修改建议 |
|---|---|---|---|---|
| 高 | `os.Open` 后 | 文件没有关闭 | 文件描述符可能泄漏 | 使用 `defer file.Close()` |
| 高 | `io.ReadAll` | 忽略读取错误 | 读取失败时仍继续解析 | 检查并返回错误 |
| 高 | `json.Unmarshal` | 忽略解析错误 | 配置可能为空或不完整 | 检查并返回错误 |
| 中 | 错误上下文 | 原始错误缺少业务信息 | 排查时不清楚哪个文件失败 | 使用 `fmt.Errorf` 包装错误 |
AI 审查代码时,最怕输出一堆“建议优化”的泛话。指定表格格式和严重程度,可以让结果更接近真正的 Code Review。
## 场景四:让 AI 重构代码
重构不是“把代码写得更优雅”。工程里的重构必须保持外部行为不变,最好还要有测试兜底。
### 重构 Prompt
```text
请帮我重构下面这段 TypeScript 代码。
目标:
- 降低重复逻辑
- 提高可读性
- 保持函数签名不变
- 保持现有返回结构不变
约束:
- 不要引入新依赖
- 不要改变错误码
- 不要改变字段名
- 如果你认为需要拆函数,请说明每个函数的职责
请输出:
1. 重构思路
2. 重构后的代码
3. 行为是否变化
4. 建议补充的测试用例
代码:
```ts
function getDiscount(userType: string, amount: number): number {
if (userType === "vip") {
if (amount > 1000) {
return 0.2;
} else {
return 0.1;
}
}
if (userType === "new") {
if (amount > 500) {
return 0.15;
} else {
return 0.05;
}
}
return 0;
}
重构时要特别强调“保持什么不变”。如果不写清楚,AI 可能会顺手改变函数签名、返回类型、异常处理方式,甚至引入新的抽象,导致调用方一起改。
重构任务里常见约束如下:
| 约束 | 为什么要写 |
|---|---|
| 函数签名不变 | 避免影响调用方 |
| 返回结构不变 | 避免接口兼容性问题 |
| 不引入依赖 | 避免增加构建和安全成本 |
| 错误码不变 | 避免前端或调用方逻辑失效 |
| 性能不能下降 | 避免为了可读性引入额外开销 |
| 必须补测试 | 确认行为没有被改坏 |
## 场景五:让 AI 生成单元测试
让 AI 写测试时,不能只说“补一下单元测试”。测试要覆盖正常输入、边界输入、异常输入,以及关键业务分支。
### 单元测试 Prompt
```text
请为下面这个函数生成 pytest 单元测试。
测试目标:
1. 覆盖正常折扣计算
2. 覆盖边界金额
3. 覆盖未知用户类型
4. 覆盖金额为 0 的情况
要求:
- 使用 pytest
- 测试函数名要表达业务含义
- 使用参数化减少重复代码
- 不要修改被测函数
被测代码:
```python
def get_discount(user_type: str, amount: int) -> float:
if user_type == "vip":
return 0.2 if amount > 1000 else 0.1
if user_type == "new":
return 0.15 if amount > 500 else 0.05
return 0
单元测试可以先列测试矩阵,再让 AI 写代码:
| 用户类型 | 金额 | 预期折扣 | 覆盖点 |
|---|---:|---:|---|
| `vip` | 1001 | 0.2 | VIP 高金额 |
| `vip` | 1000 | 0.1 | VIP 边界值 |
| `new` | 501 | 0.15 | 新用户高金额 |
| `new` | 500 | 0.05 | 新用户边界值 |
| `normal` | 1000 | 0 | 未知用户类型 |
| `vip` | 0 | 0.1 | 零金额 |
比起直接生成测试代码,先让 AI 输出测试矩阵更稳。测试矩阵能暴露遗漏分支,也方便人工检查预期是否正确。
## 场景六:让 AI 写 SQL
SQL(结构化查询语言)类 Prompt 要提供表结构、字段含义、数据量级、索引情况和期望结果。只给一句“帮我写个查询”很容易得到能跑但很慢的语句。
### SQL Prompt
```text
请帮我写一条 PostgreSQL 查询语句。
需求:
- 查询最近 30 天每个用户的订单总金额
- 只统计 paid 状态的订单
- 返回用户 ID、订单数、总金额
- 按总金额从高到低排序
- 只返回前 100 名
表结构:
```sql
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
status TEXT NOT NULL,
amount NUMERIC(12, 2) NOT NULL,
created_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_orders_created_at ON orders(created_at);
CREATE INDEX idx_orders_user_id ON orders(user_id);
约束:
- 数据量约 5000 万行
- 请考虑索引使用
- 输出 SQL 后,请解释可能的执行瓶颈
好的 SQL Prompt 不只要求“写出查询”,还要要求解释执行瓶颈。面对大表时,查询条件、索引和排序都可能影响成本。
## 常见低质量 Prompt 与改法
| 低质量问法 | 问题 | 改法 |
|---|---|---|
| 帮我优化代码 | 不知道优化目标 | 说明要优化性能、可读性、内存、并发还是结构 |
| 这段代码有 bug 吗 | 缺少预期行为 | 提供输入、预期输出、实际输出和日志 |
| 帮我写接口 | 缺少协议和数据结构 | 提供 HTTP(超文本传输协议)方法、路径、请求体、响应体、错误码 |
| 帮我写 SQL | 缺少表结构 | 提供建表语句、索引、数据量、筛选条件 |
| 帮我重构 | 缺少约束 | 写清函数签名、返回结构、依赖、兼容性要求 |
| 报错了怎么办 | 缺少复现信息 | 提供环境、命令、日志、相关代码 |
## 更可靠的 AI 编程工作流
不要让 AI 一次性完成所有事情。更稳的方式是把任务拆成计划、实现、验证、审查四步。
```mermaid
flowchart LR
A[描述需求和约束] --> B[让 AI 给方案]
B --> C[人工确认方向]
C --> D[让 AI 写代码]
D --> E[运行测试和静态检查]
E --> F[让 AI 做代码审查]
F --> G[人工合并修改]
每一步的 Prompt 目标不同:
| 阶段 | Prompt 目标 | 产物 |
|---|---|---|
| 方案 | 比较实现路径和风险 | 技术方案、边界条件 |
| 实现 | 生成局部代码 | 函数、类、配置 |
| 验证 | 补测试和检查用例 | 单元测试、测试矩阵 |
| 审查 | 找问题 | 风险清单、修改建议 |
这种拆法能减少“一大段生成代码里藏着错误”的问题。AI 更适合在明确边界内完成局部任务,而不是在缺少上下文时直接接管整个项目。
使用 AI 编程助手时要避开的坑
1. 不要贴敏感信息
代码、日志、配置里可能包含密钥、Token、数据库地址、用户手机号、身份证号等敏感数据。发给 AI 前应先脱敏。
错误示例:
DATABASE_URL=postgres://admin:real_password@prod-db.example.com:5432/app
脱敏后:
DATABASE_URL=postgres://<user>:<password>@<host>:5432/<db>
2. 不要默认 AI 给出的 API 一定存在
AI 可能生成看起来合理但实际不存在的 API(应用程序编程接口)。遇到陌生方法、参数或库,要查对应版本的官方文档,或者让 AI 明确标出“哪些地方需要确认版本”。
3. 不要把大段无关代码全贴进去
上下文太长会稀释重点。更好的做法是提供最小可复现示例:
请基于下面的最小复现代码分析问题,不要假设项目里还有其他逻辑。
如果问题涉及多个模块,可以先给调用链,再逐步补充关键代码。
4. 不要跳过测试
AI 生成的代码可能语法正确,但业务语义不一定正确。每次让 AI 改代码,都应该同步要求它给出测试用例,尤其是边界值和异常分支。
一个可直接复制的高频 Prompt
日常开发里,可以把这段作为默认模板:
请作为一名资深软件工程师,帮我处理下面这个编程问题。
背景:
- 技术栈:
- 运行环境:
- 当前需求:
问题:
- 预期行为:
- 实际行为:
- 报错或异常:
材料:
```text
在这里粘贴代码、日志、配置或 SQL
约束:
- 不能修改:
- 必须兼容:
- 不要引入:
- 代码风格:
请输出:
- 问题判断
- 关键原因
- 修改方案
- 修改后的代码
- 测试用例
- 可能的风险
“帮我看看”适合临时聊天,不适合解决复杂技术问题。把问题说清楚,AI 才能给出可验证、可修改、可落地的结果。