上一章我們介紹了不同的指令微調(diào)方案, 這一章我們介紹如何降低指令數(shù)據(jù)集的人工標(biāo)注成本!這樣每個(gè)人都可以構(gòu)建自己的專屬指令集, 哈哈當(dāng)然我也在造數(shù)據(jù)集進(jìn)行時(shí)~
介紹兩種方案SELF Instruct和Automatic Prompt Engineer,前者是基于多樣的種子指令,利用大模型的上下文和指令理解能力,以及生成的多樣性來Bootstrap生成更多樣的指令樣本,后者是prompt逆向工程,基于輸入和輸出,使用LLM來生成和挑選最優(yōu)的prompt指令。
于是我把這兩個(gè)方法強(qiáng)行組了CP,用APE把原始任務(wù)轉(zhuǎn)化成種子指令,再用SELF去擴(kuò)充,在醫(yī)學(xué)和金融NLP任務(wù)上進(jìn)行了嘗試。也在huggingface上用gradio做成了可視化的應(yīng)用, 有API Key的盆友可以自己嘗試下效果:https://huggingface.co/spaces/xl2533/MakeInstruction ,記得fork到自己的space再嘗試喲~
Automatic Prompt Engineer(APE)
- paper: 2023.3, LARGE LANGUAGE MODELS ARE HUMAN-LEVEL PROMPT ENGINEERS
- github: https://github.com/keirp/automatic_prompt_engineer
- 一語道破天機(jī): prompt逆向工程,根據(jù)輸入和輸出讓模型生成并尋找更優(yōu)的prompt
指令生成
這里作者基于原始的輸入+輸出,部分樣本只有輸出,例如自由生成類的任務(wù),來讓大模型預(yù)測(cè),原始指令是什么。作者把指令生成的模板分成了3類,不過個(gè)人感覺其實(shí)只要一類即可,就是few-shot樣本在前,待生成的指令在最后的向前生成類型,如下圖
原始論文使用的是text-davinci-002來完成這個(gè)指令生成的任務(wù),每個(gè)樣本使用5條few-shot樣例作為上下文,讓模型輸出可能的指令。這里我把生成指令的模型改成了ChatGPT(只是因?yàn)楸阋?,prompt模板也根據(jù)ChatGPT的特點(diǎn)做了調(diào)整。核心是ChatGPT作為對(duì)話模型比davinci-002,003廢話要多。如果還按上面的指令來寫,你可能會(huì)得到ChatGPT的回答是:我認(rèn)為這個(gè)朋友收到的指令時(shí)blablabla.....
在實(shí)際測(cè)試中我還發(fā)現(xiàn)了幾個(gè)有意思的點(diǎn)
- 對(duì)于相對(duì)抽象,偏生成類的任務(wù),few-shot樣本要給夠,模型才有可能猜到'無偏'的指令
例如相似新聞標(biāo)題生成任務(wù):我輸入了2條樣本作為few-shot如下,模型預(yù)測(cè):"將輸入中的公司或組織名稱規(guī)范化為全稱"
我又采樣了兩條樣本如下,模型預(yù)測(cè):"將公司公告或新聞標(biāo)題簡(jiǎn)化成簡(jiǎn)短的標(biāo)題,包括公司名稱和主要內(nèi)容"
哈哈預(yù)測(cè)的指令確實(shí)都沒毛病,只不過都是相似新聞標(biāo)題生成的子集,所以你需要根據(jù)任務(wù)輸入輸出的多樣性程度來調(diào)整你的few-shot樣本數(shù),多樣性越高你需要的few-shot樣例越多
- 構(gòu)建指令樣本,說人話很重要
例如我把以上的相似標(biāo)題生成任務(wù),簡(jiǎn)化成了判斷兩個(gè)標(biāo)題是否描述同一事件的分類任務(wù)。最初我的輸入如下??雌饋硪矝]毛病是不是?然模型的預(yù)測(cè)是:"我無法確定這個(gè)任務(wù)指令的具體內(nèi)容,但它可能與文本分類或者自然語言處理相關(guān)。給出輸入文本,需要判斷該文本是否符合某種特定的模式或標(biāo)準(zhǔn),從而得出輸出結(jié)果"
但是當(dāng)我把樣本中的輸出改成符合任務(wù)語意的相同/不相同時(shí),模型預(yù)測(cè)是:"判斷兩個(gè)新聞標(biāo)題是否相同,如果相同輸出"相同",否則輸出"不相同"
當(dāng)然考慮生成模型解碼的隨機(jī)性,我在第一類樣本構(gòu)建上多次采樣也得到了類似相似度判斷的指令,但整體效果都差于下面的構(gòu)建方式,所以和MRC構(gòu)建很相似,一切以符合語意為第一標(biāo)準(zhǔn)
- 不要你以為,要模型以為!
最初我對(duì)這種機(jī)器生成指令的方式是不太感冒的,但是在醫(yī)學(xué)術(shù)語標(biāo)準(zhǔn)化這個(gè)任務(wù)上,我對(duì)比了APE得到的最優(yōu)指令,和我人工寫的指令,在單測(cè)時(shí)確實(shí)是模型指令,得到正確答案的概率更高。所以我大膽猜測(cè),因?yàn)槟P椭g的一致性,所以合理使用模型生成的指令,能提供更精準(zhǔn)的上下文任務(wù)描述,且理論上都應(yīng)該不差于人類指令。
指令打分
這里作者使用了兩種打分方式,來評(píng)估多組樣本生成的多個(gè)候選指令的優(yōu)劣
- Accuracy:使用模型預(yù)測(cè)的正確率,例如對(duì)于QA問題,根據(jù)不同指令在相同樣本上模型回答的準(zhǔn)確率來評(píng)價(jià)指令的效果。
- Log Probability:使用模型預(yù)測(cè)的logprobs作為評(píng)價(jià)指標(biāo)。注意這個(gè)指標(biāo)有些tricky,我最初認(rèn)為和上面的Accuracy一樣是讓模型去預(yù)測(cè),把預(yù)測(cè)正確的token的logprobs求和。后來發(fā)現(xiàn)是把輸入+輸出+指令都喂給模型,計(jì)算模型生成原始輸出的概率,很好解決了生成類任務(wù)解碼隨機(jī)不同指令無法比較的問題。
如何調(diào)openai接口獲取輸入的logprobs:
把echo=True,logprobs=1, 就能返回所有采樣token的logprobs,logprobs取值對(duì)應(yīng)TopN的返回,openai最多只給你返回Top5 token,包括實(shí)際被采樣的token。max_tokens=0, 不讓模型生成新的文本,就可以讓模型原樣返回我們喂進(jìn)去的輸入,以及對(duì)應(yīng)的模型計(jì)算的每個(gè)token的條件概率啦
同時(shí)作者加入了隨機(jī)搜索,既對(duì)模型生成的指令,過濾低分的部分,對(duì)于高分的指令集,讓模型基于以下指令模板,為高分指令生成相似的指令,和原始生成的指令一起排序選出最優(yōu)指令。
這塊實(shí)現(xiàn)時(shí),我把相似指令的部分拿掉了,改成人工加入,針對(duì)得到的高分指令,補(bǔ)充上自己認(rèn)為缺少核心的信息后使用log prob的打分方式來評(píng)估是否有提升。所以應(yīng)用里,我把Generated Prompt的窗口改成了可交互的,可以直接對(duì)生成的指令做修改,再Eval效果即可。
例如在醫(yī)療搜索意圖的任務(wù)上,很明顯模型無法理解"多問"標(biāo)簽是啥意思,所以最初多組樣本得到的最優(yōu)指令是下圖的第二個(gè),而我人工加入"多問"的指令后,得到了效果更好的第一個(gè)指令
效果
這里作者使用了REF[1]里面使用的24個(gè)指令任務(wù),每類任務(wù)挑選5對(duì)樣本,使用以上的方案得到最優(yōu)的指令,再在剩余樣本上,和人工指令以及REF[1]論文中使用的方案(沒有搜索和打分排序的APE)以下稱為greedy,進(jìn)行效果對(duì)比。APE的效果在24個(gè)任務(wù)上基本可以打平人工模板甚至在部分任務(wù)上還要超越人工指令。在BigBench這類難度更高的樣本上,APE在17(共21)個(gè)任務(wù)上也超越了人工指令的效果。
我在4個(gè)醫(yī)學(xué)數(shù)據(jù)集上APE+人工優(yōu)化得到的最優(yōu)指令如下
任務(wù) | 指令 |
---|---|
搜索意圖 | 生成醫(yī)學(xué)相關(guān)問題的答案。給定一個(gè)輸入問題,需要根據(jù)問題生成相應(yīng)的輸出答案。答案包括臨床表現(xiàn)、病因、治療方法、作用、定義等等,如果有多個(gè)問題,返回多問 |
醫(yī)療術(shù)語標(biāo)準(zhǔn)化 | 將醫(yī)學(xué)手術(shù)名稱的術(shù)語表述標(biāo)準(zhǔn)化。輸入是醫(yī)學(xué)手術(shù)的名稱,輸出是對(duì)該手術(shù)的名稱進(jìn)行修正、標(biāo)準(zhǔn)化,以供醫(yī)學(xué)專業(yè)人員更好地理解 |
醫(yī)療藥物功能實(shí)體抽取 | 給定藥品信息和用途說明,根據(jù)用途說明提取出藥品的主治功能。 |
醫(yī)療文獻(xiàn)QA生成 | 訓(xùn)練一個(gè)問答系統(tǒng),給定一些醫(yī)學(xué)文本,能夠回答用戶提問關(guān)于該文本內(nèi)容的問題。每個(gè)輸入-輸出對(duì)是一組文本和對(duì)應(yīng)的問題及答案。輸出的形式是以下Json格式{"問題":\(問題, "回答":\)回答} |
以醫(yī)學(xué)術(shù)語標(biāo)準(zhǔn)化為例我簡(jiǎn)化了APE提供的gradio應(yīng)用,效果如下
SELF-Instruct
- paper: 2022.12, SELF-INSTRUCT: Aligning Language Model
with Self Generated Instructions- https://github.com/yizhongw/self-instruct
- https://github.com/tatsu-lab/stanford_alpaca#data-generation-process
- 一語道破天機(jī):類似非線性插值,通過LLM的生成多樣性做Bootstrap對(duì)種子指令集進(jìn)行不定向擴(kuò)充
上一步我們依賴APE得到了種子指令集,但是豐富度和多樣性是遠(yuǎn)遠(yuǎn)不夠的。這里SELF提出了一種Bootstrap方案來讓LLM基于種子指令生成新的指令的指令擴(kuò)充方案。這個(gè)方案也后續(xù)被用于Alpaca項(xiàng)目中生成微調(diào)指令集,主要包括以下3個(gè)步驟
1. 新指令生成
首先作者人工構(gòu)建了175個(gè)種子指令,這些種子指令由1條指令和1個(gè)樣本構(gòu)成。每個(gè)Step作者會(huì)從中采樣8個(gè)指令,其中6個(gè)來自以上種子,2個(gè)來自LLM生成的指令,當(dāng)然step1全部都是種子指令。然后基于如下的prompt模板構(gòu)建模型輸入
"""
Come up with a series of tasks:
Task 1: {instruction for existing task 1}
Task 2: {instruction for existing task 2}
Task 3: {instruction for existing task 3}
Task 4: {instruction for existing task 4}
Task 5: {instruction for existing task 5}
Task 6: {instruction for existing task 6}
Task 7: {instruction for existing task 7}
Task 8: {instruction for existing task 8}
Task 9:
"""
如果你看著這個(gè)模板,感覺和ChatGPT的模板格格不入,那就對(duì)了。因?yàn)樽髡呤腔贕PT3實(shí)現(xiàn)的,就是那個(gè)天真的續(xù)寫模型。
而Alpaca項(xiàng)目在使用SELF構(gòu)建指令樣本時(shí)升級(jí)到了davinci-003模型,因?yàn)槟P涂梢愿玫睦斫庵噶?,因此以上純few-shot的prompt模板也改成了如下(用ChatGPT翻成了中文),同時(shí)輸入的few-shot數(shù)量縮減到了3個(gè)
"""
你需要想出20個(gè)不同的任務(wù)指令。這些任務(wù)指令將輸入GPT模型,我們將評(píng)估GPT模型完成指令的情況。
以下是要求:
1. 盡量不要在每個(gè)指令中重復(fù)使用動(dòng)詞,以最大化多樣性
2. 指令的表達(dá)形式需要多樣化。例如你可以把問題和祈使句結(jié)合起來
3. 指令的類型應(yīng)該多樣化,包括但不限于開放式生成、分類、抽取、問答、文本編輯等等
4. 指令應(yīng)該是GPT模型可以完成的任務(wù)。例如,指令不能是輸出圖像或者視頻,另一個(gè)例子,不要讓助手在下午5點(diǎn)叫醒你或設(shè)置提醒,因?yàn)镚PT不能執(zhí)行任何動(dòng)作
5. 指令必須是中文
6. 指令應(yīng)該是1到2句話,可以是祈使句或問句。
20個(gè)任務(wù)的列表:
"""
我第一遍讀完SELF是一腦門子問號(hào)
后來我(似乎&努力)說服了自己,就是LLM做了類似非線性差值的工作,因?yàn)槊總€(gè)Step都會(huì)采樣不同的指令作為上下文,而模型也會(huì)根據(jù)隨機(jī)采樣得到的不同的上下文融合出新的指令。
2. 樣本生成
只有指令還不夠,還需要生成指令對(duì)應(yīng)的輸入和輸出。在SELF原論文中,作者多加了一步分類任務(wù),也就是讓LLM先判斷指令本身是否為分類任務(wù),如果是則先生成輸出,再生成輸入。如果否則先生成輸入再生成輸出。原因是作者發(fā)現(xiàn),對(duì)于分類任務(wù)模型傾向于只生成其中一個(gè)標(biāo)簽的輸入。
但在Alpaca項(xiàng)目中,因?yàn)槟P蜕?jí)到Davinci-003,以上問題也似乎不再顯著。并且隨著模型輸入長(zhǎng)度變長(zhǎng),Alpaca直接把生成樣本和生成指令的步驟合在了一起,一步到位。于是以上指令生成的模板被擴(kuò)充成了以下
"""
7. 你應(yīng)該為指令生成一個(gè)合適的輸入。輸入字段應(yīng)該包含為指令提供的一個(gè)具體示例。它應(yīng)該涉及真實(shí)的數(shù)據(jù),而不應(yīng)該包含簡(jiǎn)單的占位符。輸入應(yīng)該提供足夠的內(nèi)容,使指令具有挑戰(zhàn)性,但理想情況下不應(yīng)超過100個(gè)單詞。
8. 不是所有的指令都需要輸入。例如,當(dāng)一個(gè)指令詢問一些一般信息時(shí),“世界上最高的山峰是什么”,就不需要提供具體的上下文。在這種情況下,我們只需在輸入字段中放置“<無輸入>”。
9. 輸出應(yīng)該是對(duì)指令和輸入的合適回應(yīng)。確保輸出少于100個(gè)單詞。
20個(gè)任務(wù)的列表:
"""
于是每一步其實(shí)是直接生成指令,以及指令對(duì)應(yīng)的輸入和輸出樣本。對(duì)于自由生成類的任務(wù),也支持沒有輸入只有輸出。
3. 過濾和后處理
針對(duì)以上生成的指令和樣本還需要進(jìn)行一些系列的后處理,主要包括模型預(yù)測(cè)解析,不合理指令的過濾,以及相似指令的過濾,解析的部分建議直接看代碼
- 不可用指令過濾
- 因?yàn)檩敵鲩L(zhǎng)度被截?cái)嗟闹噶睿簉esponse停止原因是length,則過濾最后一個(gè)指令
- 過濾包含不可用關(guān)鍵詞的指令:例如圖片,音頻等GPT模型無法完成的任務(wù)
- 過濾過長(zhǎng),過短的指令
- 過濾指令前幾個(gè)字非英文/中文的指令
- 相似指令過濾
為了保證指令集的多樣性,每輪都會(huì)計(jì)算新生成指令和已有指令的Rouge-L相似度,也就是摘要任務(wù)評(píng)估中用最長(zhǎng)公共子串的長(zhǎng)度計(jì)算的F值。只保留F值小于0.7的新的指令。同時(shí)也可以根據(jù)最近幾輪生成指令的整體相似度,來判斷是否要停止生成。
我用上面APE生成的4個(gè)醫(yī)學(xué)NLP任務(wù)作為種子指令集,每輪采樣2個(gè)人工,1個(gè)機(jī)器指令作為few-shot,生成2個(gè)新的指令任務(wù)。我對(duì)以上指令做了些調(diào)整,限制只生成醫(yī)學(xué)領(lǐng)域的任務(wù),得到了如下的結(jié)果。哈哈我決定去給賬戶充錢了。。。
大致就是這么多,感興趣的盆友們一起玩起來(造數(shù)據(jù)的痛苦見者有份)~
更多Prompt相關(guān)論文·教程,開源數(shù)據(jù)·模型,以及AIGC相關(guān)玩法戳這里DecryptPrompt文章來源:http://www.zghlxwxcb.cn/news/detail-409416.html
Reference文章來源地址http://www.zghlxwxcb.cn/news/detail-409416.html
- Instruction induction: From few examples to natural language task descriptions.
- Fairness-guided Few-shot Prompting for Large Language Models
- Flipped Learning: Guess the Instruction! Flipped Learning Makes Language Models Stronger Zero-Shot Learners
到了這里,關(guān)于解密prompt系列5. APE+SELF=自動(dòng)化指令集構(gòu)建代碼實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!