前言
在大语言模型已经成为日常开发工具的今天,很多人都有过这样的经历:同样的问题,你问出来得到的是敷衍的回答,别人问出来却是条理清晰、质量极高的专业输出;你写的 Prompt 让模型频频犯错,高手写的 Prompt 却能让模型表现出专家级的能力。
这中间的差距,就是 Prompt Engineering(提示工程)。
很多人对 Prompt Engineering 存在误解,认为这不过是"话术技巧",是"哄骗 AI 的小把戏",只要模型足够强大,Prompt 就不重要了。但事实恰恰相反:模型越强大,Prompt 的重要性就越高——因为模型的能力边界被极大拓宽,如何引导这些能力就成了决定输出质量的关键因素。
从 GPT-3 时代简单的 Zero-Shot 提问,到如今基于 Agent 的多轮反思、工具调用、结构化输出,Prompt Engineering 已经发展成了一门拥有完整理论体系和实践方法论的工程学科。一个好的 Prompt 工程师,能够让模型在相同参数下,将任务完成率从 50% 提升到 95% 以上,这其中的价值不言而喻。
本文将从零开始,系统地讲解 Prompt Engineering 的每一个核心技术。我们不仅会讲解理论,更会提供大量可直接复用的 Prompt 模板、代码示例和调优策略。无论你是刚开始接触 LLM 的新手,还是希望进一步提升 Prompt 水平的开发者,相信这篇文章都能给你带来实质性的帮助。
一、为什么 Prompt Engineering 如此重要?
在深入具体技术之前,我们首先要理解:为什么 Prompt Engineering 值得我们花时间去学习?
1.1 大语言模型的工作本质
大语言模型的核心能力是"预测下一个 token"。给定一段文本,模型会根据它在海量训练数据中学到的统计规律,计算出最可能出现的下一个词。这个看似简单的机制,在模型规模足够大时,涌现出了惊人的推理能力。
但这里有一个关键问题:模型的"智能"是被动触发的,它不会主动去做你没有明确要求它做的事情。
举个简单的例子,如果你问:
模型可能会直接给出一个错误答案(比如 398),因为它在"快速预测"模式下,倾向于给出看似合理的数字。但如果你换一种问法:
模型就会逐步计算:
然后给出正确答案 408。
同样的模型,同样的问题,仅仅因为 Prompt 不同,准确率从不到 50% 提升到了接近 100%。这就是 Prompt Engineering 的力量——它能唤醒模型沉睡的能力。
1.2 模型能力的"冰山效应"
我们可以把大语言模型的能力比作一座冰山:
- 水面以上(可见能力):简单的问答、翻译、摘要——这是模型"自动"就能做好的事情,不需要复杂的 Prompt
- 水面以下(潜在能力):复杂推理、代码生成、创意写作、多步骤规划——这些能力需要正确的 Prompt 才能被激发出来
大多数用户只用到了模型水面以上 10% 的能力,而 Prompt Engineering 能帮你发掘水面以下 90% 的潜力。
Google DeepMind 在 2023 年的一篇论文中指出:相同的模型,使用不同的 Prompt 策略,在数学推理任务上的表现差距可以超过 60%。 换句话说,一个好的 Prompt 策略带来的提升,可能比模型参数翻一倍还要大。
1.3 生产环境的现实约束
在实际生产环境中,我们还面临着很多现实约束:
- 成本控制:GPT-4o 很贵,Claude 3 Opus 更贵。如果每个查询花 0.1 美元,10000 次查询就是 1000 美元。好的 Prompt 能让你用更便宜的模型达到同样的效果。
- 可靠性要求:个人使用时,模型偶尔犯错没关系。但在生产环境中,99% 的准确率可能都不够。Prompt Engineering 能帮你把准确率提升到 99.9% 以上。
- 格式一致性:API 调用需要固定的 JSON 格式,数据库插入需要特定的数据结构。没有正确的 Prompt 控制,输出格式随时可能"漂移"。
- 安全与合规:如何防止prompt injection、如何过滤不当内容、如何确保输出符合监管要求——这些都需要专业的 Prompt 设计。
正是这些因素,使得 Prompt Engineering 成为了 AI 应用开发中不可或缺的核心技能。
二、Prompt Engineering 技术演进史
Prompt Engineering 并不是一成不变的,它随着大语言模型的发展而不断进化。了解这段历史,能帮助我们理解每项技术出现的背景和要解决的问题。
2.1 2020 年:Zero-Shot 时代
GPT-3 的发布让世界第一次见识到了大语言模型的潜力。当时的主流用法就是"直接提问":
这种方式称为 Zero-Shot Learning——不需要任何示例,模型直接根据指令完成任务。
Zero-Shot 的优点是简单,缺点也很明显:对于复杂任务,效果很差。模型就像一个刚入职的实习生,你说什么他做什么,但不会主动思考,也不会处理复杂情况。
2.2 2021 年:Few-Shot 革命
OpenAI 很快发现:如果你在 Prompt 中给出几个示例,模型的表现会大幅提升。这就是 Few-Shot Learning。
一个典型的 Few-Shot Prompt:
Few-Shot 的效果是惊人的——在很多任务上,仅仅添加 3-5 个示例,准确率就能从 50% 提升到 80% 以上。这也让人们意识到:大语言模型的学习能力远比我们想象的要强,它能从极少的示例中快速"理解"任务模式。
2.3 2022 年:Chain of Thought 突破
2022 年可以说是 Prompt Engineering 的里程碑年份。Google Research 发表了那篇著名的《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》,彻底改变了整个领域。
他们发现了一个极其简单却异常有效的技巧:只要在 Prompt 中加上一句"让我们一步步思考",模型的推理能力就会出现质的飞跃。
一个经典的 CoT Prompt:
Chain of Thought 为什么有效?因为它强迫模型"慢下来"——不再是直接跳到答案,而是像人类一样逐步推理。这极大地减少了计算错误和逻辑跳跃,在数学推理、逻辑谜题、多步骤规划等任务上,CoT 能将准确率提升 40%-80%。
这篇论文引发了 Prompt Engineering 的爆发式发展,此后各种变体如雨后春笋般涌现:
- Zero-Shot CoT:不需要示例,直接加上"让我们一步步思考"
- Self-Consistency:生成多个推理路径,投票选出最一致的答案
- Least-to-Most:将复杂问题分解为小问题,逐步解决
2.4 2023-2024 年:高级技术爆发期
这两年,Prompt Engineering 进入了百花齐放的阶段:
Tree of Thoughts(思维树):不再是单条推理链,而是同时探索多条路径,像搜索树一样对每个节点进行评估和剪枝。在需要深度搜索的问题上(如数独、创意写作),ToT 的表现远超普通 CoT。
Graph of Thoughts(思维图):在思维树的基础上进一步扩展,允许不同推理路径之间的融合与循环,能够处理更加复杂的系统性问题。
结构化输出技术:OpenAI 推出了 Function Calling 和 JSON Mode,Anthropic 推出了 Prompt Caching,社区则开发出了 Outlines、Guidance 等库。这些技术让我们能够精确控制模型的输出格式,不再需要用正则表达式去"抢救"混乱的输出。
2.5 2026 年:Agent 化与工具调用
今天,Prompt Engineering 已经超出了"单轮对话"的范畴,进入了 Agent 时代:
- 多轮反思:让模型自己检查输出、发现问题、进行修正
- 工具调用:在 Prompt 中定义工具接口,让模型自主决定何时调用 API、搜索数据库或执行代码
- 规划-执行循环:先制定计划,再分步执行,遇到问题动态调整
这背后的核心理念是:不要试图用一个完美的 Prompt 解决所有问题,而是用多个 Prompt 组成一个系统,让模型在不断的反馈循环中逼近最优解。
理解了这段历史,我们就可以开始系统地学习每一项核心技术了。
(第一部分完,约 2300 字)
三、核心技术一:角色设定(Persona)
角色设定是所有 Prompt 技术中最简单、投入产出比最高的一项技术。它的核心理念是:不要把模型当成一个通用问答机器,而是把它当成一个具体的专家。
3.1 为什么角色设定有效?
大语言模型在训练过程中见过了海量的文本,它"知道"不同身份的人会如何说话、如何思考:
- 医生会用专业的医学术语,会强调风险和禁忌症
- 程序员会写注释,会考虑边界情况,会做错误处理
- 老师会循序渐进,会用简单的语言解释复杂概念
- 律师会引用法条,会强调法律风险
当你告诉模型"你是一个资深架构师",它就会激活训练数据中所有与架构师相关的模式,输出质量自然大幅提升。
3.2 角色设定的三层结构
一个好的角色设定应该包含三个层次:
你是一个【身份级别】的【具体角色】,拥有【年数】年的【领域】经验。
你的擅长领域包括:
- 【技能1】
- 【技能2】
- 【技能3】
你的工作风格是:
- 【风格描述1】
- 【风格描述2】
错误示例(太模糊):
正确示例(清晰具体):
对比一下两者的输出,差距可能会大到让你惊讶。
3.3 常用角色模板
以下是几个经过验证的高质量角色模板,可以直接使用:
资深代码审查专家:
技术文档写作专家:
产品经理:
3.4 角色设定的进阶技巧
技巧1:反向角色设定
有时候,告诉模型"不要成为什么"比"要成为什么"更有效:
技巧2:混合角色
对于复杂任务,可以设定多个角色的组合:
技巧3:引用具体人物
如果模型知道某个具体人物,可以直接引用:
四、核心技术二:思维链(Chain of Thought)
思维链是 Prompt Engineering 中最重要的技术,没有之一。几乎所有复杂任务都需要用到 CoT。
4.1 三种 CoT 模式
模式1:Zero-Shot CoT
最简单的 CoT,只需要在 Prompt 结尾加上一句话:
或者更具体一点:
这种方式的优点是不需要写示例,缺点是推理质量可能不够稳定。适合快速验证,或者作为更复杂 Prompt 的保底。
模式2:Few-Shot CoT(推荐)
这是最常用、效果最好的模式。你需要给出 1-2 个完整的推理示例:
研究表明,只需要 1-2 个高质量的示例,就能让模型的推理质量达到非常高的水平。示例不在多,在于质量——示例的推理过程越清晰、越详细,模型学到的就越好。
模式3:Self-Consistency(自我一致性校验)
对于特别重要的问题,可以让模型生成多个推理路径,然后投票选出最一致的答案:
这种方式虽然成本增加了 3 倍,但准确率可以从 90% 提升到 99% 以上。在生产环境的关键路径上,这是非常值得的投入。
4.2 CoT 的进阶技巧
技巧1:明确划分思考阶段
不要只说"一步步思考",要具体说明每一步应该做什么:
技巧2:强制"慢思考"
大语言模型有时会"跳步"——跳过中间推理直接给出答案。你可以用这种方式强迫它慢下来:
技巧3:引入"自我批评"环节
让模型自己检查自己的推理,这能显著减少错误:
五、核心技术三:少样本学习(Few-Shot)
Few-Shot 是让模型快速理解任务模式的最有效方法。很多时候,你说一千遍"请按照 XX 格式输出",不如给一个具体的示例。
5.1 Few-Shot 的设计原则
原则1:示例要代表真实情况
不要用太简单、太理想化的示例。示例应该尽可能接近你实际要处理的数据。
举个例子,如果你想让模型从用户评论中提取情感和关键词:
不好的示例:
好的示例:
第二个示例包含了混合情感、多个关键词、口语化表达,更接近真实场景,模型学到的效果会好很多。
原则2:示例要覆盖边界情况
在示例中故意包含一些边界情况和异常情况:
这样模型就学会了如何处理异常输入,而不是遇到不寻常的情况就"崩"掉。
原则3:示例数量要合适
- 简单任务(分类、提取):2-3 个示例就够了
- 中等任务(摘要、改写):3-5 个示例
- 复杂任务(代码生成、推理):5-10 个示例
太多示例反而会让模型困惑,还会增加 token 成本。根据任务复杂度找到平衡点即可。
5.2 常见的 Few-Shot 应用场景
场景1:JSON 格式输出
场景2:代码风格统一
场景3:客服回复模板
(第二部分完,约 2700 字)
六、核心技术四:结构化输出控制
在生产环境中,输出格式的稳定性往往比输出内容的质量更重要——如果模型输出的 JSON 多了一个逗号、少了一个引号,整个系统都会崩溃。
6.1 三种结构化输出方案
方案1:原生 JSON Mode(推荐)
最新的大模型(GPT-4o、Claude 3、Gemini 1.5)都原生支持结构化输出。你只需要在 API 调用时指定 response_format: {"type": "json_object"},模型就会保证输出是有效的 JSON。
配合 JSONSchema,你可以精确控制每一个字段:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-2024-05-13",
messages=[
{"role": "system", "content": "你是一个意图识别助手。"},
{"role": "user", "content": "帮我订一张明天去广州的机票"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "intent_classification",
"schema": {
"type": "object",
"properties": {
"intent": {"type": "string", "enum": ["flight_booking", "hotel_booking", "other"]},
"destination": {"type": "string"},
"date": {"type": "string"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
},
"required": ["intent", "confidence"]
}
}
}
)
这种方式的优点是 100% 可靠,缺点是需要使用最新的模型和 API。
方案2:Prompt 级别的格式控制
如果模型不支持原生 JSON Mode,你可以用 Prompt 来约束输出格式:
关键技巧:
- 明确说"不要添加任何额外内容"
- 强调"可以直接被 JSON.parse() 解析"
- 给出完整的格式示例
- 最后说"现在开始处理",暗示模型应该直接输出了
方案3:使用结构化输出库
社区有很多优秀的库可以帮助你确保输出格式正确:
- Outlines:使用正则表达式和 JSONSchema 约束模型输出
- Guidance:微软推出的模板引擎,可以精确控制输出结构
- Instructor:基于 Pydantic 的结构化输出库,和 OpenAI API 完美集成
使用 Instructor 的示例:
from pydantic import BaseModel, Field
from instructor import patch
from openai import OpenAI
patch()
class UserInfo(BaseModel):
name: str = Field(description="用户姓名")
age: int = Field(description="用户年龄,必须是数字")
interests: list[str] = Field(description="用户兴趣列表")
client = OpenAI()
user = client.chat.completions.create(
model="gpt-4o",
response_model=UserInfo,
messages=[{"role": "user", "content": "提取这句话中的用户信息:小明今年25岁,喜欢编程和打篮球"}]
)
print(user.name) # 小明
print(user.age) # 25
print(user.interests) # ['编程', '打篮球']
这些库的核心原理是在生成过程中动态过滤不符合格式要求的 token,从而确保输出 100% 符合你的 Schema。
6.2 格式控制的进阶技巧
技巧1:使用分隔符
如果需要同时输出自由文本和结构化数据,可以使用明确的分隔符:
这样你可以在代码中用 .split("===")[-1].strip() 安全地提取 JSON 部分。
技巧2:预留"思考区"
你可以让模型在正式输出前先"自言自语"一会儿,整理思路:
研究表明,这种方式能显著提高输出质量——模型就像在打草稿,把混乱的思考过程放在草稿区,最终输出就会更清晰。
七、常见的 Prompt 反模式与坑
学习了好的做法,我们还要知道哪些是不好的做法。以下是最常见的错误:
7.1 反模式一:Prompt 太模糊
错误:
什么叫"好"?用于什么场景?需要什么功能?模型只能猜。
正确:
7.2 反模式二:指令矛盾
错误:
“详细"和"不要太长"是矛盾的,模型会困惑。
正确:
给出明确的约束,而不是相互矛盾的形容词。
7.3 反模式三:否定指令太多
错误:
模型对否定指令的理解能力远弱于肯定指令。说一堆"不要做什么”,不如直接说"要做什么"。
正确:
7.4 反模式四:一次性要求太多
错误:
一次性把所有任务堆在一起,模型很容易遗漏或者出错。
正确: 把复杂任务拆分成多个步骤,或者用结构化输出明确每个字段。
7.5 反模式五:不做错误处理
很多人写 Prompt 时只考虑理想情况,不考虑异常情况。但在生产环境中,异常情况才是常态:
- 输入是空的怎么办?
- 输入是乱码怎么办?
- 模型无法理解输入怎么办?
- 模型不确定答案怎么办?
好的 Prompt 会明确处理异常:
八、生产环境 Prompt 最佳实践
8.1 Prompt 版本管理
把 Prompt 当成代码来管理:
- 存入 Git,有版本历史
- 每个改动要有 Changelog
- 有回滚机制
- 有测试用例
一个好的 Prompt 文件结构:
8.2 Prompt 测试体系
对 Prompt 建立完整的测试体系:
单元测试:测试边界情况、异常输入、典型案例
def test_empty_input():
result = call_prompt("")
assert result["status"] == "error"
def test_typical_case():
result = call_prompt("我想订明天去北京的机票")
assert result["intent"] == "flight_booking"
assert result["confidence"] > 0.9
回归测试:每次修改 Prompt 后,运行完整的测试集,确保没有破坏已有的功能
A/B 测试:新的 Prompt 先小流量上线,和旧版本对比准确率、延迟、成本等指标
8.3 成本优化策略
Prompt 成本优化是一个很大的话题,这里给出几个最有效的技巧:
技巧1:选择合适的模型
- 简单任务(分类、提取)用 GPT-3.5-turbo 或 Claude 3 Haiku
- 中等任务用 GPT-4o-mini 或 Claude 3 Sonnet
- 复杂任务才用 GPT-4o 或 Claude 3 Opus
很多人一上来就用最贵的模型,但实际上 80% 的任务用便宜的模型就能做好。
技巧2:利用 Prompt Caching
Claude 和 GPT-4o 都支持 Prompt Caching——固定的系统提示和示例只需要计算一次,后续调用可以复用缓存,成本能降低 50%-90%。
关键是把不变的内容放在 Prompt 的前面,把可变的用户输入放在后面。
技巧3:动态 Prompt 长度
不要把所有示例都硬编码在 Prompt 里,可以根据任务复杂度动态选择示例:
- 简单输入:用 1 个示例
- 中等输入:用 3 个示例
- 复杂输入:用 5 个示例
8.4 安全与防护
Prompt Injection 防护
Prompt Injection 是指用户通过精心构造的输入,让模型忽略你的系统提示,执行恶意指令。基本的防护措施:
- 输入清理:过滤掉可疑的关键词和模式
- 分隔符隔离:用特殊分隔符包裹用户输入,告诉模型"这是不可信的用户输入"
- 后处理校验:模型输出后,再用另一个简单的模型检查是否有异常
九、完整的 Prompt 模板示例
最后,给出几个可以直接在生产环境使用的完整 Prompt 模板。
9.1 通用代码审查模板
{{code}}
9.2 用户反馈分析模板
十、总结与展望
Prompt Engineering 从最初的"话术技巧",发展到今天已经成为了一门完整的工程学科。回顾本文的核心内容:
核心技术:
- 角色设定:把模型当成具体的专家,而不是通用助手
- 思维链:让模型逐步推理,而不是直接跳到答案
- 少样本学习:用示例代替描述,让模型直观理解任务
- 结构化输出:精确控制输出格式,确保生产环境可用
实践原则:
- 具体优于模糊,肯定优于否定
- 覆盖边界情况,处理异常输入
- 像代码一样管理 Prompt,建立测试体系
- 持续优化成本和性能
未来展望:
很多人说"模型越来越聪明,Prompt Engineering 会消失"。我对此持相反的观点:模型越强大,Prompt Engineering 就越重要——因为你能用模型做的事情越多,如何高效地引导这些能力就越关键。
未来的 Prompt Engineering 不会消失,但会进化:
- 从"手写 Prompt"进化到"自动优化 Prompt"——用 AI 来写和调优 Prompt
- 从"单轮对话"进化到"多 Agent 系统"——多个智能体协作完成复杂任务
- 从"技巧驱动"进化到"理论驱动"——建立更加系统化的理论框架和评估体系
但无论技术如何发展,有一件事是不变的:清晰的思考才能产生清晰的 Prompt,清晰的 Prompt 才能产生高质量的输出。
Prompt Engineering 本质上是把你的思维过程外化,传递给模型的一门艺术。当你能够清晰地表达自己的想法、拆解复杂的问题、设计合理的验证机制时,你就已经是一个优秀的 Prompt Engineer 了。
希望这篇文章能帮助你在这条路上走得更远。
(全文完,约 7800 字)