LLM Prompt工程框架
LLM Prompt工程框架
什么是Prompt工程
随着LLM的发展和爆发,Prompt工程越来约热门。提示工程(Prompt Engineering)是一种与大型语言模型(LLMs)交互的方法,它涉及设计、优化和实施提示(prompts),以指导模型的输出,帮助完成各种任务。提示工程的核心在于有效地与人工智能系统进行沟通,以最大化其效益。以下是一些关于提示工程的关键点:
- 设计:创建能够引导语言模型产生预期输出的提示。
- 优化:不断调整和改进提示,以提高模型在特定任务上的表现。
- 实施:将设计好的提示应用于实际的语言模型中,以执行任务。
- 评估:评估提示的效果,通常通过模型的输出质量和性能指标来衡量。
- 迭代:根据评估结果,反复迭代提示的设计和优化过程。
这个过程可以人工实施,也可以让大模型LLM自己循环执行直到获取好的结果,类似于Gradient梯度优化
为什么Prompt工程有效
首先我们要明白提示词与提示工程是两个不同的概念,提示词是直接提供给语言模型的输入,用以引导模型生成特定的输出或执行特定的任务。 它是一个具体的实例,可以是一个问题、一段文本、一个指令或者任何形式的输入,旨在激发模型进行特定的语言生成或决策过程。
提示工程(Prompt Engineering)是指设计和优化提示词的过程,以提高语言模型在特定任务上的表现。 它包括了对提示词的结构、内容、风格和上下文的精心设计,以及对模型响应的评估和迭代改进。
提示工程是一个更为广泛和系统的概念,涉及到对提示词效果的测试、分析和优化,以实现更好的交互和输出质量。
所以关于为什么Prompt工程有效这个问题也应该分为两部分来看:
为什么Prompt能优化模型输出结果
抛开LLM本身的原理不看,在人类互相的对话过程中也有很多的问题,比如说的请问题背景不清楚,有歧义等问题,与大模型对话类似,这种基本的语言问题应该是我们首先也解决 在这些问题的背景下我们可以通过适当的完善提示词Prompt肯定可以保障生成的质量和效果,如:
- 完善上下文:提供执行任务所需的上下文信息。这有助于模型更好地理解任务的背景和目标,从而生成更合适的回答
- 减少歧义:减少语言中的歧义性,确保模型在生成回答时能够聚焦于用户的真实意图,这里的歧义性不仅仅是我们传统意义上的歧义,有时候我们为了降低模型本身不确定性,也应该尽量减少多义词等的使用
- 指定输出的风格和格式:我们可以添加一些具体的要求让模型生成特定格式的内容。比如我们发现希望模型做一些活泼的输出,也要在要求中明确要求 如此类似的一些内容,从我们直觉上就可以理解通过完善Prompt肯定可以对模型的输出质量产生影响
从LLM模型生成原理上来看,我们也可以理解,对Prompt输入的修改,通过Embedding生成向量的时候也会产生影响,对任务的背景、要求、案例的说明都会Embeding到具体的任务上去,通过Transformer的处理,就可能引起不同的注意力头的关注,转换成更具体标准的领域问题。在Feed-Forward的变换与激活过程中,类似于模型中存储知识的应用,更容易获得高质量的输出 至于在LLM中更加精准明确的作用机制与原理,这个就很难进行解释了,目前来看暂时没有研究可以准确的得到具体Prompt的调整对输出的影响具体是哪些参数的作用及其相互作用原理
为什么Prompt Engineering能优化模型输出结果
这个就很好理解了,提示工程是一种工程化的方法来优化Prompt。 这些工程化的方法包括让你以模板化的方法定义Prompt,通过标准的评估策略来评估调整的效果, 通过标准化的梯度的或者非梯度的方法来迭代优化Prompt 通过工程化的方法,我们可以标准化高效的来得到效果相对更好的Prompt(不是最好,没法评估最好)
我们很好理解这些工程化方法对我们是有帮助的,举个例子来说,我们使用梯度方法来迭代优化Prompt,每一轮迭代我们会调整我们的Prompt、对调整后的Prompt进行评估、根据评估结果进一步调整Prompt,这个过程我们很好理解,但是迭代的方向和步长怎么定义呢,这里我认为就缺少严谨的数学理论支撑了,更多的是通过经验与总结
几个Prompt可能有的部分
一个Prompt提示词应该有哪些内容,这不是一个明确的标准或者要求,更多是基于之前经验的总结,即根据之前的论文、实践、研究,有哪些内容可能是对提示词优化有帮助的
- 指令(Directive):这是提示词的核心,通常以指令或问题的形式出现,指导模型完成特定的任务或生成特定的输出。
- 示例(Examples):也称为示例或示范(Exemplars),作为完成任务的示例,引导模型理解任务要求。
- 输出格式化(Output Formatting):指定模型输出的格式,例如要求以CSV或Markdown格式输出信息。
- 风格指导(Style Instructions):用于修改输出的风格,而不是结构,例如指示模型以“清晰而简洁”的方式写一段关于羊驼的段落。
- 角色(Role):也称为角色提示(Role Prompting)或人物设定(Persona Prompting),通过指定模型在提示中扮演的角色来改善写作风格和文本。
角色设定在LLM刚出现火爆的一段时间里比较热门,给定LLM一个角色如“你是一个xxx专家”等等可以指导LLM做更严谨的输出,但是在最近的一些研究里,也有很多的研究发现针对现在的大模型,角色已经没有作用,甚至加上可能会有反作用,所以要针对具体的情况实际测试来看,这里都是一些经验的总结,这些提示词的部分不全是有效的,而且随着时间模型的发展也不一定一直有效
- 附加信息(Additional Information):根据需要在提示中包含的额外信息,例如写电子邮件时可能包括你的名字和职位,以便模型能够正确地签署电子邮件。
几种通用的Prompt范式
少样本提示/上下文学习 Few-Shot/In-Context Learning(ICL)
In-Context Learning (ICL) 是指通过在提示中提供示例和/或相关指令,使生成性人工智能(GenAI)系统能够在没有权重更新/重新训练的情况下学习技能和任务。 在提示工程中主要是Few-Shot的方式,通过在提示词中增加示例让LLM学习模仿解决问题生成代码
因为LLM上下文的长度限制,我们只能添加有限多个示例,所以示例的选择是影响ICL的关键点,下面重点介绍下如何选择样例
示例选择的关键决策点
-
Exemplar Quantity(示例数量) 增加提示中的示例数量通常会提高模型性能,尤其是对于较大的模型。然而,在某些情况下,超过一定数量的示例(例如20个)之后,性能提升可能会减少。
-
Exemplar Ordering(示例排序) 示例的顺序会影响模型的行为和准确性。在某些任务中,示例顺序的变化可能导致准确率从低于50%到超过90%。这里的顺序如在判断对错的任务中示例中正反例的出现顺序,我们希望尽量随机而不是正例在一起反例在一起
-
Exemplar Label Distribution(示例标签分布) 提示中示例标签的分布会影响模型的行为。例如,如果一个类别的示例数量远多于另一个类别,模型可能会偏向于多数类的标签。
-
Exemplar Label Quality(示例标签质量) 尽管多个示例通常有益,但正确示例标签的必要性尚不清楚。标签就是示例中对Answer的描述。一些研究表明,即使示例标签不正确,也可能不会显著降低性能。但在特定设置下,标签质量对性能有显著影响。
-
Exemplar Format(示例格式) 示例的格式也会影响性能。常见的格式是“Q: {input}, A: {label}”,但最优格式可能因任务而异。在训练数据中常见的格式可能会带来更好的性能。
-
Exemplar Similarity(示例相似性) 选择与测试样本相似的示例通常有利于提高性能。然而,在某些情况下,选择更多样化的示例可以提高性能。
示例选择的技术
针对Few-Shot中示例的选择,假如我们有一组示例的数据集,针对特定的问题,我们如何从中选择效果最好的几个示例,这里有一些技术可以参考
-
K-Nearest Neighbor (KNN):选择与待预测样本在候选集特征空间中最近的K个示例,以提高模型对新样本的预测性能
-
Vote-K:也是选择与问题相似的示例来帮助决策方法,核心思想是从示例集中召回与问题相似的k个示例,根据示例的结果标签进行投票获得结果。
-
Self-Generated In-Context Learning (SG-ICL):利用LLM自动生成示例。这些自生成的样本在训练数据不可用时比零样本场景下更有效,但生成的样本不如实际数据有效。
-
Prompt Mining:通过大型语料库分析,找出与LLM训练预料库中出现更频繁的格式,以这种形式来组织示例和问题。
零样本提示 Zero-Shot
零样本提示,因为不需要示例,所以需要在一些trick加到提示词中让LLM表现的更好,主要的方式如:
- 角色/特征提示 Role Prompting (Persona Prompting):给LLM设定一个角色或者一种特性,这个比较简单就不多说了
- 风格提示 Style Prompting:给LLM指定一种回复的风格、语调
- 情感提示 Emotion Prompting:包含一些与人类心理相关的提示短语,比如“这对我的职业生涯很重要”,对应的希望LLM给一些审慎的答复
- System 2 Attention (S2A):更多的使用在RAG等场景中,让LLM重写Prompt,删除掉Prompt中与问题不相关的内容,利用LLM以自然语言进行推理和遵循指令的能力来决定要关注什么。因为由于Transformer模型的自注意力机制,模型可能会将上下文中不相关的信息纳入到其潜在表示中,对下一个词的生成产品不利影响。
- Rephrase and Respond (RaR):添加如
Rephrase and expand the question, and respond
(重新措辞并扩展问题,然后再回答)这种方式,让大模型先优化问题再做回答 - Re-reading (RE2):通过增加
Read the question again:
这种句子到提示词中,让模型加重问题的权重,这种方式在一些复杂问题、推理上的性能有一定提升 - Self-Ask:让模型自己做Plan,自己问自己。提示LLM首先决定是否需要针对给定的提示询问后续问题。如果是,LLM生成这些问题,然后回答这些问题,最后回答原始问题
思维生成 Thought Generation
思维生成包括一系列技术,这些技术促使LLM在解决问题时阐明其推理过程,提升问题的解决率。主要的是CoT思维链的提示方式 CoT思维里的提示也可以分成两部分,一部分是没有示例,直接通过提示词的优化来提升性能,另一种可以给定一些推理过程的示例,一般情况下,有示例的CoT效果会更好 CoT的示例应该包括题目本身、推理过程、正确答案几个部分,其中最主要也是区别一般示例的是要将推理过程也放到示例中
零样本CoT Zero-Shot CoT
我们常见的零样本CoT的提示方式如:
- Let’s think step by step. 让我们逐步思考
- Let’s work this out in a step by step way to be sure we have the right answer. 让我们一步一步地解决这个问题,以确保我们得到正确的答案
- First, let’s think about this logically. 我们先从逻辑上思考这个问题
除了这些常见的方式,也有其他的一些技术在特定场景下可以提升CoT的准确性
- Step-Back Prompting: 这是CoT的一种修改,其中LLM首先被问到一个关于相关概念或事实的一般性、高层次的问题,然后再深入到推理中。
- Analogical Prompting: 让LLM自动生成带有CoT过程的示例
- Thread-of-Thought (ThoT) Prompting: 主要用于处理复杂上下文的场景。简单来看可以通过一段prompt让大模型一步步的分析总结,根据不同的上下文片段分析提取出不同的相关信息,再让大模型生成最终的结果,这种思想可以进行扩展,形成标准化的步骤
Walk me through this context in manageable parts step by step, summarizing and analyzing as we go.
- Tabular Chain-of-Thought (Tab-CoT):让LLM以Markdown表格的形式输出推理步骤
这些技术被验证在特定场景下是有效的,在实际使用中,可以根据实际的情况评估使用
少样本CoT Few-Shot CoT
有一些带思维过程的示例加到提示中,下面介绍一些示例选择以及结果评估选择的方法,同样的,这些方法在特定的场景下被证明有效,具体使用时根据实际情况选择。重点要了解相关思想
- Contrastive CoT Prompting:在提示中既有正确推理过程的示例,也有错误推理过程的示例。让LLM知道什么是对的,什么是错的
- Uncertainty-Routed CoT Prompting:通过对LLm采样的方式选择多个CoT推理路径,并基于验证数据进行评估,如果路径评估结果高于某个阈值,则选择这个路径
- Complexity-based Prompting:选择问题、推理过程复杂的、长的示例,对生成的结果进行采样,同样选择复杂的、长的作为结果
- Active Prompting:使用训练问题/样本构造提示,要求LLM解决这些问题,然后看结果的不确定性,并要求人类注释者重写具有最高不确定性的样本
- Automatic Chain-of-Thought (Auto-CoT) Prompting:利用零样本CoT的方式生成样例,然后放到少样本CoT的提示词中使用
问题分解 Decomposition
在解决复杂问题时,先将问题分解成多个简单问题再交给大模型解决,这种方式已经成为了一种标准的解决范式
- Least-to-Most Prompting:提示LLM将给定的问题分解成子问题但不求解。然后依次求解它们,每次都将模型响应附加到提示中,直到得到最终结果
- Decomposed Prompting (DECOMP):告诉LLM可以使用的Tools,让LLM将问题拆解成Tool Use的从而将问题分解的过程
- Plan-and-Solve Prompting:通过提示词的方式让LLM先分解问题再解决问题
Let’s first understand the problem and devise a plan to solve it. Then, let’s carry out the plan and solve the problem step by step
- Tree-of-Thought (ToT):ToT是以树的形式来组织推理步骤,以树的形式来组织执行的步骤或者叫思路,使用BFS或者DFS的树遍历算法来对整个thought树进行遍历校验,找出可能性最高的路径
- Recursion-of-Thought:递归的解决,在分解的问题复杂度比较高或者超过上下文长度的时候,可以交给另外一个Prompt/LLM来解决这个子问题,然后将结果替换回原来的问题中
- Program-of-Thoughts:让LLM生成编程代码作为推理步骤
- Faithful Chain-of-Thought:让LLM生成既有自然语言处理的步骤也有编程代码的步骤的推理路径
- Skeleton-of-Thought:主要时通过并行的方式提高回答速度,先让LLM生成问题解决的推理路径作为骨架,然后并发的解决这些子问题
集成 Ensembling
集成是使用多个不同的Prompt来解决同一个问题,然后将这些响应聚合为最终输出的过程。在许多情况下,多数投票(选择最频繁的响应)用于生成最终输出。 这种技术减少了LLM输出的方差,通常提高了精度,但代价是增加了获得最终答案所需的模型调用次数。 这种技术主要要解决如何获得多个结果以及如何从多个结果中选择最优的
- Demonstration Ensembling (DENSE):使用不同的样例创建几个不同的提示,然后交给LLM生成结果,最后合并这些结果。合并的方式有很多,可以投票,可以交给大模型选择等等
- Mixture of Reasoning Experts (MoRE):使用RAG、CoT等不同的推理技术构造提示,生成多个结果
- Max Mutual Information Method:创建不同样式不同样例的提示,最后选择提示和输出最大互信息的结果
- Self-Consistency:利用LLM的非零的temperature进行多次采样生成多个结果
- Universal Self-Consistency:将采样到的多个结果放到LLM提示词中,让LLM选择一个最优的
- DiVeRSe:使用多种不同的提示词方式,然后在使用Self-Consistency的方式多次采样,生成更多的推理路径
- Consistency-based Self-adaptive Prompting (COSP):
- 先使用Self-Consistency的方式多Zero-Shot CoT多次采样生成样例
- 用示例构造Few-Shot的Prompt
- 使用Self-Consistency的方式对Few-Shot的Prompt进行结果采样
- Prompt Paraphrasing:通过一些修改一些词汇但不改变整体含义的方式来转换修改Prompt,进而得到多个结果
自我评估 Self-Criticism
让LLM自己对自己生成的结果进行批评评估,进而以此为依据让LLM优化结果,这也是一种已经被证明的有效的方法。看来自我批评不光在人自己的改进上有用,对LLM同样适用…
- Self-Calibration:先让LLM生成一个结果,然后用问题、LLM的结果构造一个新的提示,让LLM判断结果是否正确
- Self-Refine:先让LLM生成一个答案,然后让提供对这个答案的反馈,再让LLM根据这个反馈改进答案
- Reversing Chain-of-Thought (RCoT):首先提示LLM根据生成的答案重构问题。然后在原始问题和重构问题之间生成细粒度的比较来找到不一致的地方。然后将这些不一致转换为LLM的反馈,以修改生成的答案
- Self-Verification:基于CoT生成多个候选的方案,然后通过掩盖原始问题的某些部分,要求LLM基于问题的其余部分和生成的解决方案来预测这些部分,然后对每个解决方案进行评分
- Chain-of-Verification (COVE):先用LLM来生成问题的答案。然后创建一个验证答案的正确性相关问题列表。每个问题都由LLM回答,最后将所有信息提供给LLM以产生最终的修订答案。
- Cumulative Reasoning:在回答问题时产生了几个可能的步骤。然后让LLM评估决定接受或拒绝这些步骤。每执行异步检查它是否已经得到最终答案,如果是就结束,否则就重复。