一個(gè)開源的輕量級(jí)agent框架-Agere
共 3628字,需瀏覽 8分鐘
·
2024-04-14 23:54
Datawhale干貨
推薦人:happyapplehorse,Datawhale學(xué)習(xí)者
簡(jiǎn)介
agere是一個(gè)開源的輕量級(jí)agent框架,主要特點(diǎn)是通用性和完全的可定制性。它通過將一個(gè)復(fù)雜流程拆解為一系列獨(dú)立的小步驟,來簡(jiǎn)化構(gòu)建具有復(fù)雜邏輯的agent的流程。
agere是agent的拉丁語詞源,常被翻譯為“行動(dòng)”或“做”,具有“驅(qū)動(dòng)”和“推動(dòng)某事發(fā)生”的意思。
agere沒有第三方依賴,使用
pip install agere
即可簡(jiǎn)單地安裝和使用。
agere使用 Job 和 handler 作為基本的任務(wù)節(jié)點(diǎn)類型,通過定義Job(一個(gè)類)和handler(函數(shù)或方法),來拆分一個(gè)agent的各個(gè)部分,這些節(jié)點(diǎn)可以復(fù)用,當(dāng)未來你想更改或者拓展部分功能時(shí),也會(huì)更加輕松。
在一個(gè)Job中,你可以提交新的Job,也可以調(diào)用handler,在handler中,你也可以調(diào)用別的handler,當(dāng)然也可以提交Job。
Job和handler都屬于 TaskNode 類型,也就是任務(wù)節(jié)點(diǎn),這些任務(wù)節(jié)點(diǎn)構(gòu)成樹狀結(jié)構(gòu),用它可以跟蹤任務(wù)之間的關(guān)系和運(yùn)行狀態(tài),在這些節(jié)點(diǎn)中,你可以為其添加在不同時(shí)刻執(zhí)行的callback,例如在任務(wù)開始時(shí),結(jié)束時(shí),遇錯(cuò)時(shí),或者被終止時(shí)等。
agere不像LangGraph那樣將節(jié)點(diǎn)和邊完全分離,而是采用邊節(jié)點(diǎn)的模式。在LangGraph中,任務(wù)被拆分為“節(jié)點(diǎn)”和“邊”,節(jié)點(diǎn)和邊是各自獨(dú)立的,而在agere中,任務(wù)被拆分為“節(jié)點(diǎn)和邊”,為了區(qū)別,可以把它叫做邊節(jié)點(diǎn),也就是帶邊的節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)與后面的邊被放在了一起。節(jié)點(diǎn)和邊各自獨(dú)立的好處是結(jié)構(gòu)更加清晰,而邊節(jié)點(diǎn)的好處是邏輯更加連貫,你在定義一個(gè)節(jié)點(diǎn)時(shí)就明確了后面的邊,而不用再在連接邊時(shí)再去想想我這個(gè)節(jié)點(diǎn)是干什么的來著,很可能你都已經(jīng)忘了,還要去查看節(jié)點(diǎn)中的代碼。
使用邊節(jié)點(diǎn)的模式帶來的另一個(gè)不同體現(xiàn)在傳遞參數(shù)方面。在LangGraph中,你需要構(gòu)造state object,也就是上下文變量context,你需要讓它與每一個(gè)節(jié)點(diǎn)相容,也就是確保每個(gè)節(jié)點(diǎn)都可以從該context變量中取出合適的信息并恰當(dāng)?shù)馗淖兯@實(shí)際上是一種負(fù)擔(dān)。
在agere中,由于節(jié)點(diǎn)和邊是放在一起的,這使得傳輸參數(shù)可以更加直接和靈活。你可以直接在調(diào)用中按需傳遞所需的任意形式的參數(shù),而不必使用統(tǒng)一要求的context變量。不光是傳遞參數(shù),在實(shí)現(xiàn)條件邊時(shí)也更加簡(jiǎn)單和直接。
當(dāng)然,agere是很靈活的,如果你覺得使用節(jié)點(diǎn)和邊的模式更加清晰,你完全也可以這樣做,你只需要把TaskNode定義為完全的節(jié)點(diǎn),不連接邊,然后,你可以簡(jiǎn)單地自定義實(shí)現(xiàn)不同的添加邊的操作,這可以通過使用callback來實(shí)現(xiàn)。你可以高度自定義自己的邊類型,例如簡(jiǎn)單邊,條件邊等。
但當(dāng)你使用node+edge模式時(shí),你可能需要考慮如何傳遞參數(shù),這通常通過使用共享的上下文變量context的形式來實(shí)現(xiàn),就像LangGraph中那樣。在agere中,這也可以有多種實(shí)現(xiàn)方式,例如你可以通過“祖先節(jié)點(diǎn)鏈”來訪問到共享的上級(jí)節(jié)點(diǎn),比如頂級(jí)節(jié)點(diǎn)commander,在該節(jié)點(diǎn)上設(shè)置共享參數(shù)來傳遞信息。
在構(gòu)建流程時(shí),agere和LangGraph在以下幾個(gè)方面 有所不同:
一心多用:agere可以多個(gè)任務(wù)同時(shí)并行
審時(shí)度勢(shì):可以通過callback控制任務(wù)的不同時(shí)刻的不同狀態(tài)
節(jié)外生枝:可對(duì)節(jié)點(diǎn)的不同狀態(tài)進(jìn)行連接,例如將邊連接到一個(gè)節(jié)點(diǎn)的開始、結(jié)束或終止等狀態(tài)。
量體裁衣:節(jié)點(diǎn)之間傳遞參數(shù)更加靈活,每個(gè)節(jié)點(diǎn)都可以定制化傳遞參數(shù)。
當(dāng)然,LangGraph是一個(gè)很優(yōu)秀的框架,它也有很多優(yōu)點(diǎn),我就不多說了。
用agere來構(gòu)建一個(gè)agent的時(shí)候,它不會(huì)使你少寫很多代碼。agere沒有很多內(nèi)建的具體功能,它主要用于流程驅(qū)動(dòng)。agere強(qiáng)調(diào)的是通用性,它不限制你去使用任何的工具,也不依賴于任何特定的接口或形式,所以它也沒辦法封裝很多具體的功能。
有一些具體的邏輯需要你去寫,換句話說,就是你自己去調(diào)用,這是個(gè)很有意思的事情,正因?yàn)樗灰蕾囉谌魏喂ぞ?,也不依賴于特定的接口或形式,不與任何工具相耦合,使得它可以去調(diào)用任何工具,你可以去使用langchain來調(diào)用它的connector,也可以使用semantic kernel提供的語義化插件的功能等。
它的通用性使得它很容易與其它工具協(xié)同與集成,它不依賴于第三方庫(kù)也是出于這方面的考慮,現(xiàn)在ai發(fā)展地又這么快,我就遇到openai更新了一個(gè)新功能,這邊幾個(gè)依賴庫(kù)更新不同步,導(dǎo)致我這邊新的功能即使寫完了也沒法用的情況。另一個(gè)原因是,每一個(gè)工具都不可能面面俱到,我沒有必要非要在我這里寫一個(gè)別的工具中已經(jīng)有的并且可能還更好更成熟的功能,我能寫的比它更好嗎?同樣的,別的具有眾多功能的庫(kù)它提供的功能也不見得都是最好的,所以我選擇靈活的接口能力,沒有必要把自己局限于一種框架或者工具中,你喜歡用哪個(gè)庫(kù)哪個(gè)功能你都可以去用,讓它可以組合不同工具的最優(yōu)秀的功能,這是我希望的。
agere中的基本概念
我們以下面這張圖來簡(jiǎn)單介紹一下agere中的基本概念。
TaskNode
任務(wù)節(jié)點(diǎn),上圖中的Commander,Job和handler都屬于TaskNode節(jié)點(diǎn)。TaskNode節(jié)點(diǎn)用于追蹤各個(gè)任務(wù)節(jié)點(diǎn)的父子關(guān)系和完成狀態(tài),每個(gè)節(jié)點(diǎn)都具有一個(gè)父節(jié)點(diǎn),同時(shí)可以具有0個(gè)或多個(gè)子節(jié)點(diǎn)。這些節(jié)點(diǎn)構(gòu)成一個(gè)樹狀結(jié)構(gòu),通過這個(gè)節(jié)點(diǎn)樹,能夠跟蹤任務(wù)之間的關(guān)系,例如一個(gè)任務(wù)是誰的子任務(wù),它又開啟了哪些子任務(wù)等。當(dāng)一個(gè)節(jié)點(diǎn)自己的工作完成了,并且這個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)也完成時(shí),這個(gè)節(jié)點(diǎn)才會(huì)變成完成狀態(tài)。圖中灰色表示節(jié)點(diǎn)已完成。每一個(gè)節(jié)點(diǎn)完成時(shí),他就會(huì)告訴自己的父節(jié)點(diǎn),說我完成了。
Job
Job是打包了一個(gè)具體任務(wù)和執(zhí)行該任務(wù)所需資源的對(duì)象,它就好像是跟上級(jí)匯報(bào)說:我有個(gè)什么什么工作要做,具體要干這些這些事情,需要的資料給你,我跟你說清楚了吧,這個(gè)工作轉(zhuǎn)交給你了,其它我不管了。就是這么個(gè)意思。
handler
它是一個(gè)函數(shù)或者方法,類似于協(xié)程函數(shù),它返回一個(gè)handler對(duì)象,這個(gè)handler對(duì)象可以被其它任務(wù)節(jié)點(diǎn)調(diào)用,也可以被直接await。它就好像是跟下級(jí)說:我有這么件事,你去幫我做了。
Commander
它是用來自動(dòng)調(diào)度和執(zhí)行任務(wù)的節(jié)點(diǎn),它通常是所有節(jié)點(diǎn)的根節(jié)點(diǎn)。當(dāng)你定義好了一些Job和handler時(shí),把初始的入口工作交給它,它就可以幫你自動(dòng)將這些工作組織起來并執(zhí)行。
callback
另外,還有一個(gè)重要的元素是callback,在TaskNode節(jié)點(diǎn)的不同狀態(tài)可以觸發(fā)不同的回調(diào)函數(shù),例如一個(gè)節(jié)點(diǎn)的任務(wù)開始執(zhí)行時(shí),結(jié)束時(shí),遇錯(cuò)時(shí),終止時(shí)我們都可以為其添加相應(yīng)的回調(diào)函數(shù)。
示例
假如我們想構(gòu)建一個(gè)最常用的使用OpenAI的GPT模型并具有工具調(diào)用能力的聊天agent,另外,在這個(gè)agent中,我們想讓GPT可以在調(diào)用工具的同時(shí)也可以給用戶發(fā)送消息(目前GPT本身只能選擇給用戶發(fā)送消息或者選擇調(diào)用工具,兩者不能同時(shí)進(jìn)行)。
我們可以這樣做:定義兩個(gè)Job,一個(gè)ChatJob,用來發(fā)起一個(gè)新的對(duì)話,一個(gè)ResponseJob,用來接收GPT回復(fù)的內(nèi)容,三個(gè)handler,一個(gè)response_handler,用來解析GPT的回復(fù)消息,一個(gè)user_handler用來顯示發(fā)給用戶的消息,一個(gè)tool_call_handler,用來執(zhí)行函數(shù)調(diào)用。另外,我們還為ResponseJob添加一個(gè)callback,讓它在結(jié)束時(shí)發(fā)起下一輪對(duì)話,最后用一個(gè)commander來執(zhí)行它。
這個(gè)agent的流程圖如下所示:下面是它的運(yùn)行過程的演示動(dòng)畫:
如果讀到這里,相信你對(duì)agere已經(jīng)有了初步的了解,如果你感興趣,歡迎查看這里:
Github:https://github.com/happyapplehorse/agere
文檔頁(yè):https://happyapplehorse.github.io/agere/
如果覺得還不錯(cuò),歡迎您參與其中,或者給出您寶貴的意見與建議。
