基于Python和LangChain从零构建具备工具调用能力的AI智能体
大语言模型本身是封闭的知识库,它擅长推理和生成,却无法触及现实世界。当用户询问“今天北京的天气如何”或“计算一下当前股价的市盈率”时,单纯的模型只能依靠训练数据中的过时信息胡编乱造,或者礼貌地拒绝回答。
真正的智能体(Agent)之所以被称为“智能体”,核心在于它拥有“手”和“脚”。它不仅能思考,还能通过调用外部工具去获取实时信息、执行代码或操作数据库。这种从“被动问答”到“主动行动”的转变,是构建现代AI应用的关键分水岭。
本文将剥离复杂的封装,直接使用Python和LangChain框架,展示如何为一个基础的大语言模型装上“工具”,使其成为一个能感知环境并执行任务的智能体。
核心逻辑:为什么智能体需要工具
在传统的LLM应用中,输入是提示词,输出是文本。而在Agent架构中,中间增加了一个“规划-执行-观察”的循环。模型首先判断用户意图是否需要外部协助;如果需要,它会生成一个特定的动作指令(Action);系统执行该动作后,将结果(Observation)反馈给模型;模型结合新信息再次推理,直到得出最终答案。
这个过程依赖于两个核心组件:一是标准化的工具接口,让模型知道有哪些能力可用;二是强大的推理引擎,负责决定何时以及如何使用这些工具。LangChain通过AgentExecutor和Tool抽象层,极大地简化了这一流程的实现。

智能体通过感知、规划、执行和观察的循环与外部工具交互
第一步:定义智能体的“工具箱”
工具是智能体与外界交互的桥梁。在LangChain中,任何Python函数都可以被包装成一个工具,但必须提供清晰的名称、描述和参数结构。描述尤为重要,因为模型是根据描述来决定是否调用该工具的。
我们首先定义两个基础工具:一个用于模拟实时搜索,另一个用于执行数学计算。在实际生产中,搜索工具可以对接Google Search API或Bing API,这里为了演示稳定性,使用模拟数据。
from langchain.agents import Tool
from langchain.tools import BaseTool
from typing import Optional
# 定义一个简单的搜索工具
def search_tool_func(query: str) -> str:
"""模拟搜索引擎,返回查询结果"""
# 实际项目中应替换为真实的API调用,如SerpAPI或Tavily
mock_results = {
"北京天气": "北京今天晴转多云,气温25摄氏度。",
"Python创始人": "Guido van Rossum",
"当前时间": "2023-10-27 10:00:00"
}
for key, value in mock_results.items():
if key in query:
return value
return "未找到相关实时信息,请尝试其他关键词。"
search_tool = Tool(
name="RealTimeSearch",
func=search_tool_func,
description="当你需要获取实时信息、新闻、天气或特定事实时使用此工具。输入应为搜索关键词。"
)
# 定义一个计算工具
def calculator_tool_func(expression: str) -> str:
"""安全地执行数学表达式计算"""
try:
# 注意:生产环境中严禁直接使用eval,建议使用asteval或专用数学库
# 此处仅为演示原理,实际请用 safe_eval
result = eval(expression)
return str(result)
except Exception as e:
return f"计算错误: {str(e)}"
calculator_tool = Tool(
name="Calculator",
func=calculator_tool_func,
description="当你需要执行数学运算、计算价格或统计数值时使用此工具。输入必须是合法的数学表达式,如 '2 + 2' 或 '100 * 0.8'。"
)
tools = [search_tool, calculator_tool]
在这段代码中,name是模型识别工具的标识符,description则是模型理解工具用途的说明书。如果描述模糊,模型可能会在不需要计算时强行调用计算器,或在需要搜索时产生幻觉。
第二步:配置大语言模型与Agent类型
有了工具,接下来需要选择一个支持“函数调用”或“ReAct”推理模式的大语言模型。LangChain支持多种模型后端,这里以OpenAI的GPT系列为例,因为它对工具调用的原生支持最为成熟。
我们需要初始化LLM实例,并将其与工具列表绑定。LangChain提供了多种Agent类型,其中zero-shot-react-description是最经典且通用的选择。它基于ReAct(Reasoning and Acting)范式,要求模型在每一步都输出思考过程(Thought)、动作(Action)和动作输入(Action Input)。
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
import os
# 设置API Key,实际使用中建议从环境变量读取
os.environ["OPENAI_API_KEY"] = "your-api-key-here"
# 初始化LLM
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
# 初始化Agent
agent = initialize_agent(
tools=tools,
llm=llm,
agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True # 开启verbose可以看到模型的思考过程
)
verbose=True是一个调试利器。在生产环境中通常关闭它,但在开发阶段,它能打印出模型内部的“内心独白”,让我们看到模型是如何一步步拆解问题、选择工具并处理结果的。

在Python环境中定义搜索和计算工具的代码片段
第三步:运行智能体并观察执行流
现在,智能体已经准备就绪。我们可以向它提出一个需要组合使用工具的问题,例如:“帮我查一下北京今天的天气,然后计算如果气温下降5度是多少度。”
这个问题看似简单,但模型必须先调用搜索工具获取“25摄氏度”,再进行减法运算。单一的LLM无法完成这个任务,因为它不知道当前的实时气温。
query = "帮我查一下北京今天的天气,然后计算如果气温下降5度是多少度?"
response = agent.run(query)
print(f"最终回答: {response}")
当这段代码运行时,控制台会输出详细的执行日志。典型的执行流如下:
- Thought: 我需要先知道北京今天的天气,然后再做减法。
- Action: RealTimeSearch
- Action Input: "北京天气"
- Observation: "北京今天晴转多云,气温25摄氏度。"
- Thought: 现在我知道气温是25度,需要计算25 - 5。
- Action: Calculator
- Action Input: "25 - 5"
- Observation: "20"
- Thought: 我现在可以给出最终答案了。
- Final Answer: 北京今天的气温是25摄氏度,如果下降5度,将是20摄氏度。

Verbose模式下展示的模型思考过程与工具调用记录
这种链式反应展示了智能体的核心价值:它将复杂的多步任务分解为原子操作,并通过工具调用填补了模型知识的空白。模型不再是一个孤立的文本生成器,而是一个能够协调资源的调度中心。
边界与局限:智能体不是万能的
尽管上述示例展示了流畅的工具调用,但在实际开发中,智能体面临着显著的稳定性挑战。首先,模型的决策具有概率性。在某些情况下,它可能会陷入“死循环”,反复调用同一个工具却得不到满意的结果;或者它可能误解工具的描述,传入错误的参数格式导致报错。
其次,工具的执行成本和时间延迟不容忽视。每次工具调用都意味着一次额外的API请求和网络等待。对于简单的查询,直接让模型回答可能更快、更便宜。只有当任务确实涉及实时数据、私有知识库或复杂计算时,引入Agent架构才是合理的取舍。
此外,安全性也是一个重要议题。允许模型执行代码或访问数据库意味着潜在的风险。在生产环境中,必须对工具的执行权限进行严格限制,并对模型的输入输出进行校验,防止注入攻击或误操作。

智能体在复杂任务中协调多个工具的概念示意
结语:从对话到行动的演进
构建具备工具调用能力的AI智能体,本质上是将大语言模型从“大脑”扩展为“完整的人”。通过LangChain这样的框架,开发者可以低成本地实现这一架构,让AI应用真正融入业务流。
然而,技术只是手段。在设计智能体时,更重要的思考是:哪些环节真的需要自动化?哪些工具是模型真正需要的?不要为了使用Agent而使用Agent。只有当工具的定义清晰、场景的需求明确时,智能体才能展现出超越传统软件的灵活性与智能感。对于开发者而言,掌握工具定义的规范和Agent的调试技巧,比单纯追求模型的参数量更为关键。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









