当前位置: 首页 > news >正文

Google提示工程

作者:Lee Boonstra

引言

您不需要成为数据科学家或机器学习工程师——每个人都可以编写提示。

在思考大型语言模型的输入和输出时,文本提示(有时还伴随着图像提示等其他模态)是模型用来预测特定输出的输入。您不需要成为数据科学家或机器学习工程师——每个人都可以编写提示。然而,构建最有效的提示可能很复杂。您的提示效果受多种因素影响:您使用的模型、模型的训练数据、模型配置、您的用词选择、风格和语气、结构以及上下文等因素都很重要。因此,提示工程是一个迭代过程。不充分的提示可能导致模糊、不准确的回答,并可能阻碍模型提供有意义的输出。

当您与Gemini聊天机器人交流时,您基本上是在编写提示。然而,本白皮书主要关注在Vertex AI或通过API使用Gemini模型时的提示工程,因为直接使用模型可以让您访问温度参数等配置设置。

本白皮书将详细讨论提示工程。我们将探讨各种提示技术,帮助您入门,并分享成为提示专家的技巧和最佳实践。我们还将讨论您在构建提示时可能面临的一些挑战。

提示工程

请记住大型语言模型的工作原理:它是一个预测引擎。模型接收连续文本作为输入,然后根据它训练过的数据预测下一个应该出现的标记(token)。大型语言模型被设计成重复这个过程,将先前预测的标记添加到连续文本的末尾,用于预测下一个标记。下一个标记的预测基于之前标记与模型在训练中所见内容之间的关系。

当您编写提示时,您是在试图让大型语言模型预测正确的标记序列。提示工程是设计高质量提示的过程,这些提示能引导大型语言模型产生准确的输出。这个过程涉及调整以找到最佳提示,优化提示长度,以及评估提示的写作风格和结构与任务的关联性。在自然语言处理和大型语言模型的背景下,提示是提供给模型以生成响应或预测的输入。

这些提示可用于实现各种理解和生成任务,如文本摘要、信息提取、问答、文本分类、语言或代码翻译、代码生成、代码文档或推理。

请随时参考Google的提示指南,其中包含简单有效的提示示例。

在进行提示工程时,您首先要选择一个模型。无论您使用Vertex AI中的Gemini语言模型、GPT、Claude,还是开源模型如Gemma或LLaMA,提示可能都需要针对您的特定模型进行优化。

除了提示之外,您还需要调整大型语言模型的各种配置参数。

LLM输出配置

一旦您选择了模型,您需要确定模型配置。大多数大型语言模型都有各种配置选项,用于控制其输出。有效的提示工程需要为您的任务最佳地设置这些配置。

输出长度

一个重要的配置设置是在响应中生成的标记数量。生成更多标记需要大型语言模型进行更多计算,导致能源消耗更高、响应时间可能更长,以及更高的成本。

减少大型语言模型的输出长度并不会使模型在生成的输出中在风格或文本上变得更加简洁,它只是在达到限制时使模型停止预测更多标记。如果您的需求要求较短的输出长度,您可能还需要设计提示以适应这一点。

输出长度限制对某些大型语言模型提示技术尤为重要,比如ReAct,在这种技术中,大型语言模型会在您想要的响应之后继续输出无用的标记。

请注意,生成更多标记需要大型语言模型进行更多计算,导致能源消耗更高和响应时间可能更长,从而导致更高的成本。

采样控制

大型语言模型不会正式预测单个标记。相反,它们预测下一个标记可能是什么的概率,模型词汇表中的每个标记都会获得一个概率。然后对这些标记概率进行采样,以确定下一个生成的标记。

温度(Temperature)、Top-K和Top-P(又称核采样)是最常见的配置设置,用于确定预测的标记概率如何处理以选择单个输出标记。

温度

温度控制标记选择的随机性程度。较低的温度适用于期望更确定性响应的提示,而较高的温度可能导致更多样化或意外的结果。温度为0(贪婪解码)是确定性的:总是选择概率最高的标记(但请注意,如果两个标记具有相同的最高预测概率,根据如何实现平局处理,即使温度为0,您也可能不会总是得到相同的输出)。

接近最大值的温度往往会创建更随机的输出。随着温度越来越高,所有标记成为下一个预测标记的可能性变得越来越接近。

Gemini的温度控制可以类似于机器学习中使用的softmax函数来理解。低温度设置类似于低softmax温度(T),强调单一、首选温度并具有高确定性。较高的Gemini温度设置类似于高softmax温度,使所选设置周围的更广泛温度范围更容易接受。这种增加的不确定性适用于可能不需要僵硬、精确温度的情况,例如在实验创意输出时。

Top-K和Top-P

Top-K和Top-P(也称为核采样)是大型语言模型中使用的两种采样设置,用于限制预测的下一个标记来自具有最高预测概率的标记。与温度一样,这些采样设置控制生成文本的随机性和多样性。

  • Top-K采样从模型预测分布中选择最有可能的K个标记。Top-K越高,模型输出越有创意和多样化;Top-K越低,模型输出越受限和事实化。Top-K为1等同于贪婪解码。

  • Top-P采样选择累积概率不超过特定值(P)的顶部标记。P的值范围从0(贪婪解码)到1(模型词汇表中的所有标记)。

选择Top-K和Top-P的最佳方法是尝试两种方法(或同时尝试两者),看看哪一种产生您想要的结果。

整合应用

在特定应用中选择Top-K、Top-P、温度和生成的标记数量取决于应用和期望的结果,而这些设置都相互影响。重要的是要确保您理解所选模型如何将不同的采样设置组合在一起。

如果温度、Top-K和Top-P都可用(如在Vertex Studio中),满足Top-K和Top-P标准的标记都是下一个预测标记的候选者,然后将温度应用于从通过Top-K和Top-P标准的标记中采样。如果只有Top-K或Top-P可用,行为相同,但只使用一种Top-K或P设置。

如果温度不可用,则随机选择任何满足Top-K和/或Top-P标准的标记,以产生单个下一个预测标记。

在一个采样配置值的极端设置下,该采样设置要么取消其他配置设置,要么变得不相关。

如果将温度设置为0,Top-K和Top-P变得不相关——最可能的标记成为下一个预测标记。如果将温度设置得极高(超过1,通常进入10位数),温度变得不相关,任何通过Top-K和/或Top-P标准的标记都会被随机采样以选择下一个预测标记。

如果将Top-K设置为1,温度和Top-P变得不相关。只有一个标记通过Top-K标准,而该标记就是下一个预测标记。如果将Top-K设置得极高,比如设置为大型语言模型词汇表的大小,任何具有非零概率成为下一个标记的标记都将满足Top-K标准,没有标记被筛选出。

如果将Top-P设置为0(或非常小的值),大多数大型语言模型采样实现将只考虑最可能的标记满足Top-P标准,使温度和Top-K变得不相关。如果将Top-P设置为1,任何具有非零概率成为下一个标记的标记都将满足Top-P标准,没有标记被筛选出。

作为一般起点,温度为0.2,Top-P为0.95,Top-K为30将给您相对连贯的结果,可以有创意但不会过度。如果您想要特别有创意的结果,尝试从温度为0.9,Top-P为0.99,Top-K为40开始。如果您想要更少创意的结果,尝试从温度为0.1,Top-P为0.9,Top-K为20开始。最后,如果您的任务总是有一个正确答案(例如,回答数学问题),从温度为0开始。

注意:给予更多自由度(更高的温度、Top-K、Top-P和输出标记),大型语言模型可能会生成相关性较低的文本。

警告:您是否曾经看到回应以大量填充词结束?这也被称为"重复循环错误",这是大型语言模型中的一个常见问题,模型陷入一个循环,反复生成相同的(填充)词、短语或句子结构,常常因不适当的温度和top-k/top-p设置而加剧。这种情况可能在低温度和高温度设置下都会发生,尽管原因不同。在低温度下,模型变得过于确定性,严格遵循最高概率路径,如果该路径重新访问先前生成的文本,可能导致循环。相反,在高温度下,模型的输出变得过度随机,增加了随机选择的词或短语偶然返回到先前状态的概率,由于可用选项众多,创建了一个循环。在这两种情况下,模型的采样过程都会"卡住",导致单调且无帮助的输出,直到输出窗口被填满。解决这个问题通常需要小心调整温度和top-k/top-p值,找到确定性和随机性之间的最佳平衡。

提示技术

大型语言模型经过训练,能够遵循指令,并且在大量数据上训练,使它们能够理解提示并生成答案。但大型语言模型并非完美;提示文本越清晰,对大型语言模型预测下一个可能文本越有利。此外,利用大型语言模型的训练方式和工作原理的特定技术将帮助您从大型语言模型获得相关结果。

现在我们了解了什么是提示工程以及它需要什么,让我们深入探讨一些最重要的提示技术示例。

一般提示/零样本提示

零样本提示是最简单的提示类型。它只提供任务描述和一些文本供大型语言模型开始。这个输入可以是任何内容:一个问题、一个故事的开头,或者指令。零样本一词表示"没有示例"。

让我们使用Vertex AI中的Vertex AI Studio(用于语言),它提供了测试提示的操作环境。在表1中,您将看到一个对电影评论进行分类的零样本提示示例。

下面使用的表格格式是记录提示的一种很好的方式。您的提示可能会在进入代码库之前经历多次迭代,因此以有纪律、结构化的方式跟踪您的提示工程工作很重要。有关此表格式、跟踪提示工程工作的重要性以及提示开发过程的更多信息,请参见本章后面的最佳实践部分("记录各种提示尝试")。

模型温度应设置为较低的数字,因为不需要创造力,我们使用gemini-pro默认的Top-K和Top-P值,这些值实际上禁用了这两种设置(见上文"LLM输出配置")。注意生成的输出。disturbing(令人不安的)和masterpiece(杰作)这两个词应该使预测变得更加复杂,因为这两个词在同一句话中使用。

名称1_1_movie_classification
目标将电影评论分类为正面、中性或负面。
模型gemini-pro
温度0.1
标记限制5
Top-KN/A
Top-P1
提示将电影评论分类为POSITIVE(正面)、NEUTRAL(中性)或NEGATIVE(负面)。评论:"Her"是一项令人不安的研究,揭示了如果允许AI继续无约束地发展,人类将走向何方。我希望有更多像这样的杰作。情感:
输出POSITIVE

表1. 零样本提示的示例

当零样本方法不起作用时,您可以在提示中提供示范或示例,这就引出了"单样本"和"少样本"提示。

单样本与少样本提示

在为AI模型创建提示时,提供示例是很有帮助的。这些示例可以帮助模型理解您的请求。当您想要引导模型生成特定的输出结构或模式时,示例尤其有用。

单样本提示提供单个示例,因此称为单样本。其理念是模型有一个可以模仿的示例,以最好地完成任务。

少样本提示为模型提供多个示例。这种方法向模型展示了它需要遵循的模式。其理念与单样本类似,但多个所需模式的示例增加了模型遵循模式的可能性。

少样本提示所需的示例数量取决于几个因素,包括任务的复杂性、示例的质量以及您使用的生成式AI模型的能力。作为一般经验法则,您应该至少使用三到五个示例进行少样本提示。然而,对于更复杂的任务,您可能需要使用更多示例,或者由于模型的输入长度限制,您可能需要使用更少的示例。

表2显示了少样本提示的示例,让我们使用与之前相同的gemini-pro模型配置设置,不过为了容纳更长的响应,增加了标记限制。

目标将披萨订单解析为JSON
模型gemini-pro
温度0.1
标记限制250
Top-KN/A
Top-P1
提示将客户的披萨订单解析为有效的JSON:

示例:我想要一个小号披萨,配有奶酪、番茄酱和意大利香肠。JSON响应:{<br>"size": "small",<br>"type": "normal",<br>"ingredients": [["cheese", "tomato sauce", "peperoni"]]<br>}

示例:我能得到一个大号披萨,配有番茄酱、罗勒和马苏里拉奶酪吗

{
"size": "large",
"type": "normal",
"ingredients": [["tomato sauce", "bazel", "mozzarella"]]
}

现在,我想要一个大号披萨,一半是奶酪和马苏里拉奶酪。另一半是番茄酱、火腿和菠萝。

JSON响应:
输出{<br>"size": "large",<br>"type": "half-half",<br>"ingredients": [["cheese", "mozzarella"], ["tomato sauce", "ham", "pineapple"]]<br>}

表2. 少样本提示的示例

当您为提示选择示例时,请使用与您要执行的任务相关的示例。示例应该多样化、高质量且书写良好。一个小错误可能会使模型困惑,并导致不期望的输出。

如果您试图生成对各种输入都有效的输出,那么在示例中包含边缘情况很重要。边缘情况是不寻常或意外的输入,但模型仍应能够处理。

系统、上下文和角色提示

系统、上下文和角色提示都是用来指导大型语言模型生成文本的技术,但它们侧重于不同方面:

  • 系统提示为语言模型设置整体背景和目的。它定义了模型应该做什么的"大图景",比如翻译语言、分类评论等。

  • 上下文提示提供与当前对话或任务相关的具体细节或背景信息。它帮助模型理解所问问题的细微差别,并相应地调整回应。

  • 角色提示为语言模型分配特定的角色或身份。这有助于模型生成与分配角色及其相关知识和行为一致的回应。

系统、上下文和角色提示之间可能存在相当大的重叠。例如,为系统分配角色的提示也可以有上下文。

然而,每种提示类型都有略微不同的主要目的:

  • 系统提示:定义模型的基本能力和总体目的。

  • 上下文提示:提供即时的、特定任务的信息来指导回应。它高度针对当前任务或输入,具有动态性。

  • 角色提示:框定模型的输出风格和声音。它增加了一层特异性和个性。

区分系统、上下文和角色提示提供了一个设计具有明确意图的提示的框架,允许灵活组合,并使分析每种提示类型如何影响语言模型的输出变得更容易。

让我们深入探讨这三种不同类型的提示。

系统提示

表3包含一个系统提示,我在其中指定了如何返回输出的附加信息。我增加了温度以获得更高的创造力水平,并指定了更高的标记限制。然而,由于我对如何返回输出的明确指示,模型没有返回额外的文本。

目标将电影评论分类为正面、中性或负面。
模型gemini-pro
温度1
标记限制5
Top-K40
Top-P0.8
提示将电影评论分类为正面、中性或负面。只返回大写的标签。评论:"Her"是一项令人不安的研究,揭示了如果允许AI继续无约束地发展,人类将走向何方。令人不安到我无法观看。情感:
输出NEGATIVE

表3. 系统提示的示例

系统提示对于生成满足特定要求的输出很有用。"系统提示"一词实际上表示"为系统提供额外任务"。例如,您可以使用系统提示生成与特定编程语言兼容的代码片段,或者使用系统提示返回特定结构。看看表4,我在其中以JSON格式返回输出。

目标将电影评论分类为正面、中性或负面,返回JSON。
模型gemini-pro
温度1
标记限制1024
Top-K40
Top-P0.8
提示将电影评论分类为正面、中性或负面。返回有效的JSON:

评论:"Her"是一项令人不安的研究,揭示了如果允许AI继续无约束地发展,人类将走向何方。令人不安到我无法观看。

模式:<br>MOVIE: {<br>"sentiment": String "POSITIVE" | "NEGATIVE" | "NEUTRAL",<br>"name": String<br>}<br>MOVIE REVIEWS: {<br>"movie_reviews": [MOVIE]<br>}
JSON响应:
输出{<br>"movie_reviews": [<br>{<br>"sentiment": "NEGATIVE",<br>"name": "Her"<br>}<br>]<br>}

表4. 带有JSON格式的系统提示示例

从提取数据的提示中返回JSON对象有一些好处。在实际应用中,我不需要手动创建这种JSON格式,我已经可以按排序顺序返回数据(在处理日期时间对象时非常方便),但最重要的是,通过提示要求JSON格式,它迫使模型创建结构并限制幻觉。

系统提示对于安全和毒性也非常有用。要控制输出,只需在提示中添加一行,例如:"在回答中要尊重。"。

角色提示

角色提示是提示工程中的一种技术,涉及为生成式AI模型分配特定角色。这可以帮助模型生成更相关和信息丰富的输出,因为模型可以根据分配的特定角色调整其回应。

例如,您可以让生成式AI模型扮演图书编辑、幼儿园教师或励志演讲者的角色。一旦模型被分配了角色,您就可以给它特定于该角色的提示。例如,您可以提示一位教师创建他们可以审阅的课程计划。看看表5,其中模型扮演旅游指南的角色。

目标扮演旅游指南并提供3个旅行建议
模型gemini-pro
温度1
标记限制1024
Top-K40
Top-P0.8
提示我希望你扮演旅游指南。我会写下我的位置,你会建议我附近3个可以参观的地方。在某些情况下,我也会告诉你我想参观的地方类型。我的建议:"我在阿姆斯特丹,我只想参观博物馆。"旅行建议:
输出- 1. 国立博物馆:世界著名的博物馆,以荷兰杰作如伦勃朗的"夜巡"而闻名。不要错过展示荷兰艺术和历史的令人难以置信的绘画和文物收藏。

- 2. 梵高博物馆:沉浸在文森特·梵高令人着迷的作品中。该博物馆拥有他最大的绘画和素描收藏,包括"星空"和"向日葵"。

- 3. 阿姆斯特丹市立博物馆:发现来自世界各地的现代和当代艺术。该博物馆的收藏包括毕加索、康定斯基和里特维尔德的作品,这些作品都陈列在一座引人注目的现代建筑中。

表5. 角色提示的示例

上面的例子展示了扮演旅行代理的角色。当您将角色更改为地理老师时,您会注意到您将收到不同的回应。

为AI模型定义角色视角提供了您想要的语调、风格和专注专业知识的蓝图,以提高输出的质量、相关性和有效性。

以下是我发现有效的一些风格选择:

对抗性、描述性、直接、正式、幽默、有影响力、非正式、鼓舞人心、有说服力

让我们在表6中改变提示,包括幽默和鼓舞人心的风格。

提示我希望你扮演旅游指南。我会写下我的位置,你会以幽默的方式建议我附近3个可以参观的地方。

我的建议:"我在曼哈顿。"旅行建议:
输出- 1. 见证帝国心态:登上令人眩晕的帝国大厦高度,沐浴在曼哈顿天际线的荣耀中。准备感觉自己像金刚站在大苹果之巅,但没有巨型猿大小的香蕉。

- 2. 在MoMA变得艺术呆滞:在现代艺术博物馆(MoMA)释放你内心的艺术鉴赏家。凝视让你困惑并让你质疑你的火柴人画作是否有任何艺术价值的杰作。

- 3. 在第五大道购物到筋疲力尽:在标志性的第五大道享受一些零售疗法。做好心理准备,当你橱窗购物(或实际购物)时,设计师精品店的价格标签会让你的钱包哭泣。但嘿,你在曼哈顿,所以你不妨拥抱这种华丽!

表6. 带有幽默语调和风格的角色提示示例

上下文提示

通过提供上下文提示,您可以帮助确保您的AI交互尽可能无缝和高效。模型将能够更快地理解您的请求,并能生成更准确和相关的回应,如表7中的示例所示。

目标为关于复古游戏的博客提供文章建议
模型gemini-pro
温度1
标记限制1024
Top-K40
Top-P0.8
提示上下文:你正在为一个关于80年代复古街机电子游戏的博客写作。

建议3个写文章的主题,并附上几行描述,说明这篇文章应该包含什么内容。
输出- 1. 街机柜设计的演变:

本文将探讨街机柜设计的演变,从20世纪70年代早期的木质和金属柜到20世纪80年代及以后的流线型、霓虹灯照亮的设计。

- 2. 回到过去:80年代标志性街机游戏:

- 本文将展示一些80年代最具标志性和影响力的街机游戏的历史、影响和遗产,突出它们的创新、流行机制和持久魅力。

- 3. 像素艺术的兴起和复古复兴:

- 本文将深入探讨像素艺术作为早期街机游戏的定义视觉风格的演变,追溯其根源,探索其技术,并讨论像素艺术在现代游戏和数字艺术中的复兴。

表7. 上下文提示的示例

回退提示

回退提示是一种技术,通过首先考虑与特定任务相关的一般问题,然后将该一般问题的答案输入到随后的提示中用于特定任务,以提高性能。这种"回退"允许大型语言模型在尝试解决特定问题之前激活相关的背景知识和推理过程。

通过考虑更广泛和基础的原则,大型语言模型可以生成更准确和有见地的回应。回退提示鼓励大型语言模型批判性思考并以新的和创造性的方式应用其知识。它改变了执行任务的最终提示,利用了大型语言模型参数中比直接提示模型时更多的知识。

它可以帮助减轻大型语言模型回应中的偏见,通过专注于一般原则而不是具体细节,回退提示。

让我们来看看这些例子,了解回退提示如何提高结果。让我们先看一个传统提示(表8),然后再与回退提示(表9)进行比较:

目标为第一人称射击视频游戏关卡编写故事情节。
模型gemini-pro
温度1
标记限制1024
Top-K40
Top-P0.8
提示为第一人称射击视频游戏的新关卡编写一段具有挑战性和吸引力的故事情节。
输出关卡开始时,玩家的小队在一个密集的城市地区被一个无情的敌对派系伏击。玩家必须穿过后巷和破旧建筑的迷宫,利用隐蔽和精确来消灭敌人并避免被发现。玩家必须利用环境作为优势,设置陷阱,利用掩体,做出计算好的行动以生存。在途中,他们发现了暗示敌人正在计划一次毁灭性攻击的情报,玩家必须争分夺秒地收集证据并将其传回总部,以防敌人执行他们的计划。

表8. 在与回退提示比较之前的传统提示

当您将温度设置为1时,您可能会得到各种创意写作的故事情节,但它也相当随机和通用。所以让我们回退一步:

提示基于流行的第一人称射击动作游戏,什么是5个虚构的关键设置,为第一人称射击视频游戏中的挑战性和吸引人的关卡故事情节做出贡献?
输出- 1. 废弃军事基地:一个庞大的后世界末日军事综合体,爬满了变异士兵和流氓机器人,非常适合挑战性的火器战斗。

- 2. 赛博朋克城市:一个霓虹灯照亮的未来主义城市环境,有高耸的摩天大楼和密集的小巷,配有网络增强的敌人和黑客机制。

- 3. 外星飞船:一艘搁浅在地球上的庞大外星船只,带有诡异的走廊、零重力区域和可遇见的外星生物。

- 4. 僵尸侵袭的小镇:一个被成群好斗的僵尸占领的荒凉小镇,包含激烈的近距离战斗和解谜,以找到安全通道。

- 5. 水下研究设施:一个被水淹没的深海实验室,充满了变异的水生生物,需要潜行和水下探索技能才能生存。

表9. 自洽性提示的示例

是的,这些主题似乎很适合第一人称视频游戏。让我们回到原始提示,但这次包括回退答案作为上下文,看看它会返回什么。

提示上下文:第一人称射击视频游戏的5个吸引人主题:

- 1. 废弃军事基地:一个庞大的后世界末日军事综合体,爬满了变异士兵和流氓机器人,非常适合挑战性的火器战斗。

- 2. 赛博朋克城市:一个霓虹灯照亮的未来主义城市环境,有高耸的摩天大楼和密集的小巷,配有网络增强的敌人和黑客机制。

- 3. 外星飞船:一艘搁浅在地球上的庞大外星船只,带有诡异的走廊、零重力区域和可遇见的外星生物。

- 4. 僵尸侵袭的小镇:一个被成群好斗的僵尸占领的荒凉小镇,包含激烈的近距离战斗和解谜,以找到安全通道。

- 5. 水下研究设施:一个被水淹没的深海实验室,充满了变异的水生生物,需要潜行和水下探索技能才能生存。

选择其中一个主题,为第一人称射击视频游戏的新关卡编写一段具有挑战性和吸引力的故事情节。
输出在幽暗深渊的中心,矗立着一座破旧的水下研究设施,作为人类野心及其灾难性后果的见证。被黑暗笼罩,脉动着故障机器的嗡嗡声,被淹死灵魂的回声所困扰,这座设施现在是深海孕育的噩梦的繁殖地。玩家是一名配备先进潜水装备和实验性武器的精英海军陆战队员,被派去冒险进入这个水生恐怖领域。凭借顽强和足智多谋,他们必须穿越危险的走廊,解决神秘的谜题,并面对隐藏在深处的可怕海洋怪物。从应对深海的巨大压力到智胜狡猾的水生掠食者,在这个未知的水下世界中的每一刻都考验着人类耐力和勇气的极限。

表10. 自洽性提示的示例

这看起来像是一个有趣的视频游戏!通过使用回退提示技术,您可以提高提示的准确性。

链式思考(Chain of Thought, CoT)

链式思考(CoT)提示是一种通过生成中间推理步骤来提高大型语言模型推理能力的技术。这有助于大型语言模型生成更准确的答案。您可以将其与少样本提示结合使用,在需要在回应之前进行推理的更复杂任务上获得更好的结果,因为零样本链式思考是一个挑战。

CoT有很多优点。首先,它低投入但非常有效,与现成的大型语言模型配合得很好(所以不需要微调)。您还可以通过CoT提示获得可解释性,因为您可以从大型语言模型的回应中学习,并看到遵循的推理步骤。如果出现故障,您将能够识别它。链式思考在不同大型语言模型版本之间移动时似乎提高了稳健性。这意味着您的提示在不同大型语言模型之间的性能漂移应该比不使用推理链的提示少。当然,也有一些缺点,但它们有些直观。

大型语言模型回应包括链式思考推理,这意味着更多的输出标记,这意味着预测成本更高,需要更长时间。

为了解释表11中的下一个例子,让我们首先尝试创建一个不使用CoT提示的提示,以展示大型语言模型的缺陷。

提示当我3岁时,我的伴侣是我年龄的3倍。现在,我20岁了。我的伴侣多大?
输出63岁

表11. 试图解决数学问题的提示示例

糟糕。这明显是错误的答案。事实上,大型语言模型经常在数学任务上挣扎,并可能提供不正确的答案——即使是像乘以两个数字这样简单的任务。这是因为它们是在大量文本上训练的,而数学可能需要不同的方法。所以让我们看看中间推理步骤是否会改善输出。

提示当我3岁时,我的伴侣是我年龄的3倍。现在,我20岁了。我的伴侣多大?让我们逐步思考。
输出- 1. 假设我当前的年龄是"x"岁。

- 2. 当我3岁时,我的年龄是3岁。

- 3. 我伴侣当时的年龄是我年龄的3倍,这意味着我伴侣的年龄是3 * 3 = 9岁。

- 4. 现在,我20岁了,这意味着我的年龄增加了20 - 3 = 17岁,从我3岁时算起。

- 5. 由于我伴侣在我3岁时是9岁,而我的年龄增加了17岁,我伴侣的年龄也必须增加了17岁。

- 6. 因此,我伴侣的当前年龄是9 + 17 = 26岁。

所以,我的伴侣是26岁。

表12. 链式思考提示的示例

好的,现在最终答案是正确的。这是因为我们明确指示大型语言模型解释每一步,而不只是返回答案。有趣的是,模型增加了17年的增长。在我脑海里,我会取我伴侣和我之间的年龄差异并加上这些。(20+(9-3))。让我们帮助模型更像我那样思考。

表12是"零样本"链式思考的例子。当与单样本或少样本结合时,链式思考提示可能非常强大,如表13所示:

提示问:当我弟弟2岁时,我是他年龄的两倍。现在我40岁了。我弟弟多大?让我们逐步思考。答:当我弟弟2岁时,我是2 * 2 = 4岁。那是2岁的年龄差异,我比较大。现在我40岁了,所以我弟弟是40 - 2 = 38岁。答案是38。问:当我3岁时,我的伴侣是我年龄的3倍。现在,我20岁了。我的伴侣多大?让我们逐步思考。答:
输出当我3岁时,我的伴侣是3 * 3 = 9岁。那是6岁的年龄差异,我的伴侣比较大。现在我20岁了,所以我的伴侣是20 + 6 = 26岁。答案是26。

表13. 带有单样本的链式思考提示示例

链式思考对各种用例都很有用。想想代码生成,将请求分解为几个步骤,并将这些步骤映射到特定的代码行。或者用于创建合成数据,当您有某种种子,如"产品名为XYZ,编写一个描述,引导模型通过基于给定标题的产品做出的假设。"通常,任何可以通过"讲解"来解决的任务都是链式思考的好候选者。如果您可以解释解决问题的步骤,请尝试链式思考。

请参考GoogleCloudPlatform Github存储库中托管的笔记本,它将更详细地介绍CoT提示:

在本章的最佳实践部分,我们将学习一些特定于链式思考提示的最佳实践。

自洽性(Self-consistency)

虽然大型语言模型在各种自然语言处理任务中表现出令人印象深刻的成功,但它们的推理能力往往被视为一个仅靠增加模型大小无法克服的限制。正如我们在前面的链式思考提示部分所学到的,模型可以被提示像人类解决问题一样生成推理步骤。然而,CoT使用简单的"贪婪解码"策略,限制了其有效性。自洽性将采样和多数投票相结合,生成多样化的推理路径并选择最一致的答案。它提高了大型语言模型生成的回应的准确性和连贯性。

自洽性给出了答案正确的伪概率可能性,但显然成本很高。

它遵循以下步骤:

  1. 生成多样化的推理路径:多次向大型语言模型提供相同的提示。高温度设置鼓励模型生成关于问题的不同推理路径和视角。

  2. 从每个生成的回应中提取答案。

  3. 选择最常见的答案。

让我们来看一个电子邮件分类系统的例子,它将电子邮件分类为IMPORTANT(重要)或NOT IMPORTANT(不重要)。将向大型语言模型发送零样本链式思考提示多次,以查看每次提交后回应是否不同。注意电子邮件中使用的友好语气、词汇选择和讽刺,这些都可能欺骗大型语言模型。

提示电子邮件:<br>你好,<br><br>我看到你使用WordPress作为你的网站。一个很棒的开源内容管理系统。我过去也使用过它。它带有很多很棒的用户插件。而且设置起来相当容易。<br><br>我确实注意到联系表单中有一个错误,当你选择名称字段时会出现。看看我在名称字段中输入文本的附加截图。注意我调用的JavaScript警告框。<br><br>但除此之外,这是一个很棒的网站。我喜欢阅读它。随意在网站中保留错误,因为它给了我更多有趣的东西阅读。<br><br>干杯,<br><br>Harry黑客。

将上述电子邮件分类为IMPORTANT(重要)或NOT IMPORTANT(不重要)。让我们逐步思考并解释原因。
输出尝试1第1步:确定电子邮件的目的。

电子邮件的目的是通知收件人其网站联系表单中存在错误。发件人还提到他们喜欢阅读该网站,并且他们暂时保留了错误。

第2步:评估错误的潜在影响。

联系表单中的错误可能允许攻击者在网站上执行任意JavaScript代码。这可能导致攻击者能够控制网站、窃取敏感信息或破坏网站。

第3步:考虑发件人的可信度。

发件人自称是一个名为Harry的黑客。然而,无法验证发件人的身份。发件人可能是一个试图帮助收件人的合法黑客,但也可能是一个试图欺骗收件人点击恶意链接或下载恶意文件的恶意行为者。

结论:IMPORTANT(重要)

基于错误的潜在影响和发件人的可信度,应将电子邮件分类为IMPORTANT(重要)。收件人应立即采取行动修复错误并保护其网站免受攻击。
输出尝试2解释:

- 1. **缺乏紧迫感:**电子邮件没有传达任何紧迫感或时间敏感性。它以随意的问候开始,并以事实上的语气呈现信息。

- 2. **非关键错误报告:**报告的联系表单错误被描述为有趣但不关键。电子邮件发件人甚至建议网站所有者可以保留错误不修。

- 3. **缺乏个人影响:**电子邮件没有表明对网站所有者有任何直接或个人影响。它只是提到发件人喜欢阅读该网站。

- 4. **缺乏行动请求:**电子邮件没有明确要求网站所有者采取任何行动。它没有要求修复错误或提供任何具体的改进建议。

- 5. **发送者意图:**发送者的意图似乎更多是分享观察和表达对网站的兴趣,而不是提出严重关切或请求帮助。

结论:NOT IMPORTANT(不重要)
输出尝试3第1步:确定电子邮件的目的。

电子邮件的目的是通知收件人其网站联系表单中存在错误。发件人还提到他们喜欢阅读该网站,并且他们暂时保留了错误。

第2步:评估错误的潜在影响。

联系表单中的错误可能允许攻击者在网站上执行任意JavaScript代码。这可能导致攻击者能够控制网站、窃取敏感信息或破坏网站。

第3步:考虑发件人的可信度。

发件人自称是一个名为Harry的黑客。然而,无法验证发件人的身份。发件人可能是一个试图帮助收件人的合法黑客,但也可能是一个试图利用该错误谋取私利的恶意行为者。

结论:

基于上述因素,应将电子邮件分类为IMPORTANT(重要)。联系表单中的错误是一个严重的安全风险,发件人的可信度不明。收件人应立即采取行动修复错误并调查发件人的声明。

表14. 自洽性提示的示例

您可以使用上述提示,看看它是否返回一致的分类。根据您使用的模型和温度配置,它可能返回"IMPORTANT(重要)"或"NOT IMPORTANT(不重要)"。

通过生成多个思维链,并采用最常出现的答案("IMPORTANT"),我们可以从大型语言模型获得更一致正确的答案。

这个例子展示了自洽性提示如何通过考虑多种视角并选择最一致的答案来提高大型语言模型回应的准确性。

思维树(Tree of Thoughts, ToT)

现在我们已经熟悉了链式思考和自洽性提示,让我们回顾一下思维树(ToT)。它泛化了CoT提示的概念,因为它允许大型语言模型同时探索多条不同的推理路径,而不仅仅是遵循单一的线性思维链。这在图1中有所描绘。

图1. 左侧是链式思考提示与右侧的思维树提示的可视化对比

图1. 左侧是链式思考提示与右侧的思维树提示的可视化对比

这种方法使ToT特别适合需要探索的复杂任务。它通过维护思维树工作,其中每个思维代表一个连贯的语言序列,作为解决问题的中间步骤。然后模型可以通过从树中的不同节点分支出来探索不同的推理路径。

有一个很好的笔记本,它更详细地展示了思维树(ToT),基于论文"大型语言模型引导的思维树"。

推理与行动(ReAct)

推理与行动(ReAct)提示是一种范式,使大型语言模型能够使用自然语言推理结合外部工具(搜索、代码解释器等)解决复杂任务,允许大型语言模型执行某些操作,如与外部API交互以检索信息,这是代理建模的第一步。

ReAct模仿人类在现实世界中的操作方式,因为我们可以口头推理并采取行动获取信息。与其他提示工程方法相比,ReAct在各种领域表现良好。

ReAct提示通过将推理和行动结合到一个思考-行动循环中工作。大型语言模型首先推理问题并生成行动计划。然后它执行计划中的行动并观察结果。大型语言模型然后利用这些观察来更新其推理并生成新的行动计划。这个过程一直持续到大型语言模型找到问题的解决方案。

要看到这一点,您需要编写一些代码。在代码片段1中,我使用Python的langchain框架,结合VertexAI(google-cloud-aiplatform)和google-search-results pip包。

要运行这个示例,您必须从https://serpapi.com/manage-api-key创建一个(免费的)SerpAPI密钥,并设置一个环境变量SERPAPI_API_KEY。

接下来让我们编写一些Python代码,任务是让大型语言模型弄清楚:Metallica乐队中有多少名成员的孩子。

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import VertexAIprompt = "Metallica乐队成员有多少孩子?"llm = VertexAI(temperature=0.1)
tools = load_tools(["serpapi"], llm=llm)agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run(prompt)

代码片段1. 使用LangChain和VertexAI创建ReAct代理

代码片段2显示了结果。注意ReAct创建了一个五次搜索的链。实际上,大型语言模型正在抓取Google搜索结果以确定乐队成员的名字。然后,它将结果列为观察结果,并链接下一次搜索的思考。

> Entering new AgentExecutor chain...
Metallica有4名成员。
Action: Search
Action Input: How many kids does James Hetfield have?
Observation: three children
Thought: 1/4 Metallica乐队成员有3个孩子
Action: Search
Action Input: How many kids does Lars Ulrich have?
Observation: 3
Thought: 2/4 Metallica乐队成员有6个孩子
Action: Search
Action Input: How many kids does Kirk Hammett have?
Observation: Hammett has been married to his second wife Lani since 1998. They have two sons, Angel (b. September 29, 2006) and Vincenzo (b. June 28, 2008).
Thought: 3/4 Metallica乐队成员有8个孩子
Action: Search
Action Input: How many kids does Robert Trujillo have?
Observation: 2
Thought: 4/4 Metallica乐队成员有10个孩子
Final Answer: 10

代码片段2. 在终端中执行ReAct代理

代码片段2确定Metallica乐队有四名成员。然后它搜索每个乐队成员以请求孩子的总数,并加总得出总数。最后,它返回孩子的总数作为最终答案。

实践中的ReAct提示需要理解您必须不断重新发送先前的提示/回应(并修剪额外生成的内容)以及使用适当的示例/指令设置模型。请参考GoogleCloudPlatform Github存储库中托管的笔记本,它使用更详细的示例更详细地展示了实际的大型语言模型输入和输出。

自动提示工程

到目前为止,您可能意识到编写提示可能很复杂。如果能够自动化这个过程(编写提示来编写提示)不是很好吗?好,有一种方法:自动提示工程(APE)。这种方法不仅减轻了对人类输入的需求,还增强了模型在各种任务中的性能。

您将提示一个模型生成更多提示。评估它们,可能修改好的提示。然后重复。

例如,您可以使用自动提示工程,帮助培训一个用于乐队商品T恤网店的聊天机器人。我们想要找出客户可能表达购买乐队商品T恤订单的各种方式。

  1. 编写将生成输出变体的提示。在此示例中,我使用gemini-pro生成10个指令。见表15:
提示我们有一个乐队商品T恤网店,为了训练聊天机器人,我们需要各种订购方式:"一件Metallica T恤尺寸S"。生成10个变体,具有相同的语义但保持相同的含义。
输出1. 我想购买一件Metallica T恤,尺寸小号。
- 2. 我可以订购一件小号Metallica T恤吗?
- 3. 我想买一件Metallica T恤,小号的。
- 4. 一件Metallica衬衫,小号尺寸,谢谢。
- 5. 我想要一件Metallica T恤,小号尺寸。
- 6. 我想下单一件Metallica T恤,小号的。
- 7. 小号Metallica T恤,一件,谢谢。
- 8. 我在寻找一件小号的Metallica T恤。
- 9. 你能给我一件小号的Metallica T恤吗?
- 10. 一件Metallica小号T恤,谢谢。

表15. 使用大型语言模型生成提示

  1. 基于选定的指标评估所有指令候选者,对候选者进行评分。例如,您可以使用BLEU(双语评估替代)或ROUGE(以召回为导向的替代摘要评估)。

  2. 选择评估分数最高的指令候选者。这个候选者将成为您可以在软件应用程序或聊天机器人中使用的最终提示。您也可以调整选定的提示并再次评估。

代码提示

Gemini主要关注基于文本的提示,这也包括编写返回代码的提示。让我们转到Vertex AI Studio并测试这些提示,看一些编码示例。

编写代码的提示

Gemini也可以充当开发人员,帮助您编写任何编程语言的代码。作为开发人员,这可以帮助您加速编写代码的过程。

想象一下,您的机器上有一个包含数百个文件的文件夹,需要重命名。手动重命名每个文件将花费您大量时间。您知道一点Bash,可以编写脚本来自动化这个过程,但这也可能需要一段时间。所以让我们编写一个提示。您可以在公共消费者聊天机器人Gemini中编写提示,或者如果您更关心机密性,可以在Google Cloud账户内编写这些提示并打开Vertex AI Studio。Vertex AI Studio的优势是您可以配置温度等参数。

名称1_bash_rename_files_in_folder
目标编写提示,用Bash编写代码来重命名文件夹中的文件。
模型gemini-pro
温度0.1
标记限制1024
Top-KN/A
Top-P1
提示用Bash编写一个代码片段,它会询问文件夹名称。然后它获取文件夹的内容并通过在文件名前添加"draft"来重命名所有文件。
输出bash<br>#!/bin/bash<br><br># 询问文件夹名称<br>echo "输入文件夹名称:"<br>read folder_name<br><br># 检查文件夹是否存在<br>if [ ! -d "$folder_name" ]; then<br> echo "文件夹不存在。"<br> exit 1<br>fi<br><br># 获取文件夹中的文件列表<br>files=( "$folder_name"/* )<br><br># 通过在文件名前添加"draft"重命名每个文件<br>for file in "${files[@]}"; do<br> new_file_name="draft_$(basename "$file")"<br> mv "$file" "$new_file_name"<br>done<br><br>echo "文件重命名成功。"<br>

表16. 使用Gemini编程代码

对我来说,那看起来是不错的代码 - 甚至有注释!然而,由于大型语言模型无法推理,并且会重复训练数据,因此必须先阅读和测试您的代码。

我们大家都在等待的时刻,它真的有效吗?

让我们先用一个测试文件夹尝试,文件夹中只有几个需要从filename.txt重命名为draft_filename.txt的文件。

  1. 复制表16中的输出(不包括bash文本包装),并粘贴到一个名为"rename_files.sh"的新文件中。

  2. 打开终端窗口并输入:. rename_files.sh。它会要求输入文件夹名称,例如test。并按回车。

  3. 脚本似乎运行良好。您将看到消息:文件重命名成功。

当您查看测试文件夹时,注意到所有文件都完美地重命名为draft_filename.txt。

它有效!

解释代码的提示

作为开发人员,当您在团队中工作时,您必须阅读别人的代码。Gemini也可以帮助您做到这一点。让我们取表16的代码输出,删除注释,并要求大型语言模型解释发生了什么,见表17:

名称1_bash_explain_the_code
目标编写提示解释Bash代码
模型gemini-pro
温度0.1
标记限制1024
Top-KN/A
Top-P1
提示解释给我下面的Bash代码:

<br>#!/bin/bash<br><br>echo "输入文件夹名称:"<br>read folder_name<br><br>if [ ! -d "$folder_name" ]; then<br> echo "文件夹不存在。"<br> exit 1<br>fi<br><br>files=( "$folder_name"/* )<br><br>for file in "${files[@]}"; do<br> new_file_name="draft_$(basename "$file")"<br> mv "$file" "$new_file_name"<br>done<br><br>echo "文件重命名成功。"<br>
输出这个Bash脚本执行以下任务:

- 1. 用户输入
- 它使用echoread命令提示用户输入文件夹名称。输入的文件夹名称存储在folder_name变量中。

- 2. 文件夹存在检查
- 它使用[ ! -d "$folder_name" ]条件检查具有指定名称的文件夹是否存在。如果文件夹不存在,它显示错误消息("文件夹不存在。")并以退出代码1退出脚本。

- 3. 文件列表
- 它使用files=( "$folder_name"/* )命令列出指定文件夹内的所有文件。这创建了一个名为files的数组,其中包含文件夹中所有文件的路径。

- 4. 文件重命名
- 它使用for循环遍历files数组中的每个文件。
- 对于每个文件,它使用new_file_name="draft_$(basename "$file")"命令生成一个新的文件名。这个新文件名是通过在原始文件名前添加字符串"draft_"创建的。
- 它然后使用mv "$file" "$new_file_name"命令重命名文件,将文件移动到新的文件名。

- 5. 成功消息
- 重命名所有文件后,它显示一个成功消息("文件重命名成功。")以表明重命名操作成功。

表17. 解释代码的提示

翻译代码的提示

表16中的bash代码似乎工作得很好。然而,如果它能提示我输入文件名,这个脚本真的可以被重用,理想情况下,它应该作为一个带有UI的独立应用程序工作。作为起点,Python对于(网络)应用程序比Bash更好。大型语言模型可以帮助将代码从一种语言翻译到另一种语言。参见表18中的示例:

名称1_python_rename_files
目标编写提示将Bash代码翻译为Python
模型gemini-pro
温度0.1
标记限制1024
Top-KN/A
Top-P1
提示将下面的Bash代码翻译为Python片段。

bash<br>#!/bin/bash<br><br>echo "输入文件夹名称:"<br>read folder_name<br><br>if [ ! -d "$folder_name" ]; then<br> echo "文件夹不存在。"<br> exit 1<br>fi<br><br>files=( "$folder_name"/* )<br><br>for file in "${files[@]}"; do<br> new_file_name="draft_$(basename "$file")"<br> mv "$file" "$new_file_name"<br>done<br><br>echo "文件重命名成功。"<br>
输出python<br>import os<br>import shutil<br><br># 从用户获取文件夹名称<br>folder_name = input("输入文件夹名称:")<br><br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print("文件夹不存在。")<br> exit(1)<br><br># 获取文件夹中所有文件的列表<br>files = os.listdir(folder_name)<br><br># 遍历文件<br>for file in files:<br> # 创建一个带有前缀"draft_"的新文件名<br> new_file_name = f"draft_{file}"<br><br> # 将文件移动到新名称<br> shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name))<br><br># 打印成功消息<br>print("文件重命名成功。")<br>

表18. 将代码从Bash翻译为Python的提示

阅读并审查代码。复制提示中的输出并粘贴到一个新文件:file_renamer.py。通过打开终端窗口并执行以下命令来测试代码:python file_renamer.py。

注意:在Vertex AI的Language Studio中提示(Python)代码时,您必须点击"Markdown"按钮。否则,您将收到缺少行适当缩进的纯文本,这对运行Python代码很重要。

调试和审查代码的提示

让我们手动对表18的代码进行一些编辑。它应该提示用户输入文件名前缀,并以大写字符编写此前缀。参见示例代码片段3,但真遗憾。它现在返回Python错误!

import os
import shutilfolder_name = input("输入文件夹名称:")
prefix = input("输入要添加到文件名前面的字符串:")
text = toUpperCase(prefix)if not os.path.isdir(folder_name):print("文件夹不存在。")exit(1)files = os.listdir(folder_name)for file in files:new_filename = f"{text}_{file}"shutil.move(os.path.join(folder_name, file), os.path.joi(folder_name, new_file_name))print("文件重命名成功。")

代码片段3. 一个有错误的Python脚本

糟糕!看起来有一个错误:

下面的Python代码产生一个错误:

Traceback (most recent call last):File "/Users/leeboonstra/Documents/test_folder/rename_files.py", line 7, in <module>text = toUpperCase(prefix)
NameError: name 'toUpperCase' is not defined

让我们看看我们是否可以要求大型语言模型调试和审查代码。看看表19:

名称1_python_debug_code
目标编写提示来调试和审查Python代码。
模型gemini-pro
温度0.1
标记限制1024
Top-KN/A
Top-P1
提示下面的Python代码产生一个错误:

Traceback (most recent call last):
File "/Users/leeboonstra/Documents/test_folder/rename_files.py", line 7, in
text = toUpperCase(prefix)
NameError: name 'toUpperCase' is not defined

调试错误所在并解释如何改进代码。

python<br>import os<br>import shutil<br><br># 从用户获取文件夹名称<br><br>folder_name = input("输入文件夹名称:")<br>prefix = input("输入要添加到文件名前面的字符串:")<br>text = toUpperCase(prefix)<br><br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print("文件夹不存在。")<br> exit(1)<br><br># 获取文件夹中所有文件的列表<br>files = os.listdir(folder_name)<br><br># 遍历文件<br>for file in files:<br> # 创建一个带有前缀"draft_"的新文件名<br> new_filename = f"{text}_{file}"<br><br> # 将文件移动到新名称<br> shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name))<br><br># 打印成功消息<br>print("文件重命名成功。")<br>
输出代码调用toUpperCase函数将prefix转换为大写,但该函数未定义。要修复此问题,您可以使用字符串类的upper()方法,该方法将给定字符串转换为大写。修改后的代码如下所示:

python<br>import os<br>import shutil<br><br># 从用户获取文件夹名称<br>folder_name = input("输入文件夹名称:")<br>prefix = input("输入要添加到文件名前面的字符串:")<br>text = prefix.upper()<br><br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print("文件夹不存在。")<br> exit(1)<br><br># 获取文件夹中所有文件的列表<br>files = os.listdir(folder_name)<br><br># 遍历文件<br>for file in files:<br> # 创建一个带有前缀"draft_"的新文件名<br> new_filename = f"{text}_{file}"<br><br> # 将文件移动到新名称<br> shutil.move(os.path.join(folder_name, file),<br>os.path.join(folder_name, new_filename))<br><br># 打印成功消息<br>print("文件重命名成功。")<br>

此外,还可以对代码进行一些其他改进:

- 1. 新文件名未保留原始文件扩展名。最好从原始文件名中提取扩展名并将其附加到新文件名。

- 2. 代码假设文件夹名称中没有空格。然而,最好通过用下划线或连字符替换空格来优雅地处理空格。

- 3. 使用f字符串语法进行字符串插值比传统的+运算符更易读和
简洁。

- 4. 代码没有处理重命名过程中可能发生的错误。
最好将shutil.move调用包装在try...except块中以捕获任何潜在错误。

以下是采纳这些建议的改进代码:

python<br>import os<br>import shutil<br># 从用户获取文件夹名称<br>folder_name = input("输入文件夹名称:")<br>prefix = input("输入要添加到文件名前面的字符串:")<br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print("文件夹不存在。")<br> exit(1)<br># 获取文件夹中所有文件的列表<br>files = os.listdir(folder_name)<br><br># 遍历文件<br>for file in files:<br> # 获取文件扩展名<br> ext = os.path.splitext(file)[1]<br><br> # 创建一个带有前缀和文件扩展名的新文件名<br> new_filename = f"{prefix}_{os.path.splitext(file)[0]}{ext}"<br><br> # 构建原始和新文件的完整路径<br> old_path = os.path.join(folder_name, file)<br> new_path = os.path.join(folder_name, new_filename)<br><br> # 尝试移动文件<br> try:<br> shutil.move(old_path, new_path)<br><br> except Exception as e:<br> print(f"移动文件{file}时发生错误:{e}")<br><br># 打印成功消息<br>print("文件重命名成功。")<br>

这些改进使代码更加健壮和灵活,同时也使其更易于阅读和理解...(由于已达到标记限制,响应被截断。如果您需要更长的响应,请尝试增加标记限制。)

表19. 用于调试和审查Python代码的提示

太好了。它不仅告诉我如何解决问题,还发现我的代码存在更多错误并指导如何解决。提示的最后部分给出了改进代码的一般建议。

多模态提示

代码提示仍然使用相同的常规大型语言模型。多模态提示是一个单独的关注点,它指的是一种技术,您使用多种输入格式来指导大型语言模型,而不仅仅依赖于文本。这可以包括文本、图像、音频、代码或甚至其他格式的组合,取决于模型的能力和手头的任务。

最佳实践

找到正确的提示需要调整。Vertex AI中的Language Studio是一个完美的地方,可以使用各种模型测试您的提示。

使用以下最佳实践成为提示工程的专家。

提供示例

最重要的最佳实践是在提示中提供(单样本/少样本)示例。这非常有效,因为它充当强大的教学工具。这些示例展示期望的输出或类似的回应,使模型能够从中学习并相应地调整自己的生成。它就像给模型一个参考点或目标,提高其回应的准确性、风格和语调,以更好地符合您的期望。

设计简洁明了

提示应该简洁、清晰,并且对您和模型都容易理解。作为经验法则,如果它对您来说已经令人困惑,对模型来说也可能令人困惑。尽量不要使用复杂的语言,不要提供不必要的信息。

示例:

改写前:

我现在正在纽约,我想了解更多关于好地方的信息。我和两个3岁的孩子在一起。我们在度假期间应该去哪里?

改写后:

担任旅游指南为游客服务。描述纽约曼哈顿适合带3岁儿童参观的好地方。

尝试使用描述动作的动词。以下是一些示例:

行动、分析、分类、分类、对比、比较、创建、描述、定义、评估、提取、查找、生成、识别、列表、测量、组织、解析、选择、预测、提供、排名、推荐、返回、检索、重写、选择、显示、排序、总结、翻译、撰写。

明确指定输出

明确指定期望的输出。简洁的指令可能无法足够指导大型语言模型,或者可能过于泛泛。在提示中提供具体细节(通过系统或上下文提示)可以帮助模型专注于相关内容,提高整体准确性。

示例:

应该:

生成一篇关于前5名视频游戏主机的3段博客文章。博客文章应该信息丰富且引人入胜,并且应该以对话风格编写。

不应该:

生成一篇关于视频游戏主机的博客文章。

使用指令而非约束

指令和约束都用于在提示中指导大型语言模型的输出。

  • 指令提供关于期望的格式、风格或响应内容的明确指导。它指导模型应该做什么或产生什么。

  • 约束是对响应的一组限制或边界。它限制了模型不应该做或避免的内容。

越来越多的研究表明,在提示中专注于积极的指令比过度依赖约束更有效。这种方法与人类如何偏好积极指令而非不应该做的清单相一致。

指令直接传达期望的结果,而约束可能让模型猜测允许什么。它提供了灵活性并鼓励在定义的边界内的创造力,而约束可能限制模型的潜力。此外,约束列表可能相互冲突。

约束在某些情况下仍然有价值。为防止模型生成有害或有偏见的内容,或者当需要严格的输出格式或风格时。

如果可能,使用积极指令:不要告诉模型不要做什么,而是告诉它应该做什么。这可以避免混淆并提高输出的准确性。

应该:

生成一篇关于前5名视频游戏主机的1段博客文章。只讨论主机、制造它的公司、年份和总销量。

不应该:

生成一篇关于前5名视频游戏主机的1段博客文章。不要列出视频游戏名称。

作为最佳实践,首先优先考虑指令,清楚地陈述您希望模型做什么,只在必要时为安全、清晰或特定要求使用约束。实验和迭代以测试指令和约束的不同组合,找出最适合您特定任务的组合,并记录这些。

控制最大标记长度

要控制生成的大型语言模型响应的长度,您可以在配置中设置最大标记限制或在提示中明确要求特定长度。例如:

"用推文长度的消息解释量子物理学。"

在提示中使用变量

在提示中使用变量以便重用提示并使其更加动态,这些变量可以针对不同的输入进行更改。例如,如表20所示,提供关于城市的事实的提示。不要在提示中硬编码城市名称,使用变量。变量可以通过避免重复自己来节省您的时间和精力。如果您需要在多个提示中使用相同的信息,您可以将其存储在变量中,然后在每个提示中引用该变量。这在将提示集成到您自己的应用程序时非常有意义。

提示变量 {city} = "阿姆斯特丹"

提示 您是一名旅游指南。告诉我关于城市的一个事实:{city}
输出阿姆斯特丹是一个充满运河、桥梁和狭窄街道的美丽城市。这是一个很棒的地方,可以参观其丰富的历史、文化和夜生活。

表20. 在提示中使用变量

实验输入格式和写作风格

不同的模型、模型配置、提示格式、词汇选择和提交可能产生不同的结果。因此,重要的是要实验提示属性,如风格、词汇选择和提示类型(零样本、少样本、系统提示)。

例如,一个目标是生成关于革命性视频游戏主机Sega Dreamcast的文本的提示,可以被表述为问题、陈述或指令,从而产生不同的输出:

  • 问题:Sega Dreamcast是什么,为什么它是如此革命性的主机?

  • 陈述:Sega Dreamcast是世嘉在1999年发布的第六代视频游戏主机。它...

  • 指令:写一段描述Sega Dreamcast主机并解释为什么它如此革命性的单段落。

分类任务的少样本提示混合类别

一般来说,您的少样本示例的顺序不应该太重要。然而,在进行分类任务时,确保您混合可能的响应类别在少样本示例中。这是因为您可能会过度拟合特定示例的顺序。通过混合可能的响应类别,您可以确保模型正在学习识别每个类别的关键特征,而不是简单地记住示例的顺序。这将导致对未见数据的更健壮和可概括的性能。

一个好的经验法则是从6个少样本示例开始,并从那里开始测试准确性。

适应模型更新

对您来说,跟上模型架构变化、添加的数据和功能非常重要。尝试较新的模型版本,并调整您的提示以更好地利用新模型功能。像Vertex AI Studio这样的工具非常适合存储、测试和记录您提示的各种版本。

实验输出格式

除了提示输入格式外,考虑实验输出格式。对于非创意任务,如提取、选择、解析、排序、排名或分类数据,尝试使您的输出以JSON或XML等结构化格式返回。

从提取数据的提示中返回JSON对象有一些好处。在实际应用中,我不需要手动创建这种JSON格式,我已经可以按排序顺序返回数据(在处理日期时间对象时非常方便),但最重要的是,通过提示要求JSON格式,它迫使模型创建结构并限制幻觉。

总之,使用JSON输出的好处:

  • 总是以相同的风格返回
  • 专注于您想要接收的数据
  • 幻觉的可能性较小
  • 使其关系感知
  • 您获得数据类型
  • 您可以对其进行排序

表4在少样本提示部分展示了如何返回结构化输出的示例。

JSON修复

虽然以JSON格式返回数据提供了许多优势,但它也有缺点。JSON的结构化性质,虽然有利于解析和在应用程序中使用,但需要比纯文本更多的标记,导致处理时间增加和成本更高。此外,JSON的冗长可能很容易占用整个输出窗口,特别是当生成由于标记限制而突然截断时,这变得特别有问题。这种截断通常导致无效的JSON,缺失关键的闭合大括号或方括号,使输出无法使用。幸运的是,像json-repair库(在PyPI上可用)这样的工具在这些情况下可能非常有价值。该库智能地尝试自动修复不完整或格式错误的JSON对象,使其成为处理大型语言模型生成的JSON时的重要盟友,特别是在处理潜在截断问题时。

使用模式

使用结构化JSON作为输出是一个很好的解决方案,如我们在本文中多次看到的。但输入呢?虽然JSON非常适合结构化大型语言模型生成的输出,但它也可以用于结构化您提供的输入。这就是JSON模式的用武之地。JSON模式定义了您的JSON输入的预期结构和数据类型。通过提供模式,您为大型语言模型提供了它应该期望的数据的明确蓝图,帮助它将注意力集中在相关信息上,并降低误解输入的风险。此外,模式可以帮助建立不同数据片段之间的关系,甚至使大型语言模型"时间感知",包括具有特定格式的日期或时间戳字段。

以下是一个简单的示例:

假设您想使用大型语言模型为电子商务目录中的产品生成描述。不是仅仅提供关于产品的自由格式文本描述,您可以使用JSON模式来定义产品的属性:

{"type": "object","properties": {"name": {"type": "string","description": "产品名称"},"category": {"type": "string","description": "产品类别"},"price": {"type": "number","format": "float","description": "产品价格"},"features": {"type": "array","items": {"type": "string"},"description": "产品的主要特点"},"release_date": {"type": "string","format": "date","description": "产品发布日期"}},

代码片段5. 定义结构化输出模式

然后,您可以提供符合此模式的实际产品数据作为JSON对象:

{"name": "无线耳机","category": "电子产品","price": 99.99,"features": ["降噪", "蓝牙5.0", "20小时电池寿命"],"release_date": "2023-10-27"
}

代码片段6. 大型语言模型的结构化输出

通过预处理您的数据并提供模式和数据而不是完整文档,您为大型语言模型提供了对产品属性的清晰理解,包括其发布日期,使其更有可能生成准确和相关的描述。这种结构化输入方法,引导大型语言模型关注相关字段,在处理大量数据或将大型语言模型集成到复杂应用程序中时特别有价值。

与其他提示工程师一起实验

如果您处于需要尝试提出好提示的情况,您可能希望找到多人来尝试。当每个人都遵循最佳实践(如本章所列)时,您将看到所有不同提示尝试之间的性能差异。

链式思考最佳实践

对于CoT提示,将答案放在推理之后是必需的,因为推理的生成改变了模型在预测最终答案时获得的标记。

使用CoT和自洽性,您需要能够从您的提示中提取最终答案,与推理分开。

对于CoT提示,将温度设置为0。

链式思考提示基于贪婪解码,基于语言模型分配的最高概率预测序列中的下一个词。一般来说,当使用推理来得出最终答案时,可能只有一个正确答案。因此,温度应该始终设置为0。

记录各种提示尝试

本章前面提到的最后一个提示是:详细记录您的提示尝试,这样您就可以随着时间的推移了解哪些尝试成功,哪些失败。

提示输出可能因模型、采样设置甚至相同模型的不同版本而异。此外,即使对相同模型的相同提示,输出句子格式和词汇选择的小差异也可能发生。(例如,如前所述,如果两个标记具有相同的预测概率,平局可能会随机打破。这可能会影响后续预测的标记。)。

我们建议创建一个以表21为模板的Google电子表格。这种方法的优点是,当您不可避免地必须重新访问您的提示工作时,您有一个完整的记录——无论是在未来选择它(您会惊讶于即使只是短暂休息后能忘记多少),测试不同版本模型上的提示性能,还是帮助调试未来的错误。

除了此表中的字段外,追踪提示版本(迭代)、捕获结果是否OK/NOT OK/SOMETIMES OK的字段以及捕获反馈的字段也很有帮助。如果您足够幸运使用Vertex AI Studio,保存您的提示(使用与您的文档中列出的相同名称和版本),并在表格中跟踪保存提示的超链接。这样,您只需点击一下即可重新运行您的提示。

在处理检索增强生成系统时,您还应该捕获影响插入到提示中的内容的RAG系统的特定方面,包括查询、块设置、块输出和其他信息。

一旦您认为提示接近完美,将其带入您的项目代码库。在代码库中,将提示保存在与代码分开的文件中,这样更容易维护。最后,理想情况下,您的提示是一个操作化系统的一部分,作为提示工程师,您应该依赖自动化测试和评估程序来了解您的提示如何概括到任务。

提示工程是一个迭代过程。制作和测试不同的提示,分析并记录结果。根据模型的性能完善您的提示。继续实验,直到您获得所需的输出。当您更改模型或模型配置时,返回并继续使用先前使用的提示进行实验。

名称[您的提示名称和版本]
目标[这次尝试的目标的一句话解释]
模型[使用的模型名称和版本]
温度[0 - 1之间的值]
标记限制[数字]
Top-K[数字]
Top-P[数字]
提示[写出完整的提示]
输出[写出输出或多个输出]

表21. 记录提示的模板

总结

本白皮书讨论了提示工程。我们学习了各种提示技术,如:

  • 零样本提示
  • 少样本提示
  • 系统提示
  • 角色提示
  • 上下文提示
  • 回退提示
  • 链式思考
  • 自洽性
  • 思维树
  • 推理与行动

我们甚至研究了如何自动化您的提示。

白皮书然后讨论了生成式AI的挑战,如当您的提示不足时可能发生的问题。我们以如何成为更好的提示工程师的最佳实践结束。

尾注

  1. Google, 2023, Gemini by Google. 可在以下网址获取:https://gemini.google.com.

  2. Google, 2024, Gemini for Google Workspace Prompt Guide. 可在以下网址获取:https://inthecloud.withgoogle.com/gemini-for-google-workspace-prompt-guide/dl-cd.html.

  3. Google Cloud, 2023, Introduction to Prompting. 可在以下网址获取:https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/introduction-prompt-design.

  4. Google Cloud, 2023, Text Model Request Body: Top-P & top-K sampling methods. 可在以下网址获取:https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text#request_body.

  5. Wei, J., et al., 2023, Zero Shot - Fine Tuned language models are zero shot learners. 可在以下网址获取:https://arxiv.org/pdf/2109.01652.pdf.

  6. Google Cloud, 2023, Google Cloud Model Garden. 可在以下网址获取:https://cloud.google.com/model-garden.

  7. Brown, T., et al., 2023, Few Shot - Language Models are Few Shot learners. 可在以下网址获取:https://arxiv.org/pdf/2005.14165.pdf.

  8. Zheng, L., et al., 2023, Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models. 可在以下网址获取:https://openreview.net/pdf?id=3bq3jsvcQ1

  9. Wei, J., et al., 2023, Chain of Thought Prompting. 可在以下网址获取:https://arxiv.org/pdf/2201.11903.pdf.

  10. Google Cloud Platform, 2023, Chain of Thought and React. 可在以下网址获取:https://github.com/GoogleCloudPlatform/generative-ai/blob/main/language/prompts/examples/chain_of_thought_react.ipynb.

  11. Wang, X., et al., 2023, Self Consistency Improves Chain of Thought reasoning in language models. 可在以下网址获取:https://arxiv.org/pdf/2203.11171.pdf.

  12. Yao, S., et al., 2023, Tree of Thoughts: Deliberate Problem Solving with Large Language Models. 可在以下网址获取:https://arxiv.org/pdf/2305.10601.pdf.

  13. Yao, S., et al., 2023, ReAct: Synergizing Reasoning and Acting in Language Models. 可在以下网址获取:https://arxiv.org/pdf/2210.03629.pdf.

  14. Google Cloud Platform, 2023, Advance Prompting: Chain of Thought and React. 可在以下网址获取:https://github.com/GoogleCloudPlatform/applied-ai-engineering-samples/blob/main/genai-on-vertex-ai/advanced_prompting_training/cot_react.ipynb.

  15. Zhou, C., et al., 2023, Automatic Prompt Engineering - Large Language Models are Human-Level Prompt Engineers. 可在以下网址获取:https://arxiv.org/pdf/2211.01910.pdf.


相关文章:

  • Active Directory域服务管理与高级应用技术白皮书
  • Linux 深入浅出信号量:从线程到进程的同步与互斥实战指南
  • Leetcode 3514. Number of Unique XOR Triplets II
  • python爬虫 线程,进程,协程
  • Oracle数据库数据编程SQL<01. 课外关注:数据库查重方法全面详解>
  • Linux指令和权限(10-3)
  • 聚铭网络亮相2025超云产品技术大会,联合发布“铭智安全运营大模型一体机及解决方案”
  • Rust 之五 所有权、.. 和 _ 语法、引用和切片、Vec<T>、HashMap<K, V>
  • MIT6.S081 - Lab8 Locks(锁优化 | 并发安全)
  • HTTP请求方法安全剖析(不安全的网络请求方法):从CVE-2017-12615看PUT/DELETE的风险利用
  • JavaScript的常用数组API原理
  • jspm企业采购管理系统的设计与实现(源码+lw+部署文档+讲解),源码可白嫖!
  • 第四篇:[特殊字符] 深入理解MyBatis[特殊字符] 掌握MyBatis Generator ——入门与实战
  • AI 边缘计算盒子:开启智能物联新时代
  • Proteus 仿真51单片机-串口收发小窥
  • ES关系映射(数据库中的表结构)
  • MySQL数据库---修改密码以及设置密码永过期
  • 云渗透二(云主机攻防)
  • 搭建一个网站需要选择什么配置的服务器?
  • 服务器数据恢复—AIX小型机误删数据如何找回?
  • 释新闻|新加坡大选今日投票:除了黄循财首次挂帅,还有哪些看点
  • 乌美签署矿产协议
  • 夜读丨春天要去动物园
  • 奔驰一季度利润降四成,受美国加征关税影响放弃全年盈利展望
  • 范宇任上海宝山区副区长
  • 200枚篆刻聚焦北京中轴线,“印记”申遗往事