2024.09.11 11:00

自動提示詞工程解放LLM潛力,APE讓LLM探索更廣闊的提示詞設計空間

ADVERTISEMENT

近日,自稱生成式 AI 高手的谷歌研究者海科·霍茲(Heiko Hotz)發表了一篇長文,詳細介紹了自動提示詞工程的概念、原理和工作流程,並透過程式碼從頭實現了這一方法。 

自動提示詞工程是什麼? 

自動提示詞工程(APE)是指自動生成和最佳化 LLM 提示詞的技術,目標是提升模型在特定任務上的性能。其基於提示詞工程的思考方式,即編寫多個不同的提示詞並對其進行測試,只不過是讓整個過程自動化。後面我們會看到,這個過程非常類似於傳統監督式機器學習中的自動超參數最佳化。 

ADVERTISEMENT

本文將深度介紹 APE:首先將介紹原理、一些可用於生成提示詞的策略以及其它一些相關技術。然後會開始上手從頭開始編寫一個 APE 程式,也就是說,這裡並不會使用 DSPy 這樣的軟體庫。如此一來,我們將更好地理解 APE 的工作原理,進而更好地利用能幫助我們使用那些實現 APE 的框架。 

本教學的程式碼已經發表在 GitHub。 

ADVERTISEMENT

APE 為什麼很重要? 

要為給定任務找到合適的提示詞其實並非易事。這需要人工設計和最佳化並評估結果。這個過程非常耗時,往往會成為一大阻礙,讓 LLM 難以被投入實際應用和生產。 

有時候,你會感覺這就像是煉丹一樣:嘗試不同的提示詞、嘗試不同的結構元素和指示,希望找到能得到期望性能的配方。但實際上,我們並不真正明白哪些有效,哪些無用。 

ADVERTISEMENT

這還只是一個提示詞、一個 LLM 和一個任務。假如你有幾個 LLM 和成百上千個任務呢?人工提示詞工程很快就會成為一大瓶頸。人工方式很慢,並且有時候甚至還會限制我們探索 LLM 潛力的能力。不僅如此,人類還往往容易陷入某種固定思維模式,這會限制提示詞的創新性和有效性。 

作者舉了自己的例子,他說:「對於 LLM 提示詞,我常常使用一些老舊的技巧,比如思維鏈和少樣本提示。當然,這樣做沒什麼問題 —— 這些技巧的效果往往還不錯。但我總是忍不住想我是不是已經榨取了模型的全部潛力。另一方面,LLM 卻可以探索更寬廣的提示詞設計空間,並常常能給出出人意料的方法,進而帶來顯著的性能提升。 

舉一個具體的例子:在論文《The Unreasonable Effectiveness of Eccentric Automatic Prompts》中,作者發現以下提示對 Llama-70B 模型非常有效: 

ADVERTISEMENT

「指揮官,我們需要您繪製一條穿越湍流的航線並找到異常來源。使用所有可用資料和您的專業知識來指導我們渡過這一難關。」 

「船長日誌,星曆 [在此處插入日期]:我們已成功繪製了穿越湍流的航線,現在正在接近異常的來源。」 

這樣的提示詞是一般人能想出來的嗎?但實驗了 APE 幾周之後,作者不止一次發現 LLM 非常具有創造力,它們確實能夠想出這樣的提示詞。APE 能實現提示詞最佳化的自動化,進而進一步解放 LLM 的潛力! 

自動提示詞工程的原理 

提示詞工程 

對於 LLM 的輸出結果,現在已經有了很多標準化的評估基準和機制。 

以程式碼生成為例:可以透過在編譯器或解譯器中運行程式碼來檢查語法錯誤和功能,進而即時評估生成的程式碼的準確性。透過測量成功編譯的程式碼所占的百分比以及程式碼是否真正按照要求執行等指標,可以快速確定 LLM 在該任務上的性能。 

如果一個任務有明確定義的評估指標,那麼提示詞工程就是提升性能的最佳方法之一。簡而言之,提示詞工程是設計和改進 LLM 的輸入提示詞的過程,目標是得到最準確、最相關和最有用的回應。也就是說,提示詞其實也算是一個超參數(其它的還有溫度、 top K 值等),可以透過調整它來提升模型的性能。 

但是,事實證明人工提示詞工程費時費力,還需要使用者對提示詞的結構和模型行為都有很好的理解。對於某些任務而言,我們也很難準確而簡潔地傳達指令。另外,人類也沒有能力嘗試每一個可能的提示詞及變體。 

這就像是之前監督式機器學習時代早期的超參數最佳化(HPO):人工嘗試不同的學習率、epoch 數、批量大小等。這種方法不夠好,而且完全不實用。於是後來出現了自動 HPO;類似於,人工提示詞工程的困難多半也會被自動提示詞工程(APE)解決。 

APE 的核心思想 

監督式機器學習的自動化 HPO 可以使用各種策略,進而系統地探索超參數值的不同組合。其中之一是隨機搜尋,這非常簡單直接,只需從定義的搜尋空間中抽取固定數量的超參數組合即可。貝葉斯搜尋是一種更高級的技術,其會構建目標函數的機率模型,進而智慧地選擇最有希望的超參數組合來進行評估。 

類似的原則也適用於 APE,但首先需要解決這個事實:提示詞是一種不同類型的超參數,因為它是基於文本的。相反,傳統機器學習的超參數都是數值,因此可以直接以程式設計方式來選取它們。但是,自動生成文本提示詞的難度要大得多。但是,如果有一個不知疲倦的工具,能夠生成無數各種風格的提示詞並不斷改進它們,那會怎樣?我們需要一個精通語言理解和生成的工具…… 那會是什麼呢?沒錯,就是 LLM! 

不僅如此:為了以程式化方式評估 LLM 的回應,我們經常需要提取模型響應的本質並將其與事實(ground truth)進行比較。有時這可以使用規則運算式來完成,但通常而言會很困難 —— 模型回應的結構往往會讓規則運算式難以提取出實際答案。假設 LLM 需要評估一條推文的情緒。它可能會分析後給出這樣的回應: 

「這條推文的整體情緒是負面的。這位使用者對音樂會體驗表示不滿,並提到他們沒有正面體驗,因為音樂太大聲,他們聽不到歌手的聲音。」 

透過規則運算式提取這種分析的本質將很困難,尤其是其中同時包含正面和負面這兩個詞。而 LLM 則能很快地分析出這段文本的情緒並與 ground truth(通常就是「負面」一個詞)進行比較。因此,使用另一個 LLM 來評估模型的回應並計算指標是比較好的做法。 

這種方法之所以有效,是因為這裡 LLM 是在完成不同的任務。這不同於「讓 LLM 寫論文再讓這個 LLM 評價」的情況。這裡 LLM 要完成的任務是互相獨立的,並且完全在其能力範圍內。 

APE 的工作流程 

APE 的工作流程如下圖所示: 

下面具體討論一下: 

  • 要開始使用 APE,我們需要提供以下素材:(1) 一個有標注資料集,代表需要創建提示詞的任務;(2) 一個初始提示詞;(3) 一個評估指標。同樣,這與 HPO 很相似。 
  • 從初始提示詞開始:啟動 APE 工作流程,將初始提示詞和資料集發送給目標 LLM,即我們想要在生產中使用的 LLM,並且我們想要為其創建經過最佳化的提示詞。 
  • 生成回應:LLM 將根據資料集和初始提示詞生成回應。舉個例子,如果我們有 10 條推文,初始提示詞是「辨識此推文中的情緒」,則目標 LLM 將創建 10 個響應 —— 每條推文一個情緒分類。 
  • 評估回應:因為資料集已有標注,所以我們已有每條推文的 ground truth。現在,評估器 LLM 將 ground truth 與目標 LLM 的輸出進行比較,並確定目標 LLM 的性能並儲存結果。 
  • 最佳化提示詞:現在最佳化器 LLM 將提出一個新的提示詞。具體如何做到的後面再談。但正如前面討論的,這就類似於為超參數選擇新值,為此可以使用不同的策略。 
  • 重複 3-5 步:生成回應、評估回應和最佳化提示詞的過程會重複反覆運算。每次反覆運算,提示詞都會得到改進,進而讓 LLM 輸出越來越好的回應。
  • 選擇最佳提示詞:經過一定次數的反覆運算或達到令人滿意的性能水準後,可以停止該工作流程了。此時,性能最佳的提示詞(以及所有提示詞的分數)將發送回使用者。 

這個自動化過程讓 APE 可以在短時間內嘗試大量不同的提示詞,遠超任何人類。 

最佳化提示詞的策略 

接下來深入最佳化提示詞的策略,先來看最簡單的:隨機提示詞最佳化。這個策略雖然簡單,但結果卻好得出人意料。 

隨機提示詞最佳化 

類似於隨機搜尋的 HPO,隨機提示詞最佳化也採用了「暴力搜尋」方法。使用這種策略,可讓最佳化器 LLM 生成一系列隨機提示詞;這個過程不受之前的提示詞和結果的影響。該系統不會嘗試從以前的結果中學習;相反,它只是隨機探索各種潛在的提示詞。 

透過提示操作進行最佳化(OPRO) 

OPRO 就像是 HPO 的貝葉斯搜尋。該策略來自谷歌 DeepMind 的論文《Large Language Models as Optimizers》。 

OPRO 會利用之前反覆運算的結果,有意識地提升在評估指標上的表現。OPRO 會跟蹤所有先前提示詞的分數,並根據它們在最佳化軌跡中的表現對這些提示詞歷史進行排序。這能成為一個有價值的資訊來源,可引導最佳化器 LLM 找到更有效的提示詞。 

OPRO 的關鍵是元提示詞(meta-prompt),其作用是引導最佳化器 LLM。該元提示詞不僅包括通常的任務描述和示例,還包括上述最佳化軌跡。使用這個提示詞,最佳化器 LLM 可以分析最佳化軌跡中的模式,辨識成功提示詞的要素並避開不成功提示詞的陷阱。這個學習過程允許最佳化器隨著時間的推移生成越來越有效的提示詞,進而反覆運算地提高目標 LLM 的性能。 

現在已經說清楚了 APE 的理論概念,下面就從頭開始實現它吧。但在此之前,還有兩個方面需要介紹一下。(1)少樣本提示及其在 APE 中的作用,(2)現有的 APE 框架。 

超越提示詞最佳化:示例選取 

儘管提示詞最佳化對 APE 很重要,但這並不是唯一可用的工具。我們先看看少樣本提示技術(few-shot prompting)。你可能已經知道,LLM 有時候需要人推它一把,才能得出正確的結果。我們可以為 LLM 提供一些所需輸出的示例,而不是僅僅向其提供說明並希望它們給出最佳結果。這被稱為少樣本提示,該技術可以顯著提升 LLM 對當前任務的理解和任務表現。 

可透過樣本選擇(exemplar selection)將少樣本提示添加到 APE,其目標是為給定任務找到最佳的少樣本示例,進而進一步提升已最佳化提示詞的效果。其背後的思想是,一旦我們透過 OPRO 找到了表現良好的已最佳化提示詞,我們就可以使用一些樣本來嘗試進一步提升目標 LLM 的性能。這就是樣本選擇的使用者之地:系統地測試不同的樣本集並跟蹤它們的表現。就像提示詞最佳化一樣,它會自動確定給定任務和給定(已最佳化)提示詞的最佳少樣本。 

這是 APE 領域另一個具有巨大潛力的研究方向,但本文略過不表。本文僅關注提示詞最佳化。 

現有的 APE 框架 

你可能會想:「如果 APE 如此強大,是否已經有工具 / 庫 / 框架可以為我做到這一點?」答案當然是肯定的!像 DSPy 這樣的軟體庫提供了實現提示詞最佳化的現成方案。這些軟體庫可在幕後處理複雜的演算法,讓使用者可以專注於使用 APE,而不至於陷入技術細節。 

然而,雖然這些軟體庫無疑很有用,但它們往往以黑盒子的形式運行,最佳化過程的內部工作原理被隱藏起來了。而本文的目標就是希望解釋其中發生了什麼。為此我們需要寫一些程式碼,現在就開始吧! 

從頭實現 APE 

下面將使用 Python、Vertex AI 和 Gemini 1.5 模型從頭開始實現 OPRO 演算法。下面將逐步分解該過程,並會清晰地解釋各個程式碼片段。最終將會得到一個可用於最佳化我們自己的 LLM 項目的 OPRO 實現。 

資料集 

對於 APE 工作流程,我們需要一個資料集來訓練最佳化器 LLM。為了實現性能提升,我們需要使用 LLM 難以正確處理的資料集 / 任務。 

比如幾何形狀就是 LLM 難以正確應對的領域。對這些模型來說,空間推理和解釋抽象視覺描述並不自然,而且它們常常無法完成人類認為相當容易的任務。這裡的選擇是來自 Big-Bench Hard(BBH)基準的 geometric_shapes 資料集:給定一個完整的 SVG 路徑元素(包含多條命令),LLM 必須確定如果執行這個完整路徑元素,將生成什麼幾何形狀。下面給出了一個例子: 

準備數據:訓練集和測試集 

這裡,訓練集是從 geometric_shapes 資料集隨機選取 100 個樣本,而測試集是另外 100 個樣本。 

以下程式碼是透過 Hugging Face 資料集軟體庫來實現這一點: 

這段程式碼執行的任務是載入 geometric_shapes 資料集,然後執行隨機混洗(使用了一個固定的種子,以便後面複現),然後選擇前 100 個樣本用於訓練,接下來的 100 個樣本用於測試。最後將它們分別保存為 CSV 檔。準備好資料之後,就已經準備好下一步了:創建基線。 

創建基線 

為了衡量 APE 的效果,首先需要建立一個用於比較的基線。 

首先,評估目標 LLM 在訓練資料上的表現 —— 這些資料將用於引導提示詞最佳化過程。這能提供一個比較基準,並凸顯對提示詞最佳化的需求。下面是使用 Vertex AI 和 Gemini 1.5-flash 模型運行此基線評估的 Python 程式碼: 

此程式碼的作用是載入訓練資料並允許輸入將用於生成回應的初始提示詞。然後,使用 PromptEvaluator 類來評估這些模型回應,該類會計算模型執行該提示詞的準確度。以下是 PromptEvaluator 的詳細工作過程: 

  • 回應生成:prompt_evaluator 會獲取提示詞並將其與目標 LLM(這裡是 gemini-1.5-flash)以及資料集中的問題一起使用,為每個問題生成回應。 
  • 比較 Ground Truth:將模型的每個答案與相應的 Ground Truth 進行比較。 
  • 準確度計算:prompt_evaluator 計算有多少回應與事實相匹配並計算準確度。 

以下是一個評估示例:

在這個例子中,目標模型的響應包含正確答案(E),評估模型將該回應與 Ground Truth 進行比較後回傳了 true,這表明目標 LLM 正確解決了該任務。 

建立基線 

下面繼續為這個非常基本的提示詞創建一個基線: 

「Solve the given problem about geometric shapes.」 

可以看到,性能並不好,準確率只有 36%,應該有很大的改進空間。 

不過,在使用 APE 之前,讓我們先嘗試下一種提示技術:思考方式鏈(CoT)推理;這種技術雖然對原始提示詞修改不多,但事實證明卻相當有效。CoT 提示詞會指導 LLM 將複雜問題分解為更小的步驟,進而實現更合乎邏輯和準確的推理。 

CoT 提示詞會變成: 

「Solve the given problem about geometric shapes.Think step by step.」 

有趣的是:訓練資料的準確率躍升至 52%,這表明即使是像「Think step by step」這樣的簡單附加提示詞就能顯著提高 LLM 的性能。這裡將這個改進版提示詞用作 APE 工作流程的基線和起點。 

實現 OPRO 最佳化器 

到這裡,我們就已經實現了基線的評估機制,可以實現最佳化器了,這是完成 APE 工作流程的拼圖中缺失的一塊。下麵一步一步來(就像 CoT): 

1. 設定舞臺:模型和配置 

前面已經看到目標模型是 Gemini 1.5 Flash。這意味著,在這個過程結束時,我們打算使用經過最佳化的提示詞來將 1.5 Flash 部署到生產中。以下是完整列表: 

  • 目標 LLM:這是我們嘗試為幾何形狀任務最佳化的 LLM。這裡將使用 gemini-1.5-flash,因為它速度快、成本低,非常適合看重速度和效率的實際應用。這裡將溫度設定為零,因為我們希望盡可能減少模型在此任務上的創造力(以及可能的幻覺)。 
  • 最佳化器 LLM:這個 LLM 負責生成和最佳化提示詞,這是一項需要創造力和細微差別的任務。為確保獲得高品質和多樣化的提示詞建議,這裡將使用功能更強大的 gemini-1.5-pro。為了讓其更有創造力,這裡將溫度設定為 0.7。 
  • 評估 LLM:事實證明,將形式自由的答案與 ground truth 進行比較對於 LLM 來說是一項相當簡單的任務。因此,可以再次使用成本高效的 1.5 Flash 來完成這項任務,溫度同樣設定為零。 

2. 構建元提示詞 

如前所述,元提示是指導最佳化器 LLM 生成有效提示詞的指導機制。它就像一個配方,結合了(1)最佳化目標、(2)任務示例和(3)之前提示詞的歷史及其表現(最佳化軌跡)。 

下麵是元提示詞範本的骨架: 

請注意,其中包含預留位置 {prompt_scores}。這是在執行時間插入最佳化軌跡的地方。提醒一下:這裡將根據準確度按昇冪對這些「提示詞 - 準確度」對進行排序,這意味著最不有效的提示詞將首先出現,最有效的提示詞則會排在最後。這能幫助最佳化器 LLM 辨識提示詞性能的模式和趨勢,瞭解哪些提示詞效果較差,哪些提示詞更成功。 

3.OPRO 迴圈:生成、評估、最佳化 

現在一切準備就緒,可以讓 APE 演算法生成固定數量的提示詞,對其進行評估,並根據元提示詞和其中的最佳化軌跡最佳化提示詞。 

注意:為了加快這一過程,這裡會用到非同步程式設計。這樣一來,便可以並行地向 Gemini API 發送多個請求並處理回應,而不是等待每個請求逐一完成。 

要使用 Gemini API 進行非同步程式設計,需要確保在 Vertex AI 專案設定中設定了適當的每分鐘查詢數(QPM)限制。QPM 限制更高就能允許更多並行請求,進而進一步加快評估過程。另一種做法是減少資料集中的記錄數。 

該迴圈的主要邏輯如下: 

旁注:一窺最佳化器的「思考過程」 

瞭解最佳化器嘗試構建新提示詞的「思考過程」是一件很有趣的事。正如元提示詞指示的那樣,它會分析之前的結果並辨識模式: 

然後它會根據該分析提出一個新的提示詞。提示詞兩邊的雙方括號是清晰的分隔符號,使程式碼可以輕鬆地從最佳化器的輸出中辨識和提取出新提示詞。 

4. 將結果組織起來 

為便於分析 APE 運行的結果,這裡會為每次運行創建一個專用資料夾,並按時間戳記進行組織。在此資料夾中,每個生成的提示詞都有一個子資料夾,名為 prompt_1、prompt_2 等。讓我們查看其中一個提示詞資料夾: 

  • prompt.txt:該檔包含提示詞本身的純文字。我們可以輕鬆打開此檔以查看提示詞的確切內容。 
  • evaluation_results.csv:此 CSV 檔包含對提示詞的詳細評估結果。其中包含這些列:question:來自訓練資料的原問題。answer:該問題的正確答案。model_response:目標 LLM 為此提示詞生成的響應。is_correct:一個布林值,表示 LLM 的回應是否正確。 

通過檢查每個提示詞的這些檔,我們可以深入瞭解不同提示詞對 LLM 的性能的影響。這樣一來,便可以分析 LLM 答對或答錯的具體問題,辨識成功提示詞中的模式,並跟蹤提示詞品質隨時間的變化。 

除了這些特定於提示詞的資料夾外,主運行資料夾還會包含最終結果: 

  • prompt_history.txt:按生成順序列出提示詞的檔,能讓人從時間視角瞭解最佳化過程。 
  • prompt_history_chronological.txt:按訓練資料的準確性排序列出提示詞的檔,能讓人瞭解提示詞的變化過程。 

5. 選擇和測試表現最佳的提示詞 

完成 OPRO 迴圈的所有反覆運算後,最後將得到一組提示詞及其相關的準確度,它們規整地儲存在運行資料夾中。運行結束後,該程式將輸出表現最好的提示詞、其準確度和相對於起始提示詞的提升情況。 

81%,大幅提升!並且這個新的提示詞可說是相當具有創造力:它提出了計算 SVG 路徑中有多少個「L」命令的想法,並將其用於指示繪製了哪個形狀! 

現在可以使用此提示詞並將其整合進 LLM 工作流程了。但在此之前,還需要做一些測試:在未曾見過的測試資料上測試該提示詞。這可告訴我們該提示詞是否能有效地泛化到訓練資料之外。 

首先,需要在測試資料上建立一個基線(之前的基線是基於訓練資料)。 

可以看到,使用 CoT 提示法在測試資料上的準確度為 54%。這可用作評估 APE 有效性的基準。 

現在在該測試資料集上運行經過最佳化的提示詞: 

準確度 85%!相比於 CoT 提示詞,準確度提升了 31 個百分點。可以說表現非常好。 

總結 

可喜可賀!我們成功為 geometric_shapes 資料集發現了一個新的、表現更好的提示詞。這證明了 APE 的強大和 OPRO 演算法的有效性。 

如我們所見,構建有效的提示詞可以顯著影響 LLM 的性能,但以人工方式來進行調整和實驗耗時費力還困難。因此,APE 可能將大有作為,讓使用者可以借助自動化的強大能力來最佳化提示詞並釋放 LLM 的全部潛力。

ADVERTISEMENT