Prompt工程实践笔记
几个月前我需要用 GPT-4 分析一堆日志文件,找出异常请求。
“你问了AI一个问题,得到一个模糊的回答。
从一个失败案例开始
几个月前我需要用 GPT-4 分析一堆日志文件,找出异常请求。第一次写的 prompt 是这样的:
请分析这个日志文件,找出所有异常请求,并总结原因。
结果收到了一堆"根据日志内容分析,异常请求可能包括…“之类的空泛回复,根本看不出具体哪行有问题。
然后我开始尝试各种"高级技巧”:加角色设定、加输出格式要求、加思维链引导。越写越长,最后长到三屏都看不完,但结果还是一团糟。
问题不在于 prompt 够不够长,而在于我没有把任务拆清楚。日志分析不是一句话能说完的事,它需要:过滤、分类、统计、验证、解释。当我把期望的结果拆成具体步骤后,才算是入门。
请按照以下步骤分析日志文件:
1. 先统计每行的时间戳范围,确认日志覆盖的时间段
2. 提取所有 HTTP 状态码,统计每种状态码的数量和占比
3. 找出所有状态码非 200 的请求,列出其时间戳、路径、状态码
4. 分析非 200 请求的模式:哪些路径经常出问题?错误分布有什么规律?
5. 针对异常最多的 3 个路径,提取相关上下文,给出可能的原因
请以结构化 JSON 格式输出,字段包括:时间范围、状态码统计、异常请求列表、分析结论。
这段 prompt 还不算完美,但至少告诉了 AI 每一步该做什么,以及我要的是什么格式。
基础技巧:把话说清楚
很多人学 Prompt 工程是从"角色设定"开始的,什么"你是一个资深后端工程师"之类的。其实最早该学的反而是把话说清楚。
用输出格式减少歧义
最容易出问题的地方是"解释一下这段代码"这类指令。AI 可能给你一行一行注释,也可能给你讲设计模式,还可能给你重构建议。它不知道你要的是哪一种。
请解释以下 Python 代码的工作原理。
要求输出格式:
1. 一句话概括代码的主要功能
2. 列出代码中使用的 3 个关键函数/方法,并说明各自的作用
3. 指出代码中可能存在的性能问题或改进空间
4. 给出适合这个代码的使用场景和不适用的场景
代码如下:
```python
# 你的代码
这样写还有一个好处:你可以直接解析 JSON 输出,或者在脚本里用正则提取特定部分。
### 用示例代替描述
说"给我一个 MySQL 连接池的配置示例"和"给你一个示例,再让你照着改一个 PostgreSQL 的",效果完全不一样。
```markdown
以下是一个 MySQL 连接池的配置示例:
```python
import mysql.connector.pooling
dbconfig = {
"host": "localhost",
"user": "root",
"password": "password",
"database": "mydb",
"pool_name": "mypool",
"pool_size": 5,
"pool_reset_session": True
}
pool = mysql.connector.pooling.MySQLConnectionPool(**dbconfig)
请参考上面的示例,给出一个 PostgreSQL 连接池的配置。要求:
- 使用 psycopg2.pool
- 最小连接数为 2,最大连接数为 10
- 连接超时时间为 30 秒
- 添加异常处理和连接验证逻辑
少样本学习(Few-Shot Learning)的基础就是这样:给了几个例子,AI 就更容易抓住模式。
### 用负样本排除误解
有时候 AI 理解偏了,不是因为你没说清楚,而是因为你没说清楚"不要什么"。
```markdown
请帮我优化以下查询语句。
要求:
1. 保持查询逻辑不变,不要修改返回结果
2. 不要使用窗口函数或复杂的子查询(系统版本不支持)
3. 优化目标:优先提高查询速度,其次减少内存占用
4. 如果当前已经是最优写法,直接说明原因
原始 SQL:
```sql
SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC LIMIT 10;
如果不加限制条件,AI 可能会给你加上索引建议,或者推荐使用 CTE,但在某些场景下这些都不可用。
## 思维链:让 AI 把过程说出来
第一次听说"思维链"(Chain of Thought)时,我觉得这是在教 AI 像人类一样"思考"。后来用多了才发现,本质上是让 AI 把中间步骤显式写出来,这样出错了更容易定位。
### 用分步引导拆解复杂任务
```markdown
请帮我设计一个 RESTful API,用于管理用户订阅。
请按照以下思路进行设计:
**步骤 1:需求分析**
- 首先列出订阅系统需要支持的核心功能
- 标出哪些功能是必须的,哪些是可选的
**步骤 2:资源建模**
- 确定需要哪些核心资源(User, Subscription, Plan 等)
- 定义资源之间的关系
**步骤 3:API 设计**
- 为每个资源设计 CRUD 接口
- 为跨资源操作设计特殊接口
- 考虑分页、过滤、排序等通用需求
**步骤 4:安全考虑**
- 哪些接口需要认证?哪些需要授权?
- 如何处理过期订阅、降级场景?
**步骤 5:错误处理**
- 列出可能出现的错误情况
- 为每种错误设计合理的 HTTP 状态码和响应格式
请在每个步骤之间明确标注"---步骤 N---",方便我阅读和分段讨论。
这样写的优点是:如果 AI 在某个步骤错了,你可以直接定位到问题位置,而不是重写整个 prompt。
用对比分析优化决策
做技术选型时,与其让 AI 直接给结论,不如让它先对比。
我需要在一个新的 Python 项目中选择异步 Web 框架,候选包括:FastAPI, Sanic, Tornado。
请从以下维度进行对比分析:
1. 性能:基于公开的基准测试数据(如果有的话)
2. 生态成熟度:可用插件、社区支持、维护频率
3. 学习曲线:文档质量、上手难度、迁移成本
4. 实际考虑:我的项目需要高并发(10k+ QPS)、WebSocket 支持、以及与现有 SQLAlchemy 项目的兼容性
对比完成后,请给出一个推荐,并说明在什么情况下你会推荐另一个框架。
这种写法可以避免 AI 只给出"强烈推荐 X"这种单一结论,而是让你有足够信息自己做判断。
踩坑记录
坑 1:过度依赖角色设定
有一段时间我几乎每个 prompt 都会加上"你是一个有 10 年经验的资深工程师”。后来发现,这没什么实际作用。
角色设定不是没用,但要看场景。比如"你是一个技术文档作者,面向新手读者"这种设定,会影响语气和解释深度。但"资深工程师"这种,基本不会改变逻辑。
更实际的写法:
请用面向新手的方式解释以下概念,假设读者熟悉 Python 基础语法,但不了解异步编程。
要解释的概念:async/await 在 Python 中的工作原理。
要求:
1. 用一个生活化的类比开头
2. 先解释同步代码的执行过程,再对比异步
3. 尽量少用专业术语,如果必须用请额外解释
4. 提供一个简单但完整的代码示例
坑 2:没限制输出长度
让 AI"详细解释"某个东西时,它可能会生成几万字的回答。这不仅浪费 token,还可能让关键信息淹没。
请简明扼要地解释 Docker Compose 的核心概念。
要求:
- 总字数不超过 500 字
- 每个概念解释不超过 2 句话
- 只解释最核心的 3 个概念:Service, Volume, Network
- 如果某个概念需要更多信息,标注"需要扩展"
坑 3:用了错误的少样本示例
有一次我让 AI 按照示例格式化代码,结果给的示例里有几个语法错误,导致 AI 照着学,输出一堆错误代码。
少样本示例一定要自己先验证一遍。特别是代码示例,如果错了,AI 会把错误当成"正确模式"。
高级技巧:动态 Prompt
有时候你需要根据输入内容调整 prompt 本身,而不是写死一个模板。比如分析代码时,你可能需要先判断代码复杂度,再决定采用不同的策略。
请先快速评估以下代码的复杂度(简单/中等/复杂),然后根据复杂度采用不同的分析策略。
**简单代码**(< 50 行,逻辑单一):
- 直接给出功能说明
- 指出潜在 bug 或改进点
**中等代码**(50-200 行,有多个函数或类):
- 先拆分功能模块
- 每个模块单独分析
- 最后给出整体架构评价
**复杂代码**(> 200 行,涉及多个模块或设计模式):
- 先画出模块依赖关系
- 标出核心路径和边界情况
- 分析设计模式的适用性
代码如下:
```python
# 你的代码
这种写法相当于让 AI 自己做"路由",根据情况选择不同的处理流程。
## 实际应用场景
### 场景 1:代码审查
```markdown
请对以下代码进行审查,重点关注以下问题:
1. 安全问题:SQL 注入、XSS、未过滤用户输入
2. 性能问题:N+1 查询、不必要的计算、内存泄漏风险
3. 可维护性:命名规范、代码重复、缺少注释
4. 边界情况:空值处理、异常捕获、并发问题
对于每个发现的问题,请按以下格式输出:
- **问题类型**:[安全/性能/可维护性/其他]
- **严重程度**:[高/中/低]
- **具体位置**:指出代码行号或函数名
- **问题描述**:简要说明问题是什么
- **修复建议**:给出具体的修复方案或改进建议
- **代码示例**:如果适用,提供修复后的代码片段
代码如下:
```python
# 你的代码
### 场景 2:技术选型对比
```markdown
我需要在 Redis 和 Memcached 之间选择一个缓存方案,用于以下场景:
业务背景:
- 高并发读取(主要操作是 get,set/update 较少)
- 需要支持过期时间(TTL)
- 需要简单的数据结构(如列表、哈希)
- 预计 QPS 峰值在 5k-10k 之间
- 团队对 Redis 更熟悉,但 Memcached 的简单性也有吸引力
请对比 Redis 和 Memcached 在上述场景下的适用性,包括:
1. 性能差异(吞吐量、延迟)
2. 功能差异(数据结构、持久化、集群)
3. 运维复杂度(部署、监控、故障恢复)
4. 学习曲线和生态支持
最后给出一个明确的推荐,并说明在什么情况下你会改变这个推荐。
场景 3:问题诊断
我的 Node.js 服务最近出现内存泄漏,以下是观察到的情况:
现象描述:
- 服务运行 2-3 天后内存占用从 200MB 增长到 2GB
- CPU 使用率保持稳定,没有异常波动
- 日志中没有明显的错误堆栈
- 重启服务后恢复正常,但过一段时间又出现
环境信息:
- Node.js 版本:v18.16.0
- 使用的框架:Express.js
- 数据库连接:MongoDB(使用 mongoose)
- 消息队列:RabbitMQ(使用 amqplib)
- 定时任务:node-cron
请帮我分析可能的原因,并给出排查步骤。要求:
1. 列出最可能的 3-5 个原因,按可能性排序
2. 针对每个原因,给出具体的排查方法(包括工具和命令)
3. 提供一段可以用来诊断的代码片段或脚本
4. 给出预防类似问题的最佳实践建议
写到最后
Prompt 工程不是一门能速成的技术,更像是一种需要大量练习的手艺。我这段时间的体会是:没有万能模板,只有大量试错后的经验积累。
能明显提升效果的做法其实就几个:
- 把输出格式说清楚
- 用示例代替模糊描述
- 拆解复杂任务,逐步引导
- 坏了就改,而不是不断加长 prompt
还有最重要的一点:学会看 AI 的输出,找出它的理解偏差,而不是一味地认为是"AI 不够聪明"。很多时候是我们自己没把话说清楚。
最近在折腾一个自动化的 Prompt 优化工具,希望能把一些经验固化为可复用的模式。等有点进展了,再专门写一篇总结。
在那之前,还是老老实实多写、多试、多改吧。
参考资源
- OpenAI 官方文档的 Prompt 最佳实践
- Anthropic 的 Prompt Engineering 指南
- “Prompt Engineering Guide” by DAIR.AI
- 各种实际项目的失败 prompt 和优化记录
(其实最好的参考资料还是你自己写过的那些 prompt,以及它们对应的实际效果。)
版权声明: 本文首发于 指尖魔法屋-Prompt工程实践笔记(https://blog.thinkmoon.cn/post/139-prompt-engineering-deep-dive-guide/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。