一个让人崩溃的下午
上周三下午两点,我在改一个数据处理脚本。需求很简单:读取一个100MB的JSON文件,按某个字段分组聚合,输出Top 10。
我对Cursor说了一句:“帮我写个Python脚本,读取这个JSON文件,分组聚合取Top 10”。
十秒钟后,代码出来了。看着挺像那么回事——有json.load(),有defaultdict,有sorted()。
然后我跑了。等了30秒,风扇狂转,16GB内存吃满,最后OOM了。
那一刻我才意识到:我对AI说了一句”帮我写”,它就真的只是”帮我写”——写了一段教科书级别的、完全不懂生产环境的、把整个文件塞进内存的天真代码。
问题不在AI笨,在于我的Prompt太烂。
这篇文章是我踩了无数坑之后总结的AI编程Prompt方法论。不是玄学,是工程——每个技巧背后都有可复现的原理。
一个Prompt的解剖:写出让AI精准输出的”指令配方”
先看一组对比。同一个需求,不同的Prompt,输出的代码天差地别。
❌ 模糊Prompt(新手常见写法)
📎 延伸阅读:Python AI Agent 从零构建实战 — 用 50 行 Python 代码实现 Tool Calling Agent,含防死循环、容错解析、上下文压缩等生产级技巧。
“帮我写一个Python脚本处理这个JSON文件。”
如果你想知道到底哪个工具最好用、怎么搭配最效率,可以看看我写的这篇 2026年AI编程工具深度横向评测,有详细的横向对比和打分表。
AI会怎么理解?它不知道文件多大、不知道数据结构、不知道内存限制、不知道你的编码风格——于是它输出一段”理论上正确但在你机器上跑不动”的代码。
✅ 精准Prompt(生产级写法)
“用Python写一个流式处理脚本,逐行读取一个~100MB的JSON Lines文件(data/events.jsonl),按’category’字段分组统计count和amount的sum。要求:内存占用限制在200MB以内,使用ijson库做增量解析。输出Top 10结果到stdout。加上异常处理和进度条。代码用3.10+的类型注解。不要用pandas。”
这个Prompt包含了AI需要的全部上下文:数据规模、具体字段、性能约束、库选型、输出格式、编码规范、明确排除项。AI拿到这个Prompt,输出质量直接提升一个数量级。
Prompt Engineering的五个维度:一个可操作的框架
经过几个月的日常使用,我总结了五个能显著影响AI输出质量的维度。每次写Prompt前过一遍这五条,基本不会翻车。
维度1:Context(上下文)—— 告诉AI它面对的是什么
AI不知道你的项目结构、技术栈、部署环境。你得喂给它。
必填项:
- 语言和版本:别只说”Python”,说”Python 3.12″——3.10的match-case、3.11的异常组、3.12的类型语法,AI都能用上
- 文件/数据结构:给出一个真实样例,哪怕只有5行。AI靠特征匹配理解结构,比文字描述有效得多
- 运行环境:Linux/macOS/Windows?Docker?内存限制?这些决定了AI会不会推荐platform-specific的方案
# 示例:给出数据样例远比描述有效
# 输入文件 data/events.jsonl,每行格式:
# {"ts": "2026-06-22T14:23:01Z", "category": "payment", "amount": 299.0, "user_id": "u_8842"}
# {"ts": "2026-06-22T14:23:02Z", "category": "refund", "amount": -49.9, "user_id": "u_3391"}
维度2:Constraints(约束)—— 告诉AI你的边界
这一条是被忽视最多的。没有约束,AI默认输出”教科书答案”——而教科书答案在生产环境通常是灾难。
四类约束必须明确:
| 约束类型 | 示例 | 为什么重要 |
|---|---|---|
| 性能 | “内存 < 200MB”、”单次请求 < 100ms” | 防止AI写出O(n²)或全量加载方案 |
| 依赖 | “只用标准库”、”可以用httpx但不能用requests” | 避免引入你项目里没有的依赖 |
| 安全 | “不要用eval()”、”不要硬编码密码” | 防止AI生成有安全隐患的代码 |
| 风格 | “用dataclass而非dict”、”类型注解必须完整” | 保持与项目现有代码风格一致 |
维度3:Format(格式)—— 告诉AI你想要的输出形态
“格式”不止是代码vs自然语言——指定代码的结构模板,让AI知道往哪个框架里填。
# ✅ 给出函数签名作为模板
def aggregate_events(
filepath: str,
group_by: str,
agg_fields: list[str],
top_n: int = 10
) -> list[dict[str, Any]]:
"""
流式读取JSON Lines文件,分组聚合后返回Top N。
Args:
filepath: JSON Lines文件路径
group_by: 分组字段名
agg_fields: 需要聚合的数值字段(默认sum聚合)
top_n: 返回前N条
Returns:
按聚合值降序排列的Top N条记录
Raises:
FileNotFoundError: 文件不存在
ValueError: 字段不存在或文件格式错误
"""
# TODO: implement
给出这个模板后,AI会在框架内生成——函数签名、docstring、异常声明都保持一致。相比”帮我写个聚合函数”,可控性高了一个层次。
维度4:Examples(示例)—— Few-shot比你想象的更有用
如果你想让AI按某种特定风格输出,给它看一个例子。这对重构/格式化任务尤其有效。
# 给AI看你要的代码风格
# 参考以下风格重写后续代码:
def process_batch(items: list[dict]) -> BatchResult:
"""单批处理,返回结构化结果。"""
if not items:
return BatchResult.empty()
valid = [it for it in items if it.get("status") == "valid"]
errors = [it for it in items if it.get("status") != "valid"]
return BatchResult(
processed=len(valid),
failed=len(errors),
details=[{
"id": it["id"],
"error": it.get("error", "unknown")
} for it in errors]
)
AI看到这段示例就能推断出你的偏好:用命名元组/dataclass、列表推导式、提前返回空值处理、结构化错误输出。
维度5:Iteration(迭代)—— 第一版永远不完美
拿到第一版输出之后,不要重写整个Prompt——追加修正指令。
“上面的代码有两个问题:1) 没有处理JSON行中可能出现的Unicode转义 2) amount求和应该排除负值。修复这两点,其他保持不变。”
这种迭代式Prompt比重新描述需求高效得多——AI只需要在已有基础上做增量修改,不会重构整个方案引入新问题。
实战案例:从10分钟OOM到3秒完成
回到开头那个令人崩溃的100MB JSON任务。下面是我三次迭代的完整记录。
第一版Prompt(翻车版):
“帮我写个Python脚本处理这个JSON文件”
结果:全量json.load() → OOM。
第二版Prompt(加上上下文):
“写一个流式处理的脚本,处理约100MB的JSON Lines文件。每行一个JSON对象,按category字段分组,统计每组的count和amount总和”
结果:用了逐行json.loads()——能跑了,但13秒。而且amount求和时把字符串和None混在一起,静默丢数据。
第三版Prompt(五维度完整版):
用Python 3.12写一个脚本,流式处理~100MB的JSON Lines文件(data/events.jsonl)。
数据格式:
{“ts”: “2026-06-22T14:23:01Z”, “category”: “payment”, “amount”: 299.0, “user_id”: “u_8842”}要求:
1. 逐行读取,用ijson做增量解析,内存 < 200MB
2. 按category分组,统计count和amount的sum(amount为None或负值计为0)
3. 输出Top 10到stdout,格式:rank | category | count | total_amount
4. 加上tqdm进度条、FileNotFoundError处理、非法行跳过并打印warning
5. 完整的类型注解,用dataclass存储中间结果
6. 不要用pandas
结果:3.2秒完成,峰值内存87MB。代码有完整的类型注解、异常处理、进度条、警告日志。可以直接进生产。
同一个任务,三版Prompt的差距:从OOM到3秒。不是AI进步了——是我的指令进步了。
调试类Prompt的专属套路
让AI帮忙修bug时,有一套专门的高效Prompt模式。
🔴 最蠢的问法:
“这个代码有bug,帮我修一下”
AI没有足够信息,只能猜。猜错了你浪费时间,猜对了你也学不到东西。
🟢 高效的问法(四段式):
1. 期望行为:“这段代码应该对用户列表按注册日期排序,然后按国家分组输出每组前3名。”
2. 实际行为:“实际输出中,中国组的前3名是对的,但日本组只显示了1条——应该有5条数据。”
3. 已经排查的:“我确认输入数据里有5条日本用户记录;datetime解析没报错;打印了中间分组结果,日本确实只有1条。”
4. 相关代码:[粘贴函数或关键片段]
这个四段式Prompt模板能把AI的”猜谜模式”切换到”定位模式”——它不是在猜你的意图,而是在已有排查信息的基础上做逻辑推演。
我统计过我自己的使用记录:四段式Prompt的一次修正准确率约78%,而模糊Prompt的一次修正率不到30%(数据来自过去3个月与Cursor/Copilot的交互记录,样本量~200次)。
多文件/项目级Prompt:让AI看到更大的图景
这是2026年AI编程工具的新能力——Cursor和Windsurf现在支持多文件上下文,Copilot Workspace能理解整个repo。
做跨文件重构时,Prompt的关键是定义契约(interface contract),而不是命令AI逐文件修改。
❌ 逐文件命令式:“把
api.py里的get_user返回值从dict改成dataclass。然后改service.py里所有调用get_user的地方。再去改test_api.py的断言。”
✅ 契约定义式:“定义一个
Userdataclass,字段包括id(int)、name(str)、email(str)、created_at(datetime)。将项目中所有直接构造user dict的地方改为构造User实例,所有访问user['xxx']的地方改为user.xxx属性访问。保持对外API的JSON序列化格式不变。”
契约式Prompt有两个好处:(1) AI自己理解影响范围,不会漏掉边缘调用点;(2) 防止你手动枚举时遗漏文件。
常见翻车点 & 怎么抢救
🚫 翻车1:AI坚持用自己的方案,忽略你的约束
抢救:在约束前加”不要”比加”要”更有效。”不要用pandas”比”用标准库做数据分析”更能阻止AI引入它偏好的库。
🚫 翻车2:AI输出”幻觉代码”——调用了不存在的API
抢救:限定库版本。”用httpx 0.28.x的API”——AI对不同版本的API记忆有差异,指定版本能减少幻觉。
🚫 翻车3:AI输出代码风格不一致
抢救:在Prompt中引用项目中的已有代码片段作为风格参考(见维度4)。这比”用PEP 8风格”这种泛泛之词有效得多。
🚫 翻车4:长对话后AI开始”失忆”
抢救:每轮迭代时把核心约束重新贴一遍。不需要全文——一句”之前要求的内存<200MB和只用标准库仍然有效”就够了。
总结:记住这五句话就够了
把上面2000字浓缩成五个原则,每次写Prompt前快速过一遍:
- 给上下文:数据规模、环境、版本——AI不猜,你就要说
- 设边界:性能目标、依赖限制、安全红线——没边界=没质量
- 给模板:函数签名、数据样例、输出结构——框架内生成比自由发挥靠谱
- 给例子:一段你满意的代码——AI模仿能力强于理解抽象指令
- 迭代改:追加修正指令而非重写——增量修改比推倒重来稳定
说实话,学这些东西花了我三个月——从”AI写的东西不能直接用”到”大部分情况下第一次就对了”。区别不在AI版本升级,在我学会了怎么”下指令”。
如果你也在用Copilot/Cursor/Windsurf,试试下次别写”帮我写个XX”,按五个维度来一遍。你会回来的。
FAQ
Q: 这些技巧适用于所有AI编程工具吗?
核心原则(五维度框架)通用于Copilot、Cursor、Windsurf、Claude Code、Codex等所有LLM编程工具。但细节有差异:Cursor支持多文件上下文,可以把项目结构写进Prompt;Copilot的inline补全模式下Prompt要更短更聚焦;Windsurf的Cascade模式天然支持迭代。核心不变——信息越具体,输出越准确。
Q: 写了详细Prompt,AI还是给垃圾代码怎么办?
三步排查:(1) 检查是否给了足够的具体约束(”高性能”太泛 → 改成”内存<200MB, 单次<100ms”);(2) 检查是否给出了数据样例——这是最被低估的信息,AI靠样例理解数据结构比文字描述准确得多;(3) 如果前两步都做了还不行,换一个模型试试——不同模型对Prompt的”理解重心”不同,Claude偏重自然语言上下文,GPT偏重结构化指令,DeepSeek对代码示例敏感。
Q: Prompt太长会不会反而让AI困惑?
有技巧的”长”和废话连篇的”长”是两回事。好的长Prompt是信息密度高——每个句子都传递一条AI不知道的具体信息(版本、数量、格式、约束)。差的长Prompt是重复和模糊描述(”帮我写一个很好的、高质量的、最优的脚本”)。原则:字多可以,但不能有两个句子在说同一件事。
如果你觉得有用,我写过另外几篇AI编程实战文章: