智能体开发框架选型指南 Agent

作者 | Aparna Dhinakaran

编译 |岳扬

Image by author

智能体(Agents)正迎来辉煌时辰。随同着泛滥新框架的涌现和对该畛域的继续投资[1],现代 AI 智能体正在超过后来的不稳固阶段[2],迅速取代 RAG 成为开发首选。那么,2024 年能否会成为 autonomous AI 系统片面接收撰写邮件、预订航班、数据剖析等义务的一年呢?

兴许吧,但要成功这一点还有很多上班要做。开发人员在构建智能体时,不只有选择经常使用何种模型、运行场景和技术架构,还要筛选适宜的开发框架。是坚持较为早期的 LangGraph,还是转向新兴的 LlamaIndex Workflows?或许走传统路途,自己编写所有代码呢?

这篇文章的目的就是让您更轻松地做出选用。在过去几周里,我经常使用多个干流框架构建了相反的智能体,并从技术角度剖析了它们各自的优缺陷。每个智能体的一切代码都可以在此代码仓库[3]中找到。

本文测试用智能体的基本概述

本次测试所驳回的智能体整合了多项性能,包括执行函数调用(function calling)、经常使用多种工具或技艺、与外部资源建设衔接,以及成功形态或记忆的共享。

该智能体具有以下几项外围才干:

为了达成上述指标,智能体须要掌握三项基本技艺:联合产品文档的 RAG、在关系数据库上生成 SQL 语句的才干,以及数据剖析技巧。智能体的用户界面经常使用 gradio 搭建,而智能体自身则以聊天机器人(chatbot)的方式构建。

01 Code-Based Agent(不经常使用智能体框架)

在着手开发智能体时,您可以选用不依赖任何框架,而是齐全自主构建。在启动这个名目之初,我首先驳回了这种方法。

Image by author

1.1 纯代码架构

上方是基于纯代码构建的智能体, 其外围是一个由 OpenAI 提供允许的技艺路由器 ,它经过函数调用来确定经常使用哪项技艺。技艺执行终了后,控制权将前往给技艺路由器,以便调用其余技艺或间接向用户作出回应。

智能体会继续记载用户信息和智能体照应,并在每次调用时将这一完整列表传递给技艺路由器,确保在整个交互环节中保管高低文。

各项技艺均在独立的类中启动定义(例如“GenerateSQLQuery”类),这些类都保管在 SkillMap 中。技艺路由器仅与 SkillMap 启动交互,经过它来加载技艺的称号、形容以及可调用的函数。这种设计理念使得向智能体中参与新技艺变得十分便捷:只有将该技艺编写为一个独立的类,并将其参与到 SkillMap 的技艺列表即可。这样做的目的是为了在不影响技艺路由器代码的前提下,轻松成功新技艺的参与。

总的来说,这种成功方式虽然便捷易行,但依然存在一些须要克制的难题。

1.2 经常使用纯代码智能面子临的应战

第一个艰巨在于如何设计技艺路由器的系统揭示词(system prompt)。 在上方的例子中,技艺路由器往往偏差于自行生成 SQL 语句,而不是交给相应的技艺模块去处置。假设你有过试图让大言语模型中止执行某项义务的阅历,那你或许深知这其中的挫败感;为了找到适宜的揭示词,我不得不启动了屡次调试。此外, 处置每个步骤发生的不同输入格局也是一项复杂的上班。 由于我选用不经常使用结构化输入,因此必定为技艺路由器和各项技艺中大言语模型的调用预备多种格局的应答战略。

1.3 纯代码智能体的好处

基于代码的方法提供了一个扎实的基础和登程点,是一种绝佳的学习路径,让咱们可以在不依赖现成框架提供的智能体教程的状况下,了解智能体的运作原理。虽然疏导大言语模型按既定行为形式运作确实存在难度,但代码结构自身繁复明了,易于操作,关于某些经常使用场景而言,这种做法是齐全正当的(详细剖析将在下文倒退)。

02 LangGraph

LangGraph 是泛滥智能体框架中历史最为悠久的之一,它于 2024 年 1 月初次颁布。 该框架的设计初衷是为了处置现有流程和链条的非循环性疑问,它经过驳回 Pregel 图结构来处置这一疑问。 LangGraph 经过引入节点(nodes)、边(edges)以及条件边(conditional edges)的概念,简化了在智能体中创立循环流程的环节,使得图的遍历变得愈加直观。 LangGraph 是基于 LangChain 构建的,它承袭了后者的对象(objects)和类型(types)。

Image by author

2.1 LangGraph 架构

从外表上看,LangGraph 智能体与基于代码的智能体有相似之处,但它们的底层代码却有大不相反。虽然 LangGraph 在技术上也经常使用了“路由器(router)”这一律念,即经过代码函数调用 OpenAI 并应用其照应来推动到下一个步骤,但程序在不同技艺之间的切换控制机制却齐全不同。

在此定义的图(graph)中,蕴含了一个用于初始化 OpenAI 调用的节点,即上文中提到的“agent”,以及一个用于工具处置步骤节点,即“tools”。LangGraph 内置了一个名为 ToolNode 的对象,它能够接纳一系列可调用的工具,并依据 ChatMessage 的照应来触发这些工具,成功操作后再次回到“agent”节点。

每当“agent”节点(也可以了解为基于代码的智能体中的技艺路由器(router))被调用之后,should_continue 这条边将判别是将照应间接前往给用户,还是转给 ToolNode 来处置工具调用。

在每个节点中,“state” 担任保管与 OpenAI 的交互信息和照应列表,这一点与基于代码的智能体坚持高低文的方式相似。

2.2 经常使用 LangGraph 面临的应战

在处置 LangGraph 构建的智能体示例时,遇到的重要难题在于必定借助 Langchain 对象才干确保流程的顺畅。

应战 1:函数调用的 validation 失误

为了能够经常使用 ToolNode 对象,我不得不对 Skill 代码启动大规模的重构。ToolNode 须要一组可调用的函数列表,我本以为可以间接经常使用现成的函数,然而函数参数性能出了疑问,造成流程碰壁。

这些技艺(skills)是以类方式定义的,每个类都有一个可调用的成员函数,其中“self”是首个参数。GPT-4o 足够智能,能够在生成函数调用(function call)时智能扫除“self”参数,但 LangGraph 却因此以为缺少了必要参数,从而抛出了 validation 失误。

这个疑问让我探索了好几小时才搞分明,由于失误信息把函数里的第三个参数(数据剖析技艺中的“args”)失误地标志为缺失参数(missing parameter):

须要指出的是, 这个误导性的失误信息其实来自 Pydantic,而非 LangGraph。

最后,我下定信心,改用 Langchain 的 @tool 装璜器将我的技艺(skills)从新编写为基本方法,这样程序就能反常运转了。

应战 2:Debugging

正如前文所述,在框架中调试十分艰巨。重要是由于失误信息凌乱不清,以及框架中的形象概念,它们使得追踪和检查蜕变变得十分复杂。

形象概念重要体如今尝试跟踪智能体间传递的信息时。LangGraph 会将信息保管在 state[“messages”] 里。Graph 中的一些节点会智能从这些信息(messages)中提取信息,这样的智能化环节或许会让节点在访问信息(messages)时,咱们难以掌握信息(messages)的详细内容。

智能体执行的顺序视图(图片由作者提供)

2.3 LangGraph 的好处

LangGraph 的最大好处在于其易用性。它的图结构代码繁复且易于了解。关于那些领有复杂节点逻辑的场景,LangGraph 能够提供一个明晰的图视图,让咱们更轻松地掌握智能体的衔接方式。此外,LangGraph 还可以间接转换以 LangChain 构建的现有运行程序。

2.4 阅历之谈

当咱们只经常使用 LangGraph 框架的关系性能时,一切都会运转得十分流利;但一旦咱们尝试跳出框架,就要预备好启动一些令人头疼的调试了。

03 LlamaIndex Workflows

Workflows 是智能体框架畛域的新晋成员,它于往年夏初初次亮相。 与 LangGraph 相似,它的设计宗旨是简化可循环智能体的构建环节。此外,Workflows 特意强调其异步执行的才干。

在 Workflows 中,某些设计元素仿佛是为了间接对标 LangGraph,尤其是它驳回事情(events)而非边(edges)或条件边(conditional edges)作为衔接逻辑的方式。在 Workflows 中,智能体逻辑被封装在“步骤(steps)”中(与 LangGraph 中的“节点(nodes)”相对应),而事情(events)的收回和接纳则担任在不同的步骤(steps)间传递信息。

Image by author

上述框架与 LangGraph 的结构颇为相似,但有一点不同:我给 Workflow 参与了一个初始化步骤,用于预备智能体的环境高低文,稍后我会详细引见这一点。虽然两者的结构相似,但它们所依赖的代码成功却一模一样。

3.1 Workflows 架构

以下代码段描画了 Workflow 的架构。与 LangGraph 相仿,在这一局部,我性能了形态信息(state),并将各项技艺(skills)绑定到了 LLM 对象上。

在这里,我还定义了一个额外的步骤——“prepare_agent”。该步骤担任将用户输入转换成 ChatMessage,并将其存储到上班流的记忆存储中。将这一环节作为一个独立的步骤分别进去,象征着智能体在遍历上班步骤(steps)时可以重复回到这一步,从而防止重复将用户信息参与到记忆存储中。

在 LangGraph 的成功案例中,我经过一个位于图(graph)之外的 run_agent 方法成功了相反的性能。这一扭转重要是出于格调上的思考,但我以为,将这一逻辑整合到 Workflow 和图(graph)中,会愈加整洁和高效。

在 Workflow 性能成功后,我继续编写了路由代码:

以及工具调用途理代码:

它们的成功方式仿佛更凑近于纯代码的智能体,而非 LangGraph 智能体。这重要是由于 Workflows 选用在各步骤(steps)中保养条件路由(conditional routing)逻辑,而不是像 LangGraph 那样经常使用条件边(conditional edge)(第 18-24 行在 LangGraph 中是条件边,而如今它们只是路由步骤的一局部)。另外,LangGraph 中的 ToolNode 对象能够在 tool_call_handler 方法中智能处置大局部义务。

在路由步骤之后,咱们能够将 SkillMap 以及基于纯代码的智能体中已有的技艺(skills)间接运行于 Workflows。这些技艺(skills)无需任何修正即可与 Workflows 配合经常使用,这大大简化了我的上班。

3.2 经常使用 Workflows 面临的应战

应战 1:Sync vs Async

虽然关于在线运转的智能体来说,异步执行是更优的选用,但调试同步执行的智能体通常更为简便。 Workflows 自身是为了异步操作而设计的,因此尝试将其改为同步执行十分艰巨。

后来,我以为只有去掉“async”方法标识,并将函数名“achat_with_tools”改为“chat_with_tools”即可。然而,由于 Workflow 类外部的方法雷同驳回了异步标志,为了成功同步运转,我不得不从新定义这些方法。虽然如此,我最终还是选用了异步处置方式,幸运的是,这并没有参与调试的难度。

智能体执行的顺序视图(图片由作者提供)

应战 2:Pydantic Validation Errors

与 LangGraph 的疑问相似,在智能体的技艺(skills)处也发生了令人困惑的 Pydantic Validation Errors。幸运的是,由于 Workflows 能够很好地处置成员函数,这些疑问这次比拟容易处置。最终,我不得不愈加规范地为智能体技艺(skills)创立 LlamaIndex FunctionTool 对象:

从构建 FunctionTools 的 AgentFlow.文件中摘录

3.3 Workflows 的好处

与 LangGraph 相比,我在经常使用 Workflows 构建智能体时要轻松得多,重要要素是 Workflows 并未提供内置性能,而是须要我自己编写路由逻辑和工具操作代码。 这也使得我的 Workflow 智能体与基于纯代码的智能体看起来极为相似。

最大的区别在于事情(events)的经常使用上。我经常使用两个自定义事情在智能体中的各个步骤之间移动:

这种基于事情的发射器-接纳器架构(emitter-receiver),取代了间接调用智能体中某些方法的做法,例如工具调用途理(tool call handler)。

关于那些步骤(steps)更为复杂、异步触发且或许发生多个事情(events)的系统来说,这种架构就十分有助于洁净拖拉地治理这些步骤。

Workflows 的其余好处还包括其轻量级个性,不会施加过多的结构限度(除了必定经常使用特定的 LlamaIndex 对象外),并且其基于事情(event-based)的架构为间接函数调用提供了一种有效的代替打算,这关于处置复杂、异步的运行场景尤为有益。

04 对这些方法启动比拟

对比这三种方法,各有其独到之处。

无框架方法实施起来最便捷。由于所无形象层都是由开发者自行定义(如前例中的 SkillMap 对象),因此治理不同类型(types)和对象(objects)相对便捷。然而,代码的可读性和易用性齐全取决于开发者团体,可以预感,假设没有必定的智能体结构解放,智能体的复杂性参与后或许会变得难以驾驭。

LangGraph 提供了丰盛的智能体结构允许,使得智能体的定义十明显晰。关于多人单干开发的智能体来说,这种智能体结构设定有助于一致架构规范。LangGraph 也为那些对智能体结构不太相熟的开发者提供了协助。不过,这样做也有代价 —— 由于 LangGraph 为你做了许多上班,假设你不齐全认同这个框架,它或许会让你头疼不已;代码或许会十分繁复,但你或许要为此启动更多的调试上班。

Workflows 则处于两者之间。基于事情(event-based)的架构在某些名目中或许极具价值,而且由于它对 LlamaIndex 类型的经常使用要求不高,关于那些没有在运行程序中齐全经常使用该框架的开发者来说,提供了更大的自在度。

Image created by author

归根结底,关键疑问或许在于“你能否曾经在经常使用 LlamaIndex 或 LangChain 来组织运行程序?” LangGraph 和 Workflows 都与它们所依赖的框架严密集成,因此每个特定智能体框架的额外好处或许无余以成为转换经常使用的理由。

纯代码方法或许永远是一个有吸引力的选用。假设你能够严厉地记载并执行所创立的任何形象概念,那么确保外部框架不会成为你的阻碍就很容易了。

05 在选用智能体框架时须要思考的关键疑问

当然,单纯一句“详细状况详细剖析”这样的回答总是让人不太满意。以下三个疑问或许能帮你选用下一个智能体名目应该驳回哪个框架。

你的名目能否曾经深度集成了 LlamaIndex 或 LangChain?

假设是的话,无妨优先思考这两个选项。

你对智能体的经常出现架构能否相熟,还是更宿愿有人通知你应该如何构建智能体结构?

假设你偏差于后者,那么 Workflows 或许是个不错的选用。假设你十分偏差于后者,那么 LangGraph 或许更适宜你。

你要构建的智能体能否有参考样例?

框架的一个好处在于,每个框架都有少量的教程和实例供你参考。而纯代码构建智能体的参考实例相对较少。

Image created by author

06 Conclusion

选用一个智能体框架只是影响生成式人工智能系统在消费环境中体现泛滥决策中的一项,建设弱小的安保保证和对大言语模型(LLM)的监控[4]是必要的 —— 同时,面对新智能体框架、钻研成绩和模型对传统技术的推翻,咱们还需坚持灵敏应答的态度。

Thanks for reading!

Hope you have enjoyed and learned new things from this blog!

About the authors

Aparna Dhinakaran

Co-Founder and CPO of Arize AI. Formerly Computer Vision PhD at Cornell, Uber Machine Learning, UC Berkeley AI Research.

本期互动内容

您可能还会对下面的文章感兴趣: