前言
提示工程 (Prompt Engineering) 是一门较新的学科,关注提示词开发和优化,帮助用户将大语言模型 (Large Language Model, LLM) 用于各场景和研究领域。掌握了提示工程相关技能将有助于用户更好地了解大型语言模型的能力和局限性。
研究人员可利用提示工程来提升大语言模型处理复杂任务场景的能力,如问答和算术推理能力。开发人员可通过提示工程设计、研发强大的工程技术,实现和大语言模型或其他生态工具的高效接轨。
提示工程不仅仅是关于设计和研发提示词。它包含了与大语言模型交互和研发的各种技能和技术。提示工程在实现和大语言模型交互、对接,以及理解大语言模型能力方面都起着重要作用。用户可以通过提示工程来提高大语言模型的安全性,也可以赋能大语言模型,比如借助专业领域知识和外部工具来增强大语言模型能力。
提示工程简介
本部分介绍了提示词相关的基础知识,帮助了解如何通过提示词和 LLM 进行交互并提供指导建议。
模型设置
使用提示词时,我们通常会使用 API 或直接与 LLM 进行交互。我们可以通过配置一些参数以获得不同的提示结果。调整这些设置对于提高响应的可靠性非常重要,需要进行一些实验才能找出适合个人用例的正确设置。以下是使用不同 LLM 提供程序时会遇到的常见设置。
Temperature
用于控制模型返回结果的确定性。temperature
的参数值越小,模型就会返回越确定的一个结果。如果调高该参数值,模型就会返回越确定的一个结果。如果调高该参数值,LLM 会返回更随机的结果。调小temperature
实际上是在增加其他可能的 token 的权重。
实际应用:
- 质量保障 (QA):设置更低的
temperature
,促使模型基于事实返回更真实和简洁的结果 - 诗歌生成:适度地调高
temperature
参数值可能会更好
Top_p
用于控制模型返回结果的确定性。与temperature
类似,如果需要准确和事实的答案,就把参数值调低;如果需要更多样化的响应,就把参数值调高。
一般建议是改变temperature
和top_p
中的一个参数即可,不需要两个都调整。
Max Length
用于控制大模型生成的 token 数。指定Max Length
有助于防止大模型生成冗长或不相关的响应,同时控制成本。
Stop Sequences
stop sequence
是一个字符串,可以阻止模型生成 token,指定stop sequence
是控制 LLM 响应长度和结构的另一种方法。eg: 通过添加“11”作为stop sequence
来告诉模型生成不超过 10 个项的列表。
Frequency Penalty
frequency penalty
是对下一个生成的 token 进行惩罚,这个惩罚和 token 在响应和提示中已出现的次数成比例,frequency penalty
越高,某个词再次出现的可能性就越小,通过设置frequency penalty
可以给重复数量多的 token 设置更高的惩罚以减少响应中单词的重复。
Presence Penalty
presence penalty
也是对重复的 token 施加惩罚,但与frequency penalty
不同,presence penalty
对于所有重复的 token 都是相同的(出现 2 次的 token 和出现 10 次的 token 会受到相同的惩罚)。此设置可以防止模型在响应中过于频繁地生成重复的词。
与temperature
和top_p
一样,一般建议是改变frequency penalty
和presence penalty
其中一个参数就行,无须同时调整两个。
基本概念
设计有效的提示词以指导模型执行期望任务的方法被称为提示工程。
提示词格式
标准提示词应遵循以下格式。
<问题>?
或
<指令>?
提示词要素
提示词可包含以下任意要素。
- 指令:想要模型执行的特定任务或指令;
- 上下文:包含外部信息或额外的上下文信息,引导语言模型更好地响应;
- 输入数据:用户输入的内容或问题;
- 输出指示:指定输出的类型或格式。
示例如下:
请将文本分为肯定、否定或中性。 # 指令
文本:我觉得食物还可以。 # 输入数据
情绪: # 输出指示
补充说明,提示词所需的格式取决于用户想要语言模型完成的任务类型,并非所有以上要素都是必须的。
设计提示的通用技巧
- 指令:使用命令指示模型执行各种简单任务,例如“写入”、“分类”、“总结”等,从而为各种简单任务设计有效的提示;需要以不同的关键词、上下文和数据对不同的指令进行大量实验,寻找最适合特定用例和任务的指令
- 具体性:具有良好格式和描述性的提示词,同时注意提示的长度,不要包含太多不必要的细节
- 避免不准确:具体、简洁并切中要点,例如:“使用 2-3 句话向高中学生解释提示工程的概念”
- 做什么还是不做什么:避免说不要做什么,而应该说要做什么
更多的参考案例详见 Best practices for prompt engineering with the OpenAI API
提示技术
零样本提示
直接提示模型给出一个回答,而没有提供任何关于你希望它完成的任务的示例。案例如下所示。
提示:
将文本分类为中性、负面或正面。
文本:我认为这次假期还可以。
情感:
输出:
中性
指令调整已被证明可以改善零样本学习 Wei et al (2022) 。指令调整本质上是在通过指令描述的数据集上微调模型的概念。此外,RLHF 已被采用以扩展指令调整,其中模型被调整以更好地适应人类偏好。
少样本提示
虽然 LLM 展示了惊人的零样本能力,但在使用零样本设置时,它们在更复杂的任务上仍表现不佳。少样本提示可以作为一种技术,以启用上下文学习。少样本提示的格式示例如下。
<问题>?
<答案>
<问题>?
<答案>
<问题>?
<答案>
<问题>?
根据 Min et al (2022) 的研究结果,以下是在进行少样本学习时关于示例的一些额外提示。
- 标签空间和示例指定的输入文本的分布都很重要(无论标签对单个输入是否正确)
- 使用的格式也对性能起着关键作用,即使只是使用随机标签,这也比没有标签好得多
- 其他结果表明,从真实标签分布(而不是均匀分布)中选择随机标签也有帮助
首先尝试一个随机标签的例子(意味着将标签 Negative 和 Positive 随机分配给输入。
提示:
这太棒了!// Negative
这太糟糕了!// Positive
哇,那部电影太棒了!// Positive
多么可怕的节目!//
输出:
Negative
即使标签已经随机化,仍然得到了正确的答案,除此之外,案例还保留了格式,这也有助于生成正确的答案。实际上,通过进一步的实验,新的 GPT 模型对随机格式也变得更加稳健,例如:
提示:
Positive This is awesome!
This is bad! Negative
Wow that movie was rad!
Positive
What a horrible show! --
输出:
Negative
少样本提示的限制
标准的少样本提示对许多任务都有效,但仍然不是一种完美的技术,特别是在处理更复杂的推理任务时。总的来说,提供示例对解决某些任务很有用。当零样本提示和少样本提示不足时,这可能意味着模型学到的东西不足以在任务上表现良好。此时建议考虑微调模型或尝试更高级的提示技术。
链式思考(Chain of Thought, CoT)提示
在 Wei et al, 2022 中引入的链式思考(CoT)提示通过中间推理步骤实现了复杂的推理能力。可以将其与少样本提示相结合,获得更好的结果,从而能够解决需要进行推理的更复杂的任务。
提示:
这组数中的奇数加起来是偶数:4、8、9、15、12、2、1。
A:将所有奇数相加(9、15、1)得到25。答案为False。
这组数中的奇数加起来是偶数:15、32、5、13、82、7、1。
A:
输出:
将所有奇数相加(15、5、13、7、1)得到41。答案为False。
补充说明,作者生成这是足够大的语言模型才会出现的能力。
零样本 CoT 提示
最近提出的一个新想法是零样本 CoT Kojima et al, 2022,它基本涉及将“让我们逐步思考”添加到原始提示中。
自动思维链(Auto-CoT)
当使用思维链提示时,这个过程需要手工制作有效且多样化的例子,这种手动工作可能会导致次优解决方案。Zhang et al, 2022 提出了一种消除人工的方法,即利用 LLMs“让我们一步一步地思考”提示来生成一个接一个的推理链。这种自动过程仍然可能在生成的链中出现错误。为了减轻错误的影响,示例的多样性很重要。这项工作提出了 Auto-CoT,它对具有多样性的问题进行采样,并生成推理链来构建演示。
Auto-CoT 主要由两个阶段组成。
- Period 1. 问题聚类,将给定问题划分为几个聚类
- Period 2. 示例抽样,从每个数组中选择一个具有代表性的问题,并使用带有简单启发式的零样本 CoT 生成其推理链
简单的启发式方法可以是问题的长度(例如,60 个 tokens)和理由的步骤数(例如,5 个推理步骤)。这鼓励模型使用简单而准确的示例。
该过程如下图所示,代码见 Auto-CoT
自我一致性
通过少样本 CoT 采样多个不同的推理路径,并使用生成结果选择最一致的答案,这有助于提高 CoT 提示在涉及计算和常识推理的任务中的性能。
例如以下计算推理示例。
提示:
当我6岁时,我的妹妹是我的一半年龄。现在我70岁了,我的妹妹多大?
输出:
35
输出是错误的,可通过自我一致性来改进这个问题,将使用 Wang et al, 2022 的少样本示例,如下图所示。
输出:
当我6岁时,我的妹妹是我的一半年龄,也就是3岁。现在我70岁了,所以她是70-3 = 67岁。答案是67。 # Output 1
当叙述者6岁时,他的妹妹是他年龄的一半,也就是3岁。现在叙述者70岁了,他的妹妹应该是70-3 = 67岁。答案是67。 # Output 2
当我6岁时,我的妹妹是我的一半年龄,也就是3岁。现在我70岁了,所以她是70/2 = 35岁。答案是35。 # Output 3
计算最终答案涉及几个步骤(详见论文),但为了简单起见,可以看到已经出现了大多数答案,因此这基本上将成为最终答案。