LangChain:绑定工具Ⅱ
为什么要绑定工具?
在没有绑定工具时,模型只会输出纯文本。绑定工具后,模型就能在回答问题时自动判断是否需要调用某个工具,如果需要,它会在输出中包含一个工具调用请求(Tool Call),你的程序可以捕获这个请求并真正执行对应的函数,然后将结果返回给模型继续对话。这种能力被称为 Function Calling 或 Tool Use。
1、绑定工具的方式
使用聊天模型的 .bind_tools() 方法,将工具列表传递进去即可。
from langchain_openai import ChatDeepSeek
# 定义大模型
model = ChatDeepSeek(model="deepseek-chat")
# 假设你已经提前定义好了两个工具:add 和 multiply
tools = [add, multiply]
# 绑定工具,返回一个 Runnable 实例
model_with_tools = model.bind_tools(tools)
这里 add 和 multiply 是提前用 @tool 装饰器或 Pydantic 类定义的工具对象。绑定后,model_with_tools 就变成了一个“具备工具调用能力的代理”,接下来就可以像普通模型一样使用它。
注意:
bind_tools()返回的不是模型本身,而是一个Runnable实例,这意味着你可以使用.invoke()、.stream()等方法与它交互。
2、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[...]
2.1、tools (必填)
要绑定到此聊天模型的工具定义列表。
支持多种工具描述形式:
-
字典:直接传递符合 OpenAI Function Calling 格式的字典。
-
Pydantic BaseModel 类:定义一个继承自
BaseModel的类,模型会用该类的 Schema 生成函数调用。 -
Python 函数:一个普通 Python 函数,LangChain 会自动解析其签名和 docstring 来生成工具描述。
-
BaseTool 实例:通过
@tool装饰器创建的 LangChain 工具对象。
# 方式1:直接使用函数
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
# 方式2:使用 @tool 装饰器
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
tools = [add, multiply] # 函数也可直接使用
2.2、tool_choice (可选,默认 None)
控制模型必须或倾向于调用哪个工具。
-
设置为字符串
"tool_name":
强制模型只能调用名为tool_name的工具,比如"add"。 -
"auto":模型自行决定是否调用工具,以及调用哪个工具(这是默认的 OpenAI 行为)。 -
"none":禁止模型调用任何工具,相当于没有绑定工具的效果。 -
"any"或"required"或True:强制模型至少调用一个工具,但具体调用哪个由模型决定。 -
False或None:无效值,保持模型默认行为(即等同于未设置)。
# 强制只调用 multiply
model_with_tools = model.bind_tools(tools, tool_choice="multiply")
2.3、strict (可选,默认 None)
控制是否要求模型按照工具的 JSON Schema 严格输出。
-
True:-
保证模型生成的结构化输出完全匹配工具定义中的 Schema。
-
输入也会根据 Schema 进行验证。
-
-
False:不对模型输出进行严格验证,也不验证输入。 -
None:不向底层 API 传递strict参数,由 API 采用默认行为。
建议在需要精确工具调用回复的生产环境中开启
strict=True,以避免格式错误。
2.4、parallel_tool_calls (可选,默认 None)
是否允许模型在一次回复中并行调用多个工具。
-
None:允许并行调用(默认开启)。 -
False:禁止并行调用,模型一次只能返回一个工具调用的请求。
2.5、**kwargs (其他参数)
任何额外的关键字参数都会被直接传递给底层的 bind() 方法,用于满足不同模型提供商的特殊参数需求。
3、返回值:Runnable 实例
bind_tools() 返回的是一个 Runnable,它封装了模型和工具的定义。
支持的输入格式:
-
PromptValue(原始提示对象)
-
字符串,比如:“上海天气如何?”
-
消息或消息列表,例如:
[HumanMessage(content="上海天气如何?")]
输出内容:
返回的通常是 AIMessage,其中可能包含:
-
普通的文本回复
-
一个或多个
tool_calls(工具调用请求),每个调用包含工具名称、参数等信息。
示例输出结构(概念):
AIMessage(
content="",
tool_calls=[{
"name": "add",
"args": {"a": 3, "b": 5},
"id": "call_abc123"
}]
)
4、工具调用实战:从绑定到调用
绑定完成后,下一步就是通过 .invoke() 触发调用。
from langchain_openai import ChatDeepSeek
from langchain_core.messages import HumanMessage
# 定义工具
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
def multiply(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
# 绑定工具
model = ChatDeepSeek(model="deepseek-chat")
model_with_tools = model.bind_tools([add, multiply])
# 构造输入消息
messages = [HumanMessage(content="3加5等于多少?")]
# 调用模型
response = model_with_tools.invoke(messages)
# 查看模型是否想要调用工具
if response.tool_calls:
for tool_call in response.tool_calls:
print(f"欲调用工具:{tool_call['name']},参数:{tool_call['args']}")
else:
print("模型直接回复:", response.content)
如果一切正常,输出会显示模型希望调用 add 工具,参数为 {"a": 3, "b": 5}。
5、小结
绑定工具 是让聊天模型具备外部工具调用能力的关键一步。
使用 model.bind_tools(tools) 即可完成绑定,返回一个 Runnable。
通过参数 tool_choice、strict 和 parallel_tool_calls 可以精细控制工具调用的行为。
绑定后,调用 .invoke() 发送消息,模型会根据对话内容决定是否返回工具调用请求。
更多推荐
所有评论(0)