【必收藏】从Workflow到Agent:构建企业级多智能体系统(MAS)的完整指南

本文系统介绍了Agentic System的核心概念与常见执行模式,分析了单Agent面对复杂任务时的局限性,阐述了多智能体系统(MAS)作为解决方案的必然性。通过Java框架LangGraph4j的代码实例,详细展示了如何构建"团队协作式"的智能体应用,帮助开发者找到控制与自主的最佳平衡点,为Agent项目提供扎实起点。

一、背景

随着大模型技术的发展,“智能体(Agent)”成了新的热点。但对一线开发者来说,也带来了不少实际的困惑:我们用LangChain、Dify等工具搭建的应用,到底算是一个固定的“工作流”,还是一个能自主决策的“智能体”?在项目中,是该追求流程可控,还是该放手让AI自由发挥?当一个Agent的能力遇到瓶颈,处理不了复杂任务时,我们又该怎么办?

本文从开发者的角度出发,把这些问题一一讲清楚。文章会系统地梳理Agent的核心定义,探讨几种主流的实现模式,并解释为什么从单个Agent发展到多智能体协作(MAS)是解决复杂问题的必然趋势。最后,我们将介绍一个强大的Java多智能体框架——LangGraph4j,通过实际代码实现一个Supervisor(主管)模式的多智能体系统。希望对Agent开发初学者有所帮助。

二、什么是Agent?

2.1 核心困惑:Workflow还是Agent?

当我们投身于大模型应用的开发浪潮,无论是使用 LangChain、LangGraph 进行编码,还是在 Dify、Coze 等平台上进行可视化构建,大家心里可能都有个问题:我做的这个应用,到底算是一个“工作流”还是一个“智能体(Agent)”?我们应该让大模型天马行空地自主决策,还是把它牢牢地限制在预设的流程里?

首先,我们来定义一下什么是真正的“智能体”。一个合格的智能体,应该能像人一样感知和理解环境,并主动使用工具去完成目标。关键在于“主动”和“自主”。以此为标准,我们就能看清两种开发范式的区别:

  • 工作流:以 Dify、Coze 等低代码平台为例,其核心是预先编排好的任务路径。这种模式的可控性极高、结果稳定可预测,但牺牲了系统的自主性和灵活性。它更像一个高效的自动化执行器。
  • 智能体:赋予大模型充分的决策权,让其根据目标自主规划和行动。这种模式的自主性极强、能处理复杂的开放性问题,但其行为路径难以预测,带来了可控性与安全性的挑战。

**那么,在实际工作中,我们到底该怎么选?**我的观点是:这不是一个选择题,而是一个平衡题。

在商业应用落地时,我们追求的不是绝对的自主或绝对的可控,而是两者之间的最佳平衡点。这个平衡点完全取决于你的应用场景:

  • 如果你的任务是高频、标准化、且对结果准确性要求极高(如订单处理、客服问答),那么偏向工作流的设计会更稳妥。
  • 如果你的任务是开放性、探索性、且需要创意和策略(如市场分析报告、代码生成),那么赋予系统更多的自主性,让 Agent 发挥才智会更有价值。

2.2 业界定义与共识-Agentic System

  • OpenAI对于Agent的定义

Agent 是“能代表你独立完成任务的系统”

  • Anthropic对于Agent的定义

“Agent” can be defined in several ways. Some customers define agents as fully autonomous systems that operate independently over extended periods, using various tools to accomplish complex tasks. Others use the term to describe more prescriptive implementations that follow predefined workflows.

At Anthropic, we categorize all these variations as agentic systems, but draw an important architectural distinction between workflows and agents:

Workflows are systems where LLMs and tools are orchestrated through predefined code paths.Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks.

译文:

不同客户对 Agent 的认知存在差异。有些人将 Agent 视为完全自主的系统,能够长时间独立运行,灵活使用各种工具来完成复杂任务。 也有些人认为 Agent 是遵循预设规则、按照固定 Workflows 运作的系统。在 Anthropic,我们把所有这些变体都归类为 Agentic 系统,但在架构上,我们明确区分 Workflows 和 Agents:Workflows:依靠预先编写好的代码路径,协调 LLM 和工具完成任务;Agents:由 LLM 动态推理,自主决定任务流程与工具使用,拥有更大的决策自由度。

对比以上两种说法,Anthropic的定义更精确,更技术化**。**值得一提的是,根据LangChain创始人的博客、LlamaIndex官方文档, 还有吴恩达的专访。综合来看,业界对 Agent 的认知正朝着 Anthropic 所描述的更精细化的方向演进,并已形成以下关键共识:

Workflow和Autonomous Agent之间并不存在「非黑即白」的界限。这些系统之间,只是自主性的程度不同。大家普遍开始用**AgenticSystem**来取代原来宽泛的、意义模糊的Agent概念。

关于Agentic System一词,尤其以LangChain的创始人的说法最为清晰:

In practice, we see that most “agentic systems” are a combination of workflows and agents. This is why I actually hate talking about whether something is an agent, but prefer talking about how agentic a system is.

译文:

在实际中,我们发现大多数“agentic system”都是workflow和agent的组合。这也是为什么我其实不喜欢讨论某个东西是不是一个agent,而是更倾向于讨论一个系统有多么“agentic”。这句话精准地指出了行业视角的转变:我们关注的焦点不再是分类,而是程度。

三、Agentic-System 常见的任务执行模式

上文提到,我们不应再拘泥于“Workflow”与“Agent”的二元对立。与其争论一个系统“是不是 Agent”,不如关注它“有多 Agentic”。那么,在明确了业界对于Agentic System 的共识后,我们不禁要问:在实际的企业落地应用中,这些 Agentic 系统又有哪些常见的任务执行模式呢?下面,我们将结合 Anthropic 公司的研究,深入探讨几种典型的任务执行模式,希望能为您的Agent应用开发提供一些启发。

参考https://www.anthropic.com/engineering/building-effective-agents

3.1 工作流(workflow)

3.1.1 链式执行(静态workflow)

开发者预定义流程,然后按照顺序执行,输出作为下一步输入。其中的某些步骤可能需要用到LLM处理,比如生成一段总结。但是LLM并不影响下一步该如何执行,下一步已经是固化好的流程。如下,简单举例一个"写作智能体"。

  • 应用场景:标准化数据处理、内容生成流水线
  • 优点:可控性和可预测性强,部署和实现较为容易,任务方便调试,可以选择支持workflow的智能体框架比如:langchain、LangGraph、LlamaIndex,也可以选择使用低代码平台:Dify、Coze等搭建。
  • 缺点:缺乏自主性,固化流程局限性高,无法自动适配业务变化
3.1.2 局部智能+工作流(Agent+Workflow )

和静态工作流的区别在于,整体流程固定,把特定领域的任务处理抽象为流程中的一个结点,在这部分任务执行过程中给予智能体一定的自主规划的空间,利用LLM的推理能力+工具完成特定任务,之后接着按照预设流程继续执行,直到完成最终任务

  • 应用场景:适用于业务相对简单,有成熟的SOP流程可参考且业务节点可自主决策完成部分任务的场景,比如内容审核流程,内容抓取和检查评估可以是一个Agent,审核流程是固定的流程,可以使用Workflow+Agent来提效
  • 优点:这种模式最大优点是兼顾可控性与自主性
  • 缺点:相比纯静态流程,系统复杂度提升,如何做好业务抽象比较考验开发者个人对业务的理解。随着智能化业务结点越来越多,系统的可控性逐渐减弱

3.2 单智能体模式

3.2.1 ReAct

ReAct是比较常见的智能体架构之一,在这种模式下,智能体每执行一步都需要先进行思考,然后决定下一步动作通常是执行工具,完成一步之后,继续思考-行动,直到任务完成

  • 应用场景:适用于开放性研究任务、探索性分析等
  • 优点:相比大模型直接给出结论,ReAct的优势在于,显性的推理过程,让智能体类比人类的思考过程,得出的结论更让人信服,通过边思考-边执行的处理方式有效降低大模型幻觉率
  • 缺点:逐步推理,缺乏全局视角
3.2.2 规划-执行(Plan-And-Execute)

Plan-And-Execute通过分阶段规划与执行任务来应对复杂问题。其核心思想是先将任务分解为子任务,制定详细计划后再逐步执行,并根据执行反馈动态调整方案

  • 使用场景:多步骤项目、复杂集成、有依赖关系的任务
  • 优点:预先规划给予智能体全局视角减少盲目探索,提升任务完成效率和可靠性。预先输出整体执行步骤,提高用户体验
  • 缺点:响应速度相比ReAct更慢,token消耗更高。初始规划依赖语言模型性能,可能因模型缺陷导致计划不完善

3.3 多智能体模式

3.3.1 层级协作(supervisor)

这种模式下,我们使用多个Agent来构建我们的智能体应用,其中有一个顶层Agent,负责意图识别和任务规划以及任务进度把控和调度,其他Agent各司其职,由顶层Agent调度,子Agent将结果汇总至顶层Agent。其中比较有代表性的架构就是Supervisor

  • 应用场景:复杂业务分析、多领域问题、需要专家知识的任务
  • 优点:根据业务抽象或者能力抽象划分子Agent,职责明确,专业的事情交给专业的Agent来处理,提高执行效率和执行效果。拆分的子任务可以并行处理,提高速度
  • 缺点:实现复杂度较高,需要考虑多个Agent间通信问题,和上下文同步问题

3.4 技术选型的一些思考

在了解了各种模式后,一个核心问题摆在面前:我的项目到底应该用哪种模式?是单Agent就足够,还是必须上多Agent?盲目追求最复杂的架构是典型的过度工程化。正如AI领域知名学者吴恩达(Andrew Ng)反复强调的,“从简单模型开始,快速迭代” 的原则同样适用于Agent开发。技术选型没有银弹,只有符合当前业务场景的才是最适合的。不要为了设计而设计。

3.4.1 何时单Agent已足够(避免过度工程化)

在许多场景下,一个精心设计的单Agent不仅足够,而且是更优的选择,因为它更易于开发、调试和维护。以下是一些典型的“单Agent足矣”的场景:

  • 领域高度垂直:任务范围被严格限定在单一领域内。例如,一个“订单查询助手”,它的唯一职责就是调用订单系统查询相关数据信息。
  • 工具集小而精:Agent需要调用的工具数量有限(通常少于5个),且功能边界清晰,不易混淆。
  • 流程相对线性:任务可以被分解为一系列相对固定的步骤,即使有分支,也数量有限且逻辑清晰。
3.4.2 单Agent到多Agent的阈值参考

当任务复杂度超越某个临界点时,单Agent的瓶颈会愈发明显,此时转向多Agent架构就成为必然。以下是一些量化维度的参考阈值,可以帮助你判断是否需要引入MAS:

当一个任务需要多种不同“思维模式”或专业技能的组合时,强行让一个单Agent“精神分裂”去扮演所有角色,其效果远不如构建一个各司其职的专家团队。因此,当你发现你的Agent的Prompt变得臃肿不堪,充满了“如果你是A,就做X;如果你是B,就做Y”的复杂指令时,这通常就是拆分为多Agent的明确信号。

四、为什么需要MAS(Multi-Agents-System)?

4.1 Multi-Agent 的一些挑战

当我们真正决定要构建一个MAS(Multi-Agents-System),我们首先要考虑以下几个问题,

  • 多智能体系统如何平衡成本和收益?
  • 根据 Anthropic 的内部测试,一个智能体完成任务通常比简单的聊天交互消耗约 4 倍的 Token,而多智能体系统甚至可能消耗约 15 倍的 Token,所以针对前期落地场景的选择,我们应该做好定义测量,优先选择高频,高价值的场景。
  • 模型分层设计,对于需要强大逻辑推理和规划能力的节点如主管Agent,可以使用性能顶尖但成本较高的模型(如DeepSeekV3.1/GPT4o/claude-sonnet-4.5等);而对于总结、润色等相对简单的任务,则可以选择成本更低的轻量级模型(gpt-4.1-nano/gpt-4o-mini)。
  • 预算控制和熔断机制,我们要显性控制,任务执行轮次和最大重试次数,以防任务规划不当,导致Agent之间出现无效的循环调用、重复执行任务。
  • 智能体的能力与边界如何界定?

    a. 单一职责原则:让每个Agent专注于一个核心领域或一组紧密相关的技能。

    **b. 工具库与MCPserver:**为Agent提供一个标准化的工具库。Agent的能力体现在它能调用哪些工具(API)和MCP。这样既可以方便地扩展Agent的能力(增加新工具),也能清晰地界定其行为边界

  • 通信机制和状态管理如何设计?

  • 共享全局状态:建立一个所有Agent都可以读写的中心化“黑板”(如Redis、数据库),来记录系统的全局状态、任务列表、已完成的工作等。每个Agent都可以根据策略读取和更新对应区域信息。

4.2 趋势的必然-企业级智能体的演进蓝图

随着AI应用的深入,我们发现单个大型模型或单个智能体在处理复杂、多阶段的现实世界任务时面临瓶颈。从“领域专家”到“团队协作”再到”企业协作“的进化,是AI Agent发展的必然趋势。

参考:https://www.salesforce.com/blog/the-agentic-ai-era-after-the-dawn-heres-what-to-expect/

根据腾讯云、腾讯研究院联合国际权威研究机构Gartner,共同发布《企业级智能体产业落地研究报告》的内容,企业级智能体发展分为三个阶段:

  1. 领域专家:单个AI智能体,精通于执行特定领域内的单一任务
  2. 团队协作:多个专业Agent在企业内部协同工作,由一个“编排Agent”统一调度,共同完成复杂的业务目标
  3. 企业协作:AI智能体能够跨越组织边界,代表个人或企业进行复杂的互动、谈判和交易。

4.3 单Agent的瓶颈与天花板

单个AI Agent,就像一个“专业的领域专家”,虽然在特定任务上表现出色,但当面临综合性、动态性强的复杂问题时,其局限性便显现出来,

  1. Token爆炸与幻觉问题:对于需要长链条推理和跨领域工具调用的任务,为了让大型语言模型(LLM)做出正确决策,我们必须在其提示词(Prompt)中注入海量信息,包括:系统指令、完整的用户交互历史、庞大的工具(API)定义库以及多步骤的执行上下文。随着任务的推进,这个上下文会像滚雪球一样迅速膨胀,轻易便会触及模型的Token上限。即便采用百万级长上下文窗口的模型,也仅仅是推迟了问题的爆发,而非解决了根本矛盾。当模型被置于一个由海量工具定义和繁杂执行历史构成的“信息沼泽”中时,其注意力会被严重稀释,导致关键信息被淹没。这直接引发了致命的“工具选择幻觉”:面对功能繁多的工具库,单个Agent极易混淆功能相似的工具、错误地调用API或“幻觉”出不存在的参数,从而做出错误决策,最终导致整个复杂任务的失败
  2. 维护与扩展的复杂性:当业务需求变化时,修改一个庞大而复杂的“全能型”Agent的内在逻辑,远比调整一个专门负责某个小任务的Agent要困难得多。系统的迭代和扩展成本高昂,在生产环境中每动一次系统提示词带来的调试成本和风险都是巨大的。
  3. 缺乏鲁棒性与容错性(单点故障):如果单个Agent在执行任务的某个环节卡住或出错,整个任务链就会中断。它缺乏自我纠错和寻找替代方案的内在机制,系统非常脆弱。

4.4 多Agent的核心优势

  1. 领域专家+单一职责

    原理:将一个宏大、复杂的目标分解为一系列更小、更具体的子任务,并将每个子任务分配给具有特定领域专家Agent去执行。

    效果:每个Agent只需专注于自己擅长的领域,相对于一个复杂的目标,拆解后的子任务能让领域Agent的"注意力"更集中,极大地提升了任务完成的质量和效率,并且由执行任务产生的上下文内聚在领域内,只需要对外输出必要的上下文,有效降低了单一Agent因任务过于复杂而产生幻觉的风险。

  2. 可扩展性:

    原理:当需要增加新功能时,只需开发一个新的、具备该功能的专业Agent,并将其接入到现有的协作框架中即可,而无需对整个系统进行伤筋动骨的改造。

    效果:系统架构更加清晰,易于维护和扩展,能够快速适应不断变化的业务需求。

  3. 鲁棒性与可靠性

    原理:在一个多Agent系统中,我们可以通过系统设计和流程编排扩展容灾节点,如果某个Agent执行失败,协调者可以重新分配任务给另一个功能相似的Agent,或者整个系统可以调整策略继续执行。

    效果:系统不再存在“单点故障”,容错能力和稳定性得到显著提升,这对于企业级的关键业务应用至关重要。

4.5 常见的多智能体架构

构多智能体系统(Multi-Agent System)通过引入“团队协作”的模式,有效克服了单Agent的局限性,常见的多智能体架如下所示:

  • 网络(Network): 每个智能体可以与其他所有智能体通信。任何智能体都可以决定接下来调用哪个智能体。
  • 主管(Supervisor): 每个智能体只与一个主管智能体通信。主管智能体决定接下来调用哪个智能体。
  • 主管-工具调用(Supervisor-tool-calling):这是主管架构的一种特殊情况。单个智能体可以表示为工具。在这种情况下,主管智能体使用工具调用的LLM来决定调用哪个智能体工具,以及传递给这些智能体的参数。
  • 分层(Hierarchical): 您可以定义一个多智能体系统,其中包含一个主管和多个主管。这是主管架构的泛化,允许更复杂的控制流。
  • 自定义多智能体工作流(custom multi-agent workflow): 每个智能体只与一部分智能体通信。流程的某些部分是确定性的,只有部分智能体可以决定接下来调用哪些其他智能体。

五、如何构建一个MAS(Multi-Agents-System)?

了解完Agetic-System常见的任务执行模式和常见的多智能体架构之后,我们接着聊一下,如何构建一个构建‘团队协作’式的多智能体系统。

5.1 技术选型

先看看技术选型,我们选择的是langGraph4j,它是流行的 Python 库 LangGraph 的 Java 实现版本,它是一个用于构建状态化、多智能体应用的强大框架。了解过智能体开发的人可能知道有另外一款非常受欢迎的框架Langchain(以及它的Java版本Langchan4j),那么LangGraph和Langchain有什么区别呢?

  • LangChain:LLM 应用的基础构建引擎

作为生态的基础框架层,LangChain 的核心价值在于提供 “模块化构建块”,让开发者无需从零搭建 LLM 应用的基础组件。它封装了 Prompt 模板、记忆机制(Memory)、工具集成接口(Tool)等核心模块,支持检索增强生成(RAG)、简单任务链串联等基础能力。

其本质是 “LLM 应用的乐高积木”:通过组合PromptTemplate定义交互范式,用LLM模块对接底层模型,借助Chain串联多步操作,快速实现从 “输入” 到 “输出” 的线性流程。典型场景包括问答机器人、文档摘要工具、基础客服应答系统等无需复杂流程控制的应用。

  • LangGraph:复杂任务的智能编排中枢

作为 LangChain 的扩展编排层,LangGraph 专注于解决 “动态复杂流程” 难题。当任务需要状态管理、多步骤分支、失败重试或多智能体协作时,线性的链结构已无法满足需求,此时图结构的优势便凸显出来。

它通过 “节点(Nodes)- 边(Edges)- 状态(State)” 的三元组模型建模任务流:节点代表具体操作(如工具调用、条件判断),边定义执行路径,中央状态组件实现上下文持久化与流转。这种架构天然支持循环逻辑、人工介入断点恢复和多智能体协同,是构建生产级智能体(Agent)系统的核心工具。LangGraph的出现是对于使用Langchian生态来构建状态化、多智能体应用的的扩展和补充,而不是为了取代Langchain。相反在实际落地中,往往是二者结合来使用,LangGraph用来编排图的结构和控制执行流程,LangChain用来实现某个节点,实现流程编排+节点智能。

  • 下面可以看下LangGraph和其他主流的多智能体框架对比:若需要长期运行/有状态/可恢复的Agentic- system, 可以选择LangGraph ,它更适合生产级编排

5.1.1 LangGraph4j是什么?

github地址(https://github.com/langgraph4j/langgraph4j/tree/main)

LangGraph4j 是流行的 Python 库 LangGraph 的 Java 实现版本,它是一个用于构建状态化、多智能体应用的强大框架。它并非要取代 LangChain4j,而是作为其核心生态的有力补充,专门解决构建复杂Agent时遇到的**循环(cycles)和分支(branching)**问题。其核心思想是将智能体系统抽象为一个状态图(StateGraph)。在这个图中:

  • 状态(State) 是流经整个图的中央对象,它承载着所有任务信息、中间结果和历史记录,是智能体团队的“共享记忆”。
  • 节点(Nodes) 是图中的“工作人员”,可以是一个Agent、一个工具调用,或任何一个处理状态并返回更新的函数。
  • 边(Edges) 连接着节点,决定了任务的流向。特别是条件边(Conditional Edges),它能根据当前状态的某个属性,动态地决定接下来应该由哪个节点(Agent)接手工作。

这种设计,使得构建需要反复思考、修正、协作的智能体系统(例如 ReAct 循环、主管-下属协作)变得异常直观和稳健。

5.1.2 核心特性
  1. 状态化的图结构:与无状态的调用不同,LangGraph4j的核心是可持久化的状态。每个节点执行后都会更新这个中心状态,确保所有Agent都能访问到最新的上下文,这对于长流程、需要记忆的任务至关重要。
  2. 灵活的节点定义:节点可以是任何可执行的逻辑单元,从一个简单的函数到一个完整的、拥有自己工具集的子Agent。这使得系统具备极高的模块化和可扩展性。
  3. 强大的条件路由:这是实现智能体自主决策和协作编排的关键。你可以定义一个“主管”节点,它根据当前状态(如用户的最新提问、上一个Agent的执行结果)来决定下一个任务应该分发给“数据分析Agent”还是“报告生成Agent”。
  4. 原生支持循环:Agent的“思考-行动”循环、自我纠错、多轮对话等需要循环的场景,在LangGraph4j中可以轻松实现,而无需像传统编程那样写复杂的while循环和状态管理代码。
  5. 人机协同 (Human-in-the-Loop):图可以在任何节点后暂停,等待人类的输入、审核或确认,然后再继续执行。这对于构建可控、可靠的企业级应用至关重要。
5.1.3 执行原理

构建和运行一个LangGraph4j应用的流程通常如下:

  1. 定义状态对象:首先,定义一个类或数据结构来表示整个工作流的共享状态(例如,一个包含消息列表、中间结果的AgentState对象)。

  2. 定义节点:将你的Agent、工具或其他业务逻辑实现为一个个的函数或方法,这些方法接受当前的状态作为输入,并返回对状态的更新。

  3. 构建图

    ○ 实例化一个StateGraph,并传入你定义的状态类。

    ○ 使用 .addNode() 将你定义好的节点添加到图中。

    ○ 使用 .addEdge().addConditionalEdges()来连接这些节点,定义任务的流转逻辑。

  4. 编译图:调用 .compile() 方法,LangGraph4j会将你定义的图结构编译成一个可执行的 Graph 对象。

  5. 执行:调用编译后图对象的 .stream().invoke() 方法,传入初始输入,即可启动整个多智能体系统的协作流程。图会根据你定义的边和条件,自动地在不同节点间流转,直到到达终点。

5.2 牛刀小试(Talk is cheap, show me your code)

假如我们有一个需求开发一个智能体系统**,**它可以协助处理用户:用户酒店预订诉求、 订单管理类诉求、酒店搜索推荐诉求。我们可以先将这个智能体小助手定义为“**OTA平台酒店业务助手”,**下面我将分别用单Agent和多Agent来实现,对比以下两种实现方式的区别和效果。演示结果总结如下,可以看出以下几个现象:

  1. 当处理单领域问题时,多Agent架构实现有可能比单Agent实现token消耗还低

    a. 单Agent的实现,处理任何问题都需要所有的Tool作为备选工具,输入给LLM

    b. 多agent的实现,领域拆分,假如规划步骤命中工具较少的单域Agent时,则有可能会出现token消耗更少的情况

  2. 当处理跨域问题(2个领域),单Agent和多Agent都可以解决,多Agent消耗Token略多

  3. 当处理跨域问题(3个领域),单Agent没有完全达成用户目标,而多Agent完全实现了用户的诉求,但是token消耗也更明显。

5.2.1 单Agent 实现

Agent的基本元素包含Prompt+LLM+Tools,接下来我们使用langChain4j构建一个可以自主感知环境并使用工具的Agent.

5.2.1.1 Prompt:
# Role: 你是OTA酒店业务智能助手
## Skills
你的核心职责是协助处理与以下问题:
***
## Rules
***
## Workflows
***
## OutputFormat
\n - 格式:以文本形式输出,且不超过50个字
## Init
你好,我是你的酒店业务智能助手,接下来将帮你处理酒店业务相关问题。

5.2.1.2 Tools

public class HotelTool {
    @Tool("""
        处理酒店搜索请求,根据用户的查询返回酒店搜索结果。
        """)
    String search(@P("城市") String city) {
        return """
            推荐北京苏州街锦江之星酒店,位置便利,服务优质。
            """;
    }
    @Tool("""
            负责处理酒店预订请求
    """)
    String booking(@P("酒店名称") String hotelName, @P("入住日期") String checkInDate, @P("离店日期") String checkOutDate) {
        return """
            “您已成功预订锦江之星酒店”
            """;
    }
    @Tool("""
            负责处理查询用户酒店订单详情,包括订单状态、支付金额、入住日期、离店日期等。
    """)
    String queryOrder(@P("订单号") String orderNo) {
        return """
            “您预订的锦江之星酒店已成功支付200元,订单状态为已支付,入住日期为2025-10-01,离店日期为2025-10-05”
            """;
    }
    @Tool("""
            负责处理查询用户酒店订单退款信息
    """)
    String queryOrderRefund(@P("订单号") String orderNo) {
        return """
            “您预订的锦江之星酒店已成功退款,退款金额100元已原路返回支付账户”
            """;
    }
    @Tool("""
            负责处理查询用户酒店订单取消信息
    """)
    String queryOrderCancel(@P("订单号") String orderNo) {
        return """
            “您预订的锦江之星酒店已成功取消”
            """;
    }
    @Tool("""
            负责处理查询用户是否发起过取消请求
    """)
    String queryOrderCanceled(@P("订单号") String orderNo) {
5.2.1.3 核心代码

(LLM:gpt-4o)

String otaSysPrompt = "***";
HotelTool hotelTool = new HotelTool();
HotelService hotelBotService = AiServices.builder(HotelService.class)
.chatModel(model)
.streamingChatModel(openAiStreamingChatModel)
.tools(hotelTool)
.build();
String testQuery = "小明十一去北京,帮忙推荐一家酒店并预订,如果支付金额超过180元,请帮忙操作退款";
TokenStream tokenStream = hotelBotService.evaluate(otaSysPrompt, testQuery);
StringBuilder finalRes = new StringBuilder();
CountDownLatch countDownLatch = new CountDownLatch(1);
tokenStream.onPartialResponse((String partialResponse) -> {
}).onToolExecuted((ToolExecution toolExecution) -> {
System.out.println("\n调用工具:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
System.out.println(toolExecution.request().name());
System.out.println("\n返回结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
System.out.println(toolExecution.result());
}).onCompleteResponse((ChatResponse r) -> {
finalRes.append(r.aiMessage().text());
System.out.println("\n token:\n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
System.out.println(r.tokenUsage().toString());
countDownLatch.countDown();
}).onError((Throwable error) -> {
System.out.println(error.getMessage());
countDownLatch.countDown();
}).start();
countDownLatch.await();
System.out.println("\n最终结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
System.out.println(finalRes);

5.2.1.4 运行示例

  1. 小明十一假期去北京,帮他推荐一家酒店?

  1. 小明十一假期去北京,帮他推荐一家酒店,十月一号入住,十月五号离店,并且预订一下

  1. 小明十一去北京,帮忙推荐一家酒店并预订,如果支付金额超过180元,请帮忙操作退款

我们期望的执行步骤是:查询酒店-> 预订酒店-> 查询订单支付金额,并判断是否大于100->发起退款,但是实际执行效果却没有达成目标。

通过以上运行示例可以看出,当我们发出一个简单单任务时(通常1-2步),单Agent可以处理,当我们发出一个较为复杂的任务指令时(>= 3步),可以看到在完全相同的条件下,已经不能满足用户诉求了。

5.2.2 多Agent实现

下面将展示如何使用LangGraph4j构建一个Supervisor(主管)模式的多智能体系统。该系统包含一个主管Agent,一个总结Agent,3个业务专家Agent(酒店搜索专家,酒店预订专家,酒店订单专家)。示例成功演示了系统如何根据用户意图,动态地将任务路由给合适的Agent,并能协同完成涉及多个步骤的复杂请求,直观地体现了LangGraph4j在构建MAS方面的强大能力。

样例节点如下所示:(注意:本示例仅作为演示讲解,实际生产环境的架构编排可能需要更多的节点,如:反思,评估,人机交互等等)

5.2.2.1 环境和依赖准备

  1. 必须保证JDK版本在 17及以上,
  2. pom依赖
<dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-core</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-langchain4j</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-postgres-saver</artifactId>
    <version>1.7.0</version>
</dependency>
5.2.2.2 Node:定义图的节点(部分代码)
  1. Superivisor主管节点,负责意图识别和动态调度下层节点
您是一个OTA行业任务规划专家。请分析用户的查询结合当前可用的专家描述分解为具体任务,相同的专家任务,应合并为一个任务。
# 可用的专家及每个专家拥有的工具:
**
# 工作流程
1. ***。
# 输出格式要求:
* 输出必须是 JSON 对象,并且JSON响应中不应该包含Markdown代码块标记。
*   JSON 结构:
{
"steps": [
{
"stepId": "阿拉伯数字,根据优先级升序排列",
"description": "description",
"expert": "expert1",
"priority": 0.8,
"dependsOn": "依赖的任务Id,如果没有依赖,则为0"
}
]
}
@Slf4j
public class SupervisorTestAgent implements NodeAction<TestState> {
@Override
public Map<String, Object> apply(TestState state) throws Exception {
List<TestStep> steps = state.getSteps();
if(steps.isEmpty()) {
Response<AiMessage> response = service.plan(state.getOriginalQuery());
AiMessage aiMessage = response.content();
TestPlanResponse content = JsonUtils.fromJson(aiMessage.text(), TestPlanResponse.class);
steps = content.getSteps();
System.out.println("SupervisorAgent: 规划结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
System.out.println(aiMessage.text()+"\nTokenUsage:"+ response.tokenUsage().totalTokenCount()+"\n");
System.out.println("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
return Map.of("steps",steps, "next", "SUPERVISOR");
} else if(CollectionUtils.isNotEmpty(state.getRemainingExperts())) {
List<TestStep> remainingSteps = state.getRemainingExperts();
TestStep step = remainingSteps.get(0);
return Map.of("next",step.getExpert());
}
return Map.of("next","SUMMARIZE");
}
}
  1. HotelOrder节点,负责预订酒店和查询酒店订单(部分代码)
public class HotelOrderAgent implements NodeAction<TestState> {
    static class Tools {
        @Tool("""
            负责处理查询用户酒店订单详情,包括订单状态、支付金额、入住日期、离店日期等。
    """)
        String queryOrder(@P("订单号") String orderNo) {
            return """
            “您预订的锦江之星酒店已成功支付200元,订单状态为已确认,入住日期为2025-10-01,离店日期为2025-10-05”
            """;
        }
        @Tool("""
            负责用户订单退款
    """)
        String refund(@P("订单号") String orderNo) {
            return """
            “您的订单10233已成功退款200元”
            """;
        }
    }
    @Override
    public Map<String, Object> apply(TestState state) throws InterruptedException {
        var originalQuery = state.getOriginalQuery();
        List<TestStep> steps = state.getSteps();
        TestStep step = steps.stream().filter(it -> !it.isFinish()).findFirst().orElse(null);
        String dependenciesMessage = state.getDependenciesMessage(step.getDependsOn());
        TokenStream tokenStream = service.evaluate( "本次任务执行子目标:"+step.getDescription()+", 用户原始总目标" +originalQuery +", 依赖信息:"+dependenciesMessage);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        StringBuilder stringBuilder = new StringBuilder();
        tokenStream.onPartialResponse((String partialResponse) -> {
            }).onToolExecuted((ToolExecution toolExecution) -> {   
            }).onCompleteResponse((ChatResponse r) -> {
                stringBuilder.append(r.aiMessage().text());
                System.out.println("\nHotelOrderAgent: 结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                System.out.println(r.aiMessage().text()+ "\nTokenUsage:"+ r.tokenUsage().totalTokenCount());
                System.out.println("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                countDownLatch.countDown();
            }).onError((Throwable error) -> {
                System.out.println(error.getMessage());
                countDownLatch.countDown();
            }).start();
        countDownLatch.await();
        step.setFinish(true);
        step.setResult(stringBuilder.toString());
        return Map.of( "steps", steps , "messages", AiMessage.from(stringBuilder.toString()) );
    }
  1. HotelSearch 节点:负责根据用户输入和用户信息推荐合适的酒店(部分代码)
public class HotelSearchAgent implements NodeAction<TestState> {
    static class Tools {
        @Tool("""
        处理酒店搜索请求,根据用户的查询返回酒店搜索结果。
        """)
        String search(@P("城市") String city) {
            return """
            推荐北京苏州街锦江之星酒店,位置便利,服务优质。
            """;
        }
    }
    @Override
    public Map<String, Object> apply(TestState state) throws Exception {
        var message = state.lastMessage().orElseThrow();
        var text = switch( message.type() ) {
            case USER -> ((UserMessage)message).singleText();
            case AI -> ((AiMessage)message).text();
            default -> throw new IllegalStateException("unexpected message type: " + message.type() );
        };
        var result = service.search( text );
        return Map.of( "messages", AiMessage.from(result) );
    }
}
  1. HotelBooking 节点:负责处理酒店预订(部分代码)
public class HotelBookingAgent implements NodeAction<TestState> {
    static class Tools {
        @Tool("""
            负责处理酒店预订请求
    """)
        String booking(@P("酒店名称") String hotelName, @P("入住日期") String checkInDate, @P("离店日期") String checkOutDate) {
            return """
            “您已成功预订锦江之星酒店,订单号为10233”
            """;
        }
    }
    @Override
    public Map<String, Object> apply(TestState state) throws InterruptedException {
        List<TestStep> steps = state.getSteps();
        TestStep step = steps.stream().filter(it -> !it.isFinish()).findFirst().orElse(null);
        var originalQuery = ((UserMessage)state.messages().get(0)).singleText();
        String dependenciesMessage = state.getDependenciesMessage(step.getDependsOn());
        TokenStream tokenStream = service.evaluate( "本次任务执行子目标:"+step.getDescription()+", 用户原始总目标" +originalQuery +", 依赖信息:"+dependenciesMessage);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        StringBuilder stringBuilder = new StringBuilder();
        tokenStream.onPartialResponse((String partialResponse) -> {
            }).onToolExecuted((ToolExecution toolExecution) -> {
            log.info("\n调用工具:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            log.info("┃ {}", toolExecution.request().name());
            log.info("\n返回结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            log.info("┃ {}", toolExecution.result());
            }).onCompleteResponse((ChatResponse r) -> {
                stringBuilder.append(r.aiMessage().text());
                System.out.println("\nHotelBookingAgent: 结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                System.out.println(r.aiMessage().text()+ "\nTokenUsage:"+ r.tokenUsage().totalTokenCount());
                System.out.println("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                countDownLatch.countDown();
            }).onError((Throwable error) -> {
                System.out.println(error.getMessage());
                countDownLatch.countDown();
            }).start();
        countDownLatch.await();
        step.setResult(stringBuilder.toString());
        step.setFinish(true);
        return Map.of( "steps", steps , "messages", AiMessage.from(stringBuilder.toString()) );
    }
}
  1. Sumarize 节点:负责总结输出
# 你是一个专业的信息整合与内容协调助手,***"
public class HotelSummarizeAgent implements NodeAction<TestState> {
    @Override
    public Map<String, Object> apply(TestState state) throws Exception {
        String prompt = 
"# 你是一个专业的信息整合与内容协调助手***"
;
        TokenStream tokenStream = service.summarize(prompt, state.getOriginalQuery(), state.getExpertResult());
        StringBuilder responseBuilder = new StringBuilder();
        CountDownLatch countDownLatch = new CountDownLatch(1);
        tokenStream.onPartialResponse(partialResponse -> {
        }).onCompleteResponse(response -> {
            System.out.println("\nHotelSummarizeAgent: 最终结果:\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            System.out.println(response.aiMessage().text()+ "\nTokenUsage:"+ response.tokenUsage().totalTokenCount());
            System.out.println("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            countDownLatch.countDown();
        }).onError(throwable -> {
        }).start();
        countDownLatch.await();
        return Map.of("messages", AiMessage.from(responseBuilder.toString()));
    }
}
5.2.2.3 运行示例
  1. 小明十一假期去北京,帮他推荐一家酒店?

在这个示例中我们可以看到,用户希望推荐一家酒店,那这个正是我们设计的hotelSearch的职责之一,可以看到,我们正确的找到了HotelSearch节点,并且执行成功。

  1. 小明十一假期去北京,帮他推荐一家酒店,十月一号入住,十月五号离店,并且预订一下

在这个示例中,我们可以看到,这是一个协作的场景。用户希望推荐一家酒店并且自动预订一下。根据我们节点的职责描述,大模型自动规划了执行路径,先调用HotelSearch进行酒店推荐,然后调用HotelOrder进行酒店预订,最终调用总结Agent进行润色输出,全程不需要人为干预,利用多智能体协作达成最终任务目标。

  1. 小明十一假期(10.1-1.7)去北京,帮忙推荐一家酒店并预订,如果支付金额超过180元,请帮忙操作退款

在这个示例中,我们可以看到,我们成功使用Multi-Agent解决了单Agent未能处理的场景,首先主控规划节点,完整的规划了执行步骤和依赖关系,然后按照规划步骤和依赖上下文逐步执行,最终达成目标

六、总结

本文从开发者最关心的“工作流”与“智能体”之争出发,得出的核心观点是:不必纠结于分类,而应关注系统“有多智能(Agentic)”,根据业务需求找到控制与自主的最佳平衡。

文中梳理了从简单到复杂的几种任务执行模式,并阐明了单个Agent在面对复杂问题时的局限性,进而引出多智能体系统(MAS)作为解决方案的必然性。最后,通过Java框架LangGraph4j的代码实例,我们具体展示了如何构建一个“团队协作式”的智能体应用。希望这篇文章能帮你理清思路,为你的Agent项目提供一个扎实的起点。

那么,如何系统的去学习大模型LLM?

作为一名从业五年的资深大模型算法工程师,我经常会收到一些评论和私信,我是小白,学习大模型该从哪里入手呢?我自学没有方向怎么办?这个地方我不会啊。如果你也有类似的经历,一定要继续看下去!这些问题啊,也不是三言两语啊就能讲明白的。

所以我综合了大模型的所有知识点,给大家带来一套全网最全最细的大模型零基础教程。在做这套教程之前呢,我就曾放空大脑,以一个大模型小白的角度去重新解析它,采用基础知识和实战项目相结合的教学方式,历时3个月,终于完成了这样的课程,让你真正体会到什么是每一秒都在疯狂输出知识点。

由于篇幅有限,⚡️ 朋友们如果有需要全套 《2025全新制作的大模型全套资料》,扫码获取~
在这里插入图片描述

为什么要学习大模型?

我国在A大模型领域面临人才短缺,数量与质量均落后于发达国家。2023年,人才缺口已超百万,凸显培养不足。随着AI技术飞速发展,预计到2025年,这一缺口将急剧扩大至400万,严重制约我国AI产业的创新步伐。加强人才培养,优化教育体系,国际合作并进是破解困局、推动AI发展的关键。

在这里插入图片描述

在这里插入图片描述

👉大模型学习指南+路线汇总👈

我们这套大模型资料呢,会从基础篇、进阶篇和项目实战篇等三大方面来讲解。
在这里插入图片描述
在这里插入图片描述

👉①.基础篇👈

基础篇里面包括了Python快速入门、AI开发环境搭建及提示词工程,带你学习大模型核心原理、prompt使用技巧、Transformer架构和预训练、SFT、RLHF等一些基础概念,用最易懂的方式带你入门大模型。
在这里插入图片描述

👉②.进阶篇👈

接下来是进阶篇,你将掌握RAG、Agent、Langchain、大模型微调和私有化部署,学习如何构建外挂知识库并和自己的企业相结合,学习如何使用langchain框架提高开发效率和代码质量、学习如何选择合适的基座模型并进行数据集的收集预处理以及具体的模型微调等等。
在这里插入图片描述

👉③.实战篇👈

实战篇会手把手带着大家练习企业级的落地项目(已脱敏),比如RAG医疗问答系统、Agent智能电商客服系统、数字人项目实战、教育行业智能助教等等,从而帮助大家更好的应对大模型时代的挑战。
在这里插入图片描述

👉④.福利篇👈

最后呢,会给大家一个小福利,课程视频中的所有素材,有搭建AI开发环境资料包,还有学习计划表,几十上百G素材、电子书和课件等等,只要你能想到的素材,我这里几乎都有。我已经全部上传到优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费
在这里插入图片描述
相信我,这套大模型系统教程将会是全网最齐全 最易懂的小白专用课!!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值