LangChain 工具调用:从原理、入门到落地
在大模型应用开发中,纯文本LLM无法解决实时计算、外部数据查询、API交互等落地场景问题。LangChain 工具调用能力,核心是将自定义Python函数、外部能力封装为大模型可识别、可自主调度的标准化工具,让LLM自主判断何时调用工具、传递什么参数,最终结合工具输出结果生成精准回答。
本文将从零拆解LangChain工具调用的核心原理、核心组件、基础实操、手动/生产级两种实现方案、多工具调度、LCEL整合及生产避坑规范,所有代码均可直接运行,适配OpenAI、硅基流动等主流模型服务。
一、工具调用核心本质与核心概念
1.1 什么是 LangChain 工具(Tool)
LangChain 中的工具,本质是可被LLM自主调用的外部能力载体,是对普通Python函数、第三方API、数据库查询、计算器等能力的标准化封装。
简单来说:LLM 只擅长文本推理,无法执行计算、联网查询、读写数据,工具就是弥补LLM能力短板的外部插件,常见工具场景:
-
基础能力:四则运算、单位换算、数据校验
-
外部查询:天气查询、知识库检索、数据库查询
-
业务交互:调用第三方API、发送邮件、执行脚本、流程操作
1.2 工具调用核心运行逻辑
LangChain 工具调用的核心链路可总结为一句话:函数标准化封装 → 模型绑定工具 → LLM自主决策调用 → 工具执行回传结果 → LLM整合输出答案。
全程无需人工干预参数传递和工具触发,由模型根据用户问题自主判断是否需要调用工具。
二、工具调用五大核心组件
LangChain 工具调用依赖固定核心组件,各司其职,构成完整调用闭环,核心组件及作用如下:
| 核心组件 | 核心作用 |
|---|---|
| @tool 装饰器 | 将普通Python函数转为LangChain标准结构化工具,自动生成参数规约、工具描述 |
| 支持工具调用的LLM | 如DeepSeek-V3、GPT-3.5/4,具备工具决策、参数生成能力 |
| bind_tools() | 将工具列表绑定到模型,让LLM感知可用工具的能力、参数、使用场景 |
| ToolMessage | 标准化工具执行结果,接入对话上下文,供LLM二次推理 |
| Agent/AgentExecutor | 自动化完成多轮工具调用、循环推理,实现生产级闭环执行 |
三、第一步:标准化封装工具(@tool 深度解析)
普通Python函数无法被LLM识别,必须通过 @tool 装饰器 完成标准化封装,这是工具调用的基础。
3.1 @tool 底层原理
@tool 本质是对 StructuredTool.from_function() 的封装,不会修改原函数的执行逻辑,仅为函数附加大模型可识别的元信息,最终生成标准工具实例,核心附加信息:
-
name:工具名称(默认函数名),LLM通过该名称定位要调用的工具
-
description:取自函数docstring,告知LLM工具用途、适用场景
-
args_schema:通过函数类型注解自动生成Pydantic参数模型,约束参数类型、生成标准JSON Schema,避免参数传错
-
func:保留原始Python执行逻辑,保证工具功能不变
3.2 标准工具封装示例(可直接运行)
工具封装核心规范:必须写清晰docstring、必须标注参数类型、增加异常处理,保障LLM精准调用。
python
# tools.py
from langchain_core.tools import tool
@tool
def calculator(a: float, b: float, op: str) -> str:
"""
对两个数字进行四则运算计算
:param a: 第一个运算数字,浮点类型
:param b: 第二个运算数字,浮点类型
:param op: 运算符,仅支持 +、-、*、/ 四种符号
:return: 运算结果或异常提示
"""
try:
if op == "+":
return str(a + b)
elif op == "-":
return str(a - b)
elif op == "*":
return str(a * b)
elif op == "/":
if b == 0:
return "计算异常:除数不能为0"
return str(a / b)
else:
return f"计算异常:不支持{op}运算符,仅支持+、-、*、/"
except Exception as e:
return f"计算执行失败:{str(e)}"
# @tools之后,就有这这些属性了
print(cal.name)
print(cal.description)
# 封装第二个工具:模拟天气查询
@tool
def get_weather(city: str) -> str:
"""
查询指定城市的实时天气
:param city: 城市中文名称,如:北京、上海、广州
:return: 城市天气及温度信息
"""
# 模拟接口返回逻辑
weather_map = {
"北京": "晴朗,25℃,微风",
"上海": "多云,23℃,东南风",
"广州": "小雨,28℃,南风"
}
return weather_map.get(city, f"暂未查询到{city}的天气数据")
# 工具列表:统一管理所有可用工具
tools = [calculator, get_weather]
四、第二步:模型初始化与工具绑定
选用支持工具调用的大模型,通过 bind_tools 绑定工具列表,让模型具备工具调用能力。本文适配硅基流动DeepSeek-V3模型,兼容OpenAI系列模型。
4.1 模型配置文件(llm.py)
python
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 适配硅基流动模型,映射OpenAI标准环境变量
os.environ["OPENAI_API_KEY"] = os.getenv("SILICON_KEY")
os.environ["OPENAI_BASE_URL"] = os.getenv("SILICON_BASE_URL")
# 初始化支持工具调用的大模型
llm = init_chat_model("openai:deepseek-ai/DeepSeek-V3")
4.2 工具绑定核心代码
python
from llm import llm
from tools import tools
# 为模型绑定所有可用工具,生成具备工具调用能力的模型实例
llm_with_tools = llm.bind_tools(tools)
绑定后,模型推理时会自动根据用户问题判断:是否需要调用工具、调用哪个工具、传递什么参数。
五、两种工具调用实现方案(从调试到生产)
LangChain 工具调用分为手动解析版(调试专用)和Agent自动执行版(生产专用),适配不同开发场景。
5.1 方案一:手动解析工具调用(适合调试、学习原理)
手动实现「模型决策→工具执行→结果回传→多轮循环」全流程,直观理解工具调用底层逻辑,适合新手学习和问题调试。
核心规则:模型返回的 tool_calls 非空则需调用工具,content 为空;无需调用工具时tool_calls 为空,content 为直接回答。
python
from langchain_core.messages import HumanMessage, ToolMessage
from llm import llm
from tools import tools
# 1. 初始化对话上下文
messages = [HumanMessage(content="先计算3+3,结果再乘以2?北京和上海天气怎么样")]
# 绑定工具
llm_with_tools = llm.bind_tools(tools)
tool_map = {t.name: t for t in tools}
# 2. 模型首次推理
# res的tool_calls是 [{"name": "cal", "args": {"a": 3, "b": 3, "op": "+"}, "id": "xxx"}]
res = llm_with_tools.invoke(messages)
tool_calls = res.tool_calls
# 3. 循环执行工具(支持多轮嵌套调用)
while tool_calls:
# 记录模型工具调用请求到上下文
messages.append(res)
# 遍历执行所有工具调用
for tc in tool_calls:
print(f"调用工具:{tc['name']},参数:{tc['args']}") # 看每次调了什么
# 执行工具逻辑
tool_result = tool_map[tc["name"]].invoke(tc["args"])
# 工具结果写入上下文,关联调用ID
messages.append(ToolMessage(content=tool_result, tool_call_id=tc["id"]))
# 二次推理:基于工具结果继续判断是否需要新一轮工具调用
res = llm_with_tools.invoke(messages)
tool_calls = res.tool_calls
# 输出最终整合答案
print("最终回答:", res.content)
5.2 方案二:Agent自动执行(生产级首选)
手动写法冗余且易出错,LangChain 提供 create_agent 快速构建智能Agent,自动完成多轮工具调用、上下文管理、循环推理,是企业开发标准方案。
python
from langchain.agents import create_agent
from llm import llm
from tools import tools
# 1. 创建Agent:绑定模型、工具、系统提示
agent = create_agent(
llm,
tools,
system_prompt="你是智能助手,计算问题使用calculator工具,天气查询使用get_weather工具,优先使用工具获取精准结果",
)
# 2. 批量提问,自动调度对应工具
result = agent.invoke({
"messages": [("user", "北京今天天气怎么样?100乘以50再加20等于多少?")]
})
# 3. 输出完整对话流程和最终答案
print("\n===== 完整对话日志 =====")
for idx, msg in enumerate(result["messages"]):
print(f"[{idx}] {type(msg).__name__}: {msg.content}")
print("\n===== 最终回答 =====")
print(result["messages"][-1].content)
总结
-
LangChain工具调用的核心是标准化封装+模型绑定+智能调度,@tool装饰器实现Python函数到大模型可识别工具的协议转换;
-
手动解析方案适合原理学习与调试,Agent自动执行是生产环境首选,大幅简化多轮工具调用逻辑;
-
工具描述、类型注解、异常处理是保障工具稳定调用的三大核心规范。