自然语言处理(七)—— 提示工程与 In-Context Learning
Chen Kai BOSS

在大语言模型时代,如何与模型"对话"成了一门艺术。同样的模型,不同的提示( Prompt)可能产生截然不同的结果。提示工程( Prompt Engineering)正是研究如何设计有效的输入,让模型发挥出最佳性能的技术。从简单的零样本提示到复杂的思维链推理,从角色设定到模板设计,提示工程已经成为使用大模型的核心技能。

In-Context Learning(上下文学习)是提示工程的理论基础。它揭示了模型如何通过示例学习,如何在推理时动态调整行为,以及为什么少样本提示往往比零样本提示效果更好。理解这些机制不仅能帮助我们写出更好的提示,更能深入理解大语言模型的工作方式。

本文将系统介绍提示工程的核心概念与实践技巧,包括零样本、少样本、思维链提示,角色设定与格式化技巧,提示模板设计, Self-Consistency 和 ReAct 等高级技术,并通过实战案例展示如何构建高效的提示系统。

提示工程基础与原则

提示工程的基本思路:通过精心设计的输入文本,引导模型产生期望的输出。一个好的提示应该清晰、具体、包含必要的上下文信息。

提示工程的基本原则

1. 清晰性( Clarity)

提示应该明确表达任务要求,避免歧义。对比以下两个提示:

  • ❌ 差:"分析这个文本"
  • ✅ 好:"请分析以下文本的情感倾向,并给出积极、消极或中性的判断"

2. 具体性( Specificity)

提供具体的输出格式要求,让模型知道如何组织答案:

1
2
3
4
5
6
7
8
9
10
prompt = """
请分析以下产品的优缺点,并按照以下格式输出:
优点:
1. ...
2. ...

缺点:
1. ...
2. ...
"""

3. 上下文完整性( Context Completeness)

确保提示包含完成任务所需的所有信息:

1
2
3
4
5
6
7
8
9
# 缺少上下文
prompt1 = "翻译这句话"

# 包含完整上下文
prompt2 = """
请将以下英文句子翻译成中文,保持原意和语气:
英文: The quick brown fox jumps over the lazy dog.
中文:
"""

4. 角色设定( Role Assignment)

为模型设定明确的角色,可以显著提升输出质量:

1
2
3
4
5
prompt = """
你是一位经验丰富的 Python 编程专家,擅长编写清晰、高效的代码。
请为以下需求编写 Python 函数:
需求:实现一个快速排序算法
"""

提示的组成要素

一个完整的提示通常包含以下部分:

  1. 指令( Instruction):明确告诉模型要做什么
  2. 上下文( Context):提供背景信息
  3. 输入数据( Input Data):需要处理的具体内容
  4. 输出格式( Output Format):期望的输出结构
  5. 示例( Examples):可选的示例,用于演示期望行为
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
def build_prompt(instruction, context, input_data, output_format=None, examples=None):
prompt_parts = []

# 角色设定(可选)
prompt_parts.append("你是一位专业的数据分析师。")

# 指令
prompt_parts.append(f"任务:{instruction}")

# 上下文
if context:
prompt_parts.append(f"背景信息:{context}")

# 示例
if examples:
prompt_parts.append("示例:")
for ex in examples:
prompt_parts.append(f"输入:{ex['input']}")
prompt_parts.append(f"输出:{ex['output']}")

# 输出格式
if output_format:
prompt_parts.append(f"输出格式:{output_format}")

# 输入数据
prompt_parts.append(f"请处理以下数据:\n{input_data}")

return "\n\n".join(prompt_parts)

零样本、少样本与思维链提示

零样本提示( Zero-shot Prompting)

零样本提示是最简单的提示方式:直接给出任务描述,不提供任何示例。

1
2
3
4
5
zero_shot_prompt = """
请判断以下句子的情感倾向:
句子:这部电影的剧情非常精彩,演员表演也很出色。
情感:
"""

适用场景: - 模型对任务有较好的先验知识 - 任务相对简单直接 - 需要快速测试模型能力

局限性: - 对于复杂任务,模型可能理解偏差 - 输出格式可能不符合预期 - 难以处理需要多步推理的任务

少样本提示( Few-shot Prompting)

少样本提示通过提供少量示例,让模型学习任务模式。这是 In-Context Learning 的核心体现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
few_shot_prompt = """
请判断以下句子的情感倾向(积极/消极/中性):

示例 1:
句子:今天天气真好,阳光明媚。
情感:积极

示例 2:
句子:这个产品质量很差,完全不值这个价格。
情感:消极

示例 3:
句子:明天会下雨。
情感:中性

现在请判断:
句子:这家餐厅的服务态度让人印象深刻。
情感:
"""

少样本提示的优势

  1. 模式学习:模型通过示例学习任务模式
  2. 格式对齐:示例展示了期望的输出格式
  3. 任务适应:即使模型未专门训练,也能快速适应新任务

示例选择原则

  • 多样性:覆盖不同类型的输入
  • 代表性:选择典型的、边界清晰的示例
  • 相关性:示例应该与目标任务高度相关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def create_few_shot_prompt(task_description, examples, query):
prompt = f"{task_description}\n\n"
prompt += "示例:\n"

for i, ex in enumerate(examples, 1):
prompt += f"示例{i}:\n"
prompt += f"输入:{ex['input']}\n"
prompt += f"输出:{ex['output']}\n\n"

prompt += f"现在请处理:\n 输入:{query}\n 输出:"
return prompt

# 使用示例
examples = [
{"input": "今天天气真好", "output": "积极"},
{"input": "这个产品质量很差", "output": "消极"},
{"input": "明天会下雨", "output": "中性"}
]

prompt = create_few_shot_prompt(
"请判断句子的情感倾向",
examples,
"这家餐厅的服务态度让人印象深刻"
)

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

思维链提示要求模型展示推理过程,逐步思考问题。这对于复杂推理任务特别有效。

标准 CoT 提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cot_prompt = """
请解决以下数学问题,并展示你的推理过程:

问题:小明有 15 个苹果,他给了小红 3 个,又给了小华 5 个,最后自己吃了 2 个。请问小明还剩多少个苹果?

推理过程:
1. 小明最初有 15 个苹果
2. 给小红 3 个后,剩余: 15 - 3 = 12 个
3. 给小华 5 个后,剩余: 12 - 5 = 7 个
4. 自己吃了 2 个后,剩余: 7 - 2 = 5 个

答案: 5 个

现在请解决:
问题:一本书有 120 页,第一天读了 30 页,第二天读了第一天的 2 倍,第三天读了剩余页数的一半。请问第三天读了多少页?
"""

少样本 CoT

1
2
3
4
5
6
7
8
9
10
11
12
13
few_shot_cot = """
请解决以下问题,展示推理步骤:

问题 1:一个篮子里有 8 个苹果,拿走了 3 个,又放回了 2 个。现在有多少个?
推理:最初 8 个,拿走 3 个后剩 5 个,放回 2 个后是 7 个。
答案: 7 个

问题 2:商店有 20 件商品,卖出了 12 件,又进货了 8 件。现在有多少件?
推理:最初 20 件,卖出 12 件后剩 8 件,进货 8 件后是 16 件。
答案: 16 件

问题 3:班级有 30 个学生,转走了 5 个,又转来了 7 个。现在有多少个学生?
"""

CoT 的数学表达

对于问题 , CoT 提示引导模型生成推理步骤序列 ,最终得到答案

$$

P(A | Q) = {i=1}^{k+1} P(R_i | Q, R{<i}) $$

其中 是最终答案。

CoT 的优势

  1. 提升准确性:展示推理过程有助于模型避免错误
  2. 可解释性:用户可以理解模型的思考过程
  3. 复杂推理:对于多步推理任务效果显著

角色设定与格式化技巧

角色设定( Role Assignment)

为模型设定明确的角色可以显著改变输出风格和质量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
role_prompts = {
"expert": """
你是一位拥有 20 年经验的 Python 高级工程师,擅长编写高效、可维护的代码。
请为以下需求编写代码:
""",

"teacher": """
你是一位耐心的编程老师,擅长用简单易懂的方式解释复杂概念。
请解释以下概念:
""",

"analyst": """
你是一位资深数据分析师,擅长从数据中发现洞察。
请分析以下数据:
""",

"creative": """
你是一位富有创意的文案写手,擅长撰写吸引人的文案。
请为以下产品撰写文案:
"""
}

角色设定的效果

  • 专业性:专家角色产生更专业、技术性更强的输出
  • 风格一致性:角色设定确保输出风格符合预期
  • 领域适应:不同角色适应不同领域的任务

格式化技巧

1. 结构化输出

使用明确的格式标记,引导模型输出结构化内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
structured_prompt = """
请分析以下文章,并按照以下格式输出:

## 文章摘要
[摘要内容]

## 关键观点
1. [观点 1]
2. [观点 2]
3. [观点 3]

## 情感分析
- 整体情感:[积极/消极/中性]
- 情感强度:[1-10 分]

文章内容:
[文章内容]
"""

2. JSON 格式输出

对于需要程序化处理的情况,要求 JSON 格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
json_prompt = """
请分析以下文本,并以 JSON 格式输出结果:

要求:
- 字段名: title, summary, keywords, sentiment
- sentiment 的值: positive, negative, neutral

文本:[文本内容]

输出格式:
{
"title": "...",
"summary": "...",
"keywords": ["...", "..."],
"sentiment": "..."
}
"""

3. 分步骤输出

对于复杂任务,要求分步骤展示:

1
2
3
4
5
6
7
8
9
10
11
step_by_step_prompt = """
请解决以下问题,分步骤展示:

步骤 1:[第一步]
步骤 2:[第二步]
步骤 3:[第三步]
...
最终答案:[答案]

问题:[问题内容]
"""

4. 使用分隔符

使用清晰的分隔符区分不同部分:

1
2
3
4
5
6
7
8
9
10
11
12
delimiter_prompt = """
=== 任务说明 ===
[任务描述]

=== 输入数据 ===
[数据内容]

=== 输出要求 ===
[格式要求]

=== 开始处理 ===
"""

提示模板设计

提示模板是可复用的提示框架,适用于特定类型的任务。

分类任务模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classification_template = """
你是一位专业的文本分类专家。

任务:将文本分类到以下类别之一:{categories}

分类规则:
{rules}

示例:
{examples}

待分类文本:
{text}

请输出:
类别:[类别名称]
置信度:[0-1 之间的数值]
理由:[简要说明分类理由]
"""

生成任务模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
generation_template = """
你是一位专业的{domain}内容创作者。

任务:{task_description}

要求:
- 长度:{length}字左右
- 风格:{style}
- 目标受众:{audience}

参考信息:
{reference}

请生成内容:
"""

问答任务模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
qa_template = """
基于以下文档回答问题。

文档:
{document}

问题:{question}

要求:
1. 答案必须基于文档内容
2. 如果文档中没有相关信息,请回答"文档中未找到相关信息"
3. 引用文档中的具体内容支持你的答案

答案:
"""

代码生成模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
code_generation_template = """
你是一位经验丰富的{language}程序员。

需求:{requirement}

技术要求:
- 编程语言:{language}
- 代码风格:{style}
- 需要包含:{features}

示例输入/输出:
{examples}

请编写代码:
```{language}
[代码]

代码说明: [简要说明代码逻辑] """

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

### 模板参数化实现

```python
class PromptTemplate:
def __init__(self, template: str):
self.template = template

def format(self, **kwargs) -> str:
"""格式化模板,填充参数"""
return self.template.format(**kwargs)

def format_safe(self, **kwargs) -> str:
"""安全格式化,处理缺失参数"""
try:
return self.template.format(**kwargs)
except KeyError as e:
raise ValueError(f"缺少必需的模板参数: {e}")

# 使用示例
template = PromptTemplate(classification_template)
prompt = template.format(
categories="积极, 消极, 中性",
rules="根据文本的情感倾向进行分类",
examples="示例 1:今天天气真好 → 积极",
text="这部电影真的很棒"
)

Self-Consistency:一致性采样

Self-Consistency 是一种提升 CoT 推理准确性的技术。基本思路:对同一个问题生成多个推理路径,然后选择最一致的答案

Self-Consistency 原理

传统 CoT 只生成一条推理路径, Self-Consistency 生成 条路径,然后通过投票选择最终答案。

算法流程

  1. 使用 CoT 提示生成 个不同的推理路径
  2. 从每条路径中提取答案
  3. 选择出现频率最高的答案(多数投票)
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
39
40
41
42
43
import random
from collections import Counter

def self_consistency_sample(model, prompt, k=5, temperature=0.7):
"""
使用 Self-Consistency 采样多个推理路径

Args:
model: 语言模型
prompt: CoT 提示
k: 采样数量
temperature: 采样温度(较高温度增加多样性)

Returns:
最终答案
"""
answers = []

for _ in range(k):
# 使用较高温度采样,增加多样性
response = model.generate(
prompt,
temperature=temperature,
max_tokens=500
)
answer = extract_answer(response)
answers.append(answer)

# 多数投票
answer_counts = Counter(answers)
final_answer = answer_counts.most_common(1)[0][0]

return final_answer, answer_counts

def extract_answer(response):
"""从响应中提取答案"""
# 简单实现:查找"答案:"后的内容
if "答案:" in response:
return response.split("答案:")[-1].strip()
# 或者查找最后一个数字
import re
numbers = re.findall(r'\d+', response)
return numbers[-1] if numbers else response

Self-Consistency 的数学表达

对于问题 ,生成 条推理路径 ,每条路径对应答案

最终答案通过多数投票选择:

$$

A^{*} = {a} {i=1}^{k} [A_i = a] $$

其中 𝟙 是指示函数。

实现示例

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
39
40
41
42
43
44
45
46
47
48
49
50
51
class SelfConsistency:
def __init__(self, model, k=5, temperature=0.7):
self.model = model
self.k = k
self.temperature = temperature

def solve(self, question, cot_prompt_template):
"""使用 Self-Consistency 解决问题"""
prompt = cot_prompt_template.format(question=question)

answers = []
reasoning_paths = []

for i in range(self.k):
response = self.model.generate(
prompt,
temperature=self.temperature,
max_tokens=500
)

answer = self._extract_answer(response)
answers.append(answer)
reasoning_paths.append(response)

# 统计答案分布
answer_counts = Counter(answers)
final_answer = answer_counts.most_common(1)[0][0]
confidence = answer_counts[final_answer] / self.k

return {
"answer": final_answer,
"confidence": confidence,
"answer_distribution": dict(answer_counts),
"reasoning_paths": reasoning_paths
}

def _extract_answer(self, response):
"""提取答案(需要根据具体任务定制)"""
# 示例:提取最后一个数字
import re
numbers = re.findall(r'\d+', response)
return numbers[-1] if numbers else response.split()[-1]

# 使用示例
sc = SelfConsistency(model, k=5)
result = sc.solve(
"小明有 15 个苹果,给了小红 3 个,又给了小华 5 个,还剩多少个?",
cot_prompt_template
)
print(f"答案:{result['answer']}")
print(f"置信度:{result['confidence']:.2%}")

Self-Consistency 的优势

  1. 提升准确性:通过多数投票减少错误
  2. 鲁棒性:对单次采样错误不敏感
  3. 置信度估计:答案分布提供置信度信息

ReAct:推理与行动的结合

ReAct( Reasoning + Acting)是一种将推理和行动结合的方法,特别适用于需要工具使用的任务。

ReAct 框架

ReAct 的基本思路:模型在推理过程中可以调用外部工具,通过观察工具结果来指导下一步推理

基本循环

  1. 思考( Thought):分析当前情况,决定下一步行动
  2. 行动( Action):调用工具或执行操作
  3. 观察( Observation):获取行动结果
  4. 重复直到得到最终答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
react_prompt = """
可以使用以下工具:
- search(query): 搜索信息
- calculator(expression): 计算数学表达式
- get_weather(city): 获取天气信息

请按照以下格式回答:

思考:[你的思考过程]
行动:[工具名称(参数)]
观察:[工具返回的结果]
...(重复思考-行动-观察循环)
思考:[最终思考]
答案:[最终答案]

问题:{question}
"""

ReAct 实现示例

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
class ReActAgent:
def __init__(self, model, tools):
self.model = model
self.tools = tools # 工具字典

def solve(self, question):
"""使用 ReAct 方法解决问题"""
prompt = self._build_initial_prompt(question)
max_iterations = 10

for i in range(max_iterations):
# 生成思考
response = self.model.generate(prompt, max_tokens=200)

# 解析响应
thought, action = self._parse_response(response)

if action is None:
# 没有行动,可能是最终答案
answer = self._extract_answer(response)
return answer

# 执行行动
observation = self._execute_action(action)

# 更新提示
prompt += f"\n 思考:{thought}\n 行动:{action}\n 观察:{observation}\n"

return "达到最大迭代次数"

def _build_initial_prompt(self, question):
"""构建初始提示"""
tool_descriptions = "\n".join([
f"- {name}: {desc}"
for name, desc in self.tools.items()
])

return f"""
可以使用以下工具:
{tool_descriptions}

请按照以下格式回答:
思考:[你的思考过程]
行动:[工具名称(参数)]
观察:[工具返回的结果]
...(重复思考-行动-观察循环)
思考:[最终思考]
答案:[最终答案]

问题:{question}
"""

def _parse_response(self, response):
"""解析响应,提取思考和行动"""
import re

thought_match = re.search(r'思考:(.*?)(?=行动:|答案:|$)', response, re.DOTALL)
action_match = re.search(r'行动:(\w+)\((.*?)\)', response)

thought = thought_match.group(1).strip() if thought_match else ""
action = None

if action_match:
tool_name = action_match.group(1)
tool_args = action_match.group(2).strip()
action = (tool_name, tool_args)

return thought, action

def _execute_action(self, action):
"""执行行动"""
tool_name, tool_args = action

if tool_name not in self.tools:
return f"错误:工具 {tool_name} 不存在"

tool_func = self.tools[tool_name]
try:
result = tool_func(tool_args)
return str(result)
except Exception as e:
return f"错误:{str(e)}"

def _extract_answer(self, response):
"""提取最终答案"""
import re
answer_match = re.search(r'答案:(.*?)$', response, re.DOTALL)
return answer_match.group(1).strip() if answer_match else response

# 工具定义
def search_tool(query):
"""模拟搜索工具"""
# 实际实现中会调用真实搜索 API
return f"搜索结果:关于'{query}'的信息..."

def calculator_tool(expression):
"""计算器工具"""
try:
result = eval(expression)
return result
except:
return "计算错误"

# 使用示例
tools = {
"search": search_tool,
"calculator": calculator_tool
}

agent = ReActAgent(model, tools)
answer = agent.solve("北京今天的天气如何?如果温度高于 20 度,计算 15 * 3 的结果")

ReAct 的优势

  1. 工具集成:可以调用外部工具扩展能力
  2. 动态适应:根据观察结果调整策略
  3. 可解释性:思考过程清晰可见
  4. 复杂任务:适合需要多步推理和工具使用的任务

构建高效的提示系统

提示系统架构

一个完整的提示系统应该包含以下组件:

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
class PromptSystem:
def __init__(self):
self.templates = {} # 提示模板库
self.examples = {} # 示例库
self.metrics = {} # 评估指标

def register_template(self, name, template):
"""注册提示模板"""
self.templates[name] = template

def build_prompt(self, template_name, **kwargs):
"""构建提示"""
if template_name not in self.templates:
raise ValueError(f"模板 {template_name} 不存在")

template = self.templates[template_name]
return template.format(**kwargs)

def evaluate(self, prompt, test_cases):
"""评估提示效果"""
results = []
for case in test_cases:
full_prompt = prompt + "\n\n" + case['input']
output = self.model.generate(full_prompt)
results.append({
'input': case['input'],
'expected': case['expected'],
'actual': output,
'match': output.strip() == case['expected'].strip()
})

accuracy = sum(r['match'] for r in results) / len(results)
return {
'accuracy': accuracy,
'results': results
}

提示优化策略

1. A/B 测试

对比不同提示版本的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def ab_test_prompts(prompt_a, prompt_b, test_cases, model):
"""A/B 测试两个提示"""
results_a = evaluate_prompt(prompt_a, test_cases, model)
results_b = evaluate_prompt(prompt_b, test_cases, model)

return {
'prompt_a': {
'accuracy': results_a['accuracy'],
'avg_length': np.mean([len(r['actual']) for r in results_a['results']])
},
'prompt_b': {
'accuracy': results_b['accuracy'],
'avg_length': np.mean([len(r['actual']) for r in results_b['results']])
}
}

2. 迭代优化

基于反馈不断改进提示:

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
def iterative_optimization(initial_prompt, test_cases, model, max_iterations=5):
"""迭代优化提示"""
current_prompt = initial_prompt
best_accuracy = 0
best_prompt = initial_prompt

for iteration in range(max_iterations):
# 评估当前提示
results = evaluate_prompt(current_prompt, test_cases, model)
accuracy = results['accuracy']

if accuracy > best_accuracy:
best_accuracy = accuracy
best_prompt = current_prompt

# 分析错误案例
errors = [r for r in results['results'] if not r['match']]

if not errors:
break

# 基于错误改进提示(简化示例)
current_prompt = refine_prompt(current_prompt, errors)

return best_prompt, best_accuracy

3. 提示组合

组合多个提示技术:

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
def build_advanced_prompt(question, examples, use_cot=True, use_role=True):
"""构建高级提示,组合多种技术"""
prompt_parts = []

# 角色设定
if use_role:
prompt_parts.append("你是一位专业的问题解决专家。")

# 任务描述
prompt_parts.append("请解决以下问题:")

# 少样本示例
if examples:
prompt_parts.append("示例:")
for ex in examples:
prompt_parts.append(f"问题:{ex['question']}")
if use_cot:
prompt_parts.append(f"推理:{ex['reasoning']}")
prompt_parts.append(f"答案:{ex['answer']}")

# CoT 要求
if use_cot:
prompt_parts.append("\n 请展示你的推理过程,然后给出答案。")

# 当前问题
prompt_parts.append(f"\n 问题:{question}")

return "\n".join(prompt_parts)

实战案例

案例 1:情感分析系统

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class SentimentAnalyzer:
def __init__(self, model):
self.model = model
self.prompt_template = """
你是一位专业的情感分析专家。

任务:分析文本的情感倾向

分类标准:
- 积极:表达正面情感、满意、赞扬等
- 消极:表达负面情感、不满、批评等
- 中性:无明显情感倾向

示例:
文本 1:这部电影真的很棒,演员表演出色,剧情紧凑。
情感:积极
理由:使用了"很棒"、"出色"等正面词汇

文本 2:产品质量太差了,完全不值这个价格。
情感:消极
理由:使用了"太差"、"不值"等负面词汇

文本 3:明天会下雨。
情感:中性
理由:只是陈述事实,无情感色彩

请分析以下文本:
文本:{text}

输出格式:
情感:[积极/消极/中性]
置信度:[0-1 之间的数值]
理由:[简要说明]
"""

def analyze(self, text):
"""分析文本情感"""
prompt = self.prompt_template.format(text=text)
response = self.model.generate(prompt)
return self._parse_response(response)

def _parse_response(self, response):
"""解析响应"""
import re

sentiment_match = re.search(r'情感:(\w+)', response)
confidence_match = re.search(r'置信度:([\d.]+)', response)
reason_match = re.search(r'理由:(.*?)(?=\n|$)', response, re.DOTALL)

return {
'sentiment': sentiment_match.group(1) if sentiment_match else None,
'confidence': float(confidence_match.group(1)) if confidence_match else None,
'reason': reason_match.group(1).strip() if reason_match else None
}

案例 2:代码生成助手

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
class CodeGenerator:
def __init__(self, model):
self.model = model
self.prompt_template = """
你是一位经验丰富的 Python 程序员,擅长编写清晰、高效、可维护的代码。

任务:根据需求生成 Python 代码

要求:
1. 代码必须可以直接运行
2. 包含必要的注释
3. 遵循 PEP 8 代码规范
4. 处理边界情况

示例:
需求:实现一个函数,计算列表中所有偶数的和
代码:
```python
def sum_even_numbers(numbers):
\"\"\"
计算列表中所有偶数的和

Args:
numbers: 数字列表

Returns:
偶数的和
\"\"\"
return sum(num for num in numbers if num % 2 == 0)

请为以下需求生成代码: 需求:{requirement}

代码: """

def generate(self, requirement):
    """生成代码"""
    prompt = self.prompt_template.format(requirement=requirement)
    response = self.model.generate(prompt)
    return self._extract_code(response)

def _extract_code(self, response):
    """提取代码块"""
    import re
    code_match = re.search(r'```python\n(.*?)```', response, re.DOTALL)
    if code_match:
        return code_match.group(1).strip()
    return response
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

### 案例 3:智能问答系统

```python
class QASystem:
def __init__(self, model):
self.model = model
self.knowledge_base = {} # 知识库

def add_knowledge(self, doc_id, content):
"""添加知识"""
self.knowledge_base[doc_id] = content

def answer(self, question, doc_ids=None):
"""回答问题"""
if doc_ids is None:
doc_ids = list(self.knowledge_base.keys())

# 检索相关文档
relevant_docs = self._retrieve_docs(question, doc_ids)

# 构建提示
prompt = self._build_qa_prompt(question, relevant_docs)

# 生成答案
response = self.model.generate(prompt)
return self._extract_answer(response)

def _retrieve_docs(self, question, doc_ids, top_k=3):
"""检索相关文档(简化实现)"""
# 实际实现中可以使用向量检索
return [self.knowledge_base[did] for did in doc_ids[:top_k]]

def _build_qa_prompt(self, question, docs):
"""构建 QA 提示"""
doc_text = "\n\n".join([
f"文档{i+1}:{doc}"
for i, doc in enumerate(docs)
])

return f"""
基于以下文档回答问题。

文档:
{doc_text}

问题:{question}

要求:
1. 答案必须基于文档内容
2. 如果文档中没有相关信息,请回答"文档中未找到相关信息"
3. 引用文档中的具体内容支持你的答案
4. 如果文档间有冲突,请说明

答案:
"""

def _extract_answer(self, response):
"""提取答案"""
if "答案:" in response:
return response.split("答案:")[-1].strip()
return response.strip()

❓ Q&A: 提示工程常见问题

Q1: 提示越长越好吗?

不一定。提示应该包含完成任务所需的所有信息,但过长可能: - 增加计算成本 - 分散模型注意力 - 超出上下文窗口限制

最佳实践是:先写简洁版本,如果效果不佳再逐步添加细节

Q2: 少样本提示需要多少个示例?

通常 2-5 个示例效果较好。太少可能无法学习模式,太多可能: - 浪费 token - 增加混淆 - 降低效率

建议:从 2-3 个示例开始,根据效果调整

Q3: CoT 对所有任务都有效吗?

不是。 CoT 主要适用于: - 需要多步推理的任务(数学问题、逻辑推理) - 复杂决策任务

对于简单分类、直接问答等任务, CoT 可能反而增加噪声。

Q4: 如何选择合适的温度参数?

  • 低温度( 0.1-0.3):确定性输出,适合需要准确性的任务
  • 中等温度( 0.5-0.7):平衡创造性和准确性
  • 高温度( 0.8-1.0):创造性输出,适合生成任务

对于 Self-Consistency,通常使用较高温度( 0.7-0.9)增加多样性。

Q5: 提示工程可以替代微调吗?

在某些场景下可以,但各有优势:

  • 提示工程:快速、灵活、无需训练数据
  • 微调:更专业、更稳定、适合特定领域

最佳实践:先用提示工程快速验证,需要更高性能时再考虑微调

Q6: 如何处理模型的幻觉( Hallucination)问题?

  • 要求模型引用来源
  • 使用少样本示例展示期望行为
  • 要求模型标注不确定的部分
  • 结合外部知识库验证

Q7: 提示中的示例顺序重要吗?

是的。模型可能对: - 第一个示例给予更多权重 - 最近的示例记忆更深

建议:将最典型、最清晰的示例放在前面

Q8: 如何评估提示效果?

  • 准确性:在测试集上评估正确率
  • 一致性:多次运行结果的一致性
  • 相关性:输出与任务的匹配度
  • 效率: token 使用量和响应时间

Q9: 可以组合多种提示技术吗?

可以。常见组合: - 角色设定 + 少样本 + CoT - Few-shot + Self-Consistency - ReAct + 工具调用

注意:组合可能增加复杂度,需要权衡效果和成本

Q10: 提示工程有哪些局限性?

  • 依赖模型能力:基础模型能力有限
  • 上下文窗口限制:无法处理过长输入
  • 不稳定:相同提示可能产生不同结果
  • 需要人工调试:优化过程耗时

未来方向:自动化提示优化、更好的评估指标、与微调结合

  • 本文标题:自然语言处理(七)—— 提示工程与 In-Context Learning
  • 本文作者:Chen Kai
  • 创建时间:2024-03-09 10:45:00
  • 本文链接:https://www.chenk.top/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86%EF%BC%88%E4%B8%83%EF%BC%89%E2%80%94%E2%80%94-%E6%8F%90%E7%A4%BA%E5%B7%A5%E7%A8%8B%E4%B8%8EIn-Context-Learning/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论