LangChain Agent实战:从工具调用到多智能体协作的AI应用开发

📅 2026/8/7 5:11:49
LangChain Agent实战:从工具调用到多智能体协作的AI应用开发
1. 从“工具人”到“全能管家”为什么我们需要Agent最近在跟几个做AI应用的朋友聊天发现一个挺有意思的现象大家一提到LangChain第一反应往往是“哦那个做RAG检索增强生成的框架”。这其实是个挺大的误解或者说LangChain的潜力被严重低估了。RAG确实是它的一个杀手级应用场景但如果你只把它当做一个高级的文档问答工具那就好比买了一台顶配的游戏本却只用来写Word文档。真正的价值藏在它的另一个核心概念里Agent智能体。你可以把它理解为一个“全能管家”。想象一下你有一个私人助理你只需要用自然语言告诉它“帮我查一下明天上海的天气如果下雨就取消下午的户外会议并给所有参会者发一封邮件说明情况”它就能自动去调用天气查询API、访问你的日历系统、再调用邮件发送服务一气呵成。这个“助理”就是Agent。为什么这很重要因为当前绝大多数AI应用尤其是基于大语言模型LLM的应用都还停留在“单次问答”或“文档检索”的层面。它们很聪明能说会道但缺乏“行动力”。它们知道怎么描述如何发邮件但自己不会去点“发送”按钮。Agent要解决的就是赋予AI“动手能力”让它能根据目标自主规划、调用工具、执行任务。这阵子从OpenAI的GPTs到各种AI Agent框架比如CrewAI、AutoGPT再到LangChain自家的LangGraph整个圈子都在疯狂讨论如何构建更强大的Agent。网上的教程很多但很多要么是“Hello World”级别的简单示例离实战很远要么就是直接堆砌复杂的概念让人看得云里雾里。今天我就结合自己最近在项目中的实践抛开那些华而不实的理论直接上手带你构建一个真正能干活、能解决实际问题的“全能工具调用Agent”。我们会从最核心的“工具调用”机制拆解起一步步增加它的能力直到它能像一个真正的数字员工一样协同工作。2. 基石深入理解LangChain的工具调用机制在开始敲代码之前我们必须先搞清楚LangChain让Agent“动手”的核心原理。这就像学武功要先扎马步基础不牢后面复杂的招式都是花架子。2.1 工具Tool的本质给LLM装上“手和脚”一个Tool在LangChain里本质上就是一个Python函数外加一些描述信息。LLM本身并不知道如何查询数据库、发送HTTP请求或读写文件。Tool的作用就是将这些能力“封装”成一个LLM可以理解和调用的格式。举个例子我们想给Agent装上一个“计算器”功能from langchain.tools import tool tool def calculate(expression: str) - str: 用于执行数学表达式计算。输入应为一个字符串格式的数学表达式例如 ‘(35)*2‘。 try: # 安全提示实际生产中请使用更安全的评估方式如 ast.literal_eval 或专用数学库 result eval(expression) return f计算结果: {result} except Exception as e: return f计算错误: {e} # 使用这个工具 print(calculate.invoke((35)*2)) # 输出计算结果: 16你看tool这个装饰器把普通的calculate函数变成了一个LangChain Tool。关键在函数文档字符串用于执行...LLM就是通过阅读这段描述来理解这个工具是干什么的、需要什么输入。所以编写清晰、准确、无歧义的工具描述是构建可靠Agent的第一步。我踩过的坑是描述写得太简略比如“计算数学”LLM可能会困惑是该输入“35”还是“请计算三加五”。2.2 智能体Agent的核心工作流思考、行动、观察一个最简单的Agent工作流可以概括为“ReAct模式”Reasoning Acting思考ReasonLLM根据用户的问题和当前上下文思考下一步该做什么。是直接回答还是需要调用某个工具行动Act如果决定调用工具LLM会生成一个结构化的调用指令包含工具名和输入参数。观察Observe执行工具获取结果可能是数据也可能是错误信息。循环将工具执行结果作为新的上下文交给LLM继续思考下一步直到LLM认为可以给出最终答案。LangChain帮我们自动化了这个循环。它提供了一个“AgentExecutor”就像是一个导演负责协调LLM大脑和Tools手脚之间的演出。from langchain.agents import AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI from langchain import hub # 1. 准备大脑LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 2. 准备工具集 tools [calculate] # 把我们刚才定义的计算机工具放进来 # 3. 获取一个预设的“思维提示词” prompt hub.pull(hwchase17/react) # 4. 创建Agent agent create_react_agent(llm, tools, prompt) # 5. 创建执行器 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue) # 6. 运行 result agent_executor.invoke({input: 请问 (12 8) / 2 等于多少}) print(result[output])当你运行这段代码并把verbose设为True时会在控制台看到详细的思考过程 进入新的AgentExecutor链... 思考用户问了一个数学计算问题我需要使用计算器工具。 行动调用calculate工具输入为(12 8) / 2。 观察计算结果: 10.0 思考我得到了计算结果可以回答用户了。 最终答案10.0 链结束。这个过程直观地展示了Agent“思考-行动-观察”的循环。这里的核心在于LLM并不是“计算”出了答案而是“决策”去调用正确的工具并“解析”了工具返回的结果。这种“决策能力”是Agent智能的关键。2.3 工具描述的“艺术”少即是多准才是王道工具描述写得好不好直接决定Agent的智商。我总结了几条血泪教训避免歧义不要用“处理数据”这种模糊描述。应该是“根据城市名称查询该城市未来三天的天气预报返回温度和天气状况”。明确输入格式如果工具需要JSON就在描述里说清楚。“输入应为JSON格式包含‘city’字段例如 {city: 上海}”。说明输出内容“返回一个包含‘temperature’摄氏度和‘condition’字符串的JSON对象。”提及错误情况“如果城市名称不存在返回错误信息‘城市未找到’。”一个反面教材我曾写过一个工具描述是“获取信息”结果LLM在需要查天气和查股票时都试图调用它导致混乱。后来拆分成get_weather和get_stock_price两个工具并配以精准描述问题立刻解决。3. 实战构建打造一个能联网搜索与处理数据的智能体理解了基础机制我们来点实际的。一个只能算数的Agent用处不大。我们给它装上“眼睛”网络搜索和“记忆体”数据处理让它能解决更真实的问题比如“帮我找一下LangChain最新版本发布了什么新特性并总结成三点。”3.1 集成网络搜索工具LangChain社区提供了大量预构建工具。我们使用TavilySearchResults工具它封装了一个不错的搜索API。from langchain_community.tools.tavily_search import TavilySearchResultsTool from langchain.tools import Tool import os # 需要设置Tavily的API Key (可在其官网免费注册获取) os.environ[TAVILY_API_KEY] your_api_key_here # 创建搜索工具 search_tool TavilySearchResultsTool() # 我们也可以自定义一个更友好的包装工具 tool def web_search(query: str) - str: 在互联网上搜索最新信息。当需要获取实时、非公开知识库内的信息如新闻、最新事件、产品更新时使用此工具。输入应为明确的搜索关键词。 # 这里直接使用 Tavily 工具你也可以换成 SerperAPI 或 DuckDuckGo results search_tool.invoke(query) # 将结果列表浓缩成一段文本方便LLM阅读 return \n.join([f{r[title]}: {r[content]} for r in results[:3]]) # 取前三条现在我们把web_search工具和之前的calculate工具放到一起。3.2 设计一个多步骤任务的工作流用户的问题“找LangChain新特性并总结”是一个典型的多步骤任务搜索“LangChain latest release features”。从搜索结果中提取关键信息。对信息进行归纳总结。LangChain的Agent可以自动处理这个规划。我们使用更强大的create_openai_tools_agent它直接利用GPT-3.5/4等模型原生的“函数调用”能力比ReAct模式更高效。from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_openai import ChatOpenAI from langchain import hub llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) tools [web_search, calculate] # 工具集升级了 # 使用一个更适合工具调用的提示词模板 prompt hub.pull(hwchase17/openai-tools-agent) agent create_openai_tools_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue) # 执行复杂任务 result agent_executor.invoke({ input: 请搜索LangChain最近发布的重要更新或新特性并总结成三个要点。 }) print(result[output])运行后你会看到Agent自动调用了web_search工具获取了搜索结果然后LLM基于这些结果生成了总结。这里的关键进步是Agent自动完成了“规划-执行-整合”的全过程你不需要手动告诉它先搜再总结。3.3 处理复杂数据引入Python执行工具有时候搜索回来的数据可能需要简单的处理比如从一段文本里提取所有版本号或者计算一些统计值。我们可以给Agent一个更强大的武器PythonREPLTool。这个工具允许Agent在一个安全的沙箱环境中执行Python代码。警告这是一个高风险工具绝对不要在生产环境或能访问敏感数据的系统中随意使用。它可能执行任意代码。仅用于受控的演示或处理完全可信的数据。from langchain_experimental.tools import PythonREPLTool python_tool PythonREPLTool() tools.append(python_tool) # 加入到现有工具列表 # 现在Agent的能力更强了 result agent_executor.invoke({ input: 搜索‘2024年第一季度全球智能手机市场份额’如果找到数据请用Python计算排名前二的品牌份额之和。 })在这个任务中Agent可能会先调用web_search获取包含数据的文本然后调用python_tool生成类似import re; data Apple 20%, Samsung 18%...; # 提取并计算的代码来完成任务。这体现了Agent将自然语言指令转化为具体操作甚至是代码操作的强大能力。4. 超越单兵作战用LangGraph构建协同Agent系统单个Agent再强大也有瓶颈。面对复杂任务比如“分析一个竞品先爬取其官网最新动态再搜索社交媒体上的用户评价最后生成一份SWOT分析报告”一个Agent容易在长链条任务中迷失。这就需要多智能体协作。而LangChain的最新成员也可以视为一个更底层的框架——LangGraph正是为此而生。它允许你以“图”的形式定义多个Agent或节点的工作流精确控制执行逻辑和状态流转。4.1 LangGraph核心概念状态State与边Edges你可以把LangGraph想象成一个任务流程图。每个节点Node是一个处理单元可以是一个Agent一个工具或者一个普通函数节点之间的连线Edge决定了流程的走向。一个共享的“状态State”对象在所有节点间传递承载着输入、中间结果和最终输出。我们来设计一个简单的双Agent协作系统研究员ResearcherAgent负责搜索和收集信息。分析师AnalystAgent负责对收集的信息进行归纳和撰写报告。4.2 实现一个简单的协作图首先定义我们的状态。我们使用TypedDict来明确状态的结构。from typing import TypedDict, Annotated, List from langgraph.graph import StateGraph, END import operator # 1. 定义状态结构 class AgentState(TypedDict): # 用户原始问题 question: str # 研究员收集到的原始资料 research_materials: List[str] # 分析师生成的最终报告 final_report: str # 2. 创建两个“节点”函数 def research_node(state: AgentState): 研究员节点负责搜索信息 from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_openai import ChatOpenAI from langchain import hub llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 研究员只配备搜索工具 research_tools [web_search] prompt hub.pull(hwchase17/openai-tools-agent) research_agent create_openai_tools_agent(llm, research_tools, prompt) research_executor AgentExecutor(agentresearch_agent, toolsresearch_tools, verboseFalse) # 执行搜索任务 research_result research_executor.invoke({ input: f请收集关于以下主题的详细资料{state[question]} }) materials [research_result[output]] # 更新状态将资料放入 research_materials return {research_materials: materials} def analysis_node(state: AgentState): 分析师节点负责撰写报告 from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-4, temperature0.2) # 可以用更强的模型进行分析 # 基于研究员收集的资料撰写报告 materials \n\n.join(state[research_materials]) analysis_prompt f 你是一位资深分析师。以下是与“{state[question]}”相关的调研资料 --- {materials} --- 请基于以上资料撰写一份简洁、结构清晰的分析报告。 report llm.invoke(analysis_prompt).content # 更新状态放入最终报告 return {final_report: report} # 3. 构建图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(researcher, research_node) workflow.add_node(analyst, analysis_node) # 设置入口点 workflow.set_entry_point(researcher) # 定义边研究员完成后无条件进入分析师节点 workflow.add_edge(researcher, analyst) workflow.add_edge(analyst, END) # 分析师完成后图结束 # 编译图 app workflow.compile()4.3 运行与调试协作流现在我们可以运行这个协作系统了。# 初始化状态 initial_state AgentState(questionLangGraph与LangChain的主要区别及适用场景, research_materials[], final_report) # 运行图 final_state app.invoke(initial_state) print(最终报告) print(final_state[final_report])这个流程是线性的研究员 - 分析师。但LangGraph的强大之处在于可以定义条件边。例如你可以让一个“监督员”节点检查研究员收集的资料是否足够如果不够就让流程跳回研究员节点继续搜索直到满足条件再流向分析师。这种基于状态的、可循环、可分支的工作流是构建复杂、鲁棒AI应用的关键。在真实项目中我使用LangGraph构建过一个客户服务系统第一个Agent理解用户意图并分类第二个Agent处理产品咨询调用知识库第三个Agent处理退货流程调用订单API它们根据用户问题的不同在图中按不同路径执行效率比单个全能Agent高得多也更容易维护。5. 避坑指南与性能优化让Agent从“能用”到“好用”构建出能运行的Agent只是第一步让它稳定、可靠、高效地工作才是真正的挑战。下面分享几个我踩过坑才得来的经验。5.1 常见陷阱一工具描述冲突与LLM混淆当你给Agent提供了多个功能相近的工具时LLM可能会困惑。比如同时有search_web通用搜索和search_internal_wiki内部维基搜索。如果描述不清LLM在需要查公司内部政策时可能错误地调用通用搜索。解决方案命名清晰工具名本身就要有区分度。描述强调边界在search_internal_wiki的描述中明确指出“仅用于搜索公司内部知识库不包含外部网络信息”。提供示例在描述中可加入“例如输入‘年度报销政策’”。优先级在Agent的提示词Prompt中可以明确指导LLM“当问题涉及公司内部信息时优先使用search_internal_wiki工具。”5.2 常见陷阱二无限循环与超时Agent在复杂思考中可能陷入死循环比如不断调用同一个工具却得不到满足条件的结果。AgentExecutor提供了max_iterations和max_execution_time参数来强制止损。agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, max_iterations10, # 最多思考/行动10次 max_execution_time30, # 最多运行30秒 handle_parsing_errorsTrue, # 优雅处理LLM输出格式错误 early_stopping_methodgenerate # 当LLM多次输出相同动作时提前停止 )务必设置这些安全阀尤其是在面向用户的场景中。5.3 性能优化减少Token消耗与延迟每次工具调用和结果观察都会消耗Token并增加延迟。优化点工具结果精炼化让工具返回最精简、关键的信息而不是一大段HTML或JSON原始数据。可以在工具函数内部做一次提取。使用更高效的Agent类型create_openai_tools_agent利用GPT的函数调用通常比通用的create_react_agent更高效、更准确。缓存对于频繁查询且结果不变的工具如某些数据查询可以添加缓存层。异步执行如果多个工具调用之间没有依赖关系可以考虑使用LangChain的异步接口或LangGraph的并行节点来加速。5.4 提示词工程为Agent设定清晰的“人设”和规则默认的提示词可能不够。你需要通过系统消息System Message为Agent注入灵魂from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate system_template 你是一个专业、高效的数字助理。你的核心能力是使用工具完成任务。 请遵守以下规则 1. 在行动前先简要思考用户问题的核心是什么。 2. 优先使用更精确、更专业的工具。 3. 如果工具执行失败或结果不理想尝试分析原因并调整策略不要盲目重复。 4. 最终答案应基于工具返回的事实不要捏造信息。 5. 答案应结构清晰、简洁。 prompt ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(system_template), HumanMessagePromptTemplate.from_template({input}), ]) # 然后将这个自定义的prompt用于创建agent一个好的系统提示能极大提升Agent的决策质量和输出稳定性。构建一个全能的工具调用Agent就像在组装一个超级机器人。LangChain提供了丰富的零件工具、链、记忆和蓝图Agent执行器、LangGraph而你的任务就是当好这个工程师理解原理精心设计不断调试。从让LLM学会“按按钮”开始逐步搭建起能够自主处理复杂工作流的智能系统这其中的挑战和乐趣正是AI应用开发最吸引人的地方。