終於寫了一篇和系列標題沾邊的部落格,這一篇真的是解密prompt!我們會討論下思維鏈(chain-of-Thought)提示詞究竟要如何寫,如何寫的更高階。COT其實是Self-ASK,ReACT等利用大模型進行工具呼叫方案的底層邏輯,因此在Agent呼叫章節之前我們會有兩章來講思維鏈
先打預防針,COT當前的研究多少存在一些玄學成分,部分COT的研究使用的模型並非SOTA模型,以及相同的COT模板在不同模型之間可能不具備遷移性,且COT的效果和模型本身能力強相關,哈哈可以去圍觀COT小王子和Claude友商的Prompt決戰]。本章只是為大家提供一些思維鏈設計的思路,以及給Agent呼叫做一些鋪墊。
思維鏈的核心是為了提高模型解決複雜推理問題的能力,包括但不限於符號推理,數學問題,決策規劃等等,Chain-of-Thought讓模型在得到結果前,模擬人類思考推理的過程生成中間的推理步驟。適用於以下場景
Chain of Thought Prompting Elicits Reasoning in Large Language Models
開篇自然是COT小王子的成名作,也是COT的開山之作,單看參照量已經是一騎絕塵。
論文的核心是通過Few-shot的方案,來引導模型生成中間推理過程,並最終提高模型解決複雜問題的能力。核心邏輯很Simple&Naive
先看效果,見上圖,可以得到幾個insights
讓我們直觀來看下COT的Few-shot模板構建,以及對解碼的影響。這裡我們使用Belle的數學COT指令樣本取樣10個構建了一組few-shot思維鏈指令,如下,
測試數學能力嘛,小學奧數經典的汽車相遇問題走一個,問題:兩輛汽車從相距500千米的兩城同時出發,相向而行.一輛摩托車以每小時80千米的速度在兩輛汽車之間不斷往返聯絡.已知這兩輛汽車的速度分別是每小時40千米和60千米,求兩汽車相遇時,摩托車共行駛了多少千米?題目不復雜500/(40+60)*80 = 400千米
以下分別使用ChatGPT和ChatGLM在Greedy-search模式下進行解碼,分別是直接提問和加入few-shot-cot後再提問
prompt | chatgpt | chatglm-6b |
---|---|---|
直接提問 | 設兩汽車相遇時間為\(t\)小時,則兩汽車相遇時的距離為\((40+60)t=100t\)千米。摩托車在這\(t\)小時內不斷往返,相當於在兩汽車之間來回行駛了\(2\times 80t=160t\)千米。因此,摩托車共行駛了\(160t\)千米。根據題意,兩汽車相遇時的距離為500千米,因此\(t=\frac{500}{100}=5\)小時。代入可得,摩托車共行駛了\(160\times 5=\boxed{800}\)千米。 | 設兩汽車相遇時,摩托車行駛了 \(x\) 小時。根據題意,兩汽車相向而行,它們的相對速度為 \(40+60=100\) 千米/小時。因此,兩汽車相遇時,它們行駛的距離之和為:\(500\times(100+40)=50000\)因為兩汽車相遇時,摩托車一直在行駛,所以摩托車行駛的距離等於兩汽車相遇時它們行駛的距離之和:\(x\times80=50000\)解得:\(x=4000\)因此,兩汽車相遇時,摩托車共行駛了 \(4000\) 千米。 |
few-shot COT | 設摩托車共行駛了x千米,則兩輛汽車相遇時,摩托車往返的次數為x/500。在每次往返中,摩托車行駛的距離為80千米,所以摩托車共行駛的距離為:x = (80千米) × (x/500) = 0.16x千米兩輛汽車相遇時,它們的總路程為500千米,所以它們相遇所用的時間為:t = 500千米 / (40千米/小時 + 60千米/小時) = 5小時根據摩托車的速度和時間,可以得到:x = 80千米/小時 × 5小時 = 400千米因此,摩托車共行駛了400千米。 | 設兩汽車相遇時,摩托車行駛了 \(x\) 小時。由題意可知,兩汽車相遇時,它們已經行駛了 500 千米,所以有:\(40x + 60x = 500\)解得 \(x=50/9\),即兩汽車相時,摩托車行駛了 50/9 小時。因此,摩托車共行駛了:\(80 \times (50/9) = 400\) |
加入COT之後chatgpt和chatglm都雙雙答對了,雖然有運氣成分,且推理過程還顯得有點智障吧。但你會發現不加入few-shot COT模型同樣會進行推理再給出答案,而非像論文中給出的模型會直接直接給一個答案沒有任何推理。原因是論文使用的是text-davinci-002是沒有經過RLHF的舊版本模型。我們在一些需要推理的多項選擇問題上也進行了測試,不管是使用few-shot COT還是加入COT指令樣本進行微調,確實都能帶來一定程度上推理/數學能力的提升。
論文還進行了一些消融實驗包括
論文嘗試了few-shot部分只加入公式並不能顯著提升效果。個人感覺這個消融實驗不太完整,因為很多複雜MWP問題模型很難對映到單一的公式,而先進行問題分解後再逐步對映到中間公式,在我們的場景裡是可以提升效果的。這裡推薦兩個資料集:APE210K和Math23K分別是猿輔導和騰訊開源的數學世界問題轉化成公式的資料集,大家可以自己試試看
論文嘗試了先給出答案再進行推理的prompt模板,發現效果顯著變差。說明few-shot-COT只是啟用模型給出推理,推理過程本身才是模型效果提升的核心。我們在一些需要推理的多項選擇問題上也發現,先推理再回答選項的效果顯著優於先回答選項再給出推理過程
Large Language Models are Zero-Shot Reasoners
除了使用Few-shot-COT樣本可以讓模型給出推理過程,單純用指令也可以讓模型給出思維鏈,且能進一步提升模型複雜問題推理能力。論文中效果最好的啟用思維鏈的指令是"Let's think step by step"哈哈哈,我當時論文看到這裡感覺空氣都凝固了
self-consistency的基礎假設很人性化:同一個問題不同人也會給出不同的解法,但正確的解法們會殊途同歸得到相同的正確答案。以此類比模型解碼,同一問題不同隨機解碼會得到不同的思維鏈推理過程,期望概率最高的答案,準確率最高。那核心就變成針對多個解碼輸出,如何對答案進行聚合。論文對比了以下幾種方案
給定指令prompt和問題question,模型通過隨機解碼會生成一組\(a_1,a_2,...a_m\)答案候選,以及對應的思維鏈路徑\(r_1,r_2,...r_m\)。效果最好的兩種聚合方案分別是
針對解碼引數論文還做了一些測試
LEAST-TO-MOST PROMPTING ENABLES COMPLEX REASONING IN LARGE LANGUAGE MODELS
如果說上面的Self-Consisty多少有點暴力出奇跡,那Least-to-Most明顯更優雅一些。思路很簡單,在解決複雜問題時,第一步先引導模型把問題拆分成子問題;第二步逐一回答子問題,並把子問題的回答作為下一個問題回答的上文,直到給出最終答案,主打一個循序漸進的解決問題。也可以理解為通過few-shot來引導模型給出更合理,更一致的推理思路,再根據這個思路在解決問題。
設計理念很好,但我最好奇的是few-shot-COT要如何寫,才能引導模型針對不同場景進行合理的問題拆解。這裡我們還是看下針對數學問題的few-shot應該如何構建的,論文中的few-shot-prompt是純手工寫製作,這裡我採用chatgpt來生成再人工調整。從APE21K中隨便抽了3個問題,注意不要太簡單,已經有論文證明,few-shot-COT樣本的推理步驟越多效果越好。這裡我拆解問題的Prompt(未調優)是"對以下數學問題進行問題拆解,分成幾個必須的中間解題步驟並給出對應問題, 問題:",來讓ChatGPT生成中間的解題步驟作為few-shot-cot模板
還是同一道相遇問題,通過Reduce prompt,ChatGPT輸出:要解答摩托車共行駛了多少千米?我們需要回答以下問題:"兩輛汽車相遇需要多長時間?","摩托車在這段時間內共行駛了多少千米?
以上的問題拆解不是非常穩定,有時會包括最終的問題,有時只包括中間的解題步驟,為了保險起見,你可以在解析的問題後面都再加一個原始的問題。
把Reduce步驟的子問題解析出來,按順序輸入chatgpt,先回答第一個子問題
再把第一個子問題和回答一起拼接作為上文,這裡使用對話history也可以,拼接只是為了直觀展示
Least-to-Most最值得借鑑的還是它問題拆分的思路,這在後面被廣泛借鑑,例如Agent呼叫如何拆分每一步的呼叫步驟,以及如何先思考再生成下一步Action,在這些方案裡都能看到Least-to-Most的影子。
想看更全的大模型相關論文梳理·微調及預訓練資料和框架·AIGC應用,移步Github >> DecryptPropmt