020-LangGraph Agent实现分析

目录

1. 案例目标

本案例展示了如何使用LangGraph构建一个集成网络搜索工具的智能代理(Agent),使其能够根据用户输入智能决定何时调用网络搜索工具,从而获取最新信息并提供更准确的回答。

主要目标包括:

  • 将网络搜索工具集成到大型语言模型(LLM)中
  • 实现条件路由,根据是否调用搜索工具来决定工作流程
  • 创建一个能够利用实时网络数据有效响应的聊天机器人

2. 技术栈与核心依赖

  • LangGraph: 用于构建有状态、多参与者应用程序的框架
  • LangChain: 提供LLM集成和工具调用能力
  • LangChain Community: 提供社区维护的工具和集成
  • TavilySearchResults: 用于网络搜索的工具
  • LangChain OpenTutorial: 教程包,包含设置API密钥的功能
  • ChatOpenAI: OpenAI的聊天模型接口
  • TypedDict: 用于定义状态结构

3. 环境配置

首先需要安装必要的依赖包:

%pip install langchain-opentutorial
from langchain_opentutorial import package

package.install(
    [
        "langchain_community",
        "langchain_openai",
        "langchain_core",
        "langgraph",
        "langsmith"
    ],
    verbose=False,
    upgrade=False,
)

然后设置环境变量:

from langchain_opentutorial import set_env

set_env(
    {
        "OPENAI_API_KEY": "your-openai-api-key",
        "TAVILY_API_KEY": "your-tavily-api-key",
        "LANGCHAIN_TRACING_V2": "true",
        "LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
        "LANGCHAIN_PROJECT": "Agent-with-LangGraph",
    }
)

这些密钥将用于访问OpenAI的语言模型和Tavily的搜索功能。

4. 案例实现

4.1 创建搜索工具

使用TavilySearchResults创建搜索工具:

from langchain_community.tools import TavilySearchResults

# 创建搜索工具
tool = TavilySearchResults(
    max_results=3,
    include_answer=True,
    include_raw_content=True,
    include_images=True,
)

4.2 定义状态

使用TypedDict定义状态结构,并使用add_messages函数管理消息历史:

from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages

# 定义状态模式
class State(TypedDict):
    # 对列表类型应用add_messages以启用消息添加
    messages: Annotated[list, add_messages]

4.3 初始化LLM并绑定工具

from langchain_openai import ChatOpenAI

# 初始化LLM
llm = ChatOpenAI(model="gpt-4o-mini")

# 将工具绑定到LLM
llm_with_tools = llm.bind_tools(tools)

4.4 定义节点函数

# 定义节点函数
def chatbot(state: State):
    # 使用提供的消息调用带工具的LLM
    answer = llm_with_tools.invoke(state["messages"])
    # 返回更新的消息(自动应用add_messages)
    return {"messages": [answer]}

4.5 创建工具节点

import json
from langchain_core.messages import ToolMessage

class BasicToolNode:
    """运行最后AIMessage节点中请求的工具"""

    def __init__(self, tools: list) -> None:
        # 工具列表
        self.tools_list = {tool.name: tool for tool in tools}

    def __call__(self, inputs: dict):
        # 如果消息存在,提取最新消息
        if messages := inputs.get("messages", []):
            message = messages[-1]
        else:
            raise ValueError("输入中未找到消息")

        # 工具调用的结果
        outputs = []
        for tool_call in message.tool_calls:
            # 调用工具并存储结果
            tool_result = self.tools_list[tool_call["name"]].invoke(tool_call["args"])
            outputs.append(
                # 将工具调用结果存储为消息
                ToolMessage(
                    content=json.dumps(
                        tool_result, ensure_ascii=False
                    ),  # 将工具调用结果转换为字符串
                    name=tool_call["name"],
                    tool_call_id=tool_call["id"],
                )
            )

        return {"messages": outputs}

# 创建工具节点
tool_node = BasicToolNode(tools=[tool])

4.6 创建图并添加节点

from langgraph.graph import StateGraph, START, END

# 使用定义的状态模式初始化状态图
graph_builder = StateGraph(State)

# 将聊天机器人节点添加到图中
graph_builder.add_node("chatbot", chatbot)

# 将工具节点添加到图中
graph_builder.add_node("tools", tool_node)

4.7 定义条件路由

# 定义路由函数
def route_tools(state: State):
    if messages := state.get("messages", []):
        # 提取最新的AI消息
        ai_message = messages[-1]
    else:
        # 如果没有找到消息,抛出错误
        raise ValueError(f"工具边缘的输入状态中未找到消息: {state}")

    # 检查AI消息中的工具调用
    if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0:
        # 如果有工具调用,路由到"tools"
        return "tools"
    # 如果没有工具调用,路由到"END"
    return END

# 向图中添加条件边
graph_builder.add_conditional_edges(
    source="chatbot",
    path=route_tools,
    # 将返回值映射到特定节点
    path_map={"tools": "tools", END: END},
)

# 定义额外的边
graph_builder.add_edge("tools", "chatbot")  # 工具执行后返回聊天机器人
graph_builder.add_edge(START, "chatbot")    # 从聊天机器人节点开始

# 编译图
graph = graph_builder.compile()

4.8 运行代理

inputs = {"messages": "Search for information about the TED YouTube channel"}

for event in graph.stream(inputs, stream_mode="values"):
    for key, value in event.items():
        print(f"\n==============\nSTEP: {key}\n==============\n")
        print(value[-1])

5. 案例效果

这个案例实现了一个能够智能决定何时使用搜索工具的聊天机器人。当用户询问关于TED YouTube频道的信息时,机器人会:

  1. 接收用户请求
  2. 分析请求并决定需要使用搜索工具
  3. 调用Tavily搜索API获取相关信息
  4. 处理搜索结果并生成回答
  5. 向用户提供包含最新信息的回答

通过条件路由,机器人能够智能地决定何时需要使用搜索工具,何时可以直接回答问题,从而提高了效率和准确性。

6. 案例实现思路

本案例的核心实现思路是利用LangGraph的工具集成和条件路由功能,构建一个能够根据输入内容智能决策的代理。

6.1 工具集成

通过bind_tools方法将搜索工具绑定到LLM,使LLM能够在需要时调用外部工具。这种绑定使得LLM能够根据输入内容智能决定是否需要调用工具,以及调用哪个工具。

6.2 条件路由

通过add_conditional_edges和自定义的路由函数,系统可以根据LLM的输出决定下一步执行路径。在这个案例中,系统检查LLM的输出是否包含工具调用,如果有则路由到工具节点,否则直接结束对话。

6.3 工具节点

通过自定义的BasicToolNode类,系统能够执行工具调用并将结果格式化为标准消息。这个节点负责解析工具调用、执行相应工具,并将结果返回给LLM进行进一步处理。

6.4 状态管理

通过使用TypedDict和add_messages函数,系统能够有效地管理对话状态。每次工具调用和LLM响应都会被添加到消息列表中,形成完整的对话历史。

7. 扩展建议

  • 多工具集成: 可以集成更多类型的工具,如数据库查询、API调用、文件操作等
  • 智能路由优化: 实现更复杂的路由逻辑,根据内容类型、用户意图等因素决定使用哪个工具
  • 工具链: 支持多个工具的链式调用,使一个工具的输出可以作为另一个工具的输入
  • 并行工具调用: 支持同时调用多个工具,提高效率
  • 工具缓存: 实现工具结果缓存,避免重复调用相同工具
  • 工具权限管理: 根据用户角色和权限限制可用工具
  • 工具使用统计: 记录和分析工具使用情况,用于优化代理性能

8. 总结

本案例展示了如何使用LangGraph构建一个集成网络搜索工具的智能代理。通过工具绑定、条件路由和自定义工具节点,我们创建了一个能够根据输入内容智能决策的聊天机器人。

通过这个案例,我们学习了:

  • 如何在LangGraph中集成外部工具
  • 如何使用条件路由实现智能决策
  • 如何创建自定义工具节点
  • 如何管理对话状态和消息流
  • 如何构建一个能够获取实时信息的智能代理

这种模式特别适用于需要访问实时数据或执行特定操作的应用场景,如信息检索、数据分析、任务执行等。通过结合LLM的推理能力和外部工具的执行能力,我们可以构建更加强大和实用的AI应用。

LangGraph的工具集成和条件路由功能为构建智能代理提供了强大的基础架构。这种架构使得AI应用能够根据输入内容智能地决定何时使用外部工具,从而扩展了AI系统的能力边界,使其能够处理更加复杂和多样化的任务。

### 使用 LangGraph Agent 创建或绘制折线图 LangGraph 是一种用于构建多代理系统的框架,它允许开发者通过多个代理(agents)协同工作来完成复杂任务。以下是关于如何使用 LangGraphAgent 来生成折线图的具体说明。 #### 1. 初始化检索 Agent 并调用大模型 当用户请求生成折线图时,首先会触发检索 Agent。此 Agent 调用大型语言模型 (LLM),分析输入数据并决定后续操作路径[^1]。这一步的核心目标是解析用户的意图以及所需的数据源。 ```python from langchain.agents import initialize_agent, Tool from langchain.llms import OpenAI llm = OpenAI(temperature=0) tools = [ # 定义工具列表... ] retrieval_agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True) result = retrieval_agent.run("Generate a line chart based on the given data.") ``` #### 2. 数据检索与传递 如果 LLM 判断需要进一步获取数据,则检索 Agent 将调用相应的检索工具以收集必要的信息,并将这些数据返回至原始 Agent 进行处理[^1]。这一过程通常涉及数据库查询或其他外部 API 请求。 #### 3. 图表生成逻辑 一旦数据准备就绪,流程会被导向负责图表生成的特定 Agent。该 Agent 同样依赖于 LLM 对接收到的信息进行评估,并最终选择合适的绘图库(如 Matplotlib 或 Plotly)实现可视化效果[^1]。 ```python import matplotlib.pyplot as plt def generate_line_chart(data): """ Generate and save a line chart from provided dataset. Parameters: data (dict): A dictionary containing 'x' values and corresponding 'y'. Returns: str: Path to saved image file of generated plot. """ x_values = list(map(str, range(len(data['y'])))) if not isinstance(data.get('x'), list) else data['x'] y_values = data['y'] plt.figure(figsize=(8, 6)) plt.plot(x_values, y_values, marker='o', linestyle='-') plt.title("Line Chart Example") plt.xlabel("X-Axis Label") plt.ylabel("Y-Axis Label") output_path = "./line_chart.png" plt.savefig(output_path) return output_path ``` 在此阶段,`generate_line_chart()` 函数接受结构化的字典作为参数,其中键分别为 `x` 和 `y` 表示坐标轴上的数值序列。函数内部利用 Python 中广泛使用的 Matplotlib 库渲染图形,并保存为本地文件形式以便后续展示或者分享给用户端查看[^1]。 #### 4. 结果反馈循环 生成完毕之后,图表生成 Agent 把成果连同任何附加元数据一并发回至上层调用者即初始检索 Agent 处理。此时后者再次激活其内置的大规模预训练神经网络组件重新审视当前状态是否满足终止条件——亦即是说整个作业链条已经圆满达成预期目的可以安全退出;否则将继续探索新的行动方向直至成功为止[^1]。 --- ### 总结 综上所述,在基于 LangGraph 构建的应用场景下制作一条简单的线条状统计图像大致遵循以上几个主要环节:启动搜索节点询问下一步动作指南→必要时候提取关联素材资源→切换到专门从事制图工作的子模块执行具体业务功能→最后回到起点确认整体进展状况进而做出适当安排决策。期间总计需至少四轮交互式对话机制驱动下的智能化运算支持才能顺利完成全部预定程序设定要求[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值