- 翻译:八尺妖剑
- 原作者:Lee Boonstra
致谢
内容贡献者:
Michael Sherman
Yuan Cao
Erick Armbrust
Anant Nawalgaria
Antonio Gulli
Simone Cammel
策展与编辑:
Antonio Gulli
Anant Nawalgaria
Grace Mollison
技术作家:Joey Haymaker
设计师:Michael Lanning
目录
引言 6
提示工程 7
大语言模型输出配置 8
输出长度 8
采样控制 9
温度 9
Top-K 和 Top-P 10
综合应用 11
提示技巧 13
通用提示 / 零样本提示 13
单样本与少样本提示 15
系统提示、上下文提示与角色提示 18
系统提示 19
角色提示 21
上下文提示 23
回溯提示 25
思维链(CoT) 29
自我一致性 32
思维树(ToT) 36
推理与行动(ReAct) 37
自动提示工程 40
代码提示 42
编写代码的提示 42
解释代码的提示 44
翻译代码的提示 46
调试与审查代码的提示 48
多模态提示呢? 54
最佳实践 54
提供示例 54
保持简单 55
明确输出要求 56
优先使用指令而非约束 56
控制最大令牌长度 58
在提示中使用变量 58
尝试不同的输入格式与写作风格 59
在少样本分类任务中混合类别 59
适应模型更新 60
尝试不同的输出格式 60
JSON修复 61
使用模式(Schemas) 62
与其他提示工程师一起实验 63
思维链最佳实践 64
记录各种提示尝试 64
总结 66
注释 68
你不需要是数据科学家或机器学习工程师——每个人都可以写提示。
引言
当我们谈到大语言模型的输入和输出时,文本提示(有时还会伴随其他形式,比如图片提示)是模型用来预测特定输出的输入。你不需要是数据科学家或机器学习工程师——每个人都可以写提示。然而,写出最有效的提示可能有点复杂。提示的很多方面都会影响它的效果:你用的模型、模型的训练数据、模型的配置、你的措辞、风格和语气、结构以及上下文都很重要。因此,提示工程是一个反复试错的过程。不合适的提示可能导致模糊、不准确的回答,还会阻碍模型提供有意义的输出。
当你和Gemini聊天机器人互动时,基本上就是在写提示。不过,这篇白皮书主要讨论如何为Vertex AI中的Gemini模型或通过API写提示,因为直接给模型写提示可以让你调整温度等配置。
这篇白皮书会详细探讨提示工程。我们将介绍各种提示技巧,帮助你入门,并分享一些建议和最佳实践,让你成为提示专家。我们还会讨论在编写提示时可能遇到的挑战。
提示工程
先来了解大语言模型的工作原理:它是一个预测引擎。模型接收一段连续的文本作为输入,然后根据训练数据预测下一个词应该是什么。模型会不断重复这个过程,把之前预测的词加到文本末尾,继续预测下一个词。下一个词的预测基于之前词的关系以及模型在训练中见过的内容。
当你写提示时,你是在试图引导大语言模型预测正确的词序列。提示工程是设计高质量提示的过程,帮助大语言模型生成准确的输出。这个过程需要不断调整,找到最佳提示,优化提示长度,评估提示的写作风格和结构与任务的关系。在自然语言处理和大语言模型的背景下,提示是提供给模型的输入,用来生成回答或预测。
这些提示可以用来完成各种理解和生成任务,比如文本摘要、信息提取、问答、文本分类、语言或代码翻译、代码生成、代码文档编写或推理。
你可以参考谷歌的提示指南,里面有简单有效的提示示例。
在提示工程中,你首先要选择一个模型。提示可能需要针对特定模型进行优化,无论你是用Vertex AI中的Gemini语言模型、GPT、Claude,还是开源模型如Gemma或LLaMA。
除了提示本身,你还需要调整大语言模型的各种配置。
大语言模型输出配置
选好模型后,你需要确定模型的配置。大多数大语言模型都有多种配置选项,控制模型的输出。有效的提示工程需要为你的任务优化这些配置。
输出长度
一个重要的配置是生成回答的令牌(token)数量。生成更多令牌需要模型进行更多计算,导致能耗更高、响应时间可能更慢,成本也更高。
减少输出长度并不会让模型的输出在风格或文本上更简洁,它只是让模型在达到限制后停止预测更多令牌。如果你的任务需要短输出,你可能还需要设计提示来适应这个需求。
输出长度限制对一些提示技巧特别重要,比如ReAct,模型在生成你想要的回答后可能会继续输出无用的令牌。
要注意,生成更多令牌需要更多计算,导致能耗更高、响应时间可能更慢,成本也会增加。
采样控制
大语言模型并不是简单预测一个令牌,而是为下一个可能的令牌预测概率,词汇表中的每个令牌都有一个概率。这些概率会被采样,决定下一个输出的令牌。温度、Top-K和Top-P是最常见的配置,决定如何处理预测的令牌概率来选择单个输出令牌。
温度
温度控制令牌选择的随机性。低温度适合需要更确定性回答的提示,而高温度可能带来更多样化或意外的结果。温度为0(贪婪解码)是确定性的:总是选择概率最高的令牌(不过,如果两个令牌概率相同,根据实现方式的不同,温度为0时可能不会总得到相同输出)。
温度接近最大值会生成更随机的输出。随着温度越来越高,所有令牌成为下一个预测令牌的概率会趋于均等。
Gemini的温度控制可以类比机器学习中的softmax函数。低温度类似于低softmax温度(T),强调单一的高确定性选择。高温度类似于高softmax温度,允许更广泛的选择,增加不确定性,适合需要创意输出的场景。
Top-K 和 Top-P
Top-K和Top-P(也叫核采样)是两种采样设置,限制下一个预测令牌来自概率最高的令牌。和温度一样,这些设置控制生成文本的随机性和多样性。
- Top-K采样:从模型预测分布中选择概率最高的K个令牌。K值越高,模型输出越有创意和多样;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条件的令牌会随机选择,生成下一个预测令牌。
在某些极端设置下,一个采样配置会抵消其他设置或变得无关紧要:
- 如果温度设为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-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展示了一个零样本提示,用于分类电影评论。
用表格记录提示是一个好方法。提示可能会经过多次迭代才最终用于代码库,系统化记录提示工程工作很重要。更多关于表格格式、记录重要性和提示开发过程的内容会在后面的“最佳实践”部分讨论(“记录各种提示尝试”)。
模型温度设为低值,因为不需要创意,Top-K和Top-P用gemini-pro的默认值,相当于禁用(见上文“大语言模型输出配置”)。注意生成的输出。“令人不安”和“杰作”这两个词出现在同一句中,会让预测复杂一些。
表1. 零样本提示示例
名称 | 1_电影分类 | ||
---|---|---|---|
目标 | 将电影评论分类为正面、中立或负面 | ||
模型 | gemini-pro | ||
温度 | 0.1 | 令牌限制 | 5 |
Top-K | 无 | Top-P | 1 |
提示 | 将电影评论分类为正面、中立或负面。评论:《Her》是一部揭示人类未来方向的令人不安的研究,如果AI继续不受控制地发展,我希望有更多这样的杰作电影。情感: | ||
输出 | 正面 |
如果零样本效果不好,可以在提示中提供演示或示例,这就是“单样本”和“少样本”提示。
单样本与少样本提示
为AI模型创建提示时,提供示例很有帮助。示例能让模型明白你的要求,尤其在你希望模型输出特定结构或模式时。
单样本提示提供一个示例,因此叫单样本。模型通过模仿示例来完成任务。
少样本提示提供多个示例,展示模型需要遵循的模式。和单样本类似,但多个示例增加模型遵循模式的概率。
少样本所需的示例数量取决于任务复杂性、示例质量和生成AI模型的能力。一般来说,少样本提示至少需要3到5个示例。复杂任务可能需要更多,模型输入长度限制可能要求更少。
表2展示了一个少样本提示示例,使用和之前相同的gemini-pro配置,只是增加令牌限制以适应更长回答。
表2. 少样本提示示例
目标 | 将披萨订单解析为JSON | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 0.1 | 令牌限制 | 250 |
Top-K | 无 | Top-P | 1 |
提示 | 将客户披萨订单解析为有效JSON:示例:我要一个小的奶酪披萨,番茄酱和意大利辣肠。JSON响应:{ | ||
示例 | 示例:我要一个大披萨,番茄酱、罗勒和莫扎里拉。{ “size”: “large”, “type”: “normal”, “ingredients”: [[“tomato sauce”, “bazel”, “mozzarella”]] } 现在我要一个大披萨,一半奶酪和莫扎里拉,另一半番茄酱、火腿和菠萝。JSON响应: | ||
输出 | { “size”: “large”, “type”:“half-half”, “ingredients”: [[“cheese”, “mozzarella”], [“tomato sauce”, “ham”, “pineapple”]] } |
选择示例时,确保示例与任务相关,示例要多样、质量高、写得好。一个小错误可能让模型困惑,导致不理想的输出。
如果希望输出对多种输入都稳健,示例中应包含边缘情况——不常见或意外的输入,模型仍需正确处理。
系统提示、上下文提示与角色提示
系统提示、上下文提示和角色提示都是引导大语言模型生成文本的技巧,但侧重点不同:
- 系统提示设定模型的整体上下文和目的,定义模型的“大方向”,如翻译语言、分类评论等。
- 上下文提示提供与当前对话或任务相关的具体细节或背景信息,帮助模型理解需求并定制回答。
- 角色提示为模型指定特定角色或身份,帮助模型生成与角色知识和行为一致的回答。
这三者可能有重叠。比如,指定角色的提示也可能包含上下文。
但每种提示的主要目的略有不同:
- 系统提示:定义模型的基本能力和整体目标。
- 上下文提示:提供即时、任务特定的信息,动态引导回答。
- 角色提示:定义模型的输出风格和语气,增加特定性和个性。
区分这三种提示为设计意图清晰的提示提供了框架,允许灵活组合,便于分析每种提示对模型输出的影响。
下面详细介绍这三种提示。
系统提示
表3展示了一个系统提示,指定了如何返回输出的额外信息。我提高了温度以增加创意,指定了更高的令牌限制。但由于明确指令,模型没有生成多余文本。
表3. 系统提示示例
目标 | 将电影评论分类为正面、中立或负面 | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 1 | 令牌限制 | 5 |
Top-K | 40 | Top-P | 0.8 |
提示 | 将电影评论分类为正面、中立或负面,仅返回大写标签。评论:《Her》是一部揭示人类未来方向的令人不安的研究,如果AI继续不受控制地发展,太可怕了,我看不下去。情感: | ||
输出 | 负面 |
系统提示适合生成符合特定要求的输出。“系统提示”的名称意为“为系统提供额外任务”。比如,你可以用系统提示生成特定编程语言兼容的代码片段,或返回特定结构。表4展示了一个返回JSON格式的示例。
表4. 系统提示返回JSON格式示例
目标 | 将电影评论分类为正面、中立或负面,返回JSON | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 1 | 令牌限制 | 1024 |
Top-K | 40 | Top-P | 0.8 |
提示 | 将电影评论分类为正面、中立或负面,返回有效JSON。评论:《Her》是一部揭示人类未来方向的令人不安的研究,如果AI继续不受控制地发展,太可怕了,我看不下去。模式:MOVIE: { “sentiment”: String “POSITIVE” | “NEGATIVE” | “NEUTRAL”, “name”: String } MOVIE_REVIEWS: { “movie_reviews”:[MOVIE] } |
输出 | JSON响应:{ “movie_reviews”: [ { “sentiment”: “NEGATIVE”, “name”:“Her” } ] } |
返回JSON对象提取数据有几个好处。在实际应用中,我无需手动创建JSON格式,数据可按序返回(处理日期时间对象时很方便),最重要的是,提示JSON格式会迫使模型创建结构,减少幻觉(hallucination)。
系统提示对安全性和毒性控制也很有用。简单加一句“回答需尊重”即可控制输出。
角色提示
角色提示是为生成AI模型指定特定角色的技巧,帮助模型生成更相关、更具信息性的输出,模型会根据角色定制回答。
比如,你可以让模型扮演图书编辑、幼儿园老师或励志演说家。指定角色后,可以提供与角色相关的提示。比如,让老师角色创建一个可审查的课程计划。表5展示了一个旅行向导角色的示例。
表5. 角色提示示例
目标 | 扮演旅行向导,提供3个旅行建议 | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 1 | 令牌限制 | 1024 |
Top-K | 40 | Top-P | 0.8 |
提示 | 我希望你扮演旅行向导。我会告诉你我的位置,你建议3个附近可参观的地方。有时我会指定类型。我的建议:“我在阿姆斯特丹,只想参观博物馆。” 旅行建议: | ||
输出 | 1. 荷兰国立博物馆:世界知名的博物馆,以伦勃朗的《夜巡》等荷兰杰作闻名,别错过丰富的绘画和文物收藏,展示荷兰艺术与历史。2. 梵高博物馆:沉浸于梵高的迷人作品,馆内收藏了他最多的画作和素描,包括《星空》和《向日葵》。3. 阿姆斯特丹市立博物馆:探索全球现代与当代艺术,收藏包括毕加索、康定斯基和里特维尔德的作品,位于独特的现代建筑中。 |
上例展示了一个旅行向导角色。如果改为地理老师角色,回答会不同。
为模型定义角色视角能提供语气、风格和专业知识的蓝图,提升输出的质量、相关性和效果。
以下是一些我认为有效的风格:
对抗性、描述性、直接、正式、幽默、有影响力、非正式、励志、说服性
表6调整了提示,加入幽默和励志风格。
表6. 幽默风格的角色提示示例
提示 | 我希望你扮演旅行向导。我会告诉你我的位置,你以幽默风格建议3个附近可参观的地方。我的建议:“我在曼哈顿。” 旅行建议: | ||
---|---|---|---|
输出 | 1. 帝国大厦壮观景观:登上帝国大厦,俯瞰曼哈顿天际线,感受如金刚站在大苹果之巅——不过没有巨型香蕉!2. 在MoMA释放艺术气息:到现代艺术博物馆(MoMA),欣赏令人震撼的杰作,会让你怀疑自己的火柴人画有没有艺术价值。 |
上下文提示
通过提供上下文提示,你可以确保AI交互尽可能顺畅高效。模型能更快理解请求,生成更准确、相关的回答,如表7所示。
表7. 上下文提示示例
目标 | 为复古游戏博客建议文章 | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 1 | 令牌限制 | 1024 |
Top-K | 40 | Top-P | 0.8 |
提示 | 背景:你为一个关于80年代街机游戏的博客写作。建议3个文章主题,每主题附几行描述。 | ||
输出 | 1. 街机机柜设计演变:文章探讨街机机柜设计从70年代木质金属柜到80年代霓虹灯设计的演变。2. 经典回顾:80年代标志性街机游戏:介绍80年代最具影响力的街机游戏历史、影响和遗产,突出创新、流行机制和持久魅力。3. 像素艺术的兴起与复古复兴:探讨像素艺术作为早期街机游戏定义风格的演变,追溯根源、技术,并讨论其在现代游戏和数字艺术中的复兴。 |
回溯提示
回溯提示通过先让模型考虑与具体任务相关的通用问题,再将通用问题的回答输入后续具体任务提示,来提升性能。这种“回溯”让模型在解决具体问题前激活相关背景知识和推理过程。
通过考虑更广泛的基础原则,大语言模型能生成更准确、深刻的回答。回溯提示鼓励模型批判性思考,创新应用知识,改变最终任务提示,调用更多模型参数中的知识。
回溯提示还能缓解模型回答中的偏见,聚焦通用原则而非具体细节。
我们通过示例了解回溯提示如何提升效果。先看表8的传统提示,再与表9的回溯提示对比:
表8. 传统提示
目标 | 为第一人称射击游戏关卡编写故事线 | ||
---|---|---|---|
模型 | gemini-pro | ||
温度 | 1 | 令牌限制 | 1024 |
Top-K | 40 | Top-P | 0.8 |
提示 | 为第一人称射击游戏新关卡编写一段具有挑战性和吸引力的故事线。 | ||
输出 | 关卡开始时,玩家小队在密集城区被敌方伏击。玩家需在狭窄巷弄和破旧大楼中作战,利用隐蔽和精准消灭敌人,避免被发现。玩家需利用环境,设置陷阱、利用掩体,谨慎行动以生存。途中发现情报,敌人计划毁灭性攻击,玩家需争分夺秒收集证据并传回总部,阻止敌人计划。 |
温度设为1可能生成各种创意故事线,但也可能随机和泛泛。让我们回溯一步:
表9. 回溯提示示例
提示 | 根据热门第一人称射击游戏,列出5个虚构的关键场景,构成具有挑战性和吸引力的关卡故事线? | ||
---|---|---|---|
输出 | 1. 废弃军事基地:后末日军事综合体,充满变异士兵和机器人,适合挑战性枪战。2. 赛博朋克城市:霓虹灯照耀的未来都市,高楼和狭窄巷弄,敌人有赛博增强,需黑客技术。3. 外星飞船:地球上搁浅的外星飞船,诡异走廊、零重力区域,遭遇外星生物。4. 僵尸小镇:被僵尸占领的荒凉小镇,近战激烈,需解谜找到安全通道。5. 海底研究设施:被水淹没的深海实验室,充满变异水生生物,需隐蔽和水下探索。 |
这些场景很适合第一人称游戏。回到原提示,但这次将回溯答案作为上下文,看看结果如何。
表10. 回溯提示结合上下文示例
提示 | 背景:第一人称射击游戏的5个吸引人主题:1. 废弃军事基地:后末日军事综合体,充满变异士兵和机器人,适合挑战性枪战。2. 赛博朋克城市:霓虹灯照耀的未来都市,高楼和狭窄巷弄,敌人有赛博增强,需黑客技术。3. 外星飞船:地球上搁浅的外星飞船,诡异走廊、零重力区域,遭遇外星生物。 | ||
---|---|---|---|
输出 | 选择一个主题,为第一人称射击游戏新关卡编写一段具有挑战性和吸引力的故事线。在幽暗深渊中,有一座破旧的海底研究设施,见证人类野心与灾难后果。设施笼罩在黑暗中,故障机器的嗡鸣声回响,淹死灵魂的回声萦绕,如今成为深海噩梦的温床。玩家作为精锐海军陆战队员,配备高级潜水装备和实验武器,需冒险进入…… |
这看起来是个有趣的游戏!通过回溯提示技巧,你可以提升提示的准确性。
思维链(CoT)
思维链(CoT)提示通过生成中间推理步骤提升大语言模型的推理能力,帮助模型生成更准确的回答。结合少样本提示可用于更复杂的推理任务,因为零样本思维链效果有限。
思维链有很多优势:低成本高效,适用于现成模型(无需微调),提供可解释性,可看到推理步骤,易于识别问题。思维链在不同模型版本间更稳健,提示性能漂移较小。缺点也很直观:包含推理步骤的回答需要更多输出令牌,预测成本更高,耗时更长。
为解释表11的示例,我们先试一个不使用思维链的提示,展示大语言模型的缺陷。
表11. 尝试解决数学问题的提示
提示 | 我3岁时,我的伙伴是我的3倍年龄。现在我20岁,我的伙伴多大? | ||
---|---|---|---|
输出 | 63岁 |
糟糕,显然是错的。大语言模型常在数学任务中出错,即使是简单乘法。这是因为它们在大量文本上训练,数学可能需要不同方法。看看中间推理步骤能否改善输出。
表12. 思维链提示示例
提示 | 我3岁时,我的伙伴是我的3倍年龄。现在我20岁,我的伙伴多大?让我们一步步思考。 | ||
---|---|---|---|
输出 | 1. 假设我现在的年龄是“x”岁。2. 我3岁时,我的年龄是3岁。3. 当时我伙伴的年龄是我的3倍,即3 * 3 = 9岁。4. 现在我20岁,意味着从3岁起过了20 - 3 = 17年。5. 我伙伴当时9岁,年龄也增加了17年。6. 因此,我伙伴现在的年龄是9 + 17 = 26岁。 |
现在答案正确了。因为我们明确指示模型解释每一步,而非直接给答案。有趣的是,模型通过加17年计算。我会用年龄差计算:(20 + (9 - 3))。帮模型更像我思考。
表12是“零样本”思维链。结合单样本或少样本提示,思维链更强大,如表13所示:
表13. 单样本思维链提示示例
提示 | 问题:我弟弟2岁时,我是他年龄的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。 |
思维链适合多种场景,如代码生成(将请求分解为步骤,映射到代码行),或生成合成数据(基于产品标题假设描述)。任何能通过“讲解”解决的任务都适合思维链。如果能解释解决步骤,试试思维链。
请参考GoogleCloudPlatform Github上的笔记本,详细介绍思维链提示。
最佳实践部分会介绍思维链的专属最佳实践。
自我一致性
尽管大语言模型在多种自然语言处理任务中表现出色,但推理能力常被视为局限,仅靠增加模型规模难以突破。如前所述,思维链提示可让模型生成类似人类解题的推理步骤。但思维链用简单的“贪婪解码”策略,效果有限。自我一致性结合采样和多数投票,生成多样推理路径,选择最一致的答案,提升模型回答的准确性和连贯性。
自我一致性给答案正确性提供伪概率,但成本高。步骤如下:
- 生成多样推理路径:多次提供相同提示,高温设置鼓励模型生成不同推理路径和视角。
- 从每个生成回答中提取答案。
- 选择最常见的答案。
看看一个电子邮件分类系统的示例,分类邮件为“重要”或“不重要”。用零样本思维链提示多次发送,观察每次提交后回答是否不同。注意邮件中的友好语气、措辞和讽刺,可能误导模型。
提示
邮件:嗨,祝好,
我看到你的网站用了Wordpress,很棒的开源内容管理系统。我过去也用过,插件丰富,设置简单。我注意到联系表单有个bug,选择姓名字段时会出问题。附件是输入姓名时的截图,注意我触发的JavaScript警告框。但其他方面网站很棒,我喜欢读。随意保留这个bug,因为它让我读到更多有趣内容。
Harry the Hacker
将邮件分类为重要或不重要,一步步思考并解释原因。
表14. 自我一致性提示示例
| 输出尝试1 | 步骤2:评估bug的潜在影响。联系表单的bug可能让攻击者执行任意JavaScript代码。| 步骤1:识别邮件目的。邮件目的是通知收件人网站联系表单的bug。发件人提到喜欢网站,暂时保留bug。| | 输出尝试2 | 结论:重要。基于bug的潜在影响和发件人可信度,邮件应分类为重要。收件人需立即修复bug,保护网站免受攻击。| 解释:1. 无紧迫感:邮件以随意问候开头,语气平和。2. 非关键bug:bug被描述为有趣但非关键,发件人建议可保留。3. 无个人影响:邮件未指明对网站主人的直接影响,仅说喜欢网站。| | 输出尝试3 | 步骤1:识别邮件目的。邮件目的是通知收件人网站联系表单的bug。发件人提到喜欢网站,暂时保留bug。步骤2:评估bug的潜在影响。联系表单的bug可能让攻击者执行任意JavaScript代码,可能控制网站、窃取信息或破坏网站。步骤3:考虑发件人可信度。发件人自称黑客Harry,但无法验证身份。可能是想帮助的合法黑客,也可能是想利用bug的恶意者。|
你可以试试这个提示,看是否返回一致分类。根据模型和温度配置,可能返回“重要”或“不重要”。
通过生成多个思维链,取最常见答案(“重要”),可获得更一致的正确答案。
这个示例展示自我一致性提示如何通过考虑多视角并选择最一致答案,改善模型回答的准确性。
思维树(ToT)
了解了思维链和自我一致性后,我们来看思维树(ToT)。它推广了思维链的概念,允许大语言模型同时探索多种推理路径,而非单一线性思维链。如图1所示。
图1. 左侧为思维链提示,右侧为思维树提示的可视化
这种方法使思维树特别适合需要探索的复杂任务。它通过维护一个思维树工作,每个思维是一个连贯的语言序列,作为解决问题中间步骤。模型可通过从树的不同节点分支,探索不同推理路径。
有一个很棒的笔记本,基于《大语言模型引导的思维树》论文,详细展示了思维树。
推理与行动(ReAct)
推理与行动(ReAct)提示是一种范式,通过结合自然语言推理和外部工具(搜索、代码解释器等),让大语言模型解决复杂任务,允许模型执行动作(如与外部API交互获取信息),是智能体建模的第一步。
ReAct模仿人类在现实世界的操作,我们通过语言推理并采取行动获取信息。ReAct在多种领域表现优于其他提示工程方法。
ReAct通过推理和行动的思想-行动循环工作。模型先推理问题,生成行动计划,然后执行计划中的行动并观察结果。模型用观察结果更新推理,生成新计划,循环直到解决问题。
要实际操作,需写代码。代码片段1用Python的langchain框架,结合VertexAI(google-cloud-aiplatform)和google-search-results包。
运行示例需从https://serpapi.com/manage-api-key 创建免费SerpAPI密钥,并设置环境变量SERPAPI_API_KEY。
接下来写Python代码,任务是让模型计算:Metallica乐队成员有多少孩子。
Python
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import VertexAI
prompt = "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进行了五次搜索链。模型通过抓取谷歌搜索结果找出乐队成员,然后列出观察结果,链式思考下一次搜索。
> 进入新的AgentExecutor链...
Metallica有4名成员。
行动:搜索
行动输入:James Hetfield有多少孩子?
观察:三个孩子
思考:1/4 Metallica成员有3个孩子
行动:搜索
行动输入:Lars Ulrich有多少孩子?
观察:3个
思考:2/4 Metallica成员有6个孩子
行动:搜索
行动输入:Kirk Hammett有多少孩子?
观察:Hammett与第二任妻子Lani自1998年结婚。他们有两个儿子,Angel(2006年9月29日生)和Vincenzo(2008年6月28日生)。
思考:3/4 Metallica成员有8个孩子
行动:搜索
行动输入:Robert Trujillo有多少孩子?
观察:2个
思考:4/4 Metallica成员有10个孩子
最终答案:10
代码片段2 计算出Metallica有四名成员,逐个搜索成员的孩子总数,最后返回总计10个孩子。
ReAct提示需持续发送之前的提示/回答(并修剪多余内容),并为模型设置适当示例/指令。请参考GoogleCloudPlatform Github上的笔记本,展示更详细的模型输入输出示例。
自动提示工程
你可能意识到写提示很复杂。如果能自动化(写提示生成提示)不是很好吗?确实有方法:自动提示工程(APE)。这种方法不仅减少人工输入,还提升模型在多种任务中的表现。
你用模型生成更多提示,评估它们,调整好的提示,重复此过程。
例如,自动提示工程可用于训练乐队T恤网店的聊天机器人,找出客户订购T恤的各种表达方式。
- 编写生成输出变体的提示。本例用gemini-pro生成10个指令,见表15:
表15. 用大语言模型生成提示
提示 | 我们有一个乐队T恤网店,为训练聊天机器人,需各种订购方式:“一件Metallica T恤,S码”。生成10个语义相同但表达不同的变体。 | ||
---|---|---|---|
输出 | 1. 我想买一件Metallica T恤,小码。2. 能订一件小码Metallica T恤吗?3. 我想买一件小码Metallica T恤。4. 一件小码Metallica T恤,谢谢。5. 我想要一件小码Metallica T恤。6. 我想订一件小码Metallica T恤。7. 小码Metallica T恤,来一件。8. 我在找一件小码Metallica T恤。9. 能给我一件小码Metallica T恤吗?10. 一件小码Metallica T恤,拜托。 |
- 根据选定指标评估所有候选指令,比如用BLEU或ROUGE评分。
- 选择得分最高的候选指令,作为最终提示用于应用或聊天机器人。你也可以调整选定提示再次评估。
代码提示
Gemini主要聚焦文本提示,包括返回代码的提示。去Vertex AI Studio测试代码示例。
编写代码的提示
Gemini能扮演开发者,帮你用任何编程语言写代码,加速开发过程。
假设你的电脑上有一个文件夹,里面有数百个文件需要重命名。手动改名太费时间。你会点Bash,可以写脚本自动化,但也挺花时间。试试写提示。你可以在公开的Gemini聊天机器人上写提示,或为保密起见,在Google Cloud账户中用Vertex AI Studio。后者优势是可以配置温度等。
表16. 用Gemini编写代码
名称 | 1_bash_rename_files_in_folder | ||
---|---|---|---|
目标 | 编写Bash代码提示,重命名文件夹内文件 | ||
模型 | gemini-pro | ||
温度 | 0.1 | 令牌限制 | 1024 |
Top-K | 无 | Top-P | 1 |
提示 | 编写Bash代码片段,提示输入文件夹名称,然后将文件夹内所有文件名前加上“draft”。 | ||
输出 | ```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”/* )
为每个文件重命名,加前缀“draft”
for file in “${files[@]}”; do new_file_name=“draft_$(basename “$file”)“ mv “$file” “$new_file_name” done echo “Files renamed successfully.”
代码看起来不错,还有注释!但由于大语言模型不能推理,重复训练数据,需先阅读和测试代码。
来试试效果,用一个只有几个文件的测试文件夹,需从filename.txt改为draft_filename.txt。
1. 复制表16输出(去掉```bash```包装),粘贴到新文件“rename_files.sh”。
2. 打开终端,输入:`. rename_files.sh`。提示输入文件夹名称,如“test”,回车。
3. 脚本运行顺利,显示“Files renamed successfully.”。查看test文件夹,所有文件完美改为draft_filename.txt。
成功了!
#### 解释代码的提示
作为开发者,团队合作需读别人代码。Gemini也能帮忙。拿表16的代码,去掉注释,让模型解释发生了什么,见表17:
**表17. 解释代码的提示**
| 名称 | 1_bash_explain_the_code | | |
|------|-------------------|-|-|
| 目标 | 编写提示解释Bash代码 | | |
| 模型 | gemini-pro | | |
| 温度 | 0.1 | 令牌限制 | 1024 |
| Top-K | 无 | Top-P | 1 |
| 提示 | 解释以下Bash代码:
```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."
``` | | |
| 输出 | 这个Bash脚本执行以下任务:
1. **用户输入**:用`echo`和`read`命令提示用户输入文件夹名称,存储在`folder_name`变量。
2. **文件夹存在检查**:用`[! -d "$folder_name"]`检查文件夹是否存在。若不存在,显示“Folder does not exist.”并以退出码1退出。
3. **文件列举**:用`files=( "$folder_name"/* )`列出文件夹内所有文件,存储在`files`数组。
4. **文件重命名**:用`for`循环遍历`files`数组,为每个文件生成新名称,用`new_file_name="draft_$(basename "$file")"`加前缀“draft_”。用`mv`命令重命名文件。
5. **成功消息**:打印“Files renamed successfully.” | | |
#### 翻译代码的提示
表16的Bash代码运行良好。但如果能提示输入文件名前缀,脚本会更通用,理想情况下作为一个带UI的独立应用。Python比Bash更适合(Web)应用。大语言模型可帮代码从一种语言翻译到另一种,见表18:
**表18. 从Bash到Python翻译代码的提示**
| 名称 | 1_python_rename_files | | |
|------|-------------------|-|-|
| 目标 | 编写提示将Bash代码翻译为Python | | |
| 模型 | gemini-pro | | |
| 温度 | 0.1 | 令牌限制 | 1024 |
| Top-K | 无 | Top-P | 1 |
| 提示 | 将以下Bash代码翻译为Python片段:
```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."
import os
import shutil
``` | | |
| 输出 | ```python
# 获取文件夹内文件列表
files = os.listdir(folder_name)
# 遍历文件
for file in files:
# 用前缀“draft_”创建新文件名
new_file_name = f"draft_{file}"
# 将文件移到新名称
shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name))
``` | | |
阅读并审查代码。复制提示输出,粘贴到新文件file_renamer.py。打开终端,执行`python file_renamer.py`测试代码。
**注意**:在Vertex AI的Language Studio中提示Python代码需点击“Markdown”按钮,否则返回纯文本,缺失Python代码所需缩进。
#### 调试与审查代码的提示
对表18代码手动修改,要求用户输入文件名前缀,并将前缀转为大写。见代码片段3,但出错了,报Python错误!
**Python**
```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_file_name))
print("Files renamed successfully.")
错误如下:
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
代码片段4. 我搞砸了Python代码
看看能不能让大语言模型调试和审查代码,见表19:
表19. 调试和审查Python代码的提示
名称 | 1_python_debug_code | ||
---|---|---|---|
目标 | 编写提示调试和审查Python代码 | ||
模型 | gemini-pro | ||
温度 | 0.1 | 令牌限制 | 1024 |
Top-K | 无 | Top-P | 1 |
提示 | 以下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
调试问题并解释如何改进代码。
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_file_name))
# 打印成功消息
print("Files renamed successfully.")
``` | | |
| 输出 | 代码调用`toUpperCase`函数将前缀转为大写,但该函数未定义。修复方法是用字符串类的`upper()`方法将字符串转为大写。修改后的代码如下:
```python
import os
import shutil
# 获取用户输入文件夹名称
folder_name = input("Enter the folder name: ")
prefix = input("Enter the string to prepend to the filename: ")
text = prefix.upper()
# 检查文件夹是否存在
if not os.path.isdir(folder_name):
print("Folder does not exist.")
exit(1)
此外,代码还有其他改进空间:
- 新文件名未保留文件扩展名。最好提取原始文件名扩展名,附加到新文件名。
- 代码假设文件夹名称无空格。最好处理空格,替换为下划线或连字符。
- 用
f
字符串插值比传统+
操作符更可读简洁。 - 代码未处理重命名过程中的错误。最好用
try..except
包裹shutil.move
调用。
改进代码如下:
import os
import shutil
# 获取用户输入文件夹名称
folder_name = input("Enter the folder name: ")
prefix = input("Enter the string to prepend to the filename: ")
# 检查文件夹是否存在
if not os.path.isdir(folder_name):
print("Folder does not exist.")
exit(1)
# 获取文件夹内文件列表
files = os.listdir(folder_name)
# 遍历文件
for file in files:
# 获取文件扩展名
ext = os.path.splitext(file)[1]
# 用前缀和扩展名创建新文件名
new_filename = f"{prefix}_{os.path.splitext(file)[0]}{ext}"
# 构建原始和新文件的完整路径
old_path = os.path.join(folder_name, file)
new_path = os.path.join(folder_name, new_filename)
# 尝试移动文件
try:
shutil.move(old_path, new_path)
except Exception as e:
print(f"移动文件{file}时出错:{e}")
# 打印成功消息
print("Files renamed successfully.")
这些改进使代码更稳健灵活,更易读懂。(因达到令牌限制,回答被截断。如需更长回答,增加令牌限制。) | | |
太棒了!不仅告诉我如何解决问题,还发现代码其他错误并提供解决方法,最后还给出一般改进建议。
多模态提示呢?
代码提示仍使用常规大语言模型。多模态提示是另一回事,指使用多种输入格式引导模型,而非仅靠文本。可能包括文本、图像、音频、代码等组合,取决于模型能力和任务。
最佳实践
找到合适的提示需要反复尝试。Vertex AI的Language Studio是测试提示的好地方,可试用不同模型。
以下最佳实践帮你成为提示工程专家。
提供示例
最重要的实践是在提示中提供单样本或少样本示例。这很有效,因为示例是强大的教学工具,展示期望输出或类似回答,让模型学习并调整生成,匹配你的预期。这就像给模型一个参照点,提升准确性、风格和语气。
保持简单
提示应简洁、清晰,易于你和模型理解。经验法则是:如果你觉得提示已复杂,模型可能也觉得复杂。避免复杂语言和无关信息。
示例:
之前:
我现在在纽约,想知道更多好玩的地方。我带两个3岁小孩。度假期间该去哪儿?
重写后:
扮演游客向导,介绍纽约曼哈顿适合3岁小孩的景点。
尽量用描述动作的动词。示例动词:
扮演、分析、分类、对比、比较、创建、描述、定义、评估、提取、查找、生成、识别、列举、测量、组织、解析、挑选、预测、提供、排名、推荐、返回、检索、重写、选择、展示、排序、总结、翻译、编写。
明确输出要求
明确期望输出。简短指令可能不够引导模型,或过于泛泛。通过系统或上下文提示提供具体细节,帮模型聚焦相关内容,提升准确性。
示例:
正确:
生成一篇关于五大游戏主机的3段博客,内容需信息丰富、引人入胜,风格轻松对话化。
错误:
生成一篇关于游戏主机的博客。
优先使用指令而非约束
指令和约束用于引导模型输出:
- 指令:明确指定期望的格式、风格或内容,告诉模型该做什么。
- 约束:设定回答的限制或边界,告诉模型不该做什么。
研究表明,优先用正向指令比过多依赖约束更有效。这与人类更喜欢正向指导而非禁止清单一致。
指令直接传达期望结果,约束可能让模型猜测允许的内容。指令提供灵活性,鼓励在定义边界内的创意;约束可能限制模型潜力,且约束列表可能互相冲突。
约束在特定场景仍有价值,如防止生成有害或偏见内容,或需严格输出格式或风格时。
尽可能用正向指令:别告诉模型不做什么,告诉它做什么。避免混淆,提升输出准确性。
正确:
生成一篇关于五大游戏主机的1段博客,仅讨论主机、制造商、年份和总销量。
错误:
生成一篇关于五大游戏主机的1段博客,不要列出游戏名称。
最佳实践是优先用指令,清晰说明期望,仅在安全、清晰或特定要求时用约束。实验迭代,测试指令和约束组合,找到适合任务的方法,并记录。
控制最大令牌长度
控制生成回答长度,可在配置中设最大令牌限制,或在提示中明确指定长度。例如:
“用推文长度解释量子物理。”
在提示中使用变量
为复用提示并增加动态性,在提示中使用变量,可根据不同输入更改。例如表20,提示给出城市事实。用变量替代硬编码城市名称。变量节省时间,避免重复。若多提示需同一信息,可存为变量,在各提示中引用。在应用集成提示时特别有用。
表20. 提示中使用变量
提示 | 变量 {city} = “Amsterdam” 提示 | ||
---|---|---|---|
输出 | 你是旅行向导,告诉我关于{city}的一个事实。阿姆斯特丹充满运河、桥梁和狭窄街道,是体验丰富历史、文化和夜生活的绝佳之地。 |
尝试不同的输入格式与写作风格
不同模型、配置、提示格式、措辞和提交方式会产生不同结果。实验提示属性如风格、措辞和类型(零样本、少样本、系统提示)很重要。
例如,生成关于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截断问题的关键工具。
使用模式(Schemas)
结构化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": "产品发布日期" }
}
}
然后提供符合模式的产品数据JSON对象:
{
"name": "Wireless Headphones",
"category": "Electronics",
"price": 99.99,
"features": ["Noise cancellation", "Bluetooth 5.0", "20-hour battery life"],
"release_date": "2023-10-27"
}
通过预处理数据,仅提供模式和数据,而非完整文档,模型清楚产品属性,包括发布日期,更可能生成准确相关描述。结构化输入引导模型关注相关字段,处理大量数据或集成复杂应用时尤为有用。
与其他提示工程师一起实验
如果你需要尝试写好提示,可找多人一起尝试。若都遵循最佳实践(本章列出),不同提示尝试间会有性能差异。
思维链最佳实践
对于思维链提示,推理后放答案是必须的,因为推理生成改变了模型预测最终答案时的令牌。
用思维链和自我一致性需能从提示中提取最终答案,与推理分开。
思维链提示设温度为0。
思维链基于贪婪解码,根据模型分配的最高概率预测下一个词。推理得出最终答案通常只有一个正确答案,因此温度应始终设为0。
记录各种提示尝试
之前提到过,但再强调不够:详细记录提示尝试,长期学习哪些有效哪些无效。
提示输出因模型、采样设置甚至同模型不同版本而异。即使对同一模型相同提示,句子格式和措辞也可能略有不同(例如,若两个令牌概率相同,可能随机打破平局,影响后续预测令牌)。
建议用Google Sheet创建表21模板。优点是保留完整记录,便于未来重启提示工作(短暂停顿后你会惊讶自己忘了多少),测试不同模型版本的提示性能,调试未来错误。
除表中字段,建议跟踪提示版本(迭代)、结果是否OK/不OK/有时OK,以及反馈字段。若用Vertex AI Studio,保存提示(用文档中相同名称和版本),在表中跟踪保存提示的超链接,随时可重新运行。
在检索增强生成(RAG)系统中,还应记录影响提示内容插入的具体RAG系统细节,包括查询、分块设置、分块输出等信息。
提示接近完美后,放入项目代码库。在代码库中,提示与代码分开存储,便于维护。理想情况下,提示是运营系统的一部分,作为提示工程师,应依赖自动化测试和评估程序,了解提示对任务的泛化能力。
提示工程是迭代过程。编写和测试不同提示,分析记录结果。根据模型表现优化提示。不断实验直到获得理想输出。更换模型或配置时,回头实验之前用过的提示。
表21. 记录提示的模板
名称 | [提示名称和版本] | ||
---|---|---|---|
目标 | [一句解释尝试目标] | ||
模型 | [使用的模型名称和版本] | ||
温度 | [0-1之间的值] | 令牌限制 | [数字] |
Top-K | [数字] | Top-P | [数字] |
提示 | [完整提示内容] | ||
输出 | [输出或多个输出内容] |
总结
这篇白皮书讨论了提示工程,介绍了多种提示技巧,包括:
- 零样本提示
- 少样本提示
- 系统提示
- 角色提示
- 上下文提示
- 回溯提示
- 思维链
- 自我一致性
- 思维树
- ReAct
还探讨了如何自动化提示。
白皮书讨论了生成AI的挑战,如提示不足可能导致的问题。最后分享了成为更好提示工程师的最佳实践。
注释
- Google, 2023, Gemini by Google. 可用:https://gemini.google.com
- Google, 2024, Gemini for Google Workspace Prompt Guide. 可用:https://inthecloud.withgoogle.com/gemini-for-google-workspace-prompt-guide/dl-cd.html
- Google Cloud, 2023, Introduction to Prompting. 可用:https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/introduction-prompt-design
- 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
- Wei, J., et al., 2023, Zero Shot - Fine Tuned language models are zero shot learners. 可用:https://arxiv.org/pdf/2109.01652.pdf
- Google Cloud, 2023, Google Cloud Model Garden. 可用:https://cloud.google.com/model-garden
- Brown, T., et al., 2023, Few Shot - Language Models are Few Shot learners. 可用:https://arxiv.org/pdf/2005.14165.pdf
- Zheng, L., et al., 2023, Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models. 可用:https://openreview.net/pdf?id=3bq3jsvcQ1
- Wei, J., et al., 2023, Chain of Thought Prompting. 可用:https://arxiv.org/pdf/2201.11903.pdf
- 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
- Wang, X., et al., 2023, Self Consistency Improves Chain of Thought reasoning in language models. 可用:https://arxiv.org/pdf/2203.11171.pdf
- Yao, S., et al., 2023, Tree of Thoughts: Deliberate Problem Solving with Large Language Models. 可用:https://arxiv.org/pdf/2305.10601.pdf
- Yao, S., et al., 2023, ReAct: Synergizing Reasoning and Acting in Language Models. 可用:https://arxiv.org/pdf/2210.03629.pdf
- 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
- Zhou, C., et al., 2023, Automatic Prompt Engineering - Large Language Models are Human-Level Prompt Engineers. 可用:https://arxiv.org/pdf/2211.01910.pdf
PDF版本:微信公众号(我在副本写代码)回复“提示工程” 获取!