LangChain中的工具使用

工具的作用

工具调用户根本作用是让大语言模型(LLM)具备与外部世界交互的能力。
LLM 本身是⼀个封闭的知识系统,其能力受限于其训练数据(存在滞后性)和内在的文本生成逻辑。它无法执行直接计算、查询实时信息、操作数据库或调用任何外部 API。工具调用打破了这层壁垒,其作⽤具体体现在:

  1. 扩展能力边界:模型可以借助工具完成它本身无法完成的任务,如执行数学计算、搜索网络、查询数据库等。
  2. 保证信息实时性:通过调⽤搜索⼯具或数据库查询⼯具,LLM 可以获取最新的、训练数据中不存在的信息,避免回答过时或"⼀本正经地胡说⼋道"。
  3. 处理复杂任务:将⼀个复杂的⽤⼾请求(如"分析我上个⽉的消费趋势")分解成多个步骤,并依次调⽤不同的⼯具(如"从数据库获取数据" -> "⽤ Python 进⾏数据分析" -> "⽣成图表") 来协同完成。协调这件事这更体现在 Agent 智能体上。
  4. 连接现有系统:可以将企业内部已有的系统、API 和数据库封装成⼯具,让 LLM 成为⼀个⽤⾃然语⾔驱动的统⼀接⼝,极⼤地提升了⾃动化和集成能⼒。

创建工具

使用 @tool 装饰器创建⼯具

在 LangChain 中,实现了⼀个 @tool 装饰器来创建⼯具, @tool 装饰器是⾃定义⼯具的最简单⽅
法。如下所示:

复制代码
from  langchain_core.tools import tool

#定义工具
@tool
def add(a: int, b: int) -> int:
    """
    两数相加
    Args:
    a:第一个参数
    b:第二个参数
    """
    return a+b

#调用工具
print(add.invoke({"a": 1, "b": 2}))
print(add.name)
print(add.description)
print(add.args)

运行结果如下:


可以看出,⼯具通过 @tool 加 Python函数 实现,其中:

  • 该装饰器默认使⽤函数名称作为⼯具名称。
  • 该装饰器将使⽤函数的⽂档字符串作为⼯具的描述

因此,函数名、类型提示和⽂档字符串都是传递给⼯具 Schema 的⼀部分,不可缺失。定义好的描述是使模型良好运⾏的重要部分

什么是Schema

简单来说:Schema 就是描述其他数据结构的声明格式,⽤于⾃动验证数据⽽存在
对于工具schema,它将从函数名、类型提示和⽂档字符串中获取相关属性,以此来声明⼀个⼯具,包括其名称、描述、输⼊参数、输出类型等等。这⾥需要说明的是,若是简单定义⼯具,如上述示例,⼯具 schema 需要解析 Google 风格的文档字符串去获取。
什么是 Google ⻛格的⽂档字符串?Google ⻛格是 Python ⽂档字符串的⼀种写作规范。它并⾮
Python 语⾔官⽅强制要求,⽽是由 Google 为其内部 Python 项⽬制定的规范,后来因为其极⾼的可读性和简洁性⽽在整个 Python 社区中变得⾮常流⾏。它使⽤ Args: , Returns: 等关键字,参数
描述简洁明了,如下所示

def fetch_data(url, retries=3):

"""从给定的URL获取数据。

Args:

url (str): 要从中获取数据的URL。

retries (int, optional): 失败时重试的次数。默认为3。

Returns:

dict: 从URL解析的JSON响应。

"""
除了这种⽅式,还有其他⽅式可以让⼯具 schema,获取相关⼯具声明需要的内容。下⾯再展⽰其他常用的工具定义模式:

其他工具定义模式

1、依赖Pydantic类
复制代码
class AddInput(BaseModel):
    """
    两数相加
    """
    a: int = Field(description="第一个参数")
    b: int = Field(description="第二个参数")

@tool(args_schema=AddInput)
def add(a:int, b:int) -> int:
    return a+b

#调用工具
print(add.invoke({"a": 1, "b": 2}))
print(add.name)
print(add.description)
print(add.args)

运行结果如下:

注意是代码中 @tool 的 args_schema 参数,它表示工具函数在未提供描述、文档字符串等需要传 递给⼯具 Schema 的内容时,依赖 Pydantic 类使⽤ args_schema 参数,定义并提供⼯具输⼊参数的schema。默认为 None。

点击运⾏,不会报错,且将来运⾏时会进⾏数据验证。因此,我们再次印证了函数名、类型提⽰和⽂档字符串都是传递给⼯具 Schema 的⼀部分,不可缺失

2、依赖 Annotated
复制代码
@tool
def add(

    a: Annotated[int, "第一个参数"],
    b: Annotated[int, "第二个参数"]
) -> int:
    """两数相加"""
    return a+b

print(add.invoke({"a": 4, "b": 2}))
print(add.name)
print(add.description)
print(add.args)

调用结果:

使用StructuredTool 类提供的函数创建工具

class langchain_core.tools.structured.StructuredTool 类用来初始化⼯具,其中from_function 类⽅法通过给定的函数来创建并返回⼀个⼯具。 from_function 类⽅法定义如下

classmethod from_function(

func: Callable | None = None,

coroutine: Callable[[...], Awaitable[Any]] | None = None,

name: str | None = None,

description: str | None = None,

return_direct: bool = False,

args_schema: type[BaseModel] | dict[str, Any] | None = None,

infer_schema: bool = True,

*,

response_format: Literal['content', 'content_and_artifact'] = 'content',

parse_docstring: bool = False,

error_on_invalid_docstring: bool = False,

**kwargs: Any,

) → StructuredTool
关键参数说明:

  • func:要设置的⼯具函数
  • coroutine:协程函数,要设置的异步⼯具函数
  • name:⼯具名称。默认为函数名称。
  • description:⼯具描述。默认为函数文档字符串。
  • args_schema:⼯具输⼊参数的schema。默认为 None。
  • response_format:⼯具响应格式。默认为"content"。
    • 如果配置为 "content" ,则⼯具的输出为 ToolMessage 的 content 属性。
      • 对于 HumanMessage 、AIMessage 已经⻅过,分别表示用户消息和 AI消息响应 , 对于 ToolMessage ,它表示对应⼯具⻆⾊所发出的消息。
    • 如果配置为 "content_and_artifact" ,则输出应是与 ToolMessage 的 content 属性与 artifact 属性相对应的⼆元组。

实例一:常规用法

复制代码
from langchain_core.tools import StructuredTool

def add(a:int,b:int) ->int:
    """两数相加 """
    return a+b
tool = StructuredTool.from_function(add)
print(tool.invoke({"a": 1, "b": 2}))
print(tool.name)
print(tool.description)
print(tool.args)

调用结果:

示例2:加入配置,依赖 Pydantic 类

此时可以:

  • 使用 args_schema 参数,依赖 Pydantic 类定义并提供工具输入参数的 schema 属性

  • 使⽤ description 参数,替代⽂档字符串中对于⼯具描述的 schema 属性

复制代码
class AddInput(BaseModel):
    a:int = Field(description="第一个参数")
    b:int = Field(description="第一个参数")

def add(a:int,b:int) -> int:
    return a+b


tool = StructuredTool(
    func=add,
    args_schema=AddInput,
    description="两数相加",
    name="add",
)

print(tool.invoke({"a": 1, "b": 2}))
print(tool.name)
print(tool.description)
print(tool.args)

调用结果

绑定工具

为了实际将这些⼯具绑定到聊天模型,可以使⽤聊天模型的 .bind_tools() 方法。如下所示:

复制代码
@tool
def add(
        a:Annotated[int,...,"第一个整数"],
        b:Annotated[int,...,"第二个整数"],
) -> int:
    """两数相加"""
    return a + b

@tool
def multiply(
        a:Annotated[int,"第一个参数"],
        b:Annotated[int,"第二个参数"],
) -> int:
    """两数相乘"""
    return a * b
复制代码
key = os.environ['DEEPSEEK_API_KEY']
model = ChatOpenAI(
    model='deepseek-chat',
    base_url="https://api.deepseek.com",
    api_key=key,
        )

#绑定工具
tools = [add,multiply]
model_tool = model.bind_tools(tools=tools) #返回一个绑定了工具的model

bind_tools方法定义

bind_tools(

tools: Sequence[dict[str, Any] | type | Callable | BaseTool],

*,

tool_choice: dict | str | Literal['auto', 'none', 'required', 'any'] | bool

| None = None,

strict: bool | None = None,

parallel_tool_calls: bool | None = None,

**kwargs: Any,

) → Runnable[PromptValue | str | Sequence[BaseMessage | list[str] |

tuple[str, str] | str | dict[str, Any]], BaseMessage]
请求参数:

  • tools :绑定到此聊天模型的⼯具定义列表。⽀持的类型为:字典、pydantic.BaseModel 类、 Python 函数和 BaseTool(如 @tool 装饰器创建的类)。

  • tool_choice (默认空):要求模型调⽤哪个⼯具。可以设置为:

    • 形式为 '<<tool_name>>' 的 str:调⽤ <tool_name> ⼯具
    • 'auto' :⾃动选择⼯具(包括⽆⼯具)。
    • 'none' :不调⽤⼯具。
    • 'any' 或 'required' 或 True :强制调⽤⾄少⼀个⼯具。
    • False 或 None :⽆效果,默认 OpenAI 的⾏为。
    • strict (默认空)
    • 如果为 True ,则保证模型输出与⼯具定义中提供的 JSON Schema 完全匹配。输⼊也将根据提供的 Schema 进⾏验证。
    • 如果为 False ,则不会验证输⼊,也不会验证模型输出。
    • 如果为 None ,则不会将 strict 参数传递给模型。

    返回值:

    • 返回⼀个 Runnable 实例。
相关推荐
Aision_11 小时前
Agent 为什么需要 Checkpoint?
人工智能·python·gpt·langchain·prompt·aigc·agi
zc.z11 小时前
基于 LangChain4j 的 RAG 工作流智能体实战
langchain·大模型·springboot·rag智能体
不会敲代码116 小时前
从零搭建 RAG 电子书智能问答系统:天龙八部 × Milvus × LangChain
langchain·node.js·llm
杨大厨wd17 小时前
LangChain :把历史记录和链式调用写明白
langchain
幸福巡礼18 小时前
【LangChain 1.2 实战(八)】Agent Middleware 实战 —— 动态路由、监控、安全与容错
java·安全·langchain
晚风吹长发21 小时前
LangChain快速入门
langchain
Irissgwe21 小时前
LangChain之核心组件(文档加载器Document loaders)
人工智能·ai·langchain·llm·rag·langgraph·文档加载器
lbb 小魔仙1 天前
LangChain + RAG 知识库系统搭建指南:从零构建企业级文档问答系统
python·langchain