Fork me on GitHub

使用 LangChain 和 LangGraph 构建一个简单的多智能体系统

创建包含特定文字的 AI 图

 

# 多智能体报告生成系统

本文介绍了一个简单的多智能体系统的实现,使用 LangChain 结合 LangGraph 来构建这样的系统,LangGraph 作为 LangChain 生态的重要组成部分,专为构建有状态、多智能体的工作流而设计,非常适合实现复杂的智能体协作场景。

本文将详细介绍如何使用 LangChain 和 LangGraph 构建一个多智能体报告生成系统,该系统能够自动完成从网络研究、趋势分析、报告撰写到校对的全流程。

系统设计概述

我们的多智能体系统将包含四个专业智能体和一个管理智能体,形成一个监督式架构:

  • 网络研究智能体:负责通过网络搜索获取目标主题的最新信息

  • 趋势分析智能体:分析研究结果,提取并排序关键趋势

  • 报告撰写智能体:基于研究和分析结果撰写专业报告

  • 校对智能体:优化报告的语法、格式和可读性

  • 管理智能体:协调各智能体工作,控制整体流程

系统采用状态驱动的工作流,通过 LangGraph 构建状态转换图,实现智能体之间的有序协作。

开发步骤

步骤 1:安装所需库

首先安装实现系统所需的库:

pip install langchain langchain-openai langchain-community langgraph pydantic

步骤 2:导入必要的库

import os

from typing import Dict, List, Any

from pydantic import BaseModel, Field

from langchain\_openai import ChatOpenAI

from langchain\_core.tools import tool

from langchain\_community.tools import BraveSearch

from langchain\_core.prompts import ChatPromptTemplate, MessagesPlaceholder

from langchain\_core.output\_parsers import StrOutputParser

from langchain\_core.messages import BaseMessage, HumanMessage, AIMessage

from langgraph.graph import StateGraph, END

from langgraph.checkpoint.memory import MemorySaver

步骤 3:配置 API 密钥

本系统使用 OpenAI 的语言模型和 Brave 搜索引擎,需要配置相应的 API 密钥:

\# 设置API密钥

os.environ\["OPENAI\_API\_KEY"] = "YOUR-OPENAI-API-KEY"

os.environ\["BRAVE\_API\_KEY"] = "YOUR-BRAVE-API-KEY"

步骤 4:定义系统状态结构

在多智能体系统中,状态管理至关重要。我们定义一个 AgentState 类来保存整个工作流的状态:

class AgentState(BaseModel):

   """多智能体系统的全局状态"""

   topic: str = Field(description="报告的主题")

   research\_findings: str = Field(default="", description="网络研究的结果")

   trend\_analysis: str = Field(default="", description="趋势分析的结果")

   draft\_report: str = Field(default="", description="报告草稿")

   final\_report: str = Field(default="", description="校对后的最终报告")

   current\_agent: str = Field(default="", description="当前正在工作的智能体")

   next\_agent: str = Field(default="", description="下一个要工作的智能体")

   messages: List\[BaseMessage] = Field(default\_factory=list, description="消息历史")

这个状态类包含了系统运行过程中需要共享和传递的所有信息,确保智能体之间能够有效协作。

步骤 5:定义工具

智能体通过工具与外部环境交互。我们使用 Brave 搜索引擎作为网络研究智能体的工具:

@tool

def brave\_search(query: str) -> str:

   """使用Brave搜索引擎搜索网络上的信息"""

   brave = BraveSearch.from\_api\_key(

       api\_key=os.environ\["BRAVE\_API\_KEY"],

       search\_kwargs={"count": 3}  # 返回3条搜索结果

   )

   return brave.run(query)

通过 LangChain 的 @tool 装饰器,我们可以轻松定义供智能体使用的工具。

步骤 6:设计智能体类

我们创建一个通用的 Agent 类来封装智能体的基本行为,每个智能体将拥有自己的角色、目标、背景故事和可用工具:

class Agent:

   def \_\_init\_\_(self, name: str, role: str, goal: str, backstory: str, tools: List\[Any] = None):

       self.name = name

       self.role = role

       self.goal = goal

       self.backstory = backstory

       self.tools = tools or \[]

       # 创建提示模板

       self.prompt = ChatPromptTemplate.from\_messages(\[

           ("system", f"""你是{self.name},角色是{self.role}。

           你的目标是:{self.goal}

           你的背景:{self.backstory}

           可用工具:{\[tool.name for tool in self.tools]}

           如果你有可用工具,在需要时可以使用它们。

           请根据当前任务和可用信息,完成你的工作。"""),

           MessagesPlaceholder(variable\_name="messages"),

       ])

       # 创建LLM

       self.llm = ChatOpenAI(model="gpt-4o")

       # 如果有工具,创建带工具调用的链

       if self.tools:

           self.chain = self.prompt | self.llm.bind\_tools(self.tools)

       else:

           self.chain = self.prompt | self.llm | StrOutputParser()

          

   def invoke(self, state: AgentState) -> Dict\[str, Any]:

       """调用智能体处理任务"""

       # 构建智能体的输入消息

       messages = \[

           HumanMessage(content=f"请处理关于{state.topic}的任务。当前可用信息:{self.\_get\_relevant\_info(state)}")

       ]

       # 调用智能体

       result = self.chain.invoke({"messages": messages})

       # 处理结果并更新状态

       return self.\_process\_result(state, result)

   def \_get\_relevant\_info(self, state: AgentState) -> str:

       """获取与当前智能体相关的信息"""

       if self.name == "web\_researcher":

           return f"主题:{state.topic}"

       elif self.name == "trend\_analyst":

           return f"研究结果:{state.research\_findings}"

       elif self.name == "report\_writer":

           return f"研究结果:{state.research\_findings}\n趋势分析:{state.trend\_analysis}"

       elif self.name == "proofreader":

           return f"报告草稿:{state.draft\_report}"

       return ""

   def \_process\_result(self, state: AgentState, result: Any) -> Dict\[str, Any]:

       """处理智能体的输出结果并更新状态"""

       # 提取结果内容

       if hasattr(result, 'content'):

           content = result.content

       elif isinstance(result, str):

           content = result

       else:

           content = str(result)

       # 根据智能体类型更新相应的状态字段

       updates = {

           "current\_agent": self.name,

           "messages": state.messages + \[AIMessage(content=content, name=self.name)]

       }

       # 设置下一步智能体

       if self.name == "web\_researcher":

           updates\["research\_findings"] = content

           updates\["next\_agent"] = "trend\_analyst"

       elif self.name == "trend\_analyst":

           updates\["trend\_analysis"] = content

           updates\["next\_agent"] = "report\_writer"

       elif self.name == "report\_writer":

           updates\["draft\_report"] = content

           updates\["next\_agent"] = "proofreader"

       elif self.name == "proofreader":

           updates\["final\_report"] = content

           updates\["next\_agent"] = ""  # 所有任务完成

       return updates

这个通用智能体类实现了智能体的核心功能:根据提示处理任务、使用工具(如果有)、处理结果并更新系统状态。

步骤 7:创建智能体实例

基于上述 Agent 类,我们创建四个专业智能体:

\# 网络研究智能体

web\_researcher = Agent(

   name="web\_researcher",

   role="网络研究专家",

   goal="找到关于{topic}的最新、有影响力且相关的信息,包括关键用例、挑战和统计数据",

   backstory="你曾是一名调查记者,擅长发现技术突破和市场洞察,能识别可操作的数据和趋势",

   tools=\[brave\_search]  # 网络研究智能体可使用搜索工具

)

\# 趋势分析智能体

trend\_analyst = Agent(

   name="trend\_analyst",

   role="趋势分析专家",

   goal="分析研究结果,提取重要趋势,并按行业影响力、增长潜力和独特性排序",

   backstory="你是一名资深战略顾问,擅长从数据中发现模式,将原始数据转化为清晰的见解"

)

\# 报告撰写智能体

report\_writer = Agent(

   name="report\_writer",

   role="报告撰写专家",

   goal="撰写详细、专业的报告,有效传达研究结果和分析",

   backstory="你曾是知名期刊的技术作家,擅长将故事与数据结合,创作既信息丰富又引人入胜的内容"

)

\# 校对智能体

proofreader = Agent(

   name="proofreader",

   role="校对专家",

   goal="优化报告的语法准确性、可读性和格式,确保符合专业出版标准",

   backstory="你是一位获奖编辑,擅长完善书面内容,对细节有敏锐的洞察力"

)

步骤 8:创建管理智能体

管理智能体负责协调各智能体工作,决定工作流程:

class ManagerAgent:

   def \_\_init\_\_(self):

       self.prompt = ChatPromptTemplate.from\_messages(\[

           ("system", """你是多智能体系统的管理器,负责协调各个智能体完成任务。

           你的职责是根据当前状态决定下一步应该由哪个智能体工作。

           工作流程应该是:web\_researcher → trend\_analyst → report\_writer → proofreader → 完成。

           如果next\_agent已设置,则使用该值。

           只需返回智能体名称,不要添加其他内容。"""),

           MessagesPlaceholder(variable\_name="messages"),

       ])

       self.llm = ChatOpenAI(model="gpt-4o")

       self.chain = self.prompt | self.llm | StrOutputParser()

   def decide\_next\_agent(self, state: AgentState) -> str:

       """决定下一个要工作的智能体"""

       if state.next\_agent:

           return state.next\_agent

       # 如果没有设置next\_agent,则由管理器决定

       decision = self.chain.invoke({

           "messages": \[HumanMessage(content=f"当前状态: {state.dict()}")]

       })

       return decision.strip()

管理智能体根据系统当前状态决定下一步由哪个智能体执行任务,确保工作流程按预定顺序进行。

步骤 9:构建工作流图

使用 LangGraph 构建状态转换图,定义智能体之间的协作流程:

\# 初始化管理智能体

manager = ManagerAgent()

\# 定义图中的节点函数

def web\_researcher\_node(state: AgentState) -> Dict\[str, Any]:

   return web\_researcher.invoke(state)

def trend\_analyst\_node(state: AgentState) -> Dict\[str, Any]:

   return trend\_analyst.invoke(state)

def report\_writer\_node(state: AgentState) -> Dict\[str, Any]:

   return report\_writer.invoke(state)

def proofreader\_node(state: AgentState) -> Dict\[str, Any]:

   return proofreader.invoke(state)

def router(state: AgentState) -> str:

   """路由函数,决定下一步走向"""

   next\_agent = manager.decide\_next\_agent(state)

   if not next\_agent:

       return END

   return next\_agent

\# 构建工作流图

def create\_workflow\_graph():

   # 初始化状态图

   workflow = StateGraph(AgentState)

   # 添加节点

   workflow.add\_node("web\_researcher", web\_researcher\_node)

   workflow.add\_node("trend\_analyst", trend\_analyst\_node)

   workflow.add\_node("report\_writer", report\_writer\_node)

   workflow.add\_node("proofreader", proofreader\_node)

   # 设置入口点

   workflow.set\_entry\_point("web\_researcher")

   # 添加边缘

   workflow.add\_edge("web\_researcher", router)

   workflow.add\_edge("trend\_analyst", router)

   workflow.add\_edge("report\_writer", router)

   workflow.add\_edge("proofreader", router)

   # 编译图,添加内存支持

   memory = MemorySaver()

   return workflow.compile(checkpointer=memory)

在这个工作流图中,我们定义了四个智能体节点和一个路由节点。路由节点由管理智能体控制,决定流程的下一步走向。

步骤 10:运行多智能体系统

最后,我们编写代码来运行整个多智能体系统:

if \_\_name\_\_ == "\_\_main\_\_":

   # 创建工作流

   app = create\_workflow\_graph()

   # 定义报告主题

   topic = "2024年人工智能发展趋势"

   # 初始化状态

   initial\_state = AgentState(

       topic=topic,

       messages=\[HumanMessage(content=f"请生成关于{topic}的报告")]

   )

   # 运行工作流

   final\_state = None

   for step in app.stream(initial\_state, {"configurable": {"thread\_id": "report-1"}}):

       # 打印每个步骤的结果

       for node, values in step.items():

           print(f"\n--- {node} 完成 ---")

           if node == "web\_researcher":

               print(f"研究结果: {values\['research\_findings']\[:200]}...")

           elif node == "trend\_analyst":

               print(f"趋势分析: {values\['trend\_analysis']\[:200]}...")

           elif node == "report\_writer":

               print(f"报告草稿: {values\['draft\_report']\[:200]}...")

           elif node == "proofreader":

               print(f"最终报告: {values\['final\_report']\[:200]}...")

       final\_state = values

   # 输出最终报告

   if final\_state:

       print("\n\n=== 最终报告 ===")

       print(final\_state\["final\_report"])

系统工作流程说明

该多智能体系统按照以下流程运行:

  • 初始化:设置报告主题并创建初始状态

  • 网络研究:网络研究智能体使用 Brave 搜索引擎收集关于主题的信息

  • 趋势分析:趋势分析智能体分析研究结果,提取并排序关键趋势

  • 报告撰写:报告撰写智能体基于研究和分析结果撰写报告草稿

  • 校对优化:校对智能体优化报告的语法、格式和可读性

  • 完成:输出最终报告

每个步骤完成后,管理智能体决定下一步由哪个智能体执行任务,直到所有任务完成。

总结

本文展示了如何使用 LangChain 和 LangGraph 构建多智能体系统,通过 LangGraph 的状态图机制,我们可以清晰地定义智能体之间的协作关系和工作流程,同时保持系统状态的一致性和可追踪性。这种架构不仅适用于报告生成,还可以扩展到其他需要多智能体协作的复杂任务场景。

你可以根据实际需求进一步扩展这个系统,例如添加更多类型的智能体、增加更复杂的路由逻辑,或者集成更多的外部工具。

posted @ 2025-10-21 10:58  石头木  阅读(186)  评论(0)    收藏  举报