不久前,笔者分享了3篇自动prompt engineering的工作:APE、APO以及OPRO,至今已两月有余,在这期间又出现了一些新的工作,因此本文对该领域进行一次update。
本文主要分享3篇工作:PE2[1]、LongPO[2]以及BPO[3]。
其中, PE2 重在优化optimizer LLM本身的meta-prompt,属于纵向研究; LongPO 探究长prompt设置下的调优方法,属于横向研究; BPO 则提出一种预先训练、即插即用的新方法。
PE2:迭代optimizer LLM
PE2的全称是: Prompt Engineering a Prompt Engineer
,这也点明了其核心思路: 对用来prompt engineer的LLM(即optimizer LLM),进行prompt engineering 。
一般来说, prompt optimization with LLM 包含以下3个步骤:
- Prompt initialization 。即初始prompt,常见有两种初始化方法,一是人工设置,二是自动设置(
prompt induction
,即提供input-output给LLM,让LLM自己写prompt,APE采取了此类方法)。该论文指出,初始prompt的好坏直接影响优化的效果上限,因此写出较好的初始prompt很重要; - New prompt proposal 。即prompt的迭代过程,这一步由optimizer LLM来完成。在APE中,optimizer LLM主要做rephrase(改写,但保证语义相同);在OPRO中,optimizer LLM基于task description、过往的迭代记录进行逐步优化;
- Search procedure 。为保证迭代过程的鲁棒性,通常会有一个起保障作用的搜索策略。例如包含
back-tracking
过程,即允许回溯过去的prompt。该论文的方法是,在每一轮迭代时,均从过去所有prompt中保留n个表现最好的prompt ,同时在本轮迭代中,对 n个prompt,采样m个不同的batch ,迭代得到m * n个新prompt ,送入下一轮迭代。
PE2方法的核心是 优化optimizer LLM的meta-prompt ,迭代方向有两个:
providing detailed instructions and context
incorporating common optimizer concepts
具体思路如下:
- 以下4个模块属于
providing detailed instructions and context
- prompt engineering tutorial 。提供给LLM一个tutorial,帮助其理解如何进行prompt engineer。但实验发现用处不大 ,因此在对比实验中并未使用 ;
- two-step task instruction 。显式地把prompt optimization的任务分解为了two-step,step1是
Examine the prompt and a batch of examples
,step2是Propose a new prompt based on youer reasoning
。实验证明 有用 ; - step-by-step reasoning template 。在step1中,examine example的指令还是不够具体,因此作者又进一步提供了Chain-Of-Thought信息,让其对每一个example执行4步reasoning,包括
Output is correct?
、Prompt describing the task correctly?
、Necessary to edit the prompt?
以及If yes, suggestions on prompt editing?
实验证明 有用 ; - context specification 。即将inference时的具体prompt template提供给LLM,使其理解自己需要优化的prompt是如何使用的,实验证明 有用 ;
- 以下3个模块属于
incorporating common optimizer concepts
- batch size 。提供预测错误的n个examples给LLM,让其进行优化,n的大小即batch size。实验证明batch size的效果不明显 ,因此默认用batch size=2;
- step size 。限制optimizer LLM更新prompt的幅度,即限制其修改word的数量 。实验证明step size效果不明显 ,因此在对比实验中没有使用;
- optimization history 。包括了过去所有的prompt以及其dev set 效果,以及prompt edit的summary,类比Momentum。实验证明效果不明显 ,因此在对比实验中没有使用。
PE2在对比实验中,仅使用了 two-step task instruction + step-by-step reasoning template + context specification + batch size(=2),涉及optimizer concept的策略在实验中效果并不明显,作者提到这与调参过程有噪音、task-dependant、LLM对prompt的敏感度、LLM的instruction follow 能力等因素有关,因此为简便起见,仅使用了batch size技术。
LongPO:针对长prompt的调优方法
长prompt调优的难点是: 如何在优化时尽量保证prompt的一致性 。
如果直接将长prompt作为输入,去跑APE方法(核心是rephrase),有以下难点:
- 将几百字长的prompt直接进行rephrase,对LLM挑战大;
- 面临不可控问题 -- LLM可能改动的地方太多,导致优化有收敛问题。
因此,这篇文章引入了一个sentence挑选机制: 在每轮优化时,选择一个sentence进行调优 。
其单次迭代的流程如下图所示:
整个流程的核心点如下:
- 优化单位为sentence;
- 采用
Lin-UCB
算法来选择待优化sentence
- 这是个
contextual bandit problem
,其中arms对应m个sentences、每个arm有对应的feature vector、拉下arm带来的reward对应调优后的task metric提升 - 每个arm的feature vector使用其sentence embedding,原文使用T5-encoder进行表征
- 针对选出的sentence进行prompt optimization
- optimizer LLM :核心方法是 rephrase,直接通过prompting LLM实现;同时引入历史正向迭代数据辅助迭代,使用
few-shot In Context Learning
的思路,检索出Top 4语义相似的数据,作为examples。完整prompt如下所示。
- search procedure :由于LLM本身对prompt的细微改动比较敏感,为使整个优化过程更加stable,本法采取
greedy beam search
策略,既 始终保持效果最好的Top K** prompts** 。
- 重复上述两个步骤 - 选sentence、对sentence进行迭代,直到达到既定的停止条件(如达到iteration轮数)即停止,完成迭代过程。
BPO:一次训练、反复使用的新方法
截至目前,笔者所介绍的5种prompt engineering/optimization方法(APE、APO、OPRO、LongPO、PE2) 都需要训练 ,其优化过程是一个machine learning过程: 在train set上进行prompt optimization,然后在val set上挑选效果最好的prompt,将其用于最终的inference 。
而 BPO期望训练一个sequence-to-sequence model,输入original prompt,直接输出优化后的prompt 。之后需要进行prompt optimization时,直接使用这个model即可,即插即用、无需训练。
其训练步骤如下:
- 收集human preference data 。论文中直接选择open-source dataset,包括OASST1、Chatbot Arena等,这些数据的通常结构为(prompt, chosen_response, rejected_response);
- 用LLM生成优化后的prompt,构成pair data 。主要由两步组成(即COT),第一步是criticize,让LLM对比chosen_response和rejected_response,得到两者的区别,第二步是让LLM基于批判结果 + 原prompt,生成改进后的prompt,构成pair数据,其prompt如下所示。
3. 基于pair data,训练seq2seq model 。论文选取 llama2-7b-chat
进行fine-tuning,得到了一个 pre-trained prompt optimizer
。
BPO最有趣的特性在于,其prompt优化的结果并不是“看起来没什么意义”的语义改写,而是替原prompt补充重要细节,就像一个学会提示词工程指南[4]的人类专家一样。
论文归纳了几个BPO常见的优化行为:
- Explanation generation 。为LLM提供reasoning steps,即Chain of Thought。
2. Error correction 。修改原prompt中的错误。
3. Problem elaboration 。对问题进行详细说明,使用户意图对LLM来说更明显。
4. Providing hint 。提供帮助LLM解决问题的hint,例如引入一些相关知识。
5. Safety enhancement ,让LLM生成更安全的回答。
从以上case来看, BPO进行了人类可以理解的prompt engineering ,毕竟如果只是把 let's think step-by-step
改成 Take a deep breath and work on this problem step-by-step
(OPRO的优化结果),人类会觉得“这是什么...”、“这有意义吗...”,这类prompt optimization 更像是在LLM还不够聪明之前的炼丹 。而BPO的优化结果,更符合prompt engineering原则[4]。
为什么BPO有这样的优化行为?
因为BPO就是在这样的pair数据上训练的。 通过对比human preference data中的正例、负例,LLM倾向于替prompt补充必要信息,让prompt更加 具体、准确,从而更符合人类偏好 。
BPO与其他文章还有一个不同,就是其在论文中强调了alignment这一概念,初看会觉得“这能有啥关系?” 但细想一番,会发现BPO利用了human preference data,因此其优化后的prompt理论上可以生成更符合人类偏好的response,这的确是一种alignment。
总结
本文update了近期的3篇prompt engineering/optimization工作: LongPO、PE2以及BPO 。
其中,LongPO在 横向 上探究了long prompt的优化问题,PE2在 纵向 上迭代了optimizer LLM的meta-prompt,BPO则提出一种 无需重复训练的全新框架 -- 预训练一个seq2seq model,直接进行prompt optimization。
这些研究的目的,一言以蔽之,就是 帮助每个人更方便地写出高质量的prompt,让LLM能够更好、更安全地替每个人工作 。
如果读者有prompt优化问题、对prompt优化技术感兴趣, 欢迎联系笔者一起讨论交流~ 关注公众号,即可获取我的微信号。
关注笔者
欢迎关注笔者,了解有趣、有用的NLP知识。
参考资料
[1] Prompt Engineering a Prompt Engineer: https://arxiv.org/abs/2311.05661
[2] Automatic Engineering of Long Prompts: https://arxiv.org/abs/2311.10117
[3] Black-Box Prompt Optimization: Aligning Large Language Models without Model Training: https://arxiv.org/abs/2311.04155
[4] openai-prompt engineering guide: https://platform.openai.com/docs/guides/prompt-engineering