作者:openai

 

2023年6月份,OpenAI更新了一篇题目为 《GPT 最佳实践/GPT Best Practice》的文档;里面介绍了一些与 ChatGPT 交互的技巧,且附有用例。

 

先上总结:

6个策略 具体措施
1. 编写清晰的指示 1.1 在查询中包含详细信息以获得更相关的答案
1.2 要求模型扮演角色
1.3 使用分隔符清晰地标示输入的不同部分
1.4 明确完成任务所需的步骤
1.5 提供示例
1.6 指定期望输出的长度
2. 提供参考文本 2.1 指示模型使用参考文本来回答问题
2.2 指导模型使用参考文献中的引用来回答问题
3. 将复杂任务拆分为更简单的子任务 3.1 使用意图分类来确定用户查询中最相关的指令
3.2 对需要非常长对话的对话应用程序,对之前的对话进行总结或过滤
3.3 逐段总结长篇文档并递归构建完整总结
4. 给 GPT 一些“思考”时间 4.1 指导模型在盲目下结论之前自行解决问题
4.2 使用内心独白或一系列查询来隐藏模型的推理过程
4.3 询问模型之前是否遗漏了任何内容
5. 使用外部工具 5.1 使用基于嵌入的搜索实现高效知识检索
5.2 使用代码执行来进行更准确的计算或调用外部API
6. 系统地测试更改 6.1 根据标准答案评估模型输出

 

正文开始:

本指南分享了从 GPT 获取更好结果的策略和技巧,这里描述的方法有时可以组合使用以产生更大的效果。

特别说明:官方文档中,一些前置的通用要求,写在system里以不受用户后续指令的影响。使用过程中,我们可能没办法每次去修改system指令,这些通用要求可以直接写在我们作为user的问题前面去要求chatgpt。

获取更好结果的六个策略

1. 编写清晰的指示

GPT 不能读懂您的心思。如果它们的输出结果太长,请要求简短回复。如果输出内容过于简单,请要求专家级别的写作。如果您不喜欢输出的格式,请展示您想看到的格式。GPT 对您的需求猜测得越少,您获得满意结果的可能性就越大。

1.1 在查询中包含详细信息以获得更相关的答案

为了获得高度相关的回应,确保请求提供任何重要的细节或背景。否则,您将把理解您的意思的任务交给模型去猜测。

差问题 改进
如何在 Excel 中添加数字? 如何在 Excel 中对一行金额数字进行加总?我想自动执行整个工作表上的所有行,并将所有总数放在右边名为“总计”的列中。
谁是总统? 2021 年墨西哥总统是谁?选举的频率如何?
编写代码计算斐波那契数列。 编写一个 Python 函数来高效地计算斐波那契数列。请充分注释代码,说明每部分代码的作用以及为什么这样编写。
总结会议记录。 将会议记录总结为一个段落。然后用 Markdown 列出发言者及其关键观点。最后,如果有的话,请列出发言者建议的下一步行动或待办事项。

1.2 要求模型扮演角色

可以指定模型在回复中使用的角色,它会表现的更专业。

好问题:

当我请求帮助撰写某件东西时,你要回复一篇包含至少每段都有一个笑话或幽默评论的文档。

给我的钢螺栓供应商写一封感谢信,感谢他们及时交货并且提前通知。这使我们能够按时完成一个重要订单。

1.3 使用分隔符清晰地标示输入的不同部分

分隔符(如三引号、XML 标签、章节标题等)有助于划分需要区别对待的文本部分。
对于一些简单任务,使用分隔符可能不会对输出质量产生影响。然而,任务越复杂,消除任务细节的歧义就越重要。不要让 GPT 辛苦地去理解您到底在要求它们做什么。在处理更复杂的问题时,请确保提供明确、详细的指示,并通过使用分隔符等方式明确标识需要特殊处理的文本部分。这样有助于获得更准确、高质量的回答。

示例1:将以下由三引号包含的文本总结为一句话。”””在这里插入文本”””

示例2:您将收到2个关于相同主题的文章(用 XML 标签分隔)。首先总结每篇文章的观点。然后指出哪篇文章的论据更有说服力,并解释原因。<article> 文章1 </article><article> 文章2</article>

示例3:您将收到一篇论文摘要和一个建议的论文标题。论文标题应向读者传达论文主题,同时具有吸引力。如果标题不符合这些标准,请提供5个替代方案。 摘要:在此处插入摘要;标题:在此处插入标题

1.4 明确完成任务所需的步骤

有些任务最好通过一系列步骤来指定。明确地写出这些步骤可以使模型更容易执行。

示例: 按照以下逐步说明来响应用户输入。

第1步 – 用户将用三引号提供文本。以 “总结: ” 作为前缀,用一句话总结这段文字。

第2步 – 将第1步的摘要翻译成英语,前缀为 “翻译: “。 “””在此处插入文本”””

1.5 提供示例

提供适用于所有示例的一般性指导通常比通过示例演示任务的所有排列更有效,但在某些情况下,提供示例可能更容易。例如,如果您希望让模型复制一种难以明确描述的特定回答询问方式。这被称为 “few-shot” 提示。

示例:[system]以一致的风格回答问题。教我关于耐心的道理。

“助手会回答:雕刻最深山谷的河流源自一个温文尔雅的泉眼;最宏伟的交响乐始于一个单音;最复杂的织锦开始于一个孤独的线程。”

(接下来问)教我关于海洋的知识。

1.6 指定期望输出的长度

您可以要求模型生成特定目标长度的输出。目标输出长度可以用单词数、句子数、段落数、项目符号等来表示。但请注意,要求模型生成特定数量的单词精确度较低。模型更能可靠地生成具有特定数量段落或项目符号的输出。

示例1:将以下由三引号分隔的文本总结为约50个单词。”””一段文字”””

示例2:将以下由三引号分隔的文本总结为2段。”””一段文字”””

示例3:将以下由三引号分隔的文本总结为3个项目符号。”””一段文字”””

2. 提供参考文本

GPT 在回答一些深奥主题或需要引用和网址的问题时,可能会自信地编造虚假答案。就像一张笔记纸可以帮助学生在考试中取得更好的成绩一样,为 GPT 提供参考文本可以帮助它们在回答问题时减少捏造内容。

2.1 指示模型使用参考文本来回答问题

如果我们能为模型提供与当前查询相关的可靠信息,那么我们可以指示模型利用所提供的信息来撰写答案。
鉴于 GPT 具有有限的上下文窗口,为了应用这个策略,我们需要某种方式动态查找与所提问题相关的信息。嵌入可以用于实现高效的知识检索。请参阅策略 “使用基于嵌入的搜索实现高效知识检索”,了解如何实现这一点的更多细节。

示例:使用由三引号分隔的提供的文章来回答问题。如果答案不能在文章中找到,请回答 “我无法找到答案。”

<插入多个以三引号分隔的文章>

我的问题:<在此处插入问题>

2.2 指导模型使用参考文献中的引用来回答问题

如果输入已经包含了相关知识,那么可以直接要求模型通过引用提供的文档中的段落来为答案添加引用。需要注意的是,在输出中的引用可以通过在提供的文档中进行字符串匹配来进行编程验证。

示例:您将得到一个由三重引号分隔的文档和一个问题。您的任务是仅使用提供的文档回答问题,并引用用于回答问题的文档段落。如果文档中没有回答此问题所需的信息,那么只需写上:“信息不足”。如果提供了问题的答案,必须用引文注释它。请使用以下格式来引用相关段落({“引用”: …})。 “””<在这里插入文档>”””

我的问题:<插入问题>

3. 将复杂任务拆分为更简单的子任务

正如在软件工程中将一个复杂系统分解为一组模块化组件是一种很好的做法一样,这对于提交给 GPT 的任务也同样适用。复杂任务往往比简单任务具有更高的错误率。此外,复杂任务通常可以被重新定义为由一系列简单任务组成的工作流程,其中前面任务的输出用于构建后续任务的输入。

3.1 使用意图分类来确定用户查询中最相关的指令

对于需要大量独立指令集来处理不同情况的任务,首先对查询类型进行分类,然后根据该分类确定所需的指令可能是有益的。这可以通过定义固定类别并硬编码与处理给定类别任务相关的指令来实现。这个过程也可以递归地应用于将任务分解为一系列阶段。这种方法的优点是每个查询只包含执行任务下一阶段所需的指令,与使用单个查询执行整个任务相比,错误率可能较低。这也可以降低成本,因为较大的提示运行成本更高。

例如,在客户服务应用程序中,查询可以按以下方式有用地进行分类:

您将获得客户服务查询。请将每个查询分类为一个主要类别和次要类别。以json格式提供您的输出,键为:primary 和 secondary。

主要类别:计费、技术支持、账户管理或一般咨询。

计费次要类别:
退订或升级
添加支付方式
收费说明
对收费提出异议

技术支持次要类别:
故障排除
设备兼容性
软件更新

账户管理次要类别:
重置密码
更新个人信息
关闭账户
账户安全

一般咨询次要类别:
产品信息
定价
反馈意见
与人工客服交流

客户咨询的问题是:我的网断了

可以得到结果: { “primary”: “技术支持”, “secondary”: “故障排除” }

模型已被指示在对话状态改变时发出特殊的字符串。这使我们能够将系统转化为一种状态机,其中状态确定注入的指令。通过跟踪状态、在该状态下哪些指令是相关的,以及从该状态允许的状态转换(可选),我们可以在用户体验周围设置难以通过较不结构化的方法实现的保护措施。

3.2 对需要非常长对话的对话应用程序,对之前的对话进行总结或过滤

由于GPT具有固定的上下文长度,用户和助手之间的对话无法无限制地继续,而整个对话都包含在上下文窗口中。
解决此问题有多种方法,其中之一是总结对话中以前的轮次。一旦输入大小达到预定的阈值长度,就可以触发一个查询,该查询可总结对话的一部分,并将先前对话的摘要包含在系统消息中。或者,在整个对话过程中,在后台异步地总结先前的对话。
另一种解决方案是根据当前查询动态选择与之前对话部分最相关的内容。请参阅策略“使用基于嵌入的搜索来实现高效知识检索”。

3.3 逐段总结长篇文档并递归构建完整总结

由于GPT具有固定的上下文长度,它们不能用于在单个查询中总结比上下文长度减去生成的摘要长度更长的文本。
为了总结一篇非常长的文档,如一本书,我们可以使用一系列查询来总结文档的每个部分。各部分摘要可以连接并进行总结,从而生成摘要的摘要。这个过程可以递归进行,直到整个文档被总结。如果在理解后面部分时需要使用关于前面部分的信息,那么在总结某点内容时,包含在书中任何给定点之前的文本的运行总结是有用的。OpenAI在使用GPT-3的变体进行研究时,已经研究过这种程序总结书籍的有效性。

4. 给 GPT 一些“思考”时间

如果要求您计算 17 乘以 28,您可能不会立刻知道答案,但给予时间仍然可以解决问题。同样,GPT 在试图立即回答问题时,比花时间计算答案更容易出现推理错误。在回答问题之前,要求提供一系列推理过程可以帮助 GPT 更可靠地推导出正确答案。

4.1 指导模型在盲目下结论之前自行解决问题

有时候,在得出结论之前明确地指导模型从基本原理推理会得到更好的结果。

例如,假设我们要让模型评估学生解决数学问题的方法。最明显的方法是简单地询问模型学生的解决方案是否正确。

判断学生的解决方案是否正确。
问题陈述:我正在建立一个太阳能发电设备,并需要帮助计算财务数据。

土地费用为每平方英尺100美元
我可以以每平方英尺250美元的价格购买太阳能电池板
我谈判了一份维护合同,每年将花费我10万美元的固定费用和每平方英尺额外10美元。 
求第一年运营的总成本作为平方英尺数的函数。
学生的解决方案:令x为安装面积(以平方英尺为单位)。

土地成本:100x
太阳能电池板成本:250x
维护成本:100,000 + 100x 
总成本:100x + 250x + 100,000 + 100x = 450x + 100,000 

得到回答:学生的解决方案是正确的。 但是学生的解决方案实际上是不正确的!我们可以通过提示模型首先生成自己的解决方案来使模型成功地注意到这一点。

改进:

首先自己解决这个问题。然后将你的解决方案与学生的解决方案进行比较,评估学生的解决方案是否正确。
在你自己完成问题之前,不要判断学生的解决方案是否正确。

问题陈述:我正在建立一个太阳能发电设备,并需要帮助计算财务数据。

土地费用为每平方英尺100美元
我可以以每平方英尺250美元的价格购买太阳能电池板
我谈判了一份维护合同,每年将花费我10万美元的固定费用和每平方英尺额外10美元。 
求第一年运营的总成本作为平方英尺数的函数。
学生的解决方案:令x为安装面积(以平方英尺为单位)。

土地成本:100x
太阳能电池板成本:250x
维护成本:100,000 + 100x 
总成本:100x + 250x + 100,000 + 100x = 450x + 100,000 

得到了正确的回答:

令 x 为安装面积(以平方英尺为单位)。

土地成本:100x
太阳能电池板成本:250x
维护成本:100,000 + 10x 总成本:100x + 250x + 100,000 + 10x = 360x + 100,000
学生的解决方案是错误的。
他们在计算维护成本时出现了错误,使用了100x而不是10x。第一年运营的正确总成本为360x + 100,000。

4.2 使用内心独白或一系列查询来隐藏模型的推理过程

前面的策略表明,在回答特定问题之前,模型有时需要详细地对一个问题进行推理。对于某些应用程序,模型在得出最终答案时所使用的推理过程可能不适合与用户共享。例如,在辅导应用程序中,我们可能希望鼓励学生自己解决问题,但是模型关于学生解决方案的推理过程可能会向学生透露答案。
内心独白是一种可以用来减轻这个问题的策略。内心独白的思路是指导模型将一些输出放入结构化格式,使解析它们变得容易,这些输出部分是为了向用户隐藏。然后在将输出呈现给用户之前,对输出进行解析,并且只显示部分输出。

示例:

按照以下步骤回答问题。
步骤1 - 首先自己解决问题。不要依赖学生的解决方案,因为它可能是错误的。将此步骤内的所有工作用三重引号(""")括起来。
步骤2 - 将您的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。将此步骤内的所有工作用三重引号(""")括起来。
步骤3 - 如果学生犯了错误,请确定您可以给学生提供什么提示而不泄露答案。将此步骤内的所有工作用三重引号(""")括起来。
步骤4 - 如果学生犯了错误,在前一步中向学生提供提示(不使用三重引号)。不要写“步骤4 - ...”,而是写“提示:”。

问题陈述:<插入问题陈述>
学生解决方案:<插入学生解决方案>

或者,这可以通过一系列查询实现,其中除最后一个以外的所有查询都对最终用户隐藏。

首先,我们可以要求模型自己解决问题。由于这个初始查询不需要学生的解决方案,所以可以省略。这还提供了额外的好处,即模型的解决方案不会受到学生尝试解决方案的影响。接下来,我们可以让模型使用所有可用的信息来评估学生解决方案的正确性。最后,我们可以让模型使用自己的分析构建一个以有益导师为人格的回复。

4.3 询问模型之前是否遗漏了任何内容

假设我们正在使用一个模型来列出与特定问题相关的源文件摘录。在列出每个摘录后,模型需要确定它是否应该开始编写另一个摘录或停止。如果源文档很大,那么模型经常会过早停止并未列出所有相关的摘录。因此可以采用这个策略,询问模型在之前是否遗漏了任何内容。

5. 使用外部工具

通过将其他工具的输出提供给 GPT,来弥补 GPT 的不足。例如,一个文本检索系统可以告诉 GPT 有关的文件资料。代码执行引擎可以帮助 GPT 进行数学运算和运行代码。如果一个任务可以通过工具而非 GPT 更可靠或高效地完成,那么将其分配给相应工具,以便充分发挥各自优势。

5.1 使用基于嵌入的搜索实现高效知识检索

如果将外部信息源作为输入的一部分提供给模型,那么模型就可以利用这些信息生成更有见地且更及时的回答。例如,如果用户询问关于某部特定电影的问题,将关于该电影的高质量信息(如演员、导演等)添加到模型的输入中可能会很有帮助。嵌入可用于实现高效的知识检索,以便在运行时动态向模型输入中添加相关信息。

文本嵌入是一个可以度量文本字符串之间关联性的向量。相似或相关的字符串在嵌入空间里会比不相关的字符串距离更近。利用这一事实以及快速向量搜索算法的存在意味着嵌入可以用来实现高效的知识检索。具体而言,可以将文本语料库拆分成多个块,然后将每个块嵌入并存储起来。接下来,将查询请求进行嵌入,然后执行向量搜索以找到与查询请求最相关的文本块(即在嵌入空间中距离最近的那些文本块)。

OpenAI Cookbook 中提供了一些实现示例。请参阅策略 “指导模型使用检索到的知识回答问题” 以了解如何使用知识检索来尽量减少模型编造错误事实的可能性。

5.2 使用代码执行来进行更准确的计算或调用外部API

不能依赖GPT自己准确地执行算术或长时间的计算。在需要的情况下,可以指导模型编写并运行代码,而不是自己进行计算。特别是,可以指导模型将要运行的代码放入设计好的格式中,例如使用三个反引号。生成输出后,可以提取并运行代码。最后,如果需要,可以将代码执行引擎(如Python解释器)的输出作为输入提供给模型以进行下一次查询。

示例:可以写一段Python代码放在三个反引号之间来编写和执行代码,例如 “`一段python代码“`。使用此方法进行计算。 用户 求以下多项式的所有实数根:3x**5 – 5x4 – 3*x3 – 7*x – 10。

另一个适合代码执行的场景是调用外部API。如果指导模型正确使用API,它可以编写利用API的代码。通过向模型提供API文档和/或代码示例来教导它如何使用API。

6. 系统地测试更改

如果能够衡量性能,改进性能将变得更容易。在某些情况下,对提示进行修改可能会在少数个别示例上取得更好的性能,但在更具代表性的示例集上导致整体性能下降。因此,为确保某项更改对性能产生净正面影响,可能需要定义一个全面的测试套件(也称为 “eval”)。
有时候,很难判断某种变化(如新指令或新设计)是让您的系统变得更好还是更糟。观察几个例子可能会暗示哪一个更好,但在小样本情况下,很难区分真正的改进与偶然的运气。也许这种变化对某些输入的性能有所帮助,但对其他输入的性能却有所损害。

评估程序(或称为 “evals”)对于优化系统设计非常有用。好的评估程序具有以下特点:

  1. 能代表实际使用情况(或至少多样化)
  2. 包含大量测试用例以获得更大的统计效力(参见下表以获取指南)
  3. 容易自动化或重复操作

输出的评估可以由计算机、人类或二者结合来完成。计算机可以使用客观标准(如只有一个正确答案的问题)以及一些主观或模糊标准自动化评估,其中模型输出由其他模型查询进行评估。OpenAI Evals是一个开源软件框架,提供了创建自动化评估的工具。

在存在多种可能输出的情况下,基于模型的评估可以很有用,而这些输出在质量上被认为是同样高的(例如,针对长答案的问题)。可以通过基于模型的评估实际评估的边界以及需要人类评估的内容之间的界限是模糊的,并且随着模型变得越来越强大,这个界限也在不断改变。我们鼓励进行实验,了解基于模型的评估对您的应用场景的适用性如何。

6.1 根据标准答案评估模型输出

假设我们知道一个问题的正确答案应该引用一组特定的已知事实。那么,我们可以使用模型查询来统计答案中包含了多少所需事实。

例如,使用以下系统消息:

您将收到用三个引号分隔的文本,该文本应该是问题的答案。检查以下信息是否直接包含在答案中:

尼尔·阿姆斯特朗是第一个踏上月球的人。
尼尔·阿姆斯特朗首次登月的日期是1969年7月21日。
针对这些要点执行以下步骤:

1 - 重新陈述要点。
2 - 提供答案中与此要点最相关的引用。
3 - 考虑一下,如果一位不了解这个主题的读者阅读了这个引用,他是否可以直接推断出这个要点。在下定决心之前,解释为什么能或不能。
4 - 如果第3步的答案是肯定的,请写"是",否则请写"否"。

最后,统计有多少个"是"的答案。以 {"count": <插入数量>} 的形式提供此次数。