from collections.abc import Callable from dataclasses import dataclass, field @dataclass class ToolExtraMetadata: """附加元数据(用装饰器注册)""" category: str = "" # 分类: buildin, knowledge, mysql, subagents, debug tags: list[str] = field(default_factory=list) display_name: str = "" # 显示名称(给人看的名字) icon: str = "" config_guide: str = "" # 配置说明(给人看的使用前配置提示) # 全局注册表: tool_name -> ToolExtraMetadata _extra_registry: dict[str, ToolExtraMetadata] = {} # 全局工具实例列表(由 @tool 装饰器自动收集) _all_tool_instances: list = [] def get_extra_metadata(tool_name: str) -> ToolExtraMetadata | None: """获取工具附加元数据""" return _extra_registry.get(tool_name) def get_all_extra_metadata() -> dict[str, ToolExtraMetadata]: """获取所有附加元数据""" return _extra_registry.copy() def get_all_tool_instances() -> list: """获取所有工具实例(由 @tool 装饰器自动收集)""" return _all_tool_instances # 基于 langchain.tool 的拓展装饰器 def tool( category: str = "", tags: list[str] = None, display_name: str = "", icon: str = "", config_guide: str = "", name_or_callable: str | Callable | None = None, description: str | None = None, args_schema: type | None = None, return_direct: bool = False, ): """基于 langchain.tool 的拓展装饰器,同时注册元数据 使用方式: @tool(category="buildin", tags=["计算"], display_name="计算器") def calculator(a: float, b: float, operation: str) -> float: ... 或者保留原有的 name_or_callable 和 description 参数来自定义工具名称和说明。 """ from langchain.tools import tool as langchain_tool # 先应用 langchain tool 装饰器 langchain_decorator = langchain_tool( name_or_callable=name_or_callable, description=description, args_schema=args_schema, return_direct=return_direct, ) def decorator(func: Callable) -> Callable: # 应用 langchain 装饰器 tool_obj = langchain_decorator(func) # 注册附加元数据 tool_name = tool_obj.name _extra_registry[tool_name] = ToolExtraMetadata( category=category, tags=tags or [], display_name=display_name, icon=icon, config_guide=config_guide, ) # 自动收集工具实例 tool_obj.handle_tool_error = True _all_tool_instances.append(tool_obj) return tool_obj return decorator