一个开源的轻量级agent框架-Agere
共 3628字,需浏览 8分钟
·
2024-04-14 23:54
Datawhale干货
推荐人:happyapplehorse,Datawhale学习者
简介
agere是一个开源的轻量级agent框架,主要特点是通用性和完全的可定制性。它通过将一个复杂流程拆解为一系列独立的小步骤,来简化构建具有复杂逻辑的agent的流程。
agere是agent的拉丁语词源,常被翻译为“行动”或“做”,具有“驱动”和“推动某事发生”的意思。
agere没有第三方依赖,使用
pip install agere
即可简单地安装和使用。
agere使用 Job 和 handler 作为基本的任务节点类型,通过定义Job(一个类)和handler(函数或方法),来拆分一个agent的各个部分,这些节点可以复用,当未来你想更改或者拓展部分功能时,也会更加轻松。
在一个Job中,你可以提交新的Job,也可以调用handler,在handler中,你也可以调用别的handler,当然也可以提交Job。
Job和handler都属于 TaskNode 类型,也就是任务节点,这些任务节点构成树状结构,用它可以跟踪任务之间的关系和运行状态,在这些节点中,你可以为其添加在不同时刻执行的callback,例如在任务开始时,结束时,遇错时,或者被终止时等。
agere不像LangGraph那样将节点和边完全分离,而是采用边节点的模式。在LangGraph中,任务被拆分为“节点”和“边”,节点和边是各自独立的,而在agere中,任务被拆分为“节点和边”,为了区别,可以把它叫做边节点,也就是带边的节点,每个节点与后面的边被放在了一起。节点和边各自独立的好处是结构更加清晰,而边节点的好处是逻辑更加连贯,你在定义一个节点时就明确了后面的边,而不用再在连接边时再去想想我这个节点是干什么的来着,很可能你都已经忘了,还要去查看节点中的代码。
使用边节点的模式带来的另一个不同体现在传递参数方面。在LangGraph中,你需要构造state object,也就是上下文变量context,你需要让它与每一个节点相容,也就是确保每个节点都可以从该context变量中取出合适的信息并恰当地改变它,这实际上是一种负担。
在agere中,由于节点和边是放在一起的,这使得传输参数可以更加直接和灵活。你可以直接在调用中按需传递所需的任意形式的参数,而不必使用统一要求的context变量。不光是传递参数,在实现条件边时也更加简单和直接。
当然,agere是很灵活的,如果你觉得使用节点和边的模式更加清晰,你完全也可以这样做,你只需要把TaskNode定义为完全的节点,不连接边,然后,你可以简单地自定义实现不同的添加边的操作,这可以通过使用callback来实现。你可以高度自定义自己的边类型,例如简单边,条件边等。
但当你使用node+edge模式时,你可能需要考虑如何传递参数,这通常通过使用共享的上下文变量context的形式来实现,就像LangGraph中那样。在agere中,这也可以有多种实现方式,例如你可以通过“祖先节点链”来访问到共享的上级节点,比如顶级节点commander,在该节点上设置共享参数来传递信息。
在构建流程时,agere和LangGraph在以下几个方面 有所不同:
一心多用:agere可以多个任务同时并行
审时度势:可以通过callback控制任务的不同时刻的不同状态
节外生枝:可对节点的不同状态进行连接,例如将边连接到一个节点的开始、结束或终止等状态。
量体裁衣:节点之间传递参数更加灵活,每个节点都可以定制化传递参数。
当然,LangGraph是一个很优秀的框架,它也有很多优点,我就不多说了。
用agere来构建一个agent的时候,它不会使你少写很多代码。agere没有很多内建的具体功能,它主要用于流程驱动。agere强调的是通用性,它不限制你去使用任何的工具,也不依赖于任何特定的接口或形式,所以它也没办法封装很多具体的功能。
有一些具体的逻辑需要你去写,换句话说,就是你自己去调用,这是个很有意思的事情,正因为它不依赖于任何工具,也不依赖于特定的接口或形式,不与任何工具相耦合,使得它可以去调用任何工具,你可以去使用langchain来调用它的connector,也可以使用semantic kernel提供的语义化插件的功能等。
它的通用性使得它很容易与其它工具协同与集成,它不依赖于第三方库也是出于这方面的考虑,现在ai发展地又这么快,我就遇到openai更新了一个新功能,这边几个依赖库更新不同步,导致我这边新的功能即使写完了也没法用的情况。另一个原因是,每一个工具都不可能面面俱到,我没有必要非要在我这里写一个别的工具中已经有的并且可能还更好更成熟的功能,我能写的比它更好吗?同样的,别的具有众多功能的库它提供的功能也不见得都是最好的,所以我选择灵活的接口能力,没有必要把自己局限于一种框架或者工具中,你喜欢用哪个库哪个功能你都可以去用,让它可以组合不同工具的最优秀的功能,这是我希望的。
agere中的基本概念
我们以下面这张图来简单介绍一下agere中的基本概念。
TaskNode
任务节点,上图中的Commander,Job和handler都属于TaskNode节点。TaskNode节点用于追踪各个任务节点的父子关系和完成状态,每个节点都具有一个父节点,同时可以具有0个或多个子节点。这些节点构成一个树状结构,通过这个节点树,能够跟踪任务之间的关系,例如一个任务是谁的子任务,它又开启了哪些子任务等。当一个节点自己的工作完成了,并且这个节点的所有子节点也完成时,这个节点才会变成完成状态。图中灰色表示节点已完成。每一个节点完成时,他就会告诉自己的父节点,说我完成了。
Job
Job是打包了一个具体任务和执行该任务所需资源的对象,它就好像是跟上级汇报说:我有个什么什么工作要做,具体要干这些这些事情,需要的资料给你,我跟你说清楚了吧,这个工作转交给你了,其它我不管了。就是这么个意思。
handler
它是一个函数或者方法,类似于协程函数,它返回一个handler对象,这个handler对象可以被其它任务节点调用,也可以被直接await。它就好像是跟下级说:我有这么件事,你去帮我做了。
Commander
它是用来自动调度和执行任务的节点,它通常是所有节点的根节点。当你定义好了一些Job和handler时,把初始的入口工作交给它,它就可以帮你自动将这些工作组织起来并执行。
callback
另外,还有一个重要的元素是callback,在TaskNode节点的不同状态可以触发不同的回调函数,例如一个节点的任务开始执行时,结束时,遇错时,终止时我们都可以为其添加相应的回调函数。
示例
假如我们想构建一个最常用的使用OpenAI的GPT模型并具有工具调用能力的聊天agent,另外,在这个agent中,我们想让GPT可以在调用工具的同时也可以给用户发送消息(目前GPT本身只能选择给用户发送消息或者选择调用工具,两者不能同时进行)。
我们可以这样做:定义两个Job,一个ChatJob,用来发起一个新的对话,一个ResponseJob,用来接收GPT回复的内容,三个handler,一个response_handler,用来解析GPT的回复消息,一个user_handler用来显示发给用户的消息,一个tool_call_handler,用来执行函数调用。另外,我们还为ResponseJob添加一个callback,让它在结束时发起下一轮对话,最后用一个commander来执行它。
这个agent的流程图如下所示:下面是它的运行过程的演示动画:
如果读到这里,相信你对agere已经有了初步的了解,如果你感兴趣,欢迎查看这里:
Github:https://github.com/happyapplehorse/agere
文档页:https://happyapplehorse.github.io/agere/
如果觉得还不错,欢迎您参与其中,或者给出您宝贵的意见与建议。