Prompt 工程入门
flowchart LR
A["Prompt 工程入门"]
A --> B["分类:基础概念"]
A --> C["关键词:AI"]
A --> D["关键词:LLM"]
A --> E["关键词:Prompt"]
A --> F["关键词:Few-shot"]
同样的模型,Prompt 不同,输出质量可能天差地别。Prompt 工程的本质,不是“写咒语”,而是把任务说清楚、把边界讲明白、把输出设计成可控的接口。
这篇文章会讲什么
前面几篇讲了模型的原理、训练、记忆。但作为应用开发者,你在真实项目里最常打交道的,往往不是训练流程,也不是模型结构,而是每次请求时送进去的那段文本——Prompt。
很多人刚接触 LLM 时,会把 Prompt 理解成一句“对模型说的话”。这个理解没错,但还不够完整。
在工程视角里,Prompt 更像是:
- 你给模型的任务说明书
- 你和模型之间的接口契约
- 你约束输出格式和行为边界的控制层
- 你在不重新训练模型的前提下,最大化模型表现的主要手段
也正因为如此,同样一个模型,Prompt 稍微改一改,结果可能完全不同:
- 模糊的 Prompt,输出容易发散、啰嗦、跑题
- 清晰的 Prompt,输出更稳定、更短、更可解析
- 没有边界的 Prompt,模型容易乱补全
- 加了示例和约束的 Prompt,模型更像“按 SOP 办事”
本文会从最基础的概念讲起,覆盖:
- Prompt Engineering 到底是什么
- 角色设定为什么有效
- Few-shot 为什么能显著改善格式和稳定性
- 指令设计该怎么写才清楚
- Chain-of-Thought 什么时候有用,什么时候反而拖慢或扰乱输出
- 常见错误、修复思路和生产环境实践
读完之后,你应该能做到两件事:
- 写出比“随便问一句”明显更稳定的 Prompt
- 理解 Prompt 不是玄学,而是一套可拆解、可测试、可迭代的方法
延伸阅读:
先说结论:Prompt 不是“加点魔法词”,而是“减少模型猜测”
很多入门文章会把 Prompt 工程讲得很神秘,好像只要找到某种神奇写法,模型就会突然变聪明。
更准确的理解应该是:
Prompt 工程的核心,不是赋予模型新能力,而是减少模型误解任务的空间。
模型本来就有很多能力,但默认情况下,它并不知道:
- 你现在到底要它做什么
- 你希望答案多长
- 输出应该是自由文本还是 JSON
- 它该不该解释过程
- 它遇到不确定信息时应该保守还是大胆补全
- 它这次是扮演老师、客服、分析师,还是代码审查员
如果这些都不说清楚,模型就只能“猜你的意思”。
而 Prompt 工程,就是把这些本来需要模型猜的部分,尽量显式化。
1. 什么是 Prompt Engineering,为什么重要
先看定义:Prompt Engineering 是通过设计输入文本和消息结构,引导模型产生期望输出的技术。它是成本最低、反馈最快、最适合迭代的模型控制方式。
为什么 Prompt 这么重要
在大模型应用里,Prompt 往往是你最先、也最频繁能动的那个杠杆。
| 维度 | 说明 |
|---|---|
| 零边际成本 | 改 Prompt 不需要重新训练,改完就生效 |
| 快速迭代 | 几分钟就能试一版,适合 A/B 测试 |
| 稳定性控制 | 好 Prompt 能明显减少跑题、啰嗦、格式错误 |
| 工程价值 | Prompt 设计直接影响自动化、解析、用户体验 |
但更重要的是,Prompt 其实决定了“模型现在在做哪一种任务”。
同一个问题,如果你写成:
- “帮我看看这个需求”
- “请作为产品经理,列出 3 个风险点”
- “请输出 JSON,字段为 risks / assumptions / next_steps”
对模型来说,这几乎是三种不同的任务形式。
所以 Prompt 的作用不是“装饰问题”,而是:
把任务从模糊意图,转换成模型更容易稳定执行的指令。
Prompt 不只是“一段话”,而是一组输入元素
很多教程会把 Prompt 简化成一句用户输入,但在真实系统中,一次完整请求通常由多部分组成:
System Prompt:角色、规则、长期约束
User Prompt:当前任务、输入数据、输出要求
Examples(可选):Few-shot 示例
Context(可选):对话历史、检索结果、工具返回内容
所以更准确地说,Prompt Engineering 不是只改一句话,而是在设计:
- 哪些信息应该放 system
- 哪些应该放 user
- 哪些应该作为示例
- 哪些应该作为动态上下文
- 这些信息的顺序和组织方式是什么
这也是为什么生产环境里的 Prompt 工程,常常和“上下文工程(context engineering)”分不开。
Prompt 的价值边界:它能放大表现,但不能凭空造能力
这里有一个必须讲清楚的边界。
Prompt 可以:
- 更好地激活模型已有能力
- 提高输出稳定性
- 减少格式错误
- 降低幻觉概率
- 改善任务表现
但 Prompt 不能:
- 凭空注入模型根本没有的知识
- 让小模型瞬间变成大模型
- 让模型在没有依据时可靠地知道最新事实
- 从根本上消除所有推理错误
所以更准确的说法是:
模型的能力上限由训练决定,Prompt 决定的是你能把这部分能力稳定发挥到什么程度。
2. 角色 Prompt(Role Prompt):为什么“你是谁”会改变回答
先看定义:角色设定能让模型进入更合适的行为模式,从而改变回答的风格、粒度、边界和专业视角。
为什么角色会有效
角色 Prompt 有效,不是因为模型真的“变成了某个人”,而是因为训练数据里本来就包含大量带角色特征的文本模式。
例如:
- 技术支持的说话方式
- 教师的解释方式
- 律师的谨慎表达
- 产品经理的结构化思考
- 程序员的术语和代码风格
当你告诉模型:
你是资深 Python 工程师
你实际上是在向它发出一个强信号:
- 应该优先激活哪一类语言模式
- 应该用什么颗粒度解释问题
- 什么内容更 relevant
- 什么回答风格更像“合格的专家”
所以角色设定的本质是:
缩小模型需要猜测的回答风格空间。
弱角色和强角色的差别
弱角色
你是一个有帮助的助手。
这类 Prompt 当然也能用,但问题是:
- 太泛
- 没有专业边界
- 风格不明确
- 无法约束“有帮助”到底意味着什么
强角色
你是某科技公司的资深技术支持工程师,擅长 Python 和数据分析。
你的回答风格:简洁、专业、带必要代码示例。
优先给出可执行建议;不确定时明确说明需要进一步确认。
不回答与当前技术问题无关的内容。
这类角色 Prompt 更强,不是因为字更多,而是因为它补齐了四件事:
- 身份:你是谁
- 领域:你擅长什么
- 风格:你该怎么说
- 边界:你不该做什么
角色 Prompt 最适合放什么
角色 Prompt 特别适合承载以下信息:
- 角色身份
- 目标受众
- 语气风格
- 安全边界
- 回答优先级
- 高层行为原则
例如:
- 面向小白,避免术语
- 回答先给结论,再给原因
- 优先输出可执行步骤
- 不确定时说不确定,不要猜测
- 不输出内部推理,只给简明依据
这些设定很适合放在 system prompt 里,因为它们相对稳定、需要每轮生效。
角色 Prompt 的常见误区
1. 角色写得太空
例如“你是世界上最强的专家”。
这类说法听起来厉害,但对模型约束很弱。
2. 角色堆太多
比如同时要求模型是:
- 战略顾问
- 数据分析师
- 心理咨询师
- 法务顾问
- 创意总监
角色越混,输出越容易混乱。
3. 角色里塞太多知识
角色 Prompt 适合放规则和风格,不适合充当大型知识库。
如果知识经常变化,应该考虑 RAG,而不是无限拉长 system prompt。
3. Few-shot Prompting:为什么“示范”比“命令”更稳
先看定义:Few-shot 的本质不是给模型补知识,而是给模型看“这道题应该怎么做、输出应该长什么样”。
为什么 Few-shot 这么有效
很多任务失败,并不是模型完全不会,而是它不知道:
- 你要的结果是什么格式
- 哪些边界情况应该拒绝
- 哪种表达风格最符合预期
- 同类样本中最重要的模式是什么
Few-shot 的作用,就是直接给它看几个例子,让它少猜一点。
你可以把它理解成:
- 指令是在“讲要求”
- 示例是在“做演示”
对于模型来说,演示往往比抽象要求更有约束力。
0-shot、Few-shot、Many-shot
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 0-shot | 只给任务,不给例子 | 简单任务、强模型、边界清晰 |
| Few-shot | 给 1–5 个高质量示例 | 格式化、抽取、分类、改写 |
| Many-shot | 给更多示例 | 小模型、复杂映射、强约束任务 |
在很多场景里,一个好的 few-shot 示例,比再多写几句说明更有效。
因为模型看到的是:
输入长这样,输出就应该长这样。
一个简单例子:提取信息
只有指令
请从下面文本中提取公司名、融资轮次和金额。
这条指令本身不差,但模型可能会输出:
- 自由文本
- 缺字段
- 多解释几句
- 格式每次都不一样
加 Few-shot 之后
示例1
输入:星云科技完成数千万人民币 A 轮融资,由晨光资本领投。
输出:
{
"company": "星云科技",
"round": "A轮",
"amount": "数千万人民币"
}
示例2
输入:蓝海智能近日宣布获得天使轮投资,金额未披露。
输出:
{
"company": "蓝海智能",
"round": "天使轮",
"amount": "未披露"
}
这时模型会更容易学会:
- 输出 JSON
- 字段固定
- “未披露”也要填字段
- 不要额外解释
Few-shot 最大的价值,往往就在这种结构约束上。
怎么选示例才有效
1. 少而精
3 个高质量示例,通常比 10 个杂乱示例更有效。
2. 覆盖边界情况
不要只给“标准样本”,还应考虑:
- 缺失字段
- 异常输入
- 应拒绝的情况
- 容易混淆的类型
3. 格式高度一致
如果示例 A 用 JSON,示例 B 用列表,示例 C 用自然语言,模型就会困惑到底该模仿哪一种。
4. 和当前任务分布接近
示例越接近真实任务,效果通常越好。
拿新闻分类的例子去教法律文书抽取,帮助有限。
Few-shot 的副作用
Few-shot 虽然强,但也不是越多越好。
1. 占用上下文
示例本身会消耗 token,挤压真正任务输入的空间。
2. 过拟合示例风格
模型可能会模仿示例表面的语气和结构,导致泛化变差。
3. 把错误模式一并教进去
示例写错,模型会认真学错。
所以很实用的经验法则是:
先用 zero-shot + 清晰指令;不稳定,再加 few-shot。
4. 指令设计(Instruction Design):让模型少猜、多做
先看定义:好的指令不是“更礼貌”,而是“更清楚、更具体、更可执行”。
为什么模糊指令一定会带来模糊输出
模型不是读心术。
如果你说:
- “写点东西”
- “分析一下”
- “帮我优化”
- “弄成表格”
这些话在人和人之间也许还能靠上下文补全,但模型往往只能自己猜。
而一旦进入“猜”的状态,输出稳定性就会迅速下降。
所以好的指令设计,本质上是在回答四个问题:
- 你要模型做什么
- 你希望输出长什么样
- 你希望它遵守哪些边界
- 它不知道时应该怎么处理
模糊 vs 清晰
| 模糊写法 | 更清晰的写法 |
|---|---|
| 写点东西 | 写一段 200 字产品介绍,面向第一次接触该产品的用户 |
| 分析一下 | 列出 3 个优点和 3 个缺点,每点不超过 20 字 |
| 用 JSON | 输出 JSON,字段为 name、price、stock,缺失值填 null |
| 优化这段文案 | 保持原意不变,改得更简洁,适合 App 首页 Banner |
你会发现,清晰写法往往多补了这些维度:
- 目标
- 长度
- 受众
- 格式
- 缺失值处理
- 约束条件
一个好指令的四个关键部件
1. 任务目标
告诉模型这次到底是:
- 总结
- 改写
- 抽取
- 分类
- 评审
- 翻译
- 规划
- 生成结构化数据
2. 输入范围
告诉它应该基于什么材料回答,以及不能越界到哪里。
3. 输出格式
告诉它答案应该长什么样。
格式越明确,后续自动化越容易。
4. 失败策略
最容易被忽略的一点是:
模型不知道的时候怎么办?
例如你可以明确规定:
- 不确定就说“不确定”
- 找不到字段就填 null
- 信息不足时先列缺失项,不要编造
- 超出范围就拒答
这一步对降低幻觉非常重要。
约束不是“附加项”,而是 Prompt 的一半
很多 Prompt 写失败,不是任务目标没写,而是约束没写。
比如:
不要编造不存在的功能。
不要超过 200 字。
不要输出解释,只输出 JSON。
若信息不足,请明确写“无法判断”。
这些约束的价值在于:
- 把错误空间缩小
- 让输出更可控
- 降低后处理复杂度
- 降低“看起来像对,其实不对”的风险
从工程角度说,约束越清晰,模型的自由度越低,输出越稳定。
5. 输出格式设计:为什么“好解析”比“文采好”更重要
先看定义:在应用开发里,Prompt 设计的重点往往不是“让模型说得多漂亮”,而是“让模型输出能被系统稳定消费”。
对人看的输出,和对程序看的输出,是两回事
如果回答只是给人看,自然语言可读性很重要。
但如果回答还要被后端程序接着处理,那格式稳定性就比“写得优美”更重要。
例如这些任务:
- 信息抽取
- 分类标签
- 函数调用参数生成
- 审批流判断
- Agent 的下一步动作选择
它们都更依赖结构化输出。
常见格式控制方式
| 格式 | 适合场景 |
|---|---|
| JSON | 抽取、接口返回、程序消费 |
| 列表 | 步骤说明、要点总结 |
| Markdown 表格 | 对比、展示 |
| 分块输出 | 摘要 / 分析 / 建议 |
| 固定字段模板 | 审核、评分、打标签 |
例如:
请输出 JSON,格式为:
{
"summary": "",
"risks": [],
"next_steps": []
}
若某项缺失,使用空数组或 null,不要省略字段。
这种写法往往比“请结构化回答”强很多,因为它把“结构化”具体化了。
一条非常实用的经验
如果结果要被程序读取,就不要只写“请用 JSON”,而要把字段、缺失值规则、嵌套层级都写清楚。
否则模型很可能会:
- 多写解释
- 少字段
- 字段名漂移
- 在 JSON 外包一层自然语言
- 有时输出数组,有时输出对象
这些问题都不是模型“不会”,而是 Prompt 没把接口约定写清楚。
6. Chain-of-Thought(CoT):什么时候该“先分析再回答”
先看定义:对于多步推理任务,让模型先拆解再作答通常会更稳;但在生产环境里,重点不是一味追求冗长思维链,而是设计合适的中间步骤和输出结构。
CoT 为什么有效
复杂任务之所以容易错,一个重要原因是模型会“跳答案”。
比如一道多步题,直接要求最终结果时,模型可能在中途省略了关键推导。
而如果让它:
- 先识别问题类型
- 再列已知条件
- 再给推导过程
- 最后给结论
正确率通常会更高。
这背后的原因很直观:
复杂问题拆成小步后,每一步都更容易做对。
“Let’s think step by step” 为什么有用
经典写法是:
Let's think step by step.
或者:
请一步步分析后再回答。
这类提示会诱导模型生成中间过程,从而减少直接跳结论带来的错误。
但要注意,真正有效的往往不是这句英文魔法本身,而是它背后代表的策略:
让模型先展开任务结构,再输出结果。
更稳的做法:结构化推理,而不是泛泛“多想想”
与其只说“请一步步思考”,很多时候更好的写法是:
请按以下步骤回答:
1. 判断问题类型
2. 列出已知条件
3. 给出分析过程
4. 输出最终结论
或者:
先给出简短分析,再输出最终答案。
这样做有两个好处:
- 推理过程更可控
- 输出更容易检查和裁剪
在产品环境里,你通常并不需要模型生成很长、很散的“思维独白”,而是需要:
- 可用的中间结构
- 可审查的依据
- 可截断、可复用的结果
什么时候适合用 CoT
| 适合 | 不太适合 |
|---|---|
| 数学题、逻辑题 | 简单分类 |
| 多步规划 | 单字段抽取 |
| 需要解释依据 | 对延迟极度敏感的任务 |
| 复杂代码分析 | 高吞吐批处理中的轻任务 |
简单说:
任务越复杂、步骤越长、错误越可能出在中间,CoT 就越有价值。
CoT 的代价和风险
1. 输出更长
会增加 token 成本和延迟。
2. 有时会“越想越偏”
不是所有任务都适合展开过程,某些简单任务反而会被复杂化。
3. 不等于真实思维
模型生成的步骤不一定完全等价于它内部“真正如何得到答案”,所以不要把所有中间文本都当作可靠推理证据。
因此更实用的原则是:
对复杂任务,要设计“有用的中间步骤”;对简单任务,不要强迫模型长篇推理。
7. 常见错误与修复:为什么 Prompt 看起来没错,结果却不稳
很多 Prompt 失败,不是因为模型太笨,而是因为输入里留下了太多歧义。
错误 1:目标不清
表现
模型输出泛泛而谈,不知道重点是什么。
修复
把任务从“分析一下”改成:
- 分析什么
- 从哪个角度分析
- 输出几条
- 每条多长
错误 2:没有格式契约
表现
有时列表,有时段落;有时 JSON,有时自然语言。
修复
明确写出:
- 输出格式
- 字段名
- 缺失值处理
- 是否允许解释文本
错误 3:角色设定太空或太混
表现
回答风格漂移,时而像客服,时而像老师,时而像营销文案。
修复
角色不要多而杂,要明确:
- 身份
- 领域
- 语气
- 边界
错误 4:Few-shot 示例质量差
表现
模型认真模仿了错误示例,结果越改越离谱。
修复
少而精,只保留:
- 格式最稳的
- 边界最关键的
- 最接近真实任务的
错误 5:Prompt 太长,信息优先级混乱
表现
真正重要的任务被埋掉,模型抓不到重点。
修复
把 Prompt 按优先级重写:
- 角色 / 规则
- 当前任务
- 输出格式
- 约束
- 示例
- 辅助说明
不是所有信息都值得放进主 Prompt。
错误 6:把 Prompt 当“一次性作品”,不做测试
表现
偶尔有效,但换个输入就崩。
修复
把 Prompt 当成产品接口来测:
- 典型样本
- 边界样本
- 脏数据
- 空输入
- 对抗输入
Prompt 工程最容易被忽视的一点是:
它需要评测,而不只是灵感。
8. 五要素黄金公式:一条高质量 Prompt 通常包含什么
先看定义:高质量 Prompt 往往由五个核心要素组成:角色、目标、格式、约束、示例。
[角色] 你是谁,你的专业领域是什么
[目标] 这次具体要完成什么任务
[格式] 输出长什么样
[约束] 不要做什么,不确定时怎么办
[示例](可选)给几个高质量输入-输出演示
这五个要素不是每次都必须齐全,但它们构成了一个非常好用的检查框架。
模板示例
角色:你是客服助手,负责解答产品使用问题。
目标:根据用户问题,给出准确、简洁的答复。
格式:先给一句话结论,再分点说明(如有需要)。
约束:不知道的就说“需要转接人工”;不回答与产品无关的问题;不要编造政策。
示例:
用户:怎么重置密码?
助手:您可以通过“忘记密码”链接重置。步骤:1. 点击登录页的“忘记密码” 2. 输入注册邮箱 3. 查收邮件并点击链接 4. 设置新密码。
这个模板之所以有效,不是因为它“完整”,而是因为它把模型最容易猜错的几个地方都说清楚了。
9. 一个更工程化的理解:Prompt 不是文案,而是接口设计
当你把 Prompt 用在生产系统里,最应该建立的心态不是“我在写一段自然语言”,而是:
我在设计一个给模型调用的输入接口。
这意味着你需要考虑:
- 输入字段是否稳定
- 输出是否可解析
- 失败时是否有保底行为
- 换一个用户输入后会不会崩
- 是否方便评测和迭代
- 是否能和 RAG、工具调用、对话记忆拼起来
一旦你用这种视角看 Prompt,很多事情就会变简单:
- 角色 = 默认配置
- 约束 = 规则校验
- 示例 = 单元测试样本
- 格式 = 返回值 schema
- 评测 = 回归测试
Prompt 工程真正成熟的标志,不是你能写出多华丽的提示词,而是:
你能不能把模型输出变成一个稳定、可测、可维护的系统组件。
核心概念速查
| 概念 | 一句话 |
|---|---|
| Prompt Engineering | 通过设计输入和上下文组织方式,引导模型稳定完成任务 |
| Role Prompt | 用角色设定约束风格、边界和专业视角 |
| Few-shot | 用少量高质量示例教模型当前任务的做法和格式 |
| Instruction Design | 把任务、格式、约束和失败策略说清楚 |
| Output Contract | 让模型输出可解析、可复用的结构化结果 |
| CoT | 对复杂任务先分析再作答,提升多步任务稳定性 |
| 五要素 | 角色 + 目标 + 格式 + 约束 + 示例 |
下一篇
入门之后,真正难的不是“写一个 Prompt”,而是把 Prompt 系统化:
- 如何做结构化输出
- 如何管理 Prompt 模板版本
- 如何把 system、memory、RAG、tool use 拼成一套稳定链路
- 如何做评测、回归测试和迭代优化
- 什么样的 Prompt 设计才适合生产环境