工具的作用
工具调用户根本作用是让大语言模型(LLM)具备与外部世界交互的能力。
LLM 本身是⼀个封闭的知识系统,其能力受限于其训练数据(存在滞后性)和内在的文本生成逻辑。它无法执行直接计算、查询实时信息、操作数据库或调用任何外部 API。工具调用打破了这层壁垒,其作⽤具体体现在:
- 扩展能力边界:模型可以借助工具完成它本身无法完成的任务,如执行数学计算、搜索网络、查询数据库等。
- 保证信息实时性:通过调⽤搜索⼯具或数据库查询⼯具,LLM 可以获取最新的、训练数据中不存在的信息,避免回答过时或"⼀本正经地胡说⼋道"。
- 处理复杂任务:将⼀个复杂的⽤⼾请求(如"分析我上个⽉的消费趋势")分解成多个步骤,并依次调⽤不同的⼯具(如"从数据库获取数据" -> "⽤ Python 进⾏数据分析" -> "⽣成图表") 来协同完成。协调这件事这更体现在 Agent 智能体上。
- 连接现有系统:可以将企业内部已有的系统、API 和数据库封装成⼯具,让 LLM 成为⼀个⽤⾃然语⾔驱动的统⼀接⼝,极⼤地提升了⾃动化和集成能⼒。
创建工具
使用 @tool 装饰器创建⼯具
在 LangChain 中,实现了⼀个 @tool 装饰器来创建⼯具, @tool 装饰器是⾃定义⼯具的最简单⽅
法。如下所示:
from langchain_core.tools import tool #定义工具 @tool def add(a: int, b: int) -> int: """ 两数相加 Args: a:第一个参数 b:第二个参数 """ return a+b #调用工具 print(add.invoke({"a": 1, "b": 2})) print(add.name) print(add.description) print(add.args)
运行结果如下:

可以看出,⼯具通过 @tool 加 Python函数 实现,其中:
- 该装饰器默认使⽤函数名称作为⼯具名称。
- 该装饰器将使⽤函数的⽂档字符串作为⼯具的描述
因此,函数名、类型提示和⽂档字符串都是传递给⼯具 Schema 的⼀部分,不可缺失。定义好的描述是使模型良好运⾏的重要部分
什么是Schema
简单来说:Schema 就是描述其他数据结构的声明格式,⽤于⾃动验证数据⽽存在
对于工具schema,它将从函数名、类型提示和⽂档字符串中获取相关属性,以此来声明⼀个⼯具,包括其名称、描述、输⼊参数、输出类型等等。这⾥需要说明的是,若是简单定义⼯具,如上述示例,⼯具 schema 需要解析 Google 风格的文档字符串去获取。
什么是 Google ⻛格的⽂档字符串?Google ⻛格是 Python ⽂档字符串的⼀种写作规范。它并⾮
Python 语⾔官⽅强制要求,⽽是由 Google 为其内部 Python 项⽬制定的规范,后来因为其极⾼的可读性和简洁性⽽在整个 Python 社区中变得⾮常流⾏。它使⽤ Args: , Returns: 等关键字,参数
描述简洁明了,如下所示
def fetch_data(url, retries=3):
"""从给定的URL获取数据。
Args:
url (str): 要从中获取数据的URL。
retries (int, optional): 失败时重试的次数。默认为3。
Returns:
dict: 从URL解析的JSON响应。
"""
除了这种⽅式,还有其他⽅式可以让⼯具 schema,获取相关⼯具声明需要的内容。下⾯再展⽰其他常用的工具定义模式:
其他工具定义模式
1、依赖Pydantic类
class AddInput(BaseModel): """ 两数相加 """ a: int = Field(description="第一个参数") b: int = Field(description="第二个参数") @tool(args_schema=AddInput) def add(a:int, b:int) -> int: return a+b #调用工具 print(add.invoke({"a": 1, "b": 2})) print(add.name) print(add.description) print(add.args)
运行结果如下:

注意是代码中 @tool 的 args_schema 参数,它表示工具函数在未提供描述、文档字符串等需要传 递给⼯具 Schema 的内容时,依赖 Pydantic 类使⽤ args_schema 参数,定义并提供⼯具输⼊参数的schema。默认为 None。
点击运⾏,不会报错,且将来运⾏时会进⾏数据验证。因此,我们再次印证了函数名、类型提⽰和⽂档字符串都是传递给⼯具 Schema 的⼀部分,不可缺失
2、依赖 Annotated
@tool def add( a: Annotated[int, "第一个参数"], b: Annotated[int, "第二个参数"] ) -> int: """两数相加""" return a+b print(add.invoke({"a": 4, "b": 2})) print(add.name) print(add.description) print(add.args)
调用结果:

使用StructuredTool 类提供的函数创建工具
class langchain_core.tools.structured.StructuredTool 类用来初始化⼯具,其中from_function 类⽅法通过给定的函数来创建并返回⼀个⼯具。 from_function 类⽅法定义如下
classmethod from_function(
func: Callable | None = None,
coroutine: Callable[[...], Awaitable[Any]] | None = None,
name: str | None = None,
description: str | None = None,
return_direct: bool = False,
args_schema: type[BaseModel] | dict[str, Any] | None = None,
infer_schema: bool = True,
*,
response_format: Literal['content', 'content_and_artifact'] = 'content',
parse_docstring: bool = False,
error_on_invalid_docstring: bool = False,
**kwargs: Any,
) → StructuredTool
关键参数说明:
- func:要设置的⼯具函数
- coroutine:协程函数,要设置的异步⼯具函数
- name:⼯具名称。默认为函数名称。
- description:⼯具描述。默认为函数文档字符串。
- args_schema:⼯具输⼊参数的schema。默认为 None。
- response_format:⼯具响应格式。默认为"content"。
- 如果配置为 "content" ,则⼯具的输出为 ToolMessage 的 content 属性。
- 对于 HumanMessage 、AIMessage 已经⻅过,分别表示用户消息和 AI消息响应 , 对于 ToolMessage ,它表示对应⼯具⻆⾊所发出的消息。
- 如果配置为 "content_and_artifact" ,则输出应是与 ToolMessage 的 content 属性与 artifact 属性相对应的⼆元组。
- 如果配置为 "content" ,则⼯具的输出为 ToolMessage 的 content 属性。
实例一:常规用法
from langchain_core.tools import StructuredTool def add(a:int,b:int) ->int: """两数相加 """ return a+b tool = StructuredTool.from_function(add) print(tool.invoke({"a": 1, "b": 2})) print(tool.name) print(tool.description) print(tool.args)
调用结果:

示例2:加入配置,依赖 Pydantic 类
此时可以:
-
使用 args_schema 参数,依赖 Pydantic 类定义并提供工具输入参数的 schema 属性
-
使⽤ description 参数,替代⽂档字符串中对于⼯具描述的 schema 属性
class AddInput(BaseModel): a:int = Field(description="第一个参数") b:int = Field(description="第一个参数") def add(a:int,b:int) -> int: return a+b tool = StructuredTool( func=add, args_schema=AddInput, description="两数相加", name="add", ) print(tool.invoke({"a": 1, "b": 2})) print(tool.name) print(tool.description) print(tool.args)
调用结果

绑定工具
为了实际将这些⼯具绑定到聊天模型,可以使⽤聊天模型的 .bind_tools() 方法。如下所示:
@tool def add( a:Annotated[int,...,"第一个整数"], b:Annotated[int,...,"第二个整数"], ) -> int: """两数相加""" return a + b @tool def multiply( a:Annotated[int,"第一个参数"], b:Annotated[int,"第二个参数"], ) -> int: """两数相乘""" return a * b
key = os.environ['DEEPSEEK_API_KEY'] model = ChatOpenAI( model='deepseek-chat', base_url="https://api.deepseek.com", api_key=key, ) #绑定工具 tools = [add,multiply] model_tool = model.bind_tools(tools=tools) #返回一个绑定了工具的model
bind_tools方法定义
bind_tools(
tools: Sequence[dict[str, Any] | type | Callable | BaseTool],
*,
tool_choice: dict | str | Literal['auto', 'none', 'required', 'any'] | bool
| None = None,
strict: bool | None = None,
parallel_tool_calls: bool | None = None,
**kwargs: Any,
) → Runnable[PromptValue | str | Sequence[BaseMessage | list[str] |
tuple[str, str] | str | dict[str, Any]], BaseMessage]
请求参数:
-
tools :绑定到此聊天模型的⼯具定义列表。⽀持的类型为:字典、pydantic.BaseModel 类、 Python 函数和 BaseTool(如 @tool 装饰器创建的类)。
-
tool_choice (默认空):要求模型调⽤哪个⼯具。可以设置为:
- 形式为 '<<tool_name>>' 的 str:调⽤ <tool_name> ⼯具
- 'auto' :⾃动选择⼯具(包括⽆⼯具)。
- 'none' :不调⽤⼯具。
- 'any' 或 'required' 或 True :强制调⽤⾄少⼀个⼯具。
- False 或 None :⽆效果,默认 OpenAI 的⾏为。
- strict (默认空)
- 如果为 True ,则保证模型输出与⼯具定义中提供的 JSON Schema 完全匹配。输⼊也将根据提供的 Schema 进⾏验证。
- 如果为 False ,则不会验证输⼊,也不会验证模型输出。
- 如果为 None ,则不会将 strict 参数传递给模型。
返回值:
- 返回⼀个 Runnable 实例。