Prompt Engineering

是什么

Prompt Engineering(提示词工程)是设计和优化输入给 LLM 的文本(Prompt),以获得更准确、更有用输出的技术与方法论。

LLM 的能力是固定的,但 Prompt 的质量决定了你能调用出多少能力。Prompt Engineering 就是学会”如何正确地向 AI 提问”。

LLM 本质上是一个条件概率模型:P(输出 | Prompt)。Prompt 越好,输出的概率分布越集中在你期望的方向。


为什么需要 Prompt Engineering

同一个模型,不同的 Prompt,天差地别

❌ 差的 Prompt:
"写一篇关于 Docker 的文章"

✅ 好的 Prompt:
"你是一位有 10 年经验的 DevOps 工程师。请为前端开发者写一篇 Docker 入门指南,
要求:1)用通俗语言解释容器 vs 虚拟机;2)包含一个 Node.js 项目的完整 Dockerfile 示例;
3)控制在 1500 字以内。"

好的 Prompt 明确了:角色、受众、内容要求、格式约束。

编程的新形态

Prompt Engineering 不是”花式提问”,而是一种新的人机交互范式:

  • 传统编程:用代码精确描述逻辑
  • Prompt 编程:用自然语言描述意图,由 LLM 补全细节

基本原则

1. 明确具体

模糊的指令会得到模糊的回答。越具体,输出越可控。

❌ "帮我优化这段代码"
✅ "这段 JavaScript 函数处理 10 万条数据时耗时 3 秒,请从时间复杂度角度优化,
   保持函数签名不变,并解释优化思路。"

2. 提供上下文

LLM 只知道 Prompt 中给的信息。你认为”显而易见”的背景,模型可能完全不知道。

✅ "我在用 React 18 + TypeScript 开发一个后台管理系统。
   当前使用 useState 管理表单状态,表单有 20 个字段。
   请推荐更好的状态管理方案。"

3. 指定输出格式

如果你需要特定格式的输出,直接告诉模型。

✅ "请以 JSON 格式返回,结构如下:
   { "title": string, "summary": string, "tags": string[] }"

4. 分步拆解

复杂任务拆成多个步骤,比一次性塞进去效果好。

✅ "请分三步完成:
   1. 分析这段代码的性能瓶颈
   2. 列出可能的优化方案(至少 3 个)
   3. 实现最优方案并给出前后对比"

核心技巧

Zero-Shot Prompting

不给任何示例,直接下达指令。适合简单、明确的任务。

将以下英文翻译为中文:
"The quick brown fox jumps over the lazy dog."

Few-Shot Prompting

在 Prompt 中给出几个输入-输出示例,让模型”学会”任务模式。

请将以下技术词汇翻译为中文,保留英文原词:

Input: "Container orchestration"
Output: "容器编排(Container orchestration)"

Input: "Load balancing"
Output: "负载均衡(Load balancing)"

Input: "Service mesh"
Output:

模型会从示例中推断出格式和翻译风格。

适用场景

  • 模型不理解你想要的格式
  • 任务有特定的风格/规则
  • Zero-Shot 效果不理想时

Chain-of-Thought(CoT,思维链)

引导模型”一步一步思考”,显著提升推理类任务的准确率。

❌ 直接提问:
"一个商店有 23 个苹果,卖出 8 个后又进了 15 个,现在有多少个?"
→ 模型可能直接给错误答案

✅ 加入 CoT 引导:
"一个商店有 23 个苹果,卖出 8 个后又进了 15 个,现在有多少个?
请一步一步推理。"
→ 模型会先列出 23-8=15,再算 15+15=30

变体

  • Zero-Shot CoT:在 Prompt 末尾加 “Let’s think step by step”
  • Few-Shot CoT:给出包含推理过程的示例
  • Self-Consistency:多次采样,取出现最多的答案

System Prompt

设定模型的角色、行为准则和约束。通常通过 API 的 system 字段传入。

{
  "system": "你是一位高级前端工程师,专注于 React 和 TypeScript。
             回答要简洁、技术准确,并给出代码示例。
             如果问题超出你的专业范围,请明确告知。",
  "user": "如何实现一个自定义 Hook 管理分页?"
}

System Prompt 的设计要点:

  • 角色定义:明确专业领域和经验水平
  • 行为约束:输出格式、语言风格、长度限制
  • 兜底策略:不确定时的行为(坦诚说不知道 vs 推测标注)

结构化 Prompt

使用 Markdown 或 XML 标记组织复杂 Prompt,提高可读性和效果。

# 任务
分析以下 Pull Request 的代码变更。
 
# 输入
<code_diff>
...(PR diff 内容)
</code_diff>
 
# 要求
1. 检查是否有潜在的 Bug
2. 评估代码风格是否一致
3. 给出改进建议
 
# 输出格式
| 文件 | 行号 | 类型 | 说明 |
|------|------|------|------|

高级策略

ReAct(Reasoning + Acting)

让模型交替进行”思考”和”行动”,适合需要调用外部工具的场景:

问题:北京今天的天气适合户外跑步吗?

思考:我需要查看北京今天的天气数据。
行动:调用天气 API → 获取结果:晴,25°C,AQI 45
观察:天气晴朗,温度适中,空气质量优。
思考:这些条件都适合户外运动。
回答:适合。今天北京晴天,25°C,空气质量优,非常适合户外跑步。

这是 Agent 的核心推理模式之一。

自我反思(Self-Reflection)

让模型检查自己的输出,发现并纠正错误:

请回答以下问题,然后检查你的回答是否正确。如果发现错误,给出修正后的答案。

问题:...

少样本选择策略

Few-Shot 示例的质量直接影响效果:

  • 多样性:示例应覆盖不同类型的输入
  • 相关性:选择与目标任务最相似的示例
  • 排列顺序:最相关的示例放在最后(模型对末尾信息更敏感)
  • 数量:通常 3-5 个即可,过多会挤占上下文窗口

常见反模式

反模式问题改进
过度客气”能不能麻烦你帮我看一下…”直接下达指令
一次塞太多一个 Prompt 里要求 10 件事拆分为多轮对话
不给约束”写一篇文章”明确字数、格式、风格
不给上下文”这段代码有 Bug”给出完整代码、错误信息、环境
期望完美指望一次 Prompt 就得到理想输出迭代优化,多轮调整

Prompt 与代码的关系

在 AI 辅助开发场景中,Prompt 本质上就是”需求文档”:

传统开发:需求文档 → 开发者 → 代码
AI 开发:Prompt → LLM → 代码

好的 Prompt 和好的需求文档一样,需要:

  • 明确的输入/输出定义
  • 边界条件的说明
  • 期望行为的示例
  • 约束条件(性能、兼容性、风格)

延伸阅读