LLM 应用踩坑笔记:Prompt 写歪了,你以为是模型不行
接着上一篇 《别把 LLM 当裸机跑》 的话题,这次想聊一个更具体的话题:Prompt 工程。
我做 LLM 应用一年多,最大的体会是——很多人以为某个任务"模型搞不定",其实是 Prompt 写歪了。
同一个任务,同一个模型,Prompt 写法不同,输出质量能差好几个量级。这篇笔记把我踩过的坑整理一下,希望对正在做 LLM 应用的同行有点参考。
代码示例都用 Python + OpenAI SDK,但思路适用于所有主流大模型 API。
坑一:把所有约束塞进 system prompt
刚入门时我喜欢这样写:
system_prompt = """
你是一个专业的代码审查助手。
请遵循以下规则:
1. 检查变量命名是否符合 PEP8 规范
2. 检查是否有未使用的 import
3. 检查是否有 SQL 注入风险
4. 检查异常处理是否完善
5. 检查日志输出是否合理
6. 检查注释是否清晰
7. 检查测试覆盖率
8. 输出格式必须是 JSON
9. 每个问题要标注严重程度
10. ...(还有 15 条)
"""
然后兴致勃勃地运行,发现:
模型只遵循了前 3 条规则,后面的全部被无视了。
后来读了一些研究才知道,LLM 对 prompt 中信息位置的敏感度差异极大。这是所谓的 "Lost in the Middle" 现象——模型对开头和结尾的内容关注度最高,中间的内容很容易被"遗忘"。
正确做法:
把核心约束放在 prompt 的开头和结尾,重要的事情说两遍。
system_prompt = """
[核心任务] 进行 Python 代码审查,输出 JSON 格式结果。
[审查维度]
- 安全性: SQL 注入、XSS、敏感信息泄露
- 规范性: PEP8、命名约定、import 顺序
- 健壮性: 异常处理、边界条件、空值判断
- 可读性: 注释、变量命名、函数职责单一
[输出格式]
{
"issues": [
{"type": "security", "severity": "high", "line": 12, "message": "..."}
]
}
[再次强调] 必须输出合法 JSON,不要包含任何解释性文本。
"""
把约束结构化分组,把最关键的"输出格式"在开头和结尾各强调一次。这一步改完之后,我的 Prompt 遵循度从 50% 提到了 90%+。
坑二:用"否定句"约束模型
一个特别隐蔽的坑:LLM 对否定句的处理远不如肯定句。
我曾经写过这样的 prompt:
prompt = """
请总结以下文章内容,不要超过 100 字,不要使用专业术语,不要包含个人观点。
"""
结果模型给我返回了:
- 一段 250 字的总结
- 满篇专业术语
- 夹杂大量"我认为""值得注意的是"等主观表达
为什么?
因为 LLM 本质上是"概率续写","不要 X"这种指令在训练数据里出现得相对少,模型更容易抓住"X"本身然后继续生成。就像你跟一个人说"不要想白熊",他脑子里第一时间出现的就是白熊。
正确做法:把所有否定句改成肯定句。
prompt = """
请总结以下文章内容,要求:
- 总字数控制在 100 字以内
- 使用通俗易懂的日常用语
- 客观陈述事实,不加评价
"""
把"不要使用专业术语"改成"使用通俗易懂的日常用语",模型的遵循度立刻提升。这是个非常小的细节,但对输出质量影响巨大。
坑三:让模型"自由发挥"
新手做 LLM 应用时还有一个常见错误:对输出格式不做约束。
prompt = "请帮我分析这段代码的性能瓶颈"
你以为模型会给你一段精炼的分析。
实际上模型可能给你:
- 第一次:4 段散文,没有结构
- 第二次:分点列表,但条目数随机
- 第三次:先来段"非常好的问题!"开头,然后混合各种格式
这种输出基本无法做下游的程序化处理。
正确做法:用 结构化输出 + few-shot 示例 来约束。
prompt = """
分析以下代码的性能瓶颈,严格按照下面的格式输出:
## 瓶颈点 1
- 位置: [文件:行号]
- 类型: [I/O / CPU / 内存 / 网络]
- 严重程度: [高/中/低]
- 优化建议: [具体方案]
## 瓶颈点 2
...
示例输出:
## 瓶颈点 1
- 位置: main.py:42
- 类型: I/O
- 严重程度: 高
- 优化建议: 改用批量查询替代循环单次查询
[待分析代码]
{code}
"""
加上示例输出这一步是核心。LLM 是"模仿型选手",你给它一个具体例子,它的输出格式遵循度会跳一个台阶。
坑四:忽略 temperature 的副作用
很多人调 LLM 只用默认参数。但 temperature 这一个参数,对输出影响极大。
简单理解:
- temperature = 0:模型每次都选概率最高的 token → 输出确定、保守、重复性高
- temperature = 1:模型按概率分布随机采样 → 输出多样、有创意、不稳定
- temperature = 2:模型大量采样低概率 token → 输出经常崩坏、出现胡言乱语
我踩过的坑是:做严肃任务时 temperature 拉太高。
比如让模型生成 SQL,我设了 temperature=0.8,结果同一个查询需求,模型有时返回正确 SQL,有时返回带语法错误的 SQL,有时甚至开始"创造"我数据库里不存在的字段名。
经验法则:
| 任务类型 | 推荐 temperature |
|---|---|
| 代码生成、SQL 生成 | 0 - 0.2 |
| 信息提取、分类 | 0 - 0.3 |
| 总结、改写 | 0.3 - 0.6 |
| 创意写作、故事生成 | 0.7 - 1.0 |
| 头脑风暴 | 1.0+ |
严肃任务 temperature 调低,创意任务调高。这条规则简单粗暴但极其有效。
坑五:不给模型"思考空间"
最后一个想分享的,是 Chain-of-Thought(思维链) 在工程实践中的应用。
我曾经让模型做一个复杂的数学推理任务,prompt 是:
prompt = "如果一个商品打 8 折后再打 9 折,相当于打几折?直接告诉我答案。"
模型经常给错答案(比如答 17 折、7 折、85 折),错误率高得离谱。
后来我改成:
prompt = """
如果一个商品打 8 折后再打 9 折,相当于打几折?
请按以下步骤推理:
1. 假设原价为 100
2. 第一次打 8 折后的价格是?
3. 第二次打 9 折后的价格是?
4. 最终价格相对原价是几折?
最后给出答案。
"""
错误率立刻降到接近 0。
原因是:LLM 没有"心算"能力。它的每一次输出 token 本质上都是基于前面 token 的概率推理。不给它"中间推理过程"的输出空间,它就只能直接猜结果——猜对了是运气,猜错了是常态。
经验法则:复杂推理任务,一定要让模型 "step by step" 输出推理过程,再得出最终答案。哪怕你只需要最终答案,也要保留推理过程的输出——因为这个过程本身能显著提高准确率。
写在最后
Prompt 工程在很多人眼里像"玄学",但实际上它有自己的工程规律:
- 位置敏感:核心约束放头尾
- 正向表达:肯定句优于否定句
- 结构化:明确输出格式 + few-shot
- 参数匹配任务:temperature 别瞎调
- 给思考空间:让模型 step by step
这些规律每一条都不复杂,但叠加起来对输出质量的影响是数量级的。
下次写 prompt 之前,可以拿这个清单过一遍。如果你也踩过其他 Prompt 的坑,欢迎评论区交流。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)