AI Agent 是目前炙手可熱的一個領域,在OpenAI 應用研究主管LilianWeng 寫的一篇長篇文章中[1],她提出了Agent = LLM 記憶規劃技能工具使用的概念
圖1 Overview of a LLM-powered autonomous agent system
Agent的作用是利用LLM的強大語言理解和邏輯推理能力,呼叫工具來幫助人類完成任務。然而,這也帶來了一些挑戰,例如基礎模型的能力決定了Agent調用工具的效率,但基礎模型本身存在著大模型幻覺等問題
本文以「輸入一段指令自動實現複雜任務拆分與函數呼叫」的場景為例,來建構基礎Agent 流程,並著重講解如何透過「基礎模型選擇」、「Prompt設計」等來成功建構「任務拆分”和“函數調用”模組。
重新寫的內容是:位址:
https://sota. jiqizhixin.com/project/smart_agent
#GitHub Repo:
要重寫的內容是:https://github.com/zzlgreat/smart_agent
##對於實現「輸入一段指令自動實現複雜任務拆分和函數呼叫」,專案建構的Agent 流程如下:
#圖1 《ReWOO: Decoupling Reasoning from Observations for Efficient Augmented Language Models》
# #為了實現上述流程,在「任務拆分」和「函數呼叫」模組中,專案分別設計了兩個微調模型,以實現將複雜任務拆分並按需調用自訂函數的功能。歸納總結的模型solver,可以與拆分任務模型相同
在「任務拆分」模組中,大模型需要具備將複雜任務分解為簡單任務的能力。 「任務拆分」的成功與否主要取決於兩個因素:
同時希望任務分割模型在給定prompt 範本下的輸出格式可以盡可能相對固定,但也不會過度擬合喪失模型原本的推理和泛化能力,這裡採取lora 微調qv 層,對原模型的結構改變盡可能少。
在「函數呼叫」模組中,大模型需要具備穩定呼叫工具的能力,以適應處理任務的要求:
###此外,在算力使用方面,透過lora/qlora 微調實現了低算力條件下大型語言模型的微調和推理,並採用量化部署的方式,進一步降低推理的門檻。
#對於選擇「任務拆分」模型,我們希望模型具備強大的泛化能力和一定的思維鏈能力。在這方面,我們可以參考HuggingFace上的Open LLM排行榜來選擇模型,我們更關注的是衡量文本模型多任務準確性的測試MMLU和綜合評分Average
需要重新書寫的內容是:圖2 HuggingFace 開放的LLM排行榜(0921)
本專案選擇了任務分割模型型號為:
對於選擇"函數呼叫"模型,meta開源的Llama2版本的CodeLlama程式設計模型的原始訓練資料包含了大量的程式碼數據,因此可以嘗試使用qlora進行自訂腳本微調。對於函數呼叫模型,選擇CodeLlama模型(34b/13b/7b均可)作為基準
本項目選擇了函數呼叫模型型號為:
################################################################################################################## ###############codellama 34b/7b:負責函數呼叫的模型,該模型採用大量程式碼資料訓練,程式碼資料中必然包含大量對函數的描述類自然語言,對於給定函數的描述具有良好的zero-shot 能力。 ##################為了對「函數呼叫」模型進行微調,該專案採用了 prompt loss mask 的訓練方式,以穩定處理模型的輸出。以下是損失函數的調整方式:######
任務拆分方面,該專案使用了大型語言模型高效推理框架ReWOO(Reasoning WithOut Observation)中planner 設計的Prompt 格式。只需要將'Wikipedia[input]'等函數替換為相應的函數和描述即可,以下是該範例prompt:
For the following tasks, make plans that can solve the problem step-by-step. For each plan, indicate which external tool together with tool input to retrieve evidence. You can store the evidence into a variable #E that can be called by later tools. (Plan, #E1, Plan, #E2, Plan, ...) Tools can be one of the following: Wikipedia[input]: Worker that search for similar page contents from Wikipedia. Useful when you need to get holistic knowledge about people, places, companies, historical events, or other subjects.The response are long and might contain some irrelevant information. Input should be a search query. LLM[input]: A pretrained LLM like yourself. Useful when you need to act with general world knowledge and common sense. Prioritize it when you are confident in solving the problem yourself. Input can be any instruction.
對於函數調用,因為後續會進行qlora 微調,所以直接採用huggingface 上開源函數呼叫資料集[3] 中的prompt 樣式。請參見下文。
### Instruction:<prompt> (without the )### Response:如:### Instruction:For the following tasks, make plans that can solve the problem step-by-step. For each plan, indicate which external tool together with tool input to retrieve evidence. You can store the evidence into a variable #E that can be called by later tools. (Plan, #E1, Plan, #E2, Plan, ...) Tools can be one of the following:get_current_time[input]: Get the current time for now. search_bing[input]: Search the web for content on Bing, and return the top 10 results. Remember, the results may not as good as Wikipedia. If you think the result will not exist in wikipedia, use it. search_wiki[input]: Search the web for content on Wikipedia, and return the top 3 results. If you think the result can exist in wikipedia, use it. search_bilibili[input]: Search for videos on Bilibili, which is a website full of ACG. It can return top 10 search results. save_file[input]: save a file in the target dir which contains the data. query_mysql[input]: Execute the sql in the local mysql database. And return the result. What movies did the director of 'Oppenheim' direct? List the top 10 best.### Response:Step 1: Identify the director of "Oppenheimer" movie.#E1 = search_wiki("Director of Oppenheimer")Step 2: Retrieve information about the director's other works.If the retrieved name exists in Wikipedia, proceed with searching their filmography using search_wiki. Otherwise, try searching through Bing or another source like IMDb.For example, if Christopher Nolan is found as the director of "Oppenheimer":#E2 = search_bing("Filmography of Christopher Nolan")Step 3: Extract the list of films directed by this person from the retrieved information.From the returned results, extract the titles of the top 10 best movies according to critics/audience ratings or personal preference.</prompt>
採用trelis 資料集的格式。資料集規模較小,僅有55行。其結構實際上與alpaca格式相似。分為systemPrompt,userPrompt和assistantResponse,分別對應alpaca的Instruction,prompt和Response。以下是範例:
圖3 HuggingFace 函數呼叫開源資料集範例
在Ubuntu 22.04系统上,使用了CUDA 11.8和Pytorch 2.0.1,并采用了LLaMA-Efficient-Tuning框架。此外,还使用了Deepspeed 0.10.4
需要进行针对 Marcoroni-70B 的 lora 微调
全部选择完成后,新建一个训练的 bash 脚本,内容如下:
accelerate launch src/train_bash.py \--stage sft \--model_name_or_path your_model_path \--do_train \--dataset rewoo \--template alpaca \--finetuning_type lora \--lora_target q_proj,v_proj \--output_dir your_output_path \--overwrite_cache \--per_device_train_batch_size 1 \--gradient_accumulation_steps 4 \--lr_scheduler_type cosine \--logging_steps 10 \--save_steps 1000 \--learning_rate 5e-6 \--num_train_epochs 4.0 \--plot_loss \--flash_attn \--bf16
这样的设置需要的内存峰值最高可以到 240G,但还是保证了 6 卡 4090 可以进行训练。开始的时候可能会比较久,这是因为 deepspeed 需要对模型进行 init。之后训练就开始了。
需要重新写的内容是:图4 6 卡 4090 训练带宽速度
共计用时 8:56 小时。本次训练中因为主板上的 NVME 插槽会和 OCULINK 共享一路 PCIE4.0 x16 带宽。所以 6 张中的其中两张跑在了 pcie4.0 X4 上,从上图就可以看出 RX 和 TX 都只是 PCIE4.0 X4 的带宽速度。这也成为了本次训练中最大的通讯瓶颈。如果全部的卡都跑在 pcie 4.0 x16 上,速度应该是比现在快不少的。
需要进行改写的内容是:图5展示了LLaMA-Efficient-Tuning生成的损失曲线
以上是 LLaMA-Efficient-Tuning 自动生成的 loss 曲线,可以看到 4 个 epoch 后收敛效果还是不错的。
2)针对 codellama 的 qlora 微调
根据前文所述的 prompt loss mask 方法,我们对 trainer 类进行了重构(请参考项目代码仓库中的 func_caller_train.py)。由于数据集本身较小(共55行),所以仅需两分钟即可完成4个epoch的训练,模型迅速收敛
在项目代码仓库中,提供了一个简短可用的 toolkit 示例。里面的函数包括:
现在有一个70B和一个34B的模型,在实际使用中,用6张4090同时以bf16精度运行这两个模型是不现实的。但是可以通过量化的方法压缩模型大小,同时提升模型推理速度。这里采用高性能LLM推理库exllamav2运用flash_attention特性来对模型进行量化并推理。在项目页面中作者介绍了一种独特的量化方式,本文不做赘述。按照其中的转换机制可以将70B的模型按照2.5-bit量化为22G的大小,这样一张显卡就可以轻松加载
需要重新编写的内容是:1)测试方法
給定一段不在訓練集的複雜任務描述,同時在 toolkit 中加入訓練集中不包含的函數和對應描述。如果 planner 可以完成對任務進行拆分,distributor 可以呼叫函數,solver 可以根據整個流程對結果進行總結。
需要重新寫的內容是:2)測試結果
任務拆分:首先使用text-generation -webui 快速測試任務拆分模型的效果,如下圖所示:
#圖6 任務拆分測試結果
#這裡可以寫一個簡單的restful_api 接口,方便在agent 測試環境下的呼叫(請參閱專案程式碼fllama_api.py)。
函數呼叫:在專案中已經寫好了一個簡單的 planner-distributor-worker-solver 的邏輯。接下來就讓測試一下這個任務。輸入一段指令:what movies did the director of 'Killers of the Flower Moon' direct? List one of them and search it in bilibili.
「搜尋 bilibili 」這個函數是不包含在專案的函數呼叫訓練集中的。同時這部電影也是一部還沒上映的新電影,不確定模型本身的訓練資料有沒有包含。可以看到模型很好地將輸入指令進行拆分:
同時進行函數調用得到了以下結果:點擊結果是Goodfellas,和該部電影的導演配對得上。
本專案以「輸入一段指令自動實現複雜任務拆分與函數呼叫」場景為例,設計了一套基本agent 流程:toolkit-plan-distribute-worker-solver 來實現一個可以執行無法一步完成的初級複雜任務的agent。透過基礎模型的選型和 lora 微調使得低算力條件下一樣可以完成大模型的微調和推理。並採用量化部署的方式,進一步降低推理的門檻。最後透過該 pipeline 實現了一個搜尋電影導演其他作品的範例,實現了基礎的複雜任務完成。
限制:本文只是基於搜尋和基本操作的 toolkit 設計了函數呼叫和任務拆分。使用的工具集非常簡單,並沒有太多設計。針對容錯機制也沒有太多考慮。透過本項目,大家也可以繼續向前一步探索 RPA 領域上的應用,進一步完善 agent 流程,實現更高程度的智慧自動化提升流程的可管理性。
以上是AI Agent 如何實現? 6張4090 魔改Llama2:一句指令拆分任務、呼叫函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!