111.Agent-LangChain核心组件-Tools工具

**摘要:**本文围绕 LangChain 中工具(Tool)的定义与使用展开,重点讲解 @tool 注解的常用参数、Pydantic 的 Field 字段约束方式,以及如何通过 args_schema 将 Pydantic 模型接入工具,帮助大模型正确识别并调用函数。

内容参考于:图灵AI大模型全栈

工具就是大模型调用函数的能力

LangChain内置工具:https://docs.langchain.com/oss/python/integrations/tools

工具用到了@tool注解,如下图红框,注解里可以写的值

参数说明:

  • name_or_callable: str | Callable ..., Any | None = None:待包装函数或者工具名称;不传函数时作为装饰器,传函数则直接生成工具。
  • runnable: Runnable Any, Any | None = None:传入 LangChain Runnable 对象,使用该 Runnable 作为工具执行逻辑,替代被装饰函数。
  • *args: Any:内部兼容旧版本重载用的可变位置参数,业务代码不要手动传入。
  • description: str | None = None:工具功能描述,提供给大模型判断何时调用该工具;不填默认读取函数 docstring。
  • return_direct: bool = False:工具执行完毕后是否直接返回结果给用户,不再交由大模型继续思考。
  • args_schema: ArgsSchema | None = None:自定义 Pydantic 模型,定义工具入参 JSON 结构,优先级高于自动推断。
  • infer_schema: bool = True:是否自动从函数签名推断参数模型,关闭后必须手动提供 args_schema。
  • response_format: Literal "content", "content_and_artifact" = "content":工具返回结构;content 仅返回文本,content_and_artifact 返回摘要 content 与原始数据 artifact。
  • parse_docstring: bool = False:是否解析函数文档字符串,提取参数说明填充到工具 schema。
  • error_on_invalid_docstring: bool = True:开启 parse_docstring 时,文档字符串解析失败是否抛出异常;False 则静默忽略。
  • extras: dict str, Any | None = None:挂载到工具实例上的自定义元数据字典,大模型不可见,仅业务代码读取。

Python是一个是动态的语言,变量没有强制类型,它通过 Field 来对数据结构进行约束

参数说明:

  • default: Any = PydanticUndefined:字段默认值;不设置代表无默认值,必填。
  • default_factory: Callable \[, Any] | Callable \[dict \[str, Any], Any] | None = _Unset:工厂函数,用于动态生成字段默认值,不能和 default 同时使用。
  • alias: str | None = _Unset:序列化与反序列化通用别名,外部传入 key 和模型字段名不一致时使用。
  • alias_priority: int | None = _Unset:别名优先级,数值越大优先级越高,控制多个别名冲突时的选择。
  • validation_alias: str | AliasPath | AliasChoices | None = _Unset:仅反序列化校验阶段使用的别名,读取输入数据时生效,序列化输出不生效。
  • serialization_alias: str | None = _Unset:仅序列化输出阶段使用的别名,转 json 输出时替换字段名。
  • title: str | None = _Unset:生成 JSON Schema 时的标题文本。
  • field_title_generator: Callable \[str, FieldInfo, str] | None = _Unset:自定义回调函数,动态生成字段 title。
  • description: str | None = _Unset:JSON Schema 里字段描述,给 LLM / 文档查看。
  • examples: list Any | None = _Unset:JSON Schema 示例值列表,用于文档展示。
  • exclude: bool | None = _Unset:序列化时是否排除此字段,True 则输出 json 不包含该字段。
  • exclude_if: Callable \[Any, bool] | None = _Unset:回调函数,满足条件时序列化自动排除字段。
  • discriminator: str | types.Discriminator | None = _Unset:多态 Union 模型的鉴别器字段,用来自动匹配子模型。
  • deprecated: Deprecated | str | bool | None = _Unset:标记字段废弃,JSON Schema 增加 deprecated 标记。
  • json_schema_extra: JsonDict | Callable \[JsonDict, None] | None = _Unset:往 JSON Schema 追加自定义扩展字段。
  • frozen: bool | None = _Unset:标记字段只读,实例创建后不可修改。
  • validate_default: bool | None = _Unset:是否对 default/default_factory 生成的默认值执行校验。
  • repr: bool = _Unset:对象打印 repr 时是否展示该字段。
  • init: bool | None = _Unset:创建模型实例时,是否在init参数中包含此字段。
  • init_var: bool | None = _Unset:标记为初始化变量,仅实例构建时使用,不成为模型字段。
  • kw_only: bool | None = _Unset:是否强制该字段只能通过关键字参数传入。
  • pattern: str | re.Pattern str | None = _Unset:字符串正则校验规则。
  • strict: bool | None = _Unset:严格模式,开启时不自动做类型强制转换。
  • coerce_numbers_to_str: bool | None = _Unset:是否自动把数字强制转为字符串类型。
  • gt: annotated_types.SupportsGt | None = _Unset:数值校验,大于 (>)。
  • ge: annotated_types.SupportsGe | None = _Unset:数值校验,大于等于 (>=)。
  • lt: annotated_types.SupportsLt | None = _Unset:数值校验,小于 (<)。
  • le: annotated_types.SupportsLe | None = _Unset:数值校验,小于等于 (<=)。
  • multiple_of: float | None = _Unset:数值必须为此参数的倍数。
  • allow_inf_nan: bool | None = _Unset:是否允许 inf、nan 这类特殊浮点数。
  • max_digits: int | None = _Unset:Decimal 类型最大总位数。
  • decimal_places: int | None = _Unset:Decimal 类型小数点后保留位数。
  • min_length: int | None = _Unset:字符串 / 列表最小长度。
  • max_length: int | None = _Unset:字符串 / 列表最大长度。
  • union_mode: Literal 'smart', 'left_to_right' = _Unset:Union 联合类型的解析匹配策略。
  • fail_fast: bool | None = _Unset:校验时是否快速失败,遇到第一个错误就停止校验。
  • **extra: Unpack _EmptyKwargs:预留扩展关键字参数。 返回值:Any:返回 FieldInfo 实例,附加到模型字段上承载元信息。

代码:

python 复制代码
from langchain.tools import tool
import numexpr

# 函数名表示工具名称,这函数名要写的有意义不可以随便写,函数的参数表示工具的参数,函数返回值表示工具输出结果
# 函数的文档字符串会当做工具的描述,写到六个引号之间的内容就是文档字符串,注意老版本 LangChain 不是这样写的
# 所以文档字符串要写明白函数的作用、入参的作用、返回值的作用,从而保证Agent能够正确识别并且调用工具
# @tool ,这叫注解,这个注解的作用表示当前函数是LangChain的工具函数,老版本的LangChian函数的描述需要写到 @tool里
@tool
def get_天气(city:str)->str:

    # 下方Args是用来描述函数入参的,入参的数据类型和入参的作用
    # 下方Returns是用来描述函数返回值的,返回值类型和返回值的作用
    """
        获取指定城市的天气信息
        Args:
            city(str): 城市名称
        Returns:
            str: 天气信息
    """
    return f"{city}挺好"

# 下方是使用 @tool 注解来描述函数的作用,calculator是工具名,description它的值表示当前函数的作用描述
# 如果在注解中写了函数的描述和名字,然后在函数中用文档字符串又写了描述,那么它会以注解为主
@tool("calculator", description="执行算术计算。用这个来解数学题。输入应该是一个数学表达式,例如 '2 + 2' 或 'sqrt(16)'。")
def calc(expression: str) -> str:
    """计算数学表达式

    Args:
        expression (str): 数学表达式

    Returns:
        str: 计算结果
    """
    return str(numexpr.evaluate(expression).item())

# pydantic模型
from pydantic import BaseModel, Field

# Python是一个动态语言,变量没有强制类型,一个变量传递什么数据类型都可以,通过pydantic模型可以对数据类型进行校验
# 通过继承 pydantic模型中BaseModel类,来实现对数据类型的校验
class CalculateInput(BaseModel):
    # : str就表示当前变量要接收一个字符串
    # : float就表示当前变量要接收一个boolean类型的值
    # 使用 Field 可以对变量的值进行条件约束,它可以传递很多判断值的方式和逻辑
    operation: str = Field(description="要执行的运算类型,如 'add' 或 'multiply'")
    a: float = Field(description="第一个操作数")
    b: float = Field(description="第二个操作数")

# pydantic模型在工具中使用 args_schema 来的传递约束
@tool("calculator", args_schema=CalculateInput)
def calculate(operation: str, a: float, b: float) -> str:
    """当你需要进行数学计算时使用此工具"""
    if operation == "add":
        return str(a + b)
    elif operation == "multiply":
        return str(a * b)
    return "Unknown operation"

相关推荐
一直在努力的小宁1 小时前
【阅读笔记】具身智能的真机数采,到了分水岭
人工智能·深度学习·机器学习·agent·具身智能·vlm·vln
向成科技1 小时前
XC3576H工控主板|深度适配Ubuntu 26.04 LTS,释放边缘AI与工业开发新潜能
linux·人工智能·ubuntu·机器人·硬件·主板·边缘ai
AI人工智能+1 小时前
营业执照识别技术通过图像预处理、版面定位、深度学习OCR、NLP语义解析与智能校验五步流程,实现对倾斜、反光、遮挡等复杂照片的毫秒级精准识别
人工智能·深度学习·自然语言处理·营业执照识别
2601_962380481 小时前
历史统计视频的时间轴动画怎么做:从Excel年份图到分镜成片的实现流程
人工智能
海宇服务1 小时前
零信任架构实战:基于海宇车型识别精准构建自动化定损网关
运维·人工智能·架构·自动化
火山引擎开发者社区1 小时前
一个 Agent 额度用完,怎么让别的接着干?
人工智能
YH行业报告分析1 小时前
2026 AI法律合同审查平台市场洞察:NLP与机器学习如何推动企业合规与合同流程智能化?
人工智能·机器学习·自然语言处理
田里的水稻1 小时前
FA_融合和滤波(FF)-误差状态卡尔曼滤波(ESKF)
人工智能·机器学习·机器人·自动驾驶
yychen_java2 小时前
第六篇:Spring AI 实战:将 Java 业务接口封装成企业级 MCP Server
java·人工智能·spring
火山引擎开发者社区2 小时前
AgentKit 模型网关上手指南|告别多模型管理混乱
人工智能