工具
概述
LangChain 中的工具抽象将 Python 函数与定义函数名称、描述和预期参数的架构相关联。
可以将工具传递给支持工具调用的聊天模型,允许模型请求执行具有特定输入的特定函数。
关键概念
- 工具是一种以可传递给聊天模型的方式封装函数及其架构的方法。
- 使用 @tool 修饰器创建工具,这简化了工具创建过程,并支持以下功能:
- 自动推断工具的名称、描述和预期参数,同时还支持自定义。
- 定义返回工件的工具(例如图像、数据帧等)
- 使用注入的工具参数从 Schema (以及模型中) 隐藏输入参数。
工具界面
工具接口在 BaseTool 类中定义,该类是 Runnable Interface 的子类。
与工具架构对应的键属性:
- name:工具的名称。
- description:工具用途的描述。
- args:返回工具参数的 JSON 架构的属性。
执行与工具关联的函数的关键方法:
- invoke:使用给定的参数调用该工具。
- ainvoke:使用给定参数异步调用工具。用于 Langchain 的异步编程。
使用@tool装饰
创建工具的推荐方法是使用 @tool 装饰器。此装饰器旨在简化工具创建过程,在大多数情况下应使用。定义函数后,您可以使用 @tool 对其进行装饰,以创建实现 Tool Interface 的工具。
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
有关如何创建工具的更多详细信息,请参阅如何创建自定义工具指南。
LangChain 还有其他一些创建工具的方法;例如,通过子类化 BaseTool 类或使用StructuredTool.这些方法在如何创建自定义工具指南中显示,但
我们通常建议使用@tooldecorator 的 decor 来执行。
直接使用工具
定义工具后,您可以通过调用函数直接使用它。例如,要使用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']
# }
如果您使用的是预构建的 LangChain 或 LangGraph 组件(如 create_react_agent),则可能不需要直接与工具交互。但是,了解如何使用它们对于调试和测试很有价值。此外,在构建自定义 LangGraph 工作流时,您可能会发现有必要直接使用工具。
配置 Schema
这@tooldecorator 提供了其他选项来配置工具的架构(例如,修改名称、描述
或解析函数的文档字符串以推断架构)。
有关更多详细信息,请参阅 API 参考 @tool 并查看如何创建自定义工具指南 有关示例。
工具伪像
工具是可由模型调用的实用程序,其输出旨在反馈给模型。然而,有时,我们希望让 chain 或 agent 中的下游组件可以访问工具执行的工件,但我们不想将其暴露给模型本身。例如,如果工具返回自定义对象、数据帧或图像,我们可能希望将有关此输出的一些元数据传递给模型,而不将实际输出传递给模型。同时,我们可能希望能够在其他地方访问此完整输出,例如在下游工具中。
@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 store 对象传入工具。
您还可以使用Annotatedtype 替换为字符串文字,为将在工具架构中公开的相应参数提供描述。
- Annotated[..., “string literal”] -- 为将在工具架构中公开的参数添加描述。
InjectedToolArg
在某些情况下,某些参数需要在运行时传递给工具,但不应由模型本身生成。为此,我们使用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}"
对user_id参数替换为InjectedToolArg告诉 LangChain 这个参数不应该作为
工具的 schema。
有关如何使用InjectedToolArg.
RunnableConfig
您可以使用RunnableConfigobject 将自定义运行时值传递给工具。
如果您需要从工具中访问 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"}})
这config将不是工具方案的一部分,并将在运行时以适当的值注入。
您可能需要访问configobject 手动将其传播到 subclass。如果您在异步环境中使用 python 3.9 / 3.10 并且需要手动传播configobject 添加到子调用中。
请阅读 传播 RunnableConfig 了解更多详细信息,了解如何传播RunnableConfig手动沿调用链向下(或升级到 Python 3.11,这不再是问题)。
注入状态
有关更多详细信息,请参阅 InjectedState 文档。
注入存储
有关更多详细信息,请参阅 InjectedStore 文档。
最佳实践
在设计模型要使用的工具时,请记住以下几点:
- 名称正确、文档正确且类型提示正确的工具更易于模型使用。
- 设计简单且范围狭窄的工具,因为它们更容易被模型正确使用。
- 使用支持工具调用 API 的聊天模型来利用工具。
工具包
LangChain 有一个工具包的概念。这是一个非常薄的抽象,它将工具组合在一起,该 旨在一起用于特定任务。
接口
所有 Toolkit 都公开了get_tools方法返回工具列表。因此,您可以执行以下作:
# Initialize a toolkit
toolkit = ExampleTookit(...)
# Get list of tools
tools = toolkit.get_tools()
相关资源
有关更多信息,请参阅以下资源: