ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

LangChain 1.3 实战:从零构建能联网搜索与执行任务的智能 Agent

2026/8/6 5:44:12 拓冰建站 浏览量
LangChain 1.3 实战:从零构建能联网搜索与执行任务的智能 Agent 如果你正在尝试用大模型构建一个能联网搜索、查天气、发邮件甚至操作数据库的智能助手却发现大模型本身只会“纸上谈兵”无法真正执行这些外部操作那么你遇到的正是当前AI应用开发的核心瓶颈如何让大语言模型LLM与现实世界交互。LangChain 正是为解决这个问题而生的框架它通过“工具调用”Tool Calling机制让 LLM 拥有了“手”和“脚”。然而网上教程要么停留在概念要么代码过时面对 LangChain 1.3 的更新和复杂的 Agent 概念很多开发者从“入门”直接走到了“放弃”。本文将从零开始手把手带你用 LangChain 1.3 构建一个能真正调用工具的智能 Agent。我们不只讲“是什么”更会深入剖析工具调用与普通函数调用的本质区别为什么它比简单的if-else判断复杂得多LangChain 工具调用的核心流程与性能瓶颈速度慢真的是 LangChain 的锅吗从单工具调用到多步推理 Agent 的完整演进路径如何让模型学会“思考”后再行动一套可运行、可调试的本地化代码实战方案完全基于开源模型无需担心网络与费用。读完本文你将能独立开发一个能理解你的指令、自主选择工具、并执行复杂任务的 AI 助手。我们直接开始。1. 核心问题为什么需要 LangChain 和工具调用在深入代码之前我们必须先理解要解决的根本问题。假设你直接问 ChatGPT“上海今天的天气怎么样” 它会根据训练数据中的知识可能已过时生成一段描述但它无法实时访问天气 API 获取真实数据。LLM 是一个强大的“大脑”但缺乏感知和操作世界的“感官”与“肢体”。工具调用Tool Calling就是为 LLM 安装“肢体”的机制。其核心思想是定义工具将外部能力如搜索、计算、数据库查询封装成函数并附上清晰的文字描述。模型决策将用户问题、可用工具描述一起提交给 LLM。LLM 分析后决定是否需要调用工具、调用哪个工具、以及传入什么参数。执行与反馈框架执行被选中的工具函数获取结果如真实的天气数据再将结果返回给 LLM。生成最终回答LLM 结合工具返回的结果组织成自然语言回复给用户。这个过程看似简单但隐藏着几个工程挑战格式标准化如何让 LLM 的输出能被程序稳定地解析为工具调用指令复杂逻辑用户问题可能需要连续调用多个工具如先搜索“最佳咖啡店”再查其“具体位置”。错误处理工具执行失败时如何让 LLM 理解并调整策略LangChain 的价值就在于它提供了一套标准化的组件Tools, Agents, Chains和设计模式将这些复杂流程封装起来让开发者能聚焦于业务逻辑。而Agent是 LangChain 中负责控制流的核心概念一个能根据输入和中间结果动态决定下一步行动调用工具或直接回答的智能体。很多人误以为 LangChain 只是“胶水代码”但实际上它定义了一套构建复杂 LLM 应用的“设计语言”。接下来我们从环境搭建开始亲手实践这套语言。2. 环境准备与核心依赖安装我们将创建一个纯净的 Python 项目使用完全离线的本地大模型进行演示确保过程可复现。这里我们选择Ollama来本地运行开源模型它部署简单且完美支持 LangChain。2.1 基础环境与 Ollama 部署首先确保你的系统已安装 Python (建议 3.9 以上) 和 pip。然后安装 Ollama。对于 macOS/Linux:curl -fsSL https://ollama.ai/install.sh | sh对于 Windows:访问 Ollama 官网 下载并安装可执行程序。安装后拉取一个适合工具调用的轻量级模型例如qwen2.5:7b中文理解好工具调用格式遵循好ollama pull qwen2.5:7b拉取完成后运行模型服务ollama serve默认服务会在http://localhost:11434启动。保持此终端运行。2.2 创建项目并安装 Python 依赖新建一个项目目录并创建虚拟环境mkdir langchain-agent-tutorial cd langchain-agent-tutorial python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate安装核心依赖。请特别注意 LangChain 版本本文基于 1.3.x 版本其 API 与早期版本如 0.0.x有较大差异。pip install langchain0.3.0 langchain-community0.3.0 pip install langchainhub0.1.20 pip install beautifulsoup4 requests # 用于后续的网页搜索工具示例这里我们安装langchain0.3.0这是 LangChain 1.3 生态的一部分版本号规则已调整langchain包版本与核心框架版本对应关系请以官方文档为准。langchain-community包含了许多社区维护的工具和集成。3. 核心概念拆解Tool, LLM, Agent 如何协同工作在写代码前我们需要清晰理解三个核心组件的关系这能帮你避免“复制代码却不知其所以然”的困境。LLM (大语言模型)项目的“大脑”。负责理解用户意图并生成决策调用工具或直接回答。在 LangChain 中它被封装为一个ChatModel或LLM对象。Tool (工具)项目的“手”。任何一个能被 LLM 调用的函数。它必须包含name: 工具的唯一标识。description: 功能的自然语言描述这是 LLM 决定是否调用该工具的唯一依据描述质量直接决定工具调用的准确性。args_schema(可选): 参数的 Pydantic 模型用于规范输入。func或run方法具体的执行函数。Agent (智能体)项目的“指挥官”。它内部封装了一个LLM和一组Tools并遵循特定的AgentExecutor逻辑来循环执行“思考-行动-观察”的步骤直到得出最终答案。它们的工作流程如下图所示概念性描述用户输入 - Agent - (LLM思考: 需要工具吗) - 是: 选择Tool并生成参数 - 执行Tool - 观察结果 - 再次思考... - 否: 生成最终回答 - 输出给用户一个关键认知LangChain 中的Agent本身不是一个魔法黑盒它是一套预定义的提示词Prompt和执行循环Loop的模板。不同的AgentType如ZERO_SHOT_REACT_DESCRIPTION,OPENAI_FUNCTIONS对应不同的推理策略。接下来我们从最简单的工具定义开始。4. 实战第一步手动封装与调用你的第一个工具让我们暂时抛开 Agent 的复杂性先感受一下最原始的工具调用流程。这能帮你透彻理解底层发生了什么。4.1 定义一个计算器工具创建一个文件first_tool.py# first_tool.py from langchain_core.tools import tool from typing import Optional # 使用 tool 装饰器快速定义工具 tool def multiply(a: float, b: float) - float: 将两个数字相乘。当用户需要计算乘积时使用此工具。 return a * b # 手动模拟工具调用流程 if __name__ __main__: # 1. 模拟LLM的“思考”输出假设LLM决定调用 multiply 工具 # 在真实场景中这部分由LLM根据工具描述生成 tool_name multiply tool_args {a: 12.5, b: 4} # 2. 根据工具名找到对应的工具对象 # 在实际框架中Agent会维护一个工具列表 available_tools [multiply] tool_to_call None for t in available_tools: if t.name tool_name: tool_to_call t break # 3. 执行工具 if tool_to_call: result tool_to_call.invoke(tool_args) print(f工具执行结果: {result}) else: print(未找到指定工具)运行它python first_tool.py输出工具执行结果: 50.0这个例子揭示了核心工具调用的本质是 LLM 输出一个结构化的指令工具名和参数然后由外部代码执行它。LangChain 自动化了“根据描述让 LLM 生成指令”和“根据指令查找并执行工具”的过程。4.2 连接本地 LLM 与工具现在我们引入真正的 LLM让它自己决定是否调用工具。创建llm_with_tool.py# llm_with_tool.py from langchain_community.llms import Ollama from langchain_core.tools import tool from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # 1. 定义工具 tool def get_word_length(word: str) - int: 返回输入英文单词的长度。 return len(word) # 2. 连接到本地 Ollama 服务的 LLM llm Ollama(modelqwen2.5:7b, base_urlhttp://localhost:11434) # 3. 构建一个简单的提示词将工具描述告知 LLM # 注意这是一种简化的演示并非标准的Agent调用方式。 prompt ChatPromptTemplate.from_messages([ (system, 你是一个有帮助的助手。你可以使用以下工具\n工具名{tool_name}\n工具描述{tool_description}\n当用户的问题适合使用该工具时请直接输出TOOL_CALL:参数的格式例如TOOL_CALL:hello。否则直接回答用户问题。), (human, {question}) ]) # 4. 创建链 chain prompt | llm | StrOutputParser() # 5. 测试 question 单词 langchain 有几个字母 response chain.invoke({ tool_name: get_word_length.name, tool_description: get_word_length.description, question: question }) print(fLLM 原始输出: {response}) # 6. 手动解析并执行工具调用模拟Agent的工作 if response.startswith(TOOL_CALL:): word response.split(:)[1].strip() tool_result get_word_length.invoke({word: word}) print(f工具执行结果: {tool_result}) # 理论上这里应该把结果再喂回给LLM生成最终回答 final_answer f单词 {word} 的长度是 {tool_result}。 print(f最终回答: {final_answer}) else: print(fLLM 直接回答: {response})运行此脚本观察 LLM 是否输出了TOOL_CALL:langchain这样的格式。这个例子虽然简陋但它完整展示了工具调用的核心闭环提示设计 - LLM 决策 - 解析执行 - 结果整合。然而手动解析TOOL_CALL:这种格式非常脆弱。在实际开发中我们需要依赖 LLM 和框架对结构化输出的支持。这就是 LangChain Agent 的价值所在。5. 构建你的第一个真正 Agent让 LLM 自动选择工具LangChain 提供了多种 Agent 类型。对于支持工具调用如 OpenAI 的function calling或类似结构化输出能力的模型我们可以使用create_react_agent等高级接口。由于我们使用的qwen2.5:7b支持工具调用格式我们将使用 LangChain 最新的推荐方式。5.1 定义多个工具并创建 Agent创建first_agent.py# first_agent.py from langchain_community.llms import Ollama from langchain.agents import create_react_agent, AgentExecutor from langchain_core.tools import tool from langchain import hub # 用于拉取预定义的提示词 # 1. 定义多个工具 tool def get_word_length(word: str) - int: 返回输入英文单词的长度。 return len(word) tool def get_current_time() - str: 返回当前的系统时间UTC。 from datetime import datetime return datetime.utcnow().strftime(%Y-%m-%d %H:%M:%S UTC) # 2. 初始化 LLM llm Ollama(modelqwen2.5:7b, base_urlhttp://localhost:11434) # 3. 获取一个标准的 ReAct 提示词模板 # ReAct (Reasoning Acting) 是一种让 LLM 将思考过程与行动分离的经典范式。 prompt hub.pull(hwchase17/react-chat) # 一个适合聊天交互的 ReAct 提示词 # 4. 创建工具列表 tools [get_word_length, get_current_time] # 5. 创建 Agent 和 AgentExecutor # create_react_agent 会组装提示词并配置LLM以支持工具调用。 agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) # verboseTrue 会打印详细的执行步骤便于调试。 # handle_parsing_errorsTrue 能优雅处理LLM输出格式错误。 # 6. 运行 Agent print( 测试 1: 需要调用工具的问题 ) result1 agent_executor.invoke({input: 请告诉我单词 supercalifragilisticexpialidocious 的长度。}) print(f最终答案: {result1[output]}\n) print( 测试 2: 无需调用工具的问题 ) result2 agent_executor.invoke({input: 你好请做个自我介绍。}) print(f最终答案: {result2[output]}\n) print( 测试 3: 调用另一个工具 ) result3 agent_executor.invoke({input: 现在UTC时间是什么}) print(f最终答案: {result3[output]})运行这个脚本 (python first_agent.py)。你会看到控制台输出类似以下内容 测试 1: 需要调用工具的问题 Entering new AgentExecutor chain... 我需要计算这个单词的长度。我可以使用 get_word_length 工具。 Action: get_word_length Action Input: {word: supercalifragilisticexpialidocious} Observation: 34 Thought: 我已经得到了单词的长度。 Final Answer: 单词 “supercalifragilisticexpialidocious” 的长度是 34 个字母。 Finished chain. 最终答案: 单词 “supercalifragilisticexpialidocious” 的长度是 34 个字母。通过verboseTrue的输出你可以清晰地看到 Agent 的“思考链”Thought-Action-Observation。这就是ReAct 框架的威力它强制 LLM 输出结构化的推理步骤使得整个决策过程变得可解释、可调试。6. 开发实用级 Agent集成真实世界工具搜索与计算现在我们构建一个更有用的 Agent集成网络搜索和高级计算工具。我们将使用DuckDuckGo进行搜索无需API Key并使用langchain_experimental中的PythonREPLTool来执行任意 Python 代码进行复杂计算注意安全风险。6.1 安装额外依赖并创建实用工具集pip install duckduckgo-search langchain-experimental创建practical_agent.py# practical_agent.py from langchain_community.llms import Ollama from langchain.agents import create_react_agent, AgentExecutor from langchain_community.tools import DuckDuckGoSearchRun from langchain_experimental.tools import PythonREPLTool from langchain_core.tools import tool from langchain import hub import warnings warnings.filterwarnings(ignore) # 忽略一些不必要的警告 # 1. 初始化 LLM llm Ollama(modelqwen2.5:7b, base_urlhttp://localhost:11434) # 2. 创建工具集 # 工具 A: 网络搜索 search DuckDuckGoSearchRun() # 工具 B: Python REPL (谨慎使用) python_repl PythonREPLTool() python_repl.description 一个可以执行Python代码并返回结果的工具。适用于数学计算、数据转换等。**警告不要执行来自不可信来源的代码。** # 工具 C: 自定义工具 - 单位换算 tool def convert_currency(amount: float, from_currency: str, to_currency: str) - str: 进行货币换算。这是一个模拟工具实际汇率是固定的。 支持: USD, CNY, EUR, JPY。例如100 USD 换算成 CNY。 # 模拟汇率表 rates { USD: {CNY: 7.2, EUR: 0.92, JPY: 150, USD: 1.0}, CNY: {USD: 0.14, EUR: 0.13, JPY: 21, CNY: 1.0}, EUR: {USD: 1.09, CNY: 7.8, JPY: 163, EUR: 1.0}, JPY: {USD: 0.0067, CNY: 0.048, EUR: 0.0061, JPY: 1.0}, } try: rate rates[from_currency.upper()][to_currency.upper()] result amount * rate return f{amount} {from_currency.upper()} {result:.2f} {to_currency.upper()} (模拟汇率) except KeyError: return f不支持从 {from_currency} 到 {to_currency} 的换算。 tools [search, python_repl, convert_currency] # 3. 创建 Agent prompt hub.pull(hwchase17/react-chat) agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue, max_iterations5, # 防止无限循环 early_stopping_methodgenerate # 达到最大迭代次数时强制生成最终答案 ) # 4. 测试复杂任务 questions [ 用中文搜索一下 LangChain 的最新版本是什么并总结其核心特性。, 计算 3 的 5 次方加上 10 的阶乘等于多少, 把 5000 日元换算成人民币。, ] for q in questions: print(f\n{*50}) print(f用户问题: {q}) print(f{*50}) try: result agent_executor.invoke({input: q}) print(f\n最终答案: {result[output]}) except Exception as e: print(f执行出错: {e})运行此脚本。你将看到 Agent 如何针对不同问题选择不同的工具对于搜索问题它会调用DuckDuckGoSearchRun。对于复杂计算它会调用PythonREPLTool并生成如math.factorial(10) (3**5)的代码。对于单位换算它会调用我们自定义的convert_currency工具。重要安全提示PythonREPLTool允许执行任意 Python 代码在生产环境中使用必须进行严格的沙箱隔离或输入清洗本文仅用于演示。对于计算类需求更安全的做法是预定义专用的计算工具如calculator。7. 深入原理LangChain 工具调用的速度瓶颈与优化很多开发者抱怨 LangChain 工具调用“慢”。我们需要客观分析慢在哪里LLM 推理速度这是最主要的瓶颈。每次 Agent 的“思考”生成 Thought/Action都是一次完整的 LLM 调用。本地 7B 模型在普通 CPU 上推理一次可能需要数秒。网络延迟如果你使用云端 API如 OpenAI网络往返时间会叠加。工具执行时间如果工具本身是慢速操作如爬取一个大型网页那么整体时间就会很长。框架开销LangChain 的抽象层会带来一些额外开销但在大多数场景下这与前三点相比微乎其微。优化建议模型层面使用更快的推理引擎如vLLM,TGI或量化模型。对于简单工具调用小模型如 3B, 7B通常足够。流程层面设置max_iterations防止 Agent 陷入无意义的循环。使用更高效的 Agent 类型如果模型原生支持function calling如 GPT-4, Claude, 或一些优化后的开源模型使用create_openai_tools_agent会比create_react_agent更直接、更快。精简提示词过长的系统提示和上下文会拖慢推理。设计层面工具描述的精确性清晰、无歧义的工具描述能减少 LLM 的理解偏差避免错误调用和重试。工具聚合将经常连续调用的工具组合成一个减少 LLM 调用次数。下面我们演示如何使用为工具调用优化的create_openai_tools_agent即使使用本地模型只要其遵循 OpenAI 的 function calling 格式即可。修改practical_agent.py中的创建部分# 仅展示修改部分在 practical_agent.py 中替换 agent 创建代码 from langchain.agents import create_openai_tools_agent # 确保你的 Ollama 模型支持 tool calling 格式。 # 创建 prompt prompt hub.pull(hwchase17/openai-tools-agent) # 创建 agent agent create_openai_tools_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, ...)这种 Agent 期望 LLM 直接输出结构化的工具调用对象而不是 ReAct 格式的文本因此通常解析更快、更稳定。关键在于你的模型必须支持这种格式。8. 常见问题与排查指南在开发过程中你几乎一定会遇到以下问题。这里提供系统的排查思路。问题现象可能原因排查步骤解决方案ModuleNotFoundError: No module named langchain.agentsLangChain 版本不匹配。新版本中模块路径可能已变更。运行pip show langchain和pip show langchain-community查看版本。确保安装的是较新的 0.3.x 版本。对于旧版代码可能需要将from langchain.agents import ...改为from langchain import agents或查阅对应版本的文档。Agent 陷入循环不断调用同一个工具1. 工具描述不清晰LLM 无法正确理解结果。2.max_iterations设置过高或未设置。3. LLM 本身推理能力不足。1. 检查verbose日志观察Observation工具返回的结果是否清晰。2. 查看是否达到max_iterations后由early_stopping_method强制结束。1. 优化工具描述和返回结果格式使其对 LLM 更友好。2. 合理设置max_iterations如 5-10。3. 尝试能力更强的模型。LLM 不调用工具总是直接回答1. 工具描述不够有吸引力或与问题不匹配。2. 系统提示词未明确要求使用工具。3. 模型本身工具调用能力弱。1. 检查工具description是否准确描述了功能和适用场景。2. 检查使用的prompt模板是否是为工具调用设计的如react-chat。1. 重写工具描述以“当用户需要/想要...”开头明确触发条件。2. 尝试不同的提示词模板或在提示词中明确强调“你必须使用可用工具”。3. 换用工具调用能力更强的模型。KeyError或参数解析错误1. LLM 生成的参数格式与工具定义的args_schema不匹配。2. 工具函数参数名与 LLM 输出中的 key 不一致。1. 查看verbose日志中的Action Input是否是一个合法的 JSON 字符串。2. 对比工具函数的参数名。1. 使用 Pydantic 模型明确定义args_schema这能帮助 LLM 生成正确格式。2. 确保工具参数是简单的原生类型str, int, float, bool。本地模型响应极慢1. 模型太大硬件资源不足。2. 未使用 GPU 加速。3. Ollama 服务配置问题。1. 观察 CPU/GPU 和内存使用率。2. 运行ollama ps查看模型加载状态。1. 换用更小的模型如llama3.2:3b,qwen2.5:3b。2. 确保 Ollama 支持 GPU安装对应版本并在 pull 模型时选择带量化后缀的如:7b-q4_K_M。3. 检查base_url是否正确。DuckDuckGoSearchRun返回空或错误1. 网络问题。2. DuckDuckGo 临时屏蔽或更改了接口。1. 尝试在浏览器中访问 DuckDuckGo。2. 查看返回的错误信息。1. 检查网络连接和代理设置。2. 考虑使用其他搜索工具如TavilySearchResults需 API Key或SerpAPI需 API Key。9. 生产环境最佳实践与安全考量将基于 LangChain 的 Agent 部署到生产环境需要超越“跑通Demo”的思维。工具设计原则最小权限每个工具只拥有完成其任务所必需的最小权限。例如一个文件读取工具不应有删除权限。输入验证与清洗在工具函数内部对所有输入参数进行严格的类型、范围和内容检查防止注入攻击特别是对于PythonREPLTool或执行 SQL 的工具。明确的错误处理工具执行失败时应返回结构化的错误信息帮助 LLM 理解问题所在而不是抛出未处理的异常导致整个 Agent 崩溃。Agent 流程控制设置超时与重试为 AgentExecutor 设置max_execution_time并为网络请求类工具配置单独的超时和重试逻辑。对话历史管理对于多轮对话需要妥善管理历史消息避免上下文过长。考虑使用ConversationBufferWindowMemory等组件。可观测性与日志关闭verbose但将关键步骤Thought, Action, Observation记录到结构化日志系统如 JSON 格式便于监控和调试。模型与性能模型选型生产环境需权衡速度、成本与效果。可考虑使用专为工具调用优化的模型或对通用模型进行微调。缓存策略对 LLM 的相同请求或工具调用的相同查询结果进行缓存可以极大提升响应速度并降低成本。LangChain 提供了LLMCache和ToolCache的接口。异步处理对于高并发场景使用 LangChain 的异步接口ainvoke,ainvoke以提高吞吐量。安全与合规用户输入过滤对用户输入进行敏感词过滤和内容安全审核防止 Agent 被用于生成有害内容。工具访问控制根据用户身份或会话上下文动态决定哪些工具可用。例如普通用户不能使用“删除数据库”工具。审计追踪记录每个用户会话中所有的工具调用、参数和结果以满足审计要求。遵循这些实践你的 Agent 才能从玩具蜕变为可靠的生产力工具。从理解工具调用的本质到手动模拟流程再到使用 LangChain 构建功能完整的 Agent最后考虑生产级部署我们完成了一次完整的 LLM 应用开发之旅。核心在于理解 LLM 作为“决策大脑”与外部工具作为“执行手脚”的协作范式而 LangChain 提供了实现这一范式的最佳实践工具箱。