进阶大模型应用:基于 LangGraph 构建企业级多智能体(Multi-Agent)协同网络
一、 引言:单 Agent 的瓶颈与 Multi-Agent 的崛起
在构建复杂的大模型(LLM)应用时,单个 Agent(如传统的 ReAct 架构)往往会面临“能力过载”的问题。当一个 Agent 需要同时处理代码编写、数据分析、安全审计和日志输出等多项繁重任务时,其 Prompt 会变得异常臃肿,导致大模型在长文本中迷失方向,进而出现幻觉、工具误调用或逻辑死循环。
为了解决这一痛点,多智能体系统(Multi-Agent Systems, MAS) 成为了企业级 AIGC 落地的新范式。其核心思想类似于现代企业的组织架构:将一个复杂的巨型任务拆解,交由多个专注于特定领域的“专职 Agent”(如科研 Agent、编程 Agent、校对 Agent)共同协作完成。 通过明确的角色分工和严格的状态流转控制,多智能体系统能够显著提升复杂任务的成功率与稳定性。本文将基于 LangChain 生态中专为图结构设计的 LangGraph 框架,深入剖析多智能体协同网络的底层原理与代码实现。
二、 多智能体协同的核心拓扑结构
在设计 Multi-Agent 系统时,常见的协作模式主要有以下两种:
1. 协作网关模式(Hub and Spoke / Supervisor)
在这种模式下,存在一个“主管(Supervisor) Agent”,它负责接收用户输入,并根据任务性质将子任务分发给不同的“员工(Worker) Agent”。员工完成任务后将结果汇报给主管,由主管决定是继续分发还是结束任务。这种模式适合流程边界清晰、需要中心化调度的场景。
2. 流水线模式(Chains / Sequential Pipeline)
智能体之间像工业流水线一样串联,Agent A 的输出直接作为 Agent B 的输入。这种模式适合强顺序驱动的任务,例如:需求分析 -> 代码生成 -> 代码测试 -> 自动化部署。
本文将以 Supervisor(主管模式) 为例进行深度实战。
三、 基于 LangGraph 的多智能体实战准备
LangGraph 是 LangChain 团队推出的一个通过将步骤建模为图(Graph)中的顶点(Nodes)和边(Edges)来构建有状态、多角色应用的库。相比传统的链式结构,它完美支持循环(Cycles),这对于 Agent 的反思和迭代至关重要。
首先,安装核心依赖:
Bash
pip install langgraph langchain_openai langchain_core
配置核心 API 环境:
Python
import os
os.environ["OPENAI_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxx"
os.environ["OPENAI_API_BASE"] = "https://api.openai.com/v1"
四、 核心代码实现:构建一个研发团队架构
我们将构建一个小型多智能体网络,包含三个角色:
-
Coder(程序员):负责根据需求编写 Python 代码。
-
Tester(测试员):负责运行并对代码进行质量检查。
-
Supervisor(主管):负责审阅全局,分发任务。
1. 定义全局状态(State)
在 LangGraph 中,所有 Agent 共享一个全局状态对象。各个节点通过向这个状态中追加或覆盖数据来进行通信。
Python
from typing import typing, Annotated, Sequence
from typing_extensions import TypedDict
import operator
from langchain_core.messages import BaseMessage
# 定义图的全局状态,messages 字段用于记录所有的对话历史
class TeamState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
next_agent: str # 记录下一个执行任务的 Agent 名称
2. 创建独立智能体节点
接下来,我们定义 Coder 和 Tester 的逻辑。为了简化演示,我们使用 Prompt 为其注入不同的角色特性。
Python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# Coder 节点的生成函数
def coder_node(state: TeamState):
messages = state["messages"]
prompt = ChatPromptTemplate.from_messages([
("system", "你是一名精通 Python 的高级软件工程师。请根据用户的需求编写高效、整洁的代码。只输出代码,不要多余的解释。"),
MessagesPlaceholder(variable_name="messages"),
])
chain = prompt | llm
response = chain.invoke({"messages": messages})
return {"messages": [response], "next_agent": "Supervisor"}
# Tester 节点的生成函数
def tester_node(state: TeamState):
messages = state["messages"]
prompt = ChatPromptTemplate.from_messages([
("system", "你是一名严苛的测试工程师。请审阅团队生成的 Python 代码,指出其中潜在的 Bug、边界条件漏洞或性能问题。如果代码完美,请回复 'PASS'。"),
MessagesPlaceholder(variable_name="messages"),
])
chain = prompt | llm
response = chain.invoke({"messages": messages})
return {"messages": [response], "next_agent": "Supervisor"}
3. 构建 Supervisor(主管)决策大脑
Supervisor 需要决定下一步是让 Coder 修正代码、让 Tester 检查,还是认为任务已圆满结束(FINISH)。
Python
import json
from langchain_core.output_parsers import JsonOutputParser
def supervisor_node(state: TeamState):
messages = state["messages"]
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个研发团队的主管。你的职责是根据当前团队的对话进展,决定下一步由谁来工作。可以选择的角色有:'Coder'、'Tester'。如果测试已经通过(收到PASS)或者任务已经圆满完成,请选择 'FINISH'。请务必返回 JSON 格式,例如:{{\"next\": \"Coder\"}}"),
MessagesPlaceholder(variable_name="messages"),
])
chain = prompt | llm
response = chain.invoke({"messages": messages})
# 解析模型输出的路由决定
try:
route_decision = json.loads(response.content)
next_step = route_decision.get("next", "FINISH")
except:
next_step = "FINISH"
return {"next_agent": next_step}
4. 使用 LangGraph 组装有向工作流图
现在,我们将上述节点和条件路由组合成一个完整的有向图。
Python
from langgraph.graph import StateGraph, END
# 1. 初始化有状态的图
workflow = StateGraph(TeamState)
# 2. 将编写好的节点加入图中
workflow.add_node("Coder", coder_node)
workflow.add_node("Tester", tester_node)
workflow.add_node("Supervisor", supervisor_node)
# 3. 配置条件边:Supervisor 根据 next_agent 的值进行分流
def router(state: TeamState):
next_agent = state["next_agent"]
if next_agent == "FINISH":
return END
return next_agent
# 从 Supervisor 出发,根据 router 函数的返回值跳转到 Coder、Tester 或结束
workflow.add_conditional_edges(
"Supervisor",
router,
{
"Coder": "Coder",
"Tester": "Tester",
"END": END
}
)
# 4. 固定边:Worker 执行完后无条件返回给 Supervisor
workflow.add_edge("Coder", "Supervisor")
workflow.add_edge("Tester", "Supervisor")
# 5. 设置图的起点
workflow.set_entry_point("Supervisor")
# 6. 编译图,得到最终的可执行应用
app = workflow.compile()
五、 系统运行与协作链路解析
我们向这个编译好的多智能体网络投递一个开发需求:
Python
from langchain_core.messages import HumanMessage
inputs = {
"messages": [HumanMessage(content="帮我写一个 Python 函数,实现快速排序算法,并包含简单的单元测试。")]
}
for output in app.stream(inputs):
for key, value in output.items():
print(f"--- 节点 [{key}] 执行完毕 ---")
if "next_agent" in value:
print(f"流转状态 -> 下一步指派给: {value['next_agent']}\n")
当程序启动后,你会观察到以下严密的团队协作流程:
-
Supervisor 接收到原始需求,识别出这是一个编码任务,将状态置为
Coder。 -
Coder 节点介入,生成标准快速排序代码,并自动将结果推回给
Supervisor。 -
Supervisor 审查当前最新的代码消息,认为需要质量保障,于是将状态修改为
Tester。 -
Tester 节点启动,对 Coder 生成的代码进行边界条件核查,判定逻辑无误,输出
PASS。 -
Supervisor 捕捉到
PASS信号,认为项目符合交付标准,将路由导向END。
整个过程中,Agent 之间各司其职,通过修改和读取全局的 TeamState 实现了信息的无缝传递和状态的严密流转。
六、 总结:生产环境下的多智能体设计原则
在实际的企业级复杂业务场景中,构建 Multi-Agent 系统通常需要遵循以下设计原则:
-
原子化职责: 每一个子 Agent 的功能应当尽可能单一且聚焦。如果一个 Agent 既要负责查数据库,又要负责生成前端 UI,那就应当将其拆分为两个更小颗粒度的智能体。
-
状态裁剪: 在大型长对话中,不要把所有的原始日志都扔进全局 State 中。建议每个 Agent 在向全局状态汇报时,只提取关键上下文(摘要),以避免 Token 浪费和信息冗余导致的模型长文本迷失。
-
动态与静态结合: 虽然大模型具备动态路由的能力,但对于极其严谨的业务流(如财务审批),应当在 LangGraph 中使用硬编码边(Explicit Edges)来强制约束流转路径,而将大模型的推理能力留在节点内部,实现“宏观可控,微观灵活”。
更多推荐



所有评论(0)