Prompt 详解
随着大模型在2023年横空出世,“Prompt 工程” 应运而生,作为用好大模型最重要的武器,Prompt 的好坏对模型效果有着决定性的影响。
本文希望结合我们在 “Prompt 工程” 中的实践经验,更加体系化地对 “Prompt 工程” 进行梳理,希望可以一步步地帮助大家用好大模型,人人都是 Prompt 高手。
前言
Prompt 与 GPT 的前世今生
如今我们所讨论的大语言模型,大多专指2023年 “ChatGPT” 爆发以来出现的众多模型,而非广义的 Transformer 架构下的所有模型。而 Prompt 的概念也正是伴随 “GPT” 模型的发展应运而生的。我们要明白 Prompt 是什么,就要知道 Prompt 的前世今生,这就要从 GPT 的发展开始谈起。
如图,自 2017 年 Transformer 诞生以来,在这个架构的基础上,以 BERT 为代表的模型和以 GPT 为代表的模型便以极快的速度向前发展。在 2018 年 BERT 诞生后,语言模型便开始重塑 NLP 领域,快速在市场中得到广泛应用,时至今日这些语言模型依然是 NLP 领域中最被广泛应用的模型,我们今天看到以 GPT 为代表的各类大模型也是其中之一。
从 GPT 的发展来看,我们可以大致划分为4个阶段," GPT1 - GPT2 - GPT3 - ChatGPT ",我们可以从这个发展过程中了解到 Prompt 是如何诞生的,以此更好的了解 Prompt。
阶段1: GPT-1 诞生在 Transformer 初期,是最早期基于 Transformer 架构打造的模型之一,其采用了和 BERT 相同的范式,通过 "pretrain + finetune" 的方式,首先让模型在大量未标注的数据上自监督的进行学习,完成预训练,随后在应用时再使用有监督数据进行微调,以此让模型可以适用于各种任务。在这种范式下 BERT 作为双向模型,可以充分的获取上下文信息,这让他在各类任务中都展现出了更精准更稳定的效果,而 GPT 作为单向模型,更擅长生成任务,而由于在这个阶段还处于大模型发展的早期,模型规模和效果还没有成长起来,因此生成的不稳定性使得 GPT 并没有被大规模应用。时至今日,即便 GPT 已经展现出了令人惊艳的效果,但目前 BERT 类的模型依然是各个业务使用更多的模型。
阶段2: 相比 GPT-1,GPT-2 第一次提出了全新的范式,当我们扩大模型规模增加训练数据,让模型在一个称为 WebText 的由数百万个网页组成的数据集上完成预训练后,模型不再需要任何监督数据,就可以完成各类任务。在 OpenAI 的 Blog 中我们可以看到,团队在研究过程中发现,提升模型规模及训练数据的体量,可以让模型在 zero-shot 任务中的效果明显提升,这也在今天被认为是对 scaling law 的第一次发现,虽然当时还没有诞生智能涌现的现象。也有人解读,由于 BERT 在各个领域展现出的优异效果,GPT 被迫找到了新的发展方向,也为如今的智能涌现奠定了基础。由此,GPT 开启了与 BERT 截然不同的范式,并在新的范式下进行研发,专注模型在 zero-shot 中的效果。
阶段3: 沿着 GPT-2 增大模型体量和训练数据规模的思路,GPT-3 使用了 570G 的训练数据,达到了 GPT-2 的15倍,参数量更是达到了惊人的 1750B,是 GPT-2 的 116 倍。参数量的提升让 scaling law 大显神威,让模型在各个领域中都展现出了令人惊艳的效果,尤其是在 zero-shot 方面,发布会上通过手绘 UI 图生成前端代码的例子至今让人印象深刻。GPT-3 在 2020 年底发布,当时 Transformer 已经经过了4年的发展,BERT 类模型已经在各类应用中被广泛使用,成为了绝对的主流。然而在这种情况下,GPT-3 的发布也依然成为了领域中最瞩目的事件,即便还是有很多问题,但其远超预期的效果依然令人震撼。
阶段4: 之后的故事大家都非常熟悉了,OpenAI 在 GPT-3 的基础上针对不同场景进行了优化,在“多轮对话”的优化中诞生了“ChatGPT”,随后成为了世界上最火热的话题,也被认为是 AI 市场化的起点。GPT-3 后的模型不再开源,也没有论文公开发表,我们只能在 Blog 中获取一些信息,此处不再进行展开。
最后我们来做个总结,从领域发展的角度我们可以看到 3 种不同的研发范式:
- Transformer 之前:有监督训练(train)
- GPT1 & BERT:无监督预训练(pre-train) + 有监督微调(finetune)
- GPT2 & GPT3:无监督预训练(pre-train) + 提示词(Prompt)
Prompt 到底是什么
Prompt 译为 “提示”,与 "zero-shot" 的概念相辅相成,“zero-shot” 就是不通过训练直接向模型提问的应用方式,而 Prompt 就是指提问的方式。从这个概念上看 “模版” 可能是更合适的称呼,为什么要用 “提示” 这个单词呢?
实际上,在刚刚出现这个概念时并没有 “Prompt” 这样的称呼,在早期的论文中其往往会被称为 “输入形式(format)” 或 “输入模版(template)”,但随着领域的发展,尤其是在 GPT-3 之后,Prompt 的叫法才被逐步确定,大家认同 “提示” 的概念与其作用更加贴切,尤其是在大语言模型的语境下尤为合适,因此逐渐成为了公认的称呼。
那 Prompt 到底在提示什么呢?从前文中对范式的解读来看,模型能力的应用越来越向 “预训练” 的部分倾斜,绝大多数能力应当是在 “预训练” 阶段就构成的,而非通过进一步的训练构建。而在这种思想的基础上,Prompt 则像一把解锁模型能力的钥匙,让这些 “预训练” 阶段构成的能力唯我所用。因此,Prompt 就是在提示模型回忆起自己在预训练时学习到的能力。
自大模型横空出世,“Prompt 工程” 一直是其中最为火热的方向之一。在此背景下,Prompt 相关的研究已经积累的十分充足,无论是公司内外都积累了众多的文章和课程,其中最火的 《Prompt Engineering Guide》 ,和吴恩达老师的 《ChatGPT Prompt Engineering for Developers》 ,都对 “Prompt 工程” 作出了详细的介绍。
Prompt 万能框架
在编写 Prompt 时,从0到1的编写出第一版是最难的,而基于已有 Prompt 利用各种技巧进行优化则相对简单。我们可以参考 “万能模版”,把 Prompt 拆分成了 立角色 + 述问题 + 定目标 + 补要求 ** 这四个部分,通过结构化的拆分完成0到1。无论面对什么任务,利用这个模版都可以得到一个“及格”的 Prompt。下面和大家阐述一下模版是如何得到的,为什么他是有效的。
基础三要素
- 问题是什么: 首先你要告诉模型你的问题是什么,你的任务是什么,要尽量描述清楚你的需求。
- 你要做什么: 下面你需要告诉大模型具体要做什么,比如做一份攻略,写一段代码,对文章进行优化,等等。
- 有什么要求: 最后我们往往还需求对任务补充一些要求,比如按特定格式输出,规定长度限制,只输出某些内容,等等。
通这 3 部分的描述我们就把 “要大模型做什么” 描述清楚了!
这仅仅是第一版 Prompt,你不需要描述的过于详细,也不需要使用技巧,只需要用简练的语言把这几部分描述清晰即可。
1 | 例如: |
任务拆分
在描述清楚任务后,我们就需要调度模型的能力去完成我们的任务,不同的任务需要用到不同的能力,这往往依赖任务的拆分。 我们可以想像,当我们让一个小白帮我们完成一项任务时,我们需要对任务进行分解,并告诉他每一步需要怎么做,以此来让他完成一项复杂的任务。对于大模型而言,这也是适用的。
你当然可以人为的完成这种拆分,再一条条的解释给大模型,但这种做法并不通用,每个领域都有自己独特的专项能力,每个任务都有自己的工作流程,因此这种方案并不适合放到一个通用的框架当中。
好在大模型能力的调用还存在一条捷径,那就是“角色”,他就像大模型里自带一个“能力包”,可以很容易的对模型能力进行调用。 每一个角色,都对应着该角色包含的若干能力,我们可以通过设定角色,“提示”大模型使用该角色对应的能力,这与前文Prompt 到底是什么 中介绍的想法极其匹配,充分说明是“Prompt” 提示的作用,通过简单的“提示”调用出大模型预先训练的能力,这也就是“角色”如此有用的原因。
框架细化
通过我们的框架,在任何任务中我们都可以完成 Prompt 从 0 到 1 的编写,而这个初版的 Prompt 还只是一个雏形,由于各部分信息还不完整,往往不能达到我们的预期,框架提供了 Prompt 的骨架,还需要我们进一步补充血肉,下面我会对框架的每一部分进行更详细的分解,通过内容的补全一步步的提升模型的效果。
立角色
角色 可以被当作大模型的“能力包”或“语法糖”,我们不再需要对每一项能力进行详细的描述,对任务进行更细节的分解,而是可以通过 import “角色” 的方式,使用这个 “角色” 背后对应的各项能力。那我们该如何设立角色,才是这个“能力包”的正确使用方式。
1 | 角色模版: |
以上是一个简单的示例,角色的设置往往需要编写者对角色有一定的了解,这可以更好的帮助你补全你的模版
如果你不了解你要设置的角色,不知道这些信息该如何填写,我们如何可以获取到这部分信息呢?
很简单,继续套用 prompt 形成一个新的工程(以获取当前角色信息为目标的prompt)
述问题 & 定目标
对问题的描述由 “述问题” 和 “定目标” 两部分组成,是 Prompt 中信息含量最大的部分,也是和任务最相关的部分,我们要明确的描述我们希望大模型做的工作,才能让大模型输出最符合预期的结果。
除了要描述的清晰明确外,此部分值得强调的就是对任务的分解,这在复杂任务上尤为重要。如果我们需要大模型完成的任务过于复杂,我们则需要先人工对任务进行拆分,并尽量详细的描述任务中包含的各个部分。
我们也可以把这种拆分当作一个任务维度的对齐,当我们用概括的语言描述一项任务时,隐含了大量的背景知识和预期。例如,当我们希望大模型帮我们 “制作一份旅游攻略” 时,我们希望他能帮我们 “规划行程”,“收集信息”,“预定酒店” 等等,而这些信息往往都被包含在 “旅游攻略” 当中。如果我们不明确的对任务进行拆分,大模型就不知道我们的任务具体需要包含哪些部分,因此这个任务维度的对齐十分重要。下面我举几个例子:
1 | 例1:请帮我制作一份深圳的旅游攻略 |
其实,这个步骤你完全可以让大模型帮助你完成, 这类似 Agent 中的 Planning的思想【Agent 详解 】,让大模型帮助你拆分一项复杂任务。你可以使用这样简单的 Prompt 完成这个任务:
1 | 任务拆分 Prompt: |
补要求
我们已经描述清楚了我们的任务,下面我们往往还需要对我们的任务提出一些要求,告诉大模型希望他做什么以及不做什么,这往往与模型在应用中的准确率息息相关。我们常用的要求可能有如下几种:
- 字数限制。
- 输出结构(结构化输出,Json 输出)。
- 在输出中排除 xxx。
- 在输出中仅包含 xxx。
- ......
让大模型遵循我们的要求,尤其是在“格式”层面让大模型的输出符合我们的规定,对大模型的工业应用十分重要。如何让大模型更听话,让其遵循我们的要求呢?
首先, 我们可以把要求放在 Prompt 的最后。大语言模型的本质是在做文本补全,后文的输出更倾向于依据距离更近的语境。
如果利用 "LIME" 这样的模型解释算法分析,距离更近的文本间权重往往更大,这在 Transofrmer 中的 Attention 权重 上也可以清晰的看到。同时,这与大模型在预训练阶段中完成的任务也更加匹配,虽然现在的大模型在 SFT 阶段会进行多种任务的训练,但其本质上还是建立在自监督“文本补全”任务上被训练出来的,因此其天然的更加遵从离得更近的文本。因此,把要求放在 Prompt 的最后可以很有效的帮助大模型变得更“听话”。
其次, 我们还可以利用大模型的“编程”能力巧妙的让他更“听话”。
我们可以通过设定角色调用大模型的能力,那有什么能力可以让大模型更“听话”呢?我们都知道“大模型”在“编程”方面也展现出了惊人的能力,而这个能力恰好可以将“模糊的文理问题”变成“准确的数理问题”,以此让大模型更加遵守我们的要求。
具体而言,就是把我们的要求转换为一个 “编码” 任务,例如:
1 | 请列出10个国家,并以列表形式返回 |
格式很重要
除了输入的内容外,输入的格式也很重要,清晰的结构对大模型的效果有很大的影响。
除了增加合适的 “空行” 让结构变的清晰外,我们还可以增加一些“标识符”来区分各个部分,例如:#,<>,```,[],-。同时大模型也具备 MarkDown 解析的能力,我们也可以借助 MarkDown 语法进行 Prompt 结构的整理。
由于“格式”对模型效果的影响,越来越多研究聚焦在了这个方向上,其中 “LangGPT” 得到了广泛的应用。LangGPT 提出了一种结构化的 Prompt 模式,可以通过一套结构化的模版构造出格式清晰的 Prompt。
例:LangGPT 示例
1 | # Role: 设置角色名称,一级标题,作用范围为全局 |
LangGPT 示例中可以看到,他用各种分隔符对 Prompt 内容进行了整理,可以很清晰的看到每部分的作用与区分。我们可以借鉴 LangGPT 对分隔符的使用,通过对格式的整理让同样的 Prompt 展现出更好的效果。
总结(框架)
我们把 “框架细化” 分成了4步,并在每一步中都提出了通用的实践方法:
- 角色:通过角色模版和招聘 JD 补全角色。
- 问题&目标:在大模型的辅助下拆分任务。
- 要求:借助编码能力,让大模型更好的遵守要求。
- 格式整理:结合 LangGPT 的思想合理应用分隔符,让 Prompt 结构清晰。
至此,我们已经完成了 Prompt 主体部分的编写,面对任何一个任务都可以通过这套统一的方法完成一个还不错的 Prompt,并且通过我们对 Prompt 结构化的拆分,我们现在也可以更好的管理我们的 Prompt,并为上层应用提供更好的支撑。
结语
大模型的推理,根本上还是基于用户输入的信息进行推理,我们提供的信息越充分,大模型就能越好的完成推进。因此,要想让模型的效果更好,我们就需要提供更多的输入信息。
增加更多信息,让效果变得更好 这个想法十分自然,但我们要增加什么信息?如何增加这些信息呢?
为了能在合适的场景下增加合适的信息,势必要引入知识库、检索的工作,来根据需要找到合适的信息,而说到 知识库、检索 就不得不提名声大噪的 RAG 了。
要深入了解 RAG,请查看 RAG 工作机制详解 篇。












