OpenAI 新发布GPT 最佳实践:落地大模型应用的策略和战术
在今年六月份,OpenAI 在其官方文档中更新了一篇关于提高 GPT 效果的策略和方法。这篇文章包含了六种核心策略,以及一些实际的提示词案例,和知识检索和代码执行等技术来优化GPT模型的最佳实践。通过使用这些最佳实践,用户可以更好地使用 GPT 模型,并提高其效果和性能。
大部分的示例主要针对 GPT-4 模型,但对于其他模型而言也会有不少参考价值。
本文主要翻译和整理自 OpenAI 的官方文档,原文地址:https://platform.openai.com/docs/guides/gpt-best-practices
一些相关的开源资料仓库:
- 关于提示词工程(prompt)的指南、论文、讲座、笔记本和资源大全:https://github.com/yunwei37/Prompt-Engineering-Guide-zh-CN
- 使用 OpenAI API 的例子和中文指南:https://github.com/yunwei37/openai-cookbook-zh-cn
- 关于大语言模型的安全问题:提示词对抗、破解攻防的工具和案例集合:https://github.com/yunwei37/prompt-adversarial-collections
文末附有更多相关参考资料。
提高结果的六种策略
编写清晰的指令
GPT 无法读取您的思想。如果它们的输出过长,请要求简洁回复。如果它们的输出过于简单,请要求专业水平的写作。如果您不喜欢某种格式,请展示您想要看到的格式。GPT 越少猜测您想要的内容,您获得的可能性就越大。
策略:
- 在查询中包含详细信息,以获得更相关的答案。
- 要求模型扮演某个角色。
- 使用分隔符清晰地表示输入的不同部分。
- 指定完成任务所需的步骤。
- 提供示例。
- 指定输出的期望长度。
- 提供参考文本。
提供参考文本
GPT 可以自信地编造假答案,特别是当被询问奇特的话题、引用和网址时。就像一张笔记可以帮助学生在考试中取得更好的成绩一样,为 GPT 提供参考文本可以帮助它以较少的虚构进行回答。
策略:
- 指示模型使用参考文本进行回答。
- 指示模型使用参考文本中的引用进行回答。
将复杂任务分解为简单子任务
就像在软件工程中将复杂系统分解为一组模块化组件一样,提交给 GPT 的任务也是如此。相比较而言,复杂任务的错误率往往较高。此外,复杂任务通常可以重新定义为一系列较简单任务的工作流程,其中早期任务的输出用于构建后续任务的输入。
策略:
- 使用意图分类来识别用户查询的最相关指令。
- 对于需要非常长对话的对话应用程序,总结或过滤以前的对话。
- 逐段概括长文档并递归构建完整概要。
给予 GPT 足够的时间进行“思考”
如果被要求计算 17 乘以 28,您可能无法立即知道答案,但可以通过时间来计算出来。同样,GPT 在试图立即回答问题时会出现更多的推理错误,而不是花时间思考答案。在得出答案之前,要求进行一连串的推理过程可以帮助 GPT 更可靠地推理出正确答案。
策略:
- 指示模型在得出结论之前自行解决问题。
- 使用内心独白或一系列查询来隐藏模型的推理过程。
- 询问模型是否在之前的处理中漏掉了任何内容。
使用外部工具
通过向 GPT 提供其他工具的输出来弥补 GPT 的不足之处。例如,文本检索系统可以向 GPT 提供相关文档信息。代码执行引擎可以帮助 GPT 进行数学计算和代码运行。如果通过工具而不是 GPT 可以更可靠或更高效地完成任务,则将其卸载以获得最佳结果。
策略:
- 使用基于嵌入的搜索来实现高效的知识检索。
- 使用代码执行来执行更准确的计算或调用外部 API。
系统地测试变更
如果您能够进行衡量,那么改进性能就会更容易。在某些情况下,对提示的修改可能会在一些孤立的示例上实现更好的性能,但在更具代表性的一组示例上导致更差的综合性能。因此,为了确保变更对性能有正面的影响,可能需要定义一个全面的测试套件(也称为“评估”)。
策略:
- 使用参考标准答案评估模型输出。
具体的示例
每个策略都可以通过具体的战术进行实施。这些战术旨在提供尝试的思路。它们并不是完全详尽的,您可以随意尝试不在此处列出的创造性想法。本文为每个具体的策略与战术提供了一些提示词示例。
策略:编写清晰的指令
战术:在查询中包含细节以获得更相关的回答
为了获得高度相关的回复,请确保请求提供任何重要的细节或上下文。否则,您将让模型猜测您的意思。
更差的指令 | 更好的指令 |
---|---|
如何在Excel中添加数字? | 如何在Excel中累加一行美元金额?我想要自动为整个工作表的行求和,所有总数都显示在右侧的名为”Total”的列中。 |
谁是总统? | 2021年墨西哥的总统是谁?选举多久举行一次? |
编写计算斐波那契数列的代码。 | 编写一个高效计算斐波那契数列的TypeScript函数。详细注释代码,解释每个部分的作用以及为什么这样编写。 |
总结会议记录。 | 用一段话总结会议记录。然后,使用Markdown列表列出发言者及其主要观点。最后,列出发言者建议的下一步行动或待办事项(如果有)。 |
战术:要求模型扮演角色
系统消息可以用于指定模型在回复中扮演的角色。
1 | USER |
战术:使用分隔符清晰标示输入的不同部分
像三重引号、XML标记、节标题等分隔符可以帮助标示需要以不同方式处理的文本部分。
1 | USER |
1 | SYSTEM |
1 | SYSTEM |
对于像这样的简单任务,使用分隔符可能不会对输出质量产生影响。然而,任务越复杂,将任务细节澄清变得越重要。不要让 GPTs 努力理解您究竟在要求什么。
战术:指定完成任务所需的步骤
某些任务最好指定为一系列步骤。明确写出这些步骤可以让模型更容易跟随。
1 | SYSTEM |
战术:提供示例
通常情况下,提供适用于所有示例的一般说明比通过示例演示任务的所有变体更高效,但在某些情况下,提供示例可能更容易。例如,如果您打算让模型复制一种难以明确描述的用户查询响应风格。这被称为”few-shot”提示。
1 | SYSTEM |
战术:指定所需的输出长度
您可以要求模型生成指定长度的输出。目标输出长度可以根据词数、句子数、段落数、项目符号数等来指定。但请注意,指示模型生成特定数量的单词并不具有高精确度。模型更可靠地生成具有特定段落或项目符号数量的输出。
1 | USER |
1 | USER |
1 | USER |
策略:提供参考文本
战术:指示模型使用参考文本回答问题
如果我们能够为模型提供与当前查询相关的可信信息,那么我们可以指示模型使用提供的信息来组成其答案。
1 | SYSTEM |
鉴于GPT具有有限的上下文窗口,为了应用此策略,我们需要某种方式动态查找与被提问的问题相关的信息。可以使用嵌入来实现高效的知识检索。查看策略”使用基于嵌入的搜索实现高效知识检索”了解更多关于如何实现这一点的细节。
战术:指示模型使用参考文本的引文进行回答
如果输入已经被相关知识补充,直接要求模型通过引用所提供文档的段落来添加引文到其回答中就很简单了。请注意,可以通过在所提供的文档中进行字符串匹配来编程验证输出中的引文。
1 | SYSTEM |
策略:将复杂任务分解为更简单的子任务
战术:使用意图分类来识别用户查询最相关的指令
对于需要大量独立的指令集来处理不同情况的任务,首先分类查询类型并使用分类来确定需要哪些指令可能是有益的。这可以通过定义固定的类别并硬编码与处理给定类别任务相关的指令来实现。此过程也可以递归应用以将任务分解为一系列阶段。这种方法的优点是每个查询只包含执行任务的下一阶段所需的那些指令,这可能导致比使用单个查询执行整个任务时的错误率更低。这也可能导致成本更低,因为更大的提示运行成本更高(参见价格信息)。
假设例如,对于客户服务应用,查询可能被有用地分类如下:
1 | SYSTEM |
基于客户查询的分类,可以向GPT模型提供一组更具体的指令来处理下一步。例如,假设客户需要帮助”故障排除”。
1 | SYSTEM |
请注意,已经指示模型在会话状态改变时发出特殊的字符串。这使我们能够将我们的系统转变为状态机,其中状态决定哪些指令被注入。通过跟踪状态,什么指令在那个状态下是相关的,以及从那个状态允许什么状态转换,我们可以在用户体验周围设置保护,这在一种不太结构化的方法中很难实现。
战术
:对需要进行非常长对话的对话应用程序,对先前的对话进行汇总或过滤 由于GPT具有固定的上下文长度,用户和助手之间的对话不能无限地继续,如果整个对话都包含在上下文窗口中。
解决这个问题的方法有很多,其中之一是对对话的前几个回合进行汇总。一旦输入的大小达到预定的阈值长度,这可能会触发一个查询,该查询会汇总对话的一部分,先前对话的汇总可以作为系统消息的一部分。或者,先前的对话可以在整个对话过程中异步地进行汇总。
另一个解决方案是动态选择与当前查询最相关的对话的先前部分。参见战术”使用基于嵌入的搜索来实现高效的知识检索”。
战术:分段汇总长文档并递归构造完整汇总
由于GPT具有固定的上下文长度,它们不能在单个查询中用来汇总超过上下文长度减去生成汇总长度的文本。
要汇总一个非常长的文档,如一本书,我们可以使用一系列的查询来汇总每一部分的文档。部分汇总可以被连接起来并进行汇总,产生汇总的汇总。这个过程可以递归地进行,直到整个文档被汇总。如果需要使用关于早期部分的信息来理解后来的部分,那么在对那一点的内容进行汇总时包含一个运行汇总的文本,这可能是一个有用的技巧。OpenAI在之前的研究中已经研究了这种用于汇总书籍的程序的有效性,使用的是GPT-3的变体。
策略:给予 GPT 时间“思考”
战术:在匆忙得出结论前,指导模型自行找出解决方案
有时候,我们明确地指导模型在得出结论之前先进行从头至尾的推理,会得到更好的结果。比如,假设我们希望模型评估一个学生解决数学问题的方法。最直观的做法就是直接询问模型学生的解决方案是否正确。
1 | SYSTEM |
但实际上,学生的解答并不正确!我们可以通过提示模型首先生成自己的解答,从而让模型成功地注意到这一点。
1 | SYSTEM |
战术:使用内心独白或一系列查询来隐藏模型的推理过程
前一个战术表明,模型有时需要在回答特定问题之前详细地推理一个问题。对于某些应用程序,模型用来得出最终答案的推理过程是不适合与用户分享的。例如,在辅导应用程序中,我们可能希望鼓励学生自己找出答案,但是模型对学生解答的推理过程可能会向学生透露答案。
内心独白是一种可以用来解决这个问题的战术。内心独白的想法是,指导模型将那些应该对用户隐藏的输出部分放入一种结构化的格式中,使其易于解析。然后,在向用户呈现输出之前,解析输出并只使部分输出可见。
1 | SYSTEM |
或者,这也可以通过一系列查询实现,其中所有查询的输出(除了最后一个)都对最终用户隐藏。
首先,我们可以让模型自己解决问题。
由于这个初始查询不需要学生的解答,所以可以省略它。这提供了额外的优势,即模型的解答不可能被学生尝试的解答偏倚。
1 | USER |
接下来,我们可以让模型使用所有可用的信息来评估学生解答的正确性。
1 | SYSTEM |
最后,我们可以让模型使用自己的分析,构造一个有帮助的导师的回复。
1 | SYSTEM |
战术:询问模型是否在前几轮查询中遗漏了任何内容
假设我们正在使用模型列出与特定问题相关的源文本的摘录。在列出每一篇摘录之后,模型需要确定是否应开始编写另一篇,或者是否应该停止。如果源文档很大,模型通常会过早地停止,无法列出所有相关的摘录。在这种情况下,通过提示模型用后续查询找出它在前几轮中遗漏的摘录,通常可以获得更好的性能。
1 | SYSTEM |
注意,如果文档特别长,这个战术可能需要多次应用。
策略:使用外部工具
战术:利用基于嵌入的搜索实现高效的知识检索
模型可以利用作为其输入的外部信息源。这可以帮助模型生成更有依据和最新的响应。例如,如果用户询问关于特定电影的问题,将有关该电影的高质量信息(如演员、导演等)添加到模型的输入可能是有用的。嵌入可以用来实现高效的知识检索,以便在运行时动态地将相关信息添加到模型输入。
文本嵌入是一种可以测量文本字符串之间相关性的向量。相似或相关的字符串将比无关的字符串更接近。这个事实,再加上快速向量搜索算法的存在,意味着嵌入可以被用来实现高效的知识检索。具体来说,文本语料库可以被切割成块,每个块可以被嵌入并存储。然后,给定的查询可以被嵌入,向量搜索可以被执行,以找到与查询最相关的文本块(即,在嵌入空间中最接近的)。
实施示例可以在OpenAI Cookbook中找到。请参阅战术”Instruct the model to use retrieved knowledge to answer queries”,以获取如何使用知识检索来最小化模型制造错误事实的可能性的例子。
战术:使用代码执行进行更精确的计算或调用外部API
我们不能依赖GPT自己精确地进行算术或长时间的计算。在需要的情况下,可以指导模型编写和运行代码,而不是自己进行计算。特别是,可以指导模型将要运行的代码放入特定格式,如三重反引号。在产生输出后,可以提取并运行代码。最后,如果必要,可以将代码执行引擎(如Python解释器)的输出作为模型下一次查询的输入。
1 | SYSTEM |
代码执行的另一个好用途是调用外部API。如果模型在API的正确使用上得到了指导,它就可以编写使用这个API的代码。可以通过向模型提供文档和/或代码示例来指导模型如何使用API。
1 | SYSTEM |
警告:执行由模型产生的代码本质上并不安全,任何希望执行此操作的应用都应该采取预防措施。特别地,需要一个沙箱化的代码执行环境来限制不受信任的代码可能导致的危害。
策略:系统地测试改变
有时候,很难确定一个改变——例如,新的指令或新的设计——是否使你的系统更好或更差。观察几个例子可能会暗示哪个更好,但是在小样本的情况下,很难区分真正的改进和随机运气。可能这种变化在某些输入上提高了性能,但在其他输入上却降低了性能。
评估程序(或“评估”)对优化系统设计很有用。良好的评估具有以下特性:
- 代表现实世界的使用情况(或至少多样化)
- 包含许多测试用例,以获得更大的统计能力(见下表作为指南)
- 易于自动化或重复
检测到的差异 | 95%置信度所需的样本大小 |
---|---|
30% | ~10 |
10% | ~100 |
3% | ~1,000 |
1% | ~10,000 |
输出的评估可以由计算机、人或两者混合完成。计算机可以使用目标标准(例如,具有单一正确答案的问题)以及某些主观或模糊的标准自动化评估,其中模型输出由其他模型查询进行评估。OpenAI Evals 是一个开源软件框架,提供用于创建自动化评估的工具。
当存在一系列被认为是同等高质量的可能输出(例如,对于具有长答案的问题)时,基于模型的评估可能有用。哪些可以用基于模型的评估真实地进行评估,哪些需要人来评估的边界是模糊的,随着模型变得越来越有能力,这个边界正在不断地移动。我们鼓励进行实验,以确定基于模型的评估对你的用例有多大的效果。
战术:参照标准答案评估模型输出
假设已知一个问题的正确答案应该参考一组特定的已知事实。然后,我们可以使用模型查询来计算答案中包含了多少必需的事实。
例如,使用以下的系统消息:
1 | SYSTEM |
下面是一个例子,其中两个要点都得到了满足:
1 | SYSTEM |
这是一个只满足一个要点的输入示例:
1 | SYSTEM |
这是一个没有满足任何要点的输入示例:
1 | SYSTEM |
这种类型的基于模型的评估有许多可能的变体。考虑下面这个跟踪候选答案和金标准答案之间的重叠种类,以及候选答案是否与金标准答案的任何部分矛盾的变体。
1 | SYSTEM |
这是一个输入例子,其中的答案质量较差:
1 | SYSTEM |
这是一个有好答案的输入示例:
1 | SYSTEM |
相关资料
- OpenAI 官方 Blog:使用 OpenAI API 进行提示词工程的最佳实践:关于如何构建一个 AI 应用,从提示词工程到向量数据库、微调等等的详细指南。
https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-openai-api
这篇文章主要针对于 GPT-3,可能相对而言有些过时,但也是一个入门的不错选择。
- 微软发布的关于构建 AI 应用的概念和学习资料:关于如何构建一个 AI 应用,从提示词工程到向量数据库、微调等等的详细指南。
这里也有一些相关的开源资料仓库:
- 关于提示词工程(prompt)的指南、论文、讲座、笔记本和资源大全:https://github.com/yunwei37/Prompt-Engineering-Guide-zh-CN
- 使用 OpenAI API 的例子和中文指南:https://github.com/yunwei37/openai-cookbook-zh-cn
- 关于大语言模型的安全问题:提示词对抗、破解攻防的工具和案例集合:https://github.com/yunwei37/prompt-adversarial-collections
OpenAI 新发布GPT 最佳实践:落地大模型应用的策略和战术