langchain_core.tools 模块详解

langchain_core.tools 是 LangChain 框架中用于定义和管理工具的核心模块,工具是代理(Agents)、链(Chains)或大语言模型(LLMs)与外部世界交互的接口。本文结合前文内容,详细介绍该模块的功能、主要组件、使用方法、实际应用及注意事项,确保内容条理清晰、易于理解。

1. 概述

1.1 什么是 langchain_core.tools

langchain_core.tools 模块提供了一套类和函数,用于创建、配置和管理工具。工具是封装特定功能的组件,例如数据检索、数学计算或 API 调用,允许语言模型通过调用工具与外部系统交互。该模块通过标准化的接口和灵活的配置选项,确保工具与 LangChain 的可运行对象(Runnable)生态系统无缝集成。

工具的核心作用是为模型提供结构化的调用接口,结合名称、描述和 JSON 模式,指导模型选择和使用工具。模块在 langchain-core 0.2.14 版本中引入,工件支持在 0.2.19 版本添加。

1.2 与其他组件的关系

  • BaseTool:前文讨论的 BaseTool 是模块中的核心抽象基类,所有工具都继承自它。
  • @tool 装饰器tool 装饰器是模块的实用函数,简化工具创建,自动将函数转换为 BaseTool 实例。
  • InjectedToolArg:模块支持通过 InjectedToolArg 标记运行时注入参数,增强安全性。
  • chain 装饰器:结合 langchain_core.runnables.chain,可在工具调用链中注入参数或处理工具输出。

1.3 核心功能

  • 工具定义:提供基类(如 BaseTool)和实现(如 ToolStructuredTool)以定义工具。
  • 输入验证:通过 Pydantic 模型验证工具输入,确保类型安全。
  • 运行时注入:支持通过 InjectedToolArg 注入敏感参数,防止模型生成。
  • 工件支持:工具可返回内容和工件(如图片、数据框),工件用于下游处理。
  • 灵活集成:工具与 LangChain Expression Language (LCEL) 兼容,可组成复杂链。
  • 版本要求:需 langchain-core>=0.2.14,工件支持需 >=0.2.19。

2. 模块结构与主要组件

以下是 langchain_core.tools 模块的主要组件,按类别组织:

2.1 基类和接口

组件 描述
BaseTool 抽象基类,所有工具的父类,继承自 RunnableSerializable。定义工具接口,包括同步(_run)和异步(_arun)执行方法,支持 invokebatchstream 等操作。
BaseToolkit 工具包基类,用于组织一组相关工具,便于功能分组和管理。

2.2 工具实现

组件 描述
Tool 简单工具类,继承自 BaseTool,包装函数或协程,适合单一输入场景。
StructuredTool 支持多参数输入的工具,使用 Pydantic 模式定义输入结构,适合复杂场景。
RetrieverInput 输入模式(推测为 Pydantic 模型),用于定义检索器工具的输入结构。

2.3 注解和异常

组件 描述
InjectedToolArg 注解,标记不应由模型生成的参数,由运行时注入,增强安全性。
InjectedToolCallId 注解(推测),用于注入工具调用 ID,可能用于跟踪或日志。
SchemaAnnotationError args_schema 缺失或类型注解错误时抛出的异常。
ToolException 工具执行错误时抛出的可选异常,用于错误处理。

2.4 实用函数

函数 描述
tool 装饰器或函数,将 Python 函数转换为工具,自动推断名称、描述和参数。
create_schema_from_function 从函数签名创建 Pydantic 模式,用于定义工具输入结构。
get_all_basemodel_annotations 获取 Pydantic BaseModel 及其父类的所有注解。
convert_runnable_to_tool 将任何 Runnable 对象转换为 BaseTool,增强灵活性。
render_text_description 生成工具名称和描述的文本,用于提示模型。
render_text_description_and_args 生成工具名称、描述和参数的文本,用于提示模型。
create_retriever_tool 创建文档检索工具,集成 LangChain 的检索器组件。

3. 使用方法

以下是 langchain_core.tools 模块的主要使用方式,结合前文内容展示具体示例:

3.1 继承 BaseTool

为复杂工具创建子类,定义 namedescriptionargs_schema 并实现 _run_arun

from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field
from typing import Optional, Type
from langchain_core.callbacks import CallbackManagerForToolRun

class CalculatorInput(BaseModel):
    a: int = Field(description="第一个数字")
    b: int = Field(description="第二个数字")

class CustomCalculatorTool(BaseTool):
    name = "Calculator"
    description = "用于回答数学相关问题"
    args_schema: Type[BaseModel] = CalculatorInput
    return_direct: bool = True

    def _run(
        self,
        a: int,
        b: int,
        run_manager: Optional[CallbackManagerForToolRun] = None
    ) -> int:
        """执行工具"""
        return a * b

    async def _arun(
        self,
        a: int,
        b: int,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None
    ) -> int:
        """异步执行工具"""
        return self._run(a, b, run_manager=run_manager)

调用方式

tool = CustomCalculatorTool()
result = tool.invoke({"a": 2, "b": 3})  # 输出 6

3.2 使用 @tool 装饰器

简化工具创建,自动推断模式:

from langchain_core.tools import tool

@tool
def add_numbers(a: int, b: int) -> int:
    """添加两个数字"""
    return a + b

调用方式

result = add_numbers.invoke({"a": 2, "b": 3})  # 输出 5

3.3 结合 InjectedToolArg

标记运行时注入参数,增强安全性:

from langchain_core.tools import tool, InjectedToolArg
from typing import Annotated, List

@tool
def update_favorite_pets(pets: List[str], user_id: Annotated[str, InjectedToolArg]) -> None:
    """更新用户的收藏宠物"""
    user_to_pets[user_id] = pets  # 假设的存储

注入参数(结合 chain 装饰器):

from langchain_core.runnables import chain

@chain
def inject_user_id(input):
    """注入用户 ID 到工具调用"""
    tool_call = input["tool_call"]
    user_id = input["user_id"]
    tool_call_copy = tool_call.copy()
    tool_call_copy["args"]["user_id"] = user_id
    return {"tool_call": tool_call_copy}

chain = inject_user_id | update_favorite_pets
chain.invoke({"tool_call": {"name": "update_favorite_pets", "args": {"pets": ["dog"]}}, "user_id": "123"})

3.4 创建检索工具

使用 create_retriever_tool 创建文档检索工具:

from langchain_core.tools import create_retriever_tool
from langchain_core.vectorstores import VectorStoreRetriever

retriever = VectorStoreRetriever(...)  # 假设的检索器
tool = create_retriever_tool(
    retriever,
    name="search_documents",
    description="搜索相关文档"
)

4. 参数与配置

以下是模块中主要组件的关键参数:

4.1 BaseTool 初始化参数

参数 类型 默认值 描述
args_schema Type[BaseModel] | None None Pydantic 模型,定义输入参数结构和验证。
description str 无默认 工具描述,指导模型使用。
return_direct bool False 若为 True,输出直接返回,代理停止处理。
response_format Literal['content', 'content_and_artifact'] 'content' 输出格式:仅内容或内容加工件。
handle_tool_error bool | str | Callable False 处理 ToolException 的方式。

4.2 @tool 装饰器参数

参数 类型 默认值 描述
name_or_callable Optional[str | Callable] None 工具名称或可调用对象。
description str | None None 工具描述,优先级高于文档字符串。
return_direct bool False 若为 True,输出直接返回。
args_schema Type[BaseModel] | dict | None None 参数模式,定义输入结构。
response_format Literal['content', 'content_and_artifact'] 'content' 输出格式。
parse_docstring bool False 若为 True,解析 Google 风格文档字符串。
error_on_invalid_docstring bool True 若为 True,无效文档字符串抛出错误。

5. 实际应用

langchain_core.tools 模块在以下场景中广泛使用:

  • 代理系统:为代理提供工具列表,代理根据输入选择工具。例如,数学计算工具、搜索工具。
  • 自定义工作流:在 LangGraph 或链中集成工具,实现模块化功能。例如,数据处理管道。
  • 工件处理:工具返回内容和工件,工件用于下游处理,如生成图片或数据框。
  • 运行时注入:结合 InjectedToolArg,为工具注入敏感参数,如用户 ID。

示例:综合应用

创建一个工具链,结合 InjectedToolArgchain 装饰器:

from langchain_core.tools import tool, InjectedToolArg
from langchain_core.runnables import chain
from typing import Annotated, List

@tool
def update_user_profile(name: str, user_id: Annotated[str, InjectedToolArg]) -> str:
    """更新用户配置文件"""
    return f"Updated profile for user {user_id} with name {name}"

@chain
def inject_user_id(input):
    """注入用户 ID"""
    return {**input, "user_id": "123"}

chain = inject_user_id | update_user_profile
result = chain.invoke({"name": "Alice"})  # 输出 "Updated profile for user 123 with name Alice"

6. 最佳实践

  • 清晰描述:为工具提供详细的 description,包含少样本示例,帮助模型选择。
  • 输入验证:使用 args_schema 定义和验证输入,确保类型安全。
  • 注入参数:结合 InjectedToolArg 保护敏感信息,防止模型生成。
  • 文档字符串:使用 Google 风格文档字符串,确保 parse_docstring=True 时正确解析。
  • 版本检查:确保安装 langchain-core>=0.2.14,工件支持需 >=0.2.19,通过 pip install -qU langchain

7. 注意事项与限制

  • 抽象方法:继承 BaseTool 时必须实现 _run,否则抛出 NotImplementedError
  • 文档字符串格式:若使用 parse_docstring=True,需正确格式化 Google 风格文档字符串,否则可能抛出 SchemaAnnotationError
  • 版本依赖:工件支持等功能需特定版本。
  • 工件格式:工件需为可序列化对象(如字典、字节)。
  • 类方法支持:在类方法上使用 @tool 可能需变通方法,建议使用 StructuredTool.from_function

8. 结论

langchain_core.tools 模块为 LangChain 提供了定义和管理工具的强大功能,通过基类(如 BaseTool)、工具实现(如 StructuredTool)和实用函数(如 @tool),支持开发者创建自定义工具并集成到复杂应用程序中。其支持输入验证、运行时注入和工件输出,确保工具的高效性和安全性。结合 InjectedToolArgchain 装饰器,模块在代理系统和自定义工作流中表现尤为出色。

9. 参考资料

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐