【LangChain专栏】LangChain使用之Tools
本文介绍了LangChain的Tools组件,它是大语言模型(LLM)的外部能力扩展接口,使AI能够调用搜索引擎、计算器等外部功能,实现从文本生成到实际操作的跨越。Tools与Agent结合形成"思考+行动"能力,具有增强LLM功能、支持智能决策和模块化设计三大特点。文章详细解析了Tool的核心要素(名称、描述、参数规范等)和两种自定义方式:@tool装饰器(适合新手)和Str
一、Tools 核心概述
1. 工具的核心价值
LangChain的Tools是为大语言模型(LLM) 打造的外部能力扩展接口,解决了LLM仅能生成文本、无法与外部系统交互的问题,让AI从“文本生成”走向“实际操作”。
- 核心作用:让LLM能调用搜索引擎、计算器、数据库、文件操作、API等外部功能,完成纯文本生成做不到的任务。
- 应用场景:实时信息搜索、数据计算、文件操作、SQL查询、天气查询、代码运行等。

2. Tools 与LangChain其他组件的关系
Tools是LangChain中Agent(智能体) 的核心依赖,Agent负责决策何时/调用哪个工具,Tools负责执行具体操作,二者结合实现AI的“思考+行动”能力。
同时Tools可搭配Memory(记忆)、Chain(链)使用,形成完整的AI工程应用流程:用户输入 → Agent决策 → 调用Tools → 工具执行 → 结果返回(给Agent/直接给用户)
3. Tools 三大核心特点
- 增强LLM功能:突破纯文本限制,实现实际操作;
- 支持智能决策:Agent可根据用户输入动态选择合适工具;
- 模块化设计:每个工具只做一个功能,可自由组合(如搜索+计算+天气)。
4. LangChain 官方工具生态
LangChain内置了大量第三方集成工具,可直接调用,官网地址:https://docs.langchain.com/oss/python/langchain/tools#tools
常见官方工具:Bing Search(必应搜索)、Calculator(计算器)、CodeInterpreter(代码解释器)、MoveFileTool(文件移动)、SQLTool(数据库查询)等。
二、Tool 的核心要素(定义工具的关键)
Tools本质是封装特定功能的可调用模块,定义一个工具必须明确以下要素,要素的规范性直接影响LLM/Agent能否正确调用工具。
| 要素 | 类型 | 是否必选 | 核心作用 |
|---|---|---|---|
| name | str | 是 | 工具的唯一标识,LLM通过名称识别工具,工具集中不能重名 |
| description | str | 建议选 | 工具的功能描述,LLM/Agent靠这段文字判断是否调用该工具,描述越精准,调用越准确 |
| args_schema | Pydantic BaseModel | 建议选 | 工具的入参规范,定义入参的类型、描述、约束,用于参数校验和给LLM提示入参信息 |
| return_direct | bool | 可选 | 仅对Agent生效,True=工具执行结果直接返回给用户(中断Agent流程),False=结果返回给Agent(由Agent决定下一步) |
注意点
description是工具调用的核心,比如描述写“用于两个整数相加的计算工具”,LLM遇到“10+20等于多少”时会自动选择该工具;如果描述模糊,LLM可能无法识别。args_schema用于规范入参,比如限定入参为int类型,可避免传入字符串导致工具执行报错。
三、自定义工具的两种核心方式
文档中讲解了LangChain自定义工具的两种主流方式,其中@tool装饰器是新手首选(最简单),StructuredTool.from_function是进阶选择(可配置性更高)。
方式1:@tool 装饰器
基于Python装饰器快速定义工具,默认复用函数名作为工具名、函数文档字符串作为工具描述,可通过参数覆盖默认配置,支持自定义入参规范。
基础用法(直接装饰函数)
from langchain.tools import tool
# 装饰器直接修饰函数,函数文档字符串=工具描述,函数名=工具名
@tool
def add_number(a:int,b:int)->int:
"""两个整数相加的计算工具"""
return a + b
# 调用工具:传入字典格式的入参
res = add_number.invoke({"a":10,"b":20})
print(res) # 输出30
进阶用法(覆盖默认配置+自定义入参描述)
通过装饰器参数修改工具名、描述、return_direct,结合Pydantic的BaseModel定义入参的详细描述:
from langchain.tools import tool
from pydantic import BaseModel, Field
# 定义入参规范:给每个参数加描述,LLM能识别
class AddNumberSchema(BaseModel):
a :int = Field(description="需要相加的第一个整数")
b :int = Field(description="需要相加的第二个整数")
# 覆盖默认配置:自定义工具名、描述、return_direct,指定入参规范
@tool(
name_or_callable="add_two_integer", # 自定义工具名
description="实现两个整数的加法运算,输入两个整数返回求和结果", # 自定义描述
args_schema=AddNumberSchema, # 绑定入参规范
return_direct=True # 结果直接返回给用户
)
def add_number(a:int,b:int)->int:
"""两个整数相加"""
return a + b
# 调用
res = add_number.invoke({"a":20,"b":30})
print(res) # 输出50
方式2:StructuredTool.from_function(进阶,高可配置)
与@tool装饰器功能一致,但支持更精细的配置,适合需要自定义更多细节的场景,写法上更显式,便于团队协作和代码维护。
基础用法
from langchain_core.tools import StructuredTool
# 定义工具的核心执行函数
def search_function(query: str):
"""模拟搜索工具:根据关键词返回搜索结果"""
return f"关键词【{query}】的搜索结果:LangChain工具使用教程"
# 用from_function创建工具
search_tool = StructuredTool.from_function(
func=search_function, # 绑定核心执行函数
name="SearchTool", # 工具名
description="用于根据关键词检索实时信息、知识内容的搜索工具" # 工具描述
)
# 调用工具:可传字符串/字典
res = search_tool.invoke("LangChain Tools怎么用")
print(res)
进阶用法(自定义入参+return_direct)
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field
# 定义入参规范
class SearchSchema(BaseModel):
query: str = Field(description="需要检索信息的关键词,为字符串类型")
# 核心执行函数
def search_function(query: str):
return f"关键词【{query}】的搜索结果:LangChain工具使用教程"
# 创建工具
search_tool = StructuredTool.from_function(
func=search_function,
name="SearchTool",
description="用于根据关键词检索实时信息、知识内容的搜索工具",
args_schema=SearchSchema, # 绑定入参规范
return_direct=True # 结果直接返回用户
)
# 调用
res = search_tool.invoke({"query": "LangChain自定义工具"})
print(res)
两种方式的对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| @tool 装饰器 | 代码简洁、开发速度快,一行装饰器搞定 | 配置项相对少,显式性弱 | 新手入门、简单工具开发、快速原型验证 |
| StructuredTool.from_function | 配置显式、可定制性高,便于维护 | 代码量稍多 | 企业级开发、复杂工具、团队协作、需要精细配置的场景 |
四、Tools 实际调用流程
工具的核心价值是被LLM/Agent调用,文档中以MoveFileTool(文件移动工具)为例,讲解了LLM根据用户输入判断是否调用工具、如何解析调用参数、如何实际执行工具的完整流程,这是落地Tools的关键,分为4个核心步骤。
整体调用逻辑
定义LLM模型 → 加载/定义工具 → LLM分析用户输入并决策是否调用工具 → 解析工具调用参数 → 实际执行工具并返回结果
完整实操代码
步骤1:安装依赖
# 核心LangChain依赖
pip install langchain langchain-core langchain-community
# OpenAI依赖(如果用OpenAI模型)
pip install langchain-openai
# 环境变量管理
pip install python-dotenv
步骤2:完整调用代码(以MoveFileTool为例)
# 1. 导入所有依赖
from langchain_community.tools import MoveFileTool
from langchain_core.messages import HumanMessage
from langchain_core.utils.function_calling import convert_to_openai_function
from langchain_openai import ChatOpenAI
import os
import dotenv
import json
# 2. 配置环境变量(OpenAI API)
dotenv.load_dotenv() # 加载.env文件中的环境变量
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY") # 你的OpenAI API Key
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL") # 可选,国内需配置代理
# 3. 定义LLM模型(温度0=结果更确定,适合工具决策)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 4. 加载官方工具(也可替换为自定义工具)
tools = [MoveFileTool()] # 文件移动工具
# 5. 将LangChain工具转换为LLM可识别的函数格式(关键步骤)
functions = [convert_to_openai_function(t) for t in tools]
# 6. 定义用户输入
user_input = "将本目录下的abc.txt文件移动到C:\\Users\\你的用户名\\Desktop"
messages = [HumanMessage(content=user_input)]
# 7. LLM分析输入,决策是否调用工具
response = llm.invoke(input=messages, functions=functions)
print("LLM返回结果:", response)
# 8. 解析LLM结果,判断是否调用工具并执行
if "function_call" in response.additional_kwargs:
# 8.1 解析工具名称和入参
tool_name = response.additional_kwargs["function_call"]["name"]
tool_args = json.loads(response.additional_kwargs["function_call"]["arguments"])
print(f"LLM决定调用工具:{tool_name},入参:{tool_args}")
# 8.2 实际执行工具
if tool_name == "move_file":
tool = MoveFileTool()
result = tool.run(tool_args) # 执行工具
print("工具执行结果:", result)
else:
# LLM不调用工具,直接返回自然语言结果
print("LLM直接回复:", response.content)
LLM调用工具的两种结果判断
LLM接收到用户输入后,会根据工具的description判断是否需要调用工具,返回两种结果,需通过代码解析:
- 决定调用工具:
response.additional_kwargs中包含function_call,里面有工具名和入参,content通常为空; - 不调用工具:
response.additional_kwargs中无function_call,content为LLM的自然语言回复(如用户问天气,却只加载了文件工具,LLM会直接说无法回答)。
更多推荐


所有评论(0)