免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

自定义工具开发实战:把任意Python函数变成AI Agent可用的工具

自定义工具开发实战:把任意Python函数变成AI Agent可用的工具 自定义工具开发把任意Python函数变成Agent工具内置工具只能解决通用问题。真正做项目的时候你肯定需要写自己的工具。比如对接公司内部的API操作特定的业务系统调用内部的数据库。这些都得自己写。好消息是在LangChain里写自定义工具特别简单。把一个普通的Python函数装饰一下Agent就能调用了。这一篇我们从最简单的开始一步步讲怎么写工具、怎么写好工具描述、怎么处理异常以及实际项目里的一些经验。最简单的写法用tool装饰器是最简单的方式。fromlangchain.toolsimporttooltooldefadd_numbers(a:int,b:int)-str:把两个数字相加返回相加的结果。returnf结果是{ab}就这么简单。一个普通的函数加上tool装饰器就变成了Agent能用的工具。函数名就是工具名。函数的文档字符串就是工具的描述。函数的参数类型注解就是参数的类型说明。这三样东西都很重要。Agent靠它们来理解这个工具是干什么的、什么时候该用、参数怎么传。写的时候注意几点。函数名要直观。一看就知道这个工具做什么的。别起太抽象的名字。文档字符串要写详细。别只写一句话。说清楚功能、参数含义、什么时候用、举个例子。后面会专门讲怎么写好描述。参数类型要标清楚。int、str、float这些基本类型直接写就行。复杂类型用Pydantic模型。用Pydantic定义输入参数简单的时候直接写类型注解就行。参数多了或者参数有嵌套结构最好用Pydantic模型来定义。fromlangchain.toolsimporttoolfrompydanticimportBaseModel,FieldclassWeatherInput(BaseModel):city:strField(description城市名称比如北京、上海、广州)date:strField(description查询的日期格式为YYYY-MM-DD比如2026-08-06)tool(args_schemaWeatherInput)defget_weather(city:str,date:str)-str:查询指定城市指定日期的天气情况。 返回天气状况、温度、湿度、风力等信息。 例如用户问明天北京天气怎么样的时候可以调用这个工具。 # 实际项目中这里调用天气APIreturnf{city}{date}的天气是晴25度。用Pydantic的好处是你可以给每个参数加description还可以加校验规则。Agent能更准确地理解参数的含义参数传错的概率会降低。参数超过两个的时候我建议都用Pydantic来定义。多写几行代码省很多调试的时间。工具描述怎么写才好用工具能不能用好描述占了八成。描述写得好Agent用得准。描述写得烂Agent经常选错工具、填错参数。我自己总结了几个写工具描述的经验。第一说清楚能做什么也说清楚不能做什么。边界清楚了Agent才知道什么时候该调用、什么时候不该调用。第二举例子。在描述里加一两个使用场景的例子。比如当用户问’某某城市天气怎么样’的时候可以调用这个工具。例子对大模型特别有效。第三参数说明要具体。每个参数是什么意思、什么格式、有什么限制都写清楚。有可选值就列出来。日期格式、数字范围、单位都说明白。第四说明返回值的格式。告诉Agent工具会返回什么样的结果它拿到结果以后知道怎么处理。举个反例和正例对比一下。反面教材。tooldefsearch(query:str)-str:搜索工具。...这种描述等于没写。Agent根本不知道什么时候该用、参数怎么传。正面教材。tooldefsearch(query:str)-str:通过搜索引擎查询互联网上的最新信息。 当你需要回答以下类型的问题时使用这个工具 - 实时新闻和热点事件 - 最新的产品价格、发布日期 - 不确定的知识或者你的训练数据里可能没有的信息 - 具体的事实核查 参数说明 query: 搜索关键词。用中文或英文都可以。不要太长20个字以内效果最好。 返回搜索结果的摘要包含标题、摘要和链接。 ...这样写Agent就很清楚什么时候该调用、怎么传参数。处理异常和错误工具调用总会出错。网络断了API限流了参数不对数据库连不上。各种情况都可能发生。出错了怎么办。两个原则。第一工具内部要捕获异常不要直接抛出去。Agent拿到异常信息也不知道怎么处理。第二返回给Agent的错误信息要有意义。告诉它哪里错了、可能的原因、建议的处理方式。它才能决定是重试、换个方式还是告诉用户。比如这样。tooldefget_weather(city:str)-str:查询城市天气。try:resultcall_weather_api(city)returnresultexceptNetworkError:return网络连接失败无法查询天气。请稍后再试。exceptCityNotFoundError:returnf找不到{city}的天气数据。请确认城市名称是否正确或者换一个城市试试。exceptExceptionase:returnf查询天气时出现未知错误{e}。不同的错误返回不同的提示。Agent能根据提示决定下一步怎么做。城市找不到就换个名字网络错了就重试。如果只返回出错了三个字Agent也不知道该怎么办任务就卡住了。同步和异步默认的工具是同步的。如果你的工具里有IO操作比如网络请求、数据库查询可以写成异步的性能更好。toolasyncdefasync_get_weather(city:str)-str:异步查询天气。resultawaitasync_weather_api(city)returnresult用的时候调用ainvoke而不是invoke。简单的工具无所谓同步异步。IO密集型的工具做成异步的并发调用的时候速度会快很多。完整示例最后给一个完整的自定义工具例子你可以照着写。fromlangchain.toolsimporttoolfrompydanticimportBaseModel,FieldimportrequestsclassTranslateInput(BaseModel):text:strField(description要翻译的文本可以是中文或英文)target_lang:strField(description目标语言可选值zh中文、en英文、ja日文,)tool(args_schemaTranslateInput)deftranslate(text:str,target_lang:str)-str:文本翻译工具。支持中文、英文、日文互译。 当用户要求翻译文本或者用户说的语言和默认语言不同时可以使用这个工具。 例如用户说把这句话翻译成英文、这个日语是什么意思的时候。 参数说明 text: 要翻译的原文内容长度不超过5000字 target_lang: 翻译后的目标语言代码 返回翻译后的文本内容。 try:# 这里替换成实际的翻译API调用responserequests.post(https://api.translation.example.com/translate,json{text:text,target:target_lang},timeout10,)response.raise_for_status()resultresponse.json()returnf翻译结果{result[translated_text]}exceptrequests.Timeout:return翻译服务超时了请稍后重试。exceptrequests.HTTPErrorase:ife.response.status_code429:return翻译请求太频繁了等一下再试。returnf翻译服务出错了状态码{e.response.status_code}。exceptExceptionase:returnf翻译时出现未知错误{e}。这个例子包含了Pydantic参数定义、详细的工具描述、异常处理。可以作为你写自定义工具的模板。下一篇我们讲搜索引擎接入。搜索是Agent最重要的能力之一我们深入讲一讲怎么接、怎么用好。
返回列表