GPT PROMPT 最佳实践(中):GPT复杂任务方案和Prompt高级策略

共 13354字,需浏览 27分钟

 ·

2024-04-10 15:33


a7f53fffda3cc144b3fad1ed61af472e.webp

01


前言

书接上文,我们继续讲 GPT Prompt 最佳实践。上一篇我重点通过对prompt 充分描述、明确要求和对指令的精准表达,来实现 构建 更好效果的SYSTEM PROMPT 本篇我将重点讲解几个 Prompt的 高级策略及复杂任务的解决方案。

本篇文章的属于ppt的第二部分, 主要目录如下:

  • 4.1、复杂任务面临的问题


  • 4.2、复杂任务拆解方案


  • 4.3、提供示例:单样本和小样本方法(One/Few-Shot)


  • 4.4、链式思考(COT)


  • 4.5、给GPT时间-慢慢思考


  • 4.6、 使用外部工具




4.1


复杂任务面临的 突出问题


Outstanding issues faced by complex tasks




一、任务流复杂导致鲁棒性下降


当 GPT 执行的任务流复杂时,大概率会导致系统的鲁棒性(往往指系统的健壮性或性能的稳定性)下降。而复杂任务也往往比简单任务具有更高的错误率。特别是当你的任务,需要串联多个不同流程的子任务或者程序的时候。往往这个时候所 有的信息输入,都会占比一定权重,prompt 会比较冗长,各个子任务会相互影响,甚至导致信息紊乱及程序错乱。


同时,在一个 Prompt 当中完成全部的任务,在调试时会异常困难,当生成的内容不符合预期时,比较难定位到出现问 题的段落和文字。

列举几个我实践中常见的几个问题: 1)GPT 执行流程和逻辑不稳定,prompt不能完全限定住,会出现比较恶劣的 badcas:如GPT 不按步骤对话一次性输出全部内容;既定流程无法正常结束,或者GPT 无故突然结束流程;或者推理性问题,GPT 无法进行逐级判断而只是在一个平 行逻辑层级上无限枚举等;

2)GPT 内容输出不符合要求或输出效果不佳:如GPT输出内容出错,或者前后矛盾;GPT对用户输入的答案判定出错;GPT出题难度不分级;GPT具体内容不能定制化、个性化;GPT记 不住对话历史等;


这些问题都极大地拉低了 GPT的能效,并严重影响了用户的功能体验。而如何解决这些问题就是我今天要讲到的,主要方案包括对复杂任务的拆解、各个击破,小样本以及思维链等方法。


二、复杂任务选用模型往往涉及产品成本控制问题


都知道,高版本模型效果好,但费用也高。很多时候,直接全铺开使用高版本的模型,往往是不现实的,因为成本就在那里摆着呢,尤其是当产品的商业模式还没有跑通的情况下。


考虑到成本控制问题,我们首先能想到的就应该是进行任务拆解,如我们将大任务转化为小任务之后,部分小任务可以使用 3.5 来完成,在一些关键核心任务还可以使用高版本模型,这样可以在产品化时更为灵活。


在 Prompt Chain 当中,每个任务都可以根据需要(比如成本、任务特性)来灵活选用模型。使用更便宜的模型完成同样效果的任务。


当然从各个环节降低prompt的token 也能减少一些费用。



4.2


复杂任务 拆解方案


Split complex tasks into simpler subtasks

1、 将复杂任务拆分为更简单的子任务:按照业务逻辑或使用流程 Use intent classification to identify the most relevant instructions for a user query

正如互联网产品法则提倡的那样,我们需要将复杂系统分解为很多模块化组件进行小步迭代,而提交给 GPT 的任务也是如此。


这里面包含了两层意思,一方面早期的任务流程本身不要太复杂,尤其是实验阶段,要尽可能遵循MVP思路,在经过验证后再慢慢增加枝干逻辑;另外一方面就是 复杂任务通常可以重新定义为多个简单任务的工作流,或并行或者串行。


而重新定义子任务首选的方法就是从业务逻辑和使用流程来拆解。


业务逻辑举个例子:我在一个游戏case里设定的结束判断逻辑包括三种情况:正常流程结束、超时未响应结束和达到最大会话轮次时自动结束,如果把这三种结束逻辑都揉在一个prompt里面,逻辑非常混乱,gpt还不一定好判断,最后就拆为了3个prompt来控制;


按照使用流程来拆解,其实更好理解和操作,很多复杂的功能都可以这样来操作,比如我设计一个字词学习的任务流程,你会发现从字的讲解、考查然后再过度到词的讲解和考查,整个流程使用gpt去串联,token会非常长,任务执行效果会打折扣,这个时候拆解为字的学习和词的学习两个任务使用两个prompt去完成,结果的稳定性和输出效果就会好很多。


并且,将 复杂任务重新拆解为简单任务的工作流,其中前置任务的输出还可以用于后续任 务的输入,有时候效果并不会打折扣甚至会更好。


2、将复杂任务拆分为更简单的子任务- 使用意图分类来满足不同用户query


Use intent classification to identify the most relevant instructions for a user query


通过语义识别和意图分类,以将任务分解为多个子任务,每个子任务给出不同 解决方案。


比如我们会发现目前在语文、历史等科目的query 使用同样价位的文心一言3.5效果要明显优于gpt3.5,此时我们就会把语文、历史类query走文心来满足。


可以说, 结合意图分类新增一个触发策略,你的问答满意度就会有显著提升;


3、将复杂任务拆分为更简单的子任务- 总结或 过滤对话


For dialogue applications that require very long conversations, summarize or filter previous dialogue


由于 GPT 具有固定的上下文长度(Max token),因此user和assistant之间的对话(整个对话都包含在上下文窗口中)不能无限期 地继续下去。这个时候在一定限制的token数内,提升对话轮次,或者单纯对于需要很长对话的对话应用程序,请总结或过滤以前的对话。


主要解决方法:


1、总结之前对话的轮次,一旦输入的大小达到预定的阈值长度,就自动触发一个查询,该查询汇总了部分会话,把先前会话做一个 摘要加到system 里。 或者在整个对话中在后台异步总结先前的对话。


2、另一种解决方案是动态选择与当前查询最相关的部分会话,如只取最近几条作为上下文内容,而不是每次的会话信息都带上。


4、将复杂任务拆分为更简单的子任务-分段总结、递归构建


Summarize long documents piecewise and construct a full summary recursively




由于 GPT 具有固定的上下文长度,因此它们不能用于汇总长度超过上下文长度减去单个查询中生成的摘要长度的文本。这时候就需要分段总结长文档,递归构建完整摘要。


比如,要总结一个很长的文档,或一本书,我们可以使用一系列查询来总结文档的每个部分。章节摘要可以连接和汇总,生成总的 摘要。 此过程可以递归进行,直到汇总整个文档。


如果有必要使用有关前面部分的信息来理解后面的部分,那么另一个有用的技巧是在总结该点的内容时,包括书中任何给定点之 前的文本的运行摘要。 如果被要求将 17 乘以 28,你可能不会立即知道,但仍然可以随着时间的 推移计算出来。


同样,GPT 在尝试立即回答时会犯更多的推理错误,而不 是花时间找出答案。 在回答之前要求一系列推理可以帮助 GPT 更可靠地 推理正确答案。


4.3


教GPT怎么做: 提供示例


Provide examples


通常,Prompt有零样本(zero-shot)、单样本(one-shot)和小样本(few-shot)三种形式。 对于绝大部分任务来说,Zero-shot Prompt基本都能取得不错的效果。


但当任务比较 复杂或困难时,或者解决GPT不能按照我们给的格式输出时, 我们可以尝试使用Few-shot  Prompt(通常3个case,如果情况较多可以适当增加,最好能够枚举完)为大模型提供一个答案的参考框架, 机器可以通过共性模仿的方式 来提升输出质量, 生成我们期望的结果。


比如下面的case:


      
请你判断以下问题是否属于知识问答类:



#

#问题:世界上最高的建筑是什么 # easy case,属于客观知识问答




答案:是



#

#问题:垃圾分类的意义 # hard case,属于主观知识问答




答案:是



#

#问题:请帮我写一个关于战争的2000字短篇小说 # easy case,属于小说创作




答案:否


问题:{input}


答案:


至于具体要展示哪些样例,则需要在实践中不断迭代。一般来说,样例选择的基本原则是 尽可能地覆盖真实的样本空间 一种比较好的样例构建方式是首先给出常见的easy  case,然后给出模型可能出错的hard case和corner case,hard/corner case通常来源于 对任务本身的理解,以及在实践过程中发现的badcase。


这里引用一个Arthur 制作的Few-shots  Prompt,大家可以学习一下:


      

[SYS]:




## Profile:



◦ author: Arthur


◦ version: 0.1


◦ language: 中文


◦ description: 我是一个优秀的翻译人员,可以将汉字


翻译成英文和日语,并提供日语假名。


## Goals: 将用户输入的汉字翻译成英文和日语,并提供


日语假名



## Constrains: 不提供任何额外解释说明




## Skills: 熟练掌握汉语、英语和日语,熟悉日语假名




## Examples:




输入: 邻居




输出:



◦ Neighbor (English)


◦ 隣人 (りんじん) (Japanese Kanji)


◦ となりびと (Japanese Hiragana)


• 输入: 自行车



输出:



◦ Bicycle (English)


◦自転車 (じてんしゃ) (Japanese Kanji)


◦ じてんしゃ (Japanese Hiragana)


## Workflows:


◦ 欢迎用户,并介绍自己是一个翻译人员


◦ 翻译用户输入的汉字


◦ 输出翻译结果


• 输入: 日语



输出:



◦ Japanese (English)


◦日本語 (にほんご) (Japanese Kanji)


◦ にほんご (Japanese Hiragana)


• 输入:




4.4


链式思考: COT


Chain of Thought


我们在实际学习过程中,老师或家长都会鼓励我们“慢慢来,一步步好好 想想怎么做出来”,从而提升我们的思维能力。 对于大模型也一样,具备 逐步思考能力。 我们要想让GPT更好的推理能力,需要借助链式思考和慢 思考。 链式思考就是将复杂任务分解为一系列简单的任务,让GPT把推理 过程拆分成若干步骤,一步步输出关键环节的中间状态, 并最终完成目 标。


      
Bad:(1362+5145)*145-(1517*42+24)=?


Good:请你帮我计算一下(1362+5145)*145-(1517*42+24)=?,每一步运算过程都要展示出来,并确保计算的正确性。


实际上,一个常规的问题,加上“let’s do it step by step” 之类的词语, gpt 输出质量就会有 明显的提升,尤其是在逻辑推理与数学计算任务上。 分步骤请求的好处就是每一步更好控制,并且某些结果可以缓存,质量相 对更高,坏处是可能Tokens消耗要多一点,时间也要长一点。


      
Bad:宇宙中有外星人吗?


Good:宇宙中有外星人吗?Let's think step by step。




下面是一个链式思考的 Case:一个分步骤 翻译的Prompt:


      
首先给GPT传入的字幕文本数组,然后让GPT在翻译的时候分成三步:


- 第一步:将数组的字符串合并成一个段落,一起翻译成中文


- 第二步:再将翻译好的段落拆分成数组,和输入的数组一一匹配


- 第三步 检查返回的数组长度是不是和输入的数组长度相等,如果不相等返回第二步重试



------



You are a program responsible for translating subtitles. Your task is to translate the


subtitles into 简体中文, maintaining a colloquial tone and style, avoiding long


sentences, and ignoring verbal tics such as 'so', 'you know', etc.


The input will be a JSON-formatted string array, which should be translated in


accordance with the following steps:


Step1: Join the string array to a sentence, then translate it to 简体中文;


Step2: Split the translated sentence to a string array, each item of which should


correspond to an item in the original input array.


Step3: Verify if the count of items in the output array equals that of the input array. If it


doesn't, go back to Step 2 and try again.


Respond with a JSON-formatted string array:



------





4.5


给 GPT 时间: 思考


  Give GPTs time to "think"


1、给 GPT 时间“思考”-让模型先自行找出解决方案


Instruct  the model to work out its own solution before rushing to a  conclusion


策略: 指示模型在匆忙得出结论之前制定自己的解决方案 


有时,当我们明确指示模型在得出结论之前从第一原理进行推理时,我们就 会得到更好的结果。 比如,我们让模型出题并判断学生的回答 是否正确。实际执行过程中, 往往GPT会有惯性回答,即便是学生回答错误,GPT也会认为是正确的!所以这个时候 我们可以通过提示模型首先生成自己 的的答案,再和学生的答案进行比对,来让模型成功注意到这一点。


再比如,一个AI学习考查的prompt,我们希望既能准确判断学生的答案对错,在学生出错时要求 给出合理的提示同时又不能向学生透露答案。 将要求拆解一下:

1. 判断学生答案是否正确 2. 如果答案错误,发现学生答案中的问题,给出提示 3. 不能告诉学生答案
这个题的难点在于: - 怎么能判断学生答案中哪里错了,而不是简单的给出正确或者错误? - 怎么不泄露答案给学生? 我们先来解决判断学生答案正确性和找出错误位置的问题。

这时候就需要将推理过程拆分成若干步骤,这样可以获得更好的推理能力。按照这个思 路,我们可以将整个Prompt分成几步:


步骤1 - GPT不要依赖学生的答案,自己去解决原始的问题,因为学生的答案可能是错误 的。


步骤2 - 将步骤1中GPT生成的答案与学生的答案进行比较,评估学生的答案是否正确。


步骤3 - 如果比较两个答案后发现学生的答案是错误的,确定你可以给学生什么提示,但 不直接给出答案。 并且要求将每一步结果打印出来。


解决了如何判断结果和提示的问题后,怎么不透露答案很简单,就是要求GPT输出特定 格式,例如JSON,在得到GPT完整的输出结果后,对结果进行解析,不要输出GPT的 中间推理过程,只是输出最后对学生的提示结果。


另外,并非要将所有的步骤放在一个Prompt里面,还有一个方案就是将单个请求拆分成 个请求:


请求1:输入原始问题,要求GPT给出自己的推理和答案,并且这个结果还可以缓存起 来;


请求2:输入原始问题、GPT自己的推理和答案、学生的答案,给出学生答案的判断。


请求3:根据请求2中返回的结果,让GPT以导师的身份给出相应的提示,但是不泄露答 案。 最后给学生返回结果。 给 GPT 时间“思考”


2、给 GPT 时间“思考”-让模型用内心独白或查询进行推理


Use inner monologue or a sequence of queries to hide the model's reasoning process


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


前面的策略表明,模型在回答特定问题之前详细推理问题有时很重要。对于某些应用程序,模型用于得出最终答案的推理过程不适 合与用户共享。 例如,在AI学习考查类prompt里,要求GPT出题但是不能把出题的逻辑和正确答案说出来,就是这样。



内心 独白 的想法是指示GPT将对用户要隐藏的部分内容。 或者,这可以通过一系列查询 来实现,其中除最后一个查询外的所有查询都对最终用户隐藏其输出。 如prompt这么写: 如果学生回答错误,请确定您可以在不泄 露答案的情况下给学生提示。


总之:首先,我们可以要求模型自己解决问题。这提供了额外的优势,即模型的解决方案不会因学生尝试的解决方案而产生偏差。


接下来,我们可以让模型使用所有可用信息来评估学生答案的正确性。最后,我们可以让模型构建一个导师的角色,以一种不 会透露答案的方式向学生提供提示。 假设我们正在使用一个模型来列出与特定问题相关的来源摘录。 列出每个摘录后,模型需要确定是应该开始编写另一个摘 录还是应该停止。 如果源文档很大,则模型通常会过早停止并且无法列出所有相关摘录。 在这种情况下,通常可以通过使 用后续查询提示模型来查找它在以前的传递中遗漏的任何摘录,从而获得更好的性能。

3、给 GPT 时间“思考”-询问模型是否遗漏内容

Ask the model if it missed anything on previous passes


策略: 询问模型在之前 的传递中是否遗漏了任何内容

Ask the model if it missed anything on previous passes

对我们的启示是最后结束 prompt可以让模型在输出用户答对题数时,先自己排查一下是否有遗漏,再给出总结;


4、给 GPT 时间“思考” -后退一推理步prompt


Step-Back Prompting


这个是谷歌提出一种称为“Step-Back Prompting”的Prompt技术,让LLMs自己抽象问题,得到更高 维度的概念和原理,再用这些知 识推理并解决问题。 后退提问是一种思考策略,意在从更宏观或更基础的角度去理解和分析一个特定的问题或情境。 这种策 略要求我们在面对一个具体问题时,先“后退” 一步,从一个更广泛或更根本的角度去提问和思考。 这样做的目的是帮助我们更 深入地理解问题的背景、原因或相关的基础知识,从而更好地回答原始问题。


基于这个论文思路的中文Prompt如下:


      

##你是世界知识的专家,擅长用后退提问策略,一步步仔细思考并回答问题。



后退提问是一种思考策略,意在从更宏观或更基础的角度去理解和分析一个特定的问题或情境。你在面对一个具体问题时,先“后退”一步,从一个更广泛或更根本的角度去提问和思考。来帮助你更深入地理解问题的背景、原因或相关的基础知识,从而更好地回答原始问题。



##策略



- 核心概念识别:首先确定问题的核心概念。例如,如果问题涉及到物理学中的力,那么可能需要后退到基础的力的定义和原理。


- 问题的范围:尝试识别问题的范围和上下文。这有助于确定后退的深度。有些问题可能只需要稍微后退一步,而其他问题可能需要深入到基础原理。


- 历史和背景:对于一些问题,了解其历史背景和发展可能会有助于提出恰当的后退问题。


- 原理和假设:明确当前问题的基础原理和假设。这可以帮助确定应该从哪些方面后退。



##执行步骤



1.用中文和用户打招呼,要求用户输入一个问题,每当用户输入一个问题,你要根据以下流程回答问题.


2.给出至少3个符合<策略>的可选<后退提问>并分别回答。


3.将上述回答作为论据,有逻辑,条理的,使用可视化辅助对用户的问题进行最终作答。通过向 GPT 提供其他工具的输出来弥补它们的弱点。


例如:时效性语聊问题,使用web- search;文本检索系统可以告诉 GPT 相关文档。代码执行引擎可以帮助 GPT 进行数学运算和运行代码。


这些高级策略可以看出来,大模型非常具有人的特性,你如果能够按照人的思维方式去很好 他,效果会越来越好。


4.6


使用外部工具: 检索 变量、API、知识库等




1、使用外部工具-嵌入的搜索实现高效的知识检索


Use embeddings-based search to implement efficient knowledge retrieval


通过向 GPT 提供其他工具的输出来弥补它们的弱点。 例如:时效性语聊问题,使用 web- search ;文本检索系统可以告诉 GPT 相关文档。 代码执行引擎可以帮助 GPT 进行 数学运算和运行代码。


如果模型作为其输入的一部分提供,则可以利用外部信息源。 这可以帮助模型生成更明智和最新的响应。 例如,如果用户 询问有关特定电影的问题,则在模型的输入中添加有关电影的高质量信息(例如演员、导演等)可能很有用。 嵌入可用于 实现高效的知识检索,以便可以在运行时将相关信息动态添加到模型输入中。


文本嵌入是可以测量文本字符串之间相关性的向量。相似或相关的字符串将比不相关的字符串更紧密地结合在一起。这一 事实,加上快速矢量搜索算法的存在,意味着嵌入可用于实现有效的知识检索。 特别是,文本语料库可以拆分为块,并且 每个块都可以嵌入和存储。 然后可以嵌入给定的查询并执行矢量搜索,以从语料库中查找与查询最相关的嵌入文本块(即 在嵌入空间中最接近)。


2、使用外部工具-使用代码来执行计算或调用外部 API


Use code execution to perform more accurate calculations or call external APIs


不能依靠 GPT 自行准确地执行算术或长计算。 如果需要,可以指示模型编写和运行代码,而不是进行自己的计算。 特别 是,可以指示模型将要运行的代码放入指定的格式。 生成输出后,可以提取并运行代码。


最后,如有必要,代码执行引擎 (即 Python 解释器)的输出可以作为下一个查询的模型输入提供。


聊天完成 API 允许在请求中传递函数说明列表。这使模型能够根据提供的架构生成函数参数。生成的函数参数由 API 以 J SON 格式返回,可用于执行函数调用。 然后,可以在以下请求中将函数调用提供的输出反馈到模型中以关闭循环。 这是 使用 GPT 模型调用外部函数的推荐方法。

3、使用外部工具-授予模型对特定功能的访问权限 Give the model access to specific functions

聊天完成 API 允许在请求中传递函数说明列表。


这使模型能够根据提供的架构生成函数参数。生成的函数参数由 API 以 JSON 格式返回,可用于执行函数调用。然后,可以在 以下请求中将函数调用提供的输出反馈到模型中以关闭循环。 这是使用 GPT 模型调用外部函数的推荐方法。


case:可以 使用变量 Using variables获取到一些用户的属性。


      
你的名字叫{ai_name},][你是{ai_role},][你的性别是{ai_gender},][{ai_description}。]


[我是一名{user_grade}的学生,][我的名字叫{user_name},][我的性别是{user_gender}。]


除了使用检索、变量、API, 可以直接使用prompt接知识库或者通过函数触发知识库等。


【后台回复「prompt」获取PPT文件】


关于 prompt复杂任务的一些方法和策略, 有什么想聊的也欢迎留言讨论~


...................END...................





hello,我是阿外,10 年+PM&Designer,AGI领域关注者和研究者。 欢迎关注「波悟馆」(bo_club),也可以加我微信,申请加入读者群,和更多小伙伴一起学习交流,共同成长。






推荐阅读


GPT PROMPT 最佳实践(一)


BingChat的产品启示


Stable Diffusion安装教程


免费使用GPT-4



如果你觉得文章对你有帮助,请一定点下面👇的「分享」、「赞」和「在看」哦~


浏览 123
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报