很早之前我們就聊過ToolFormer,Gorilla這類API呼叫的Agent正規化,這一章我們針對真實世界中工具呼叫的以下幾個問題,介紹微調(ToolLLM)和prompt(AnyTool)兩種方案。
- 真實世界的API數量龐大且多樣:之前的多數工具呼叫論文,工具數量有限,工具相對簡單具體,並且往往侷限在某一個領域例如模型呼叫
- 多工具呼叫:解決一個問題往往需要使用多個工具,需要透過多輪迭代實現
- 當API數量多且涉及多工具時,如何更有效的規劃工具呼叫,並召回相關工具用於推理
ToolLLM
- ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs
- Tool Learning with Foundation Models
- StableToolBench: Towards Stable Large-Scale Benchmarking on Tool Learning of Large Language Models
- https://github.com/beijixiong1/ToolLLM
- https://github.com/OpenBMB/ToolBench
ToolLLM是清華一系列工具呼叫文章中的其中一篇,透過構建工具呼叫樣本訓練LLaMA並開源了評估集ToolBench。既然是微調方案,如何構建微調樣本是核心,所以我們重點說下樣本構建,和評估部分
訓練
1.API Pool
ToolLLM使用了RapidAPI Hub提供的真實世界各類API,透過初步的呼叫測試過濾了類似高延時,404調不通之類的工具後,總共保留了3451個工具,包含16464個API。
RapidAPI的工具有category和collection兩種分類體系,其中每個工具包含1個或多個API。例如yahoo finance工具屬於金融分類,該工具下面有get_market_news, get_stock_quotes等眾多API。這裡的分類體系後面被用於多工具呼叫的指令樣本構建的分層取樣的依據。
2.指令生成
為了保證指令樣本的覆蓋率和多樣性,指令的構建會基於每個工具的所有API來進行,分成了單工具呼叫和多工具呼叫指令兩部分。其中單工具就是遍歷以上所有的Tool,每次使用一個工具的所有API,而多工具組合是每次取樣同一個分類下2~5個工具,每個工具取樣不超過3個API來構成, 這裡論文分別使用上面RapidAPI的category分類,和collection分類作為分層取樣的類別。單工具,category多工具,collection多工具分別對應了資料樣例中的G1,G2,G3分類。
基於上面取樣的API候選,指令構建使用Prompt讓ChatGPT來同時生成相關的指令,以及該指令使用哪些API來完成,得到(Instruction,APIs)的樣本對。prompt包含3個部分
- 任務描述:哈哈看到prompt的一刻我小腦都萎縮了怎麼這麼長....., 直接看吧
- few-shot: 這裡論文人工構建了12個單工具,36個多工具的種子,每次隨機取樣3個,如下圖
- API說明:包括API描述,引數描述,和codesnippet
針對生成的指令和APIs樣本對,會進行簡單的過濾,過濾生成的API列表出現輸入API之外的幻覺樣本。最終得到了200K的樣本對
3.DFSDT答案生成
在構建多輪的工具呼叫回答時,論文在ReACT的基礎上進行了改良,主要解決兩個問題:Error Propogation, Limited Exploration。說白了就是ReACT是線性串聯的,而論文借鑑了Tree of Thought,把線性改成了樹形結構(DT),透過深度優先搜尋(DFS),來提高正確路徑生成的機率。整個遍歷的過程如下圖
遍歷的幾個細節如下
- 構建順序是DFS而非BFS,無他更經濟實惠,如果第一條path走到Leaf Node就解決了,那其實就是ReACT。如果中間節點失敗了,再回退到parent Node去生成新的child Node,也就是DFS的前序遍歷。
- 以上判斷一個Node是否失敗或者是Leaf節點,論文增加了"Finish by Giving Up","Finish with Final Answer"兩個API,前者DFS回退搜尋,後者終止DFS。
- 在DFS過程中,為了增加子節點生成結果的多樣性,論文采用了Diversity Prompt,會把之前Node生成的推理結果作為輸入,讓模型生成不一樣的嘗試步驟,prompt指令如下
這一步最終只保留成功生成最終“Finish with Final Answer“的路徑,總共得到了126,486個(指令,答案)樣本對
4.微調
論文選擇微調LLaMA-2 7B, 以上多輪工具呼叫,被構建成多輪對話的形式。訓練超參:epoch=2, LR =5e-5, batch= 64, MAX_SEQ_LEN =8192, 這裡考慮LLaMA是4096的長度論文使用了PI內插。
推理和評估
推理過程可說的不多,流程就是先使用API Retriever召回使用者指令相關的多個工具,再進行一輪-多輪的工具呼叫路徑生成。我們分別說下2個細節:API召回和評估。論文還使用了一些API返回內容壓縮一類的技巧,不過這個感覺離專為大模型設計API返回的一天並不遠,咱這裡就不聊壓縮了。
1. API Retriever
推理過程的第一步是如何根據使用者的query召回可能用來回答的API候選。當然可以讓使用者自己選擇工具(Oracle),但其實細想就會發現,要是得讓使用者自己從API海洋裡面找自己想要的,那通用智慧也就不通用了.....
這裡論文微調了Sentence-Bert,使用上面指令構建步驟得到的(query,APIs)作為正樣本對,這裡API使用API Document(包括API名稱,描述,引數etc)來表徵API,然後隨機取樣其他API作為負樣本,進行對比學習。效果上,論文和BM25,OpenAI-Ada進行對比效果顯著更好。
在很多垂直場景裡,API Retriever這一步的重要性可能被低估,感覺給API生成更豐富全面的Description描述,來提升工具召回率是很有必要的。以及可以引入API相關工具,相關分類的其他資訊,來進一步最佳化召回。
2. 評估
考慮整個工具呼叫路徑的複雜程度,人工標註的成本極高。因此這裡論文借鑑了AlpacaEval使用模型來進行評估,分別從以下兩個角度進行評估。
- Pass Rate:評估單模型生成的回答路徑是否回答指令問題
- Win Rate:評估兩個模型生成的回答路徑進行對比評估
以上評估均是使用ChatGPT3.5進行,取多次評估的平均值。具體指令詳見toolbench/tooleval/evaluators/。論文對比了全機器的ToolEval和人工標註的一致性,一致率在80%左右。
為了檢驗樣本外泛化的效果,論文分別評估了樣本外指令(Inst),相同分類樣本外工具(Tool),不同分類樣本外工具(Cat),整體上微調後的llama-7B基本能打平GPT4,並且DFSDT相比ReACT在L2,L3的複雜問題上有更明顯的提升。
AnyTool
- AnyTool:Self-Reflective, Hierarchical Agents for Large-Scale API Calls
- https://github.com/dyabel/anytool
AnyTool在ToolLLM的基礎上做了幾點調整,這裡只我們關注幾個差異點。更多論文的細節,大家在有需要的時候再去看論文就好~
1. 分層召回
AnyTool更好的利用了RapidAPI的層次化結構進行API候選的召回。論文使用的是3類Agent互動的方案,分別是
- Meta Agent:就是基於使用者Query,先聯想相關的工具分類,並建立對應分類的Agent
- Category Agent:每個分類的Agent思考相關的工具,並初始化對應工具的Agent
- Tool Agent:每個工具的Agent召回相關的API,併合並進API候選池
以上的3類Agent都是基於大模型Prompt實現,具體指令詳見anytool/prompt_template。雖然大模型推理成本較高,但以上Divide-Conqure的方案,可以透過多層召回降低每一層的候選數量,並在同一層Agent推理進行併發,所以整體推理耗時相對可控。論文對比了把以上層次召回展平,以及Ada等Embedding的召回效果,整體上分層召回顯著更優。不過這裡其實有個前提,就是你的API全集要足夠大,才需要考慮這種方案。
2. Self-Reflection
當一輪推理結束,如果模型給出了“Give UP”的結果,則使用模型自己的放棄理由作為Context觸發反思模組;如果模型給出了結果,但GPT4判斷結果錯誤,則使用GPT4的理由作為Context。反思涉及到API召回模組和規劃推理模組。
API召回部分會分別使用以上Context,和下面的指令,按從底層到頂層的順序重新啟用上一輪使用的Tool,Category,Meta Agent,目標就是進一步擴充套件更多的API候選,來進行重新推理。
推理部分,如果模型上一輪給出了“Give UP”的結果,會先剔除上一輪使用過的API,再加入上面擴充套件的新API,進行一輪重新的嘗試。
3. 評估
AnyTool針對以上ToolBench的評估標準中的Pass Rate進行了調整。ToolLLM在計算Pass Rate時分成了“可解決”和“不可解決”兩個部分,其中“不可解決“是GPT4判斷指令的候選API都和指令無關,或者指令本身不可解決。而這部分“不可解決”會大機率被算成透過。所以如果在構建指令的過程中,有相當量級的API候選和指令無關的話,就會拉高Pass Rate。而AnyTool在評估過程中,剔除了GPT4評估問題是否可解的步驟,直接評估模型的回答結果是否正確。並且對ToolBench集進行了人工過濾,剔除了無效的指令樣本。 在過濾後的樣本上,AnyTool只計算了Pass Rate結果如下,和以上ToolLLM一樣分成了Inst-I, Category-C,Tool-T三種不同的樣本外型別進行評估,AnyTool會有進一步的提升。
同時論文針對以上兩個模組進行了消融實驗,層次召回和反思模組對AnyTool的貢獻都很大。個人對召回模組帶來的提升更感興趣,因為一切推理的前置模組的影響都更顯著。也進一步印證了召回合理API這一步在整個工具呼叫鏈路中的重要性。
ToolLLM資源收藏
如果你也在開發工具相關服務,或者在設計Agent Pipeline,以下是一些可以學習借鑑的資源~
- Tool Server構建
- llama index tools:https://github.com/run-llama/llama_index/tree/main/llama-index-integrations/tools
- langchain tools: https://github.com/langchain-ai/langchain/tree/master/libs/community/langchain_community/tools
- phidata tools:https://github.com/phidatahq/phidata/tree/main/phi/tools
- BMTools:https://github.com/OpenBMB/BMTools
- MSAgent:https://github.com/modelscope/modelscope-agent
- 工作流搭建/中間層設計
- Coze: https://www.coze.com/store/bot
- Anakin: https://app.anakin.ai/discover
- Dify: https://cloud.dify.ai/tools
- langflow:https://www.langflow.org/
想看更全的大模型相關論文梳理·微調及預訓練資料和框架·AIGC應用,移步Github >> DecryPrompt