《Prompt Engineering》提示词工程白皮书是Google团队成员联合推出的。主要内容包括如何设计高质量的提示(prompt)优化大型语言模型(LLM)的输出效果。白皮书详细介绍多种提示技术,如零样本提示(zero-shot)、单样本和少样本提示(one-shot/few-shot)、系统提示(system prompting)、角色提示(role prompting)和上下文提示(contextual prompting)等,探讨了模型输出配置(如温度、top-K、top-P等参数)对生成结果的影响,提供实际示例和最佳实践,帮助用户在不同场景下更有效地使用LLM。强调提示工程是一个迭代过程,需结合任务需求调整提示结构和模型参数,获得准确、相关的输出。
获取《Prompt Engineering》提示词工程白皮书 PDF原文件,扫码关注回复: 20250411
致谢
内容贡献者
迈克尔·谢尔曼
袁曹
埃里克·阿姆布鲁斯特
阿南特·纳瓦尔加里亚
安东尼奥·古利
西蒙·卡梅尔
编者
安东尼奥·古利
阿南特·纳瓦尔加里亚
格蕾丝·莫里森
技术作家
乔伊·海梅克
设计师
迈克尔·兰宁
简介
在大型语言模型的输入输出机制中,文本提示(有时会配合图像等多模态输入)是模型用于生成预测结果的基础输入。您无需成为数据科学家或机器学习工程师,任何人都可以编写提示词。但要想构建真正高效的提示词,这个过程可能相当复杂。提示词的效果受多重因素影响,所选模型版本、模型的训练数据、参数配置、措辞精准度、语言风格与语气、结构设计以及上下文关联性都至关重要。因此,提示词工程本质上是一个需要持续优化的过程。低质量的提示词不仅会导致模棱两可或错误的输出,更会限制模型生成有价值内容的能力。
当你与Gemini聊天机器人交流时,你实际上是在编写提示。不过本白皮书将重点探讨如何在Vertex AI平台或通过API为Gemini模型编写提示词,因为直接调用模型时,您将能访问温度参数(temperature)等完整配置项。
这份白皮书详细讨论了提示工程。我们将探讨各种提示技术,帮助你入门并分享成为提示专家的技巧和最佳实践。我们还将讨论设计提示时可能遇到的挑战。
提示工程
记住LLM的工作原理,它是一个预测引擎。模型接收序列文本作为输入,然后根据其训练数据预测下一个标记。LLM会反复执行此操作,将先前预测的标记添加到序列文本末尾以预测下一个标记。下一个标记的预测基于先前标记的内容与LLM在训练期间所见内容之间的关系。
编写提示时,你是在为LLM设置正确的标记序列。提示工程是设计高质量提示的过程,引导LLM生成准确的输出。这包括调整提示以找到最佳版本,优化提示长度,并评估提示的写作风格和结构是否与任务相关。在自然语言处理和LLM的背景下,提示是为模型提供的输入,用于生成响应或预测。
这些提示可用于完成各种理解和生成任务,如文本摘要、信息提取、问答、文本分类、语言或代码翻译、代码生成以及代码文档或推理。
请随时参考Google的提示指南,其中包含简单有效的提示示例。
进行提示工程时,首先需要选择一个模型。无论你使用Vertex AI中的Gemini语言模型、GPT、Claude,还是像Gemma或LLaMA这样的开源模型,提示可能需要针对你的特定模型进行优化。
除了提示外,你还需要调整LLM的各种配置。
LLM输出配置
选择模型后,你需要确定模型的配置。大多数LLM提供多种配置选项来控制输出。有效的提示工程需要根据任务优化这些设置。
输出长度
一个重要的配置参数是控制生成响应中的token数量。生成更多token需要大语言模型进行更多计算,从而导致能耗增加、响应时间可能变慢以及成本上升。
减少LLM的输出长度并不会使LLM在输出内容上变得更加简洁或风格化,它只是让LLM在达到长度限制时停止继续预测token。如果您的需求要求输出较短,您可能还需要对提示词进行专门设计来满足要求。
输出长度限制对于某些LLM提示技术尤为重要,比如ReAct,LLM可能会在您想要的响应之后继续生成无用的token。
采样控制
LLM不会预测单个标记,而是预测下一个标记的概率分布。温度、Top-K和Top-P是最常见的配置选项,用于决定如何从预测的标记概率中选择输出标记。
- 温度
温度参数控制token选择的随机程度。较低温度适合需要确定性输出的提示,而较高温度可能产生更多样化或出人意料的结果。温度为0(贪婪解码)时是完全确定性的:总是选择概率最高的token(但需注意,若两个token具有相同的最高预测概率,根据平局处理机制的不同,温度设为0时输出也可能不一致)
温度接近最大值时,输出往往更加随机。随着温度不断升高,所有token被选为下一个预测token的概率会趋于均等。
Gemini温度控制机制与机器学习中使用的softmax函数原理相似,低温设置类似于softmax低温(T),强调单一优选结果,确定性高。高温设置类似于softmax高温,接受更宽泛的结果范围 这种灵活性特别适用于不需要严格精确输出的场景(例如创意内容生成实验)。
- Top-K与Top-P采样
Top-K和Top-P(又称核采样)是LLMs中用于限制预测token范围的两种采样设置,与温度参数类似,它们控制生成文本的随机性和多样性。
- Top-K采样从模型预测分布中选择概率最高的K个token。K值越大,输出越具创造性,K值越小,输出越保守准确,K=1时等同于贪婪解码。
- Top-P采样选择累计概率不超过设定值(P)的最高概率token集合。P值范围,0(贪婪解码)到1(包含所有vocabulary token)。
最佳实践是通过实验比较两种方法(或组合使用),根据实际需求选择最优方案。
整合一切
在top-K、top-P、temperature和要生成的token数量之间进行选择取决于具体应用和预期结果,这些设置都会相互影响。同时,确保您理解所选模型如何将不同的采样设置组合在一起也很重要。
如果temperature、top-K和top-P都可用(如在Vertex Studio中),同时满足top-K和top-P标准的token将成为下一个预测token的候选,然后应用temperature从这些通过top-K和top-P标准的token中进行采样。如果只有top-K或top-P可用,行为相同但仅使用其中一个top-K或top-P设置。
如果temperature不可用,则从满足top-K和/或top-P标准的token中随机选择以生成单个下一个预测token。
当某个采样配置值设为极端值时,该采样设置要么会抵消其他配置设置,要么变得无关紧要。
- 如果你将温度设置为 0,top‑K 和 top‑P 就变得无关紧要了,最可能的标记将成为下一个预测的标记。如果你将温度设置得非常高(超过 1— 通常在 10 以上),温度就变得无关紧要了,然后随机采样通过 top‑K 和 / 或 top‑P 标准的标记来选择下一个预测的标记。
- 如果你将 top‑K 设置为 1,温度和 top‑P 就变得无关紧要了。只有一个标记通过了 top‑K 标准,并且这个标记就是下一个预测的标记。如果你将 top‑K 设置得非常高,比如达到 LLM 词汇表的大小,任何有非零概率成为下一个标记的标记都将满足 top‑K 标准,并且没有任何标记被选中。
- 如果你将 top‑P 设置为 0 (或一个非常小的值),大多数 LLM 采样实现将只考虑最可能的标记来满足 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 和输出令牌),LLM 可能会生成与主题关联度较低的文字。
警告:您是否见过以大量填充词结尾的响应?这也被称为”重复循环错误”,这是大语言模型中的一个常见问题。当模型陷入循环时,会反复生成相同的(填充)单词、短语或句子结构,这种情况通常因不恰当的temperature和top-k/top-p设置而加剧。这种现象可能出现在低temperature和高temperature两种设置下,但原因不同,在低temperature时,模型变得过于确定,严格遵循最高概率路径,如果该路径重新访问之前生成的文本,就可能导致循环。在高temperature时,模型的输出变得过于随机,由于可选选项众多,随机选择的单词或短语可能偶然回到之前的状态,从而形成循环。在这两种情况下,模型的采样过程都会”卡住”,产生单调无用的输出,直到填满输出窗口。解决这个问题通常需要仔细调整temperature和top-k/top-p值,以在确定性和随机性之间找到最佳平衡。
提示技术
大语言模型(LLMs)经过专门调优以遵循指令,并通过海量数据训练使其能够理解提示词并生成回答。但LLMs并非完美无缺。您的提示文本越清晰,模型就越能准确预测后续文本。此外,充分利用LLMs的训练机制和运作原理的特定技巧,将帮助您从模型中获得更精准的相关结果。
现在我们已经了解了什么是提示工程以及它需要什么,让我们深入探讨一些重要的提示技术示例。
通用提示 / 零样本
零样本提示是最简单的提示类型。它仅提供任务描述和供LLM开始处理的基础文本。这种输入可以是任何内容:一个问题、故事开头或指令。”零样本”这一名称代表”无示例”的含义。
让我们使用Vertex AI中的Vertex AI Studio(语言版),它提供了一个测试提示词的实验环境。在表1中,您将看到一个用于电影评论分类的零样本提示词示例。
如下所示的表格格式是记录提示词的绝佳方式。您的提示词在最终进入代码库之前可能会经历多次迭代,因此以规范、结构化的方式跟踪提示词工程工作非常重要。关于这种表格格式、跟踪提示词工程工作的重要性以及提示词开发流程的更多内容,请参阅本章后面的”最佳实践”部分(”记录各种提示词尝试”)。
因为不需要创造性输出,将模型温度设置为较低数值,我们使用gemini-pro默认的top-K和top-P值,这实际上禁用了这两个设置(参见前文的”LLM输出配置”)。请注意生成的输出结果。单词”disturbing”和”masterpiece”会使预测变得稍微复杂一些,因为这两个词出现在同一个句子中。
目标 | 将电影评论分类为正面、中性或负面 |
---|---|
模型 | gemini-pro |
温度 | 0.1 |
提示 | 将电影评论分类为POSITIVE、NEUTRAL或NEGATIVE。评论:“《她》是一部令人不安的研究,揭示了如果AI继续无限制发展,人类将走向何方。我希望有更多这样的杰作。”情感: |
输出 | POSITIVE |
表 1. 零样本提示示例
当零样本(zero-shot)方法无效时,您可以在提示词中提供示范案例,从而采用”单样本(one-shot)”或”少样本(few-shot)”提示技术。
单样本 & 少样本
在为 AI 模型创建提示时,提供示例是有帮助的。这些示例可以帮助模型理解你要求的内容。当你想引导模型到一个特定的输出结构或模式时,示例特别有用。
单样本提示提供了一个 示例,因此得名单样本。其理念是模型有一个可以模仿以最好完成任务的示例。
少样本提示提供了多个示例给模型。这种方法向模型展示了它需要遵循的模式。理念与单样本类似,但提供多个目标模式的示例增加了模型遵循该模式的可能性。
少样本提示(few-shot prompting)所需示例数量取决于几个因素,包括任务复杂性、示例质量以及所使用的生成式AI(gen AI)模型的能力。一般来说,您应该至少使用三个到五个示例进行少量样本提示。然而,对于更复杂的任务,您可能需要使用更多的示例,或者由于模型输入长度限制,您可能需要使用更少的示例。
表2展示了一个少样本提示(few-shot prompt)的示例。我们将继续使用之前相同的gemini-pro模型配置参数,但需要增加token限额以适应生成长度更大的响应需求。
目标 | 将披萨订单解析为JSON |
---|---|
提示 | 示例:我想要一个小披萨,加奶酪、番茄酱和意大利辣香肠。JSON响应:{ “size”:”small”, “type”:”normal”, “ingredients”:[“cheese”,”tomato sauce”,”pepperoni”] } |
输出 | { “size”:”large”, “type”:”half-half”, “ingredients”:[[“cheese”,”mozzarella”],[“tomato sauce”,”ham”,”pineapple”]] } |
表2.少样本提示示例
在选择提示词示例时,应使用与您要执行的任务相关的示例。这些示例应当具备多样性、高质量且表述规范。即使是一个小错误也可能使模型产生混淆,从而导致不理想的输出结果。
如果您需要生成能够应对各种输入的稳健输出,则必须在示例中包含边缘案例(edge cases)。边缘案例指那些不常见或意料之外的输入情况,但模型仍应能够正确处理这些情况。
系统、上下文和角色提示
系统、上下文和角色提示都是用于指导 LLM 生成文本的技术,但它们关注不同的方面:
- 系统提示(System prompting)为语言模型设定整体上下文和目的。它定义了模型应该执行的”大局”任务,如翻译语言、分类评论等。
- 上下文提示(Contextual prompting)提供与当前对话或任务相关的具体细节或背景信息。它帮助模型理解所提要求的细微差别,并相应调整回答。
- 角色提示(Role prompting)为语言模型指定特定的角色或身份。这有助于模型生成与所分配角色及其相关知识和行为一致的响应。
系统、上下文和角色提示之间可能存在相当大的重叠。例如,一个为系统分配角色的提示也可以包含上下文。每种提示类型的主要目的略有不同:
- 系统提示:定义模型的基本能力和总体目标。
- 上下文提示:提供即时的、特定任务的信息来指导响应。它是高度特定于当前任务或输入的,具有动态性。
- 角色提示:塑造模型的输出风格和语气。它增加了特定性和个性层面。
区分系统提示、上下文提示和角色提示为设计具有明确意图的提示词提供了一个框架,允许灵活组合,并更容易分析每种提示类型如何影响语言模型的输出。
- 系统提示
表3包含一个系统提示,其中我额外指定了如何返回输出的相关信息。我提高了温度参数以获得更高的创造力水平,并指定了更高的token限制。然而,由于我对输出返回方式的明确指令,模型没有返回额外文本。
目标 | 将电影评论分类为正面、中性或负面。 |
---|---|
模型 | gemini-pro |
温度 | 1 令牌限制 5 |
Top-K | 40 |
Top-P | 0.8 |
提示 | Classify movie reviews as positive, neutral or negative. Only return the label in uppercase. Review: “Her” is a disturbing study revealing the direction humanity is headed if AI is allowed to keep evolving, unchecked. It’s so disturbing I couldn’t watch it. Sentiment: |
输出 | 否定 |
表 3. 系统提示的示例
系统提示对于生成满足特定要求的输出非常有用。‘ 系统提示 ’ 这个名字实际上代表 ‘ 向系统提供额外任务 ’。例如,您可以使用系统提示生成与特定编程语言兼容的代码片段,或者您可以使用系统提示返回一个清晰的框架。请看表 4,我在其中以 JSON 格式返回了输出。
Name | Content |
---|---|
目标 | 将电影评论分类为正面、中性或负面,返回 JSON。 |
模型 | gemini-pro |
温度 | 1 |
Top-K | 40 |
Token Limit | 1024 |
Top-P | 0.8 |
提示 |
Classify movie reviews as positive, neutral or negative. Return valid JSON: Review: “Her” is a disturbing study revealing the direction humanity is headed if AI is allowed to keep evolving, unchecked. It’s so disturbing I couldn’t watch it. Schema: “` MOVIE: { “sentiment”: String “POSITIVE” | “NEGATIVE” | “NEUTRAL”, “name”: String } MOVIE REVIEWS: { “movie_reviews”: [MOVIE] } “` JSON Response: |
输出 |
“` { “movie_reviews”: [ { “sentiment”: “NEGATIVE”, “name”: “Her” } ] } “` |
表 4. 使用 JSON 格式的系统提示示例
从提示词中返回JSON对象提取数据有以下优势,在实际应用中,我不需要手动创建JSON格式,可以直接返回排序好的数据(在处理datetime对象时非常方便)。最重要的是,通过要求JSON格式,可以强制模型创建结构化输出并限制幻觉现象。
系统提示词在安全性和内容过滤方面也非常有用。要控制输出,只需在提示词中添加额外指令,例如:”回答时应保持尊重态度”。
- 角色提示
角色提示(Role prompting)是提示工程中的一种技术,涉及为生成式AI模型分配特定角色。这有助于模型生成更相关和信息丰富的输出,因为模型可以根据被分配的角色来定制其响应。
例如,您可以让生成式AI模型扮演图书编辑、幼儿园教师或励志演讲者的角色。一旦模型被分配了角色,您就可以给出与该角色相关的特定提示。例如,您可以提示教师创建一个可供他们审阅的教案。请参阅表5,其中模型扮演了旅行指南的角色。
参数/内容 | 详细信息 |
---|---|
目标 | 扮演旅行指南并提供 3 个旅行建议 |
模型 | Gemini Pro |
温度 | 1 |
Top-K | 40 |
Token 限制 | 1024 |
Top-P | 0.8 |
提示 | I want you to act as a travel guide. I will write to you about my location and you will suggest 3 places to visit near me. In some cases, I will also give you the type of places I am on: “I am in Amsterdam and I want to visit only museums.” |
输出 | 旅行建议: 1. 荷兰皇家博物馆:世界著名博物馆,以荷兰大师作品而闻名,类似于伦勃朗的《夜巡》。不要错过令人难以置信的收藏。画作和展示荷兰艺术与历史的互动事实。2. 梵高博物馆:沉浸在文森特的迷人作品之中。该博物馆收藏了他最大规模的画作和绘图,包括《星夜》和《向日葵》。3. 阿姆斯特丹市立博物馆:探索现代与当代艺术,来自世界各地。博物馆的藏品包括毕加索的作品,康定斯基和里特维尔德的作品,收藏在一座引人注目的现代建筑中。 |
表 5. 角色提示的示例
以上示例展示了让AI担任旅行代理角色的情景。当您将角色改为地理教师时,会注意到获得的响应将有所不同。
为AI模型定义角色视角,相当于为其提供了关于语气、风格和专业领域的蓝图,从而提升输出质量、相关性和有效性。
以下是一些您可以选择的样式,我认为它们很有效:对抗性、描述性、直接性、正式性、幽默性、影响力、非正式性、激励性、说服性。
将表 6 中的提示更改为包括幽默和启发性的风格。
提示 | I want you to act as a travel guide. I will write to you about my location and you will suggest 3 places to visit near me in a humorous style.
My suggestion: “I am in Manhattan.” Travel Suggestions: |
---|---|
输出 | 1. 帝国大厦:感受“金刚”般的视角(但没有巨型香蕉)。2. 现代艺术博物馆:质疑自己的简笔画艺术价值。3. 第五大道:让钱包哭泣的购物体验。 |
表 6. 具有幽默语气和风格的示例角色提示
- 上下文提示
通过提供上下文提示(Contextual Prompts),您可以使AI交互更加流畅高效。如表7示例所示,该技术能让模型更快理解请求,并生成更准确相关的响应。
目标 | 为关于复古游戏的博客提出一些文章建议 |
---|---|
模型 | Gemini Pro |
温度 | 1 |
Top-K | 40 |
Token 限制 | 1024 |
Top-P | 0.8 |
提示 | Context: You are writing for a blog about retro 80’s arcade video games. Suggest 3 topics to write an article about with a few lines of description of what this article should contain. |
输出 | 1. 街机柜设计的发展:这篇文章将探讨街机柜设计的发展,从20世纪70年代的早期木制和金属柜到光滑、霓虹灯照亮的现代设计。20世纪80年代及以后。2. 怀旧经典:80年代的标志性街机游戏:这篇文章将带您回顾一些最具标志性和影响力的80年代街机游戏的历史、影响和遗产,其中包括一些最具标志性和影响力的80年代街机游戏,突出它们的创新、流行机制和持久的魅力。3. 像素艺术的崛起与复古复兴:本文将深入探讨像素艺术作为定义视觉的演变过程追溯早期街机游戏风格的根源,探讨其技术,并讨论像素艺术在现代游戏和数字艺术中的复兴。 |
表 7. 上下文提示的一个示例
回溯提示
回溯提示是一种通过提示大语言模型(LLM)先思考与当前具体任务相关的普遍性问题,然后将该普遍性问题的答案输入到后续具体任务提示中,从而提高性能的技术。这种回溯步骤能让LLM在尝试解决具体问题前,激活相关的背景知识和推理过程。
通过考虑更广泛和根本的原则,LLM能生成更准确和富有洞察力的响应。回溯提示鼓励LLM进行批判性思考,并以新颖创造性的方式应用其知识。相比直接提示LLM执行任务,该技术通过利用LLM参数中更多未被调用的知识,改变了最终执行任务的提示方式。
回溯提示通过聚焦普遍原则而非具体细节,有助于减轻LLM响应中的偏见。
让我们通过示例理解回溯提示如何改善结果。首先查看传统提示(表8),再与回溯提示(表9)进行对比。
目标 | Write a storyline for a level of a first-person shooter video game. |
---|---|
模型 |
gemini-pro |
温度 | 1 |
Token 限制 | 1024 |
Top-K | 40 |
Top-P | 0.8 |
提示 | Write a one paragraph storyline for a new level of a first-person shooter video game that is challenging and engaging. |
输出 | 关卡开始时,玩家小队在密集的城区遭到敌对势力的伏击。玩家必须穿越错综复杂的后巷和破败建筑群,运用潜行战术和精准射击消灭敌军并避免暴露。玩家需巧妙利用环境优势——设置陷阱、寻找掩体、精心策划每一步行动以求生存。途中获取的情报显示敌人正在策划毁灭性袭击,玩家必须争分夺秒收集证据,赶在敌方行动前将情报传回总部。 |
表 8. 在我们将它与回退提示进行比较之前的一个传统提示。
当温度参数设为1时,您可能会获得各种富有创意的故事情节,但输出结果往往过于随机且缺乏独特性。因此,我们采用回退式思考:
提示 | Based on popular first-person shooter action games, what are 5 fictional key settings that contribute to a challenging and engaging level storyline in a first-person shooter video game? |
---|---|
输出 |
1. 废弃军事基地:一个广阔的末日军事综合体爬满了变异士兵和流氓机器人,非常适合挑战重新装备战斗2. 赛博朋克城市:一个霓虹灯闪烁的未来城市环境,有高耸的摩天大楼和密集的巷道拥有电子增强的敌人以及黑客机制。3. 外星飞船:一艘庞大的外星飞船在地球上搁浅,带有令人毛骨悚然的走廊、零重力区域以及可以遭遇的外星生物。4. 僵尸横行的城镇:一个被成群结队的僵尸占领的荒凉城镇,有激烈的近距离战斗和解决谜题以找到安全通道。5. 水下研究设施:一个充满水的深海实验室,充满了变异的水生生物,并且需要潜水和水下探索技能才能生存。 |
表 9. 自洽性提示的一个示例
确实,这些主题非常适合开发第一人称视角游戏。现在让我们回到原始提示词,但这次将”回溯思考”得出的答案作为上下文信息加入,观察模型的输出变化。
提示 |
Context: 5 engaging themes for a first person shooter video game:
Take one of the themes and write a one paragraph storyline for a new level of a first-person shooter video game that is challenging and engaging. |
---|---|
输出 | 在一片幽暗的深渊深处,坐落着一座破败的水下研究设施,它见证了人类的雄心壮志及其带来的灾难性后果。这里被黑暗笼罩,充斥着故障机器的嗡嗡声,还回荡着溺亡者的幽灵般的回响。如今,这座设施已成为深海噩梦的滋生地。玩家是一名身着先进潜水装备、手持实验性武器的精英潜水员,肩负着深入这片恐怖水下世界的重任。凭借坚韧不拔的毅力和机智,他们必须穿越危险重重的走廊,解开神秘的谜题,并与潜伏在深处的可怕海怪展开殊死搏斗。从应对深海的巨大压力,到智胜狡猾的水下掠食者,这片未知的水下世界中的每一刻都在考验着人类的极限耐力和勇气。 |
表 10. 自洽性提示的一个示例
这个游戏概念看起来很有趣!通过运用回溯提示技术(step-back prompting),您可以显著提升提示词的精准度。
思维链( CoT )
思维链(Chain of Thought,简称CoT)是一种通过生成中间推理步骤来提高大型语言模型(LLM)推理能力的技术。这有助于LLM生成更准确的答案。你可以将其与少量示例提示(few-shot prompting)结合使用,以在需要推理才能响应的更复杂任务上获得更好的结果,因为这是零次示例(zero-shot)思维链的挑战。
CoT有很多优点。首先,它在低努力的情况下非常有效,并且与现成的LLM(因此无需微调)配合得很好。你还可以通过CoT提示获得可解释性,因为你可以从LLM的响应中学习并看到所遵循的推理步骤。如果出现故障,你将能够识别它。思维链似乎在不同LLM版本之间移动时提高了鲁棒性。这意味着你的提示在不同LLM之间的性能变化应该比不使用推理链的提示要小。当然,也有一些缺点,但它们是相当直观的。
LLM的响应包括思维链推理,这意味着更多的输出标记,这意味着预测成本更高,耗时更长。
为了解释表11中的以下示例,让我们首先尝试创建一个不使用CoT提示的提示,以展示大型语言模型的缺陷。
提示 | When I was 3 years old, my partner was 3 times my age. Now, I am 20 years old. How old is my partner? |
输出 | 63岁 |
表 11. 一个尝试解决数学问题的提示示例
显然是错误的答案。事实上,大型语言模型在数学任务上往往表现不佳,可能给出错误的答案 ,即使是像乘法这样简单的任务。是因为它们是在大量文本上训练的,而数学可能需要不同的方法。那么,让我们看看中间推理步骤是否会改善输出。
提示 | When I was 3 years old, my partner was 3 times my age. Now, I am 20 years old. How old is my partner? Let’s think step by step. |
输出 | 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. 思维链提示的示例
现在最终答案是正确的。是因为我们明确指示了大语言模型(LLM)解释每个步骤,而不仅仅是返回答案。有趣的是,模型采用了将17个增加的年份相加的方式(17+3=20)。而我的思维方式是:先计算伴侣与我之间的年龄差,然后再相加(20+(9-3))。让我们帮助模型更贴近我的思考方式。
表 12 是一个 ‘ 零样本 ’ 思维链的例子。当与单样本或少量样本结合使用时,思维链提示可以非常强大,正如你在表 13 中看到的那样
提示 | Q: When my brother was 2 years old, I was double his age. Now I am 40 years old. How old is my brother? Let’s think step by step.
A: When my brother was 2 years, I was 2 * 2 = 4 years old.That’s an age difference of 2 years and I am older. Now I am 40 years old, so my brother is 40 – 2 = 38 years old. The answer is 38. Q: When I was 3 years old, my partner was 3 times my age. Now,I am 20 years old. How old is my partner? Let’s think step by step. A: |
输出 | 当我 3 岁的时候,我的伴侣是3 * 3 = 9岁。这是一个年龄相差 6 年,我的伴侣比我大。现在我 20 岁了,我的伴侣现在是 26 岁。答案是 26。 |
表 13. 单次提示的思维链示例
思维链(Chain of Thought,CoT)可用于多种应用场景。例如在代码生成中,将需求分解为多个步骤,并将这些步骤映射到特定的代码行。或者在创建合成数据时,基于类似”产品名为XYZ”这样的种子信息,编写引导模型根据给定产品标题做出假设的说明描述。一般来说,任何可以通过”分步阐述”来解决的任务都适合使用思维链。如果您能解释解决问题的步骤,就可以尝试使用思维链方法。
请参考GoogleCloudPlatform Github仓库中的notebook10,该文档将详细讲解思维链提示技术。
在本章的最佳实践部分,我们将学习一些特定于思维链提示的最佳实践。
自洽性
大语言模型(LLM)虽然在各种NLP任务中取得了显著成功,但其推理能力仍被视为一个无法仅通过扩大模型规模来克服的局限。正如我们在前文思维链提示(Chain of Thought prompting)部分所学,可以通过提示让模型像人类解决问题一样生成推理步骤。然而,CoT使用的是简单的”贪婪解码”(greedy decoding)策略,限制了其效果。自洽性方法(Self-consistency)结合了采样和多数表决机制,通过生成多样化的推理路径并选择最一致的答案,提高了LLM生成响应的准确性和连贯性。
自洽性方法通过以下步骤实现:
- 生成多样化推理路径:向LLM多次提供相同的提示,通过设置较高的温度参数促使模型针对问题生成不同的推理路径和视角。
- 从每个生成的响应中提取答案。
- 选择出现频率最高的答案。
让我们看一个邮件分类系统的例子,该系统需要将邮件分类为”重要”或”不重要”。我们会多次向LLM发送零样本思维链提示,观察每次提交后的响应是否不同。注意邮件中使用的友好语气、措辞选择和讽刺表达,这些都可能会误导LLM。
您可以使用上述提示词测试其是否返回一致的分类结果。根据所使用的模型及温度参数配置,系统可能返回”IMPORTANT”或”NOT IMPORTANT”两种判定。
通过生成多个思维链(Chains of Thoughts)并选择最常出现的答案(”IMPORTANT”),我们可以从大语言模型(LLM)获得更一致且正确的答案。
这个例子展示了自洽性提示(self-consistency prompting)如何通过考虑多个视角并选择最一致的答案,来提高LLM响应的准确性。
思维树(ToT)
现在我们熟悉了思维链和自洽提示,让我们回顾一下思维树(ToT)。它推广了思维链提示的概念,因为它允许 LLM 同时探索多个不同的推理路径,而不仅仅是遵循单一的线性思维链。这如图 1 所示。
图 1. 左侧为链式思维提示的可视化,右侧为思维树提示的树状图
这种方法使 ToT 特别适合需要探索的复杂任务。它通过维护一个思维树来实现,其中每个思维代表一个连贯的语言序列,作为解决问题的一个中间步骤。然后,模型可以通过从树的不同节点分支出来探索不同的推理路径。
有一个很好的笔记,详细地介绍了思维树(Tree of Thought, ToT)方法,该方法基于论文《大语言模型引导的思维树》(Large Language Model Guided Tree-of-Thought)。
ReAct (推理与行动)
推理与行动(ReAct)提示是一种范式,使大语言模型(LLM)能够通过结合自然语言推理和外部工具(搜索、代码解释器等)来解决复杂任务,允许LLM执行某些操作,例如与外部API交互以检索信息,这是实现智能体建模的第一步。
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的成员?
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?"
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执行了五次连续的搜索。实际上,LLM通过抓取Google搜索结果来识别乐队名称,然后将结果列为观察项,并为下一次搜索串联思考过程。
> Entering new AgentExecutor chain...
Metallica has 4 members.
Action: Search
Action Input: How many kids does James Hetfield have?
Observation: three children
Thought: 1/4 Metallica band members have 3 children
Action: Search
Action Input: How many kids does Lars Ulrich have?
Observation: 3
Thought: 2/4 Metallica band members have 6 children
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 band members have 8 children
Action: Search
Action Input: How many kids does Robert Trujillo have?
Observation: 2
Thought: 4/4 Metallica band members have 10 children
Final Answer: 18
代码片段 2. 在终端中执行 ReAct 代理
代码片段2首先确定乐队Metallica有四名成员,随后通过搜索每位成员获取其子女数量并进行累加,最终返回子女总数作为答案。
在实际应用中,ReAct提示需要持续重新发送先前的提示/响应(需对额外生成内容进行修剪),为模型配置适当的示例和指令。
详细实现方法可参考GoogleCloudPlatform Github仓库中的notebook14文档,其中通过更完整的示例展示了LLM的实际输入输出过程。
自动提示工程
此时您可能已经意识到,编写提示词可能相当复杂。如果能自动完成这个工作(编写能生成提示词的提示词)不是很好吗?实际上确实存在这样的方法,自动提示工程(APE)。这种方法不仅能减少人工输入的需求,还能提升模型在各种任务中的表现。
您需要让模型生成更多提示词。评估这些提示词,对效果好的进行修改。然后重复这个过程。
例如,在开发周边T恤网店聊天机器人时,可以使用自动提示工程技术来收集客户购买乐队周边T恤的各种可能表达方式。具体实施步骤如下:
- 编写将生成输出变体的提示。在这个例子中,我使用 gemini‑pro 生成 10 条指令。见表 15:
提示 | We have a band merchandise t-shirt webshop, and to train a chatbot we need various ways to order: “One Metallica t-shirt size S”. Generate 10 variants, with the same semantics but keep the same meaning. |
输出 |
|
表 15. 使用 LLM 生成提示
- 通过选择指标对所有的指令候选者进行评分评估,例如,你可以使用 BLEU (双语评估助手)或 ROUGE (面向摘要评估的召回辅助者)。
- 选择评分最高的指令候选者。这个候选者将成为你可以在软件应用或聊天机器人中使用的最终提示。你还可以调整所选提示并再次评估。
代码提示
Gemini主要专注于基于文本的提示词,其中也包括用于返回代码的提示词编写。让我们进入Vertex AI Studio测试这些提示词,查看一些代码示例。
- 编写代码提示
Gemini也可以充当开发者的角色,帮助您用任意选择的编程语言编写代码。作为开发者,这可以加速您的代码编写过程。
想象一下,您的机器上有一个包含数百个文件的文件夹需要重命名。逐个重命名文件会耗费大量时间。您了解一些Bash命令,可以编写脚本来实现自动化,但这可能也需要一些时间。因此,让我们编写一个提示词。您可以在公开的Gemini聊天机器人中编写提示词,或者如果您更关注保密性,可以在Google Cloud账户中打开Vertex AI Studio编写这些提示词。Vertex AI Studio的优势在于您可以配置温度等参数。
Name | 1.bash_rename_files_in_folder |
---|---|
目标 | 编写一个提示词,要求生成用于重命名文件夹内文件的Bash脚本代码。 |
模型 | gemini-pro |
温度 | 0.1 |
Token 限制 | 1024 |
Top-K | N/A |
Top-P | 1 |
提示 | Write a code snippet in Bash, which asks for a folder name. Then it takes the contents of the folder and renames all the files inside by prepending the name draft to the file name. |
输出 |
“`bash #!/bin/bash # Ask for the folder name echo “Enter the folder name: “ read folder_name # Check if the folder exists if [ ! -d “$folder_name” ]; then echo “Folder does not exist.” exit 1 fi # Get the list of files in the folder files=( “$folder_name”/* ) # Rename each file by prepending “draft” to the file name for file in “${files[@]}”; do new_file_name=”draft_$(basename “$file”)” mv “$file” “$new_file_name” done echo “Files renamed successfully.” “` |
表16:用Gemini 编写代码
这段代码看起来不错。甚至还有注释!不过由于大语言模型不具备真正的推理能力,且会重复训练数据,因此务必先仔细阅读并测试你的代码。
让我们尝试使用一个只包含几个文件的测试文件夹,这些文件需要从 lename.txt 重命名为dra_lename.txt。
- 复制表 16 的输出(不包括 “`bash “` 文本包装器),并将其粘贴到名为 “rename_ les.sh” 的新文件中。
- 打开一个终端窗口,输入:. rename_ les.sh。它会要求输入文件夹名称,例如 test. 然后按回车键。
- 脚本运行正常。您将看到消息:文件重命名成功。当您查看测试文件夹时,请注意所有文件都已完全重命名为draft_filename.txt.
- 解释代码提示
作为开发者,在团队协作中经常需要阅读他人编写的代码。Gemini同样能在这方面为您提供帮助。我们以表16的代码输出为例,先移除其中的注释,然后让大语言模型解释代码逻辑,见表17:
Name | 1.bash_explain_the_code |
---|---|
目标 | 编写解释 Bash 代码的提示 |
模型 | gemini-pro |
温度 | 0.1 |
Token 限制 | 1024 |
Top-K | N/A |
Top-P | 1 |
提示 |
Explain to me the below Bash code: “` #!/bin/bash echo “Enter the folder name: “ read folder_name if [ ! -d “$folder_name” ]; then echo “Folder does not exist.” exit 1 fi files=( “$folder_name”/* ) for file in “${files[@]}”; do new_file_name=”draft_$(basename “$file”)” mv “$file” “$new_file_name” done echo “Files renamed successfully.” “` |
输出 |
该Bash脚本执行以下操作:
|
表 17. 解释代码的提示
- 翻译代码提示
表16中的Bash代码看起来运行良好。但如果能提示输入文件名,这个脚本将更具可重用性,理想情况下应该作为带UI界面的独立应用程序运行。作为起点,Python比Bash更适合开发(Web)应用程序。大语言模型可以帮助实现不同编程语言之间的代码转换。具体示例请参见表18:
Name | 1.python_rename_files |
---|---|
目标 | 编写将 Bash 代码翻译成 Python 的提示 |
模型 | gemini-pro |
温度 | 0.1 |
Token 限制 | 1024 |
Top-K | N/A |
Top-P | 1 |
提示 |
Translate the below Bash code to a Python snippet. “`bash #!/bin/bash echo “Enter the folder name: “ read folder_name if [ ! -d “$folder_name” ]; then echo “Folder does not exist.” exit 1 fi files=( “$folder_name”/* ) for file in “${files[@]}”; do new_file_name=”draft_$(basename “$file”)” mv “$file” “$new_file_name” done echo “Files renamed successfully.” “` |
输出 |
“`python import os import shutil # Get the folder name from the user folder_name = input(“Enter the folder name: “) # Check if the folder exists if not os.path.isdir(folder_name): print(“Folder does not exist.”) exit(1) files = os.listdir(folder_name) # Iterate over the files for file in files: # Create a new file name with the prefix “draft_” new_file_name = f”draft_{file}” # Move the file to the new name shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name)) # Print a success message print(“Files renamed successfully.”) “` |
表 18. 从 Bash 到 Python 的代码翻译提示
阅读并审查代码。将提示词生成的输出复制并粘贴到新文件:file_renamer.py中。通过打开终端窗口并执行以下命令来测试代码:python file_renamer.py。
注意:在Vertex AI的Language Studio中请求(Python)代码时,需要点击”Markdown”按钮。否则您将获得纯文本格式的代码,缺少Python运行所需的正确缩进。
- 调试和审查代码提示
让我们手动对表18的代码进行一些编辑。它应该提示用户输入文件名前缀,并将该前缀以大写字母形式写入。参见代码片段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:
new_filename = f"{text}_{file}"
shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_filename))
print("Files renamed successfully.")
代码片段3:一个有问题的Python脚本
这看起来是个bug:
The below Python code gives an error:
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
代码片段4:Python代码执行异常
- 关于多模态提示
让我们看看是否可以让大型语言模型进行代码调试和审查。请查看第 19 表:
Name | 1_python_debug_code |
---|---|
目标 | 编写用于调试和审查 Python 代码的提示。 |
模型 | gemini-pro |
温度 | 0.1 |
Token 限制 | 1024 |
Top-K | N/A |
Top-P | 1 |
提示 |
The below Python code gives an error: 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 Debug what’s wrong and explain how I can improve the code. “`python import os import shutil # Get the folder name from the user folder_name = input(“Enter the folder name: “) prefix = input(“Enter the string to prepend to the filename: “) text = toUpperCase(prefix) # Check if the folder exists if not os.path.isdir(folder_name): print(“Folder does not exist.”) exit(1) # Get a list of all files in the folder files = os.listdir(folder_name) # Iterate over the files for file in files: # Create a new file name with the prefix “draft_” new_filename = f”{text}_{file}” # Move the file to the new name shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name)) # Print a success message print(“Files renamed successfully.”) |
输出 |
代码调用了 `toUpperCase` 函数将 `pre x` 转换为大写,但该函数未定义。要修复此问题,您可以使用`upper()` 方法。将给定字符串转换为大写的字符串类。修改后的代码如下所示: “`python import os import shutil # Get the folder name from the user folder_name = input(“Enter the folder name: “) prefix = input(“Enter the string to prepend to the filename: “) text = prefix.upper() # Check if the folder exists if not os.path.isdir(folder_name): print(“Folder does not exist.”) exit(1) # Get a list of all files in the folder files = os.listdir(folder_name) # Iterate over the files for file in files: # Create a new file name with the prefix “draft_” new_filename = f”{text}_{file}” # Move the file to the new name shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_filename)) # Print a success message print(“Files renamed successfully.”) “` Additionally, there are a few other improvements that can be made to the code:
extension from the original filename and append it to the new filename.
it is a good practice to handle spaces gracefully by replacing them with underscores or hyphens.
concise than the traditional `+` operator.
It would be better to wrap the `shutil.move` call in a `try…except` block to catch any potential errors. Here is the improved code with these suggestions: “`python import os import shutil # Get the folder name from the user folder_name = input(“Enter the folder name: “) prefix = input(“Enter the string to prepend to the filename: “) # Check if the folder exists if not os.path.isdir(folder_name): print(“Folder does not exist.”) exit(1) # Get a list of all files in the folder files = os.listdir(folder_name) # Iterate over the files for file in files: # Get the file extension ext = os.path.splitext(file)[1] # Create a new file name with the prefix and the file extension new_filename = f”{prefix}_{os.path.splitext(file)[0]}{ext}” # Build the full paths for the original and new files old_path = os.path.join(folder_name, file) new_path = os.path.join(folder_name, new_filename) # Try to move the file try: shutil.move(old_path, new_path) except Exception as e: print(f”An error occurred while moving the file {file}: {e}”) # Print a success message print(“Files renamed successfully.”) “` 这些改进使代码更加健壮和灵活,同时提升了可读性和可理解性……(回答因达到token限制而被截断,如需完整回答请尝试提高token上限) |
表 19. 调试和审查 Python 代码的提示
太好了。它不仅告诉我如何解决问题,还发现我的代码有更多错误以及如何解决它们。提示的最后部分给出了改进代码的一般建议。
- 关于多模态提示
代码提示仍使用常规的大语言模型。多模态提示是另一个不同的概念,它指的是使用多种输入格式(而不仅仅是文本)来引导大语言模型的技术。根据模型的能力和具体任务需求,这可能包括文本、图像、音频、代码或其他格式的组合。
最佳实践
找到合适的提示词需要反复调试。Vertex AI中的Language Studio是测试提示词的理想环境,您可以在其中使用不同模型进行验证。
遵循以下最佳实践,您将成为提示工程专家:
提供示例
最重要的最佳实践是在提示词中包含示例(单样本/少样本)。这种方法非常有效,因为它能作为强大的教学工具。这些示例展示了期望的输出或类似响应,使模型能够从中学习并相应地调整其生成内容。这就像为模型提供了参考目标,从而提高其响应的准确性、风格和语气,以更好地符合您的期望。
设计简洁原则
提示词应当简洁、清晰且易于理解(对您和模型都是如此)。根据经验,如果您自己都觉得混乱,那么模型很可能也会感到困惑。尽量避免使用复杂语言,不要提供不必要的信息。
示例:
- 改写前:“我现在正在纽约旅游,想了解一些好去处。我带着两个3岁的孩子。我们假期该去哪里?”
- 改写后:”扮演旅游向导的角色。推荐适合3岁儿童的纽约曼哈顿旅游景点。”
建议使用动作动词:
行动、分析、分类、对比、比较、创建、描述、定义、评估、提取、查找、生成、识别、列出、测量、组织、解析、选择、预测、提供、排序、推荐、返回、检索、改写、选择、展示、排序、总结、翻译、编写。
明确输出要求
对期望的输出要具体说明。简洁的指令可能无法为大语言模型提供足够的指导,或者可能过于笼统。在提示词中提供具体细节(通过系统提示或上下文提示)可以帮助模型聚焦相关内容,提高整体准确性。
示例:
- 正确做法:”生成一篇3段落的博客文章,介绍排名前5的视频游戏主机。文章应内容翔实、引人入胜,并采用对话式风格撰写。”
- 错误做法:”生成一篇关于视频游戏主机的博客文章。”
优先使用指令而非限制条件
在提示工程中,指令与限制条件共同引导大型语言模型(LLM)的输出:
- 指令:明确要求响应内容应遵循的格式、风格或具体内容。其作用在于指导模型”应当如何生成”内容。
- 限制条件:设定响应内容的边界与禁忌。其作用在于约束模型”不得涉及”的内容范畴。
越来越多的研究表明,在提示工程中,专注于正向指导比过度依赖限制条件更有效。这种方法符合人类更喜欢接受积极指导而非禁止事项列表的心理特征。
指导直接传达了期望的结果,而限制条件可能会让模型猜测什么是被允许的。它能在定义的范围内提供灵活性并鼓励创造性,而限制条件可能会限制模型的潜力。此外,限制条件列表之间可能会相互冲突。
限制条件在某些情况下仍然有价值,例如需要防止模型生成有害或有偏见的内容,或者需要严格的输出格式或风格时。
如果可能,请使用正向指导:与其告诉模型不要做什么,不如告诉它应该做什么。这可以避免混淆并提高输出的准确性。
- 正确做法:生成一段关于排名前5的视频游戏主机的博客段落。仅讨论游戏主机、制造商、发布年份和总销量。
- 错误做法:生成一段关于排名前5的视频游戏主机的博客段落。不要列出游戏名称。
作为最佳实践,首先应优先考虑指令,明确指出您希望模型做什么,并且仅在必要时出于安全、清晰或特定要求使用约束。进行实验和迭代,测试指令和约束的不同组合,找到最适合您特定任务的方法,并记录这些信息。
控制最大token长度
要控制LLM生成响应的长度,在配置中设置最大token限制,或在提示中明确要求特定长度。
例如: “用一条推文的长度解释量子物理学。“
在提示中使用变量
要重复使用提示词并使其更具动态性,可以在提示词中使用变量,这些变量可以根据不同输入进行更改。例如,如表20所示,一个提供城市相关信息的提示词。与其在提示词中硬编码城市名称,不如使用变量。通过使用变量可以避免重复操作,从而节省时间和精力。如果您需要在多个提示词中使用相同的信息,可以将其存储在变量中,然后在每个提示词中引用该变量。当将提示词集成到您自己的应用程序中时,这种做法非常有意义。
Prompt |
VARIABLES {city} = “Amsterdam” PROMPT You are a travel guide. Tell me a fact about the city: {city} |
---|---|
Output | 阿姆斯特丹是一个拥有运河、桥梁和狭窄街道的美丽城市。它是一个历史丰富、文化深厚、夜生活丰富的绝佳旅游地。 |
表 20. 在提示中使用变量
尝试不同的输入格式和写作风格
不同的模型、模型配置、提示词格式、措辞选择和提交方式可能产生不同的结果。因此,有必要对提示词的属性进行实验,包括风格、措辞和提示类型(零样本、少样本、系统提示)。
例如,要生成关于革命性游戏主机世嘉Dreamcast的文本,可以通过以下不同形式表达,从而产生不同的输出:
- 提问式:世嘉Dreamcast是什么?为什么它是一款革命性的游戏主机?
- 陈述式:世嘉Dreamcast是由世嘉于1999年发布的第六代游戏主机。它…
- 指令式:写一段话描述世嘉Dreamcast游戏主机,并解释它为何如此具有革命性。
少样本提示的分类任务技巧
对于少样本提示的分类任务,应当混合不同类别的样本。
一般来说,少样本示例的顺序影响不大。但在分类任务中,请确保在少样本示例中混合不同的响应类别。否则可能会过度拟合特定示例顺序。通过混合可能的响应类别,可以确保模型学习识别每个类别的关键特征,而不是简单地记忆示例顺序。这将使模型在未见数据上表现更加稳健和具有泛化能力。
一个好的经验法则是从 6 个少量示例开始,并测试准确性。
适应模型更新
必须及时掌握模型架构变更、新增数据和功能更新。尝试使用更新的模型版本,并调整提示词以更好地利用新模型特性。像Vertex AI Studio这样的工具非常适合存储、测试和记录不同版本的提示词。
尝试不同的输出格式
除了提示词的输入格式外,还应尝试不同的输出格式。对于数据提取、选择、解析、排序、排名或分类等非创造性任务,可以尝试让输出以结构化格式(如JSON或XML)返回。
从提示词中返回JSON对象有以下优势:在实际应用中,无需手动创建JSON格式,数据可以直接按排序顺序返回(在处理日期时间对象时特别方便)。最重要的是,通过要求JSON格式,可以强制模型生成结构化输出,减少幻觉内容的产生。
总结来说,使用 JSON 作为输出格式的好处:
- 始终以统一格式返回数据
- 精准聚焦目标数据内容
- 降低幻觉产生概率
- 保持数据关联性
- 自动获取数据类型
- 支持排序功能
在少样本提示部分,表 4 展示了如何返回结构化输出的示例。
JSON 修复
虽然以JSON格式返回数据具有诸多优势,但也存在一些缺点。JSON的结构化特性虽然有利于解析和应用集成,但相比纯文本需要消耗更多的token,这会导致处理时间增加和成本上升。此外,JSON的冗长特性很容易占满整个输出窗口,当生成内容因token限制被突然截断时,这一问题尤为突出。这种截断通常会导致JSON格式无效——缺失关键的闭合括号或中括号,从而使输出无法使用。幸运的是,像json-repair这样的工具库(可通过PyPI获取)在这种情况下非常有用。该库能智能地尝试自动修复不完整或格式错误的JSON对象,使其成为处理大语言模型生成的JSON数据时的重要工具,特别是在应对可能出现的截断问题时尤其有效。
使用模式
正如本文多次提到的,使用结构化JSON作为输出是一个很好的解决方案。但输入呢?虽然JSON非常适合构建LLM生成的输出结构,但它对于构建您提供的输入数据也同样非常有用。这就是JSON Schema发挥作用的地方。JSON Schema定义了您输入的JSON数据的预期结构和数据类型。通过提供一个schema,您为LLM提供了一个清晰的数据蓝图,帮助它聚焦于相关信息,并降低误解输入的风险。此外,schema还能帮助建立不同数据片段之间的关系,甚至通过包含特定格式的日期或时间戳字段,使LLM具备”时间感知”能力。
一个简单的例子:让我们假设您想使用一个大型语言模型( LLM )来生成电子商务目录中产品的描述。除了提供产品的文本描述外,您还可以使用 JSON 模式来定义产品的属性:
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "Product name" },
"category": { "type": "string", "description": "Product category" },
"price": { "type": "number", "format": "float", "description": "Product price" },
"features": {
"type": "array",
"items": { "type": "string" },
"description": "Key features of the product"
},
"release_date": { "type": "string", "format": "date", "description": "Date the product was released" }
}
}
代码片段 5. 结构化输出模式的定义
然后,您可以提供符合此架构的实际产品数据,作为 JSON 对象:
{
"name": "Wireless Headphones",
"category": "Electronics",
"price": 99.99,
"features": ["Noise cancellation", "Bluetooth 5.0", "20-hour battery life"],
"release_date": "2023-10-27"
}
代码片段 6. LLM 的格式化输出
通过预处理数据并仅提供模式和数据而非完整文档,您可为大语言模型明确展示产品的各项属性(包括发布日期),从而大幅提高生成描述的准确性和相关性。这种结构化输入方法能精准引导大语言模型关注关键字段,在处理海量数据或将大语言模型集成至复杂应用时尤为重要。
提示工程师协同实验方案
当需要开发优质提示时,建议组建多人协作团队。在全员遵循本章最佳实践的前提下,您将观察到不同提示方案间的性能差异。
CoT 最佳实践
必须将答案放在推理过程之后,因为推理过程的生成会改变模型预测最终答案时接收到的token。
使用CoT和自我一致性方法时,需要能够从提示中提取最终答案,并将其与推理过程分离。
对于CoT提示,温度参数应设置为0。
思维链提示基于贪婪解码策略,即根据语言模型分配的最高概率预测序列中的下一个词。一般来说,当使用推理得出最终答案时,很可能只有一个正确答案。因此温度参数应始终设为0。
详细记录提示尝试
虽然本章前文已提及,但我们必须再次强调其重要性,请完整详细地记录您的提示尝试,这样才能持续了解哪些方法有效、哪些无效。
提示输出可能在不同模型、不同采样设置以及同一模型的不同版本之间有所不同。此外,即使在同一模型的相同提示下,输出句子结构和词语选择也可能存在细微差异。(例如,如前所述,如果两个标记具有相同的预测概率,则可能会随机打破平局。这可能会影响后续预测的标记。)
我们建议按照表21的模板创建Google表格进行记录。这种方法的优势在于,当您不可避免地需要重新审视提示工程工作时(无论是将来继续这项工作、测试不同模型版本的提示性能,还是调试未来出现的错误),都能获得完整记录,您会惊讶地发现,即使只是短暂中断后也会遗忘许多细节。
除了表格中的字段外,跟踪提示版本(迭代)、记录结果是否 OK/NOT OK/SOMETIMES OK的字段以及记录反馈的字段也非常有帮助。如果你使用VertexAI Studio,请保存你的提示(使用与文档中列出的相同名称和版本),并在表格中跟踪保存提示的超链接。这样,你只需点击一下即可重新运行你的提示。
当在处理一个 retrieval augmented generation 系统时,你还应该捕捉影响内容被插入到提示中的 RAG 系统的具体方面,包括查询、块设置、块输出和其他信息。
当提示词趋于完善时,应将其迁移至项目代码库。在代码库中,提示词应与业务代码分开存储以便维护。最终,理想的提示词应成为可运维系统的一部分,作为提示工程师,您应该依赖自动化测试和评估流程来验证提示词对任务的泛化能力。
提示工程是一个迭代过程。需要不断设计测试不同提示、分析并记录结果,根据模型表现优化提示词,持续实验直至获得理想输出。当更换模型或调整配置时,应重新测试之前使用过的提示词方案。
Name | [ 您的提示名称和版本 ] |
---|---|
模型 | [对本次提示工程目标的简述] |
温度 | [值介于 0 – 1] |
Top-K | [ 数字 ] |
Token 限制 | [ 数字 ] |
Top-P | [ 数字] |
提示 | [写出完整的提示词] |
输出 | [ 输出或多个输出 ] |
表 21. 记录提示的模板
摘要
这篇白皮书讨论了提示工程。我们学习了各种提示技术,例如:
- 零样本提示
- 少样本提示
- 系统提示
- 角色提示
- 上下文提示
- 回溯提示
- 思维链
- 自我一致性
- 思维树
- ReAct
我们甚至研究了如何自动化提示方法。
白皮书随后讨论了生成式 AI 的挑战,例如当你的提示不足时可能出现的问题。我们以如何成为一名更好的提示工程师的最佳实践作为结尾。
参考文献
- Google, 2023,《Gemini:谷歌多模态AI系统》在线访问:https://gemini.google.com
- Google, 2024,《Google Workspace中Gemini提示词指南》在线访问: https://inthecloud.withgoogle.com/gemini-for-google-workspace-prompt-guide/dl-cd.html
- Google Cloud, 2023,《提示工程入门指南》在线访问: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/introduction-prompt-design
- Google Cloud, 2023,《文本模型请求体:Top-P与top-K采样方法》在线访问: https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text#request_body
- Wei, J. 等, 2023,《零样本学习:微调语言模型的零样本能力》在线访问: https://arxiv.org/pdf/2109.01652.pdf
- Google Cloud, 2023,《Google云模型库》在线访问:https://cloud.google.com/model-garden
- Brown, T. 等, 2023,《少样本学习:语言模型的少样本能力》在线访问: https://arxiv.org/pdf/2005.14165.pdf
- Zheng, L. 等, 2023,《退一步思考:通过抽象化激发大语言模型推理能力》在线访问: https://openreview.net/pdf?id=3bq3jsvcQ1
- Wei, J. 等, 2023,《思维链提示方法》在线访问:https://arxiv.org/pdf/2201.11903.pdf
- Google云平台, 2023,《思维链与ReAct实践》在线访问:https://github.com/GoogleCloudPlatform/generative-ai/blob/main/language/prompts/examples/chain_of_thought_react.ipynb
- Wang, X. 等, 2023,《自洽性提升语言模型思维链推理能力》在线访问: https://arxiv.org/pdf/2203.11171.pdf
- Yao, S. 等, 2023,《思维树:大语言模型的系统性问题解决方法》在线访问: https://arxiv.org/pdf/2305.10601.pdf
- Yao, S. 等, 2023,《ReAct:语言模型中推理与行动的协同机制》在线访问: https://arxiv.org/pdf/2210.03629.pdf
- Google云平台, 2023,《高级提示技术:思维链与ReAct》在线访问: https://github.com/GoogleCloudPlatform/applied-ai-engineering-samples/blob/main/genaion-vertex-ai/advanced_prompting_training/cot_react.ipynb
- Zhou, C. 等, 2023,《自动提示工程:大语言模型的人类级提示词生成能力》在线访问: https://arxiv.org/pdf/2211.01910.pdf
获取《Prompt Engineering》提示词工程白皮书 PDF原文件,扫码关注回复: 20250411