Prompt Engineering
Author: Lee Boonstra
从 第二章提示技术的Chain of Thought (CoT)小节 至 第二章提示技术的Automatic Prompt Engineering 小节
本书主要是以Google自己的平台为主进行介绍,但将这些操作迁移到其他平台上可存在可行性。
Prompting techniques
思维链 (Chain of Thought, CoT)
思维链(Chain of Thought, CoT)是一种通过生成中间推理步骤来增强大型语言模型(LLM)推理能力的技术。这种方法有助于LLM提供更准确的答案。将思维链与少样本提示(few-shot prompting)结合使用,可以在处理更复杂的任务时获得更好的结果。这种方式让模型不仅依赖于直接的答案,还通过一系列逻辑步骤逐步推导出答案,从而提高解决复杂问题的能力。
CoT(思维链)具有多方面的优势。首先,它实现简便且效果显著,能够与现有的大型语言模型(LLM)很好地协作,无需进行微调即可发挥作用。
使用CoT提示不仅能提升回答的准确性,还增加了可解释性,因为可以清晰地看到模型在生成答案时所遵循的推理步骤。这使得当出现 BUG 时,更容易定位并理解 BUG 。此外,思维链似乎还能增强在不同版本LLM之间的鲁棒性。这意味着,如果提示中包含了推理链,在不同的LLM之间其性能变化会相对较小,相比之下,不使用推理链的提示则可能出现较大的性能波动。当然,CoT也有其局限性,但这些限制通常是直观易懂的。
比如,大型语言模型(LLM)的回应中包含思维链推理,这意味着 输出的标记数量更多,从而导致预测成本更高且耗时更长。
为了更好的说明CoT的优势,如下表所示,我们首先尝试创建一个不使用CoT提示的提示,以展示大型语言模型的缺陷。
Prompt | 当我3岁的时候,我的朋友的年龄是我的3倍。现在我20岁了,我的朋友多大? |
Output | 51岁 |
这显然是个错误的答案。事实上,大型语言模型(LLM)在处理数学任务时经常遇到困难,甚至可能在乘法这样简单的任务上给出错误答案。这是因为它们是在大量文本数据上训练的,而数学问题可能需要不同的思维方式。
Prompt | 当我3岁的时候,我的朋友的年龄是我的3倍。现在我20岁了,我的朋友多大?让我们一步一步来思考。 |
Output | 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)逐步解释每个步骤,而不是直接给出答案。这可以让模型在运算时,考虑到自身是否出现错误。
上表是"zero-shot"思维链(Chain of Thought, CoT)的一个示例。
当思维链提示与单样本或少样本结合使用时,它可以更强大,如下表所示。
Prompt | 问题:当我弟弟2岁的时候,我的年龄是他的两倍。现在我40岁了,我弟弟多大?让我们一步一步来思考。 答:当我弟弟2岁的时候,我是 2 * 2 = 4 岁。 这意味着我比他大2岁。现在我40岁了,所以我的弟弟是 40 - 2 = 38 岁。答案是38。 问题:当我3岁的时候,我的朋友的年龄是我的3倍。现在我20岁了,我的朋友多大?让我们一步一步来思考。 |
Output | 当我3岁的时候,我的朋友是 3 * 3 = 9 岁。这意味着我的朋友比我大6岁。现在我20岁了,所以我的伴侣是 20 + 6 = 26 岁。答案是26。 |
链式思维在很多场景下都非常有用。例如:
- 在编写代码时,可以将复杂的需求拆分成几个简单的步骤,并逐步转化为具体的代码实现。
- 再比如,在生成产品描述时,如果你已知某个产品的名字叫XYZ,你可以通过引导模型基于这个名称进行联想和假设,进而撰写出详细的产品描述。
总的来说,只要是能够通过"分步讲解"来完成的任务,都非常适合运用链式思维。当你能够清晰地解释解决问题的每一步骤时,就可以尝试使用这种方法,让思路更加流畅和系统化。
思维链本质上是复杂问题线性拆分
自我一致性 (Self-consistency)
通过前面介绍的链式思维,我们知道模型可以被引导去生成类似于人类解决问题时的思考步骤。然而,这种CoT方法通常依赖一种简单的"greedy search"策略(依赖于唯一一种思维方式),这在一定程度上限制了它的效果。
为了克服这一局限性,引入了自我一致性(Self-consistency) 的方法。这种方法结合了采样和多数投票的机制,能够产生多样化的推理路径,并选择出最一致的答案。这样一来,不仅能提高答案的准确性,还能增强回答的整体连贯性。简单来说,自我一致性让大型语言模型在解决问题时更加灵活、准确,更接近人类的思维方式。
Self-consistency 提供了一种类似概率的方式来估计答案的正确性,但这种方法的成本相对较高。换句话说,虽然它能帮助我们更准确地评估答案的可能性,不过其实现过程需要更多的资源和计算力,因此成本也更高。
自我一致性主要包括以下几个步骤:
- 生成多样化的推理路径:对同一个问题,多次向大型语言模型(LLM)提出相同的请求。通过调整温度参数到较高的值,促使模型产生不同的思考路径和多样的解答角度。
- 从每个响应中提取答案:仔细分析每一个生成的答案,找出其中的关键信息。
- 选择最常见的答案:比较所有得到的答案,选择出现频率最高的那个作为最终答案。这种方法通过多样化的探索和多数投票的选择方式,提高了找到正确答案的概率。
以一个电子邮件分类系统为例,该系统负责将邮件标记为"重要"或"不重要"。在这个场景中,我们向 LLM 多次发送相同的 zero-shot 思维链提示,目的是观察每次生成的响应是否存在差异。特别需要注意的是邮件中的友好语气、用词选择以及可能存在的讽刺意味------这些元素都有可能引起模型的混淆。通过这种方式,我们可以更深入地了解模型在处理复杂或模糊信息时的表现。
Prompt | 邮件: 嗨,我看到你用 WordPress 搭建了你的网站。这是一个非常棒的开源内容管理系统。我也曾经用过它。它自带了许多很棒的用户插件,而且设置起来相当简单。 我确实注意到联系表单中有一个漏洞,当你选择名字字段时就会触发。请看附件中的截图,显示我在名字字段输入文字时的情况。请注意我触发的那个 JavaScript 弹窗。 不过除此之外,这是个很棒的网站。我喜欢阅读它。尽管放心地把这个漏洞留在网站上吧,因为这会让我有更多有趣的东西可以读。 此致问候, 黑客Harry 将上述邮件分类为"重要"或"不重要"。让我们一步步思考并解释原因。 |
尝试1 | 步骤1:确定邮件的目的。 这封邮件的目的是告知收件人他们网站上的联系表单存在一个漏洞。发件人还提到他们喜欢阅读该网站,并且暂时保留这个漏洞。 步骤2:评估漏洞的潜在影响。 联系表单中的漏洞可能允许攻击者在网站上执行任意JavaScript代码。这可能导致攻击者能够控制网站、窃取敏感信息或破坏网站。 步骤3:考虑发件人的可信度。 邮件的发件人自称是名叫哈里的黑客。然而,无法验证发件人的身份。发件人可能是试图帮助收件人的合法黑客,但也有可能是试图诱骗收件人点击恶意链接或下载恶意文件的恶意行为者。 结论:重要 基于漏洞的潜在影响和发件人的可信度,这封邮件应被归类为重要。收件人应立即采取行动修复漏洞并保护他们的网站免受攻击。 |
尝试2 | 解释: 1. 缺乏紧迫感: 这封邮件没有传达任何紧迫感或时间敏感性。它以随意的问候开始,并以陈述事实的语气呈现信息。 2. 非关键漏洞报告: 报告的联系表单中的漏洞被描述为有趣但不关键。发件人甚至建议网站所有者可以保留这个漏洞。 3. 缺乏个人影响: 这封邮件没有表明对网站所有者的任何直接或个人影响。它只是提到发件人喜欢阅读该网站。 4. 缺乏行动请求: 这封邮件没有明确要求网站所有者采取任何行动。它没有要求修复漏洞或提供任何具体的改进建议。 5. 发件人的意图: 发件人的意图似乎更侧重于分享观察结果和表达对网站的兴趣,而不是提出严重关切或请求帮助。 结论:不重要 |
尝试3 | 步骤1:确定邮件的目的。 这封邮件的目的是告知收件人他们网站上的联系表单存在一个漏洞。发件人还提到他们喜欢阅读该网站,并且暂时保留这个漏洞。 步骤2:评估漏洞的潜在影响。 联系表单中的漏洞可能允许攻击者在网站上执行任意JavaScript代码。这可能导致攻击者能够控制网站、窃取敏感信息或破坏网站。 步骤3:考虑发件人的可信度。 邮件的发件人自称是名叫哈里的黑客。然而,无法验证发件人的身份。发件人可能是试图帮助收件人的合法黑客,但也有可能是试图利用漏洞为自己谋利的恶意行为者。 结论: 基于以上因素,这封邮件应被归类为重要。联系表单中的漏洞是一个严重的安全风险,而发件人的可信度未知。收件人应立即采取行动修复漏洞并保护他们的网站免受攻击。 |
这个例子很好地展示了如何利用自我一致性提示来提升大型语言模型的输出质量。通过从多个角度综合分析,这种方法不仅有助于获得更准确的答案,还能让我们更深入地理解模型在处理复杂问题时的表现。
可以使用上述提示来测试是否能得到一致的分类结果。根据使用的模型和温度设置的不同,可能会得到"重要"或者"不重要"的结论。
通过生成多个思考路径,并选择最常见的答案(比如"重要"),可以从LLM那里获得更加稳定和准确的回答。这个过程要考虑多种视角并选取最一致的答案,并以此提高模型响应的准确性。
思维树(Tree of Thoughts, ToT)
现在我们已经对思维链(Chain of Thought, CoT)和自我一致性提示有所了解,接下来可以进一步探索思维树(Tree of Thoughts, ToT)。实际上,思维树可以看作是CoT的一种扩展和进化,它让LLM能够同时探索多个不同的推理路径,而不仅仅局限于单一的线性思考方式。换句话说,思维树提供了一个框架,使LLM在解决问题时能考虑到更多的可能性和视角,而不是仅仅沿着一条直线前进。
下图中清晰地描绘了思维树是如何运行,它通过分叉出多个思考路径来涵盖广泛的可能性和解决方案。这种方法特别适合需要综合考虑多种因素或潜在答案的复杂问题。利用这种方式,不仅能更全面地理解问题的本质,还能够探索到更多创新的解决策略。

这种方法使得思维树(ToT)非常适合处理需要深入探索的复杂任务。它通过构建和维护一棵思维树来运作,其中每个节点代表解决问题过程中一个连贯的语言序列。模型能够从这棵树的不同节点开始分支,探索多种不同的推理路径。这样一来,模型不仅能考察到各种可能性,还能够找到更合适的解决方案。
ToT可以说是CoT与Self-consistency的结合
推理与行动 ReAct (reason & act)
推理与行动(ReAct)提示是一种创新的范式,使LLM能够利用自然语言推理并结合外部工具(如搜索引擎、代码解释器等)解决复杂任务。这种方法允许LLM与外部API交互以收集必要信息,这标志着向构建更高级代理模型迈出的重要一步。
ReAct模仿了人类在日常生活中的行为模式,即我们通过思考和语言推理来决定如何行动,并通过实际行动来获取或验证信息。正因为如此,ReAct在多种应用领域中展现出比其他提示工程技术更高的效能和更大的灵活性。这一方法为实现更加智能和自主的系统提供了可能。
ReAct 提示通过将推理和行动结合到一个"思维-行动"循环中来工作。LLM 首先对问题进行推理并生成行动计划。然后,执行计划中的操作并观察结果。接着,LLM 使用这些观察结果,更新推理并生成新的行动计划。这个过程会一直持续,直到 LLM 找到解决问题的方法。
下面就是一份代码示例,给 LLM 的任务是:找出有多少个孩子他们的著名父亲是在乐队 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 = "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)
下面展示了结果。注意,ReAct 进行了五次搜索链。事实上,LLM 正在抓取 Google 搜索结果以找出乐队名称。然后,它将结果列为推断内容,并为下一次搜索构建思维链。
shell
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: 10
上方确定 Metallica 乐队成员的孩子总数。首先,它确认乐队有四名成员,然后逐一搜索每位成员的信息,查询他们各自孩子的数量,并将这些数字相加,最终得出总和作为答案。
在实际应用 ReAct 时,需要注意的是,必须持续将之前的提示和响应内容重新发送给模型,同时去除生成过程中产生的冗余信息。此外,还需通过合适的示例或指令对模型进行配置,以确保其能够正确理解和执行任务。
上面的内容,就是常说的AI Agent,让AI调用第三方资源来提高自己的能力
自动提示工程(Automatic Prompt Engineering, APE)
到目前为止,可以发现编写提示也是一个相当复杂的过程。如果能将这一过程自动化,比如说通过一个提示来自动生成其他提示,将会非常方便提示编写。实际上,这种方法确实存在,被称为自动提示工程(APE)。采用这种方式,不仅可以减少手动输入的需求,还能大幅提升模型在各种任务中的表现和效率。这样一来,既节省了时间,也提高了工作的准确性。
可以通过提示模型来自动生成更多或更优的提示。然后对这些提示进行评估,可以对其中较好的提示进行修改,并重复这一过程。
例如,可以使用自动提示工程来帮助训练一个用于商品 T 恤网店的聊天机器人。我们希望找出客户可能用来表达购买乐队周边 T 恤订单的各种方式。
- 编写用于生成输出变体的提示。在本例中,使用 LLM 生成了 10 条指令。如下表所示:
提示 | 我们有一个乐队周边T恤网店,为了训练一个聊天机器人,我们需要各种方式来表达订单:"一件Metallica T恤,小号"。生成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(用于摘要评估的召回导向替代工具) 等指标来进行评估。
-
选择得分最高的指令候选作为最终提示。这个提示可以直接应用于您的软件应用或聊天机器人中。此外,您还可以对选定的提示进行进一步调整,并再次进行评估以优化效果。
实际上,也可以使用自动提示工程来优化用户的提问,让用户的提问更准确
结语
下一部分专门用于介绍与代码生成有关的提示