_如果您不是會員但想閱讀本文,請查看此好友鏈接。 _
鍊式思維 (CoT) 已經存在一段時間了,從技術上講是一種高級提示工程,但即使在首次引入幾年後的今天,它仍然具有重要意義。各種形式的 CoT 通常都是為了迫使大型語言模型進行推理。
今年9月OpenAI發布其模型o1預覽版後,我們看到圍繞CoT的熱度有所提升。
沒有人完全知道o1是如何工作的(除了OpenAI),它是否是組合系統,它使用什麼數據進行微調,是否使用強化學習,或者是否有幾個模型一起工作。
也許一個模型負責規劃,另一個負責思考,第三個負責評估。但我們知道他們正在採用某種逐步推理的方法。
圍繞這一問題已經進行了大量的公開研究,您可能需要深入研究。因此,在這篇文章中,我將介紹現有的方法,以便您知道可以使用哪些方法。當然,我會測試不同的技術,看看我們能否取得任何真正的改進。
然後,如果您熱衷於進行一些技術工作,我將幫助您構建一個系統,該系統查看模型的內部置信度級別以生成答案。
在過去兩年中,已經發表了許多論文,我已經收集了我在這裡找到的許多論文。
您將在下面的圖片中看到他們討論的推理技術。
大部分工作直接來自 DeepMind 或普林斯頓大學。感謝他們開源瞭如此多的工作。
CoT一詞來自DeepMind在2022年的論文,僅在提示中使用它,最新的論文探索了具有蒙特卡洛搜索的三思而後行以及無需提示的CoT。
在這篇文章中,我們將介紹簡單的鍊式思維 (CoT)、CoT 鏈、貪婪解碼、CoT-SC、解碼 CoT 和具有蒙特卡洛樹搜索的三思而後行 (ToT)。
我們還將使用我們自己的一組數據來了解在採用這些推理技術時我們可以取得的改進。
為了了解如何改進大型語言模型的結果,我們首先需要建立某種基準分數。
當引入一個模型時,它通常會帶有評估指標。有一些流行的指標,例如 MMLU(語言理解)、BigBench(推理)、HellaSwag(常識推理)等等。
但是,您應該知道,其中一些數據集已經過時,並且可能有點被污染。
Hugging Face 在12 月推出了一份新的LLM 排行榜,該榜單基於較新的數據集進行評估,您可以清楚地看到,大多數模型的分數都比原始數據集低得多。
值得在這裡進行一些研究,以了解您應該如何考慮模型評估以及您和您的組織應該基於什麼理由進行評估。擁有一個內部私有數據集進行測試可能並非最糟糕的主意。
但無論如何,我從各種數據集以及我在網上找到的一些流行問題中提取了大約 350 個問題,以評估多達 11 個不同的模型。
我還需要了解這些數據集以及大型語言模型生成的答案是什麼樣的。
因此,我構建了自己的腳本來循環遍歷這些問題,然後使用每個問題的 0 或 1 來評估大型語言模型。
你可以叫我完美主義者。您可以在下面看到我發現的結果。
這告訴我們什麼?嗯,不多。
我使用了來自 Big Bench、MMLU、Putnam 的問題,以及諸如“草莓中有多少個 r”之類的流行問題,但我們無法知道這些問題是否已被這些問題污染。此外,這是一個相當小的數據集。
但是,我們可以清楚地看到,更大的模型性能更好。
有趣的是,通過應用使模型在回答之前進行推理和“思考”的方法,我們能否提高這些分數。
鍊式思維 (CoT) 提示由 DeepMind 的大腦團隊在 2022 年的論文“鍊式思維提示在大型語言模型中引發推理”中提出。
因此,CoT 的想法已經存在了相當長一段時間。
然而,這篇第一篇論文是對如何通過使用提示策略激活模型固有的推理能力來迫使模型對問題進行推理的研究。
那時,人們只是通過要求模型“逐步思考”來以正確的方式進行提示,這可以通過零樣本(不提供示例)或少樣本(提供一些示例)方法來實現。
今天,您可以通過在提示的末尾簡單地添加“讓我們一步一步地思考”來對各種模型(例如 Claude、ChatGPT 或其他模型)執行此操作。如果您想嘗試少樣本學習,您可以在提示中提供一些示例。
DeepMind 報告說,他們可以通過正確地進行提示來驗證性地看到使用 CoT 技術有顯著的改進。
從那時起,許多論文都基於這些技術構建,擴展到越來越先進的路徑。
提示工程社區中有許多人使用 CoT 風格的技術進行實驗。我已經收集了我在這裡找到的大多數存儲庫,因此很容易找到。
不久前,Benjamin Klieger 突出了一點,他構建了一個提示風格的應用程序,通過進一步分解思考過程,使用 Groq 和 Llama 3.1 70b 來引發鍊式思維。
您可以在此處找到他的應用程序。
其想法是要求大型語言模型將其思維分解成鏈,它會繼續思考,直到對答案充滿信心為止。
然後,系統將繼續為鏈的每個部分生成大型語言模型調用,而不是在一個響應中擁有整個思考過程。
請參閱將此應用於 Grok-Beta 的示例,問題是“草莓中有多少個 R?”
模型本身正在設置每個部分,為其命名,並決定是否需要另一個“想法”並應該繼續,或者它是否已經達到最終答案。
這仍然是一種 CoT 風格的技術,因為它具有線性關係,但它比簡單地要求模型“逐步思考”略微先進。
我使用了他的一些代碼來構建一個腳本來循環遍歷一些大型語言模型的基準問題,以了解這種系統實際上會產生多少改進。我還調整了 Claude 和 Grok 的腳本以評估這種策略。
您將在下面看到百分比改進。
Llama 3.1 70B 在前三類中取得了最佳改進。 Grok 在流行問題上的表現更差(Haiku 也是如此)。
Putnam 數據集是高級數學,很少有大型語言模型能夠在這方面做得很好,因此當Claude Sonnet 3.5 能夠在這些CoT 鏈中以68.75% 的成績優於o1-preview(o1-preview為63%)時,我很驚訝。
總的來說,Sonnet 使用 CoT 在高級數學方面提高了 81%。
請記住,我在這裡使用了一個非常小的數據集,它只是為了了解它們在哪些方面做得很好以及我們能否提高分數。如果沒有在更大的數據集上進行測試,它並不能告訴我們任何具體的東西。
然而,我還觀察到,如果較小的模型開始過度分析簡單的問題,則可能會產生更糟糕的結果。這在 Grok-Beta 和 Haiku 的流行“更容易”問題上很明顯。
更容易的非數學問題可能不會獲得 CoT 的相同好處。
我們還必須記住,我們可以推動模型在其能力範圍內發揮作用,但很少超過其能力。如果它不知道答案,它就不知道。
在繼續之前,我想提一下微調。
一個非常有趣的領域是嘗試在 CoT 數據集上微調較小的模型,以提高其準確性,使其達到比大 1-2 倍的模型的準確性。
我已經找到了多個資源,但不幸的是,我沒有發現任何我認為值得進行適當分析的基準模型的重大改進。
您將在下面看到我找到的開源模型。
您將在下面看到我還找到的已開源的 CoT 數據集。
這並不是說用於 CoT 的微調不會起作用,只是需要構建更好的、有良好文檔記錄的模型。
如果您熱衷於自己嘗試微調,請查看這些資源。我相信還有更多資源。
到目前為止,我們一直在研究模型在一個線程(或鏈)中生成輸出的線性技術。
但在第一篇 CoT 論文發表後不久,DeepMind 就提出了一種更先進的技術,稱為具有自一致性的鍊式思維 (CoT-SC)。
此技術創建多個推理路徑,並使用某種方法在最後選擇最一致的答案(或路徑)。
他們報告說,使用這種方法在算術推理方面獲得了大約 1-8% 的改進。
今年剛剛提出的一種方法遵循使用多條路徑的相同思想,但不使用任何提示。
還記得我在上一節中討論過的貪婪解碼的想法嗎?
這種方法類似,只是它不僅僅是強制使用最可能的標記,還查看整個響應的置信度分數。
為此,系統首先啟動一定數量 k 的初始頂級標記,然後從每個標記生成路徑。生成答案後,它通過分析不同路徑中每個標記的概率(logit)來計算置信度分數。
返回具有最高概率的答案(或路徑)。
這種方法稱為解碼 CoT,由 DeepMind 提出。這種方法的思想是查看模型對返回答案的內部置信度。
但是,如果它沒有固有的知識來回答問題會發生什麼?與 CoT-SC 一樣,這種方法在很大程度上取決於模型是否首先擁有正確的答案。
然而,這並不意味著我們不應該測試它。
對於所有這些技術,都有人在開源不同的實際實現,而這個也不例外。
因此,我很容易建立一個系統來測試這些方法,並使用較小的開源模型 Llama 3 8b 來比較哪個更好。
感謝 Codelion 開源了他的實現,這使得我很容易複製。
查看上面的結果,您可以看到與其他方法(例如熵或僅對該特定模型使用貪婪解碼)相比,我們使用解碼 CoT 明顯產生了最佳結果。
我們將在技術部分創建一個將使用此解碼 CoT 系統的 API,以便您可以了解其工作原理。
很難跟上,但研究已經遠遠超出了在更高風險領域內使用簡單的 CoT 進行推理。
我現在不會介紹所有這些策略,因為那是另一個主題,但我確實想提到三思而後行 (ToT),尤其是在與蒙特卡洛搜索結合使用的情況下。
ToT 於 2023 年底由普林斯頓大學和 DeepMind 提出,但通常基於先前基於樹的推理方法。
三思而後行 (ToT) 與具有自一致性的鍊式思維 (CoT-SC) 有些不同。它不是生成多個路徑並在生成後才對其進行評估,而是動態地評估 ToT 隨著其進展而產生的想法。
可以將其想像為 4 個不同的人一起解決問題。在每一步中,他們都會提出自己的想法,並共同評估哪些想法最具前景。如果一個人的推理似乎有缺陷,他們就會離開,因此其他人會繼續努力解決他們的問題。
最後,能夠正確推理的人將能夠提供他們的答案。
這允許模型動態地修剪看起來不佳的路徑,專注於更有前景的線程,從而可能節省資源。
但是,人們可能會質疑,系統如何決定哪個線程是對的,哪個線程是錯的?這由模型本身決定。
這也是為什麼像蒙特卡洛樹搜索 (MCTS) 這樣的擴展會提供更無偏見的評估機制的原因。 MCTS 允許反向傳播,這意味著它可以根據新信息重新訪問和改進早期步驟,而簡單的 ToT 只會向前移動。
對於 4 個人解決問題的案例,MCTS 將允許人們有不太理想的想法,並且仍然可以在遊戲中停留更長時間。評估方法將有所不同。
MCTS 可以模擬多個未來路徑,評估其潛力,並回溯以改進早期決策。它引入了外部指標(獎勵),而不是完全依賴模型。
像 UCB(上限置信界)這樣的統計數據使用這些獎勵來決定進一步探索或重新訪問哪些想法。
MCTS 比簡單的 ToT 複雜一些,可能應該單獨成文。
因此,到目前為止,您可能會認為,好吧,我們有一些改進,為什麼不總是使用更高級形式的鍊式思維呢?
好吧,首先是成本(以及思考時間)。
對於我應用於不同模型的鏈,我計算了平均推理步驟數。
看看這個,您平均每個問題要多付 8 倍的費用。對於在高級數學問題上表現最佳的 Sonnet,您將為每 500 個問題支付高達 15 美元。
這看起來可能不多,但是一旦您每天都使用此系統為客戶服務或您的團隊生成答案,您每月就要花費數百甚至數千美元。
在某些情況下,使用高級推理方法是有意義的,但並非總是如此。
現在可能有一種情況是針對 CoT 進行微調,基本上消除了產生多個調用的需要,但我到目前為止還沒有看到任何做得很好的開源模型。
這裡有點權衡。我們希望增加思考時間,以便模型有足夠的時間有效地進行推理,但這樣做也會增加用戶的挫敗感和成本。
今年 9 月,發表了一篇題為“To CoT or not to CoT?”的論文,該論文認為,應用 CoT 的大多數改進主要體現在數學和復雜推理方面。
我們在這裡也看到了這一點,簡單的問題改進有限。
當我們應用這些鏈時,我們必須等待更長時間才能得到響應。值得嗎?不過,應該注意的是,所有這些策略對於簡單的任務來說都可能過於復雜。
這就是為什麼您在大多數問題中使用 OpenAI 的 o1 時可能會感到沮喪的原因,而簡單的答案通常就足夠好了。
但是,如果您正在構建一個需要確保答案正確的系統,那麼採用某種形式的 CoT 或解碼可能是一個好主意。
可能值得使用一個模型根據問題的難度來設置第一步,然後分析它是否確信自己能夠首先回答它。然後讓模型進行推理(通過鏈),並在最後讓另一個模型對響應進行評分。
除了我在這裡介紹的內容之外,還有更多框架嗎?絕對有,但我只介紹了我認為理解起來很有趣的那些。這可以讓您了解我們在沒有信息過載的情況下取得了多大的進展。
大多數人工智能工程師都精通這些框架,但很可惜,這項研究並沒有像預期的那樣迅速傳播到公眾。
了解如何實現 CoT 應該是構建 LLM 應用程序的基礎知識的一部分,即使您決定不使用它們也是如此。
讓我們付諸實踐。
我們將使用開源模型 Llama 3.1 8b 實現解碼 CoT 系統。
解碼 CoT 的方法來自今年發布的論文“無需提示的鍊式思維推理”,實現是從此處找到的 Codelion 獲取的。我添加了一些功能,以便系統檢查難度級別以決定路徑數量 (k)。
由於我上次使用的是 Modal,這次我們可以使用 Beam,這也是一個無服務器 LLM 服務平台。他們提供 15 小時的免費套餐,因此這是免費的。我們將使用的腳本可以在此處找到。
如果您更願意使用 Colab 進行測試,則可以在此處運行此腳本。
結果應該是一個 API 端點,讓我們可以提出問題,它將評估難度,然後對問題執行解碼 CoT 並返回如下響應。
您將看到對大型語言模型的請求數量以及系統如何對問題進行分類。您還會注意到,該系統相當緩慢,因為它正在生成多個答案進行評估。
但是,如果我們使用相同的 8b 模型嘗試 Groq,我們會發現它無法正確回答問題。
正確答案是 27.3,額外燃料可獲得額外積分。
關於最終答案,我將注意到,雖然這樣一個較小的模型只能讓我們走這麼遠。不幸的是,使用更大的模型需要更多工作,因為我們需要將其存儲在某個地方,這可能很昂貴。
為了設置此系統,我將佔用您 5 分鐘的時間。您可以按照以下說明進行操作。
我們將首先獲得對我們將使用的模型的訪問權限。要使用 Llama 3 8b 模型,您需要通過 Hugging Face 獲得對它的訪問權限。
如果您已經擁有 Hugging Face 帳戶,此過程通常非常快。如果您沒有帳戶,您可以免費創建一個帳戶,然後導航到模型卡。
一旦我們進入模型卡,我們不妨測試一下模型,看看我們可以使用哪個問題來測試這個新系統。
這是一個相當標準的問題,我之前在評估中使用過它,但標準的 Llama 3 8b 模型很難處理這個問題。
獲得訪問權限後,請導航到“設置”以獲取訪問令牌。
將此令牌保存在某個地方,因為我們需要在 Beam 中設置它。
如果您沒有 Beam 帳戶,則需要創建一個帳戶(除非您選擇直接使用 Colab)。當然,您也可以在不同的平台上構建自己的系統。
如果您決定使用 Beam,請從其儀表板獲取 API 密鑰。
### 設置環境
現在,我們可以開始了。打開一個新的終端並創建一個新目錄,然後 cd 到該目錄。
<code>mkdir my-testing-dir cd my-testing-dir</code>
克隆我設置的存儲庫。
<code>git clone https://github.com/ilsilfverskiold/decoding-cot-beam.git </code>
創建一個虛擬環境(您需要為此安裝 python)。
<code>python3 -m venv .venv && source .venv/bin/activate</code>
安裝 beam 並進行身份驗證。
<code>pip install beam-client beam configure default --token "your_token_here"</code>
確保您設置了我們之前從 Hugging Face 獲取的 HF_TOKEN。
<code>beam secret create HF_TOKEN</code>
您可以直接從此處提供服務,但讓我們簡要介紹一下代碼。
如果您不感興趣,可以跳過下一部分。
根文件夾中有三個 python 文件。
<code>│ ├── app.py ├── question_classifier.py └── cot_decoder.py </code>
在 app.py 中,我們有來自 Beam 的代碼,允許我們(在啟動時)從 Hugging Face 下載模型的權重並通過卷緩存它。這意味著我們第一次運行它時,它可能很笨拙且緩慢。
Beam 還允許我們在腳本在 Beam 上遠程運行時加載包。
以下是帶有我的註釋的 app.py 的開頭:
<code>[...] # 这确保了这些包仅在脚本在 Beam 上远程运行时加载 if env.is_remote(): import torch from transformers import AutoModelForCausalLM, AutoTokenizer from cot_decoder import cot_decode from question_classifier import get_k_value # 模型参数和在卷中缓存的位置 MODEL_NAME = "meta-llama/Meta-Llama-3-8B-Instruct" CACHE_PATH = "./cached_models2" # 加载模型和标记器 def load_models(): tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, cache_dir=CACHE_PATH) tokenizer.pad_token = tokenizer.eos_token model = AutoModelForCausalLM.from_pretrained( MODEL_NAME, device_map="auto", torch_dtype=torch.float16, cache_dir=CACHE_PATH ) return model, tokenizer # 定义端点 # 您可以指定 CPU/内存/GPU + 图像 @endpoint( secrets=["HF_TOKEN"], on_start=load_models, # 启动时加载模型以进行缓存 name="meta-llama-3-8b-instruct", cpu=2, memory="32Gi", gpu="A100-40", image=Image( python_version="python3.9", python_packages=["torch", "transformers", "accelerate"], ), volumes=[Volume(name="cached_models2", mount_path=CACHE_PATH)], ) [...]</code>
我們定義了一個 @endpoint,其中包含我們想要使用的資源(A100 GPU 和 2 個 CPU 內核)。您還會看到我們在啟動時加載模型。
收到 API 調用後,我們將運行 generate_text() 函數。
<code>[...] def generate_text(context: Dict[str, Any], **inputs: Dict[str, Any]) -> Dict[str, Any]: # 从 on_start 检索模型和标记器 model, tokenizer = context.on_start_value # 根据问题的复杂性获取自适应 k 值 classification_type = None if k is None: k, classification_type = get_k_value(messages, context) try: output_text, confidence, llm_calls = cot_decode( model=model, tokenizer=tokenizer, messages=messages, k=k, # 使用自适应 k 值 **inputs # 将任何其他参数直接传递给 cot_decode ) # 返回输出 return { "output": output_text, "confidence": confidence, "complexity_info": { "k": k, "total_calls": llm_calls + 1, # + 分类调用 "classification": classification_type } } except Exception as e: return {"error": f"Error during generation: {str(e)}"}</code>
我們有一個函數,它首先使用 get_k_value() 根據複雜性計算 k。但這裡的關鍵函數是 cot_decode(),它將對我們的問題執行解碼鍊式思維。
此函數將接收消息、模型和標記器,並進行第一次初始調用以使用最高 logit 預測 k 個可能的下一個標記。
logit 是模型為每個可能的下一個標記分配的原始分數,讓我們知道模型對每個選項的置信度分數。
這些將作為生成多個答案的潛在起點。對於每個這些起點或起始標記,我們都會生成一個完整的答案,然後將其整體評分。
還記得我們討論過的貪婪解碼嗎?如果下一個標記的概率很高,我們只生成它?這將通過計算反映模型對完整答案的確定程度的置信度分數來查看整個句子,而不是逐個標記。
獲得具有最高置信度分數的路徑後,它將與 k 值一起返回。
還有一些其他選項,例如在模型返回多個高置信度答案時添加 aggregate_answers bool,但我們這裡沒有使用它。
現在我已經簡要解釋了代碼,我們將運行它以查看它的效果。
如果您一切設置正確,則應該能夠簡單地調用 serve。
<code>beam serve app.py:generate_text</code>
如果超時,請再次運行 serve,它將為您緩存模型。
要查看模型的存儲位置,您可以轉到 Beam.Cloud 平台中的卷。
一旦它運行起來,您將看到如下內容。
這意味著它已準備好進行測試。
您可以啟動 Postman 或使用 cURL(這意味著您在終端窗口中運行對端點的調用)
<code>mkdir my-testing-dir cd my-testing-dir</code>
響應應該類似於以下內容。
正如您所看到的,它的性能略好一些。
如果您想部署模型,您可以簡單地運行 deploy。
<code>git clone https://github.com/ilsilfverskiold/decoding-cot-beam.git </code>
我只是用它來測試,所以我現在可以關閉它了。
希望這篇文章具有教育意義和趣味性,並且您有所收穫。
如果您想查看大型語言模型和 CoT 技術的結果,您可以查看此表格以及您在此存儲庫中可以找到的所有其他資源。
如果它對您有所幫助,請留下評論並為我鼓掌。
❤
以上是高級及時工程:思想鏈(COT)的詳細內容。更多資訊請關注PHP中文網其他相關文章!