LangChain最详细教程之Tools
本文详细介绍了LangChain框架中的Tools模块,重点讲解了如何自定义工具来扩展大语言模型(LLM)的能力。主要内容包括:1) Tools的核心作用是通过与外部系统交互突破纯文本生成限制;2) 工具的五大要素:名称、描述、输入模式、调用函数和返回控制;3) 两种自定义工具方式:使用@tool装饰器和StructuredTool类方法;4) 实际应用示例展示如何通过大模型分析用户需求并调用相应
简介
本系列教程将以「系统梳理 + 实战落地」为核心,从基础到进阶全面拆解 LangChain—— 这个目前最流行的大语言模型(LLM)应用开发框架。之前对langchain进行了系统的概述,现在我们就来详细看看每一个板块。
LangChain最详细教程之Model I/O(一)调用模型
LangChain最详细教程之Model I/O(二)Prompt Template
LangChain最详细教程之Model I/O(三)Output Parsers
一、Tools概述


- 增强 LLM 的功能 :让 LLM 突破纯文本生成的限制,执行实际操作(如调用搜索引擎、查询数据库、运行代码等)
- 支持智能决策 :在Agent 工作流中,LLM 根据用户输入动态选择最合适的 Tool 完成任务。
- 模块化设计 :每个 Tool 专注一个功能,便于复用和组合(例如:搜索工具 + 计算工具 + 天气查询工具)
- name :工具的名称
- description :工具的功能描述
- 该工具输入的 JSON模式
- 要调用的函数
- return_direct :是否应将工具结果直接返回给用户(仅对Agent相关)
实操步骤:
- 步骤1:将name、description 和 JSON模式作为上下文提供给LLM
- 步骤2:LLM会根据提示词推断出 需要调用哪些工具 ,并提供具体的调用参数信息
- 步骤3:用户需要根据返回的工具调用信息,自行触发相关工具的回调

二、自定义工具
1 、两种自定义方式
2、 几个常用属性
| 属性 | 类型 | 描述 |
|---|---|---|
name |
str | 必选的,在提供给 LLM 或 Agent 的工具集中必须是唯一的。 |
description |
str | 可选但建议,描述工具的功能。LLM 或 Agent 将使用此描述作为上下文,使用它确定工具的使用 |
args_schema |
Pydantic BaseModel | 可选但建议,可用于提供更多信息(例如,few-shot 示例)或验证预期参数。 |
return_direct |
boolean | 仅对 Agent 相关。当为 True 时,在调用给定工具后,Agent 将停止并将结果直接返回给用户。 |
3、 具体实现
from docutils.nodes import description
from langchain_core.tools import tool, StructuredTool
from pydantic import BaseModel
@tool
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
print(f"name = {add_number.name}") #默认是函数的名称
print(f"args = {add_number.args}")
print(f"description = {add_number.description}") #默认是函数的说明信息
print(f"return_direct = {add_number.return_direct}") #默认值是False
举例2:
from langchain_core.tools import tool
@tool(name_or_callable="add_two_number", description="add two numbers", return_direct=True)
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
print(f"name = {add_number.name}") #add_two_number
print(f"args = {add_number.args}")
print(f"description = {add_number.description}") #add two numbers
print(f"return_direct = {add_number.return_direct}") #True
add_number.invoke({"a": 10, "b": 20})
举例3:修改args参数的描述
from pydantic import Field
from langchain_core.tools import tool
from pydantic import BaseModel
class FieldInfo(BaseModel):
a: int = Field(description="第1个整型参数")
b: int = Field(description="第2个整型参数")
@tool(name_or_callable="add_two_number", description="add two numbers", return_direct=True, args_schema=FieldInfo)
def add_number(a: int, b: int) -> int:
"""计算两个整数的和"""
return a + b
print(f"name = {add_number.name}") #add_two_number
print(f"args = {add_number.args}")
print(f"description = {add_number.description}") #add two numbers
print(f"return_direct = {add_number.return_direct}") #True
from langchain_core.tools.structured import StructuredTool
# 声明一个函数
def search_google(query: str):
return "最后查询的结果"
# 定义一个工具
search01 = StructuredTool.from_function(
func=search_google,
name="Search",
description="查询google搜索引擎,并将结果返回"
)
print(f"name = {search01.name}")
print(f"args = {search01.args}")
print(f"description = {search01.description}")
print(f"return_direct = {search01.return_direct}")
search01.invoke({"query":"中美AI的发展现状"})
举例2:
from langchain_core.tools.structured import StructuredTool
from pydantic import BaseModel,Field
class FieldInfo(BaseModel):
query: str = Field(description="要检索的关键词")
# 声明一个函数
def search_google(query: str):
return "最后查询的结果"
# 定义一个工具
search02 = StructuredTool.from_function(
func=search_google,
name="Search",
description="查询google搜索引擎,并将结果返回",
return_direct=True,
args_schema=FieldInfo
)
print(f"name = {search02.name}")
print(f"args = {search02.args}")
print(f"description = {search02.description}")
print(f"return_direct = {search02.return_direct}")
4 、工具调用举例
# 1、获取大模型
#导入相关依赖
from langchain_community.tools import MoveFileTool
from langchain_core.messages import HumanMessage
from langchain_core.tools import StructuredTool
from langchain_core.utils.function_calling import convert_to_openai_function
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
# 定义LLM模型
chat_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 2、获取工具的列表
tools = [MoveFileTool()]
# 3、因为大模型invoke调用时,需要传入函数的列表,所以需要将工具转换为函数:convert_to_openai_function()
functions = [convert_to_openai_function(t) for t in tools]
# 4、获取消息列表
messages = [HumanMessage(content="将文件a移动到桌面")]
# 5、调用大模型(传入消息列表、工具的列表)
response = chat_model.invoke(
input=messages,
# tools = tools, #不支持
functions=functions,
)
print(response)
作为对比:
# 获取消息列表
messages = [HumanMessage(content="查询一下明天北京的天气")]
# 调用大模型(传入消息列表、工具的列表)
response = chat_model.invoke(
input=messages,
# tools = tools, #不支持
functions=functions,
)
print(response)
通过上面两个测试发现,得到的AIMessage的核心属性如下:
1、如果分析出需要调用对应的工具:
content:信息为空。因为大模型要调用工具,所以就不会直接返回信息给用户
additional_kwargs:包含function_call字段,指明具体函数调用的参数和函数名。比如:
additional_kwargs={'function_call': {'arguments': '{"source_path":"a","destination_path":"/Users/YourUsername/Desktop/a"}', 'name': 'move_file'}, 'refusal': None}
2、如果分析出不需要调用对应的工具:
content:信息不为空。
additional_kwargs:不包含function_call字段
举例2:如何调用具体大模型分析出来的工具
说明:
1、大模型与Agent的核心区别:是否涉及到工具的调用
2、针对于大模型:仅能分析出要调用的工具,但是此工具(或函数)不能真正的执行
针对于Agent:除了分析出要调用的工具之外,还可以执行具体的工具(或函数)
# 1、获取大模型
#导入相关依赖
from langchain_community.tools import MoveFileTool
from langchain_core.messages import HumanMessage
from langchain_core.utils.function_calling import convert_to_openai_function
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
# 定义LLM模型
chat_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 2、获取工具的列表
tools = [MoveFileTool()]
# 3、因为大模型invoke调用时,需要传入函数的列表,所以需要将工具转换为函数:convert_to_openai_function()
functions = [convert_to_openai_function(t) for t in tools]
# 4、获取消息列表
messages = [HumanMessage(content="将当前目录下的文件a.txt移动到C:\\Users\\shkst\\Desktop")]
# 5、调用大模型(传入消息列表、工具的列表)
response = chat_model.invoke(
input=messages,
# tools = tools, #不支持
functions=functions,
)
# print(response)
步骤1:分析下要调用哪个工具或函数
import json
if "function_call" in response.additional_kwargs:
tool_name = response.additional_kwargs["function_call"]["name"]
tool_args = json.loads(response.additional_kwargs["function_call"]["arguments"])
print(f"调用工具:{tool_name} \n 参数:{tool_args}")
else:
print(f"模型回复:{response.content}")
步骤2:调用对应的工具
if "move_file" in response.additional_kwargs["function_call"]["name"]:
tool = MoveFileTool()
result = tool.run(tool_args) #调用工具
print("工具执行的结果", result)
更多推荐


所有评论(0)