基于LangChain与函数调用构建AI智能体:从原理到工程实践
30款热门AI模型一站整合DeepSeek/GLM/Claude 随心用限时 5 折。 点击领海量免费额度在实际 AI 应用开发中我们常常面临一个核心矛盾如何让一个强大的大语言模型LLM去理解和操作一个它“看不见”的复杂外部系统比如你想让 AI 帮你整理电脑文件、分析系统日志或者像标题中提到的“重写操作系统应用”这本质上不是让 AI 去写代码而是让 AI 学会调用一系列外部工具Tools来完成一个复杂的、多步骤的任务。这个过程的核心技术栈就是Agent智能体和Function Calling函数调用。对于希望构建实用 AI 应用的开发者而言理解如何将大模型的“思考”能力与外部工具的执行能力无缝衔接是迈向下一代人机交互的关键一步。本文将以一个工程化的视角带你从零构建一个具备工具调用能力的 AI 智能体。我们将使用目前主流的开发框架如 LangChain和开源模型如 GLM、Qwen 等完成从环境搭建、工具定义、Agent 构建到任务规划与执行的完整流程。你将了解到 Agent 的核心工作流ReAct 模式学会如何将 Python 函数“包装”成 AI 可用的工具并掌握让 AI 自主规划并执行复杂任务的调试与排错方法。最终你将能搭建一个可以查询天气、搜索信息、进行数学计算甚至操作本地文件的简易“AI 助手”并理解其背后支撑“重写一千个应用”这类宏大叙事的技术原理。1. 理解智能体Agent与函数调用Function Calling的核心机制在传统的人机交互中用户需要明确指令程序按固定流程执行。而 AI 智能体引入了一种新的范式用户提出一个目标Goal由智能体来理解目标、制定计划Plan、选择工具Action并根据工具返回的结果Observation进行下一步决策直到任务完成或无法继续。这个循环就是经典的ReActReasoning Acting框架。1.1 什么是 Function CallingFunction Calling 并非真的让大模型去执行代码而是一种标准化的通信协议。开发者预先定义好一系列工具每个工具包含名称、描述和参数模式并将这些定义“告诉”大模型。当用户提出一个需求时大模型会判断是否需要调用工具以及调用哪个工具、传入什么参数。然后模型会输出一个结构化的调用请求如一个 JSON 对象由我们的程序来接收并真正执行对应的函数最后将函数执行结果返回给模型由模型生成最终面向用户的回答。例如用户问“北京今天天气怎么样” 模型会识别出这需要调用get_weather工具并输出{name: get_weather, arguments: {location: 北京}}。我们的程序解析这个请求执行真实的天气查询 API将结果{temperature: 22°C, condition: 晴}返回给模型模型再组织成自然语言“北京今天天气晴朗气温 22 摄氏度。”1.2 Agent 的关键组件与工作流一个典型的 Agent 系统包含以下核心组件LLM Core大模型核心负责理解用户意图、进行推理和决策。它是整个系统的“大脑”。Tools工具集一系列可供 Agent 调用的外部函数或 API。这是系统的“手”和“脚”。Agent Executor代理执行器驱动整个 ReAct 循环的引擎。它管理对话历史Memory根据当前状态用户输入历史工具结果调用 LLM 获取下一步决策执行工具并循环往复。Memory记忆存储对话历史和中间结果使 Agent 具备上下文感知能力。其工作流如下图所示概念性描述用户输入 - Agent Executor - LLM 思考 - 决定调用工具X - 执行工具X - 观察结果 ^ | | v —— 将结果作为新上下文再次进行LLM思考决定下一步行动 ——这个循环会持续进行直到 LLM 认为已经得到最终答案并输出一个面向用户的自然语言响应。1.3 为什么需要框架如 LangChain、LlamaIndex手动实现上述循环涉及大量重复性工作对话历史管理、工具定义的标准化、与不同模型 API 的适配、错误处理等。LangChain 这类框架将这些通用逻辑抽象成可复用的模块让开发者能专注于定义工具和业务逻辑。本文将以 LangChain 为例因为它生态丰富、文档齐全是快速构建 Agent 的原型首选。2. 环境准备与依赖配置为了构建一个可运行的 Agent 示例我们需要准备 Python 环境、安装必要的库并配置大模型访问权限。2.1 基础环境与核心库首先确保你的 Python 版本在 3.8 及以上。然后使用 pip 安装核心依赖。我们将使用 LangChain 作为主要框架并使用langchain-community来集成各种工具和模型。# 创建并进入项目目录 mkdir ai-agent-demo cd ai-agent-demo # 创建虚拟环境推荐 python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate # 安装核心依赖 pip install langchain langchain-community langchain-core # 安装用于网页搜索和数学计算的工具库 pip install duckduckgo-search langchain-experimental # langchain-experimental 包含一些高级Agent # 安装用于结构化输出的库对Function Calling友好 pip install langchain-openai注意langchain-experimental中的模块可能不稳定但对于学习最新 Agent 模式很有帮助。生产环境建议评估更稳定的替代方案。2.2 大模型接入配置你需要一个能够进行 Function Calling 的大模型。这里有几个主流选择OpenAI GPT 系列Function Calling 支持最成熟但需要 API Key 和网络条件。国内智谱 GLM、百度文心、阿里通义千问通过官方提供的 SDK 或 OpenAI 兼容接口接入。开源模型如 Qwen、DeepSeek可以通过本地部署或托管的 API 服务使用。本文以智谱 AIGLM和OpenAI 兼容模式为例进行配置。你需要先前往对应平台申请 API Key。配置环境变量推荐将 API Key 等敏感信息存储在环境变量中避免硬编码在代码里。# 在 Linux/Mac 的终端中或写入 ~/.bashrc / ~/.zshrc export ZHIPUAI_API_KEYyour_zhipuai_api_key_here # 如果你使用其他兼容OpenAI的本地服务 export OPENAI_API_BASEhttp://localhost:8000/v1 # 本地服务地址 export OPENAI_API_KEYsk-no-key-required # 如果本地服务不需要key可以随意填写在代码中配置模型创建一个config.py或直接在主程序中初始化模型。import os from langchain_openai import ChatOpenAI # 方式一使用智谱AI需要安装zhipuai库pip install zhipuai # LangChain 通过 openai_api_base 和 openai_api_key 参数兼容智谱 zhipu_llm ChatOpenAI( modelglm-4, # 或其他GLM模型如 glm-3-turbo openai_api_basehttps://open.bigmodel.cn/api/paas/v4/, openai_api_keyos.getenv(ZHIPUAI_API_KEY), temperature0.1, # 降低随机性使Agent决策更稳定 ) # 方式二使用本地部署的Qwen等开源模型假设服务端提供了OpenAI兼容接口 local_llm ChatOpenAI( modelQwen2.5-7B-Instruct, # 模型名根据实际服务调整 openai_api_baseos.getenv(OPENAI_API_BASE, http://localhost:8000/v1), openai_api_keyos.getenv(OPENAI_API_KEY, not-needed), temperature0.1, ) # 后续我们将使用 llm 变量来指代我们选择的大模型 llm zhipu_llm # 或 local_llm2.3 验证模型连接在深入构建 Agent 前先简单测试模型是否能正常工作。from langchain_core.messages import HumanMessage # 使用上面配置的 llm messages [HumanMessage(content你好请简单介绍一下你自己。)] response llm.invoke(messages) print(response.content)如果能看到模型返回的自我介绍说明环境配置成功。如果遇到连接错误请检查API Key 是否正确且未过期。网络是否能访问对应的 API 地址。本地模型服务是否已正确启动并监听对应端口。3. 构建你的第一个工具并让 Agent 使用它Agent 的强大之处在于能使用工具。我们从一个最简单的工具开始一个能计算两个数之和的加法器。3.1 使用tool装饰器定义工具LangChain 提供了tool装饰器可以轻松地将一个 Python 函数转化为 Agent 可用的工具。关键是为函数编写清晰的文档字符串docstring模型会据此理解工具的功能和参数。from langchain.agents import tool tool def add(a: float, b: float) - float: 计算两个浮点数的和。 Args: a: 第一个加数。 b: 第二个加数。 Returns: 两个数的和。 return a b # 查看工具的定义这会被发送给模型 print(f工具名称: {add.name}) print(f工具描述: {add.description}) print(f工具参数: {add.args})运行上述代码你会看到工具被解析成了一个结构化的模式。description和参数说明对于模型能否正确调用至关重要。3.2 创建工具集并初始化一个简单 Agent有了工具我们需要将它放入一个列表然后创建一个能使用这些工具的 Agent。这里我们使用 LangChain 的create_react_agent函数它实现了标准的 ReAct 推理模式。from langchain.agents import create_react_agent, AgentExecutor from langchain import hub # 用于拉取预定义的提示词 # 1. 定义工具列表 tools [add] # 2. 从LangChain Hub拉取一个为ReAct Agent设计好的提示词模板 # 这个提示词会告诉模型如何使用工具、如何格式化输出 prompt hub.pull(hwchase17/react) # 3. 创建ReAct Agent agent create_react_agent(llm, tools, prompt) # 4. 创建Agent执行器它负责运行循环 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) # verboseTrue 会打印出详细的思考过程便于调试 # handle_parsing_errorsTrue 能处理模型输出格式错误的情况3.3 运行你的第一个 Agent 任务现在让我们向 Agent 提问一个需要用到加法工具的问题。# 用户输入一个问题 question “请计算 123.45 和 678.9 的和是多少” print(f用户问题: {question}) # 执行Agent try: result agent_executor.invoke({input: question}) print(f\n最终答案: {result[output]}) except Exception as e: print(f执行过程中出现错误: {e})当verboseTrue时你会在控制台看到类似以下的输出这就是 ReAct 循环的思考轨迹 Entering new AgentExecutor chain... 我需要计算两个数的和。用户提供了数字 123.45 和 678.9。我有一个叫做 add 的工具可以完成这个任务。 Action: add Action Input: {a: 123.45, b: 678.9} Observation: 802.35 Thought: 我已经得到了计算结果 802.35。现在我可以把这个答案告诉用户。 Final Answer: 123.45 和 678.9 的和是 802.35。 Finished chain. 最终答案: 123.45 和 678.9 的和是 802.35。这个过程清晰地展示了 Agent 的“思考-行动-观察”循环它先推理出需要调用add工具然后生成正确的参数执行工具得到结果最后根据结果生成最终回答。4. 扩展工具集实现一个多功能 AI 助手单一的加法工具显然不够。一个实用的助手需要整合多种能力。下面我们添加网络搜索和天气查询模拟工具。4.1 添加 DuckDuckGo 搜索工具我们可以利用langchain_community中集成的现成工具。from langchain_community.tools import DuckDuckGoSearchRun # 初始化搜索工具 search_tool DuckDuckGoSearchRun(nameweb_search) # 可以自定义描述让模型更清楚它的用途 search_tool.description 一个搜索引擎。当需要获取最新的、实时的或未知领域的信息时使用此工具例如查询新闻、概念解释、事件详情等。 # 更新工具列表 tools [add, search_tool]4.2 创建一个模拟的天气查询工具由于真实的天气 API 需要注册我们创建一个模拟工具来演示。注意工具的描述要尽可能精确这直接影响模型的调用准确性。tool def get_weather(location: str, date: str “today”) - str: 获取指定城市在指定日期的天气情况。 Args: location: 城市名称例如“北京”、“上海”。 date: 日期默认为“today”。也可以是“tomorrow”或“2024-01-01”这样的具体日期。 Returns: 返回天气情况的字符串描述。 # 这里模拟一个固定的响应。真实场景应调用如和风天气、OpenWeatherMap等API。 weather_data { “北京”: {“today”: “晴朗气温 5-15°C” “tomorrow”: “多云气温 7-18°C”}, “上海”: {“today”: “小雨气温 10-18°C” “tomorrow”: “阴天气温 12-20°C”}, } city_weather weather_data.get(location, {}) forecast city_weather.get(date, “未找到该城市或日期的天气信息。”) return f”{location}在{date}的天气是{forecast}” # 再次更新工具列表 tools [add, search_tool, get_weather]4.3 使用更强大的 Agent 类型并执行复杂任务create_react_agent适合演示但对于更复杂的多工具场景LangChain 提供了更高级的create_openai_tools_agent即使你用的不是 OpenAI 模型只要支持 Function Calling 即可。它能更好地利用模型的原生工具调用能力。from langchain.agents import create_openai_tools_agent, AgentExecutor # 1. 重新拉取一个适合OpenAI工具调用的提示词 prompt hub.pull(“hwchase17/openai-tools-agent”) # 2. 创建支持OpenAI工具调用的Agent agent create_openai_tools_agent(llm, tools, prompt) # 3. 创建执行器 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) # 测试一个需要结合搜索和计算的问题 complex_question “先搜索一下‘Python 3.12’是什么时候发布的然后在这个发布年份的数字上加上 10。” print(f”用户问题: {complex_question}”) result agent_executor.invoke({“input”: complex_question}) print(f”\n最终答案: {result[‘output’]}”)观察verbose输出你会看到 Agent 先调用web_search获取 Python 3.12 的发布日期假设搜索结果是 2023 年然后调用add工具计算 2023 10最后给出答案“2033”。这展示了 Agent 进行多步骤规划和工具链式调用的能力。5. 核心参数、配置详解与生产环境考量构建一个玩具 Agent 和构建一个稳定可用的生产级 Agent 有很大不同。以下是一些关键配置和最佳实践。5.1 Agent 执行器AgentExecutor的关键参数参数类型默认值说明max_iterationsint15最重要参数之一。限制 ReAct 循环的最大次数防止 Agent 陷入死循环或执行成本过高。对于复杂任务可以调高但必须有上限。early_stopping_methodstr“force”停止条件。”force”表示在达到max_iterations或模型输出最终答案后强制停止。”generate”则依赖模型自己决定停止可能不可靠。handle_parsing_errorsboolFalse强烈建议设为 True。当模型输出的工具调用格式不符合预期时执行器会尝试修复或给出友好错误而不是直接崩溃。verboseboolFalse调试时设为 True生产环境设为 False。return_intermediate_stepsboolFalse设为 True 时返回结果会包含所有的中间思考Thought和观察Observation用于日志记录或前端展示。生产环境配置示例agent_executor AgentExecutor( agentagent, toolstools, max_iterations10, early_stopping_method”force”, handle_parsing_errorsTrue, verboseFalse, # 生产环境关闭详细日志 return_intermediate_stepsFalse, )5.2 工具Tool定义的最佳实践清晰的描述和参数名使用英文或简单中文准确描述工具功能。参数名应直观。类型注解Type Hints务必为函数参数和返回值添加类型注解如str,int,List[str]。这能帮助模型更好地理解参数格式。错误处理工具函数内部应有完善的try-except逻辑并返回明确的错误信息而不是抛出未捕获的异常导致整个 Agent 崩溃。幂等性与安全性对于写操作如发送邮件、修改文件工具应设计为幂等的并考虑权限校验。避免在工具内执行危险操作。tool def read_file(file_path: str) - str: 读取指定路径的文本文件内容。 Args: file_path: 文件的绝对路径或相对于当前工作目录的路径。 Returns: 文件的内容字符串。如果文件不存在或读取失败返回错误描述。 try: with open(file_path, ‘r’, encoding‘utf-8’) as f: return f.read() except FileNotFoundError: return f”错误找不到文件 ‘{file_path}‘。” except Exception as e: return f”读取文件时发生未知错误{str(e)}”5.3 大模型LLM调参建议temperature控制输出的随机性。对于需要精确执行工具调用的 Agent 任务建议设置为较低值如 0.1 或 0.2以减少模型“胡思乱想”和错误格式输出的概率。model选择明确支持 Function Calling 的模型。并非所有模型都支持此功能。超时与重试在生产环境中需要为 LLM 调用配置超时和重试机制以应对网络波动或服务不稳定。from langchain_openai import ChatOpenAI from langchain.callbacks.manager import CallbackManager from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler llm ChatOpenAI( model“glm-4”, temperature0.1, max_retries2, # 配置重试 request_timeout30, # 配置超时秒 # 可以添加回调函数进行流式输出或监控 # callback_managerCallbackManager([StreamingStdOutCallbackHandler()]), )6. 常见问题排查与调试技巧在开发 Agent 过程中你可能会遇到以下典型问题。6.1 问题一Agent 不调用工具直接回答问题现象对于明显需要工具的问题如“今天天气如何”Agent 直接基于自身知识生成一个可能错误或通用的答案而不是调用get_weather工具。可能原因与解决方案工具描述不清晰检查工具的description和参数描述是否足够准确。模型可能无法将用户问题与工具功能匹配。尝试用更直接的语言重写描述例如将“获取天气”改为“查询指定城市在指定日期的实时天气和温度预报”。提示词Prompt不合适不同的 Agent 类型需要不同的提示词。确保你使用的提示词如hwchase17/react或hwchase17/openai-tools-agent是专门为工具调用设计的。可以尝试拉取不同的提示词进行测试。模型能力不足某些较小的或未经专门微调的模型可能工具调用能力较弱。尝试更换为更强大的模型如 GLM-4、GPT-4、Qwen-Max。温度temperature过高过高的temperature会增加随机性可能导致模型忽略工具调用指令。将其调低至 0.1 或 0。6.2 问题二工具调用参数错误或格式不对现象Agent 决定调用工具但输出的Action Input参数格式错误如 JSON 解析失败、缺少必要参数或参数类型不对。排查步骤开启verboseTrue这是最重要的调试手段直接查看模型输出的原始Action Input是什么。检查模型输出观察Thought部分看模型是否正确地“思考”出了需要的参数。如果思考正确但输出格式错误可能是提示词中关于输出格式的指令不够明确。使用handle_parsing_errorsTrue这个参数能防止因格式错误导致的崩溃并可能尝试修复。观察修复后的参数是否正确。简化工具参数初期尽量使用简单类型str,int,float,bool避免复杂的嵌套对象。确保参数名简单明了。6.3 问题三Agent 陷入死循环或无效调用现象Agent 反复调用同一个工具或者在不同工具间来回切换始终无法得出最终答案直到达到max_iterations限制。解决方案设置合理的max_iterations这是最后的安全网必须设置。根据任务复杂度通常 5-15 次迭代足够。优化工具设计确保每个工具都是原子性的完成一个明确的小功能。避免让一个工具做太多事情导致模型无法有效利用其结果。增强模型的“停止”信号在提示词中明确强调当获得足够信息回答用户问题时应该输出Final Answer而不是继续调用工具。可以查阅所用提示词模板的原始内容并进行微调。检查工具返回结果工具返回的结果是否清晰、结构化如果返回一段冗长且不相关的文本模型可能无法从中提取有效信息进行下一步决策。尽量让工具返回简洁、关键的信息。6.4 调试清单当 Agent 行为不符合预期时可以按此清单逐步检查步骤检查项操作1模型基础对话先测试模型是否能正常进行一轮基础问答排除连接和鉴权问题。2工具列表打印tools列表确认所有工具都已正确加载并且name和description正确。3详细日志设置verboseTrue完整观察一次 ReAct 循环的Thought、Action、Action Input、Observation。4工具独立测试脱离 Agent手动调用有问题的工具函数传入模拟参数检查其返回值是否符合预期。5提示词查看使用的提示词模板内容确认其是否鼓励工具调用并定义了正确的输出格式。6参数与配置检查temperature是否过高max_iterations是否过小handle_parsing_errors是否开启。7简化问题用一个最简单的工具如加法和一个最简单的问题“11等于几”测试确保基础流程是通的。7. 从 Demo 到实践扩展方向与系统设计思考掌握了基础 Agent 构建后你可以向以下几个方向深化以应对更真实的场景。7.1 扩展更强大的工具文件操作结合os和shutil库创建读写、移动、复制文件的工具。数据库查询封装 SQL 查询工具让 Agent 能根据自然语言查询数据库。务必注意 SQL 注入风险应使用参数化查询或严格限制查询类型。代码执行在安全的沙箱环境中执行代码片段需极度谨慎评估安全风险。API 集成将企业内部系统CRM、ERP、工单系统的 API 封装成工具。浏览器自动化通过playwright或selenium库创建网页自动化工具用于处理需要登录或复杂交互的任务。7.2 引入记忆Memory实现多轮对话目前的 Agent 是无状态的。通过集成 Memory可以让 Agent 记住之前的对话上下文。from langchain.agents import AgentExecutor from langchain.memory import ConversationBufferMemory # 创建记忆体 memory ConversationBufferMemory(memory_key“chat_history”, return_messagesTrue) # 在创建执行器时传入memory agent_executor AgentExecutor( agentagent, toolstools, memorymemory, verboseTrue, handle_parsing_errorsTrue, ) # 现在可以进行多轮对话了 result1 agent_executor.invoke({“input”: “我的名字叫小明。”}) print(result1[‘output’]) # 可能回复“你好小明。” result2 agent_executor.invoke({“input”: “我刚才说我叫什么名字”}) # Agent 能记住上下文 print(result2[‘output’]) # 应该能回答“你叫小明。”7.3 面向生产系统的设计考量安全性工具权限隔离为不同用户或角色的 Agent 分配不同的工具集。普通用户不应有删除文件或执行系统命令的工具。输入验证与过滤对所有从用户输入和模型输出中解析出的工具参数进行严格的验证、转义和过滤。沙箱环境对于执行代码、访问网络等高风险工具必须在隔离的沙箱环境中运行。可靠性错误恢复Agent 执行链中任何一个环节失败模型调用、工具执行、网络异常都应有降级或重试策略。超时控制为每个工具调用和模型调用设置独立的超时时间。结果验证对工具返回的结果进行合理性检查避免将错误或恶意结果传递给模型进行下一步推理。可观测性全链路日志记录每一次用户输入、模型思考、工具调用参数和结果、最终输出。这对于排查问题和优化效果至关重要。监控与告警监控 Agent 的调用延迟、成功率、工具使用频率等指标设置异常告警。性能与成本缓存对频繁且结果稳定的工具调用如某些查询引入缓存机制减少不必要的模型调用和工具执行。优化提示词精心设计的提示词可以减少不必要的思考步骤Iterations从而降低延迟和 Token 消耗。模型选型在效果和成本间权衡。复杂的规划任务可能需要强模型如 GLM-4而简单的工具执行可以用更小、更快的模型。回到文章开头那个“重写操作系统应用”的宏大设想其技术本质正是构建一个拥有极其丰富工具集的超级 Agent。这些工具可能包括代码分析工具、语法树修改工具、版本控制工具、代码风格检查工具、单元测试工具、编译构建工具等。Agent 的核心任务不再是直接生成代码而是理解重构需求并智能地调度这一系列工具形成一个自动化的重构流水线。这揭示了 AI 应用开发的未来趋势从让 AI 生成一切转向让 AI 成为复杂工具生态的智能调度者和协调者。你现在构建的这个简易助手正是迈向那个未来的第一步。 30款热门AI模型一站整合DeepSeek/GLM/Claude 随心用限时 5 折。 点击领海量免费额度