大语言模型(LLM)的能力边界很大程度上取决于你怎么跟它说话。同样的模型,一个精心设计的Prompt可以得到专业级的回答,一个随意的Prompt可能只得到平庸甚至错误的结果。Prompt Engineering就是研究如何有效地与LLM沟通的技术。

一、Prompt的基本构成

1.1 一个Prompt的解剖

一个高质量的Prompt通常包含以下要素:

graph TD
    P["完整的Prompt"] --> R["角色
Role"] P --> C["上下文
Context"] P --> I["指令
Instruction"] P --> E["示例
Examples"] P --> F["格式要求
Format"] P --> CO["约束
Constraints"]
要素作用示例
角色设定模型的身份和专业背景“你是一位有10年经验的iOS架构师”
上下文提供背景信息“我们的项目使用MVVM架构,Swift语言”
指令明确说明任务“请review以下代码并指出问题”
示例展示期望的输入输出格式给出一个输入-输出样例
格式要求指定输出的结构“以Markdown表格形式输出”
约束限制条件“不超过500字"“只使用Swift标准库”

1.2 System Prompt vs User Prompt

在API调用中,消息分为不同的角色:

{
  "messages": [
    {
      "role": "system",
      "content": "你是一位资深iOS开发工程师,擅长性能优化。回答时给出具体的代码示例。"
    },
    {
      "role": "user", 
      "content": "如何优化UITableView的滚动性能?"
    }
  ]
}
  • System Prompt:设定模型的整体行为、角色和约束,贯穿整个对话
  • User Prompt:具体的问题或指令
  • Assistant:模型的历史回复,提供对话上下文

二、核心Prompt技术

2.1 Zero-Shot Prompting

直接给指令,不提供任何示例:

将以下文本分类为"正面"、"负面"或"中性":
"这个App启动速度很快,但UI有点丑。"

适用于简单任务和能力强的大模型。

2.2 Few-Shot Prompting

通过少量示例来"教"模型期望的行为模式:

将以下文本分类情感。

文本:"这个功能太棒了!"
分类:正面

文本:"应用总是崩溃。"
分类:负面

文本:"更新后界面有所改变。"
分类:中性

文本:"这个App启动速度很快,但UI有点丑。"
分类:

Few-Shot的关键:

  • 示例要覆盖不同的情况(包括边界案例)
  • 示例的格式要与期望的输出一致
  • 通常3~5个示例就足够了

2.3 Chain of Thought(思维链)

让模型"想一步说一步”,而不是直接给结论:

没有CoT

Roger有5个网球。他又买了2罐网球,每罐3个。他现在有多少个网球?
答案:11个

有CoT

Roger有5个网球。他又买了2罐网球,每罐3个。他现在有多少个网球?
让我们一步步思考:
1. Roger一开始有5个网球
2. 他买了2罐,每罐3个,所以买了 2 × 3 = 6 个
3. 总共有 5 + 6 = 11 个
答案:11个

CoT对推理类任务效果显著。简单的触发方式:在Prompt末尾加上 “Let’s think step by step”

2.4 ReAct(Reasoning + Acting)

结合推理和行动,模型交替进行"思考"和"调用工具":

问题:2024年诺贝尔物理学奖得主的年龄总和是多少?

思考:我需要先查找2024年诺贝尔物理学奖的得主是谁。
行动:搜索 "2024年诺贝尔物理学奖得主"
观察:John Hopfield 和 Geoffrey Hinton

思考:现在我需要查找他们各自的出生年份来计算年龄。
行动:搜索 "John Hopfield 出生年份"
观察:1933年

思考:再查Geoffrey Hinton的出生年份。
行动:搜索 "Geoffrey Hinton 出生年份"
观察:1947年

思考:John Hopfield在2024年是91岁,Geoffrey Hinton是77岁。总和是91+77=168。
答案:168岁

ReAct是AI Agent的核心推理模式,后续文章会深入讲解。

2.5 Self-Consistency(自一致性)

对同一个问题用相同的CoT Prompt多次采样(用较高的温度),然后对多个答案取多数投票

graph LR
    Q["问题"] --> S1["采样1 → 答案A"]
    Q --> S2["采样2 → 答案A"]
    Q --> S3["采样3 → 答案B"]
    Q --> S4["采样4 → 答案A"]
    Q --> S5["采样5 → 答案A"]
    
    S1 --> VOTE["多数投票"]
    S2 --> VOTE
    S3 --> VOTE
    S4 --> VOTE
    S5 --> VOTE
    VOTE --> R["最终答案:A"]

以数量换质量——多条推理路径更可能收敛到正确答案。

2.6 Tree of Thought(思维树)

CoT是一条线性推理链,ToT则将推理扩展为一棵树——每一步考虑多个可能的方向,评估后选择最优的分支继续:

graph TD
    ROOT["问题"] --> A["方向A"]
    ROOT --> B["方向B"]
    ROOT --> C["方向C"]
    
    A --> A1["A.1 ✓"]
    A --> A2["A.2 ✗"]
    
    B --> B1["B.1 ✗"]
    B --> B2["B.2 ✓"]
    
    A1 --> A1a["A.1.a → 最终答案"]
    B2 --> B2a["B.2.a → 备选答案"]

适用于需要探索和回溯的复杂问题(如数学证明、策略规划)。

三、高级Prompt模式

3.1 结构化输出

强制模型输出特定格式(JSON、XML、表格等):

分析以下代码的问题,以JSON格式输出:

{
  "issues": [
    {
      "severity": "high|medium|low",
      "line": "行号",
      "description": "问题描述",
      "fix": "修复建议"
    }
  ]
}

现代模型(GPT-4、Claude等)还支持在API层面强制JSON输出。

3.2 角色扮演与多角色辩论

让模型扮演多个角色从不同角度分析问题:

请分别从以下三个角色的视角评估"使用SwiftUI重写现有UIKit项目"这个决策:

1. **技术负责人**:关注技术可行性和团队技术栈
2. **产品经理**:关注交付时间和用户体验
3. **QA负责人**:关注测试覆盖和回归风险

每个角色给出明确的"支持/反对/有条件支持"立场和理由。

3.3 Mega-Prompt(超级提示词)

将多种技术组合成一个详尽的Prompt,适合复杂的持续性任务:

# 角色
你是一位资深的iOS架构师和代码审查专家。

# 背景
- 项目语言:Swift 5.9
- 最低支持:iOS 16
- 架构:MVVM + Coordinator
- 依赖管理:SPM

# 任务
对提交的代码进行全面审查。

# 审查维度
1. **架构一致性**:是否符合MVVM模式
2. **性能**:是否存在性能隐患
3. **安全性**:是否有内存泄漏、线程安全问题
4. **可维护性**:代码可读性、命名规范

# 输出格式
对每个问题使用以下格式:
- [严重程度] 文件:行号 - 问题描述
  建议:修复方案

# 约束
- 忽略纯风格问题(如空格、换行)
- 重点关注可能导致线上问题的bug

四、Prompt Engineering的原则

4.1 明确性原则

差的Prompt

帮我写段代码。

好的Prompt

用Swift编写一个URLSession网络请求封装,要求:
1. 支持GET和POST方法
2. 使用async/await
3. 自定义错误类型
4. 支持JSON解码为Codable对象

越具体,模型越能理解你的意图。

4.2 分治原则

复杂任务拆分为多个子任务,每个子任务用单独的Prompt完成:

graph TD
    T["重构整个网络层"] --> T1["1. 分析现有代码结构"]
    T --> T2["2. 设计新的接口协议"]
    T --> T3["3. 实现核心网络请求"]
    T --> T4["4. 添加错误处理"]
    T --> T5["5. 编写单元测试"]

而不是一个Prompt让模型完成所有事情。

4.3 迭代优化

Prompt Engineering是一个迭代过程:

graph LR
    A["初始Prompt"] --> B["测试效果"]
    B --> C{满意?}
    C -->|否| D["分析问题"]
    D --> E["调整Prompt"]
    E --> B
    C -->|是| F["固定Prompt"]

常见的调整方向:

  • 增加/减少约束
  • 添加具体示例
  • 调整指令的措辞
  • 改变输出格式要求

4.4 常见的Prompt反模式

反模式问题改进
过于模糊“帮我优化代码”指明优化的具体方向和约束
信息过载一次给太多无关上下文只提供与任务相关的信息
否定指令“不要使用第三方库”用肯定表述:“只使用Swift标准库”
假设模型知道上下文“继续上次的工作”在Prompt中提供完整上下文
多任务混杂一个Prompt包含5个不同任务拆分为多个独立的Prompt

五、Prompt在工程中的管理

5.1 Prompt模板化

将经过验证的Prompt抽象为可复用的模板:

REVIEW_TEMPLATE = """
你是一位{role}
请审查以下{language}代码:

```{language}
{code}

关注以下方面: {aspects}

以{format}格式输出审查结果。 """


### 5.2 Prompt版本管理

像管理代码一样管理Prompt:

prompts/ ├── code-review/ │ ├── v1.0.txt # 初始版本 │ ├── v1.1.txt # 增加了安全审查维度 │ └── v2.0.txt # 重构为结构化输出 ├── translation/ │ └── v1.0.txt └── changelog.md # 记录每次修改的原因和效果


### 5.3 Prompt评估

建立评估数据集,系统地衡量Prompt的效果:

| 指标 | 衡量内容 |
|------|---------|
| 准确率 | 输出是否正确 |
| 一致性 | 多次运行结果是否稳定 |
| 格式符合率 | 输出是否符合指定格式 |
| 延迟 | 由Prompt长度引起的响应时间变化 |
| 成本 | Token消耗量 |

## 六、总结

Prompt Engineering不是"玄学",而是一套可系统化学习和实践的技术。核心原则可以归纳为:

1. **明确意图**:告诉模型你要什么,而不是让它猜
2. **提供上下文**:模型不知道你的项目背景,需要你提供
3. **给出示例**:一个好的示例胜过千言万语的描述
4. **引导推理**:对复杂问题,引导模型一步步思考
5. **迭代优化**:没有完美的第一版Prompt,持续调整

随着模型能力的增强,Prompt Engineering的重心正在从"如何让模型理解意图"转向"如何让模型高效完成复杂任务"——而这正是AI Agent要解决的问题。