当前位置: 首页 > news >正文

【LangChain指南】Agents


第一部分:Agents 是什么?为什么需要它?

在开始编码之前,我们必须理解一个核心概念。

问题:大语言模型(LLM)本身有什么局限?
答案:LLM 本质上是一个“文本预测器”。它非常擅长根据输入生成连贯、有信息量的文本,但它不能主动执行操作,比如搜索网络、查询数据库或调用一个 Python 函数。

Agents 的作用
Agents 就是为了解决这个问题而生的。它是一个系统,利用 LLM 作为“大脑”或“推理引擎”,来决定:

  1. 需要采取什么行动? (例如,是调用“搜索工具”还是“计算器工具”?)
  2. 这个行动的输入参数是什么? (例如,搜索什么关键词?)
  3. 是否需要根据行动结果进行下一步?还是可以给出最终答案?

简单来说,Agents 让 LLM 从一个“只说不做”的聊天机器人,变成了一个“能思考、能动手”的智能助手。


第二部分:使用传统 AgentExecutor 构建代理

这是 LangChain 中最经典、最入门的代理构建方式。我们通过一个完整的例子来学习。

步骤 1: 环境准备与工具定义

首先,我们需要安装必要的库并定义代理可以使用的“工具”。

# 安装必要的库
# !pip install -U langchain langchain-openai langchain-community tavily-pythonimport getpass
import os
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults# 设置 API Keys
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")
os.environ["TAVILY_API_KEY"] = getpass.getpass("Enter your Tavily API Key: ")# 定义一个简单的自定义工具
@tool
def multiply(a: int, b: int) -> int:"""将两个整数相乘"""return a * b# 定义一个搜索工具
search = TavilySearchResults(max_results=2)# 将所有工具放入一个列表
tools = [multiply, search]# 初始化语言模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)
步骤 2: 创建代理 (Agent) 和执行器 (AgentExecutor)

代理负责“思考”,执行器负责“执行思考的结果并管理流程”。

from langchain import hub
from langchain.agents import create_tool_calling_agent, AgentExecutor# 从 LangChain Hub 拉取一个预设的、适合工具调用的提示词模板
# 这个模板告诉 LLM 如何思考、如何调用工具。
prompt = hub.pull("hwchase17/openai-functions-agent")# 创建代理 (Agent)
# 注意:这里传入的是原始的 llm,create_tool_calling_agent 会自动帮我们绑定工具。
agent = create_tool_calling_agent(llm, tools, prompt)# 创建代理执行器 (AgentExecutor)
# 它将代理和工具组合起来,形成一个可以运行的完整系统。
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # verbose=True 可以看到思考过程
步骤 3: 运行代理

现在,我们可以向代理提问了。

# 提问1: 一个不需要调用工具的简单问题
result = agent_executor.invoke({"input": "你好,今天过得怎么样?"})
print(result["output"])# 提问2: 一个需要调用自定义工具的问题
result = agent_executor.invoke({"input": "37乘以42等于多少?"})
print(result["output"])# 提问3: 一个需要调用搜索工具的问题
result = agent_executor.invoke({"input": "今天北京的天气怎么样?"})
print(result["output"])

AgentExecutor 的优点

  • 简单易用:几行代码就能快速搭建一个功能强大的代理。
  • 开箱即用:提供了预设的提示词和执行逻辑。

AgentExecutor 的缺点

  • 灵活性差:内部循环和状态管理是固定的,很难进行深度定制。
  • 调试困难:当逻辑复杂时,追踪每一步的状态变化比较麻烦。
  • 状态管理弱:虽然可以通过 RunnableWithMessageHistory 添加记忆,但本质上是附加的,不够原生。

第三部分:迁移到 LangGraph - 构建更强大的代理

为了解决 AgentExecutor 的局限性,LangChain 推出了 LangGraph。它不是一个简单的代理,而是一个基于图(Graph)的状态机,可以构建任意复杂的、多步骤的、有状态的工作流。

我们将学习如何将上面的 AgentExecutor 迁移到 LangGraph

步骤 1: 安装 LangGraph
# !pip install -U langgraph
步骤 2: 使用 create_react_agent 创建 LangGraph 代理

LangGraph 提供了 create_react_agent 这个预构建函数,可以让我们以几乎相同的代码量,获得一个功能更强大的代理。

from langgraph.prebuilt import create_react_agent# 创建 LangGraph 代理
# 注意:这里不需要传入 prompt,它有默认的 ReAct 提示词。
# 工具和模型的传入方式与之前相同。
graph_agent_executor = create_react_agent(llm, tools)# 运行代理
# 输入格式不同:需要传入一个包含 "messages" 键的字典,值是一个消息列表。
from langchain_core.messages import HumanMessagemessages = graph_agent_executor.invoke({"messages": [HumanMessage(content="37乘以42等于多少?")]
})# 输出是整个对话历史,最后一个消息是 AI 的最终回复
final_answer = messages["messages"][-1].content
print(final_answer)
步骤 3: LangGraph 的核心优势演示
优势 1: 原生、强大的状态管理

LangGraph 的核心是一个“状态图”。每次调用 .invoke(),它都会返回并更新整个对话历史。这使得多轮对话和上下文记忆变得极其自然。

# 第一轮对话
messages = graph_agent_executor.invoke({"messages": [HumanMessage(content="你好,我叫小明。")]
})# 第二轮对话,直接将上一轮的所有消息作为历史传入
messages = graph_agent_executor.invoke({"messages": messages["messages"] + [HumanMessage(content="我刚才告诉你我叫什么名字?")]
})final_answer = messages["messages"][-1].content
print(final_answer) # 输出应该包含 "小明"
优势 2: 高度灵活的提示词控制

AgentExecutor 中,我们通过修改 prompt 来控制 LLM 的行为。在 LangGraph 中,控制方式更加灵活。

from langchain_core.messages import SystemMessage# 方式一:传入一个字符串作为系统消息
system_message_str = "你是一个乐于助人的助手,请用中文回答所有问题。"
graph_agent_executor_v2 = create_react_agent(llm, tools, prompt=system_message_str)# 方式二:传入一个 SystemMessage 对象
system_message_obj = SystemMessage(content="你是一个乐于助人的助手,请用中文回答所有问题。")
graph_agent_executor_v3 = create_react_agent(llm, tools, prompt=system_message_obj)# 方式三:传入一个可调用对象 (Callable) 或 Runnable,进行更复杂的预处理
def custom_prompt_modifier(state):# state 是整个图的状态,我们可以对其进行任意修改# 例如,在开头加系统消息,在结尾加一个固定的用户消息modified_messages = [SystemMessage(content="你是一个乐于助人的助手,请用中文回答。"),*state["messages"], # 解包原有的消息列表HumanMessage(content="请在回答的最后加上 '谢谢!'")]return {"messages": modified_messages}graph_agent_executor_v4 = create_react_agent(llm, tools, prompt=custom_prompt_modifier)# 测试
messages = graph_agent_executor_v4.invoke({"messages": [HumanMessage(content="1+1等于几?")]
})
print(messages["messages"][-1].content) # 输出结尾应该有“谢谢!”
优势 3: 无限的可扩展性

create_react_agent 只是一个起点。LangGraph 允许你从零开始构建自己的图,定义节点(Nodes)、边(Edges)和状态(State),从而实现像“带审批流程的代理”、“多代理协作”等 AgentExecutor 无法实现的复杂逻辑。


总结与建议

  • 初学者/快速原型:如果你是刚接触 LangChain,或者需要快速搭建一个简单的代理原型,AgentExecutor 是非常好的起点。它简单、直接。
  • 生产环境/复杂应用:一旦你的项目需要更复杂的逻辑、更好的可调试性、更强大的状态管理或多代理协作,强烈建议迁移到 LangGraph。它代表了 LangChain 未来的方向,提供了无与伦比的灵活性和控制力。

记住,AgentExecutor 是“轮子”,而 LangGraph 是“造轮子的工厂”。学会 LangGraph,你将能构建出任何你想象得到的智能体工作流。

今天的课就到这里,大家课后可以动手实践一下这两种方式,感受它们的区别。下节课我们将深入 LangGraph 的底层,学习如何从零开始构建一个自定义的图。

http://www.dtcms.com/a/394992.html

相关文章:

  • Linux 的进程信号与中断的关系
  • IS-IS 协议中,是否在每个 L1/L2 设备上开启路由渗透
  • pycharm常用功能及快捷键
  • 滚珠导轨在半导体制造中如何实现高精度效率
  • 如何实现 5 μm 精度的视觉检测?不仅仅是相机的事
  • JavaScript学习笔记(六):运算符
  • Jenkins运维之路(制品上传)
  • 20届-高级开发(华为oD)-Java面经
  • 光流估计(可用于目标跟踪)
  • CANoe仿真报文CRC与Counter的完整实现指南:多种方法详解
  • sward入门到实战(4) - 如何编写Markdown文档
  • S32K146-LPUART+DMA方案实现
  • 【架构设计与优化】大模型多GPU协同方案:推理与微调场景下的硬件连接策略
  • 软件的安装python编程基础
  • Linux系统与运维
  • [Maven 基础课程]基于 IDEA 进行 Maven 构建
  • 一个基于 .NET 开源、简易、轻量级的进销存管理系统
  • 基于Flowlet的ARS(自适应路由切换)技术在RoCE网络负载均衡中的应用与优势
  • 计算机网络实验[番外篇]:MobaXterm连接Centos9的配置
  • Go语言实战案例-项目实战篇:实现一个词频分析系统
  • Grok 4 Fast vs GPT-5-mini:新一代高效AI模型开发者选型指南
  • LeetCode:47.从前序和中序遍历序列构造二叉树
  • MySQL安装避坑指南:从环境适配到故障修复的全场景实战手册
  • React教程(React入门教程)(React组件、JSX、React Props、React State、React事件处理、Hooks、高阶组件HOC)
  • 2025年CSP-S初赛真题及答案解析(完善程序第1题)
  • 六、页面优化
  • CVAT部署到虚拟机小记
  • scss基础学习
  • 基于衍射神经网络的光学高速粒子分类系统A1(未做完)
  • ffprobe安装与简单使用