langgraph_ipynb

agent_supervisor

这段代码是一个关于多智能体系统的示例,使用LangGraph库构建一个多代理监督者的框架。下面是对每个部分的详细讲解:

1. 介绍

这段代码介绍了一个多代理监督的示例,目的是通过一个大型语言模型(LLM)来协调多个代理的任务。通过使用一个监督者来分配任务,可以有效地管理代理之间的协作。

2. 安装必要的包和设置API密钥

%%capture --no-stderr
%pip install -U langgraph langchain langchain_openai langchain_experimental langsmith pandas

这段代码安装了所需的Python库,包括LangGraph、LangChain、OpenAI API等。%%capture用于捕获安装过程中的输出。

import getpass
import os

def _set_if_undefined(var: str):
    if not os.environ.get(var):
        os.environ[var] = getpass.getpass(f"Please provide your {var}")

_set_if_undefined("OPENAI_API_KEY")
_set_if_undefined("TAVILY_API_KEY")

这里定义了一个辅助函数_set_if_undefined,用于设置环境变量(API密钥),如果未设置的话,会提示用户输入。

3. 创建工具

from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_experimental.tools import PythonREPLTool

tavily_tool = TavilySearchResults(max_results=5)
python_repl_tool = PythonREPLTool()

在这里,创建了两个工具:

  • TavilySearchResults用于执行网页搜索。
  • PythonREPLTool用于执行Python代码(需要小心,因为这可能会执行任意代码)。

4. 辅助函数

from langchain_core.messages import HumanMessage

def agent_node(state, agent, name):
    result = agent.invoke(state)
    return {
        "messages": [HumanMessage(content=result["messages"][-1].content, name=name)]
    }

这个函数agent_node接收当前状态、代理和代理名称,调用代理并将其返回的最后一条消息格式化为人类可读的形式。

5. 创建代理监督者

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from pydantic import BaseModel
from typing import Literal

members = ["Researcher", "Coder"]
system_prompt = (
    "You are a supervisor tasked with managing a conversation between the"
    " following workers:  {members}. Given the following user request,"
    " respond with the worker to act next. Each worker will perform a"
    " task and respond with their results and status. When finished,"
    " respond with FINISH."
)

在这部分,定义了代理的成员和系统提示。这个提示告知监督者它需要管理哪个代理,并指示它在用户请求下选择下一个工作者。

options = ["FINISH"] + members

class routeResponse(BaseModel):
    next: Literal[*options]

定义了一个routeResponse类,用于描述监督者选择的下一个代理或结束的状态。

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        MessagesPlaceholder(variable_name="messages"),
        (
            "system",
            "Given the conversation above, who should act next?"
            " Or should we FINISH? Select one of: {options}",
        ),
    ]
).partial(options=str(options), members=", ".join(members))

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

def supervisor_agent(state):
    supervisor_chain = prompt | llm.with_structured_output(routeResponse)
    return supervisor_chain.invoke(state)

创建了一个聊天提示模板prompt,用于监督者选择下一个代理,并定义了supervisor_agent函数来处理这个逻辑。

6. 构建图

import functools
import operator
from typing import Sequence
from typing_extensions import TypedDict

from langchain_core.messages import BaseMessage

from langgraph.graph import END, StateGraph, START
from langgraph.prebuilt import create_react_agent

class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    next: str

research_agent = create_react_agent(llm, tools=[tavily_tool])
research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")

code_agent = create_react_agent(llm, tools=[python_repl_tool])
code_node = functools.partial(agent_node, agent=code_agent, name="Coder")

workflow = StateGraph(AgentState)
workflow.add_node("Researcher", research_node)
workflow.add_node("Coder", code_node)
workflow.add_node("supervisor", supervisor_agent)

这部分代码构建了一个状态图,定义了代理状态和节点。分别为“研究者”和“编码者”创建了节点,并添加到工作流中。

7. 连接图中的边

for member in members:
    workflow.add_edge(member, "supervisor")

conditional_map = {k: k for k in members}
conditional_map["FINISH"] = END
workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
workflow.add_edge(START, "supervisor")

graph = workflow.compile()

连接了各个节点,确保每个代理完成后都回到监督者,并定义了从监督者到各个代理或结束状态的条件边。最后,编译图。

8. 调用团队

for s in graph.stream(
    {
        "messages": [
            HumanMessage(content="Code hello world and print it to the terminal")
        ]
    }
):
    if "__end__" not in s:
        print(s)
        print("----")

for s in graph.stream(
    {"messages": [HumanMessage(content="Write a brief research report on pikas.")]},
    {"recursion_limit": 100},
):
    if "__end__" not in s:
        print(s)
        print("----")

最后,调用构建好的图,传入不同的消息以触发代理执行任务。结果将通过stream方法输出。

总结

这个代码示例展示了如何使用LangGraph和多个代理系统协同工作。通过创建一个监督者,能够有效地管理不同任务的执行和状态更新,展示了多智能体系统的强大和灵活性。

整体

当然可以!以下是将上述代码合并成一个完整的Python脚本,以便于整体理解:

# multi_agent_supervisor.py

# 安装必要的包(在运行时注释掉这部分,如果已安装)
# !pip install -U langgraph langchain langchain_openai langchain_experimental langsmith pandas

import getpass
import os
from typing import Annotated, Sequence
from typing_extensions import TypedDict
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_experimental.tools import PythonREPLTool
from langchain_core.messages import HumanMessage, BaseMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langgraph.graph import END, StateGraph, START
from langgraph.prebuilt import create_react_agent
from pydantic import BaseModel
import functools
import operator

# 设置API密钥
def _set_if_undefined(var: str):
    if not os.environ.get(var):
        os.environ[var] = getpass.getpass(f"Please provide your {var}")

_set_if_undefined("OPENAI_API_KEY")
_set_if_undefined("TAVILY_API_KEY")

# 创建工具
tavily_tool = TavilySearchResults(max_results=5)
python_repl_tool = PythonREPLTool()

# 定义辅助函数
def agent_node(state, agent, name):
    result = agent.invoke(state)
    return {
        "messages": [HumanMessage(content=result["messages"][-1].content, name=name)]
    }

# 创建代理监督者
members = ["Researcher", "Coder"]
system_prompt = (
    "You are a supervisor tasked with managing a conversation between the"
    " following workers: {members}. Given the following user request,"
    " respond with the worker to act next. Each worker will perform a"
    " task and respond with their results and status. When finished,"
    " respond with FINISH."
)

options = ["FINISH"] + members

class routeResponse(BaseModel):
    next: str

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        MessagesPlaceholder(variable_name="messages"),
        (
            "system",
            "Given the conversation above, who should act next?"
            " Or should we FINISH? Select one of: {options}",
        ),
    ]
).partial(options=str(options), members=", ".join(members))

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

def supervisor_agent(state):
    supervisor_chain = prompt | llm.with_structured_output(routeResponse)
    return supervisor_chain.invoke(state)

# 构建图
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    next: str

research_agent = create_react_agent(llm, tools=[tavily_tool])
research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")

code_agent = create_react_agent(llm, tools=[python_repl_tool])
code_node = functools.partial(agent_node, agent=code_agent, name="Coder")

workflow = StateGraph(AgentState)
workflow.add_node("Researcher", research_node)
workflow.add_node("Coder", code_node)
workflow.add_node("supervisor", supervisor_agent)

# 连接图中的边
for member in members:
    workflow.add_edge(member, "supervisor")

conditional_map = {k: k for k in members}
conditional_map["FINISH"] = END
workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
workflow.add_edge(START, "supervisor")

graph = workflow.compile()

# 调用团队
for s in graph.stream(
    {
        "messages": [
            HumanMessage(content="Code hello world and print it to the terminal")
        ]
    }
):
    if "__end__" not in s:
        print(s)
        print("----")

for s in graph.stream(
    {"messages": [HumanMessage(content="Write a brief research report on pikas.")]},
    {"recursion_limit": 100},
):
    if "__end__" not in s:
        print(s)
        print("----")

使用说明

  1. 安装依赖:确保在运行脚本之前安装所有必要的包。
  2. 设置API密钥:运行脚本时,系统会提示你输入OpenAI和Tavily的API密钥。
  3. 运行脚本:执行这个脚本,它会创建一个多智能体系统,并通过两个任务进行示例展示。

通过将代码合并为一个脚本,你可以更清晰地理解整个流程是如何工作的。

multi_agent_collaboration

下面我将详细讲解您提供的 LangGraph 入门文档,帮助您更快地理解和学习如何使用 LangGraph 创建多代理网络。

概述

这个笔记本(notebook)演示了如何使用 LangGraph 创建一个多代理(multi-agent)网络,以解决复杂任务。它借鉴了论文 AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation 的思想,通过让多个专门的代理协作,每个代理负责特定的任务或领域,从而实现“分而治之”的策略。

最终创建的图形结构如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

环境设置

首先,安装所需的 Python 包并设置 API 密钥。

%%capture --no-stderr
%pip install -U langchain langchain_openai langsmith pandas langchain_experimental matplotlib langgraph langchain_core

接下来,导入必要的库并设置环境变量(如 OpenAI 的 API 密钥)。

import getpass
import os

def _set_if_undefined(var: str):
    if not os.environ.get(var):
        os.environ[var] = getpass.getpass(f"Please provide your {var}")

_set_if_undefined("OPENAI_API_KEY")
_set_if_undefined("TAVILY_API_KEY")

设置 LangSmith(可选)

LangSmith 是一个用于 LangGraph 开发的调试、测试和监控工具,可以帮助您更快地发现问题并提高性能。如果需要,可以按照提示进行设置。

创建代理(Agents)

接下来,定义一些辅助函数来创建代理。这些代理将作为图中的节点。

创建 create_agent 函数

from langchain_core.messages import BaseMessage, HumanMessage, ToolMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langgraph.graph import END, StateGraph, START

def create_agent(llm, tools, system_message: str):
    """Create an agent."""
    prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                "You are a helpful AI assistant, collaborating with other assistants."
                " Use the provided tools to progress towards answering the question."
                " If you are unable to fully answer, that's OK, another assistant with different tools "
                " will help where you left off. Execute what you can to make progress."
                " If you or any of the other assistants have the final answer or deliverable,"
                " prefix your response with FINAL ANSWER so the team knows to stop."
                " You have access to the following tools: {tool_names}.\n{system_message}",
            ),
            MessagesPlaceholder(variable_name="messages"),
        ]
    )
    prompt = prompt.partial(system_message=system_message)
    prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
    return prompt | llm.bind_tools(tools)

这个函数用于创建一个代理(agent)。它接受以下参数:

  • llm:语言模型(如 GPT-4)。
  • tools:代理可用的工具列表。
  • system_message:系统消息,用于定义代理的行为。

函数的主要步骤:

  1. 创建一个 ChatPromptTemplate,其中包含系统消息和消息占位符。
  2. 使用 partial 方法将 system_messagetool_names 填入模板。
  3. 返回绑定了工具的代理。

定义工具(Tools)

接下来,定义一些代理将使用的工具。

from typing import Annotated
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tool
from langchain_experimental.utilities import PythonREPL

tavily_tool = TavilySearchResults(max_results=5)

# 警告:这将执行本地代码,在未沙箱的情况下可能不安全
repl = PythonREPL()

@tool
def python_repl(
    code: Annotated[str, "The python code to execute to generate your chart."],
):
    """Use this to execute python code. If you want to see the output of a value,
    you should print it out with `print(...)`. This is visible to the user."""
    try:
        result = repl.run(code)
    except BaseException as e:
        return f"Failed to execute. Error: {repr(e)}"
    result_str = f"Successfully executed:\n```python\n{code}\n```\nStdout: {result}"
    return (
        result_str + "\n\nIf you have completed all tasks, respond with FINAL ANSWER."
    )

这里定义了两个工具:

  1. tavily_tool:一个搜索工具,用于获取 Tavily 的搜索结果。
  2. python_repl:一个 Python 解释器工具,可以执行 Python 代码。这是一个自定义的工具,使用了 @tool 装饰器。

创建图(Graph)

现在,我们开始创建图形,将前面定义的代理和工具整合起来。

定义状态(State)

首先,定义图的状态。状态将包含消息列表,以及用于跟踪最近发送者的键。

import operator
from typing import Annotated, Sequence
from typing_extensions import TypedDict
from langchain_openai import ChatOpenAI

# 定义在图中传递的对象
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    sender: str

这里,AgentState 是一个字典类型,包含:

  • messages:消息的序列。
  • sender:最近发送消息的代理名称。

定义代理节点(Agent Nodes)

接下来,定义图中的代理节点。

import functools
from langchain_core.messages import AIMessage

# 辅助函数,用于为给定的代理创建节点
def agent_node(state, agent, name):
    result = agent.invoke(state)
    # 将代理输出转换为适合附加到全局状态的格式
    if isinstance(result, ToolMessage):
        pass
    else:
        result = AIMessage(**result.dict(exclude={"type", "name"}), name=name)
    return {
        "messages": [result],
        # 跟踪发送者,以便知道下一步将消息传递给谁
        "sender": name,
    }

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

# 创建研究代理和节点
research_agent = create_agent(
    llm,
    [tavily_tool],
    system_message="You should provide accurate data for the chart_generator to use.",
)
research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")

# 创建图表生成代理和节点
chart_agent = create_agent(
    llm,
    [python_repl],
    system_message="Any charts you display will be visible by the user.",
)
chart_node = functools.partial(agent_node, agent=chart_agent, name="chart_generator")

这里创建了两个代理:

  1. 研究代理(Researcher)

    • 使用 tavily_tool 作为工具。
    • 系统消息强调应为 chart_generator 提供准确的数据。
  2. 图表生成代理(chart_generator)

    • 使用 python_repl 作为工具。
    • 系统消息强调生成的任何图表都将对用户可见。

agent_node 函数用于创建代理节点,并包装了代理的调用逻辑。

定义工具节点(Tool Node)

定义一个节点来运行工具。

from langgraph.prebuilt import ToolNode

tools = [tavily_tool, python_repl]
tool_node = ToolNode(tools)

ToolNode 是一个预定义的节点,用于处理工具调用。

定义边缘逻辑(Edge Logic)

接下来,定义一些边缘逻辑,以根据代理的结果决定下一步的操作。

# 任何代理都可以决定结束
from typing import Literal

def router(state):
    # 路由器
    messages = state["messages"]
    last_message = messages[-1]
    if last_message.tool_calls:
        # 上一个代理正在调用工具
        return "call_tool"
    if "FINAL ANSWER" in last_message.content:
        # 任何代理决定工作已完成
        return END
    return "continue"

router 函数根据当前状态决定下一步操作:

  • 如果最后一条消息包含工具调用,则返回 "call_tool",表示需要调用工具。
  • 如果消息内容包含 "FINAL ANSWER",表示任务完成,返回 END
  • 否则,返回 "continue",继续下一个代理。

定义图(Graph)

现在,将所有部分组合起来,定义整个图。

from langgraph.graph import END, StateGraph, START

workflow = StateGraph(AgentState)

workflow.add_node("Researcher", research_node)
workflow.add_node("chart_generator", chart_node)
workflow.add_node("call_tool", tool_node)

workflow.add_conditional_edges(
    "Researcher",
    router,
    {"continue": "chart_generator", "call_tool": "call_tool", END: END},
)
workflow.add_conditional_edges(
    "chart_generator",
    router,
    {"continue": "Researcher", "call_tool": "call_tool", END: END},
)

workflow.add_conditional_edges(
    "call_tool",
    # 每个代理节点更新 'sender' 字段
    # 工具调用节点不更新,因此
    # 此边缘将路由回调用工具的原始代理
    lambda x: x["sender"],
    {
        "Researcher": "Researcher",
        "chart_generator": "chart_generator",
    },
)
workflow.add_edge(START, "Researcher")
graph = workflow.compile()

这个部分的主要步骤:

  1. 创建一个 StateGraph 实例,指定状态类型为 AgentState

  2. 添加节点:

    • "Researcher":对应研究代理。
    • "chart_generator":对应图表生成代理。
    • "call_tool":用于处理工具调用。
  3. 添加条件边(conditional edges):

    • "Researcher" 到下一个节点,依据 router 函数的返回值:
      • "continue":转到 "chart_generator"
      • "call_tool":转到 "call_tool"
      • END:结束。
    • "chart_generator" 到下一个节点,逻辑类似。
  4. 添加从 "call_tool" 返回的边:

    • 根据 sender 字段,返回到调用工具的代理("Researcher""chart_generator")。
  5. 添加开始节点 START,指向 "Researcher"

  6. 编译图。

可视化图(可选)

from IPython.display import Image, display

try:
    display(Image(graph.get_graph(xray=True).draw_mermaid_png()))
except Exception:
    # 这需要一些额外的依赖项,是可选的
    pass

如果您安装了必要的依赖项,可以生成图的可视化表示。

运行(Invoke)

现在,使用创建的图运行一个示例任务。

events = graph.stream(
    {
        "messages": [
            HumanMessage(
                content="Fetch the UK's GDP over the past 5 years,"
                " then draw a line graph of it."
                " Once you code it up, finish."
            )
        ],
    },
    # 最大步骤数
    {"recursion_limit": 150},
)
for s in events:
    print(s)
    print("----")

在这个示例中,我们向代理发送一个请求:

  • 获取过去 5 年英国的 GDP 数据。
  • 绘制一条折线图。
  • 编写代码完成后,结束任务。

代理的协作过程

  1. 初始消息:用户请求被传递给 "Researcher"

  2. 研究代理(Researcher)

    • 使用 tavily_tool 搜索并获取英国过去 5 年的 GDP 数据。
    • 将结果发送给 "chart_generator"
  3. 图表生成代理(chart_generator)

    • 接收数据,使用 python_repl 编写 Python 代码来绘制折线图。
    • 如果代码成功执行并生成图表,发送 "FINAL ANSWER",任务结束。
  4. 工具调用

    • 如果代理调用了工具,"call_tool" 节点将处理工具的执行。
    • 执行完工具后,返回结果给调用工具的代理。

总结

通过这个示例,您学习了如何使用 LangGraph 创建一个多代理网络,让多个专门的代理协作完成复杂任务。主要步骤包括:

  • 定义代理和工具。
  • 创建图的状态和节点。
  • 定义代理之间的边缘逻辑。
  • 编译并运行图。

希望这能帮助您更快地理解 LangGraph 的使用方法。如果您有任何疑问,欢迎提问!

汇总

好的,我将把您提供的代码整合到一个 py 文件中,以便于整体理解。同时,我会将提示词(Prompt)翻译成中文,并按照您提供的方式使用大模型 ChatTongyi

以下是完整的代码:

# multi_agent_network.py

# 导入必要的模块
import os
import functools
import operator
from typing import Annotated, Sequence
from typing_extensions import TypedDict
from dotenv import load_dotenv

# 从 LangChain 和 LangGraph 导入所需的类和函数
from langchain_core.messages import (
    BaseMessage,
    HumanMessage,
    ToolMessage,
    AIMessage,
)
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langgraph.graph import END, StateGraph, START
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tool
from langchain_experimental.utilities import PythonREPL
from langgraph.prebuilt import ToolNode

# 导入 ChatTongyi 模型
from langchain_community.chat_models.tongyi import ChatTongyi

# 加载 .env 文件
load_dotenv()

# 读取环境变量
api_key = os.getenv("DASHSCOPE_API_KEY")

if not api_key:
    raise ValueError("API Key not found in .env file.")

# 初始化 LLM(ChatTongyi)
llm = ChatTongyi(model='qwen-plus')

# 定义 create_agent 函数,用于创建代理
def create_agent(llm, tools, system_message: str):
    """创建一个代理。"""
    prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                "你是一个有帮助的 AI 助手,正在与其他助手协作。"
                "使用提供的工具来推进回答问题。"
                "如果你无法完全回答,也没关系,另一个具有不同工具的助手会接手你留下的部分。"
                "尽你所能执行任务以取得进展。"
                "如果你或任何其他助手已经有了最终答案或可交付成果,请在你的回复前加上 '最终答案',以便团队知道停止。"
                "你可以使用以下工具:{tool_names}。\n{system_message}",
            ),
            MessagesPlaceholder(variable_name="messages"),
        ]
    )
    prompt = prompt.partial(system_message=system_message)
    prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
    return prompt | llm.bind_tools(tools)

# 定义工具
tavily_tool = TavilySearchResults(max_results=5)

# 警告:这将执行本地代码,在未沙箱的情况下可能不安全
repl = PythonREPL()

@tool
def python_repl(
    code: Annotated[str, "生成图表所需执行的 Python 代码。"],
):
    """使用此工具来执行 Python 代码。如果你想查看某个值的输出,你应该使用 `print(...)`。这将对用户可见。"""
    try:
        result = repl.run(code)
    except BaseException as e:
        return f"执行失败。错误:{repr(e)}"
    result_str = f"成功执行:\n```python\n{code}\n```\n标准输出:{result}"
    return (
        result_str + "\n\n如果你已完成所有任务,请回复 '最终答案'。"
    )

# 定义状态类
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    sender: str

# 定义代理节点
def agent_node(state, agent, name):
    result = agent.invoke(state)
    # 将代理输出转换为适合附加到全局状态的格式
    if isinstance(result, ToolMessage):
        pass
    else:
        result = AIMessage(**result.dict(exclude={"type", "name"}), name=name)
    return {
        "messages": [result],
        # 跟踪发送者,以便知道下一步将消息传递给谁
        "sender": name,
    }

# 创建研究代理和节点
research_agent = create_agent(
    llm,
    [tavily_tool],
    system_message="你应该为 chart_generator 提供准确的数据。",
)
research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")

# 创建图表生成代理和节点
chart_agent = create_agent(
    llm,
    [python_repl],
    system_message="你展示的任何图表都会被用户看到。",
)
chart_node = functools.partial(agent_node, agent=chart_agent, name="chart_generator")

# 定义工具节点
tools = [tavily_tool, python_repl]
tool_node = ToolNode(tools)

# 定义路由逻辑
def router(state):
    # 路由器
    messages = state["messages"]
    last_message = messages[-1]
    if last_message.tool_calls:
        # 上一个代理正在调用工具
        return "call_tool"
    if "最终答案" in last_message.content:
        # 任何代理决定工作已完成
        return END
    return "continue"

# 创建工作流程图
workflow = StateGraph(AgentState)

workflow.add_node("Researcher", research_node)
workflow.add_node("chart_generator", chart_node)
workflow.add_node("call_tool", tool_node)

workflow.add_conditional_edges(
    "Researcher",
    router,
    {"continue": "chart_generator", "call_tool": "call_tool", END: END},
)
workflow.add_conditional_edges(
    "chart_generator",
    router,
    {"continue": "Researcher", "call_tool": "call_tool", END: END},
)

workflow.add_conditional_edges(
    "call_tool",
    # 每个代理节点更新 'sender' 字段
    # 工具调用节点不更新,这意味着
    # 此边缘将路由回调用工具的原始代理
    lambda x: x["sender"],
    {
        "Researcher": "Researcher",
        "chart_generator": "chart_generator",
    },
)
workflow.add_edge(START, "Researcher")
graph = workflow.compile()

# 运行流程
if __name__ == "__main__":
    events = graph.stream(
        {
            "messages": [
                HumanMessage(
                    content="获取过去 5 年英国的 GDP 数据,然后绘制一条折线图。一旦你编写完代码,结束任务。"
                )
            ],
        },
        # 最大递归深度
        {"recursion_limit": 150},
    )
    for s in events:
        print(s)
        print("----")

请将上述代码保存为 multi_agent_network.py

代码说明

  • 导入模块:首先,我们导入了所有必要的模块和库,包括 dotenvlangchain_corelanggraph 等。

  • 加载环境变量并初始化 LLM:使用 dotenv 加载环境变量,并初始化 ChatTongyi 模型作为 LLM。

  • 定义代理和工具

    • create_agent 函数:用于创建代理,并将提示词翻译成中文。
    • 工具:包括 tavily_tool(用于搜索数据)和 python_repl(用于执行 Python 代码)。我们也将这些工具的提示信息翻译成了中文。
  • 定义状态和节点

    • AgentState:定义了代理的状态,包括消息和发送者。
    • 代理节点research_nodechart_node,分别对应研究代理和图表生成代理。
  • 定义路由逻辑和工作流程图

    • router 函数:用于决定下一步的操作。
    • 工作流程图:使用 StateGraph 创建,并添加了节点和条件边。
  • 运行流程

    • if __name__ == "__main__": 块中,我们启动了图的执行,向代理发送了一个中文的请求。

运行代码

确保您已经安装了所有必要的依赖项,并在 .env 文件中设置了 DASHSCOPE_API_KEY 环境变量。

在终端中运行以下命令:

python multi_agent_network.py

注意事项

  • 模型兼容性:请注意,ChatTongyi 模型可能与 ChatOpenAI 的接口略有不同。如果在运行过程中遇到接口兼容性问题,可能需要根据 ChatTongyi 的官方文档调整代码。

  • 工具的使用python_repl 工具执行本地 Python 代码,可能存在安全风险。在实际应用中,应确保代码的安全性或使用沙箱环境。

  • 环境变量:确保您的 .env 文件中包含正确的 DASHSCOPE_API_KEY,以便成功调用 ChatTongyi 模型。

希望这份代码能够帮助您更好地理解如何使用 LangGraph 创建多代理网络。如果您有任何疑问,欢迎提问!

出现 `ImportError: cannot import name 'RedisSaver' from 'langgraph.checkpoint' (unknown location)` 以及 `ModuleNotFoundError: No module named 'langgraph_checkpoint_redis'` 错误,可能是由于多种原因导致的,以下是一些解决办法: ### 检查库安装情况 确保 `langgraph` 库已正确安装,且版本支持 `RedisSaver`。可使用以下命令安装或更新: ```bash pip install --upgrade langgraph ``` ### 检查模块路径 Python 可能找不到 `langgraph` 模块的位置。可通过以下 Python 代码检查 `sys.path` 中是否包含 `langgraph` 所在路径: ```python import sys print(sys.path) ``` 若不在其中,可将其添加到 `sys.path` 中: ```python import sys sys.path.append('/path/to/langgraph') ``` 需将 `/path/to/langgraph` 替换为 `langgraph` 实际所在路径。 ### 检查模块内容 确认 `langgraph.checkpoint` 模块中确实定义了 `RedisSaver`。可在 Python 交互式环境中查看模块内容: ```python import langgraph.checkpoint print(dir(langgraph.checkpoint)) ``` 若 `RedisSaver` 不在输出列表中,可能是库版本不支持或模块内容有问题。 ### 检查拼写和大小写 确保导入时 `RedisSaver` 的拼写和大小写正确,Python 区分大小写,拼写错误会导致导入失败。 ### 重新安装依赖 依赖库可能损坏或不兼容,可尝试卸载并重新安装 `langgraph` 及其依赖: ```bash pip uninstall langgraph pip install langgraph ``` ### 检查环境 若使用虚拟环境,需确保虚拟环境已激活,且所有安装操作都在该环境中进行。 ### 检查导入路径 根据引用,`RedisSaver` 类的完整路径可能是 `langgraph.checkpoint.redis.RedisSaver`,可尝试使用此路径导入: ```python from langgraph.checkpoint.redis import RedisSaver ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值