写点什么

【一文读懂 LangGraph、AutoGen、Swarm】大模型时代 AI 智能体框架核心技术原理

作者:小奇同学
  • 2024-10-18
    北京
  • 本文字数:6307 字

    阅读完需:约 21 分钟

【一文读懂LangGraph、AutoGen、Swarm】大模型时代AI智能体框架核心技术原理

一、前言


随着大模型时代的到来,各企业都在不同的细分赛道拥抱 AI,总体上可概括为 4 个技术领域,分别为基础大模型、领域大模型、智能体平台与应用、AI 应用与集成。我们团队所面临的都是实际的生产场景,直接关系到用户的感知,所以一直关注智能体领域,同时认为智能体是大模型能真正落地的最后一公里,所以我们对智能体、多智能体研发框架进行了深入研究,本文中重点介绍 LangGraph、AutoGen、Swarm 三个框架的核心原理与案例。

二、ReAct、Function Call 与智能体


1、ReAct 与智能体


通过对不同多智能体框架的研究我们发现大多数框架都是基于类 ReAct(Reason+Act)的技术思想来实现,各框架基本上也都是围绕如何便捷化、自动化的增强 ReAct 来展开框架底层研发,所以在介绍多智能体框架之前我们来分析下大模型时代下 ReAct 模型的技术原理,这也为我们更好的理解 LangGraph、AutoGen、Swarm 打下一个基础。



上图为 ReAct 结合大模型的核心流程图,LLM 为大语言模型,同时也作为整个 ReAct 的核心实现,Tools 为工具,提供需要执行的函数或接口,ReAct 可以简单的理解为“思考-动作-观察”的一整套流程,下面以一个例子为切入点为让大家更好的理解智能体的底层逻辑。


以“美国总统生日是哪天”这个问题为例,LLM 会对整个任务进行分解,确定我们需要知道“美国总统是谁”,然后再“确定他的生日”,所以 LLM 经过“思考”决定先调用“查询美国总统是谁“的工具,经过该”动作”的执行得到了美国总统是拜登,然后 LLM 通过“观察”发现我们还有未完成的任务,还需要调用”查询拜登生日是哪天“的工具,经过该“动作”的执行得到拜登生日是 11 月 20 日,最后 LLM 通过对这两个工具的调用做最终判断,返回“美国总统拜登的生日是 11 月 20 日”。


其实从这个例子我们会很清晰的了解”大模型+ReAct“的整个技术原理,LLM 作为 ReAct 的大脑负责工具的选择、流程的调度,而整个流程的串联正是多智能体研发框架要解决的重要问题,如工具的自动调用、工具参数的构造等。


2、Function Call 与智能体


2023 年 GPT3.5 和 GPT4 在模型层支持了 Function Call,又一次引领了大模型行业对于应用落地的进一步支撑,其核心理念是 Function Call 将上述框架层需要做的工具选取、工具参数构建等工作的具体实现下移到模型层,不再需要框架层结合 Prompt 解决这些问题,这对于大模型应用研发人员又进一步精简了逻辑,随着"大模型+Function Call"方式的出现,国内通义千问、ChatGLM2 等模型也都进行了接口层适配,而智能体研发框架也逐渐增加 Function Call 特性,那下面就为大家分别介绍 LangGraph、AutoGen、Swarm 三个多智能体框架的核心原理。

三、LangGraph 多智能体框架


众所周知,LangChain 是业界最流行、使用最广泛的 AI 开发框架,在 LangChain 中其实很早就有智能体 Agent 应用的研发框架,其核心原理也是本文第二部分的内容,但随着智能体的发展,大家对多个智能体之间的调度与灵活性提出了更高的要求,所以 LangGraph 因运而生。


1、LangGraph 重要概念


LangGraph 核心是构造一个图,通过图的方式实现对 Agent、Tool 等元素的编排,使智能体能够处理更多复杂的场景,LangGraph 中有三个核心概念分别是节点(Node)、边(Edge)、有条件边(Conditional Edge),通过这些元素 LangGraph 可以为我们构造一个流程,也就是一个智能体。


  • Node:节点,可以是 Agent、可以是 Tool,Agent 其实就是利用 LLM 实现的 ReAct 和 Function Call,Tool 就是实现一些业务逻辑的函数;

  • Edge:边,Node 之间的关联,用于协助完成整个工作流的执行;

  • Conditional Edge:条件边,可以通过设置 True 和 False 来实现工作流对于分支的支持。


2、LangGraph 流程示例



以上图为例,我们构造了一个智能体执行引擎,用于模拟智能体平台的调度引擎,其中 Node 有一个 Agent 调度引擎,一个判断是否还有任务需要执行的 exist,一个具体工具调用的 action;涉及的 Edge 有 Agent 与 exist 的边,action 与 LLM 的边,涉及的 Conditional Edge 有 exist 到 aciton 和 end 的边。


对照之前的案例,整个流程中有两个工具,一个是“查询美国总统是谁”,一个是“查询美国总统的生日是哪天”,具体的调用在 acion 方法中,exist 方法用于判断该问题是否已经处理完成,Agent 则根据问题进行任务拆解、工具选择,LangGraph 框架用于实现方法的调用与整个流程执行的全流程,这种图的方式能够更灵活、直观的执行同一个任务。


同时 LangGraph 具备一些特点与优势,具体如下:

  • 用户可以通过真实反馈参与到整个智能体的执行中,确保智能体正确的执行;

  • 可以支持上下文的关联与用户的隔离,通过 Config 的方式可以实现不同用户的内存记忆;

  • 图的方式构造的流程式智能体,可以在任意一个环节进行回退与重执行,并更新整个图的状态;


其实 LangGraph 还有很多特性,这里只是介绍了一些关键的特性,大家感兴趣可以到 LangGraph 的官网进行学习。


3、LangGraph 技术原理


在上述的流程中,我们分析一下具体的技术原理,Agent 是通过 LLM 实现的 ReAct,具体就是实现一个 Prompt,在 Prompt 中将所有的工具的方法名、方法描述、方法参数等进行描述,让 LLM 对整个问题任务进行分解,并能推荐出合适的工具进行任务处理(如模型支持 Function Call 则可以忽略 Prompt 的构建)。


然后通过 LangGraph 构造的图触发整个流程的执行,LangGraph 在拿到 Agent 推荐的工具时,会按照设置的 Edge 执行 exist,exist 判断 Agent 还有任务要执行,所以执行 action 函数,action 函数执行的入参由 Agent 负责提供,调用由 LangGraph 框架执行,在 action 函数中会具体的执行查询操作,然后再通过 edge 回到 Agent,直到推导出最后的结果。


其实我们会发现 Agent 和 LangChain 中的 Agent 甚至于说 ReAct 都没有特别实质的理念区别,核心就在于 LangGraph 框架搭建了这么一个流程式智能体研发框架,让智能体变得更灵活。


4、LangGraph 示例代码


该案例应用的是 LangGraph 开源社区 Commiter 发布的一个在线课程中的案例,我这里进行了详细注释,便于大家进行理解。


class Agent:
def __init__(self, model, tools, system=""): self.system = system #创建一个LangGraph的流程,记录执行的所有步骤与状态 graph = StateGraph(AgentState) #创建一个LLM Node,用于问答,使用的模型是OpenAI graph.add_node("llm", self.call_openai) #创建一个Action Node,用于对选工具进行具体的执行 graph.add_node("action", self.take_action) #构造一个边,llm到exists Node,如果函数返回T则调用Action Node,F则终止流程 graph.add_conditional_edges( "llm", self.exists_action, {True: "action", False: END} ) #构造一个边,aciton到LLM graph.add_edge("action", "llm") #入口为Node LLM graph.set_entry_point("llm") #生成智能体执行引擎 self.graph = graph.compile() #指定工具集 self.tools = {t.name: t for t in tools} #将工具集与LLM绑定,用于构造Agent self.model = model.bind_tools(tools) logger.info(f"model: {self.model}") #exist Node具体逻辑,通过查看整个状态情况做出流程判断 def exists_action(self, state: AgentState): result = state['messages'][-1] logger.info(f"exists_action result: {result}") return len(result.tool_calls) > 0 #Agent Node具体逻辑 def call_openai(self, state: AgentState): logger.info(f"state: {state}") messages = state['messages'] if self.system: messages = [SystemMessage(content=self.system)] + messages message = self.model.invoke(messages) logger.info(f"LLM message: {message}") return {'messages': [message]} #具体的工具的执行 def take_action(self, state: AgentState): import threading print(f"take_action called in thread: {threading.current_thread().name}") tool_calls = state['messages'][-1].tool_calls results = [] print(f"take_action called with tool_calls: {tool_calls}") for t in tool_calls: logger.info(f"Calling: {t}") print(f"Calling: {t}") if not t['name'] in self.tools: # check for bad tool name from LLM print("\n ....bad tool name....") result = "bad tool name, retry" # instruct LLM to retry if bad else: result = self.tools[t['name']].invoke(t['args']) logger.info(f"action {t['name']}, result: {result}") print(f"action {t['name']}, result: {result}") results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result))) print("Back to the model!") return {'messages': results}
复制代码

四、AutoGen 多智能体框架


AutoGen 是微软开源的一款专为处理复杂工作流设计的多智能体交互框架。该框架利用多 agent 对话来支持基于大型语言模型(LLM)的复杂工作流程。通过提供可定制且具备对话能力的 agent,使得与 LLM 的交互变得更加灵活,这些 agent 可以基于 LLM、工具、人工输入或是它们之间的任意组合进行配置,简化 LLM 工作流程的编排、优化以及自动化过程。


1、AutoGen 示例流程


定义复杂的多 Agent 对话系统通常经过如下步骤:1、定义一组具有特定功能和角色的 Agent2、定义 Agent 之间的交互行为,即当一个 Agent 从另一个 Agent 接收消息时,应该如何响应。当用户输入请求时,接收请求的 Agent 规划任务处理步骤,并与其他的 Agent 通信交互,并通过 Agent 间的响应信息匹配需要处理当前任务不同步骤的若干 Agent,从而实现工作流自动化编排。


2、AutoGen 示例代码


先通过一段简单的示例了解一下交互流程:

    def testGroup(self):        user_proxy = UserProxyAgent(            name="user_proxy",            system_message="用户代理,用于向其他的角色请求处理问题",            is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),            human_input_mode="TERMINATE",            max_consecutive_auto_reply=10,            code_execution_config={"last_n_messages": 2,"work_dir": "groupchat","use_docker": False}        )        chatbot = AssistantAgent(            name="美元欧元转换",            system_message="用于计算美元欧元转换任务,在得到最终结果后,回复结果中拼接上TERMINATE",            # system_message="For currency exchange tasks, only use the functions you have been provided with. Reply TERMINATE when the task is done.",            llm_config=llm_config,        )        hellobot = AssistantAgent(            name="打招呼",            system_message="用于向某个人say hello打招呼,在得到最终结果后,回复结果中拼接上TERMINATE",            # system_message="For currency exchange tasks, only use the functions you have been provided with. Reply TERMINATE when the task is done.",            llm_config=llm_config,        )
groupchat = GroupChat(agents=[user_proxy, hellobot, chatbot], messages=[], max_round=20) manager = GroupChatManager( groupchat=groupchat, code_execution_config={"use_docker": False}, llm_config=llm_config, is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE") ) user_proxy.initiate_chat(manager, message="123.45美元( USD) 等于多少 欧元(EUR)?") user_proxy.initiate_chat(manager, message="向eshin打招呼")
复制代码

运行结果:


3、AutoGen 技术原理


通过源码分析,我们来看看大致的交互流程:


可以看到 GroupChatManager 将多个 agent 的描述信息及相关问题一同发往 LLM,LLM 通过分析匹配对应的 agent,返回对应的 agent 名和对应的角色给到 GroupChatManager,GroupChatManager 再 speak to 对应的 agent,然后由对应的 agent 完成任务处理。

五、Swarm 多智能体框架


Swarm 是 openai 近期开源的智能体应用开发框架,项目上线不久就获得了 12.9k star。项目提供了一种轻量化的多 agent 编排方法,借助 LLM 的能力实现多步骤任务链的执行。但目前该框架只是一个探索性、实验性的项目,暂时不能应用于生产,本文侧重于对其中思想进行分析与研究。


1、Swarm 技术原理


目前主流的智能体应用框架大多基于 ReAct 和 Function Call 的方式,Swarm 则是基于后者。Function Call 是 openai 在 2023 年发布的框架中提供的增强能力,通过加入 function call 相关训练数据进行微调,使得模型能够支持结构化的输入与输出。国内大模型对相关能力进行了对齐,目前 Qwen、ChatGLM、Kimi 等大模型均支持相关功能,通过 openai 模块可快速完成功能的实现。简单来说,Function Call 框架主要是通过给模型提供 JSON 格式的提供消息上下文、可选的函数列表、函数功能描述、函数参数等内容,让大模型选择需要调用的函数,输出返回的函数及参数列表。


Swarm 基于 Function Call 的思路,提出了一种以 handoffs 机制为核心的 agent 编排的方法,核心思想是通过 LLM 的决策能力,实现任务的路由与重定向,完成上下文、函数传参在 agent 间移交,保证任务的正确执行。 梳理项目核心代码,整理主要运行逻辑整理如下:



3、Swarm 示例代码


这里以官方例子为例说明一下 handoffs 机制。


from swarm import Swarm, Agent
client = Swarm()
english_agent = Agent( name="English Agent", instructions="You only speak English.",)
spanish_agent = Agent( name="Spanish Agent", instructions="You only speak Spanish.",)

def transfer_to_spanish_agent(): """Transfer spanish speaking users immediately.""" return spanish_agent

english_agent.functions.append(transfer_to_spanish_agent)
messages = [{"role": "user", "content": "Hola. ¿Como estás?"}]response = client.run(agent=english_agent, messages=messages)
print(response.messages[-1]["content"])
复制代码


例子中首先定义了两个 agent,一个用于处理英语,一个用于处理西班牙语,可以理解为针对两种不同语言的智能对话 agent。其中,english_agent 定义了一个函数,必要时可以将当前 agent 切换至 spanish_agent,至于是否需要切换是由大模型根据输入内容来决定的。例子中,执行初始指定的 agent 为 english_agent,因此当用户的输入为西班牙语时,大模型会根据对话内容及可选函数列表,调用 transfer_to_spanish_agent 函数,实现将对话任务移交给 spanish_agent,具体流转流程如下。

六、总结


本文对业界三种比较重要的智能体研发框架进行了介绍,其实这也是智能体平台、智能体构建所关注的核心技术,下面简单的对三个智能体框架进行对比,但随着我们在生产中的不断实践,我们发现如果想完全满足业务场景的 AI 化都需要对框架源码进行二次开发,但是框架的出现的确为我们提供了更广阔的思路。



通过本文希望能给智能体平台建设与应用相关小伙伴提供思想碰撞与参,如有不足也欢迎指正。

用户头像

小奇同学

关注

还未添加个人签名 2020-04-17 加入

还未添加个人简介

评论

发布
暂无评论
【一文读懂LangGraph、AutoGen、Swarm】大模型时代AI智能体框架核心技术原理_智能体_小奇同学_InfoQ写作社区