来源:互联网 更新时间:2026-07-19 13:43
智能体正迎来辉煌时刻。伴随着众多新框架的涌现和对该领域的持续投资[1],现代 AI 智能体正在跨越起初的不稳定阶段[2],迅速取代 RAG 成为开发首选。那么,2024 年是否会成为 autonomous AI 系统全面接管撰写邮件、预订航班、数据分析等任务的一年?
也许吧,但要实现这一点还有很多工作要做。开发人员在构建智能体时,不仅要决定使用何种模型、应用场景和技术架构,还要挑选合适的开发框架。是坚持较为早期的 LangGraph,还是转向新兴的 LlamaIndex Workflows?或者走传统路线,自己编写全部代码?
这篇文章的目的就是让您更轻松地做出选择。在过去几周里,我用多个主流框架构建了相同的智能体,并从技术角度分析了它们各自的优缺点。每个智能体的所有代码都可以在此代码仓库[3]中找到。
本次测试所采用的智能体整合了多项功能,包括执行函数调用(function calling)、使用多种工具或技能、与外部资源建立连接,以及实现状态或记忆的共享。
该智能体具备以下几项核心能力:
基于知识库进行问题解答
数据交互:针对 LLM 应用程序的数据进行问题解答
数据洞察:对获取的数据进行更高层次的趋势和模式分析
为了达成上述目标,智能体需要掌握三项基本技能:结合产品文档的 RAG、在相关数据库上生成 SQL 语句的能力,以及数据分析技巧。智能体的用户界面使用 gradio 搭建,而智能体本身则以聊天机器人(chatbot)的形式构建。
在着手开发智能体时,可以选择不依赖任何框架,而是完全自主构建。在启动这个项目之初,我首先采用了这种方法。

下面是基于纯代码构建的智能体,
智能体会持续记录用户消息和智能体响应,并在每次调用时将这一完整列表传递给技能路由器,确保在整个交互过程中保留上下文。
各项技能均在独立的类中进行定义(例如“GenerateSQLQuery”类),这些类都保存在 SkillMap 中。技能路由器仅与 SkillMap 进行交互,通过它来加载技能的名称、描述以及可调用的函数。这种设计理念使得向智能体中添加新技能变得非常简单:只需将该技能编写为一个独立的类,并将其加入到 SkillMap 的技能列表即可。这样做的目的是为了在不影响技能路由器代码的前提下,轻松实现新技能的添加。
总的来说,这种实现方式虽然简单易行,但仍然存在一些需要克服的难题。
基于代码的方法提供了一个扎实的基础和出发点,是一种绝佳的学习途径,让我们可以在不依赖现成框架提供的智能体教程的情况下,了解智能体的运作原理。虽然引导大语言模型按既定行为模式运作确实存在难度,但代码结构本身简洁明了,易于操作,对于某些使用场景而言,这种做法是完全合理的(具体分析将在下文展开)。
LangGraph 是众多智能体框架中历史最为悠久的之一,它于 2024 年 1 月首次发布。

从表面上看,LangGraph 智能体与基于代码的智能体有相似之处,但它们的底层代码却大不相同。虽然 LangGraph 在技术上也使用了“路由器(router)”这一概念,即通过代码函数调用 OpenAI 并利用其响应来推进到下一个步骤,但程序在不同技能之间的切换控制机制却完全不同。
在此定义的图(graph)中,包含了一个用于初始化 OpenAI 调用的节点,即上文中提到的“agent”,以及一个用于工具处理步骤节点,即“tools”。LangGraph 内置了一个名为 ToolNode 的对象,它能够接收一系列可调用的工具,并根据 ChatMessage 的响应来触发这些工具,完成操作后再次回到“agent”节点。
每当“agent”节点(也可以理解为基于代码的智能体中的技能路由器(router))被调用之后,should_continue 这条边将判断是将响应直接返回给用户,还是转给 ToolNode 来处理工具调用。
在每个节点中,“state” 负责保存与 OpenAI 的交互消息和响应列表,这一点与基于代码的智能体保持上下文的方式相似。
在处理 LangGraph 构建的智能体示例时,遇到的主要难题在于必须借助 Langchain 对象才能确保流程的顺畅。
为了能够使用 ToolNode 对象,我不得不对 Skill 代码进行大规模的重构。ToolNode 需要一组可调用的函数列表,我本以为可以直接使用现成的函数,但是函数参数配置出了问题,导致流程受阻。
这些技能(skills)是以类形式定义的,每个类都有一个可调用的成员函数,其中“self”是首个参数。GPT-4o 足够智能,能够在生成函数调用(function call)时自动排除“self”参数,但 LangGraph 却因此认为缺少了必要参数,从而抛出了 validation 错误。
这个问题让我摸索了好几小时才搞清楚,因为错误信息把函数里的第三个参数(数据分析技能中的“args”)错误地标记为缺失参数(missing parameter):
需要指出的是,
最后,我下定决心,改用 Langchain 的 @tool 装饰器将我的技能(skills)重新编写为基本方法,这样程序就能正常运行了。
抽象概念主要体现在尝试跟踪智能体间传递的消息时。LangGraph 会将消息保存在 state[“messages”] 里。Graph 中的一些节点会自动从这些消息(messages)中提取信息,这样的自动化过程可能会让节点在访问消息(messages)时,我们难以把握消息(messages)的具体内容。
智能体行动的顺序视图(图片由作者提供)
LangGraph 的最大优势在于其易用性。它的图结构代码简洁且易于理解。对于那些拥有复杂节点逻辑的场景,LangGraph 能够提供一个清晰的图视图,让我们更轻松地把握智能体的连接方式。此外,LangGraph 还可以直接转换以 LangChain 构建的现有应用程序。
当我们只使用 LangGraph 框架的相关功能时,一切都会运行得非常流畅;但一旦我们尝试跳出框架,就要准备好进行一些令人头疼的调试了。
Workflows 是智能体框架领域的新晋成员,它于今年夏初首次亮相。
在 Workflows 中,某些设计元素似乎是为了直接对标 LangGraph,尤其是它采用事件(events)而非边(edges)或条件边(conditional edges)作为连接逻辑的方式。在 Workflows 中,智能体逻辑被封装在“步骤(steps)”中(与 LangGraph 中的“节点(nodes)”相对应),而事件(events)的发出和接收则负责在不同的步骤(steps)间传递信息。

上述框架与 LangGraph 的结构颇为相似,但有一点不同:我给 Workflow 增加了一个初始化步骤,用于准备智能体的环境上下文,稍后我会详细介绍这一点。尽管两者的结构相似,但它们所依赖的代码实现却截然不同。
以下代码段描绘了 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 配合使用,这大大简化了我的工作。
尽管对于在线运行的智能体来说,异步执行是更优的选择,但调试同步执行的智能体通常更为简便。
起初,我以为只需去掉“async”方法标识,并将函数名“achat_with_tools”改为“chat_with_tools”即可。但是,由于 Workflow 类内部的方法同样采用了异步标记,为了实现同步运行,我不得不重新定义这些方法。尽管如此,我最终还是选择了异步处理方式,幸运的是,这并没有增加调试的难度。
智能体行动的顺序视图(图片由作者提供)
与 LangGraph 的问题类似,在智能体的技能(skills)处也出现了令人困惑的 Pydantic Validation Errors。幸运的是,由于 Workflows 能够很好地处理成员函数,这些问题这次比较容易解决。最终,我不得不更加规范地为智能体技能(skills)创建 LlamaIndex FunctionTool 对象:
从构建 FunctionTools 的 AgentFlow.__init__ 文件中摘录
最大的区别在于事件(events)的使用上。我使用两个自定义事件在智能体中的各个步骤之间移动:
这种基于事件的发射器-接收器架构(emitter-receiver),取代了直接调用智能体中某些方法的做法,例如工具调用处理(tool call handler)。
对于那些步骤(steps)更为复杂、异步触发且可能产生多个事件(events)的系统来说,这种架构就非常有助于干净利落地管理这些步骤。
Workflows 的其他优点还包括其轻量级特性,不会施加过多的结构限制(除了必须使用特定的 LlamaIndex 对象外),并且其基于事件(event-based)的架构为直接函数调用提供了一种有效的替代方案,这对于处理复杂、异步的应用场景尤为有益。
无框架方法实施起来最简单。由于所有抽象层都是由开发者自行定义(如前例中的 SkillMap 对象),因此管理不同类型(types)和对象(objects)相对简单。但是,代码的可读性和易用性完全取决于开发者个人,可以预见,如果没有一定的智能体结构约束,智能体的复杂性增加后可能会变得难以驾驭。
LangGraph 提供了丰富的智能体结构支持,使得智能体的定义非常清晰。对于多人协作开发的智能体来说,这种智能体结构设定有助于统一架构规范。LangGraph 也为那些对智能体结构不太熟悉的开发者提供了帮助。不过,这样做也有代价 —— 由于 LangGraph 为你做了许多工作,如果你不完全认同这个框架,它可能会让你头疼不已;代码可能会非常简洁,但你可能要为此进行更多的调试工作。
Workflows 则处于两者之间。基于事件(event-based)的架构在某些项目中可能极具价值,而且因为它对 LlamaIndex 类型的使用要求不高,对于那些没有在应用程序中完全使用该框架的开发者来说,提供了更大的自由度。

归根结底,关键问题可能在于“你是否已经在使用 LlamaIndex 或 LangChain 来组织应用程序?” LangGraph 和 Workflows 都与它们所依赖的框架紧密集成,因此每个特定智能体框架的额外优势可能不足以成为转换使用的理由。
纯代码方法可能永远是一个有吸引力的选择。如果你能够严格地记录并执行所创建的任何抽象概念,那么确保外部框架不会成为你的阻碍就很容易了。
当然,单纯一句“具体情况具体分析”这样的回答总是让人不太满意。以下三个问题或许能帮你选择下一个智能体项目应该采用哪个框架。
如果是的话,不妨优先考虑这两个选项。
如果你倾向于后者,那么 Workflows 可能是个不错的选择。如果你非常倾向于后者,那么 LangGraph 或许更适合你。
框架的一个优势在于,每个框架都有大量的教程和实例供你参考。而纯代码构建智能体的参考实例相对较少。

选择一个智能体框架只是影响生成式人工智能系统在生产环境中表现众多决策中的一项,建立强大的安全保障和对大语言模型(LLM)的监控[4]是必要的 —— 同时,面对新智能体框架、研究成果和模型对传统技术的碘伏,我们还需保持灵活应对的态度。
七麦数据官网网页地址 七麦数据官方入口在线首页
问卷星官方网站入口地址 问卷星网页版在线使用
币安Binance官方中文网站 币安App最新版下载及新手注册指南
闲鱼的严选验货在哪里看?闲鱼严选和验货宝哪个可靠
淘宝直播如何看回放在哪里看?怎么查看淘宝直播回放
PokePay加密卡2026完整指南:申请开卡全攻略+多场景应用技巧
新浪人工智能热点小时报丨2026年06月20日02时_今日实时人工智能热点速递
摩托车活塞环性能如何
为何比特币BTC价格跌破7.3万美元?一文拆解影响近期比特币行情的五大原因
ThinkBook系列最新价格全解析:2026年选购避坑与实时询价指南
迷你网名古风男生霸气(精选100个)
GPT5.6惨遭切脑,Fable 5回归要变弱鸡版?
《梦幻西游》特殊鬼怪怎么抓-隐藏变异鬼应对要点
文雅简易网名男生可爱(精选100个)
动漫《恶之华》剧情介绍
王者荣耀「西行封妖记」【孙权-仙扇使者】6月25日上线!
豆包AI专业版使用教程【新手必看】
闲鱼严选和验货宝哪个可靠?闲鱼的验货宝怎么样,,
币圈十大实用工具:从实时行情监控到数据分析、资产管理
币安杀入美股市场,重头戏bStocks还没来
手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc