网站首页布局诊断wordpress会员小图标
2026/1/10 7:02:20 网站建设 项目流程
网站首页布局诊断,wordpress会员小图标,咖啡豆网站模板,图片设计美工day31:自定义 Tool 函数 自定义Tool函数详解与实践 1. 什么是自定义Tool函数#xff1f; 1.1 核心概念 自定义Tool函数是LangChain中允许开发者根据特定需求创建的工具函数#xff0c;这些函数可以被Agent调用以执行特定任务。它们是扩展Agent能力的关键机制#xff0c;…day31:自定义 Tool 函数自定义Tool函数详解与实践1. 什么是自定义Tool函数1.1 核心概念自定义Tool函数是LangChain中允许开发者根据特定需求创建的工具函数这些函数可以被Agent调用以执行特定任务。它们是扩展Agent能力的关键机制让LLM能够与外部系统、API、数据库或自定义逻辑进行交互。1.2 Tool函数的基本结构一个完整的Tool函数包含三个核心要素函数实现实际的Python函数逻辑 工具描述自然语言描述帮助LLM理解何时使用该工具 输入参数明确定义的输入参数和模式1.3 为什么需要自定义Tool函数特定领域需求内置工具无法满足专业领域需求 私有系统集成连接企业内部系统、数据库或API 定制化逻辑实现特定的业务逻辑或计算 安全控制限制LLM对某些资源的访问权限2. Tool函数的组成要素2.1 必需组件fromlangchain.toolsimportBaseToolfrompydanticimportBaseModel,Field# 1. 输入Schema定义工具接受的参数classCalculatorInput(BaseModel):计算器输入参数a:floatField(...,description第一个数字)b:floatField(...,description第二个数字)operation:strField(...,description运算符: add, subtract, multiply, divide)# 2. 工具类继承BaseToolclassCustomCalculatorTool(BaseTool):namecustom_calculatordescription执行基本的数学计算args_schemaCalculatorInputdef_run(self,a:float,b:float,operation:str)-str:工具的核心执行逻辑# 实现具体功能passasyncdef_arun(self,a:float,b:float,operation:str)-str:异步版本可选pass2.2 关键属性说明属性说明重要性name工具的唯一标识符⭐⭐⭐⭐⭐description帮助LLM理解工具用途的描述⭐⭐⭐⭐⭐args_schema定义输入参数的结构⭐⭐⭐⭐_run()同步执行方法⭐⭐⭐⭐⭐_arun()异步执行方法可选⭐⭐⭐3. 创建自定义Tool的完整流程3.1 从0到1的完整示例# custom_tools_demo.pyimportosfromtypingimportOptional,Typefromdatetimeimportdatetime# LangChain相关导入fromlangchain.toolsimportBaseTool,Toolfromlangchain.agentsimportinitialize_agent,AgentTypefromlangchain_openaiimportChatOpenAIfrompydanticimportBaseModel,Field# 设置API密钥确保已设置环境变量os.environ[OPENAI_API_KEY]your-api-key-here# 示例1基础计算器工具 classCalculatorInput(BaseModel):计算器输入参数定义num1:floatField(...,description第一个数字)num2:floatField(...,description第二个数字)operation:strField(...,description要执行的操作: add, subtract, multiply, divide)classCalculatorTool(BaseTool):自定义计算器工具namecalculatordescription执行基本的数学运算。输入两个数字和操作类型。args_schema:Type[BaseModel]CalculatorInputdef_run(self,num1:float,num2:float,operation:str)-str:执行计算try:ifoperationadd:resultnum1num2elifoperationsubtract:resultnum1-num2elifoperationmultiply:resultnum1*num2elifoperationdivide:ifnum20:return错误除数不能为零resultnum1/num2else:returnf错误不支持的操作 {operation}returnf计算结果:{result}exceptExceptionase:returnf计算错误:{str(e)}asyncdef_arun(self,**kwargs):异步执行简单调用同步版本returnself._run(**kwargs)# 示例2简易天气查询工具 classWeatherInput(BaseModel):天气查询输入参数city:strField(...,description城市名称例如: 北京, 上海)date:Optional[str]Field(None,description查询日期格式: YYYY-MM-DD默认为今天)classWeatherTool(BaseTool):模拟天气查询工具真实场景可接入天气APInameweather_checkerdescription查询指定城市的天气信息。需要提供城市名称和可选日期。args_schema:Type[BaseModel]WeatherInput# 模拟天气数据真实应用中应调用API_mock_weather_data{北京:{today:晴15-25°C,tomorrow:多云16-24°C},上海:{today:小雨18-22°C,tomorrow:阴19-23°C},广州:{today:雷阵雨24-30°C,tomorrow:多云25-31°C},}def_run(self,city:str,date:Optional[str]None)-str:查询天气ifdateisNone:date_keytodaydate_str今天elifdatedatetime.today().strftime(%Y-%m-%d):date_keytodaydate_str今天else:date_keytomorrowdate_str明天ifcityinself._mock_weather_data:weatherself._mock_weather_data[city][date_key]returnf{city}{date_str}天气:{weather}else:available_cities, .join(self._mock_weather_data.keys())returnf抱歉未找到{city}的天气数据。可用城市:{available_cities}asyncdef_arun(self,**kwargs):returnself._run(**kwargs)# 示例3使用装饰器创建简单工具 fromlangchain.toolsimporttooltooldeftext_length_counter(text:str)-str:计算输入文本的长度字符数和单词数char_countlen(text)word_countlen(text.split())returnf文本分析结果:\n字符数:{char_count}\n单词数:{word_count}# 示例4文件内容读取工具 classFileReadInput(BaseModel):文件读取输入参数filepath:strField(...,description要读取的文件路径)max_lines:Optional[int]Field(10,description最大读取行数默认为10)classFileReadTool(BaseTool):安全地读取本地文件内容namefile_readerdescription读取本地文本文件的内容。需要提供文件路径。args_schema:Type[BaseModel]FileReadInputdef_run(self,filepath:str,max_lines:int10)-str:读取文件try:# 安全检查限制文件类型和大小ifnotfilepath.endswith((.txt,.md,.py,.json)):return错误只支持读取文本文件(.txt, .md, .py, .json)withopen(filepath,r,encodingutf-8)asf:lines[]fori,lineinenumerate(f):ifimax_lines:lines.append(f... (已限制显示{max_lines}行))breaklines.append(line.rstrip())content\n.join(lines)returnf文件 {filepath} 内容 (前{max_lines}行):\n{content}exceptFileNotFoundError:returnf错误找不到文件 {filepath}exceptPermissionError:returnf错误没有权限读取文件 {filepath}exceptExceptionase:returnf读取文件时出错:{str(e)}asyncdef_arun(self,**kwargs):returnself._run(**kwargs)# 使用Agent测试自定义工具 deftest_custom_tools():测试自定义工具# 初始化LLMllmChatOpenAI(modelgpt-3.5-turbo,temperature0)# 创建工具列表tools[CalculatorTool(),WeatherTool(),text_length_counter,# 装饰器创建的工具FileReadTool(),]# 创建Agentagentinitialize_agent(toolstools,llmllm,agentAgentType.ZERO_SHOT_REACT_DESCRIPTION,verboseTrue,# 显示详细执行过程handle_parsing_errorsTrue# 处理解析错误)# 测试查询print(*50)print(测试1: 数学计算)print(*50)result1agent.run(计算15.5乘以3.2的结果)print(f结果:{result1}\n)print(*50)print(测试2: 天气查询)print(*50)result2agent.run(查询北京今天的天气)print(f结果:{result2}\n)print(*50)print(测试3: 文本分析)print(*50)result3agent.run(统计这句话的长度: LangChain是一个强大的LLM应用开发框架)print(f结果:{result3}\n)# 注意文件读取测试需要实际存在的文件print(*50)print(测试4: 链式工具调用)print(*50)result4agent.run(查询上海明天的天气然后计算温度平均值。假设最高温度是查询结果中的第一个数字最低温度是第二个数字)print(f结果:{result4})# 进阶带记忆和状态的工具 classCounterInput(BaseModel):计数器操作输入action:strField(...,description操作类型: increment, decrement, reset, get)step:Optional[int]Field(1,description步长默认为1)classCounterTool(BaseTool):带状态的计数器工具namecounterdescription一个简单的计数器支持增加、减少、重置和获取当前值args_schema:Type[BaseModel]CounterInputdef__init__(self):super().__init__()self._count0# 内部状态def_run(self,action:str,step:int1)-str:执行计数器操作ifactionincrement:self._countstepreturnf计数器增加了{step}当前值:{self._count}elifactiondecrement:self._count-stepreturnf计数器减少了{step}当前值:{self._count}elifactionreset:self._count0return计数器已重置为0elifactionget:returnf当前计数器值:{self._count}else:returnf错误不支持的操作 {action}asyncdef_arun(self,**kwargs):returnself._run(**kwargs)deftest_counter_tool():测试带状态的工具print(*50)print(测试计数器工具)print(*50)counterCounterTool()# 手动测试print(counter._run(increment,5))print(counter._run(increment,3))print(counter._run(get))print(counter._run(decrement,2))print(counter._run(reset))# 主程序 if__name____main__:print(自定义Tool函数演示)print(*60)# 测试基础工具test_custom_tools()# 测试计数器工具test_counter_tool()print(\n*60)print(演示完成)4. 注意事项4.1 编写建议4.1.1 描述要清晰具体# ❌ 不好的描述description处理数据# ✅ 好的描述description 分析用户提供的CSV数据文件。支持以下操作 1. 显示前N行数据 2. 计算数值列的统计信息平均值、中位数、标准差 3. 按指定列排序数据 需要提供文件路径和操作类型。 4.1.2 错误处理要完善def_run(self,**kwargs):try:# 业务逻辑returnresultexceptValueErrorase:returnf输入错误:{str(e)}exceptConnectionErrorase:returnf连接失败:{str(e)}exceptExceptionase:returnf未知错误:{str(e)}4.1.3 参数验证要严格classSearchInput(BaseModel):query:strField(...,min_length1,max_length100)max_results:intField(5,ge1,le50)validator(query)defvalidate_query(cls,v):ifDROP TABLEinv.upper()orDELETEinv.upper():raiseValueError(查询包含非法关键词)returnv4.2 性能优化技巧4.2.1 使用缓存fromfunctoolsimportlru_cacheclassAPITool(BaseTool):lru_cache(maxsize128)def_call_api(self,params):# API调用逻辑pass4.2.2 实现异步版本asyncdef_arun(self,**kwargs):# 异步调用API或IO操作asyncwithaiohttp.ClientSession()assession:asyncwithsession.get(url)asresponse:returnawaitresponse.text()5. 常见问题与解决方案Q1: Tool函数不执行怎么办检查点确认description是否足够清晰检查args_schema是否正确定义了参数确保工具已正确添加到Agent的tools列表中Q2: 参数解析失败解决方案agentinitialize_agent(toolstools,llmllm,agentAgentType.ZERO_SHOT_REACT_DESCRIPTION,handle_parsing_errorsTrue,# 启用错误处理max_iterations5# 限制最大迭代次数)Q3: 如何调试Tool的调用# 1. 启用verbose模式agentinitialize_agent(verboseTrue)# 2. 手动测试工具toolCalculatorTool()print(tool._run(num15,num23,operationadd))# 3. 检查工具描述print(f工具名称:{tool.name})print(f工具描述:{tool.description})DEMO PROBLEMValueError: ZeroShotAgent does not support multi-input tool Calculator.AgentType.ZERO_SHOT_REACT_DESCRIPTION 不支持多参数输入的工具。你自定义的 CalculatorTool 需要接收三个参数num1, num2, operation这超出了该代理类型的处理能力。 问题根源与解决方案对比以下是两种主要的解决方案你可以根据实际情况选择方案核心思路优点缺点方案一切换代理类型将代理类型更换为支持多参数输入的工具如 STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION。改动最小仅需修改一行代码即可让当前代码运行。仍然是基于旧版Agent API的临时方案存在被废弃的风险。方案二使用新版API重构遵循LangChain官方建议弃用旧版 initialize_agent改用基于 LCEL 或 LangGraph 的新方案构建代理。官方推荐性能更优功能更灵活是未来的发展方向。需要重新学习并编写更多代码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询