上个月,我有幸参加了由新加坡科技部门主办的首届GPT-4提示工程比赛,共有超过400位杰出选手参与其中,我取得了冠军。
在编写这篇文章时,我有意避免了那些司空见惯的工程技巧,因为它们已经被广泛讨论并得到验证。我更愿意与大家分享我从实验中获得的新发现,以及我对它们的独特理解与应用。希望你在阅读中能获得乐趣!
这篇文章包括了下面的话题,*表示初学者容易掌握的技能,而**表示高级技能:
* 借助 CO-STAR 框架构建高效的提示
* 利用分隔符来分节构建提示
** 设计含有 LLM 保护机制的系统级提示
** 仅依靠大语言模型分析数据集,无需插件或代码 — 实际案例分析 Kaggle 的真实数据集
当你使用大语言模式的时候,高效的提示构建是非常重要的。CO-STAR框架是新加坡科技局的数据科学和人工智能团队创建的,是一种实用的构建技巧的工具。
(C)上下文:通过向大语言模型(LLM)提供详尽的背景信息,有助于其准确地理解特定情景,并保证所给出的反馈是相关的。
(O) 目标:弄清楚你需要大语言模型去做什么工作,清楚地定义任务的目的可以让这个大语言模型更加响应来达到这个特定的目标。
(S)风格:确定你想要什么样的写作风格,你可以用一位知名的人或者一位业内的专家风格来写,这样就可以引导大语言模型根据您的需要作出相应的选择。
(T) 语气:为回答设置合适的语调,以保证对大语言模型的响应符合期望的情绪或情感环境。适当的语调包括正式,幽默,同情等等。
(A)受众:为具体读者量身定做的大语言模型,不管是专业人士,初学者,还是孩子,都可以保证这些内容适合于具体的环境,并且易于理解。
(R) 响应:决定输出的格式,以保证这个大语言模型能够满足您的特定需要,使后续的工作更加容易。常用的格式有列表,数据的 JSON格式,专业的报告等等。JSON是大多数需要编程以处理大型语言模型的输出的应用程序。
下面是一个实际的例子,说明了为什么CO-STAR结构会有帮助。假如你是一名社会媒体管理者,你必须在Facebook上撰写一篇宣传公司新产品的文章。如果没有使用CO-STAR,以下是一个快速提示:
这是 GPT-4 的回答:
这样的产出介绍文案虽然是介绍充分的,但是似乎太笼统了,缺少了所需的具体内容和有针对性的吸引力,并没有真正打动企业的目标观众。
以下是一个使用CO-STAR模板的例子,它会提醒我们,当你设计提示的时候,要把任务中的其他方面都考虑进去,尤其是风格,语调,以及用户:
GPT-4的回应由于采用了CO-STAR框架而更有针对性,更有效:
CO-STAR框架指导你用系统化的方法来提供重要的任务信息,保证你的回应能准确地满足你的需要和最佳化。
分隔符是一种特殊的符号,可用于区分线索中的各个部分,将其视为独立的语义单元。这一点非常重要,因为你的提示会一次性传递到大语言模型,就像一串长长的Token。你可以为这些Token提供结构,以便对其进行不同的处理。
分隔符可以是任何不常见组合的特殊字符序列,如:
###
===
>>>
不管选取的是什么类型的字符,它都是独一无二的,这样的话,模型就可以把它作为一个分隔符来识别。
这里是一个分隔符使用的示例:
请在<<<CONVERSATIONS>>>中对每段对话的情绪进行分类,标为“正面”或“负面”。只提供情绪分类的结果,无需说明。
在指令中使用的名词与 XML 标签的名词一致,如 conversations、classes 和 examples,因此使用的 XML 标签分别是<conversations>、<classes>、<example-conversations> 和 <example-classes>。这样可以保证该模型对说明和所用标记间的联系有一个清楚的了解。
本节仅适用于具备系统提示功能的大语言模型(LLM),与文章中适用于所有大语言模型的其他部分有所不同。最常见的系统提示模型就是ChatGPT,因此我们将以ChatGPT作为一个示例。
让我们澄清一下一些术语:在讨论 ChatGPT 时,这三个术语“系统提示”、“系统消息”和“自定义指令”几乎可以互换使用。很多人,包括我在内,对这个词的使用感到困惑,所以 OpenAI发布了一个特别的帖子来解释这个术语。下面是一个简短的概述:
虽然这三个词所表述的观念是一样的,但是我们并不需要因为它们的不同而感到困惑。在这里,我们将统一地说成“系统提示”。
系统提示是你向大语言模型提供的关于其应如何响应的额外指示。这会被看作是一个附加的提示,因为它已经超过了你通常使用的大语言模型的用户提示。
在对话中,每当你提供新提示时,系统提示都会起到一种过滤作用,并在你发出新提示时,大语言模型会自动应用这些筛选条件。这意味着,当大语言模型在对话中作出响应时,这些系统提示将被纳入其中。
系统提示通常包括以下几个方面:
-任务定义:确保大语言模型(LLM)清楚自己在整个对话中的任务;
-输出格式:指导LLM如何格式化其回答;
-操作边界:使LLM明确知道哪些行为是不应该进行的。这两个边界是LLM管理的新领域,其目的在于确定LLM的操作范围。
比如,系统提示如下:
每一部分对应的内容如下图所示:
系统提示已经概括了任务的总体要求。在上述示例中,任务被定义为仅使用特定文本进行问题解答,同时指导 LLM 按照{“问题”:”答案”}的格式进行回答。
这种情况下,每个用户提示就是您想用该文本回答的具体问题。例如,用户提示可能是”这篇文本主要讲了什么?”,LLM 的回答将是{“这篇文本主要讲了什么?”:”文本主要讲述了……”}。
但我们可以将这种任务进一步推广。通常,与只询问一个文本相比,你可能会有多个文本需要询问。这时,我们可以将系统提示的首句从:
改为:
如此,每个用户提示将包括要问答的文本和问题,例如:
此处,我们使用 XML 标签来分隔信息,以便以结构化方式向 LLM 提供所需的两个信息。XML 标签中的名词,text和question,与系统提示中的名词相对应,以便 LLM 理解这些标签是如何与指令相关联的。
在先前的讨论中,我们根据系统提示制定了规则,一旦确定规则,便会在对话过程中保持不变。但是,如果你希望在对话的不同阶段采用不同的规定,那么我们应该采取哪些措施呢?
目前,如果你您想要直接使用ChatGPT用户接口,还没有直接的方法可以实现这一点。然而,如果您通过编程方式与ChatGPT进行交互,情况就大不相同了!随着对开发有效LLM规则的关注不断增加,一些允许通过编程方式设定更为详细和动态规则的开源软件包也应运而生。
其中一个特别推荐的是由NVIDIA团队开发的NeMo Guardrails。这个工具允许配置用户与LLM之间的预期对话流程,并通过在对话过程中设置不同的对话规则,实现动态调节的目的。这绝对是探讨对话动态管理的一种优秀方法。
你可能听说过 OpenAI 在 ChatGPT 的 GPT-4 中为付费用户提供的高级数据分析插件。这个插件允许用户将数据集上传到 ChatGPT,并在数据集上执行编码,以实现精准的数据分析。但是,你知道吗?并不总是需要依赖这类插件来有效地使用大语言模型 (LLM) 分析数据集。现在,让我们先探讨一下仅利用 LLM 进行数据分析的优势与限制。
如你所知,LLMs在执行精确的数学计算方面存在限制,因此它们不适合需要精确量化分析的任务,比如描述性统计(如均值或方差)、相关性分析(获取列间的精确相关系数)、统计分析(如假设检验)以及机器学习任务。为了解决这些限制,OpenAI推出了高级数据分析插件,允许用户通过编程语言在数据集上运行代码。
那么,为什么还有人想仅用LLMs来分析数据集而不用这些插件呢?
LLM 擅长的数据集分析类型:LLMs在识别模式和趋势方面表现出色,得益于它们在庞大且多样化的数据上接受的广泛训练,能够发现复杂的模式。这使它们非常适合执行基于模式查找的任务,如异常检测、聚类、跨列关系、文本分析(适用于文本列)以及趋势分析(针对有时间维度的数据集)。对于这些任务,单独使用LLMs可能比使用编程代码在更短的时间内产生更好的结果!接下来,我们将通过一个例子来详细说明这一点。
我们将使用一个流行的实际Kaggle数据集,该数据集专为客户个性分析而设计,帮助公司更好地了解客户并对客户基础进行细分。
为了验证LLM分析的便利性,我们将这个数据集缩减至50行,并仅保留最相关的几列。缩减后的数据集如下所示,每一行代表一位客户,各列展示了客户的相关信息:
假设你是公司营销团队的一员,你的任务是利用这份客户信息数据集来指导营销活动。这是一个分两步的任务:首先,利用数据集生成有意义的客户细分;其次,针对每个细分提出最佳的市场营销策略。这个实际的商业问题中,LLM的模式识别能力在第一步中将大显身手。
我们将按以下方式设计任务提示,采用四种提示工程技术:
将复杂任务分解成简单步骤;
引用每个步骤的中间输出;
格式化 LLM 的回答;
将指令与数据集分离。
下面是 GPT-4 的回复,我们将继续将数据集以 CSV 字符串的形式传递给它。
随后,GPT-4按照我们要求的标记符报告格式回复了分析结果:
为了简洁,我们选择了两个由大语言模型生成的客户群体进行验证,分别是“年轻家庭”和“挑剔的爱好者”。
年轻家庭群体的描述是:出生于1980年后,已婚或同居,收入中等偏低,育有孩子,消费倾向于小额。这一群体包括数据行3、4、7、10、16和20。深入查看这些数据行的详细信息后,我们得到了以下结果:
这些数据完美对应大语言模型确定的用户描述,甚至能识别包含空值的数据行,无需我们预处理!
挑剔的爱好者群体的描述是:年龄跨度广泛,不限婚姻状况,高收入,孩子情况不一,消费水平高。这一群体包括数据行2、5、18、29、34和36。深入查看这些数据行的详细信息后,我们得到了以下结果:
这些数据再次精准匹配了大语言模型确定的用户描述!本例彰显了大型语言模型在识别模式、解读和简化多维数据集以提炼有意义洞见方面的强大能力,确保其分析结果扎根于真实数据情况。
我尝试了同一任务,并让ChatGPT通过编程方式进行分析,启用了其高级数据分析插件。该插件应用K-均值等聚类算法直接对数据集进行处理,以便划分不同的客户群体,并据此制定营销策略。然而,尽管数据集仅含50行,多次尝试均出现错误信息且未产生任何结果。
目前的情况表明,虽然高级数据分析插件能够轻松完成一些简单任务,例如统计描述或生成图表,但在执行需要较大计算量的高级任务时,有时可能因为计算限制或其他原因而发生错误,导致无法输出结果。
答案取决于分析任务的具体性质。
对于需要精确的数学运算或复杂的规则处理的任务,传统的编程方法仍然更为适用。
然而,对于依赖模式识别的任务,传统的编程和算法处理可能更为困难且耗时。大语言模型在这些任务中表现优异,能够提供包括附加分析在内的额外输出,并生成Markdown 格式的完整分析报告。
在本节结束前,让我们重新审视用于生成此数据分析的提示,并详细解析关键的提示工程技巧:
技巧 1:将复杂任务简化成步骤
大型语言模型(LLM)擅长处理简单任务,但对复杂任务表现不佳。因此,将复杂任务分解成简单步骤至关重要。明确告知LLM每个步骤是什么。例如:
数据聚类(CLUSTERS):利用数据集的特征将数据行聚类,确保同一聚类中的客户相似,而不同聚类的客户明显不同。每个数据只能属于一个聚类。
聚类描述(CLUSTER_INFORMATION):描述聚类的特点。
聚类命名(CLUSTER_NAME):根据聚类描述为客户群体起一个简洁名字。
营销策略(MARKETING_IDEAS):为客户群体制定营销策略。
策略解释(RATIONALE):解释为什么这些营销策略对客户群体有效。这种分步指导可以提高LLM输出的准确性,而不是直接要求LLM“对客户进行分组并提出营销策略”。
这样的分步指导,比起直接要求 LLM“对客户进行分组并提出营销策略”的方式,能显著提高其输出的准确性。
技巧 2:标记并引用中间输出
在提供步骤时,我们使用大写字母标记每个步骤的输出,例如数据聚类(CLUSTERS)、聚类描述(CLUSTER_INFORMATION)、聚类命名(CLUSTER_NAME)、营销策略(MARKETING_IDEAS)和策略解释(RATIONALE)。这样做是为了区分指令中的变量名和其他文本,并方便后续引用这些中间输出。
技巧 3:优化响应格式
我们请求一个 Markdown 格式的报告,以提高响应的可读性和结构性。利用中间步骤的变量名,可以明确报告的结构。
此外,你还可以让ChatGPT将报告以可下载文件形式提供,便于你在编写最终报告时参考使用。
技巧 4:将任务指令与数据集分离
在我们的首个提示中,你会发现我们没有直接将数据集提供给大型语言模型(LLM)。相反,提示只给出了数据集分析的任务指令,并在底部添加了以下内容:
随后ChatGPT表示它已理解,并在下一个提示中,我们通过 CSV 字符串的形式将数据集传递给它:
但为什么需要将指令与数据集分开处理呢?
通过分离指令与数据集,大语言模型能够更清晰地理解任务要求,减少遗漏信息的可能性,尤其是在复杂且多指令的情境下。这种做法避免了一些常见问题,比如在长提示中忽略某些指令的情况。例如,你可能请求一个 100 字的回答,但模型却给出了更长的段落。通过先接收指令,理解任务需求,然后处理对应的数据集,模型可以更有效地执行所需操作,提高执行效率。需要注意的是,这种指令与数据集的分离只适用于具有对话记忆功能的聊天型大语言模型,而不适用于那些没有此功能的完成型模型。
首先,我要由衷感谢GovTech Singapore精心策划这场令人难忘的比赛。其次,我要向所有杰出的竞争对手致以最高的敬意,每个人都展现出独特的才能,让比赛既充满挑战又充满成果!我永远都不会忘记决赛时的激烈竞争,以及现场观众的欢呼声——这是我将永远珍视的记忆。