Skip to main content
Open on GitHub

工具

Prerequisites

概述

LangChain中的工具抽象将一个Python函数与一个定义函数名称描述预期参数模式关联起来。

工具可以传递给支持聊天模型工具调用,允许模型请求执行具有特定输入的特定函数。

关键概念

  • 工具是一种封装函数及其模式的方式,可以将其传递给聊天模型。
  • 使用@tool装饰器创建工具,该装饰器简化了工具创建过程,支持以下内容:
    • 自动推断工具的名称描述预期参数,同时支持自定义。
    • 定义返回工件(如图像、数据框等)的工具。
    • 使用注入的工具参数从模式(以及模型)中隐藏输入参数。

工具接口

工具接口定义在BaseTool类中,该类是Runnable Interface的子类。

与工具的模式相对应的关键属性:

  • name: 工具的名称。
  • description: 工具功能的描述。
  • args: 返回工具参数的JSON模式的属性。

执行与工具相关的功能的关键方法:

使用@tool装饰器创建工具

创建工具的推荐方法是使用@tool装饰器。这个装饰器旨在简化工具创建过程,在大多数情况下应该使用它。在定义一个函数后,你可以用@tool装饰它,以创建一个实现工具接口的工具。

from langchain_core.tools import tool

@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
API Reference:tool

有关如何创建工具的更多详细信息,请参阅如何创建自定义工具指南。

note

LangChain 还有其他几种创建工具的方法;例如,通过子类化 BaseTool 类或使用 StructuredTool。这些方法在 如何创建自定义工具指南 中展示,但我们通常建议在大多数情况下使用 @tool 装饰器。

直接使用工具

一旦你定义了一个工具,你可以直接通过调用函数来使用它。例如,使用上面定义的multiply工具:

multiply.invoke({"a": 2, "b": 3})

检查

您还可以检查工具的模式和其他属性:

print(multiply.name) # multiply
print(multiply.description) # Multiply two numbers.
print(multiply.args)
# {
# 'type': 'object',
# 'properties': {'a': {'type': 'integer'}, 'b': {'type': 'integer'}},
# 'required': ['a', 'b']
# }
note

如果您使用的是预构建的LangChain或LangGraph组件,如create_react_agent,您可能不需要直接与工具交互。然而,了解如何使用它们对于调试和测试可能非常有价值。此外,在构建自定义的LangGraph工作流时,您可能会发现有必要直接使用工具。

配置模式

@tool 装饰器提供了额外的选项来配置工具的架构(例如,修改名称、描述或解析函数的文档字符串以推断架构)。

请参阅@tool的API参考以获取更多详细信息,并查看如何创建自定义工具指南以获取示例。

工具工件

工具是模型可以调用的实用程序,其输出设计为反馈给模型。然而,有时我们希望将工具执行的一些产物提供给链或代理中的下游组件,但不希望将其暴露给模型本身。例如,如果工具返回一个自定义对象、数据框或图像,我们可能希望将有关此输出的一些元数据传递给模型,而不将实际输出传递给模型。同时,我们可能希望能够在其他地方访问此完整输出,例如在下游工具中。

@tool(response_format="content_and_artifact")
def some_tool(...) -> Tuple[str, Any]:
"""Tool that does something."""
...
return 'Message for chat model', some_artifact

详情请参阅如何从工具返回工件

特殊类型注解

有许多特殊的类型注释可以在工具的函数签名中使用,以配置工具的运行时行为。

以下类型注释将最终移除工具模式中的参数。这对于不应暴露给模型且模型不应控制的参数非常有用。

  • InjectedToolArg: 值应在运行时使用 .invoke.ainvoke 手动注入。
  • RunnableConfig: 传入RunnableConfig对象到工具中。
  • InjectedState: 将LangGraph图的整体状态传递给工具。
  • InjectedStore: 将LangGraph存储对象传递给工具。

你也可以使用Annotated类型与字符串字面量来为相应的参数提供一个描述,这个描述将会在工具的架构中暴露出来。

  • Annotated[..., "string literal"] -- 向参数添加描述,该描述将在工具的架构中暴露。

注入工具参数

在某些情况下,需要在运行时将某些参数传递给工具,但这些参数不应由模型本身生成。为此,我们使用InjectedToolArg注解,它允许从工具的架构中隐藏某些参数。

例如,如果一个工具需要在运行时动态注入一个user_id,它可以以这种方式构建:

from langchain_core.tools import tool, InjectedToolArg

@tool
def user_specific_tool(input_data: str, user_id: InjectedToolArg) -> str:
"""Tool that processes input data."""
return f"User {user_id} processed {input_data}"
API Reference:tool | InjectedToolArg

使用InjectedToolArg注释user_id参数,告诉LangChain这个参数不应该作为工具模式的一部分暴露出来。

请参阅如何将运行时值传递给工具以获取有关如何使用InjectedToolArg的更多详细信息。

可运行配置

你可以使用RunnableConfig对象将自定义的运行时间值传递给工具。

如果你需要从工具内部访问RunnableConfig对象。这可以通过在工具的函数签名中使用RunnableConfig注解来实现。

from langchain_core.runnables import RunnableConfig

@tool
async def some_func(..., config: RunnableConfig) -> ...:
"""Tool that does something."""
# do something with config
...

await some_func.ainvoke(..., config={"configurable": {"value": "some_value"}})
API Reference:RunnableConfig

config 不会成为工具模式的一部分,并且将在运行时注入适当的值。

note

你可能需要访问config对象以手动将其传播到子类。这种情况发生在你在async环境中使用python 3.9 / 3.10时,并且需要手动将config对象传播到子调用中。

请阅读Propagation RunnableConfig以了解更多详细信息,了解如何手动将RunnableConfig沿调用链传播(或升级到Python 3.11,此问题不再存在)。

注入状态

请参阅InjectedState文档以获取更多详细信息。

注入存储

请参阅InjectedStore文档以获取更多详细信息。

最佳实践

在设计供模型使用的工具时,请记住以下几点:

  • 命名良好、文档正确且类型提示适当的工具更容易被模型使用。
  • 设计简单且范围狭窄的工具,因为它们更容易让模型正确使用。
  • 使用支持tool-calling API的聊天模型以利用工具。

工具包

LangChain 有一个工具包的概念。这是一个非常轻量级的抽象,将设计用于特定任务一起使用的工具组合在一起。

接口

所有工具包都暴露了一个get_tools方法,该方法返回一个工具列表。因此,您可以这样做:

# Initialize a toolkit
toolkit = ExampleTookit(...)

# Get list of tools
tools = toolkit.get_tools()

查看更多信息,请参考以下资源:


这个页面有帮助吗?