LangChain:调用工具Ⅲ

在 绑定工具Ⅱ中,我们通过 model.bind_tools(tools) 得到了一个 Runnable 实例 model_with_tools。这个实例就像一个普通的聊天模型,可以接受消息并给出回复,但它多了一个能力:在需要的时候,回复中会包含工具调用的请求。

本篇文章会聚焦在一个完整的调用流程上:定义工具 → 绑定模型 → 用 .invoke() 触发调用 → 解读返回的 AIMessage。


1、准备工具:用 @tool 装饰器定义函数

python 复制代码
from langchain_openai import ChatDeepSeek
from langchain.core.messages import HumanMessage
from langchain.core.tools import tool
from typing_extensions import Annotated

# 定义大模型
model = ChatDeepSeek(model="deepseek-chat")

@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

关于 Annotated
Annotated[int, "First integer"] 这种写法告诉 LangChain 这个参数的类型是 int,并且附加了人类可读的描述 "First integer"。这样在生成工具调用的 JSON Schema 时,模型就能更准确地理解每个参数的含义。

现在,add 和 multiply 已是两个标准的 LangChain 工具对象,可以被 bind_tools() 识别。


2、绑定并调用

python 复制代码
tools = [add, multiply]
model_with_tools = model.bind_tools(tools)

# 调用工具
result = model_with_tools.invoke("9乘6等于多少?")
print(result)

这里的关键是 .invoke()。我们直接传了一个中文问题 "9乘6等于多少?",模型需要判断:

  1. 这个问题是否需要工具?

  2. 如果需要,选哪个工具?

  3. 调用该工具时需要什么参数?

结果 result 是一个 AIMessage 对象:

python 复制代码
AIMessage(
    content='',
    additional_kwargs={
        'tool_calls': [{
            'id': 'call_mbNxNYVfA0rExEETcdECG1',
            'function': {'name': 'multiply', 'arguments': {'a': 9, 'b': 6}},
            'type': 'function'
        }],
        'refusal': None
    },
    response_metadata={
        'token_usage': { ... },
        'model_name': 'deepseek-chat',
        'finish_reason': 'tool_calls',
        ...
    },
    id='run--1f43e942-d5bb-46dd-8df3-f45b75ed0836-0',
    tool_calls=[{
        'name': 'multiply',
        'args': {'a': 9, 'b': 6},
        'id': 'call_mbNxNYVfA0rExEETcdECG1',
        'type': 'tool_call'
    }],
    usage_metadata={'input_tokens': 86, 'output_tokens': 17, 'total_tokens': 103}
)

content (消息正文)

  • 值为空字符串 ''。

  • 表示模型这次没有生成文本回复 ,而是直接选择调用工具。如果模型想同时给出文字说明,content 中就会包含那段话。

additional_kwargs

  • 这是附加的有效负载数据,通常由模型提供程序直接编码。

  • 其中的 tool_calls 是一个列表,包含了模型计划调用的工具信息:

    • id:这次工具调用的唯一标识。

    • function:{'name': 'multiply', 'arguments': {'a': 9, 'b': 6}},指出要调用的函数名及参数。

    • type:'function',固定表示函数调用。

response_metadata

  • 存放响应的元数据,例如:

    • token_usage:本次请求消耗的 token 数。

    • model_name:实际作答的模型版本。

    • finish_reason:结束原因,这里是 'tool_calls',说明模型因要调用工具而停止生成。这也是我们判断是否需要进行工具调用的一个重要标志。

tool_calls (最常用)

  • LangChain 为了方便开发者,直接解析了 additional_kwargs 中的工具调用信息,放在了顶层的 tool_calls 属性里。

  • 它是一个列表,每个元素是一个字典,包含:

    • name:工具名('multiply')。

    • args:参数字典({'a': 9, 'b': 6})。

    • id:调用唯一 ID。

    • type:类型。

  • 实战中我们通常直接使用 result.tool_calls 来获取工具调用请求 ,而不必手动钻入 additional_kwargs。

usage_metadata

  • 统计了本次调用的 token 使用情况,方便计费和性能监控。
字段 含义 关键作用
content 模型的文本回复 为空字符串 '' 表示模型这次没有生成文本回复,而是直接选择调用工具。如果模型想同时给出文字说明,这里会包含对应的文本。
additional_kwargs 附加的有效负载数据 由模型提供程序直接编码,其中的 tool_calls 列表包含了模型计划调用的工具信息。
tool_calls LangChain 解析后的工具调用信息 最常用的字段,直接包含了工具名、参数和调用 ID,实战中通常用 result.tool_calls 获取调用请求。
response_metadata 响应的元数据 包含 token_usage(本次请求消耗的 token 数)、model_name(实际作答的模型版本)、finish_reason(结束原因)。其中 finish_reason='tool_calls' 是关键标志,说明模型因要调用工具而停止生成。
usage_metadata token 使用统计 方便计费和性能监控,和 response_metadata 中的 token_usage 信息一致。

3、小结

通过 .bind_tools() + .invoke(),我们让模型从"纯聊天"升级为"能主动提出工具调用需求"的智能体。返回的 AIMessage 中,tool_calls 是核心字段,它明确指出了要调用的函数名和参数。

相关推荐
外收内放3 小时前
面向对象高级(实战案例)
开发语言·python·学习
专业程序开发源4 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
FPGA小迷弟4 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
c++·python·ai·plotly·django·ai编程·claude
卷无止境4 小时前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
fanruitian4 小时前
python else用法
开发语言·python
Thinker QAQ5 小时前
并发编程(十一):Shared Memory 与 Message Passing——关系与组合使用
java·python·go·并发编程·shared memory·message passing
用户8356290780515 小时前
如何使用 Python 对 Excel 数据进行分组和分级显示
后端·python
vx_Biye_Design5 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express
学Linux的语莫7 小时前
python中类的常见写法
开发语言·python·状态模式
垆边人似月.7 小时前
Python中如何使用get函数实现频次查询
服务器·前端·python