我是如何赢得GPT-4提示工程大赛冠军的

日期: 2024-05-17 作者: 新闻资讯

  去年 11 月 8 日,新加坡政府科技局(GovTech)组织举办了首届 GPT-4 提示工程(Prompt Engineering)竞赛。数据科学家 Sheila Teo 最终夺冠,成为最终的提示女王(Prompt Queen)。之后,Teo 发布了一篇题为《我如何赢得了新加坡 GPT-4 提示工程赛》的博客文章,慷慨分享了其获胜法门。机器之心对这篇文章进行了不改变原义的翻译与整理,以让我们的读者同样成为 LLM 提示工程达人。

  上个月,我非常荣幸地赢得了新加坡首届 GPT-4 提示工程竞赛;该竞赛由新加坡政府科技局组织,汇聚了 400 多名优秀的参赛者。

  提示工程是一门融合了艺术和科学的学科 —— 它既需要对技术的理解,也需要创造力和战略思维。这篇文章汇编了我一路以来学习到的提示工程策略,这些策略能让 LLM 切实完成你想完成的任务并做到更多!

  作者注:写作本文时,我试图摆脱已在网上被广泛讨论和整理成文档的传统提示工程技术。相反,我的目标是分享我通过实验学习到的新见解以及对理解和处理某些技术的一些不同的个人看法。希望你会喜欢这篇文章!

  本文包含以下内容,其中 是指适合初学者的提示工程技术,而 是指进阶技术。

  4. [] 仅使用 LLM 分析数据集,不使用插件或代码 —— 附带一个实操示例:使用 GPT-4 分析一个真实的 Kaggle 数据集。

  为了让 LLM 给出最优响应,为 prompt 设置有效的结构至关重要。CO-STAR 框架是一种可以方便用于设计 prompt 结构的模板,这是新加坡政府科技局的数据科学与 AI 团队的创意成果。该模板考虑了会影响 LLM 响应的有效性与相关性的方方面面,从而有助于得到更优的响应。

  (C) 上下文(Context):提供与任务有关的背景信息。这有助于 LLM 理解正在讨论的具体场景,从而确保其响应是相关的。

  (O) 目标(Objective):定义你希望 LLM 执行的任务。明晰目标有助于 LLM 将自己响应重点放在完成具体任务上。

  (S) 风格(Style):指定你希望 LLM 使用的写作风格。这可能是一位具体名人的写作风格,也可以是某种职业专家(比如商业分析师或 CEO)的风格。这能引导 LLM 使用符合你需求的方式和词语给出响应。

  (T) 语气(Tone):设定响应的态度。这能确保 LLM 的响应符合所需的情感或情绪上下文,比如正式、幽默、善解人意等。

  (A) 受众(Audience):确定响应的目标受众。针对具体受众(比如领域专家、初学者、孩童)定制 LLM 的响应,确保其在你所需的上下文中是适当的和可被理解的。

  (R) 响应(Response):提供响应的格式。这能确保 LLM 输出你的下游任务所需的格式,比如列表、JSON、专业报告等。对于大多数通过程序化方法将 LLM 响应用于下游任务的 LLM 应用而言,理想的输出格式是 JSON。

  这里通过一个实际案例说明 CO-STAR 为什么有用。假设你是一位社会化媒体管理者,你需要帮助草拟一篇 Facebook 帖文,其內容是宣传你公司的新产品。

  这个结果也许够用了,但却只是泛泛而谈,缺乏具体的细节和有明确的目的性的吸引力,而这些是吸引目标受众所必需的。

  通过使用 CO-STAR,GPT-4 的响应会变得明显更有明确的目的性、效果更好:

  CO-STAR 框架能引导用户以一种结构化的方式向 LLM 提供有关你的任务所有关键信息,从而确保得到完全符合你的需求的定制化的更优的响应。

  分隔符是一种特殊 token,可帮助 LLM 分辨 prompt 的哪些部分应被视为单个含义单元。这很重要,因为输入 LLM 的整个 prompt 是单个的 token 长序列。分隔符能将 prompt 中不同部分隔离开,从而为这个 token 序列提供结构,让其中每个部分能被区别对待。

  需要说明的是,如果任务很简单,那么分隔符对 LLM 的响应质量的影响不大。但是,任务越复杂,使用分隔符分节对 LLM 响应的影响就越大。

  分隔符能够正常的使用任何通常不会同时出现的特殊字符序列,举些例子:###、===、

  特殊字符的数量和类型并不重要,只要它们足够独特即可,这样才可以让 LLM 将它们理解成内容分隔符,而不是普通的标点符号。

  上面例子中使用的分隔符是 ###,同时每一节都带有完全大写的标题以示区分,如 EXAMPLE CONVERSATIONS 和 EXAMPLE OUTPUTS。前置说明部分陈述了要分类的对话是在

   中,这些对话是在 prompt 末尾提供,也不带任何解释说明文本,但由于有了 和 这样的分隔符,LLM 就能理解这就是要分类的对线 对此 prompt 给出的输出如下,其给出的情感分类结果不带任何附加文本,这符合我们的要求:

  另一种方法是使用 XML 标签作为分隔符。XML 标签是使用尖括号括起来的成对标签,包括开始和结束标签。比如 。这很有效,因为 LLM 在训练时就看过了大量用 XML 标注的网络内容,已经学会了理解其格式。

  同样的,使用这样的分隔符能以清晰的结构化方式对 prompt 进行分节,从而确保 GPT-4 输出的内容就刚好是你想要的结果:

  在深入之前,需要指出这一节的内容仅适用于具有 System Prompt(系统提示)功能的 LLM,而本文其它章节的内容却适用于任意 LLM。当然,具有这一功能的最著名 LLM 是 ChatGPT,因此这一节将使用 ChatGPT 作为示例进行说明。

  首先,我们先把术语搞清楚:对于 ChatGPT,有大量资源使用 System Prompts、System Messages 和 Custom Instructions 这三个术语,而且很多时候它们的意思似乎差不多。这给很多人(包括我)带来了困扰,以至于让 OpenAI 都专门发了一篇文章来解释这些它们。简单总结一下:

  不过整体而言,这三个术语指代的是同一对象,因此请不要过多纠结于此!我们这一节将使用 System Prompts 这个术语。现在继续深入吧!

  System Prompts 是指附加的额外 prompt,其作用是指示 LLM 理应的行为方式。之所以说这是额外附加的,是因为它位于「普通」prompt(也被称为用户 prompt)之外。

  在一组聊天中,每一次你都要提供一个新的 prompt,System Prompts 的作用就像是一个 LLM 会自动应用的过滤器。这在某种程度上预示着,在一组聊天中,LLM 每次响应都要考虑 System Prompts。

  你脑袋冒出的第一个问题可能是:我为什么应该在 System Prompts 中提供指令,毕竟我可以在一组聊天的第一个 prompt 中提供这些指令?

  答案是因为 LLM 的对话记忆有局限。如果在一组对话的第一个 prompt 中提供这些指令,随着对话的进行,LLM 可能会「遗忘」你提供的第一个 prompt,其中的指令也就失效了。

  另一方面,如果在 System Prompts 中提供这些指令,那么 LLM 就会自动将其与新的 prompt 一起纳入考量。这能确保随着对话进行,LLM 能持续接收这些指令,无论聊天变得多长。

  总结一下:使用 System Prompts 提供你希望 LLM 在整个聊天过程中全程记住的指令。

  现在你很有可能会想:看起来 System Prompt 中已经给出了大量信息。那么我们又该在「普通」prompt(也称为用户 prompt)中放什么内容?

  但我们能更加进一步泛化这个示例任务。在实践中,你更可能会有多个希望得到解答的问题,而不只是一个。在这个案例中,我们大家可以将上述 System Prompt 的第一行从

  现在,每个用户 prompt 中都既包含执行问答所基于的文本,也包含所要回答的问题。

  总结起来,System Prompt 应能给出整体的任务指令,而每个用户 prompt 应提供你希望执行任务时使用的确切细节。比如在这个案例中,这个确切的细节是文本和问题。

  在上面,防护围栏是通过 System Prompt 中的几句话添加的。然后,这些防护围栏在聊天的整一个完整的过程中就不变了。那如果你希望在对话的不同位置使用不相同的防护围栏呢?

  不幸的是,对于 ChatGPT 用户界面的用户,目前还没有能做到这一点的简单方法。但是,如果你通过编程方法与 ChatGPT 交互,你就很幸运了!现在人们对构建有效的 LLM 防护围栏的兴趣慢慢的变大,有研究者开发了一些开源软件包,可让用户能以编程方式设置远远更加细节和动态的防护围栏。

  英伟达团队开发的 NeMo Guardrails 尤其有必要注意一下,这能让用户配置与 LLM 之间的期望对话流,从而在聊天的不同位置设置不一样的防护围栏,实现随聊天不断演进的动态防护围栏。我强烈建议你研究看看!

  你可能听说过 OpenAI 为 GPT-4 版本的 ChatGPT 提供的 Advanced Data Analysis(高级数据分析)插件 —— 高级(付费用户)能够正常的使用。这让用户都能够向 ChatGPT 上传数据集,然后直接在数据集上运行代码,实现精准的数据分析。

  但你知道吗,其实不使用这样的插件也能让 LLM 分析数据集?我们第一步了解一下完全使用 LLM 分析数据集的优势和局限。

  你可能已经知道,LLM 执行准确数学计算的能力有限,这使得它们不适合需要对数据集进行精确定量分析的任务,比如:

  统计分析:比如假设测试,能确定不同数据点分组之间是不是存在统计学上的显著差异。

  机器学习:在数据集上执行预测性建模,能够正常的使用的方法有线性回归、梯度提升树或神经网络。

  正是为了在数据集上执行这样的定量分析任务,OpenAI 才做了 Advanced Data Analysis 插件,这样才可以借助编程语言来为这些任务在数据集上执行代码。

  LLM 擅长识别模式和趋势。这种能力源自 LLM 训练时使用的大量多样化数据,这让它们能识别出可能并不显而易见的复杂模式。

  该示例会使用一个常用的真实世界 Kaggle 数据集,该数据集是为客户个性分析任务收集整理的,其中的任务目标是对客户群进行细分,以更好地了解客户。

  为了方便后面验证 LLM 的分析结果,这里仅取用一个子集,其中包含 50 行和最相关的列。之后,用于分析的数据集如下所示,其中每一行都代表一个客户,列则描述了客户信息:

  假设你在该公司的宣传团队工作。你的任务使用这个客户信息数据集来指导营销工作。这个任务分为两步:第一步,使用数据集生成有意义的细分客户群。第二步,针对每个细分群生成最好的经营销售的策略。现在,这样的一个问题就成了模式发现(第一步)的实际业务问题,这也正是 LLM 擅长的能力。

  下面针对这个任务草拟一个 prompt,这里用到了 4 种提示工程技术(后面还有非常多!):

  之后,GPT-4 以我们要求的 markdown 报告格式回复其分析结果:

  其刚好对应于 LLM 识别出的人群画像。它甚至能在不事先预处理的情况下聚类空值行!

  这个例子彰显了 LLM 发现模式的能力,其能从多维度的数据集中解读和提炼出有意义的见解,这能确保其分析深深植根于数据集的事实真相。

  为了完整比较,我使用同样的 prompt 尝试了同样的任务,但是让 ChatGPT 使用代码执行分析,这会激活其高级数据分析插件。这里的思路是让插件直接在数据集上运行 k - 均值聚类等聚类算法的代码,从而得到每个客户群,之后再合成每个聚类的人群画像,以提供营销策略。

  但是,多次尝试都得到了以下报错信息,并没有输出,尽管这个数据集只有 50 行:

  目前而言,使用高级数据分析插件只能执行更简单的数据集任务,比如计算描述性统计信息或创建图表,但需要算法的更高级任务有时可能会遭遇报错,没办法得到输出结果,原因可能是计算限制等问题。

  对于需要精准数学计算或基于规则的复杂处理的任务,常规的编程方法依然更优。

  对于基于模式识别的任务,使用常规的编程和算法方法可能很困难且非常耗时。而 LLM 擅长这些任务,而且甚至还能提供额外的输出,比如用于支撑其分析结果的附加说明,以 markdown 格式编写完整的分析报告。

  最终,决定是不是使用 LLM,取决于当前任务的性质以及 LLM 的模式识别能力与传统编程技术提供的精确性和针对性之间的权衡。

  本章节最后,我们回到用于生成数据集分析的 prompt,分解一下其中使用的关键性提示工程技术:

  :将复杂任务分解为简单步骤LLM 擅于执行简单任务,并不很擅长复杂任务。因此,对这种的复杂任务,一种很好的做法是将其分解成简单的逐步指示,以便 LLM 遵从。这里的思路是为 LLM 提供你希望采取的步骤。

  使用大写可以将这些变量名与指令主体区分开。然后,能够最终靠加方括号的形式 [变量名] 索引这些中间输出。

  :设置 LLM 的响应的格式这里我们要求输出 markdown 报告格式,这能美化 LLM 的响应结果。在这里,中间输出的变量名再次派上用场,可以更方便地指定报告的结构。

  :将任务指令与数据集分离开能够正常的看到,我们从未在第一个 prompt 中向 LLM 提供数据集。相反,该 prompt 只给出了数据集分析的任务指令,最后再加上了以下内容:

  这样做有助于 LLM 清晰理解每一部分,降低遗漏信息的可能性;尤其是当任务更复杂时,例如例子中这个指令较长的任务。你可能经历过 LLM「意外遗忘」长 prompt 中某个特定指令的情况,举个例子,如果你让 LLM 给出 100 词的响应,但其反馈的结果却长得多。而如果让 LLM 先接收指令,然后再接收指令处理的数据集,就能让 LLM 先消化其应当做的事情,之后再基于后面提供的数据集来执行它。

  请注意,这种指令与数据集分离的操作仅适用于有对话记忆的聊天式 LLM,不适用于没有对话记忆的任务完成式 LLM。


水利技术相关文章