Tools概述Tools 用于扩展大语言模型LLM的能力使其能够与外部系统、API 或自定义函数交互从而完成仅靠文本生成无法实现的任务如搜索、计算、数据库查询等。LangChain通过提供统一框架集成功能的具体实现。在框架内每个功能被封装成一个工具具有自己的输入输出及处理方法。代理接收任务后通过大模型推理选择适合的工具处理任务。一旦选定LangChain将任务输入传递给该工具工具处理输入生成输出。输出经过大模型推理可用于其他工具的输入或作为最终结果返回给用户。特点增强 LLM 的功能 让 LLM 突破纯文本生成的限制执行实际操作如调用搜索引擎、查询数据 库、运行代码等支持智能决策 在Agent 工作流中LLM 根据用户输入动态选择最合适的 Tool 完成任务。模块化设计 每个 Tool 专注一个功能便于复用和组合例如搜索工具 计算工具 天气查 询工具Tool 的要素Tools 本质上是封装了特定功能的可调用模块是Agent、Chain或LLM可以用来与世界互动的接口。Tool 通常包含如下几个要素name 工具的名称description 工具的功能描述该工具输入的 JSON模式要调用的函数return_direct 是否应将工具结果直接返回给用户仅对Agent相关实操步骤步骤1将name、description 和 JSON模式作为上下文提供给LLM步骤2LLM会根据提示词推断出 需要调用哪些工具 并提供具体的调用参数信息步骤3用户需要根据返回的工具调用信息自行触发相关工具的回调示列import os from langchain_community.tools import TavilySearchResults os.environ[TAVILY_API_KEY] tool TavilySearchResults(top_k_results1, doc_content_chars_max100) print(name:, tool.name) print(description:, tool.description) print(args:, tool.args) print(return_direct:, tool.return_direct) print(langchain:, tool.run({query:langchain})) print(tool.run(langchain))两种自定义Tool方式第1种使用tool装饰器自定义工具的最简单方式装饰器默认使用函数名称作为工具名称但可以通过参数 name_or_callable 来覆盖此设置。 同时装饰器将使用函数的 文档字符串 作为 工具的描述 因此函数必须提供文档字符串。第2种使用StructuredTool.from_function类方法这类似于 tool 装饰器但允许更多配置和同步/异步实现的规范。几个常用属性Tool由几个常用属性组成案例1from langchain.tools import tool from langchain_core.tools import StructuredTool tool(name_or_callableadd, description计算两个数字的和, return_directTrue) def add(a,b): return ab print(add.name) print(add.description) print(add.args) print(add.return_direct) resp1 add.invoke({a:1, b:2}) print(resp1)案例2from langchain.tools import tool from langchain_core.tools import StructuredTool def search(keyword): return f检索{keyword}结果 search_tool StructuredTool.from_function(funcsearch, namesearch, description一个可以进行网络搜索的工具) print(search_tool.name) print(search_tool.description) print(search_tool.args) print(search_tool.return_direct) resp2 search_tool.invoke(狗) print(resp2)工具调用bind_tools和agent是构建智能代理系统时常用的功能bind_tools可用于将工具绑定到特定的组件上而agent则是一个智能实体它可以根据输入和可用的工具来决定如何采取行动以实现目标。下面将详细介绍如何使用bind_tools和agent来调用工具。bind_tools在LangChain里bind_tools是一种将工具绑定到链Chain或模型LLM上的方法目的是让模型能够自动调用这些工具来完成特定任务。它主要用于简化工具调用的流程使得模型在处理输入时可以直接利用绑定的工具进行信息查询或其他操作。import os from langchain_community.tools import TavilySearchResults from langchain_core.prompts import ChatPromptTemplate from langchain_core.tools import tool from model.deepseek import deepseek_llm # 搜索工具 os.environ[TAVILY_API_KEY] search_tool TavilySearchResults(max_results5) # 定义几个计算工具 from pydantic import BaseModel class CalculatorArgs(BaseModel): operation: str operand1: float operand2: float tool(Calculator, return_directTrue, args_schemaCalculatorArgs) def calculator(operation, operand1, operand2): 计算器工具支持加减乘除四种基本运算。 参数: operation (str): 运算类型可选值为 add, subtract, multiply, divide。 operand1 (float): 第一个操作数。 operand2 (float): 第二个操作数。 返回: float: 运算结果。 异常: ValueError: 如果运算类型不支持或除数为零。 if operation add: return operand1 operand2 elif operation subtract: return operand1 - operand2 elif operation multiply: return operand1 * operand2 elif operation divide: if operand2 0: raise ValueError(Cannot divide by zero.) return operand1 / operand2 else: raise ValueError(fUnsupported operation: {operation}) tools [search_tool, calculator] model_with_tools deepseek_llm.bind_tools(tools) prompt_template ChatPromptTemplate.from_messages( [ (system, 你是一个助手请根据用户输入提供准确的回答。), (user, {input}) ] ) chain prompt_template | model_with_tools # 示例调用工具的逻辑 def invoke_tool_example(user_input): # 调用模型并传递工具 res chain.invoke({input: user_input}) # 解析返回结果 if res.response_metadata[finish_reason] tool_calls: # 处理工具调用 for tool_call in res.tool_calls: tool_name tool_call[name] tool_args tool_call[args] # 根据工具名称调用相应的工具 print(fTool name: {tool_name}, Args: {tool_args}) if tool_name Calculator: result calculator.invoke({input: tool_args}) print(fCalculator result: {result}) elif tool_name tavily_search_results_json: result search_tool.invoke(tool_args[query]) print(fsearch tool: {result}) else: print(res.content) # 执行示例函数 while True: user_input input(请输入你的问题输入 exit 退出) if user_input.lower() exit: break invoke_tool_example(user_input)测试agent可以理解为一个智能决策者它基于大语言模型LLM根据输入的问题和工具的描述决定调用哪些工具以及如何使用它们来生成答案from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool from pydantic import Field, BaseModel from model.zhipu import zhipu_llm class AddInput(BaseModel): num1: int Field(description计算的第一个数字) num2: int Field(description计算的第二个数字) tool(add_num, args_schemaAddInput, description求两个数字的和) def add_num(num1: int, num2: int) - int: 求两个数字的和 print(f工具被调用num1: {num1}, num2: {num2}) return num1 num2 prompt ChatPromptTemplate.from_messages( [ (system, 你是一个智能助手尽可能的调用工具回答用户的问题), MessagesPlaceholder(variable_namechat_history, optionalTrue), (user, {input}), MessagesPlaceholder(variable_nameagent_scratchpad, optionalTrue), ] ) agent create_tool_calling_agent(zhipu_llm, [add_num], prompt) executor AgentExecutor(agentagent, tools[add_num]) result executor.invoke({input: 我昨天赚了100今天赚了200 总共赚了多少}) print(result)bind_tools与Agent的对比1.Agent概述Agent是LangChain中一种更高级的机制它可以根据输入动态地决定是否调用工具、调用哪个工具以及如何使用工具的输出。Agent通常包含一个决策逻辑能够根据模型的输出和任务的需求进行智能决策。2. 优点对比bind_tools代码简单适合初学者和简单任务。工具调用流程固定易于调试和理解。Agent自主性强能够根据任务的复杂性和输入内容动态地决定是否调用工具以及调用哪个工具更适合处理复杂任务。适应性好可以处理多步推理和复杂决策的任务能够根据工具的输出进一步调整处理流程。3. 缺点对比bind_tools缺乏自主性不能根据情况动态调整工具调用。对于复杂任务的处理能力有限。Agent代码复杂需要配置决策逻辑、工具选择策略等代码编写和调试的难度较大。性能开销大由于需要进行额外的决策和推理Agent的运行时间和资源消耗可能会更高。综上所述bind_tools适合简单任务追求代码简洁和快速实现而Agent则更适合复杂任务需要模型具备智能决策和多步推理能力的场景。