AI · #llm#ai#prompt-engineering

高级Prompt Engineering技巧与模式

2025.09.03 8 min 3.3k
// 目录 · contents

引言

Prompt Engineering 是与 LLM 高效沟通的艺术和科学。一个精心设计的 Prompt 可以将模型的输出质量提升一个量级,而错误的 Prompt 则会导致幻觉、偏差和不稳定的结果。本文将系统介绍从基础到高级的 Prompt 技巧——Few-shot Learning、Chain-of-Thought、Tree-of-Thought、System Prompt 设计、结构化输出、Prompt 链式编排以及常见的反模式与规避策略。

Prompt Engineering 技巧全景

graph TB
    A[Prompt Engineering] --> B[基础技巧]
    A --> C[推理增强]
    A --> D[输出控制]
    A --> E[高级模式]

    B --> B1[Zero-shot]
    B --> B2[Few-shot]
    B --> B3[Role Playing]

    C --> C1[Chain-of-Thought CoT]
    C --> C2[Tree-of-Thought ToT]
    C --> C3[Self-Consistency]
    C --> C4[ReAct]

    D --> D1[Structured Output]
    D --> D2[Format Instructions]
    D --> D3[Constrained Generation]

    E --> E1[Prompt Chaining]
    E --> E2[Meta-Prompting]
    E --> E3[Self-Refine]

    style A fill:#2c3e50,color:#fff
    style C fill:#e74c3c,color:#fff
    style D fill:#3498db,color:#fff
    style E fill:#2ecc71,color:#fff

Few-shot Learning

通过提供示例来引导模型的输出格式和风格:

基础 Few-shot

1
2
3
4
5
6
7
8
9
10
11
12
13
将以下句子分类为"正面"、"负面"或"中性"。

句子:这家餐厅的服务太棒了!
分类:正面

句子:今天天气一般般。
分类:中性

句子:等了两个小时还没上菜。
分类:负面

句子:新买的手机续航还不错,就是有点重。
分类:

动态 Few-shot 选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from langchain_core.prompts import FewShotPromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

# Examples pool
examples = [
{"input": "Python中如何读取文件?", "output": "```python\nwith open('file.txt', 'r') as f:\n content = f.read()\n```"},
{"input": "如何用JavaScript发送HTTP请求?", "output": "```javascript\nconst response = await fetch(url);\nconst data = await response.json();\n```"},
{"input": "Go中如何处理错误?", "output": "```go\nresult, err := doSomething()\nif err != nil {\n return fmt.Errorf(\"failed: %w\", err)\n}\n```"},
# ... more examples
]

# Select most relevant examples based on semantic similarity
selector = SemanticSimilarityExampleSelector.from_examples(
examples,
OpenAIEmbeddings(),
Chroma,
k=2, # Select top-2 most similar examples
)

# The prompt automatically picks the best examples for each query
dynamic_prompt = FewShotPromptTemplate(
example_selector=selector,
example_prompt=example_prompt_template,
prefix="你是一个编程助手。参考以下示例回答问题:",
suffix="问题:{input}\n回答:",
input_variables=["input"],
)

Chain-of-Thought (CoT)

CoT 通过引导模型展示推理过程来提升复杂问题的准确率:

Zero-shot CoT

1
2
3
4
问题:一个商店有100个苹果。第一天卖出了40%,第二天又进货了剩余数量的50%,
第三天又卖出了20个。最终还剩多少个苹果?

请一步一步思考后给出答案。

手动 CoT 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
问题:小明有3个红球和5个蓝球。他先给小红2个红球,再从小红那里拿回1个蓝球。
小明现在有多少个球?

思考过程:
1. 初始状态:小明有 3红 + 5蓝 = 8个球
2. 给小红2个红球后:小明有 (3-2)红 + 5蓝 = 1红 + 5蓝 = 6个球
3. 从小红拿回1个蓝球后:小明有 1红 + (5+1)蓝 = 1红 + 6蓝 = 7个球
答案:小明现在有7个球。

问题:一个水箱容量是200升。第一个水管每小时进水30升,第二个水管每小时排水10升。
水箱从空开始,多少小时后水满?

思考过程:

结构化 CoT Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
COT_PROMPT = """你是一个严谨的问题分析专家。请按以下步骤分析问题:

## 分析框架

1. **理解问题**:明确问题要求什么
2. **识别关键信息**:列出所有已知条件
3. **选择方法**:确定解题策略
4. **逐步推理**:展示完整的推理过程
5. **验证结果**:检查答案是否合理
6. **给出结论**:简洁陈述最终答案

## 问题
{question}

## 开始分析
"""

Tree-of-Thought (ToT)

ToT 扩展了 CoT,让模型探索多条推理路径并自我评估:

graph TD
    A[问题] --> B1[思路 A]
    A --> B2[思路 B]
    A --> B3[思路 C]

    B1 --> C1[评估: 60分]
    B2 --> C2[评估: 85分]
    B3 --> C3[评估: 40分]

    C2 -->|选择最佳| D1[深入展开思路B]
    D1 --> E1[子思路 B1]
    D1 --> E2[子思路 B2]

    E1 --> F1[评估: 90分]
    E2 --> F2[评估: 75分]

    F1 -->|最终选择| G[答案]

    style C2 fill:#2ecc71,color:#fff
    style F1 fill:#2ecc71,color:#fff
    style G fill:#3498db,color:#fff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
TOT_PROMPT = """针对以下问题,请生成3个不同的解题思路,然后评估每个思路的可行性。

问题:{question}

## 思路生成

### 思路1
[描述第一种解题方法]
可行性评分(1-10):
理由:

### 思路2
[描述第二种解题方法]
可行性评分(1-10):
理由:

### 思路3
[描述第三种解题方法]
可行性评分(1-10):
理由:

## 选择最佳思路
基于评估,选择得分最高的思路,并详细展开求解过程。

## 详细求解
[使用最佳思路完整求解]

## 最终答案
"""

System Prompt 设计

System Prompt 定义了 AI 的角色、能力边界和行为规范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SYSTEM_PROMPT = """# 角色定义
你是一个高级Python开发顾问,专注于后端开发和系统设计。

# 能力范围
- Python 3.8+ 特性和最佳实践
- Web框架: FastAPI, Django
- 数据库: PostgreSQL, Redis
- 系统设计和架构模式
- 代码审查和性能优化

# 行为规则
1. 所有代码示例使用Python 3.10+语法
2. 优先推荐类型注解和async/await
3. 遵循PEP 8和Google Python Style Guide
4. 解释WHY,不仅仅是HOW
5. 指出潜在的安全风险和性能陷阱
6. 不确定时明确说明,不要编造

# 回答格式
- 简短问题: 直接回答 + 代码示例
- 设计问题: 先分析需求 → 方案对比 → 推荐方案 + 理由
- 代码审查: 问题列表 + 严重程度 + 修改建议

# 约束
- 不提供与安全漏洞利用相关的建议
- 数据库查询必须使用参数化查询
- 敏感信息不硬编码,使用环境变量
"""

结构化输出

JSON 模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
JSON_OUTPUT_PROMPT = """分析以下技术文章并提取结构化信息。

文章:
{article}

请以JSON格式输出,包含以下字段:
{{
"title": "文章标题",
"summary": "50字以内的摘要",
"technologies": ["涉及的技术列表"],
"difficulty": "beginner | intermediate | advanced",
"key_points": [
{{
"point": "要点描述",
"importance": "high | medium | low"
}}
],
"related_topics": ["相关主题"]
}}

注意:
- 只输出JSON,不要包含其他文字
- 确保JSON格式正确
- technologies最多5个
- key_points最多3个
"""

XML 标签结构化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
分析用户反馈并提供分类结果。

<feedback>
{user_feedback}
</feedback>

请按以下XML格式输出:

<analysis>
<sentiment>positive|negative|neutral</sentiment>
<category>bug|feature_request|praise|complaint|question</category>
<urgency>high|medium|low</urgency>
<summary>一句话总结</summary>
<action_items>
<item priority="1">建议的行动1</item>
<item priority="2">建议的行动2</item>
</action_items>
</analysis>

Prompt Chaining — 链式编排

将复杂任务拆分为多个简单的 Prompt 步骤:

graph LR
    A[用户需求] --> B[Step 1<br/>需求分析]
    B --> C[Step 2<br/>技术方案]
    C --> D[Step 3<br/>代码生成]
    D --> E[Step 4<br/>代码审查]
    E --> F[Step 5<br/>测试用例]

    style A fill:#2c3e50,color:#fff
    style B fill:#3498db,color:#fff
    style C fill:#e74c3c,color:#fff
    style D fill:#f39c12,color:#000
    style E fill:#9b59b6,color:#fff
    style F fill:#2ecc71,color:#fff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Step 1: Analyze requirements
step1_prompt = """分析以下需求,提取关键功能点和非功能性需求:
需求:{requirement}

输出格式:
- 功能点:[列表]
- 非功能性需求:[列表]
- 技术约束:[列表]
"""

# Step 2: Design solution based on Step 1's output
step2_prompt = """基于以下需求分析,设计技术方案:
{step1_output}

请包含:
1. 架构选择及理由
2. 核心数据模型
3. API设计
4. 技术栈推荐
"""

# Step 3: Generate code based on Step 2's output
step3_prompt = """基于以下技术方案,生成核心代码实现:
{step2_output}

要求:
- 使用Python + FastAPI
- 包含类型注解
- 包含错误处理
- 包含文档字符串
"""

# Chain execution
async def execute_chain(requirement: str):
result1 = await llm.invoke(step1_prompt.format(requirement=requirement))
result2 = await llm.invoke(step2_prompt.format(step1_output=result1))
result3 = await llm.invoke(step3_prompt.format(step2_output=result2))
return {"analysis": result1, "design": result2, "code": result3}

Self-Refine — 自我改进

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
INITIAL_PROMPT = """请写一篇关于"{topic}"的技术博客大纲。
要求:结构清晰、内容全面、有深度。
"""

CRITIQUE_PROMPT = """请严格评审以下大纲,指出不足之处:
{draft}

从以下维度评审:
1. 结构完整性
2. 逻辑连贯性
3. 深度是否足够
4. 是否有遗漏的重要主题
5. 对目标读者是否友好

请列出具体问题。
"""

REFINE_PROMPT = """基于以下评审意见,改进大纲:

原始大纲:
{draft}

评审意见:
{critique}

请输出改进后的完整大纲。
"""

async def self_refine(topic: str, iterations: int = 2):
draft = await llm.invoke(INITIAL_PROMPT.format(topic=topic))

for i in range(iterations):
critique = await llm.invoke(CRITIQUE_PROMPT.format(draft=draft))
draft = await llm.invoke(REFINE_PROMPT.format(draft=draft, critique=critique))

return draft

常见反模式

反模式一:过于模糊

1
2
3
4
5
6
# BAD
帮我写个程序。

# GOOD
请用Python编写一个函数,接收一个整数列表作为参数,
返回列表中所有偶数的平方和。包含类型注解和至少3个测试用例。

反模式二:过度约束

1
2
3
4
5
6
7
8
# BAD — 过多矛盾的约束
请用50字以内全面详细地解释量子力学的基本原理,
包含所有重要公式和历史背景,用小学生能理解的语言。

# GOOD — 合理约束
用简单的语言解释量子力学中"叠加态"的概念。
目标读者:高中生。字数:200字左右。
可以用一个生活中的类比来帮助理解。

反模式三:假设模型知道上下文

1
2
3
4
5
6
7
8
9
10
11
# BAD
继续上次的内容。

# GOOD
我们正在讨论微服务架构的设计。
之前已经确定了以下决策:
1. 使用事件驱动架构
2. 消息队列选择Kafka
3. 数据库每个服务独立

现在请设计服务间的认证与授权方案。

反模式四:忽略输出格式

1
2
3
4
5
6
7
8
9
10
11
12
# BAD
分析这段代码的问题。
(模型可能输出散文、列表、表格等不可预测的格式)

# GOOD
分析这段代码的问题。

请按以下格式输出每个问题:
- 行号:<行号>
- 问题类型:bug | 性能 | 可读性 | 安全
- 描述:<问题描述>
- 建议:<修改建议>

Prompt 评估框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import json
from dataclasses import dataclass

@dataclass
class EvalCase:
input_text: str
expected_output: str
criteria: list[str]

def evaluate_prompt(prompt_template: str, eval_cases: list[EvalCase]) -> dict:
results = []

for case in eval_cases:
actual_output = llm.invoke(prompt_template.format(input=case.input_text))

# Score each criterion
scoring_prompt = f"""评估以下输出是否满足各项标准。

输入: {case.input_text}
期望输出: {case.expected_output}
实际输出: {actual_output}
评估标准: {json.dumps(case.criteria, ensure_ascii=False)}

对每个标准打分(0-1)并说明理由。JSON格式输出。"""

scores = llm.invoke(scoring_prompt)
results.append({"case": case.input_text, "scores": scores})

return results

总结

高效的 Prompt Engineering 需要以下核心能力:

  1. 明确性:清楚地表达任务需求和期望输出
  2. 结构化:使用模板、分隔符、标签组织 Prompt
  3. 示例驱动:通过 Few-shot 示例引导模型行为
  4. 推理引导:复杂问题使用 CoT/ToT 提升准确率
  5. 迭代优化:通过评估框架持续改进 Prompt

记住,Prompt Engineering 的本质是在向模型精确传达你的意图。最好的 Prompt 不是最长的,而是消除了最多歧义的。

作者 · authorzt
发布 · date2025-09-03
篇幅 · length3.3k 字 · 8 min
许可 · licenseCC BY-SA 4.0
$ echo "comments" · 评论