LangChain工具调用完全指南:从基础到实战
在LangChain框架中,工具(Tools)是让大语言模型(LLM)能够与外部系统、API或函数进行交互的核心组件。通过工具,LLM可以执行计算、查询数据、调用外部服务等操作,从而突破纯文本生成的限制,实现更强大的功能。Schema是描述数据结构的声明格式,用于自动验证数据。在JSON Schema中,我们定义数据的类型、字段、格式等约束条件。// 示例1:简单结构"name": "张小红","
什么是LangChain工具?
在LangChain框架中,工具(Tools)是让大语言模型(LLM)能够与外部系统、API或函数进行交互的核心组件。通过工具,LLM可以执行计算、查询数据、调用外部服务等操作,从而突破纯文本生成的限制,实现更强大的功能。
2.1 创建工具
2.1.1 使用@tool装饰器创建工具
@tool装饰器是LangChain中创建工具的最简单方法。它通过装饰Python函数来定义工具,自动从函数名、类型提示和文档字符串中提取工具的相关属性。
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two integers.
Args:
a: First integer
b: Second integer
"""
return a * b
print(multiply.invoke({"a": 2, "b": 3})) # 输出:6
print(multiply.name) # 输出:multiply
print(multiply.description) # 输出:Multiply two integers...
print(multiply.args) # 输出:{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
关键特性:
-
默认使用函数名称作为工具名称
-
使用函数的文档字符串作为工具描述
-
函数名、类型提示和文档字符串都是传递给工具Schema的重要组成部分
什么是Schema?
Schema是描述数据结构的声明格式,用于自动验证数据。在JSON Schema中,我们定义数据的类型、字段、格式等约束条件。
示例对比:
// 示例1:简单结构
{
"name": "张小红",
"birthday": "1732年2月22日",
"address": "陕西省西安市雁塔区"
}
// 示例2:结构化结构
{
"surname": "王",
"given_name": "刚",
"birthday": "1732-02-22",
"address": {
"district": "萧山区",
"city": "杭州市",
"province": "浙江省",
"country": "中国"
}
}
对应的JSON Schema:
{
"type": "object",
"properties": {
"surname": { "type": "string" },
"given_name": { "type": "string" },
"birthday": { "type": "string", "format": "date" },
"address": {
"type": "object",
"properties": {
"district": { "type": "string" },
"city": { "type": "string" },
"province": { "type": "string" },
"country": { "type": "string" }
}
}
}
}
Google风格文档字符串:
Google风格是Python文档字符串的一种写作规范,使用Args:、Returns:等关键字,参数描述简洁明了:
def fetch_data(url, retries=3):
"""从给定的URL获取数据。
Args:
url (str): 要从中获取数据的URL。
retries (int, optional): 失败时重试的次数。默认为3。
Returns:
dict: 从URL解析的JSON响应。
"""
# 函数实现
2.1.1.1 模式1:依赖Pydantic类
当函数没有提供文档字符串时,可以使用Pydantic类来定义工具Schema:
from langchain_core.tools import tool
from pydantic import BaseModel, Field
class AddInput(BaseModel):
"""Add two integers."""
a: int = Field(..., description="First integer")
b: int = Field(..., description="Second integer")
class MultiplyInput(BaseModel):
"""Multiply two integers."""
a: int = Field(..., description="First integer")
b: int = Field(..., description="Second integer")
@tool(args_schema=AddInput)
def add(a: int, b: int) -> int:
# 未提供描述
return a + b
@tool(args_schema=MultiplyInput)
def multiply(a: int, b: int) -> int:
# 未提供描述
return a * b
注意: 除非提供默认值,否则所有字段都是required。
2.1.1.2 模式2:依赖Annotated
使用Annotated和文档字符串传递工具Schema:
from langchain_core.tools import tool
from typing_extensions import Annotated
@tool
def add(
a: Annotated[int, ..., "First integer"],
b: Annotated[int, ..., "Second integer"]
) -> int:
"""Add two integers."""
return a + b
@tool
def multiply(
a: Annotated[int, ..., "First integer"],
b: Annotated[int, ..., "Second integer"]
) -> int:
"""Multiply two integers."""
return a * b
2.1.2 使用StructuredTool类创建工具
StructuredTool.from_function类方法通过给定的函数来创建并返回一个工具:
from langchain_core.tools import StructuredTool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
calculator_tool = StructuredTool.from_function(func=multiply)
print(calculator_tool.invoke({"a": 2, "b": 3})) # 输出:6
关键参数说明:
-
func:要设置的函数 -
name:工具名称,默认为函数名称 -
description:工具描述,默认为函数文档字符串 -
args_schema:工具输入参数的schema -
response_format:工具响应格式,默认为"content"
2.1.2.2 加入配置,依赖Pydantic类
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
def multiply(a: int, b: int) -> int:
return a * b
calculator_tool = StructuredTool.from_function(
func=multiply,
name="Calculator",
description="两数相乘",
args_schema=CalculatorInput,
)
print(calculator_tool.invoke({"a": 2, "b": 3})) # 输出:6
print(calculator_tool.name) # 输出:Calculator
print(calculator_tool.description) # 输出:两数相乘
print(calculator_tool.args) # 输出:{'a': {'description': 'first number', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'second number', 'title': 'B', 'type': 'integer'}}
2.1.2.3 加入response_format配置
当需要区分消息内容(content)和其他工件(artifact)时,可以使用response_format="content_and_artifact":
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field
from typing import List, Tuple
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
def multiply(a: int, b: int) -> Tuple[str, List[int]]:
nums = [a, b]
content = f"{nums}相乘的结果是{a * b}"
return content, nums
calculator_tool = StructuredTool.from_function(
func=multiply,
name="Calculator",
description="两数相乘",
args_schema=CalculatorInput,
response_format="content_and_artifact"
)
# 直接调用工具,只返回content
print(calculator_tool.invoke({"a": 2, "b": 3})) # 输出:[2, 3]相乘的结果是6
# 模拟大模型调用,返回ToolMessage
print(calculator_tool.invoke({
"name": "Calculator",
"args": {"a": 2, "b": 3},
"id": "123", # 必须,工具调用标识符
"type": "tool_call", # 必须
}))
输出结果:
content='[2, 3]相乘的结果是6' name='Calculator' tool_call_id='123' artifact=[2, 3]
artifact的作用:
-
保存原始结构化数据,供链中后续组件使用
-
不适合直接塞给大模型
-
可用于日志记录、数据分析、自定义处理等场景
2.2 绑定工具
使用聊天模型的.bind_tools()方法将工具绑定到模型:
from langchain_openai import ChatOpenAI
# 定义大模型
model = ChatOpenAI(model="gpt-4o-mini")
# 绑定工具,返回一个Runnable实例
tools = [add, multiply]
model_with_tools = model.bind_tools(tools)
bind_tools()方法参数:
-
tools:绑定的工具定义列表 -
tool_choice:要求模型调用哪个工具-
'<<tool_name>>':调用指定工具 -
'auto':自动选择工具 -
'none':不调用工具 -
'any'或'required'或True:强制调用至少一个工具
-
-
strict:是否严格验证输入输出 -
parallel_tool_calls:是否允许并行工具调用
2.3 工具调用
使用绑定的Runnable实例调用.invoke()方法完成工具调用:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from typing_extensions import Annotated
# 定义大模型
model = ChatOpenAI(model="gpt-4o-mini")
@tool
def add(
a: Annotated[int, ..., "First integer"],
b: Annotated[int, ..., "Second integer"]
) -> int:
"""Add two integers."""
return a + b
@tool
def multiply(
a: Annotated[int, ..., "First integer"],
b: Annotated[int, ..., "Second integer"]
) -> int:
"""Multiply two integers."""
return a * b
# 绑定工具
tools = [add, multiply]
model_with_tools = model.bind_tools(tools)
# 调用工具
result = model_with_tools.invoke("9乘6等于多少?")
print(result)
输出结果(AIMessage):
content='' additional_kwargs={'tool_calls': [{'id': 'call_mBnxNMY7vfAOrExEETcdEC6l', 'function': {'arguments': '{"a":9,"b":6}', 'name': 'multiply'}, 'type': 'function'}], 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 86, 'total_tokens': 103, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_560af6e559', 'id': 'chatcmpl-C6DSvbskJtwUl6YTkPILUaiDdDuEN', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None} id='run--1f43e942-d56b-4d6d-8d3f-145b7e5d0036-0' tool_calls=[{'name': 'multiply', 'args': {'a': 9, 'b': 6}, 'id': 'call_mBnxNMY7vfAOrExEETcdEC6l', 'type': 'tool_call'}] usage_metadata={'input_tokens': 86, 'output_tokens': 17, 'total_tokens': 103, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}
关键输出字段:
-
content:消息内容 -
additional_kwargs:工具调用信息 -
tool_calls:工具调用详情(名称、参数、ID) -
finish_reason:完成原因(tool_calls表示调用了工具)
2.4 强制模型调用工具
通过设置tool_choice="any"强制模型调用至少一个工具:
model_with_tools = model.bind_tools(tools, tool_choice="any")
result = model_with_tools.invoke("hello world!")
print(result)
2.5 工具属性
如果调用了工具,result将具有tool_calls属性:
model_with_tools = model.bind_tools(tools, tool_choice="any")
result = model_with_tools.invoke("9乘6等于多少?")
print(result.tool_calls)
输出结果:
[{'name': 'multiply', 'args': {'a': 9, 'b': 6}, 'id': 'call_csFbMmYD4Dmz8yMja3ZWK1QW', 'type': 'tool_call'}]
总结
LangChain的工具系统提供了灵活的方式来扩展大语言模型的能力。通过@tool装饰器、StructuredTool类以及Pydantic模型,我们可以轻松定义各种工具,并将其绑定到聊天模型中。工具调用机制使得LLM能够与外部系统交互,实现更复杂的应用场景。
核心要点:
-
工具定义需要函数名、类型提示和文档字符串
-
可以使用Pydantic类或Annotated来定义Schema
-
通过
bind_tools()方法将工具绑定到模型 -
工具调用返回AIMessage,包含工具调用信息
-
可以强制模型调用工具或让模型自动选择
掌握这些工具调用技术,将为构建更强大的AI应用奠定坚实基础。
更多推荐

所有评论(0)