尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

从零构建AI智能体:基于LangChain与LangGraph的ReAct实战指南

从零构建AI智能体:基于LangChain与LangGraph的ReAct实战指南 最近在技术社区和招聘网站上AI Agent智能体开发的热度持续攀升。很多开发者无论是刚入行的新手还是希望转型的程序员都对这个领域充满好奇但面对海量的概念、框架和工具往往感到无从下手Agent到底是什么它和传统程序有什么区别如何从零开始搭建一个能实际运行的Agent更重要的是如何通过系统性的项目实践真正掌握这项技能并将其转化为职业竞争力本文旨在解决这些痛点。我将为你梳理一条清晰的AI Agent开发学习路径并提供一个从零到一的完整实战项目。通过这个项目你将不仅理解Agent的核心概念更能亲手搭建一个具备规划、执行和反思能力的智能体掌握主流的开发框架和工具链。无论你是想入门AI应用开发还是寻求职业转型这篇手把手的教程都将为你提供扎实的起点。1. AI Agent 核心概念与价值在深入代码之前我们必须先厘清几个核心概念这有助于理解我们正在构建的是什么以及为什么需要以新的范式来思考。1.1 什么是 AI Agent简单来说一个AI Agent智能体是一个能够感知环境、自主决策并执行行动以实现特定目标的软件实体。它不同于传统的“输入-输出”式程序其核心特征在于自主性。你可以把它想象成一个虚拟的“数字员工”。例如一个数据分析Agent你只需要告诉它“帮我分析上个月的销售数据找出异常并给出建议”它就会自主完成数据获取、清洗、分析、生成报告等一系列步骤并在遇到问题时比如数据格式不对尝试不同的解决方法。1.2 Agent 与传统程序及RPA的区别为了避免混淆我们通过一个表格来对比特性传统程序 / 脚本RPA (机器人流程自动化)AI Agent (智能体)核心预定义的、确定的逻辑流。模拟人类在UI界面的操作遵循固定规则。大模型驱动的推理、规划和决策。灵活性低。输入和流程必须严格匹配预设条件。中。流程固定但可处理一定程度的界面变化。高。能理解模糊的自然语言指令动态规划步骤。处理不确定性无法处理。遇到未预见的输入会报错或崩溃。较差。界面元素变化可能导致流程失败。强。能尝试不同策略具备一定的容错和反思能力。开发范式过程式/面向对象编程代码控制一切。录制/配置自动化流程。提示工程 (Prompt Engineering) 工具调用 (Tool Calling) 工作流编排。示例一个计算税费的函数。自动登录系统下载报表填入Excel。根据“优化客服效率”的目标自主决定何时、如何调用知识库、工单系统、生成回复模板。关键洞察Agent的核心驱动力是大语言模型(LLM)。LLM为Agent提供了理解、推理和生成能力使其能够处理非结构化的自然语言指令并动态地规划任务。1.3 为什么Agent是下一个技术焦点自然交互降低软件使用门槛用户可以用最自然的方式表达需求。处理复杂任务能够将模糊的、多步骤的高级目标拆解为具体的可执行动作序列。自动化新高度超越基于固定规则的RPA实现更智能、更适应变化的业务流程自动化。新的应用形态催生个人AI助手、智能客服、自动编程、AI研究员等全新应用。理解了“为什么”之后我们就可以开始着手“怎么做”了。接下来我们将从环境搭建开始一步步构建我们的第一个智能体。2. 环境准备与核心工具栈工欲善其事必先利其器。现代AI Agent开发已经形成了相对稳定的工具生态。我们将选择目前最主流、社区最活跃的框架进行实战。2.1 基础环境要求操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04)。本文示例将在 macOS/Linux 环境下进行Windows 用户建议使用 WSL2 以获得最佳体验。Python版本 3.10 或 3.11。这是大多数AI框架的推荐版本。包管理工具pip(Python自带) 或conda(推荐用于管理复杂的Python环境)。代码编辑器VS Code (推荐) 或 PyCharm。2.2 核心框架与库介绍我们将使用LangChain和LangGraph作为本次实战的核心框架。LangChain: 一个用于构建由LLM驱动的应用程序的框架。它提供了连接LLM、数据文档、数据库、工具API、函数以及记忆对话历史的标准接口和组件。它是构建Agent的“脚手架”。LangGraph: 建立在LangChain之上用于构建有状态、多参与者Agent工作流的库。它特别擅长描述复杂的循环、分支和协作流程是构建高级Agent的“大脑皮层”。为什么选择这个组合LangChain提供了构建Agent所需的基础模块如工具、记忆、链而LangGraph则提供了以“图”的形式来编排这些模块的能力使得构建具备规划、执行、反思循环的复杂Agent变得直观和可控。这与网络热词中提到的“新版langchain langgraph mcp 的智能体和工作流开发”趋势完全吻合。2.3 项目初始化与环境搭建首先我们创建一个干净的项目环境。# 1. 创建项目目录并进入 mkdir ai-agent-tutorial cd ai-agent-tutorial # 2. 创建并激活虚拟环境 (使用 venv) python -m venv venv # 在 macOS/Linux 上激活 source venv/bin/activate # 在 Windows 上激活 # venv\Scripts\activate # 3. 升级 pip pip install --upgrade pip # 4. 安装核心依赖 pip install langchain langchain-community langgraph langchain-openai安装说明langchain: LangChain 核心库。langchain-community: 社区维护的第三方集成如各种工具、模型。langgraph: LangGraph 工作流库。langchain-openai: LangChain 对 OpenAI 模型的官方集成。2.4 配置大模型访问密钥Agent的核心是LLM。我们将使用 OpenAI 的 GPT 模型作为“大脑”。你需要一个 OpenAI API Key。访问 OpenAI Platform 并登录。点击右上角个人头像选择 “View API keys”。点击 “Create new secret key” 创建一个新的密钥并妥善保存。安全提示切勿将API Key直接硬编码在代码中或提交到版本控制系统如Git。我们将通过环境变量来管理密钥# 在 macOS/Linux 的终端中 export OPENAI_API_KEY你的-api-key-here # 在 Windows 的 CMD 中 # set OPENAI_API_KEY你的-api-key-here # 在 Windows 的 PowerShell 中 # $env:OPENAI_API_KEY你的-api-key-here为了代码的可移植性我们也可以在项目根目录创建一个.env文件确保该文件在.gitignore中# .env 文件内容 OPENAI_API_KEY你的-api-key-here然后在Python代码中使用python-dotenv库来加载pip install python-dotenv环境准备就绪现在让我们进入核心部分理解并构建一个Agent的基本单元。3. Agent 核心组件拆解工具、记忆与规划一个功能完整的Agent通常由多个核心组件协同工作。理解这些组件是进行开发的基础。3.1 工具 (Tools)Agent 的“手和脚”工具是Agent与外部世界交互的接口。它可以是一个函数、一个API调用或者任何一段可执行的代码。定义工具示例我们创建一个简单的计算器和网络搜索工具。# tools.py import requests from langchain.tools import tool from math import sqrt, log10 tool def calculator(expression: str) - str: 执行数学计算。支持加减乘除(,-,*,/)、乘方(**)、开方(sqrt)、对数(log10)等。 例如calculator(\3 5 * 2\) calculator(\sqrt(16)\) # 警告使用eval存在安全风险仅用于演示。生产环境应使用安全表达式解析器如asteval。 try: # 为安全起见限制可用的内置函数和属性 allowed_names {sqrt: sqrt, log10: log10} result eval(expression, {__builtins__: {}}, allowed_names) return f计算结果: {result} except Exception as e: return f计算错误: {e} tool def search_web(query: str) - str: 使用 DuckDuckGo 即时答案进行网络搜索。 # 注意这是一个简化的示例。实际应用中可能需要更复杂的处理如使用SerpAPI等。 try: url fhttps://api.duckduckgo.com/ params { q: query, format: json, no_html: 1, skip_disambig: 1 } response requests.get(url, paramsparams, timeout10) data response.json() # 提取摘要信息 abstract data.get(AbstractText, ) if abstract: return f搜索摘要: {abstract[:300]}... # 截断以避免过长 else: return 未找到相关摘要信息。 except Exception as e: return f网络搜索失败: {e} # 工具列表方便后续使用 ALL_TOOLS [calculator, search_web]关键点使用tool装饰器将普通函数转换为LangChain可识别的工具。工具必须有清晰的文档字符串docstringLLM会据此决定何时以及如何使用该工具。安全警告示例中的calculator使用了eval这在生产环境中是极度危险的因为它允许执行任意代码。此处仅用于演示简单原理真实项目必须使用安全的数学表达式库如asteval、numexpr或沙箱环境。3.2 记忆 (Memory)Agent 的“经历”记忆使Agent能够记住之前的交互从而进行连贯的对话或执行多轮任务。# memory.py from langchain.memory import ConversationBufferMemory from langchain.schema import BaseMessage, HumanMessage, AIMessage # 创建一个简单的对话记忆 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 模拟一次对话 memory.chat_memory.add_user_message(今天的天气怎么样) memory.chat_memory.add_ai_message(根据搜索今天北京晴15-25°C。) # 加载记忆变量 memory_variables memory.load_memory_variables({}) print(memory_variables[chat_history]) # 输出: [HumanMessage(content今天的天气怎么样), AIMessage(content根据搜索今天北京晴15-25°C。)]在复杂的Agent中记忆可能包括短期记忆/对话历史如上例。长期记忆/向量存储将历史信息嵌入并存入向量数据库供后续检索。实体记忆专门记忆对话中提到的关键实体如人名、地点、偏好。3.3 规划与执行循环ReAct 模式这是Agent的“思考”过程。最经典的范式是ReAct (Reason Act)。Reason (思考)LLM分析当前状态目标、记忆、可用工具决定下一步该做什么。Act (行动)执行选定的工具并获取结果。观察 (Observe)将工具执行结果作为新的输入进入下一轮思考。循环以上步骤直到任务完成或达到最大步数。LangGraph 完美地支持了这种循环结构的建模。接下来我们就用 LangGraph 来构建一个具备 ReAct 能力的智能体。4. 实战构建一个具备规划能力的 ReAct 智能体我们将构建一个“研究助手”Agent。它的任务是根据用户提出的复杂问题自主规划步骤利用计算器和网络搜索工具来寻找答案。4.1 定义 Agent 状态与模型首先我们需要定义Agent工作流中流转的“状态”。状态是一个字典包含了工作流每一步都需要知道的信息。# agent_graph.py from typing import TypedDict, Annotated, List, Union from langgraph.graph.message import add_messages import operator # 1. 定义状态结构 class AgentState(TypedDict): # 消息历史LangGraph 提供了便捷的注解来管理 messages: Annotated[List[Union[HumanMessage, AIMessage, ToolMessage]], add_messages] # 用户最初提出的问题 original_input: str # 当前步骤的中间思考可选用于调试 reasoning: str # 已完成的步骤列表可选用于跟踪进度 steps_completed: List[str] # 注意这里先定义类型HumanMessage等需要在导入后使用 from langchain_core.messages import HumanMessage, AIMessage, ToolMessage4.2 创建工具调用节点我们需要一个函数让LLM根据当前状态决定是回答问题还是调用工具。# agent_graph.py (续) from langchain_openai import ChatOpenAI from langchain.tools.render import render_text_description from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser # 2. 初始化LLM llm ChatOpenAI(modelgpt-4o-mini, temperature0) # 使用成本较低的 gpt-4o-mini温度设为0使输出更确定 # 3. 绑定工具到LLM # 将我们之前定义的工具列表转换为LLM能识别的格式 tools ALL_TOOLS # 从 tools.py 导入 llm_with_tools llm.bind_tools(tools) # 4. 创建提示词模板 prompt ChatPromptTemplate.from_messages([ (system, 你是一个强大的研究助手。你的任务是逐步思考解决用户的问题。 你可以使用以下工具 {tools} 请遵循以下规则 1. 仔细分析用户的问题。 2. 如果需要计算或查询外部信息请调用相应的工具。 3. 每次只调用一个工具。 4. 根据工具返回的结果决定下一步是继续调用工具还是给出最终答案。 5. 当你拥有足够的信息来完整、准确地回答用户的问题时请直接给出最终答案不要再调用工具。 当前对话历史 {chat_history}), MessagesPlaceholder(variable_namemessages), # 这里会填入最新的用户消息 ]) # 5. 构建“代理”执行链 # 这个链将组合提示词 - 调用带工具的LLM - 解析输出是调用工具还是直接回答 agent_chain ( { tools: lambda _: render_text_description(tools), # 将工具描述文本化 chat_history: lambda state: state[messages][:-1] if len(state[messages]) 1 else [], # 历史消息是除最新一条外的所有消息 messages: lambda state: [state[messages][-1]] if state[messages] else [], # 最新一条消息 } | prompt | llm_with_tools | OpenAIToolsAgentOutputParser() # 关键解析LLM输出判断是 ToolCall 还是 AIMessage )4.3 构建 LangGraph 工作流现在我们将各个节点函数组合成一个有向图。# agent_graph.py (续) from langgraph.graph import StateGraph, END from langgraph.prebuilt import ToolExecutor # 6. 创建工具执行器 tool_executor ToolExecutor(tools) # 7. 定义图节点函数 def run_agent(state: AgentState): 代理节点让LLM思考并决定下一步行动。 print(f\n[Agent 思考中...]) agent_output agent_chain.invoke(state) # 输出可能是 AIMessage直接回答或包含 ToolCall 的 AIMessage return {messages: [agent_output]} def execute_tools(state: AgentState): 工具执行节点执行LLM要求的工具调用。 last_message state[messages][-1] tool_calls last_message.tool_calls # 获取LLM要求调用的工具列表 results [] for tool_call in tool_calls: print(f[执行工具] {tool_call[name]} 参数: {tool_call[args]}) # 执行工具 result tool_executor.invoke(tool_call) # 将结果封装为 ToolMessage results.append(ToolMessage(contentstr(result), tool_call_idtool_call[id], nametool_call[name])) return {messages: results} # 8. 构建图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(agent, run_agent) workflow.add_node(action, execute_tools) # 设置入口点 workflow.set_entry_point(agent) # 定义边路由逻辑 from langgraph.graph import START def route_after_agent(state: AgentState): 根据agent节点的输出决定下一步是去执行工具还是结束。 last_message state[messages][-1] if last_message.tool_calls: # 如果LLM决定调用工具则前往“action”节点 print(f[决策] 需要调用工具转向执行。) return action else: # 如果LLM直接给出了最终答案则结束工作流 print(f[决策] 给出最终答案工作流结束。) return END def route_after_action(state: AgentState): 工具执行完毕后总是返回agent节点进行下一轮思考。 print(f[决策] 工具执行完毕返回Agent进行下一步思考。) return agent # 添加条件边和普通边 workflow.add_conditional_edges( agent, route_after_agent, { action: action, END: END } ) workflow.add_edge(action, agent) # 编译图 app workflow.compile()4.4 运行与测试智能体让我们用几个复杂问题来测试这个智能体。# run_agent.py from agent_graph import app, AgentState from langchain_core.messages import HumanMessage def run_research_assistant(question: str): 运行研究助手Agent print(f\n{*50}) print(f用户问题: {question}) print(f{*50}) # 初始化状态 initial_state: AgentState { messages: [HumanMessage(contentquestion)], original_input: question, reasoning: , steps_completed: [] } # 运行图 final_state app.invoke(initial_state, config{recursion_limit: 10}) # 限制递归深度防止无限循环 # 打印最终答案 print(f\n{*50}) print(最终答案:) for msg in final_state[messages]: if isinstance(msg, AIMessage) and not msg.tool_calls: print(msg.content) print(f{*50}) if __name__ __main__: # 测试用例1需要计算和搜索的复杂问题 question1 请先计算光在真空中的速度约3e8 m/s的平方然后搜索爱因斯坦的质能方程并用这个方程计算与刚才计算结果等效的能量对应的质量是多少 run_research_assistant(question1) # 测试用例2纯信息查询 question2 LangChain 和 LangGraph 的主要区别是什么 run_research_assistant(question2) # 测试用例3多步骤计算 question3 一个圆的半径是5厘米请先计算它的面积再计算周长的平方。 run_research_assistant(question3)预期运行流程以问题1为例Agent节点接收问题。LLM分析后发现需要先计算(3e8)**2于是决定调用calculator工具。路由到action节点执行计算得到结果9e16。返回agent节点LLM结合计算结果决定调用search_web工具搜索“爱因斯坦质能方程”。执行搜索得到方程Emc^2。返回agent节点LLM意识到需要利用方程m E/c^2且E9e16,c3e8于是再次调用calculator计算9e16 / (3e8)**2。执行计算得到结果1。返回agent节点LLM拥有所有必要信息合成最终答案“光速平方为9e16 (m^2/s^2)。根据质能方程Emc^2等效质量m E/c^2 9e16 / 9e16 1 千克。”由于本次输出没有工具调用工作流结束。通过这个实战项目你已经构建了一个具备自主规划、工具调用和循环推理能力的智能体原型。这涵盖了Agent开发最核心的流程。5. 进阶主题与最佳实践掌握了基础构建后要开发出健壮、可用的Agent还需要关注以下方面。5.1 错误处理与鲁棒性一个真实的Agent必须能处理各种异常。# advanced_agent.py - 错误处理示例 from typing import Any import traceback def safe_tool_executor(tool_name: str, tool_args: dict) - dict: 一个安全的工具执行包装器 try: # 根据 tool_name 找到对应的工具函数并执行 # ... 执行逻辑 ... result some_tool(**tool_args) return {status: success, content: result} except Exception as e: error_info traceback.format_exc() # 将错误信息结构化返回供LLM分析 return { status: error, error_type: e.__class__.__name__, message: str(e), traceback: error_info[:500] # 截断过长的堆栈 } # 在提示词中指导LLM处理错误 error_handling_prompt 如果工具调用返回错误请分析错误原因 1. 如果是参数错误请调整参数后重试。 2. 如果是网络或服务暂时不可用可以等待后重试或尝试替代方案。 3. 如果错误无法解决请向用户诚实说明情况并给出已获得的部分信息。 错误信息{error_detail} 请根据以上信息决定下一步行动。 5.2 记忆优化与检索对于长对话或需要背景知识的任务简单的ConversationBufferMemory可能不够。# 使用向量存储实现长期记忆 from langchain_community.vectorstores import Chroma from langchain_openai import OpenAIEmbeddings from langchain.memory import VectorStoreRetrieverMemory from langchain.docstore import InMemoryDocstore import faiss import numpy as np # 创建向量存储 embedding_function OpenAIEmbeddings() index faiss.IndexFlatL2(1536) # OpenAI 嵌入的维度 vectorstore Chroma( embedding_functionembedding_function, indexindex, docstoreInMemoryDocstore(), index_to_docstore_id{}, ) # 创建基于向量检索的记忆 retriever vectorstore.as_retriever(search_kwargsdict(k5)) memory VectorStoreRetrieverMemory(retrieverretriever) # 使用方式将重要的对话片段或事实存入记忆 memory.save_context({input: 我的名字叫张三}, {output: 好的张三我记住了。}) # 在需要时检索相关记忆 relevant_memories memory.load_memory_variables({prompt: 用户是谁}) print(relevant_memories)5.3 性能优化与成本控制使用大模型API会产生费用且调用速度较慢。设置超时与重试为工具调用和模型调用配置合理的超时和重试机制。缓存对频繁且结果不变的查询如某些计算、静态知识查询使用缓存。流式输出对于生成长文本的Agent使用流式输出以提升用户体验。选择合适模型简单的分类、路由任务使用轻量级模型如gpt-3.5-turbo复杂的推理再使用gpt-4系列。限制步数在app.invoke中设置recursion_limit防止Agent陷入无限循环。5.4 生产环境部署考量API密钥管理使用环境变量或专业的密钥管理服务如AWS Secrets Manager, HashiCorp Vault。日志与监控详细记录Agent的决策过程、工具调用和结果便于调试和优化。版本控制对Agent的提示词、工具定义、工作流图进行版本控制。可观测性集成 tracing如 LangSmith来可视化和分析Agent的每一步执行。安全工具权限为Agent配置最小必要权限的工具。输入输出过滤对用户输入和模型输出进行内容安全过滤。沙箱环境对于执行代码的工具必须在安全的沙箱环境中运行。6. 常见问题与排查指南在开发过程中你可能会遇到以下典型问题。问题现象可能原因排查步骤与解决方案OpenAI API调用失败报认证错误1. API Key 未设置或错误。2. API Key 余额不足或过期。3. 环境变量未正确加载。1. 检查print(os.getenv(“OPENAI_API_KEY”))是否输出正确不输出真实Key。2. 登录OpenAI平台检查额度与有效期。3. 重启终端或IDE确保环境变量生效。Agent 陷入无限循环不断调用同一个工具1. 提示词未明确“何时停止”。2. 工具返回的结果未能让LLM做出结束判断。3. 递归限制未设置。1. 在系统提示词中强化“当信息足够时直接给出最终答案”的指令。2. 检查工具返回的结果是否清晰、完整。3. 在app.invoke()中务必设置config{“recursion_limit”: N}。LLM 不调用工具总是尝试自己回答1. 工具描述 (docstring) 不够清晰。2. 提示词未强调使用工具。3. 模型能力或温度参数问题。1. 优化工具描述明确其功能、输入格式和适用场景。2. 在系统提示词开头明确“你必须使用工具来解决问题”。3. 尝试使用能力更强的模型如gpt-4或降低temperature。工具执行出错但Agent不会处理缺乏错误处理逻辑。1. 在工具函数内部进行try-catch并返回结构化的错误信息。2. 在提示词中教导LLM如何根据错误信息进行重试或调整。LangGraph编译或运行时报图结构错误1. 节点未正确定义或添加到图中。2. 边的指向错误如指向不存在的节点。3. 状态结构 (TypedDict) 定义与节点返回值不匹配。1. 使用workflow.get_graph().draw_mermaid()输出图结构可视化检查节点和边。2. 确保每个节点返回的字典键是AgentState中定义的字段。3. 仔细检查add_conditional_edges和add_edge的参数。导入错误找不到langchain_community等模块依赖未正确安装或版本冲突。1. 确认虚拟环境已激活。2. 运行 pip list7. 学习路线与项目进阶建议完成本基础项目后你可以沿着以下路径深入构建更强大的智能体。7.1 纵向深入增强单个Agent能力复杂规划实现更高级的规划算法如 Chain-of-Thought (CoT), Tree of Thoughts (ToT)。专业工具集成代码执行集成PythonREPLTool让Agent能编写并运行代码。数据库操作集成SQLDatabaseToolkit让Agent能查询和分析数据库。文件处理集成读写本地文件、解析PDF/Word的工具。网络API为Agent封装公司内部或第三方API。记忆系统升级结合向量数据库实现长期、海量记忆的存储与检索。7.2 横向扩展构建多智能体系统这是当前最前沿的方向之一即多个Agent分工协作。角色扮演创建“产品经理”、“架构师”、“程序员”、“测试员”等角色Agent协作完成软件设计任务。辩论与评审创建“主张者”和“反对者”Agent对某个方案进行辩论以得出更严谨的结论。流水线工作流使用LangGraph精确编排多个Agent的顺序、并行和条件执行流程。7.3 实战项目灵感个人知识库助手接入你的Notion、Obsidian笔记实现基于个人知识的问答和总结。自动化数据分析师给定一个数据集和问题Agent自动完成数据清洗、分析和可视化。智能客服升级结合业务知识库和订单系统处理复杂的、多轮的用户咨询和售后问题。AI产品经理输入模糊的需求描述输出PRD文档、原型草图和技术选型建议。AI Agent的开发是一个快速迭代的领域其魅力在于将大语言模型的认知能力与程序的可执行能力相结合创造出能真正理解意图并自主完成任务的数字实体。从理解ReAct模式开始到熟练使用LangChain/LangGraph搭建工作流再到集成各种工具并优化其可靠性这条路径充满了挑战与乐趣。建议你以本文的“研究助手”为起点选择一个你感兴趣的具体领域如编程、写作、数据分析为其定制工具和提示词亲手打造一个能解决你实际问题的智能体。在这个过程中你将积累最宝贵的经验。
返回列表