Prompt Engineering

1. Prompt Engineering 的意义

在 LLM(大语言模型)时代,Prompt Engineering(提示工程)已经成为开发者与用户的重要技能和概念。随着大模型(如 GPT、GLM、BERT 等)的快速发展,prompt 成为驱动这些模型生成结果的核心因素。

Prompt Engineering 的重要性在于,它可以通过精心设计的提示词,引导大模型生成更加精准、相关和有效的内容。随着 LLM 在各个领域的广泛应用,Prompt Engineering 不仅提升了模型的性能,还为普通用户打开了使用 AI 工具的大门。

在未来,Prompt Engineering 将继续成为 AI 应用开发中的关键技能。Prompt,不仅仅是简单的输入,它是用户与大模型交互的桥梁。通过有效的 Prompt Engineering,我们可以最大化地利用 AI 的潜力,实现多样化的任务和应用。

那么,Prompt Engineering 究竟有什么意义呢?

大模型入门到精通——Prompt Engineering工程-LMLPHP

1.1 什么是 Prompt?

简单来说,Prompt 就是用户与大语言模型交互时提供的输入。换句话说,prompt 是你希望大模型处理和生成回应的提示词指令。在与大模型的对话中,prompt 是一个输入,模型根据它来理解用户的需求,生成相应的输出(通常被称为 Completion,即完成的文本)。

1.1.1 Prompt Engineering 的定义

Prompt Engineering 是设计和优化 prompt 的过程,目的是通过精心构建的输入来引导模型生成理想的输出。这涉及到如何合理地提出问题、如何在 prompt 中提供背景信息、如何精确表达需求,甚至使用特定的格式、约束条件或多轮对话来影响生成的结果。

1.1.2 Prompt Engineering意义
  1. 最大化模型性能
    大模型本质上是基于统计和概率预测的,它们依赖于 prompt 提供的信息来生成内容。精心设计的 prompt 可以最大程度地发挥模型的潜力,生成更符合预期的响应。而不合适或模糊的 prompt 可能会导致模型产生误解或输出不理想的内容。

  2. 提升结果的相关性和准确性
    通过提供更具体的上下文、约束条件和目标指示,Prompt Engineering 可以引导模型生成更相关和准确的内容。例如,明确要求模型输出步骤化指南或对特定概念的详细解释,有助于模型生成精准的回答。

  3. 节省计算资源
    一个精心设计的 prompt 可以减少无用的生成内容,避免长时间计算或不必要的多轮对话。因此,Prompt Engineering 不仅提高了模型的输出质量,还优化了计算效率。

  4. 使复杂任务变得简单
    Prompt Engineering 不仅可以用于简单的问答,还可以用于解决复杂的任务,如代码生成、文本摘要、数据分析、翻译等。通过适当设计的 prompt,模型可以在复杂任务中表现得像人类专家一样高效。

  5. 降低用户门槛
    Prompt Engineering 使得非技术用户也能轻松使用大模型。通过简单的自然语言提示,用户不需要深入了解机器学习和自然语言处理的细节即可获取所需的结果。这大大降低了与 AI 交互的门槛。

  6. 应用场景的多样性
    大模型的强大之处在于其多用途性,可以广泛应用于各种领域,如教育、金融、医学、法律等。Prompt Engineering 通过优化输入,能在不同领域和场景中最大化模型的表现,使得 AI 在各个行业中具有实际应用价值。

1.1.3 Prompt Engineering实践

为了充分利用 Prompt Engineering,以下是一些常见的技巧和方法:

  1. 明确指令:尽可能明确地告诉模型你需要的是什么。如果是生成特定格式的内容或要点,应该在 prompt 中清楚地表达。

    示例:

    • 不明确的 prompt:写一篇关于气候变化的文章。
    • 明确的 prompt:写一篇 300 字的文章,讨论气候变化对北极熊栖息地的影响。
      大模型入门到精通——Prompt Engineering工程-LMLPHP
  2. 提供上下文:为模型提供足够的背景信息,以帮助它更好地理解问题。

    示例:

    • 简单 prompt:解释量子力学。
    • 上下文丰富的 prompt:为一名高中生用简单的语言解释量子力学的基本原理。
  3. 控制输出长度和风格:通过提示词中指定内容的长度、形式、风格等条件,可以控制模型的输出。

    示例:

    • 用专业且简洁的语言总结以下段落。
    • 写一个具有幽默感的故事,包含两只猫和一只狗的冒险。
      大模型入门到精通——Prompt Engineering工程-LMLPHP
  4. 迭代和实验:设计 prompt 是一个实验性的过程。通过迭代地调整和测试 prompt,可以不断改进和优化生成结果。

2. 设计高效 Prompt 的关键原则

对于具有强大自然语言理解和生成能力的大语言模型(LLM)来说,一个好的 Prompt 设计极大地决定了模型的能力上限与下限。如何设计有效的 Prompt,以充分发挥 LLM 的性能?首先,我们需要了解设计 Prompt 的原则,这些原则是每一个开发者必须掌握的基础概念。本节讨论了设计高效 Prompt 的两个关键原则:编写清晰、具体的指令给予模型充足的思考时间。掌握这两点,对于创建可靠的语言模型交互尤为重要。

2.1 原则一:编写清晰、具体的指令

在与大语言模型交互时,提供清晰且具体的指令是确保模型生成高质量响应的关键。清晰的指令可以减少模型对用户意图的误解,提高输出的准确性和相关性。

  • 避免模糊不清的表达:模糊的提示会让模型难以确定用户的真正需求,导致生成的内容不符合预期。例如,输入“写一篇关于技术发展的文章”可能会得到非常宽泛的结果,而“写一篇 500 字的文章,讨论过去十年人工智能的发展及其对金融行业的影响”则会产生更符合预期的结果。

  • 具体化需求:明确指出需要生成的内容的结构、长度、风格或特定的关注点。例如,如果你希望模型写一个故事,可以指明故事的情节、角色类型、背景等细节。

    示例:

    • 模糊的 prompt:描述一下公司的文化。
    • 清晰、具体的 prompt:用三句话描述一家初创科技公司注重创新、协作和员工福利的文化。

通过编写清晰和具体的指令,你可以有效地引导模型朝着期望的方向生成内容,避免无关或不符合预期的输出

2.1.1 使用分隔符清晰地表示输入的不同部分

在编写 Prompt 时,使用分隔符可以帮助清晰地区分输入中的不同部分,避免模型在处理时混淆上下文、指令或不同的输入内容。分隔符就像是提示中的“墙”,有效地将不同的部分隔开,从而确保模型理解各部分的独立性。

1. 使用 ``` 作为分隔符
请按照以下要求生成代码:
def fibonacci(n):
	if n <= 0:
		return 0
	elif n == 1:
		return 1
	else:	
return fibonacci(n-1) + fibonacci(n-2)

```
说明:
- 语言:Python
- 功能:计算斐波那契数列的第10项
```

在这个例子中,使用 ``` 分隔符将生成的代码与说明部分区分开。这样可以确保模型能够理解哪些内容是代码,哪些是说明,避免混淆。

2. 使用 “”" 作为分隔符
请生成一封客户通知邮件,内容如下:

"""
尊敬的客户,

感谢您选择我们的服务。我们想通知您,您的订单已成功处理,并将在3个工作日内发货。

如有任何问题,请随时联系我们的客户服务团队。

此致,
公司团队
"""

请为这封邮件添加一个合适的标题。

这里使用 “”" 分隔符将邮件正文与其他指令部分区分开。这样可以让模型明确识别出邮件内容部分,从而进行准确的处理。

3. 使用 <> 作为分隔符
你是一名客服代表。请根据以下客户反馈生成一段回复。

<客户反馈>
产品包装损坏,我对此非常不满意。请告知如何退货。
</客户反馈>

<回复>
尊敬的客户,
我们非常抱歉听到您的包装损坏。您可以通过以下方式退货...
</回复>

在这里,使用 < > 分隔符将客户的反馈和客服回复部分明确分开。这使得模型能够区分客户的输入和需要生成的回复内容。

4. 使用 : 作为分隔符
请将以下词汇翻译成法语:

猫: 
狗: 
房子: 

使用冒号 : 作为分隔符,将需要翻译的每个单词与其对应的法语翻译区分开。这个格式非常简洁,适用于需要逐项处理的场景。

5. 使用 ------ 作为分隔符
请回答以下两个问题:

------
问题一:你如何看待人工智能的发展?
------
问题二:你认为未来十年哪些职业会受到 AI 的影响?

在这个例子中,使用 ------ 作为分隔符,将两个不同的问题分隔开来,确保模型能够独立处理每个问题。

2.1.2 寻求结构化的输出

有时候我们需要语言模型给出一些结构化的输出,而不仅仅是连续的文本。结构化输出 是指按照某种格式组织的内容,例如 JSON、HTML 等格式。这种输出特别适合在代码中进一步解析和处理,例如在 Python 中将其读入字典或列表中,便于后续的编程操作。

示例 1: 生成 JSON 格式的输出
请生成一个包含以下信息的 JSON 对象:
- 姓名: 张三
- 年龄: 28
- 职业: 软件工程师
- 技能: Python, Java, C++

输出格式:
{
  "姓名": "张三",
  "年龄": 28,
  "职业": "软件工程师",
  "技能": ["Python", "Java", "C++"]
}

这个示例中,提示模型输出一个结构化的 JSON 对象,便于在程序中直接解析使用。

示例 2: 生成 HTML 格式的输出
请生成一个简单的 HTML 页面,包含以下内容:
- 标题: 我的博客
- 一个一级标题,内容为: 欢迎来到我的博客
- 一段文本,内容为: 这是我的第一篇博客文章。

输出格式:
<!DOCTYPE html>
<html>
<head>
  <title>我的博客</title>
</head>
<body>
  <h1>欢迎来到我的博客</h1>
  <p>这是我的第一篇博客文章。</p>
</body>
</html>

在这个示例中,模型被要求生成 HTML 格式的结构化输出,可以直接在网页中使用。

示例 3: 生成表格格式的输出
请生成一个 Markdown 表格,内容如下:
- 表头:产品名称、价格、库存
- 产品1:笔记本电脑、5000元、10台
- 产品2:智能手机、3000元、20台

输出格式:
| 产品名称   | 价格  | 库存  |
| ---------- | ----- | ----- |
| 笔记本电脑 | 5000元 | 10台  |
| 智能手机   | 3000元 | 20台  |

该示例中,模型生成了一个 Markdown 表格,这种结构化的格式在文档生成和显示时非常实用。

2.1.3 要求模型检查是否满足条件

在某些情况下,任务的前提条件可能不总是满足。为了确保模型能够正确执行任务,我们可以要求模型首先检查这些条件是否满足。如果条件不满足,则模型应当指出问题并停止执行后续的完整流程。这种方法有助于避免错误或意外的结果,尤其是在处理复杂或高度依赖上下文的任务时。

示例:检查是否包含指令

我们给模型两段不同的文本,一段包含制作茶的步骤,另一段则不包含明确的步骤。我们要求模型判断每段文本是否包含一系列指令,如果包含,则按照给定格式重新编写指令;如果不包含,则回答“未提供步骤”。

示例 1: 包含明确步骤的文本

输入:

请根据以下文本判断是否包含制作茶的步骤:

文本:
1. 烧开水。
2. 把茶叶放入茶壶中。
3. 倒入热水,等待3分钟。
4. 倒出茶水,享用。

如果文本包含明确的步骤,请将其按照以下格式重新编写:
- 第一步:
- 第二步:
- 第三步:
- 第四步:

如果文本不包含明确的步骤,则回答“未提供步骤”。

输出:

- 第一步:烧开水。
- 第二步:把茶叶放入茶壶中。
- 第三步:倒入热水,等待3分钟。
- 第四步:倒出茶水,享用。

在这个示例中,模型识别出文本包含明确的步骤,因此按照要求重新编写了步骤。

示例 2: 不包含明确步骤的文本

输入:

请根据以下文本判断是否包含制作茶的步骤:

文本:
茶是一种非常受欢迎的饮品,有许多种类和冲泡方式。不同的茶叶需要不同的温度和时间来释放最佳风味。

如果文本包含明确的步骤,请将其按照以下格式重新编写:
- 第一步:
- 第二步:
- 第三步:
- 第四步:

如果文本不包含明确的步骤,则回答“未提供步骤”。

输出:

未提供步骤

在这个示例中,模型识别出文本并不包含明确的步骤,因此正确地返回了“未提供步骤”。


2.1.4 提供少量示例

“Few-shot” 提示法(少样本提示)是一种有效的方式,在要求模型执行实际任务之前,通过提供一两个参考样例,让模型了解我们的要求和期望的输出样式。这种方法能帮助模型迅速理解任务要求,并生成符合预期的答案。Few-shot 提示法通过提供一两个参考样例,能够帮助模型迅速学习我们想要的语气、风格或结构,确保生成的内容与期望一致。这种方法特别适用于需要特定风格或格式的任务,可以显著提高模型输出的准确性和一致性。

示例 1: 学术与圣贤的对话

我们先给模型一个 {<学术>:<圣贤>} 对话样例,然后要求模型用同样的风格回答关于“孝顺”的问题。

输入:

示例:
{<学术>:<圣贤>,何谓德行?}
{<圣贤>:<学术>,德行者,内修心志,外彰礼义;为人之本,亦为世之重也。}

请用同样的隐喻风格回答以下问题:
{<学术>:<圣贤>,何谓孝顺?}

输出:

{<圣贤>:<学术>,孝顺者,心怀父母之恩,践行尽孝之道;为人子者,慎独修德,待亲如己,亲恩则厚,孝行则广也。}

在这个示例中,通过提供学术与圣贤对话的样例,模型理解了文言文的风格和隐喻表达方式,并在回答关于“孝顺”的问题时应用了相同的风格。

示例 2: 产品推荐

我们希望模型根据给定的用户需求推荐产品,可以通过提供示例来指导模型。

输入:

示例:
用户需求:我想买一台可以处理高端游戏的笔记本电脑。
推荐产品:我们推荐Alienware m15 R3,这款笔记本电脑配备了最新的Intel i9处理器和NVIDIA RTX 2080显卡,能够轻松处理各种高端游戏。

用户需求:我需要一款适合家庭使用的多功能打印机。

输出:

推荐产品:我们推荐HP OfficeJet Pro 9015,这款打印机具备打印、扫描、复印和传真功能,非常适合家庭使用。此外,它还支持无线连接,方便操作。

通过给出一个产品推荐的示例,模型能够理解推荐的格式和内容,并按照预期的风格生成了对第二个需求的回答。

2.2 原则二:给模型时间去思考

在设计 Prompt 时,给予语言模型充足的推理时间非常重要。语言模型与人类一样时间来思考并解决复杂问题。如果让语言模型匆忙给出结论,其结果很可能不准确。例如,若要语言模型推断一本书的主题,仅提供简单的书名和一句简介是不足够的。这就像让一个人在极短时间内解决困难的数学题,错误在所难免。

相反,我们应通过 Prompt 引导语言模型进行深入思考。可以要求其先列出对问题的各种看法,说明推理依据,然后再得出最终结论。在 Prompt 中添加逐步推理的要求,能让语言模型投入更多时间逻辑思维,输出结果也将更可靠准确。

综上所述,给予语言模型充足的推理时间,是 Prompt Engineering 中一个非常重要的设计原则。这将大大提高语言模型处理复杂问题的效果,也是构建高质量 Prompt 的关键之处。开发者应注意给模型留出思考空间,以发挥语言模型的最大潜力。

从该原则出发,我们也提供几个设计 Prompt 的技巧:


1. 逐步推理的提示

在复杂问题中,引导模型逐步推理可以避免直接给出错误的结论。通过要求模型列出推理的各个步骤,并逐步得出结论,可以让结果更准确。

示例:

请分析以下数学问题,并逐步列出你的推理过程,最后得出结论。

问题:如果一个水池中有5000升水,每小时蒸发200升,假设没有其他的进水或出水,多少小时后水池中的水将蒸发至一半?

请按以下步骤回答:
1. 列出已知条件。
2. 计算每小时的水量变化。
3. 计算水量减少至一半所需的时间。
4. 得出最终结论。

2. 提供充分的上下文信息

为了帮助模型更好地推理和理解问题,可以提供更多的上下文信息。这样可以确保模型在做出结论前有足够的背景知识支持。

示例:

请根据以下背景信息推断书的主题,并解释你的推理过程。

背景信息:这本书讲述了一位年轻人在科技公司工作的经历,探索了技术对社会的影响以及人类如何适应迅速变化的世界。

步骤:
1. 识别书中的主要主题。
2. 说明该主题与背景信息中的哪些内容相关。
3. 总结你的推理过程并得出结论。

3. 分阶段问题分解

对于复杂的任务,可以将其分解为多个阶段,并要求模型逐步完成每个阶段的任务。这种方式不仅能确保任务的准确性,还能让模型在每个步骤中都进行更深入的思考。

示例:

请根据以下描述写一篇关于环境保护的文章。为了确保文章结构清晰,请按照以下步骤进行:

步骤1:首先列出文章的主要论点。
步骤2:针对每个论点列出支持的证据或案例。
步骤3:为每个论点写一段解释性的文字。
步骤4:最后总结全文并得出结论。

4. 指导模型在下结论之前找出一个自己的解法

在设计 Prompt 时,我们还可以通过明确指导语言模型进行自主思考,来获得更好的效果。例如,假设我们要求语言模型判断一个数学问题的解答是否正确。仅仅提供问题和解答是不够的,语言模型可能会匆忙做出错误判断。

相反,我们可以在 Prompt 中先要求语言模型自己尝试解决这个问题,思考出自己的解法,然后再与提供的解答进行对比,判断其正确性。这种先让语言模型自主思考的方式,能帮助它更深入理解问题,从而做出更准确的判断。

示例:指导模型自主解题

输入:

请判断以下解答是否正确。

问题:某商品的原价是100元,现打8折出售,最终售价是多少?

解答:原价100元,打8折,最终售价是100元 * 0.8 = 80元。

请按照以下步骤回答:
1. 自行计算出商品的最终售价。
2. 与提供的解答进行对比。
3. 判断解答是否正确,并说明理由。

输出:

1. 自行计算:原价100元,打8折,计算公式为100元 * 0.8 = 80元。
2. 对比:模型的计算结果与提供的解答一致,均为80元。
3. 结论:解答正确,因为计算步骤和结果都与模型的解法一致。

在这个示例中,模型被引导先自主解决问题,然后再对比给定解答,从而更准确地判断其正确性。这种方法避免了模型匆忙下结论,提高了判断的准确性。

参考

https://datawhalechina.github.io/llm-universe/#/C2/3. Prompt Engineering

08-26 06:06