LangChain代理工具选择与调用的源码实现机制深度剖析(76)

部署运行你感兴趣的模型镜像

LangChain代理工具选择与调用的源码实现机制深度剖析

一、LangChain代理工具选择与调用概述

1.1 代理工具的核心作用

在LangChain框架中,代理(Agent)通过调用外部工具(Tool)实现复杂任务,如查询天气、执行代码、检索文档等。工具选择与调用机制是代理的核心能力,它使代理能够根据用户输入和任务需求,动态匹配最合适的工具,并准确调用工具获取结果。这种机制打破了语言模型仅依赖文本生成的局限性,极大扩展了AI应用的功能边界,从单纯的文本交互转向多领域任务处理。

1.2 工具选择与调用的关键流程

整个过程可分为三个核心阶段:

  1. 工具选择:代理根据用户输入分析任务类型,从工具库中筛选候选工具,并通过推理确定最优工具。
  2. 参数构建:将用户输入转换为工具可接受的参数格式,确保调用的准确性。
  3. 工具调用与结果处理:执行工具调用,接收返回结果并处理,最终将结果整合为响应返回给用户。

1.3 工具选择与调用的设计目标

  • 准确性:确保选择的工具与任务高度匹配,避免无效调用。
  • 高效性:减少工具筛选和调用的时间开销,提升响应速度。
  • 可扩展性:支持灵活添加、删除或替换工具,适配多样化的任务需求。
  • 鲁棒性:对不明确或错误的用户输入具备容错能力,保证系统稳定运行。

二、工具定义与注册机制

2.1 基础工具接口定义

LangChain通过BaseTool抽象类定义工具的基础接口,所有具体工具均需继承该类:

class BaseTool(ABC):
    """基础工具接口"""
    name: str  # 工具名称,用于唯一标识
    description: str  # 工具功能描述,辅助代理理解工具用途
    return_direct: bool = False  # 是否直接返回工具结果,不经过代理二次处理
    
    @abstractmethod
    def _run(self, tool_input: str) -> str:
        """工具核心执行方法,接收输入并返回结果"""
        pass
    
    def _arun(self, tool_input: str) -> Awaitable[str]:
        """异步执行方法,可选实现,用于支持异步调用"""
        raise NotImplementedError("异步方法未实现")

_run方法是工具执行的核心逻辑,而_arun为异步场景提供支持。

2.2 具体工具实现示例

以天气查询工具为例,展示工具的具体实现:

class WeatherTool(BaseTool):
    name = "weather"
    description = "用于查询指定城市的当前天气情况,输入应为城市名称"
    
    def _run(self, tool_input: str) -> str:
        try:
            # 调用天气API的逻辑,假设使用第三方库获取数据
            weather_data = self._call_weather_api(tool_input)
            return self._process_weather_response(weather_data)
        except Exception as e:
            return f"天气查询失败:{str(e)}"
    
    def _call_weather_api(self, city: str) -> Any:
        # 实际API调用代码,如使用requests库发送请求
        pass
    
    def _process_weather_response(self, response: Any) -> str:
        # 解析API响应,提取关键信息并格式化
        pass

该工具通过_run方法封装了从API调用到结果处理的完整流程。

2.3 工具注册与管理

LangChain通过Tool类管理工具实例,并提供注册机制。工具可通过两种方式注册:

  1. 手动注册:将工具实例添加到代理的工具列表中。
from langchain.agents import AgentType, initialize_agent
from langchain.llms import OpenAI
from langchain.tools import Tool

weather_tool = WeatherTool()
llm = OpenAI()
agent = initialize_agent(
    [weather_tool],  # 将工具实例传入列表
    llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION
)
  1. 自动注册:利用工具发现机制,扫描指定模块或目录自动加载工具类。
from langchain.tools import load_tools

# 加载内置工具(如serpapi搜索引擎工具)
tools = load_tools(["serpapi"])

注册后的工具构成代理的“工具库”,供后续选择使用。

三、工具选择的核心策略

3.1 基于描述的匹配策略

代理通过工具的description字段与用户输入进行语义匹配,筛选候选工具。在ZeroShotAgent中,提示词构建逻辑包含工具描述:

class ZeroShotAgent(BaseSingleActionAgent):
    def _construct_prompt(
        self,
        intermediate_steps: List[Tuple[AgentAction, str]],
        **kwargs: Any
    ) -> Prompt:
        tools = self.tools
        tool_strings = "\n".join([f"{tool.name}: {tool.description}" for tool in tools])
        prefix = PREFIX.format(tools=tool_strings)  # PREFIX为预设提示词模板
        suffix = SUFFIX.format(
            input_variables=self.input_variables,
            intermediate_steps=intermediate_steps
        )
        return Prompt(input_variables=self.input_variables, template=prefix + "\n" + suffix)

代理将用户输入与工具描述拼接成提示词,调用LLM生成工具选择建议。例如,用户输入“北京天气如何”,LLM根据提示词中的工具描述,推理出应选择WeatherTool

3.2 基于推理的决策策略

ReActAgent采用“推理-行动”(Reasoning-Acting)模式,通过LLM生成推理步骤辅助工具选择:

class ReActAgent(BaseSingleActionAgent):
    def plan(
        self,
        intermediate_steps: List[Tuple[AgentAction, str]],
        **kwargs: Any
    ) -> AgentAction:
        thoughts = ""
        for action, observation in intermediate_steps:
            thoughts += f"Action: {action.tool}\nAction Input: {action.tool_input}\nObservation: {observation}\n"
        
        input_str = kwargs["input"]
        thoughts += f"Thought: 需要解决问题 {input_str},考虑可用工具..."
        
        prompt = self.llm_chain.predict(input=thoughts)
        action_match = re.search(r"Action: (.*?)\nAction Input:[\s]*(.*)", prompt, re.DOTALL)
        if action_match:
            tool = action_match.group(1).strip()
            tool_input = action_match.group(2).strip()
            return AgentAction(tool=tool, tool_input=tool_input, log=prompt)
        return AgentFinish(return_values={"output": "无法确定合适工具"}, log=prompt)

代理先通过LLM生成推理思路(如“需要查询天气,应使用WeatherTool”),再根据推理结果选择工具,提高选择准确性。

3.3 动态优先级与权重策略

为处理复杂场景,可引入工具优先级和权重机制。例如,为工具添加priority属性,并在选择时根据优先级排序:

class PrioritizedTool(BaseTool):
    priority: int  # 工具优先级,数值越高优先级越高
    
    def __init__(self, name, description, priority=0):
        self.name = name
        self.description = description
        self.priority = priority
    
class DynamicToolSelector:
    def select_tool(self, user_input, tools):
        prioritized_tools = sorted(tools, key=lambda t: t.priority, reverse=True)
        for tool in prioritized_tools:
            if self._is_relevant(tool, user_input):
                return tool
        return None
    
    def _is_relevant(self, tool, user_input):
        # 通过语义匹配或关键词检测判断工具是否相关
        pass

该策略确保高优先级工具在匹配时被优先选择,适用于资源受限或任务有明确优先级的场景。

四、工具调用参数构建

4.1 参数解析基础逻辑

工具调用前需将用户输入转换为工具可接受的参数格式。以代码执行工具为例,其输入需符合特定语法:

class CodeExecutionTool(BaseTool):
    name = "code_execution"
    description = "用于执行Python代码,输入应为完整的Python代码字符串"
    
    def _run(self, tool_input: str) -> str:
        try:
            exec(tool_input)  # 直接执行Python代码
            return "代码执行成功"
        except Exception as e:
            return f"代码执行失败:{str(e)}"

代理需确保输入为合法的Python代码,可通过语法检查或正则表达式预处理:

import ast

def validate_python_code(code):
    try:
        ast.parse(code)
        return True
    except SyntaxError:
        return False

class CodeAgent:
    def prepare_tool_input(self, user_input):
        if not validate_python_code(user_input):
            raise ValueError("输入不是有效的Python代码")
        return user_input

4.2 上下文信息整合

部分工具需要结合上下文信息生成参数。例如,在文档问答场景中,检索工具需根据问题筛选相关文档:

class DocumentRetrievalTool(BaseTool):
    name = "document_retrieval"
    description = "根据问题从知识库中检索相关文档,输入应为问题字符串"
    vector_store: Any  # 向量数据库实例
    
    def _run(self, tool_input: str) -> str:
        relevant_docs = self.vector_store.similarity_search(tool_input)
        return "\n".join([doc.page_content for doc in relevant_docs])

class DocumentQAAgent:
    def prepare_tool_input(self, user_input, chat_history):
        # 结合历史对话优化问题表述
        enhanced_question = self._enhance_question(user_input, chat_history)
        return enhanced_question
    
    def _enhance_question(self, question, history):
        # 例如,补充历史对话中的关键信息
        pass

通过整合上下文,工具调用参数更贴合实际需求,提升结果准确性。

4.3 多参数工具支持

对于需要多个参数的工具,代理需解析用户输入并拆分参数。以文件操作工具为例:

class FileOperationTool(BaseTool):
    name = "file_operation"
    description = "用于文件读写操作,输入格式为'操作类型:文件路径:内容',例如'write:/path/to/file.txt:Hello, World!'"
    
    def _run(self, tool_input: str) -> str:
        parts = tool_input.split(":")
        if len(parts) != 3:
            return "输入格式错误"
        operation, file_path, content = parts
        if operation == "write":
            with open(file_path, "w") as f:
                f.write(content)
            return "文件写入成功"
        elif operation == "read":
            try:
                with open(file_path, "r") as f:
                    return f.read()
            except FileNotFoundError:
                return "文件不存在"
        return "不支持的操作类型"

代理需解析用户输入并校验格式,确保工具调用的正确性。

五、工具调用与结果处理

5.1 同步调用实现

工具的同步调用通过BaseTool_run方法实现,以HTTP请求工具为例:

import requests

class HTTPRequestTool(BaseTool):
    name = "http_request"
    description = "用于发送HTTP请求,输入应为URL"
    
    def _run(self, tool_input: str) -> str:
        try:
            response = requests.get(tool_input)
            return f"状态码: {response.status_code}\n内容: {response.text[:100]}..."
        except Exception as e:
            return f"请求失败:{str(e)}"

代理调用该工具时,直接执行_run方法并等待结果返回。

5.2 异步调用实现

对于IO密集型工具(如网络请求、文件读写),异步调用可提升性能。BaseTool_arun方法提供异步支持:

import aiohttp
import asyncio

class AsyncHTTPRequestTool(BaseTool):
    name = "async_http_request"
    description = "用于异步发送HTTP请求,输入应为URL"
    
    async def _arun(self, tool_input: str) -> str:
        async with aiohttp.ClientSession() as session:
            async with session.get(tool_input) as response:
                text = await response.text()
                return f"状态码: {response.status}"

class AsyncAgent:
    async def run_async_tool(self, tool, input_str):
        result = await tool._arun(input_str)
        return result

# 调用示例
async def main():
    tool = AsyncHTTPRequestTool()
    agent = AsyncAgent()
    result = await agent.run_async_tool(tool, "https://example.com")
    print(result)

asyncio.run(main())

异步调用通过async/await语法实现非阻塞执行,提高系统吞吐量。

5.3 结果解析与整合

工具返回的结果需经过解析和整合,才能作为代理的最终响应。例如,JSON解析工具的结果处理:

import json

class JSONParseTool(BaseTool):
    name = "json_parse"
    description = "用于解析JSON字符串,输入应为JSON格式文本"
    
    def _run(self, tool_input: str) -> str:
        try:
            data = json.loads(tool_input)
            return str(data)
        except json.JSONDecodeError as e:
            return f"解析失败:{str(e)}"

class JSONAgent:
    def process_tool_result(self, tool_result):
        try:
            # 进一步处理解析后的数据,如提取关键字段
            processed_data = self._extract_key_info(tool_result)
            return f"处理后的结果: {processed_data}"
        except Exception as e:
            return f"结果处理失败:{str(e)}"
    
    def _extract_key_info(self, data):
        # 例如,提取JSON中的特定字段
        pass

代理通过process_tool_result方法对工具结果进行二次处理,确保输出符合用户预期。

六、工具调用的错误处理

6.1 工具执行错误捕获

在工具的_run方法中捕获异常,返回错误信息:

class DatabaseQueryTool(BaseTool):
    name = "database_query"
    description = "用于执行SQL查询,输入应为SQL语句"
    
    def _run(self, tool_input: str) -> str:
        try:
            # 假设使用sqlite3执行查询
            import sqlite3
            conn = sqlite3.connect('example.db')
            cursor = conn.cursor()
            cursor.execute(tool_input)
            results = cursor.fetchall()
            conn.close()
            return str(results)
        except Exception as e:
            return f"查询失败:{str(e)}"

代理接收到错误信息后,可选择重试或向用户反馈问题。

6.2 代理级错误处理

代理层面通过回调机制统一处理工具调用错误。BaseCallbackHandleron_tool_error方法用于捕获错误:

class ErrorLoggingCallbackHandler(BaseCallbackHandler):
    def on_tool_error(
        self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    ) -> Any:
        tool_name = kwargs.get("tool_name", "unknown_tool")
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f"工具 {tool_name} 调用失败:{str(error)}", exc_info=True)

class ToolUsingAgent:
    def __init__(self, llm, tools):
        self.llm = llm
        self.tools = tools
        self.callback_manager = CallbackManager([ErrorLoggingCallbackHandler()])
    
    def run(self, input_str):
        # 工具选择与调用逻辑...
        try:
            result = self._call_selected_tool(tool, tool_input)
            return result
        except Exception as e:
            self.callback_manager.on_tool_error(error=e, tool_name=tool.name)
            return f"任务执行失败:{str(e)}"

通过日志记录和统一处理,提升系统的错误可追溯性。

6.3 重试与回滚机制

对于可恢复的错误(如网络临时故障),可实现重试机制:

class RetryableTool(BaseTool):
    max_retries: int = 3
    retry_delay: int = 2
    
    def _run(self, tool_input: str) -> str:
        for attempt in range(self.max_retries):
            try:
                return self._actual_run(tool_input)
            except Exception as e:
                if attempt < self.max_retries - 1:
                    import time
                    time.sleep(self.retry_delay)
                else:
                    return f"重试失败:{str(e)}"
    
    def _actual_run(self, tool_input: str) -> str:
        # 具体工具执行逻辑
        pass

对于涉及状态变更的工具(如文件写入),可添加回滚逻辑,确保系统一致性。

七、工具选择与调用的优化策略

7.1 缓存优化

对频繁调用且结果稳定的工具,可添加缓存机制。例如,缓存天气查询结果:

import functools

class CachedWeatherTool(WeatherTool):
    @functools.lru_cache(maxsize=128)
    def _run(self, tool_input: str) -> str:
        return super()._run(tool_input)

八、工具动态加载与插件化扩展

8.1 工具动态加载原理

LangChain支持工具的动态加载,允许在运行时发现并注册新工具,增强系统扩展性。其核心依赖Python的模块导入机制和反射技术。通过扫描指定目录或模块,获取工具类定义并实例化。

load_tools函数中,通过importlib库实现动态导入:

from langchain.tools.base import BaseTool
from importlib import import_module

def load_tools(tool_names, *args, **kwargs):
    tools = []
    for tool_name in tool_names:
        try:
            # 动态导入工具模块
            module = import_module(f"langchain.tools.{tool_name}")
            # 查找工具类并实例化
            for attr_name in dir(module):
                attr = getattr(module, attr_name)
                if isinstance(attr, type) and issubclass(attr, BaseTool) and attr != BaseTool:
                    tools.append(attr(*args, **kwargs))
        except ImportError:
            raise ValueError(f"工具 {tool_name} 未找到")
    return tools

该函数遍历工具名称列表,尝试导入对应模块,从中筛选继承自BaseTool的类并创建实例,最终返回工具列表。这种机制使得用户无需修改核心代码,即可引入新工具。

8.2 插件化架构设计

为进一步提升扩展性,LangChain可采用插件化架构。定义插件接口ToolPlugin,要求插件实现工具注册和初始化逻辑:

class ToolPlugin:
    def register_tools(self, tool_registry):
        """向工具注册表注册工具"""
        pass
    
    def initialize(self, config):
        """插件初始化,接受配置参数"""
        pass

插件开发者通过实现该接口,将自定义工具注册到系统中。例如,自定义的股票查询插件:

class StockToolPlugin(ToolPlugin):
    def register_tools(self, tool_registry):
        from .stock_tool import StockQueryTool
        tool_registry.register_tool(StockQueryTool())
    
    def initialize(self, config):
        # 初始化插件所需资源,如API密钥配置
        pass

主程序通过加载插件并调用其方法,完成工具的动态添加:

class PluginManager:
    def __init__(self):
        self.plugins = []
        self.tool_registry = []
    
    def load_plugin(self, plugin_class):
        plugin = plugin_class()
        plugin.initialize({})  # 可传入配置参数
        plugin.register_tools(self.tool_registry)
        self.plugins.append(plugin)
        return self.tool_registry
    
    def get_tools(self):
        return self.tool_registry

# 使用示例
manager = PluginManager()
stock_tools = manager.load_plugin(StockToolPlugin)

插件化架构使工具扩展更规范,便于管理和维护。

8.3 工具版本管理

随着工具功能迭代,需要对工具版本进行管理。在工具类中添加版本属性,并在注册时记录版本信息:

class VersionedTool(BaseTool):
    version: str = "1.0"  # 工具版本号
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
    def serialize(self):
        return {
            "name": self.name,
            "description": self.description,
            "version": self.version
        }

class ToolRegistry:
    def __init__(self):
        self.tools = {}  # 以工具名称和版本号为键存储工具实例
    
    def register_tool(self, tool):
        key = (tool.name, tool.version)
        if key in self.tools:
            raise ValueError(f"工具 {tool.name} 版本 {tool.version} 已存在")
        self.tools[key] = tool
    
    def get_tool(self, tool_name, version=None):
        if version:
            key = (tool_name, version)
            return self.tools.get(key)
        # 若未指定版本,返回最新版本
        matching_tools = [t for n, t in self.tools.items() if n[0] == tool_name]
        return max(matching_tools, key=lambda t: t.version) if matching_tools else None

通过版本管理,可避免新旧工具冲突,并支持回滚到稳定版本。

九、多代理协同工具调用

9.1 主从代理架构

在复杂任务场景下,可采用主从代理架构实现多代理协同。主代理负责任务分解和整体调度,从代理专注于特定子任务的工具调用。

主代理通过TaskDispatcher类将任务分配给从代理:

class TaskDispatcher:
    def __init__(self, sub_agents):
        self.sub_agents = sub_agents  # 从代理列表
    
    def dispatch_task(self, task):
        # 根据任务类型选择合适的从代理
        agent = self._select_agent(task)
        if agent:
            return agent.run(task)
        return "无法找到处理该任务的代理"
    
    def _select_agent(self, task):
        for agent in self.sub_agents:
            if agent.can_handle(task):
                return agent
        return None

从代理根据自身能力判断是否能处理任务:

class SubAgent:
    def __init__(self, tools):
        self.tools = tools
    
    def can_handle(self, task):
        # 判断任务是否与工具匹配
        for tool in self.tools:
            if tool.name in task:
                return True
        return False
    
    def run(self, task):
        # 选择工具并调用
        tool = self._select_tool(task)
        if tool:
            return tool.run(task)
        return "无法找到处理该任务的工具"
    
    def _select_tool(self, task):
        for tool in self.tools:
            if tool.name in task:
                return tool
        return None

主从代理架构将复杂任务拆解为多个子任务,提高处理效率和专业性。

9.2 代理间通信机制

多代理协同需要通信机制传递信息。通过消息队列实现代理间异步通信,例如使用pika库与RabbitMQ集成:

import pika

class AgentMessenger:
    def __init__(self, queue_name):
        self.connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=queue_name)
        self.queue_name = queue_name
    
    def send_message(self, message):
        self.channel.basic_publish(exchange='', routing_key=self.queue_name, body=message)
    
    def receive_message(self, callback):
        self.channel.basic_consume(queue=self.queue_name, on_message_callback=callback, auto_ack=True)
        self.channel.start_consuming()

代理通过send_message发送任务或结果,receive_message接收消息并处理。例如,主代理将分解后的子任务发送给从代理,从代理处理后返回结果:

# 主代理发送任务
main_messenger = AgentMessenger("sub_agent_queue")
main_messenger.send_message("查询北京今日股票价格")

# 从代理接收任务
def handle_task(channel, method, properties, body):
    task = body.decode()
    result = sub_agent.run(task)
    reply_messenger = AgentMessenger("main_agent_queue")
    reply_messenger.send_message(result)

sub_messenger = AgentMessenger("sub_agent_queue")
sub_messenger.receive_message(handle_task)

通信机制确保代理间信息流畅,实现高效协同。

9.3 协同冲突解决

多代理协同可能出现任务重复处理或资源竞争问题。通过任务锁机制避免重复处理:

import threading

class TaskLock:
    def __init__(self):
        self.lock = threading.Lock()
        self.processed_tasks = set()
    
    def can_process(self, task):
        with self.lock:
            if task in self.processed_tasks:
                return False
            self.processed_tasks.add(task)
            return True

代理在处理任务前,先通过TaskLock检查任务是否已被处理,避免重复劳动。对于资源竞争,可采用资源分配器统一管理共享资源,确保同一时刻只有一个代理访问资源。

十、工具选择与调用的安全与合规

10.1 输入安全校验

为防止恶意输入导致安全漏洞(如代码注入、SQL注入),需对工具输入进行严格校验。以SQL查询工具为例,使用参数化查询替代字符串拼接:

import sqlite3

class SecureDatabaseQueryTool(BaseTool):
    name = "secure_database_query"
    description = "用于安全执行SQL查询,输入应为查询参数"
    
    def _run(self, tool_input: str) -> str:
        try:
            conn = sqlite3.connect('example.db')
            cursor = conn.cursor()
            # 使用参数化查询
            cursor.execute("SELECT * FROM users WHERE username = ?", (tool_input,))
            results = cursor.fetchall()
            conn.close()
            return str(results)
        except Exception as e:
            return f"查询失败:{str(e)}"

同时,对输入进行正则表达式过滤,限制特殊字符:

import re

class InputFilteringTool(BaseTool):
    def _run(self, tool_input: str) -> str:
        if re.search(r'[;--\*]', tool_input):
            raise ValueError("输入包含非法字符")
        return super()._run(tool_input)

通过多重校验,提升工具调用的安全性。

10.2 权限与访问控制

对敏感工具(如文件操作、系统命令执行)设置权限控制。定义权限模型ToolPermission,记录用户或角色对工具的访问权限:

class ToolPermission:
    def __init__(self):
        self.permissions = {}  # {user_id: {tool_name: True/False}}
    
    def grant_permission(self, user_id, tool_name):
        self.permissions.setdefault(user_id, {})[tool_name] = True
    
    def has_permission(self, user_id, tool_name):
        return self.permissions.get(user_id, {}).get(tool_name, False)

class SecureAgent:
    def __init__(self, llm, tools, permission_manager):
        self.llm = llm
        self.tools = tools
        self.permission_manager = permission_manager
    
    def run(self, user_id, input_str):
        tool = self._select_tool(input_str)
        if tool and self.permission_manager.has_permission(user_id, tool.name):
            return tool.run(input_str)
        return "你没有权限使用该工具"

用户调用工具前,代理先检查其权限,防止越权操作。

10.3 合规性与审计

记录工具调用日志,满足合规审计要求。在BaseCallbackHandler中扩展日志记录功能:

import logging

class AuditLoggingCallbackHandler(BaseCallbackHandler):
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        file_handler = logging.FileHandler('tool_audit.log')
        file_handler.setFormatter(formatter)
        self.logger.addHandler(file_handler)
    
    def on_tool_start(
        self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
    ) -> Any:
        self.logger.info(f"工具 {serialized['name']} 开始调用,输入: {input_str}")
    
    def on_tool_end(
        self, output: str, **kwargs: Any
    ) -> Any:
        tool_name = kwargs.get("tool_name", "unknown_tool")
        self.logger.info(f"工具 {tool_name} 调用结束,输出: {output}")
    
    def on_tool_error(
        self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    ) -> Any:
        tool_name = kwargs.get("tool_name", "unknown_tool")
        self.logger.error(f"工具 {tool_name} 调用失败,错误: {str(error)}")

通过完整的日志记录,可追溯工具使用情况,确保系统符合合规要求。

上述内容从多个维度深入剖析了LangChain代理工具选择与调用机制。如果还想了解某部分细节,或有其他相关探索需求,欢迎随时沟通。

您可能感兴趣的与本文相关的镜像

Qwen3-VL-30B

Qwen3-VL-30B

图文对话
Qwen3-VL

Qwen3-VL是迄今为止 Qwen 系列中最强大的视觉-语言模型,这一代在各个方面都进行了全面升级:更优秀的文本理解和生成、更深入的视觉感知和推理、扩展的上下文长度、增强的空间和视频动态理解能力,以及更强的代理交互能力

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android 小码蜂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值