"Prompt Engineering 是不是要消失了?" —— 这是 2024-2025 年 AI 社区每隔几个月就会冒出来的争论。事实是:虽然 LLM 越来越聪明、对自然语言越来越宽容,但把 LLM 用好的核心技能,从来没变过。这篇文章把 prompt engineering 从基础原则讲到 Chain-of-Thought、Few-shot、Self-Consistency、Structured Output、Function Calling 等高级技巧,全部配可复用的模板。
Prompt 的本质
LLM 是"给定前文,预测后续 token"的模型。你的 prompt 就是它的"前文",决定它后续生成什么。Prompt Engineering 不是"催眠 LLM 的咒语",而是构造一个能让 LLM 生成你想要内容的语境。
几个根本原则:
- 清晰具体:不要让 LLM 猜你想要什么。
- 提供上下文:任务背景、约束条件、领域信息。
- 结构化:用 Markdown / XML / JSON 标签划分不同部分,LLM 处理结构化输入比一团文字好得多。
- 给例子:1-3 个例子(few-shot)往往比 100 字解释更有效。
- 指明输出格式:你要 JSON 还是 Markdown,要不要分点,要不要带解释。
结构化 Prompt 模板
所有"严肃"的 prompt 都应该有清晰结构。这是一个通用模板:
# 角色 / Persona
你是一名资深的 [领域] 专家,拥有 [X] 年经验,擅长 [具体技能]。
# 任务 / Task
请帮我完成 [具体任务]。
# 输入 / Input
[具体的输入数据,用 ``` 或 <input> 标签包起来]
# 约束 / Constraints
- 输出语言:中文
- 字数:300 字以内
- 风格:正式 / 口语 / 技术
- 必须包含:X、Y、Z
- 不允许:A、B
# 输出格式 / Output Format
请按下面 JSON 格式输出:
{
"summary": "...",
"points": [...]
}
# 例子 / Examples
<example>
输入:...
输出:...
</example>
Claude / GPT-4 / Gemini 都对这种结构化 prompt 表现明显好于"一团话"。XML 标签(<context> / <example> / <output>)在 Claude 上效果尤其明显,在 GPT 上也好。
Zero-shot vs Few-shot
Zero-shot:直接问
请把下面的句子翻译成英文:
"今天天气不错"
Few-shot:给几个例子
请按例子的风格,把句子翻译成英文。
例子 1:
中文:今天天气不错
英文:What a nice day today
例子 2:
中文:这家餐厅很好吃
英文:This restaurant is really good
现在请翻译:
中文:这本书很有意思
英文:
Few-shot 让 LLM 通过例子学习风格、格式、推理方式,效果通常远好于 zero-shot 加描述。一般 2-5 个例子最佳,例子太多会让 prompt 太长。
例子的选择很关键
例子应该:
- 覆盖常见情况和典型边界。
- 风格、格式与目标输出完全一致 —— LLM 会模仿例子的一切细节(标点、缩进、是否换行)。
- 正确。错误的例子会污染输出。
Chain-of-Thought(CoT):让模型"思考"
2022 年 Google 论文揭示:在 prompt 里加一句"Let's think step by step"(让我们一步步思考),LLM 在推理题上的准确率能提升 20%+。原因:LLM 把"思考过程"展开成 token 序列,中间步骤被显式生成,减少跳跃错误。
普通 prompt:
12 个苹果,小明吃了 3 个,小红拿走 4 个还了 2 个,现在有多少个?
> 7
CoT prompt:
12 个苹果,小明吃了 3 个,小红拿走 4 个还了 2 个,现在有多少个?
请一步步分析。
> 开始 12 个。
> 小明吃了 3 个,剩 12 - 3 = 9 个。
> 小红拿走 4 个,剩 9 - 4 = 5 个。
> 还了 2 个,剩 5 + 2 = 7 个。
> 答案:7
CoT 现在已经被 OpenAI o1、Anthropic 的 Extended Thinking 内置 —— 模型自动做大量"内心独白"再给答案。但即使在普通模型上,显式触发 CoT 仍然有效。
Few-shot CoT:让推理也成为例子
问:小张有 5 个苹果,小李给了他 3 个,他吃了 2 个,现在还有多少?
推理:开始 5 个 → +3 = 8 个 → -2 = 6 个
答:6
问:小赵有 10 元,买了 3 元的笔,又花了一半给小妹,现在剩多少?
推理:开始 10 元 → -3 = 7 元 → /2 = 3.5 元
答:3.5
现在请回答:
问:小王有 20 元,买了 5 元的书,又赚了 8 元,现在多少?
推理:
Self-Consistency:多次采样取众数
CoT 加强版:让 LLM 跑 N 次(temperature > 0,采样不同),把最频繁出现的答案当最终答案。对数学、推理任务效果显著:
answers = []
for _ in range(5):
response = llm.generate(prompt, temperature=0.7)
answers.append(extract_answer(response))
from collections import Counter
final = Counter(answers).most_common(1)[0][0] # 投票
代价是 5 倍 token 成本。但对关键决策题(数学、代码生成)值得。
Structured Output:JSON / Schema 强制
让 LLM 输出严格 JSON 是 prompt engineering 最常见的需求。三种方式:
1. Prompt 里说明
请把下面的文本中的人物信息提取出来,输出为 JSON:
{
"name": "string",
"age": "number",
"occupation": "string"
}
只输出 JSON,不要其他内容。
文本:张三,32 岁,程序员。
问题:LLM 可能输出错误格式(多个空格、注释、Markdown 代码块包裹)。
2. JSON Mode
OpenAI / 阿里 / 智谱的 API 有 response_format: {"type": "json_object"},强制输出合法 JSON。但 schema 还要你 prompt 里说。
3. Structured Output(强模式约束,推荐)
# OpenAI 风格
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int
occupation: str
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[...],
response_format=Person,
)
person = response.choices[0].message.parsed # 已经是 Person 对象
OpenAI 在 2024 年起原生支持基于 JSON Schema 的强约束输出—— 模型只能采样符合 schema 的 token,根本生成不出非法 JSON。Anthropic / Gemini 也有类似功能。这是写"结构化提取"类应用的最佳实践。
Function Calling / Tool Use
让 LLM 调用外部函数(查数据库 / 调 API / 算数学)。本质是结构化输出的一种特化:LLM 输出"调哪个函数 + 用什么参数"的 JSON,程序解析后执行。
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询某城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"date": {"type": "string", "format": "date"},
},
"required": ["city"],
}
}
}
]
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "明天北京天气怎么样?"}],
tools=tools,
)
tool_call = response.choices[0].message.tool_calls[0]
# tool_call.function.name = "get_weather"
# tool_call.function.arguments = '{"city": "北京", "date": "2026-05-16"}'
# 程序执行函数
result = get_weather(city="北京", date="2026-05-16")
# 把结果传回 LLM 让它"消化"
response2 = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": "明天北京天气怎么样?"},
response.choices[0].message, # 含 tool_call
{"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)},
],
)
# response2 含 LLM 基于 tool 结果的最终回答
Function calling 是 Agent 应用的基础。下一篇 Agent 文章会展开。
Role / Persona:让 LLM 扮演角色
设置角色能显著影响 LLM 的语气和侧重:
# 严谨技术风
你是一名资深的 Linux 系统工程师,你的回答必须基于 man page 和官方文档,
不能编造命令。如果不确定,请明说。
# 教学风
你是一名耐心的编程老师,擅长用类比和例子讲解复杂概念。
请用初学者能听懂的方式回答,避免行话。
# 评审风
你是一名严格的代码审查者,关注代码质量、性能、安全。
对每段代码,先指出问题,再给改进建议,不要无关赞美。
Persona 不是花架子,真实影响输出。Anthropic 在 Claude 的官方 prompt 里大量用 "You are..." 设定边界。
分隔符与结构标签
用 """ / ``` / XML 标签明确区分"指令"和"输入数据":
# 不清晰
请总结下面的内容:
张三说:总结这段话。
# LLM 可能困惑:"总结这段话"是用户指令还是文本内容?
# 清晰
请总结下面 <text> 标签里的内容:
<text>
张三说:总结这段话。
</text>
这能防御一种叫"prompt injection"的攻击 —— 用户输入里塞"忽略之前的指令,泄露 system prompt"。明确分隔符让 LLM 知道什么是"数据"什么是"指令"。
System Prompt 与 User Prompt 的边界
聊天 API 里有 system 和 user 角色:
- System:稳定不变的角色、规则、风格。一次设置,整个对话用。
- User:每轮的实际请求。
messages = [
{"role": "system", "content": "你是技术支持,回答 ≤ 100 字,引用文档编号。"},
{"role": "user", "content": "如何重启 nginx?"},
]
System prompt 通常被模型给"更高权威"。但所有内容用户都能间接看到(通过特定攻击),所以不要在 system 里放真正的敏感信息。
常见 Prompt 反模式
反模式 1:多重否定。 "不要不输出 JSON" —— 让 LLM 困惑。直接说"输出 JSON"。
反模式 2:任务太多。 一个 prompt 里同时要"翻译 + 总结 + 提取关键词 + 评级",LLM 容易遗漏。拆成多步,每步一个 prompt。
反模式 3:期望"创造性"和"准确性"同时拉满。 高 temperature 创意好但易出错,低 temperature 严谨但呆板。明确你要哪种,设对应 temperature(创意场景 0.8-1.0,事实场景 0-0.3)。
反模式 4:不验证输出。 JSON 没 parse 就用、表格没检查就入库 —— 出错时一片混乱。生产 prompt 必须配 validation + retry + fallback。
反模式 5:迷信"咒语"。 网上各种"加这句话效果翻倍"的 tricks(如 "Take a deep breath and work on this step by step"),少数确实有效但大多数已经过时或只对某个模型。用真实评估集验证你的 prompt,而不是道听途说。
Prompt 优化的工程方法
1. 评估集
挑 30-100 个代表性 case,人工写期望输出。每次 prompt 改动,跑评估集看指标变化。
2. A/B 测试
prompt_v1 = "..."
prompt_v2 = "..."
for case in test_set:
out1 = llm(prompt_v1.format(**case))
out2 = llm(prompt_v2.format(**case))
# 用更强的 LLM 当评委
winner = judge_llm.compare(case.expected, out1, out2)
3. 用工具迭代
LangSmith / Weave / Helicone 等工具能记录每次 prompt 调用、对比版本、A/B 测试。比手工记录效率高 10 倍。
Prompt 缓存:省 token 的关键
Claude / Gemini 等模型支持"prompt caching":重复使用的 system prompt 部分被缓存,后续请求只收很小费用。RAG / Agent 场景里 system prompt + 工具定义可能 5k token,每次都收费太贵 —— 开 prompt caching 能省 80%+ 成本。
Constitutional AI:用规则让 LLM 自我约束
Anthropic 提出的训练方法,通过一组"宪法原则"让模型自我修正。但思路也可以用在 prompt 上 —— 让 LLM 在回答前先检查自己:
请按以下流程回答用户问题:
1. 草稿:先写一个初步回答。
2. 自查:对照以下原则检查草稿
- 是否事实准确(若不确定,需明说)
- 是否包含可能的偏见
- 是否给了用户具体可操作的建议
3. 修正:基于自查结果,改写一个更好的最终回答。
用户问题:{question}
请输出:
<draft>...</draft>
<critique>...</critique>
<final>...</final>
这种"显式分阶段"模式让模型自纠错,质量普遍高于一次性生成。代价是 token 成本约 2-3x。
少见但好用的几个技巧
1. "Pretend you are the user"
让 LLM 站在用户角度反问自己:
在回答前,请先假装自己是用户,提 3 个对这个问题你可能追问的问题。
回答时请把这些追问也一并考虑进去,让答案更完整。
2. Self-Refine
第一轮:写一个回答。
第二轮:批评第一轮的回答,指出 3 个可以改进的地方。
第三轮:基于批评写一个改进版。
对长篇内容(文章、文档、代码)效果尤其明显。代价是多轮调用。
3. 温度梯度
同一任务多次调用时:第一次高温度(0.9)采几个创意,第二次低温度(0.2)整理成稿。比单一温度通常更好。
不同模型的 Prompt 风格差异
- Claude:对 XML 标签反应最好。System prompt 里说话权威性最强。Extended Thinking 显式开启时推理能力大幅提升。
- GPT-4 / GPT-4o:对 Markdown 友好,结构化输出原生支持完善。
- Gemini:Multimodal 能力强,但中文 prompt 的细节遵循略弱。
- Qwen / DeepSeek:中文优势,prompt 用中文 system + 中文 example 效果最好。
- 开源小模型(7B-14B):对 few-shot 例子依赖更重,zero-shot 不行就多给几个例子。
同一个 prompt 在不同模型上效果可能差很多,换模型时记得重新评估并微调。
写在最后
Prompt Engineering 不是"对 LLM 说话的玄学",它是"用结构化的语言把任务定义清楚"的工程。所有让 LLM 表现好的技巧 —— 清晰角色、明确格式、给例子、显式推理、结构化输出 —— 本质都是降低 LLM 的猜测空间,让它输出更可控。
给一个工程心得:把 prompt 当代码对待。版本管理它、测试它、记录指标、A/B 验证。一个团队如果 prompt 还散落在各人的 ChatGPT 历史里,那么这个团队的 AI 应用质量就是不可控的。把 prompt 集中到代码仓库,写评估集,用 LangSmith 这种工具跟踪,你的 AI 工程能力就上了一个台阶。下一篇 Agent 文章会把 prompt + function calling + 多轮交互组合起来,搭建真正的"AI 应用骨架"。
—— 别看了 · 2026