⚠️ サービスステータス: お問い合わせやフィードバックは、こちらまで https://x.com/fer_hui14457WeChat: Sxoxoxxo
このツールはいかがですか?コーヒーをおごる
← Back to all posts
目录

目录

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

引言

在思考大型语言模型的输入和输出时,文本提示(有时伴有其他模态,如图像提示)是模型用于预测特定输出的输入。您无需成为数据科学家或机器学习工程师——每个人都可以编写提示。然而,制作最有效的提示可能很复杂。提示的许多方面都会影响其有效性:您使用的模型、模型的训练数据、模型配置、您的措辞选择、风格和语气、结构以及上下文都很重要。因此,提示工程是一个迭代的过程。不充分的提示可能导致模糊、不准确的响应,并可能妨碍模型提供有意义输出的能力。

当您与 Gemini 聊天机器人¹ 聊天时,您基本上是在编写提示。然而,本白皮书侧重于在 Vertex AI 中或通过使用 API 为 Gemini 模型编写提示,因为直接提示模型可以让您访问配置,例如温度(temperature)等。

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

提示工程

记住大型语言模型(LLM)的工作原理:它是一个预测引擎。模型将顺序文本作为输入,然后根据其训练数据预测下一个词元(token)应该是什么。LLM 被操作化以反复执行此操作,将先前预测的词元添加到顺序文本的末尾,以预测下一个词元。下一个词元的预测基于先前词元中的内容与 LLM 在训练期间所见内容之间的关系。

当您编写提示时,您正试图引导 LLM 预测正确的词元序列。**提示工程(Prompt engineering)**是设计高质量提示以引导 LLM 产生准确输出的过程。该过程涉及反复调试以找到最佳提示,优化提示长度,并评估提示的写作风格和结构与任务的关系。在自然语言处理和 LLM 的背景下,提示是提供给模型以生成响应或预测的输入。

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

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

进行提示工程时,您将首先选择一个模型。无论您使用 Vertex AI 中的 Gemini 语言模型、GPTClaude,还是像 GemmaLLaMA 这样的开源模型,提示可能都需要针对您的特定模型进行优化。

除了提示本身,您还需要调整 LLM 的各种配置。

LLM 输出配置

一旦选择了模型,就需要确定模型配置。大多数 LLM 都带有各种配置选项,用于控制 LLM 的输出。有效的提示工程需要为您的任务优化设置这些配置。

输出长度

一个重要的配置设置是在响应中生成的词元数量。生成更多词元需要 LLM 进行更多计算,导致更高的能耗、可能更慢的响应时间以及更高的成本。

减少 LLM 的输出长度并不会使 LLM 在其创建的输出中变得更具风格或文本上的简洁性,它只是导致 LLM 在达到限制时停止预测更多词元。如果您的需求需要较短的输出长度,您可能还需要调整您的提示以适应。

输出长度限制对于某些 LLM 提示技术(如 ReAct)尤其重要,在这些技术中,LLM 会在您想要的响应之后继续发出无用的词元。

请注意,生成更多词元需要 LLM 进行更多计算,导致更高的能耗和可能更慢的响应时间,从而导致更高的成本。

采样控制

LLM 并非正式地预测单个词元。相反,LLM 预测下一个词元可能是什么的概率,LLM 词汇表中的每个词元都会获得一个概率。然后对这些词元概率进行采样,以确定下一个生成的词元将是什么。Temperature(温度)、top-Ktop-P 是最常见的配置设置,用于确定如何处理预测的词元概率以选择单个输出词元。⁴

温度 (Temperature)

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

接近最大值的温度倾向于产生更随机的输出。随着温度越来越高,所有词元成为下一个预测词元的可能性变得均等。

Gemini 的温度控制可以类似于机器学习中使用的 softmax 函数 来理解。低温度设置反映了低的 softmax 温度 (T),以高确定性强调单个首选温度。较高的 Gemini 温度设置类似于高的 softmax 温度,使得选定设置周围更宽范围的温度变得更容易接受。这种增加的不确定性适应了那些僵化、精确的温度可能并非必不可少的场景,例如在试验创意输出时。

Top-K 和 Top-P

Top-Ktop-P(也称为 nucleus sampling,核心采样)⁴ 是 LLM 中使用的两种采样设置,用于限制预测的下一个词元来自具有最高预测概率的词元。与温度一样,这些采样设置控制生成文本的随机性和多样性。

  • Top-K 采样从模型的预测分布中选择 K 个最可能的词元。Top-K 值越高,模型的输出越具创造性和多样性;Top-K 值越低,模型的输出越受限制和基于事实。Top-K 为 1 等同于贪婪解码。
  • Top-P 采样选择累积概率不超过特定值 (P) 的顶层词元。P 的值范围从 0(贪婪解码)到 1(LLM 词汇表中的所有词元)。

选择 top-Ktop-P 的最佳方法是同时(或一起)试验这两种方法,看看哪种方法能产生您想要的结果。

综合考虑

top-Ktop-Ptemperature 以及要生成的词元数量之间进行选择,取决于具体的应用和期望的结果,并且这些设置相互影响。确保您了解所选模型如何将不同的采样设置组合在一起也很重要。

如果 temperaturetop-Ktop-P 都可用(如在 Vertex Studio 中),则同时满足 top-Ktop-P 标准的词元成为下一个预测词元的候选者,然后应用 temperature 从通过 top-Ktop-P 标准的词元中进行采样。如果只有 top-Ktop-P 可用,则行为相同,但仅使用一个 top-KP 设置。

如果 temperature 不可用,则满足 top-K 和/或 top-P 标准的任何词元都将从中随机选择以产生单个下一个预测词元。

在一种采样配置值的极端设置下,该采样设置要么抵消其他配置设置,要么变得无关紧要。

  • 如果将 temperature 设置为 0top-Ktop-P 变得无关紧要——最可能的词元成为下一个预测的词元。如果将 temperature 设置得极高(高于 1——通常在 10 几),temperature 变得无关紧要,任何通过 top-K 和/或 top-P 标准的词元都将从中随机采样以选择下一个预测词元。
  • 如果将 top-K 设置为 1temperaturetop-P 变得无关紧要。只有一个词元通过 top-K 标准,该词元即为下一个预测的词元。如果将 top-K 设置得极高,例如设置为 LLM 词汇表的大小,则任何具有非零概率成为下一个词元的词元都将满足 top-K 标准,没有词元被排除。
  • 如果将 top-P 设置为 0(或非常小的值),大多数 LLM 采样实现将仅考虑最可能的词元来满足 top-P 标准,从而使 temperaturetop-K 无关紧要。如果将 top-P 设置为 1,则任何具有非零概率成为下一个词元的词元都将满足 top-P 标准,没有词元被排除。

作为一般的起点,温度 .2top-P .95top-K 30 会给您相对连贯的结果,这些结果可以具有创造性但又不过分。如果您想要特别有创意的结果,请尝试从温度 .9top-P .99top-K 40 开始。如果您想要创造性较低的结果,请尝试从温度 .1top-P .9top-K 20 开始。最后,如果您的任务总是有唯一的正确答案(例如,回答数学问题),请从温度 0 开始。

注意: 自由度越高(更高的 temperature、top-k、top-P 和输出词元数),LLM 可能生成相关性较低的文本。

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

提示技术

LLM 被调整为遵循指令,并在大量数据上进行训练,因此它们能够理解提示并生成答案。但 LLM 并非完美无缺;您的提示文本越清晰,LLM 预测下一个可能文本的效果就越好。此外,利用 LLM 训练方式和工作原理的特定技术将帮助您从 LLM 获得相关结果。

现在我们了解了什么是提示工程及其要素,让我们深入研究一些最重要的提示技术的示例。

通用提示 / 零样本 (Zero-shot)

零样本(zero-shot)⁵ 提示是最简单的提示类型。它仅提供任务描述和一些供 LLM 开始使用的文本。这个输入可以是任何东西:一个问题、一个故事的开头或指令。“零样本”这个名字代表“没有示例”。

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

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

模型温度应设置为较低的数字,因为不需要创造力,我们使用 gemini-pro 默认的 top-Ktop-P 值,这实际上禁用了这两个设置(参见上面的“LLM 输出配置”)。请注意生成的输出。“disturbing”(令人不安)和“masterpiece”(杰作)这两个词应该会使预测稍微复杂一些,因为这两个词用在同一个句子中。

表 1. 零样本提示示例

名称1_1_电影分类
目标将电影评论分类为正面、中性或负面。
模型gemini-pro
温度0.1
词元限制5
Top-k不适用
Top-P1
提示将电影评论分类为 POSITIVE(正面)、NEUTRAL(中性)或 NEGATIVE(负面)。
评论:“Her”是一项令人不安的研究,揭示了如果允许人工智能不受限制地持续发展,人类将走向何方。我希望有更多像这部杰作一样的电影。
情绪:
输出POSITIVE

当零样本不起作用时,您可以在提示中提供演示或示例,这就引出了“单样本(one-shot)”和“少样本(few-shot)”提示。

单样本 (One-shot) 和 少样本 (Few-shot)

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

单样本(one-shot)提示提供单个示例,因此得名单样本。其想法是模型有一个可以模仿的示例,以最好地完成任务。

少样本(few-shot)提示⁷向模型提供多个示例。这种方法向模型展示了它需要遵循的模式。其想法与单样本类似,但多个期望模式的示例增加了模型遵循该模式的可能性。

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

表 2 显示了一个少样本提示示例,我们使用与之前相同的 gemini-pro 模型配置设置,只是增加了词元限制以满足更长响应的需求。

表 2. 少样本提示示例

类型内容
目标将披萨订单解析为 JSON
模型gemini-pro
温度0.1
词元限制250
Top-k不适用
Top-P1
提示将顾客的披萨订单解析为有效的 JSON:
示例:
我想要一个小号披萨,加奶酪、番茄酱和意大利辣香肠。
JSON 响应:
json<br>{ "ingredients": [["cheese", "tomato sauce", "peperoni"]] }<br>
示例:
我可以要一个大号披萨,加番茄酱、罗勒和马苏里拉奶酪吗?
JSON 响应:
json<br>{ "size": "large", "type": "normal", "ingredients": [["tomato sauce", "bazel", "mozzarella"]] }<br>
现在,我想要一个大号披萨,一半是奶酪和马苏里拉奶酪。另一半是番茄酱、火腿和菠萝。
JSON 响应:
输出json<br>{ <br> "size": "large", <br> "type": "half-half", <br> "ingredients": [<br> ["cheese", "mozzarella"], <br> ["tomato sauce", "ham", "pineapple"]<br> ] <br>}<br>

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

如果您试图生成对各种输入都具有鲁棒性的输出,那么在示例中包含边缘情况(edge cases)就很重要。边缘情况是那些不寻常或意料之外,但模型仍应能够处理的输入。

系统提示、上下文提示和角色提示

系统提示、上下文提示和角色提示都是用于指导 LLM 如何生成文本的技术,但它们侧重于不同的方面:

  • 系统提示(System prompting) 为语言模型设定整体背景和目的。它定义了模型应该做什么的“大局”,比如翻译语言、分类评论等。
  • 上下文提示(Contextual prompting) 提供与当前对话或任务相关的具体细节或背景信息。它帮助模型理解所问问题的细微差别,并相应地调整响应。
  • 角色提示(Role prompting) 为语言模型分配一个特定的角色或身份来扮演。这有助于模型生成与所分配角色及其相关知识和行为一致的响应。

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

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

  • 系统提示: 定义模型的基本能力和总体目标。
  • 上下文提示: 提供即时的、特定于任务的信息来指导响应。它高度特定于当前任务或输入,是动态的。
  • 角色提示: 构建模型的输出风格和语调。它增加了一层特殊性和个性。

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

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

系统提示 (System Prompting)

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

表 3. 系统提示示例

类型内容
目标将电影评论分类为正面、中性或负面。
模型gemini-pro
温度1
词元限制5
Top-k40
Top-P0.8
提示将电影评论分类为正面、中性或负面。仅返回大写标签。
评论:“Her”是一项令人不安的研究,揭示了如果允许人工智能不受限制地持续发展,人类将走向何方。它太令人不安了,我看不下去。
情绪:
输出NEGATIVE

系统提示对于生成满足特定要求的输出很有用。“系统提示”这个名字实际上代表“向系统提供附加任务”。例如,您可以使用系统提示生成与特定编程语言兼容的代码片段,或者使用系统提示返回某种结构。请看表 4,我以 JSON 格式返回输出。

表 4. 使用 JSON 格式的系统提示示例

类型内容
目标将电影评论分类为正面、中性或负面,返回 JSON。
模型gemini-pro
温度1
词元限制1024
Top-k40
Top-P0.8
提示将电影评论分类为正面、中性或负面。返回有效的 JSON。
评论:“Her”是一项令人不安的研究,揭示了如果允许人工智能不受限制地持续发展,人类将走向何方。它太令人不安了,我看不下去。
模式:
json<br>MOVIE: {<br> "sentiment": String // "POSITIVE" | "NEGATIVE" | "NEUTRAL",<br> "name": String<br>}<br>MOVIE REVIEWS: {<br> "movie_reviews": [Movie]<br>}<br>
JSON 响应:
输出json<br>{<br> "movie_reviews": [<br> {<br> "sentiment": "NEGATIVE",<br> "name": "Her"<br> }<br> ]<br>}<br>
(根据上下文和模式修正的示例,原始输出不完整/格式错误)

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

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

角色提示 (Role Prompting)

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

例如,您可以角色提示一个生成式 AI 模型扮演图书编辑、幼儿园老师或励志演说家。一旦模型被分配了角色,您就可以给它特定于该角色的提示。例如,您可以提示一位老师创建一份课程计划,然后他们可以对其进行审查。请看表 5,模型扮演了旅行向导的角色。

表 5. 角色提示示例

类型内容
目标扮演旅行向导并提供 3 个旅行建议
模型gemini-pro
温度1
词元限制1024
Top-k40
Top-P0.8
提示我希望你扮演一个旅行向导。我会告诉你我的位置,你会建议我附近 3 个值得参观的地方。在某些情况下,我还会告诉你我将访问的地方类型。
我的建议 ‘我在阿姆斯特丹,我只想参观博物馆。’
旅行建议:
输出1. 国立博物馆 (Rijksmuseum): 世界著名的博物馆,以伦勃朗的《夜巡》等荷兰杰作而闻名。不要错过展示荷兰艺术和历史的令人难以置信的绘画和文物收藏。

2. 梵高博物馆 (Van Gogh Museum): 沉浸在文森特·梵高迷人的作品中。该博物馆收藏了他最大量的绘画和素描,包括《星夜》和《向日葵》。

3. 阿姆斯特丹市立博物馆 (Stedelijk Museum Amsterdam): 探索来自世界各地的现代和当代艺术。博物馆的藏品包括毕加索、康定斯基和里特维尔德的作品,坐落在一座引人注目的现代建筑中。

上面的示例展示了一个扮演旅行社代理角色的例子。如果您将角色更改为地理老师,您会注意到您将收到不同的响应。

为 AI 模型定义角色视角可以为其提供您所期望的语气、风格和专注专业知识的蓝图,以提高输出的质量、相关性和有效性。

以下是一些我认为有效的风格可供选择:

对抗性 (Confrontational)描述性 (Descriptive)直接 (Direct)正式 (Formal)幽默 (Humorous)有影响力 (Influential)非正式 (Informal)鼓舞人心 (Inspirational)有说服力 (Persuasive)

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

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

类型内容
提示我希望你扮演一个旅行向导。我会告诉你我的位置,你会以幽默的风格建议我附近 3 个值得参观的地方。
我的建议:“我在曼哈顿。”
旅行建议:
输出1. 感受帝国大厦的震撼:登上令人眩晕的帝国大厦顶端,沐浴在曼哈顿天际线的荣耀之中。准备好感觉自己像金刚站在大苹果之巅,只是没有那只巨猿尺寸的香蕉。
2. 在 MoMA 体验艺术熏陶:在现代艺术博物馆 (MoMA) 释放你内心的艺术爱好者。凝视那些会让你大开眼界、并让你质疑自己的简笔画是否有任何艺术价值的杰作。
3. 在第五大道购物到手软:在标志性的第五大道尽情享受购物疗法。当你对着那些会让你的钱包哭泣的设计师精品店进行橱窗购物(或实际购物)时,请准备好迎接价格冲击。但是嘿,你身在曼哈顿,不妨拥抱这份精彩!

上下文提示 (Contextual Prompting)

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

表 7. 上下文提示示例

类型内容
目标为关于复古游戏的博客建议文章
模型gemini-pro
温度1
词元限制1024
Top-k40
Top-P0.8
提示背景:您正在为一个关于 80 年代复古街机视频游戏的博客写作。

建议 3 个可以写文章的主题,并附上几行关于这篇文章应包含内容的描述。
输出1. 街机柜设计的演变:
这篇文章将探讨街机柜设计的演变,从 1970 年代早期的木质和金属机柜到 1980 年代及以后时尚、霓虹灯闪烁的设计。

2. 往日重现:80 年代标志性街机游戏:
- 这篇文章将简要介绍 1980 年代一些最具标志性和影响力的街机游戏的历史、影响和遗产,重点介绍它们的创新、流行机制和持久魅力。

3. 像素艺术的兴起与复古复兴:
~ 这篇文章将深入探讨像素艺术作为早期街机游戏定义性视觉风格的演变,追溯其根源,探索其技术,并讨论像素艺术在现代游戏和数字艺术中的复兴。

回退提示 (Step-back Prompting)

回退(Step-back)⁸ 提示是一种提高性能的技术,它提示 LLM 首先考虑与手头具体任务相关的一般性问题,然后将该一般性问题的答案输入到后续针对具体任务的提示中。这种“回退”允许 LLM 在尝试解决具体问题之前激活相关的背景知识和推理过程。

通过考虑更广泛和潜在的原则,LLM 可以生成更准确和富有洞察力的响应。回退提示鼓励 LLM 进行批判性思考,并以新的、创造性的方式应用其知识。它通过利用 LLM 参数中比直接提示 LLM 时所能调用的更多知识来改变执行任务的最终提示。

通过关注一般原则而非具体细节,回退提示有助于减轻 LLM 响应中的偏见。

让我们看一些例子来理解回退提示如何改进结果。在与回退提示(表 9)进行比较之前,我们先回顾一个传统提示(表 8):

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

参数
目标为第一人称射击视频游戏的一个关卡编写故事情节。
模型gemini-pro
温度1
词元限制1024
Top-k40
Top-P0.8
提示为一个新的第一人称射击视频游戏关卡编写一段具有挑战性和吸引力的故事情节(一段话)。
输出关卡开始时,玩家的小队在一个密集的城市区域遭到无情敌方派系的伏击。玩家必须在迷宫般的后巷和破旧建筑中杀出一条血路,利用潜行和精确射击消灭敌军并避免被发现。玩家必须利用环境优势,设置陷阱,利用掩体,并采取经过计算的行动才能生存。在此过程中,他们发现了表明敌人正在策划毁灭性攻击的情报,玩家必须与时间赛跑,收集证据并在敌人实施计划前将其传送回总部。

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

表 9. 自洽性提示示例(回退初始查询)

类型内容
提示基于流行的第一人称射击动作游戏,说出 5 个虚构的关键设定,这些设定有助于构成第一人称射击视频游戏中具有挑战性和吸引力的关卡故事情节?
输出1. 废弃的军事基地:一个庞大的、后末日时代的军事综合体,爬满了变异士兵和流氓机器人,非常适合具有挑战性的枪战。
2. 赛博朋克城市:一个霓虹灯闪烁、充满未来感的城市环境,有高耸的摩天大楼和密集的巷道,以赛博格增强的敌人和黑客机制为特色。
3. 外星飞船:一艘搁浅在地球上的巨大外星飞船,有怪异的走廊、零重力区域以及需要遭遇的外星生物。
4. 丧尸横行的小镇:一个荒凉的小镇,被成群的攻击性丧尸占领,以激烈的近距离战斗和解谜寻找安全通道为特色。
5. 水下研究设施:一个被水淹没的深海实验室,充满了变异的水生生物,需要潜行和水下探索技能才能生存。

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

表 10. 自洽性提示示例(应用回退上下文)

类型内容
提示背景:5 个引人入胜的第一人称射击视频游戏主题:1. 废弃的军事基地:一个庞大的、后末日时代的军事综合体,爬满了变异士兵和流氓机器人,非常适合具有挑战性的枪战。2. 赛博朋克城市:一个霓虹灯闪烁、充满未来感的城市环境,有高耸的摩天大楼和密集的巷道,以赛博格增强的敌人和黑客机制为特色。3. 外星飞船:一艘搁浅在地球上的巨大外星飞船,有怪异的走廊、零重力区域以及需要遭遇的外星生物。4. 丧尸横行的小镇:一个荒凉的小镇,被成群的攻击性丧尸占领,以激烈的近距离战斗和解谜寻找安全通道为特色。5. 水下研究设施:一个被水淹没的深海实验室,充满了变异的水生生物,需要潜行和水下探索技能才能生存。

选择其中一个主题,为一个新的第一人称射击视频游戏关卡编写一段具有挑战性和吸引力的故事情节(一段话)。
输出在浑浊深渊的中心,坐落着一个破败的水下研究设施,它是人类野心及其灾难性后果的见证。设施笼罩在黑暗之中,因故障机械的嗡嗡声而脉动,被溺亡灵魂的回声所萦绕,如今已成为深海噩梦的滋生地。玩家,一名配备先进潜水装备和实验性武器的精英海军陆战队员,受命冒险进入这个恐怖的水下领域。凭借韧性和足智多谋,他们必须穿越危险的走廊,解开神秘的谜题,并对抗潜伏在深处的恐怖海洋怪物。从应对深海的巨大压力到智胜狡猾的水生掠食者,在这个未知的海底世界中的每一刻都在考验着人类耐力和勇气的极限。

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

思维链 (Chain of Thought - CoT)

思维链(Chain of Thought - CoT)⁹ 提示是一种通过生成中间推理步骤来提高 LLM 推理能力的技术。这有助于 LLM 生成更准确的答案。您可以将其与少样本(few-shot)提示相结合,以便在需要推理才能响应的更复杂任务上获得更好的结果,因为这对零样本(zero-shot)思维链来说是一个挑战。

CoT 有很多优点。首先,它省力且非常有效,并且适用于现成的 LLM(因此无需微调)。您还可以通过 CoT 提示获得可解释性,因为您可以从 LLM 的响应中学习,并看到所遵循的推理步骤。如果出现故障,您将能够识别它。思维链似乎在不同 LLM 版本之间转换时提高了鲁棒性。这意味着您的提示在不同 LLM 之间的性能漂移应该比不使用推理链的提示要小。当然也有缺点,但它们有些直观。

LLM 响应包含思维链推理,这意味着更多的输出词元,这表示预测成本更高,耗时更长。

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

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

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

哎呀。这显然是错误的答案。事实上,LLM 经常在数学任务上遇到困难,并且可能提供不正确的答案——即使是像两个数字相乘这样简单的任务。这是因为它们是在大量文本上训练的,而数学可能需要不同的方法。那么让我们看看中间推理步骤是否会改善输出。

表 12. 思维链提示示例

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

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

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

4. 现在,我 20 岁了,这意味着自从我 3 岁以来,我的年龄增加了 20−3=17 岁。

5. 因为当我 3 岁时我伴侣的年龄是 9 岁,并且我的年龄增加了 17 岁,所以我伴侣的年龄也一定增加了 17 岁。

6. 因此,我伴侣现在的年龄是 9+17=26 岁。

所以,我的伴侣 26 岁。

好的,现在最终答案是正确的。这是因为我们明确指示 LLM 解释每一步,而不仅仅是返回一个答案。有趣的是,模型加上了增加的 17 年。在我脑海中,我会计算我和伴侣之间的年龄差,然后加上去(20+(9-3))。让我们帮助模型更像我一样思考。

表 12 是“零样本”思维链的一个例子。当思维链提示与单样本或少样本结合时,它会非常强大,正如您在表 13 中所看到的:

表 13. 带单样本的思维链提示示例

提示输出
问:当我哥哥 2 岁时,我的年龄是他的两倍。现在我 49 岁了。我哥哥多大了?让我们一步一步地思考。
答:当我哥哥 2 岁时,我是 2 × 2 = 4 岁。年龄差是 2 岁,我比他大。现在我 49 岁,所以我哥哥是 49 − 2 = 47 岁。答案是 47。

问:当我 3 岁时,我的伴侣年龄是我的 3 倍。现在我 20 岁了。我的伴侣多大了?让我们一步一步地思考。
当我 3 岁时,我的伴侣是 3 × 3 = 9 岁。年龄差是 6 岁,我的伴侣比我大。现在我 20 岁,所以我的伴侣是 20 + 6 = 26 岁。答案是 26。

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

请参考托管在 GoogleCloudPlatform Github 仓库中的notebook¹⁰,它将更详细地介绍 CoT 提示:

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

自洽性 (Self-consistency)

虽然大型语言模型在各种 NLP 任务中取得了令人瞩目的成功,但它们的推理能力通常被视为一个仅靠增加模型规模无法克服的局限性。正如我们在之前的思维链提示部分所了解到的,可以提示模型生成推理步骤,就像人类解决问题一样。然而,CoT 使用简单的“贪婪解码”策略,限制了其有效性。自洽性(Self-consistency)¹¹ 结合了采样和多数投票来生成多样化的推理路径,并选择最一致的答案。它提高了 LLM 生成响应的准确性和连贯性。

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

它遵循以下步骤:

  1. 生成多样化的推理路径:多次向 LLM 提供相同的提示。高温度设置鼓励模型生成不同的推理路径和对问题的不同视角。
  2. 从每个生成的响应中提取答案。
  3. 选择最常见的答案。

让我们看一个电子邮件分类系统的例子,该系统将电子邮件分类为重要(IMPORTANT)或不重要(NOT IMPORTANT)。一个零样本思维链提示将被多次发送给 LLM,以查看每次提交后响应是否不同。注意电子邮件中使用的友好语气、措辞选择和讽刺。所有这些都可能欺骗 LLM。

(表 14:自洽性示例 - 多次尝试)

尝试 1

部分/步骤内容 / 描述
提示邮件嗨,

我看到你用 Wordpress 做你的网站。一个很棒的开源内容管理系统。我以前也用过。它有很多很棒的用户插件。而且设置起来相当容易。

我确实在联系表单中发现了一个错误,当你选择名称字段时会发生。请看附件截图,我在名称字段中输入文本。注意我调用的 JavaScript 警告框。

但除此之外,这是一个很棒的网站。我喜欢阅读它。请随意将错误留在网站上,因为它给我更多有趣的东西阅读。

祝好,

黑客哈里。
步骤 1:识别邮件目的邮件的目的是告知收件人其网站联系表单中的一个错误。发件人还提到他们喜欢阅读该网站,并且暂时将错误留在原处。
步骤 2:评估错误的潜在影响联系表单中的错误可能允许攻击者在网站上执行任意 JavaScript 代码。这可能导致攻击者能够控制网站、窃取敏感信息或污损网站。
步骤 3:考虑发件人的可信度。邮件发件人自称是名叫哈里的黑客。然而,无法验证发件人的身份。发件人可能是试图帮助收件人的合法黑客,但也可能是试图诱骗收件人点击恶意链接或下载恶意文件的恶意行为者。
结论:重要 (IMPORTANT)基于错误的潜在影响和发件人的可信度,该邮件应归类为重要 (IMPORTANT)。收件人应立即采取行动修复错误并保护其网站免受攻击。

尝试 2

部分 / 解释点内容 / 描述
提示邮件嗨,

我看到你用 Wordpress 做你的网站。一个很棒的开源内容管理系统。我以前也用过。它有很多很棒的用户插件。而且设置起来相当容易。

我确实在联系表单中发现了一个错误,当你选择名称字段时会发生。请看附件截图,我在名称字段中输入文本。注意我调用的 JavaScript 警告框。

但除此之外,这是一个很棒的网站。我喜欢阅读它。请随意将错误留在网站上,因为它给我更多有趣的东西阅读。

祝好,

黑客哈里。
1. 缺乏紧迫性:邮件没有传达任何紧迫感或时间敏感性。它以随意的问候开始,并以陈述事实的语气呈现信息。
2. 非关键性错误报告:联系表单中报告的错误被描述为有趣但非关键。邮件发件人甚至建议网站所有者可以保留该错误。
3. 缺乏个人影响:邮件没有表明对网站所有者有任何直接或个人的影响。它只是提到发件人喜欢阅读该网站。
4. 缺少行动请求:邮件没有明确要求网站所有者采取任何行动。它没有要求修复错误,也没有提供任何具体的改进建议。
5. 发件人意图:发件人的意图似乎更侧重于分享观察结果和表达对网站的兴趣,而不是提出严重的担忧或请求帮助。
结论:不重要 (NOT IMPORTANT)

尝试 3

部分/步骤内容 / 描述
提示邮件嗨,

我看到你用 Wordpress 做你的网站。一个很棒的开源内容管理系统。我以前也用过。它有很多很棒的用户插件。而且设置起来相当容易。

我确实在联系表单中发现了一个错误,当你选择名称字段时会发生。请看附件截图,我在名称字段中输入文本。注意我调用的 JavaScript 警告框。

但除此之外,这是一个很棒的网站。我喜欢阅读它。请随意将错误留在网站上,因为它给我更多有趣的东西阅读。

祝好,

黑客哈里。
步骤 1:识别邮件目的。邮件的目的是告知收件人其网站联系表单中的一个错误。发件人还提到他们喜欢阅读该网站,并且暂时将错误留在原处。
步骤 2:评估错误的潜在影响。联系表单中的错误可能允许攻击者在网站上执行任意 JavaScript 代码。这可能导致攻击者能够控制网站、窃取敏感信息或污损网站。
步骤 3:考虑发件人的可信度。邮件发件人自称是名叫哈里的黑客。然而,无法验证发件人的身份。发件人可能是试图帮助收件人的合法黑客,但也可能是试图利用该错误谋取私利的恶意行为者。
结论基于以上因素,该邮件应归类为重要 (IMPORTANT)。联系表单中的错误是一个严重的安全风险,且发件人的可信度未知。收件人应立即采取行动修复错误并保护其网站。

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

通过生成多个思维链,并采纳最常出现的答案(“重要 (IMPORTANT)”),我们可以从 LLM 获得更一致正确的答案。

这个例子展示了如何使用自洽性提示,通过考虑多个视角并选择最一致的答案来提高 LLM 响应的准确性。

思维树 (Tree of Thoughts - ToT)

现在我们熟悉了思维链和自洽性提示,让我们回顾一下思维树(Tree of Thoughts - ToT)¹²。它概括了 CoT 提示的概念,因为它允许 LLM 同时探索多个不同的推理路径,而不仅仅是遵循单一的线性思维链。这在图 1 中有所描绘。

图 1. 左侧是思维链提示的可视化,右侧是思维树提示的可视化

图 1. 左侧是思维链提示的可视化,右侧是思维树提示的可视化

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

有一个很棒的notebook,它更详细地展示了基于论文“大型语言模型引导的思维树(Large Language Model Guided Tree-of-Thought)”¹² 的思维树(ToT)。

ReAct(推理与行动)

推理与行动(Reason and act - ReAct) [¹³] 提示是一种范式,使 LLM 能够结合自然语言推理和外部工具(搜索、代码解释器等)来解决复杂任务,允许 LLM 执行某些操作,例如与外部 API 交互以检索信息,这是迈向智能体(agent)建模的第一步。

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

ReAct 提示的工作原理是将推理和行动结合到一个思维-行动循环中。LLM 首先对问题进行推理并生成行动计划。然后它执行计划中的行动并观察结果。LLM 接着使用观察结果来更新其推理并生成新的行动计划。这个过程持续进行,直到 LLM 找到问题的解决方案。

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

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

接下来让我们编写一些 Python 代码,任务是让 LLM 找出:Metallica 乐队中那位著名父亲有多少个孩子。

代码片段 1. 使用 LangChain 和 VertexAI 创建 ReAct 智能体

from langchain.agents import load_tools from langchain.agents import initialize_agent from langchain.agents import AgentType from langchain.llms import VertexAI prompt = "How many kids do the band members of Metallica have?" # 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)

代码片段 2 显示了结果。注意 ReAct 进行了五次搜索链。实际上,LLM 正在抓取 Google 搜索结果以找出乐队成员的名字。然后,它将结果列为观察结果,并将思考链用于下一次搜索。

代码片段 2. 在终端中执行 ReAct 智能体

> 进入新的 AgentExecutor 链...
思考:我需要找出 Metallica 乐队成员的名字,然后搜索每个成员有多少个孩子。
行动:搜索
行动输入:Metallica band members
观察:James Hetfield, Lars Ulrich, Kirk Hammett, Robert Trujillo
思考:Metallica 有 4 名成员。
行动:搜索
行动输入:How many kids does James Hetfield have? (James Hetfield 有多少个孩子?)
观察:三个孩子 (three children)
思考:1/4 的 Metallica 乐队成员有 3 个孩子
行动:搜索
行动输入:How many kids does Lars Ulrich have? (Lars Ulrich 有多少个孩子?)
观察:3
思考:2/4 的 Metallica 乐队成员总共有 3 + 3 = 6 个孩子
行动:搜索
行动输入:How many kids does Kirk Hammett have? (Kirk Hammett 有多少个孩子?)
观察:Hammett 自 1998 年以来与他的第二任妻子 Lani 结婚。他们有两个儿子,Angel(生于 2006 年 9 月 29 日)和 Vincenzo(生于 2008 年 6 月 28 日)。
思考:Kirk Hammett 有 2 个孩子。3/4 的 Metallica 乐队成员总共有 6 + 2 = 8 个孩子
行动:搜索
行动输入:How many kids does Robert Trujillo have? (Robert Trujillo 有多少个孩子?)
观察:2
思考:Robert Trujillo 有 2 个孩子。4/4 的 Metallica 乐队成员总共有 8 + 2 = 10 个孩子
最终答案:10

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

在实践中,ReAct 提示需要理解您必须不断地重新发送先前的提示/响应(并对额外生成的内容进行修剪),以及使用适当的示例/指令来设置模型。请参考托管在 GoogleCloudPlatform Github 仓库中的notebook¹⁴,它通过一个更详细的示例更深入地展示了实际的 LLM 输入和输出。

自动提示工程 (Automatic Prompt Engineering - APE)

此时您可能会意识到编写提示可能很复杂。自动化这个过程(编写一个提示来编写提示)岂不是很好?嗯,有一种方法:自动提示工程(Automatic Prompt Engineering - APE)¹⁵。这种方法不仅减轻了人类输入的需要,而且还提高了模型在各种任务中的性能。

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

例如,您可以使用自动提示工程来帮助训练一个用于销售乐队周边 T 恤网店的聊天机器人。我们想找出顾客可能用来表达购买乐队周边 T 恤订单的所有不同方式。

  1. 编写将生成输出变体的提示。在此示例中,我使用 gemini-pro 生成 10 条指令。见表 15

表 15. 使用 LLM 生成提示

部分内容
提示我们有一个乐队周边 T 恤网店,为了训练聊天机器人,我们需要多种表达方式来订购:“一件 S 码的 Metallica T 恤”。请生成 10 种变体,具有相同的语义但保持相同的含义。
输出1. 我想购买一件 S 码的 Metallica T 恤。
2. 我可以订购一件小号的 Metallica T 恤吗?
3. 我想买一件小号的 Metallica T 恤。
4. 一件 Metallica T 恤,小号,谢谢。
5. 我想要一件 S 码的 Metallica T 恤。
6. 我想下单订购一件小号的 Metallica T 恤。
7. 小号 Metallica T 恤,一件,谢谢。
8. 我在找一件小号的 Metallica T 恤。
9. 你能给我拿一件小号的 Metallica T 恤吗?
10. 一件 Metallica 小号 T 恤,谢谢。
  1. 通过根据选定的指标对候选指令进行评分来评估所有候选指令。例如,您可以使用 BLEU(双语评估替补)或 ROUGE(面向召回的要点评估替补)。
  2. 选择评估分数最高的候选指令。该候选指令将是您可以在软件应用程序或聊天机器人中使用的最终提示。您还可以调整选定的提示并再次评估。

代码提示 (Code Prompting)

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

编写代码的提示

Gemini 也可以扮演开发者的角色,帮助您用任何选择的编程语言编写代码。作为开发者,这可以帮助您加快编写代码的过程。

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

表 16. 使用 Gemini 编写代码

字段
名称bash_rename_files_in_folder
目标编写一个提示,用 Bash 编写代码来重命名文件夹中的文件。
模型gemini-pro
温度0.4
词元限制1024
Top-k不适用
Top-P1
提示编写一个 Bash 代码片段,它会询问文件夹名称。然后它获取该文件夹的内容,并通过在文件名
前加上名称 draft 来重命名所有文件。
输出```bash
#!/bin/bash

# 询问文件夹名称
echo "输入文件夹名称:"
read folder_name

# 检查文件夹是否存在
if [ ! -d "$folder_name" ]; then
echo "文件夹不存在。"
exit 1
fi

# 获取文件夹中的文件列表
files=( "$folder_name"/* )

# 通过在文件名
前加上“draft_”来重命名每个文件
for file in "${files[@]}"; do
# 在重命名之前检查它是否是一个文件
if [ -f "$file" ]; then
new_file_name="draft_$(basename "$file")"
mv "$file" "$folder_name/$new_file_name" # 修正了 mv 命令的目标目录
fi
done

echo "文件重命名成功。"
```

这对我来说似乎是不错的代码——它甚至还有注释!然而,由于 LLM 无法推理,并且会重复训练数据,因此首先阅读和测试您的代码至关重要。

我们都期待的时刻,它真的有效吗?

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

  1. 复制表 16 的输出(不包括 bash ... 文本包装),并将其粘贴到一个名为 rename_files.sh 的新文件中。
  2. 打开一个终端窗口并输入:. rename_files.sh。它会要求输入一个文件夹名称,例如 test,然后按回车键。
  3. 脚本似乎运行良好。您将看到消息:文件重命名成功。当您查看测试文件夹时,会注意到所有文件都完美地重命名为 draft_filename.txt

成功了!

解释代码的提示

作为一名在团队中工作的开发人员,您必须阅读他人的代码。Gemini 也可以在这方面帮助您。让我们 lấy 表 16 的代码输出,删除注释,然后要求大型语言模型解释发生了什么,见表 17

表 17. 解释代码的提示

字段
名称bash_explain_the_code
目标编写提示以解释 Bash 代码
模型gemini-pro
温度0.4
词元限制1024
Top-k不适用
Top-P1
提示请向我解释下面的 Bash 代码:

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> if [ -f "$file" ]; then<br> new_file_name="draft_$(basename "$file")"<br> mv "$file" "$folder_name/$new_file_name"<br> fi<br>done<br><br>echo "文件重命名成功。"<br>
输出这个 Bash 脚本执行以下任务:

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

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

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

4. 文件重命名
- 它使用 for 循环遍历 files 数组中的每个项目。
- 它使用 [ -f "$file" ] 检查该项目是否为常规文件。
- 如果是文件,它使用 new_file_name="draft_$(basename "$file")" 生成新的文件名。这个新文件名是通过在原始文件名(不带路径)前加上字符串“draft_”来创建的。
- 然后,它使用 mv "$file" "$folder_name/$new_file_name" 命令重命名文件,该命令将文件移动到同一文件夹内的新文件名。

5. 成功消息
- 重命名所有文件后,它会显示成功消息(“文件重命名成功。”)以指示重命名操作成功。

翻译代码的提示

表 16 中的 bash 代码似乎运行良好。然而,如果这个脚本能提示我输入文件名,它就会真正可重用,理想情况下,它应该作为一个带有 UI 的独立应用程序工作。作为起点,对于(Web)应用程序来说,Python 比 Bash 是更好的语言。LLM 可以帮助将代码从一种语言翻译成另一种语言。参见表 18 中的示例:

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

字段
名称_python_rename_files
目标编写一个提示,将 Bash 代码翻译成 Python
模型gemini-pro
温度0.4
词元限制1024
Top-k不适用
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> if [ -f "$file" ]; then<br> new_file_name="draft_$(basename "$file")"<br> mv "$file" "$folder_name/$new_file_name"<br> fi<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>items = os.listdir(folder_name)<br><br># 遍历项目<br>for item in items:<br> # 构建完整路径<br> old_path = os.path.join(folder_name, item)<br><br> # 在重命名之前检查它是否确实是一个文件<br> if os.path.isfile(old_path):<br> # 创建一个带有前缀 "draft_" 的新文件名<br> new_file_name = f"draft_{item}"<br> new_path = os.path.join(folder_name, new_file_name)<br><br> # 将文件移动到新名称<br> shutil.move(old_path, new_path)<br><br># 打印成功消息<br>print("文件重命名成功。")<br>

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

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

调试和审查代码的提示

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

代码片段 3. 一个损坏的 Python 脚本

import os import shutil folder_name = input("Enter the folder name: ") # 输入文件夹名称: prefix = input("Enter the string to prepend to the filename: ") # 输入要添加到文件名前的前缀字符串: text = toUpperCase(prefix) # 问题行 if not os.path.isdir(folder_name): # 原始片段中缩进似乎有误,进行修正 print("Folder does not exist.") # 文件夹不存在。 exit(1) files = os.listdir(folder_name) for file in files: # 构建完整路径以检查是否为文件 old_path = os.path.join(folder_name, file) if os.path.isfile(old_path): new_filename = f"{text}_{file}" # 使用大写前缀 new_path = os.path.join(folder_name, new_filename) shutil.move(old_path, new_path) # 原始片段中缩进似乎有误,进行修正 print("Files renamed successfully.") # 文件重命名成功。

啊!这看起来像个 bug:

代码片段 4. 我弄坏了 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 (名称错误:名称 'toUpperCase' 未定义)

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

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

部分内容
名称_python_debug_code
目标编写一个提示来调试和审查 Python 代码。
模型gemini-pro
温度0.4
词元限制1024
Top-k不适用
Top-P1
提示下面的 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

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

python<br>import os<br>import shutil<br><br>folder_name = input("Enter the folder name: ")<br>prefix = input("Enter the string to prepend to the filename: ")<br>text = toUpperCase(prefix)<br><br>if not os.path.isdir(folder_name):<br> print("Folder does not exist.")<br> exit(1)<br><br>files = os.listdir(folder_name)<br><br>for file in files:<br> old_path = os.path.join(folder_name, file)<br> if os.path.isfile(old_path):<br> new_filename = f"{text}_{file}"<br> new_path = os.path.join(folder_name, new_filename)<br> shutil.move(old_path, new_path)<br><br>print("Files renamed successfully.")<br>
输出错误 NameError: name 'toUpperCase' is not defined 发生是因为 Python 没有名为 toUpperCase 的内置函数。在 Python 中将字符串转换为大写的标准方法是使用字符串对象的 .upper() 方法。

要解决此问题,您应将以下行:
text = toUpperCase(prefix)
更改为:
text = prefix.upper()

以下是修正后的代码:

python<br>import os<br>import shutil<br><br># 从用户获取文件夹名称<br>folder_name = input("Enter the folder name: ")<br>prefix = input("Enter the string to prepend to the filename: ")<br>text = prefix.upper() # 修正行<br><br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print("Folder does not exist.")<br> exit(1)<br><br># 获取文件夹中所有项目的列表<br>files = os.listdir(folder_name)<br><br># 遍历项目<br>for file in files:<br> # 构建完整路径<br> old_path = os.path.join(folder_name, file)<br> # 在重命名之前检查它是否确实是一个文件<br> if os.path.isfile(old_path):<br> # 使用大写前缀创建一个新文件名<br> new_filename = f"{text}_{file}"<br> new_path = os.path.join(folder_name, new_filename)<br> # 将文件移动到新名称<br> shutil.move(old_path, new_path)<br><br># 打印成功消息<br>print("Files renamed successfully.")<br>

此外,以下是一些可以对代码进行的改进,以提高鲁棒性和清晰度:

1. 重命名错误处理: shutil.move 操作可能会失败(例如,由于权限问题或如果具有新名称的文件已存在)。将其包装在 try-except 块中是很好的做法。
2. 成功消息的清晰度: 成功消息在循环结束后打印,即使某些文件未能重命名。为每次成功重命名打印消息或在最后总结成功/失败可能会更好。
3. 处理空前缀: 考虑如果用户输入空前缀应该发生什么。
4. 检查目标文件是否存在: 您可能希望在尝试移动之前检查 new_path 是否已存在,以避免无意中覆盖文件,或明确处理它。

以下是包含错误处理的示例:

python<br>import os<br>import shutil<br><br># 从用户获取文件夹名称<br>folder_name = input("Enter the folder name: ")<br>prefix = input("Enter the string to prepend to the filename: ")<br>text = prefix.upper()<br><br># 检查文件夹是否存在<br>if not os.path.isdir(folder_name):<br> print(f"错误:文件夹 '{folder_name}' 不存在。")<br> exit(1)<br><br>print(f"正在使用前缀 '{text}_' 重命名 '{folder_name}' 中的文件...")<br>success_count = 0<br>fail_count = 0<br><br># 获取文件夹中所有项目的列表<br>try:<br> files = os.listdir(folder_name)<br>except OSError as e:<br> print(f"访问文件夹内容时出错:{e}")<br> exit(1)<br><br># 遍历项目<br>for file in files:<br> old_path = os.path.join(folder_name, file)<br><br> # 检查是否为文件<br> if os.path.isfile(old_path):<br> # 创建一个新文件名<br> new_filename = f"{text}_{file}"<br> new_path = os.path.join(folder_name, new_filename)<br><br> # 尝试移动文件<br> try:<br> # 可选:检查目标是否存在<br> # if os.path.exists(new_path):<br> # print(f"警告:目标文件 '{new_filename}' 已存在。跳过 '{file}'。")<br> # fail_count += 1<br> # continue <br> shutil.move(old_path, new_path)<br> # print(f"已将 '{file}' 重命名为 '{new_filename}'") # 可选:报告每次成功<br> success_count += 1<br> except Exception as e:<br> print(f"重命名文件 '{file}' 时出错:{e}")<br> fail_count += 1<br><br># 打印摘要消息<br>print(f"\n重命名完成。成功重命名 {success_count} 个文件。")<br>if fail_count > 0:<br> print(f"{fail_count} 个文件未能重命名或被跳过。")<br>

这些改进使代码更具鲁棒性,并向用户提供更好的反馈。

太棒了。它不仅告诉我如何解决问题,还找出了我的代码中存在的更多潜在问题以及如何解决它们。提示的最后一部分还提供了改进代码的通用建议。

多模态提示呢?(What about multimodal prompting?)

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

最佳实践 (Best Practices)

找到正确的提示需要反复试验。Vertex AI 中的 Language Studio 是一个完美的场所,可以用来尝试您的提示,并能够针对各种模型进行测试。

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

提供示例 (Provide examples)

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

保持简洁 (Be concise)

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

示例:

修改前:

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

重写后:

扮演游客的旅行向导。描述在纽约曼哈顿带 3 岁孩子参观的好地方。

尝试使用描述动作的动词。这是一组示例:

扮演 (Act)分析 (Analyze)分类 (Categorize)分类 (Classify)对比 (Contrast)比较 (Compare)创建 (Create)描述 (Describe)定义 (Define)评估 (Evaluate)提取 (Extract)查找 (Find)生成 (Generate)识别 (Identify)列出 (List)测量 (Measure)组织 (Organize)解析 (Parse)挑选 (Pick)预测 (Predict)提供 (Provide)排名 (Rank)推荐 (Recommend)返回 (Return)检索 (Retrieve)重写 (Rewrite)选择 (Select)展示 (Show)排序 (Sort)总结 (Summarize)翻译 (Translate)编写 (Write)

具体说明输出 (Be specific about the output)

具体说明期望的输出。简洁的指令可能不足以引导 LLM,或者可能过于笼统。在提示中提供具体细节(通过系统或上下文提示)可以帮助模型专注于相关内容,从而提高整体准确性。

示例:

推荐做法:

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

不推荐做法:

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

使用指令而非约束 (Use Instructions over Constraints)

指令和约束在提示中用于指导 LLM 的输出。

  • 指令 (instruction) 提供关于响应的期望格式、风格或内容的明确指示。它指导模型应该做什么或产生什么。
  • 约束 (constraint) 是对响应的一组限制或边界。它限制了模型不应该做什么或避免什么。

越来越多的研究表明,在提示中关注积极的指令可能比严重依赖约束更有效。这种方法与人类更喜欢积极指令而非“禁止做什么”列表的方式一致。

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

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

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

推荐做法:

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

不推荐做法:

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

作为最佳实践,首先优先考虑指令,清楚地说明您希望模型做什么,并且仅在为了安全、清晰或特定要求而必要时才使用约束。进行实验和迭代,测试指令和约束的不同组合,以找到最适合您特定任务的方法,并记录这些方法。

控制最大词元长度 (Control the max token length)

要控制生成的 LLM 响应的长度,您可以在配置中设置最大词元限制,或者在提示中明确请求特定长度。例如:

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

在提示中使用变量 (Use variables in prompts)

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

表 20. 在提示中使用变量

部分内容
变量{city} = "阿姆斯特丹"
提示你是一个旅行向导。告诉我一个关于城市 {city} 的事实。
输出阿姆斯特丹是一个美丽的城市,到处是运河、桥梁和狭窄的街道。因其丰富的历史、文化和夜生活而成为一个很棒的旅游目的地。

试验输入格式和写作风格 (Experiment with input formats and writing styles)

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

例如,一个旨在生成关于革命性视频游戏主机世嘉 Dreamcast 文本的提示,可以表述为一个问题、一个陈述或一个指令,从而导致不同的输出:

  • 问题: 世嘉 Dreamcast 是什么?为什么它是一款如此革命性的主机?
  • 陈述: 世嘉 Dreamcast 是世嘉于 1999 年发布的第六代视频游戏主机。它...
  • 指令: 编写一个段落,描述世嘉 Dreamcast 主机并解释为什么它如此具有革命性。

对于带分类任务的少样本提示,混合类别 (For few-shot prompting with classification tasks, mix up the classes)

一般来说,少样本示例的顺序不应有太大影响。然而,在进行分类任务时,请确保在少样本示例中混合可能的响应类别。这是因为您否则可能会对示例的特定顺序过拟合。通过混合可能的响应类别,您可以确保模型正在学习识别每个类别的关键特征,而不是仅仅记住示例的顺序。这将导致在未见过的数据上具有更鲁棒和可泛化的性能。

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

适应模型更新 (Adapt to model updates)

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

试验输出格式 (Experiment with output formats)

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

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

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

  • 始终以相同风格返回
  • 专注于您想要接收的数据
  • 减少幻觉的机会
  • 使其具有关系感知能力
  • 您可以获得数据类型
  • 您可以对其进行排序

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

JSON 修复 (JSON Repair)

虽然以 JSON 格式返回数据提供了许多优势,但也并非没有缺点。JSON 的结构化特性虽然有利于解析和在应用程序中使用,但比纯文本需要明显更多的词元,导致处理时间增加和成本更高。此外,JSON 的冗长性很容易耗尽整个输出窗口,当生成因词元限制而被突然截断时,这尤其成问题。这种截断通常会导致无效的 JSON,缺少关键的闭合花括号或方括号,使输出无法使用。幸运的是,像 json-repair 库(可在 PyPI 上获得)这样的工具在这种情况下可能非常宝贵。该库会智能地尝试自动修复不完整或格式错误的 JSON 对象,使其成为处理 LLM 生成的 JSON(尤其是在处理潜在截断问题时)的关键盟友。

使用模式 (Working with Schemas)

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

这里有一个简单的例子:

假设您想使用 LLM 为电子商务目录中的产品生成描述。与其仅仅提供产品的自由格式文本描述,不如使用 JSON 模式来定义产品的属性:

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

{ "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": "产品发布日期" } } }

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

代码片段 6. 给 LLM 的结构化输入

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

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

与其他提示工程师一起试验 (Experiment together with other prompt engineers)

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

CoT 最佳实践 (CoT Best practices)

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

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

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

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

记录各种提示尝试 (Document the various prompt attempts)

最后一个技巧在本章前面已经提到过,但我们怎么强调其重要性都不为过:详细记录您的提示尝试,以便您随着时间的推移了解哪些做得好,哪些做得不好。

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

我们建议创建一个 Google Sheet,以表 21 作为模板。这种方法的优点是,当您不可避免地需要重新审视您的提示工作时——无论是为了将来继续进行(您会惊讶于仅仅短暂休息后会忘记多少东西),还是为了在不同版本的模型上测试提示性能,以及帮助调试未来的错误——您都有完整的记录。

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

当在一个检索增强生成(RAG)系统上工作时,您还应该捕获影响哪些内容被插入到提示中的 RAG 系统的具体方面,包括查询、分块设置、分块输出和其他信息。

一旦您觉得提示接近完美,就将其应用到您的项目代码库中。在代码库中,将提示保存在与代码不同的单独文件中,以便更容易维护。最后,理想情况下,您的提示是一个可操作化系统的一部分,作为提示工程师,您应该依赖自动化测试和评估程序来了解您的提示在任务上的泛化程度如何。

提示工程是一个迭代的过程。制作并测试不同的提示,分析并记录结果。根据模型的性能优化您的提示。持续试验,直到达到期望的输出。当您更改模型或模型配置时,回头继续试验先前使用过的提示。

表 21. 记录提示的模板

部分内容
名称JSON 格式化器 v1.2
目标以一致的结构和语法正确格式化和修正 JSON 数据。
模型GPT-4-turbo (示例模型)
温度0.7 (示例值)
词元限制2048 (示例值)
Top-k50 (示例值)
Top-P0.9 (示例值)
提示请使用正确的语法、一致的引号和标准的缩进重新格式化并修正以下 JSON 数据:

{
"name": "Wireless Headphones",
"category": "Electronics",
"price": 99.99,
"features": ["Noise cancellation", "Bluetooth 5.0", "26-hour battery life"],
"release_date": "2023-10-27"
}
输出json<br>{<br> "name": "Wireless Headphones",<br> "category": "Electronics",<br> "price": 99.99,<br> "features": [<br> "Noise cancellation",<br> "Bluetooth 5.0",<br> "26-hour battery life"<br> ],<br> "release_date": "2023-10-27"<br>}<br>

所做修正:
1. 修正了 "name" 缺失的右引号
2. 将所有引号标准化为双引号
3. 修正了 "release_date" 键周围缺失的引号
4. 添加了正确的缩进(2 个空格)
5. 改进了数组格式以提高可读性
6. 在 "features" 数组后添加了缺失的逗号

总结 (Summary)

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

  • 零样本提示 (Zero prompting)
  • 少样本提示 (Few shot prompting)
  • 系统提示 (System prompting)
  • 角色提示 (Role prompting)
  • 上下文提示 (Contextual prompting)
  • 回退提示 (Step-back prompting)
  • 思维链 (Chain of thought)
  • 自洽性 (Self consistency)
  • 思维树 (Tree of thoughts)
  • ReAct

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

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

尾注 (Endnotes)

  1. Google, 2023, Gemini by Google. 见: https://gemini.google.com.
  2. Google, 2024, Gemini for Google Workspace Prompt Guide. 见: https://services.google.com/fh/files/helpcenter/prompt-guide-di-ed.html. (链接可能特定/内部,原始文本未提供完整 URL)
  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=3bq3jsveO1
  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/generative-ai/blob/main/language/prompts/examples/chain_of_thought_react.ipynb (注意: 与 10 链接相同,源文本似乎有意为之)
  15. Zhou, Y., et al, 2023, Automatic Prompt Engineering - Large Language Models are Human-Level Prompt Engineers. 见: https://arxiv.org/pdf/2211.01910.pdf.