当前位置: 首页 > article >正文

## 014、LangChain 中的 Tool 开发:自定义工具与第三方工具集成

昨天凌晨三点我被线上一个 Agent 的报警吵醒。日志里反复出现一条错误ToolInputParsingException: Could not parse tool input。排查下来问题出在一个自定义工具上——我写了一个查询天气的 Tool返回的是 JSON 字符串但 LLM 在调用时传进来的参数格式跟预期对不上。LLM 以为它传的是{location: Beijing}但我的工具函数签名里写的是def run(self, location: str)LangChain 的默认解析器直接把整个字典当成了一个字符串参数塞了进去。结果就是工具收到了{location: Beijing}这个字符串而不是一个字典自然就炸了。这个坑让我意识到很多人包括当时的我对 LangChain 中 Tool 的底层机制理解得不够深。今天这篇笔记我们就从这个问题出发把自定义工具和第三方工具集成的细节彻底捋一遍。1. Tool 的本质一个带“说明书”的函数LangChain 里的 Tool本质上就是一个函数外加一份给 LLM 看的“说明书”。这个说明书就是name和description。LLM 根据 description 决定要不要调用这个工具根据 name 决定调用哪个工具然后根据函数的参数签名或者你手动定义的 args_schema来生成调用参数。所以开发一个自定义工具核心就两件事写好函数逻辑写好说明书。说明书写不好LLM 要么不调用要么乱调用。2. 自定义工具三种写法各有坑LangChain 提供了三种定义 Tool 的方式我按推荐程度排个序。方式一tool 装饰器最推荐但要注意类型注解fromlangchain.toolsimporttooltooldefget_weather(location:str)-str:查询指定城市的天气。输入应为城市名称例如 Beijing 或 Shanghai。# 这里踩过坑如果返回的是 dictLLM 可能无法直接处理# 最好统一返回字符串returnf{location}的天气是晴天25°C这个写法最简洁LangChain 会自动从函数签名和 docstring 里提取参数信息。但有个隐藏问题如果你的参数是location: str Beijing给了默认值LLM 可能会偷懒不传参直接使用默认值。所以别给工具参数设默认值除非你确定 LLM 的行为符合预期。方式二继承 BaseTool 类最灵活但代码多fromlangchain.toolsimportBaseToolfrompydanticimportBaseModel,FieldclassWeatherInput(BaseModel):location:strField(description城市名称如 Beijing)classWeatherTool(BaseTool):nameget_weatherdescription查询指定城市的天气args_schema:type[BaseModel]WeatherInputdef_run(self,location:str)-str:# 实际业务逻辑returnf{location}的天气是晴天25°Casyncdef_arun(self,location:str)-str:# 异步版本如果不需要可以 raise NotImplementedErrorraiseNotImplementedError(异步调用暂不支持)这种方式的好处是你可以精确控制参数结构。比如你的工具需要同时接收location和date两个参数用 Pydantic 模型定义就非常清晰。而且args_schema里每个字段的description会被 LLM 看到这能显著提高参数生成的准确率。方式三直接实例化 Tool 类最不推荐容易出问题fromlangchain.toolsimportTooldefweather_func(location:str)-str:returnf{location}的天气是晴天25°Cweather_toolTool(nameget_weather,funcweather_func,description查询指定城市的天气。输入应为城市名称。)这种写法看着简单但问题在于description里没有明确告诉 LLM 参数格式。LLM 可能会传{location: Beijing}这种字典而你的函数只接受字符串就会触发我开头说的那个解析异常。除非你的函数只有一个参数且参数名非常直观否则别用这种写法。3. 第三方工具集成别自己造轮子LangChain 社区已经集成了大量第三方工具从 SerpAPI 到 Wikipedia从 Wolfram Alpha 到 YouTube 搜索。集成方式很简单fromlangchain_community.toolsimportWikipediaQueryRunfromlangchain_community.utilitiesimportWikipediaAPIWrapper wikipediaWikipediaQueryRun(api_wrapperWikipediaAPIWrapper(top_k_results1,doc_content_chars_max500))但这里有个容易忽略的点第三方工具的 description 可能不适合你的场景。比如 Wikipedia 工具的默认 description 是“A wrapper around Wikipedia. Useful for when you need to answer general questions about people, places, companies, facts, historical events, or other subjects.” 这个描述太长LLM 可能会被误导。我习惯在集成后手动修改 descriptionwikipedia.description搜索维基百科获取人物、地点、事件等知识。输入应为搜索关键词。另外很多第三方工具需要 API Key。别硬编码在代码里用环境变量。我见过有人把 API Key 直接写在 Tool 的__init__方法里然后代码上传到 GitHub 公开仓库——别这样写。4. 工具链的“暗坑”参数传递与错误处理回到开头的那个问题。为什么 LLM 传的参数格式会跟工具预期的不一致因为 LLM 看到的“说明书”是description和args_schema但实际执行时LangChain 内部有一个ToolInputParser负责把 LLM 输出的字符串通常是 JSON解析成 Python 对象。如果你的工具参数简单比如只有一个字符串LLM 可能会直接输出Beijing而不是{location: Beijing}。这时候默认的解析器会尝试把Beijing当成 JSON 解析结果失败。解决方案有两个在 description 里明确告诉 LLM 参数格式。比如“输入应为 JSON 格式例如{\location\: \Beijing\}”。但 LLM 不一定每次都听话。使用 Pydantic 模型定义 args_schema并设置strictTrue。这样 LangChain 会强制 LLM 输出符合 schema 的 JSON。我推荐第二种因为更可靠。但要注意strictTrue会让 LLM 在无法生成合法 JSON 时直接报错而不是尝试“猜”一个格式。这其实更好——宁可让 Agent 明确失败也不要让它带着错误数据继续执行。5. 调试技巧让 LLM 的“思考过程”可见当你发现工具调用不正常时第一件事不是改代码而是看 LLM 到底输出了什么。在 LangChain 中可以通过设置verboseTrue来打印 LLM 的完整输出agentinitialize_agent(tools[weather_tool],llmllm,agentAgentType.ZERO_SHOT_REACT_DESCRIPTION,verboseTrue# 这里踩过坑生产环境记得关掉否则日志会爆炸)你会看到类似这样的输出 Entering new AgentExecutor chain... Thought: 用户想知道北京的天气我需要调用 get_weather 工具。 Action: get_weather Action Input: Beijing Observation: Beijing 的天气是晴天25°C Thought: 我已经得到了结果可以回答用户了。 Final Answer: 北京今天天气晴朗气温25°C。如果Action Input的格式跟你预期的不一样那就是 description 或 args_schema 的问题。如果Observation是空或者报错那就是工具函数本身的问题。6. 个人经验工具开发的三条铁律工具函数的返回值必须是字符串。不要返回 dict、list 或自定义对象。LLM 只能理解文本你返回一个 Python 对象它看不懂。如果必须返回结构化数据用 JSON 字符串并在 description 里说明格式。每个工具只做一件事。我见过有人写一个execute_sql工具既能查询又能修改还能删除。这很危险——LLM 可能会在用户只要求查询时执行了删除操作。把查询、修改、删除拆成三个独立的工具每个工具的 description 里明确说明它的职责和限制。给工具加“护栏”。比如一个发送邮件的工具在_run方法里检查收件人地址是否在白名单中。LLM 可能会被 prompt injection 攻击诱导它发送恶意邮件。工具函数是你最后的防线别完全信任 LLM 的输入。最后关于第三方工具集成我的建议是能用现成的就别自己写。LangChain 社区维护的第三方工具经过了大量用户的测试稳定性比自己写的要高。但一定要检查它的 description 和参数定义是否符合你的需求必要时手动修改。下一篇我会讲 Agent 的“记忆”机制——为什么你的 Agent 总是“记不住”之前说过的话以及如何让它在长对话中保持上下文连贯。

相关文章:

## 014、LangChain 中的 Tool 开发:自定义工具与第三方工具集成

昨天凌晨三点,我被线上一个 Agent 的报警吵醒。日志里反复出现一条错误:ToolInputParsingException: Could not parse tool input。排查下来,问题出在一个自定义工具上——我写了一个查询天气的 Tool,返回的是 JSON 字符串&#x…...

用快马平台将awesome-design-md秒变可交互设计资源库原型

最近在整理设计资源时,发现了一个很棒的markdown项目awesome-design-md,里面收集了大量优质的设计资源。但直接看markdown文件总觉得不够直观,于是尝试用InsCode(快马)平台快速把它变成了一个可交互的原型,整个过程比想象中简单很…...

开发者必备设计技能:从原则到代码的完整学习路径与实践指南

1. 项目概述:一份为开发者量身定制的设计技能图谱在技术驱动的产品开发世界里,一个普遍存在的认知鸿沟是:开发者懂代码,设计师懂美学,两者之间仿佛隔着一道无形的墙。很多优秀的项目,其核心功能强大、逻辑严…...

嵌入式开发提效神器:一个框架整合命令行、低功耗与设备管理(基于IAR/Keil)

嵌入式开发提效神器:模块化框架设计实战指南 在资源受限的MCU开发中,工程师们常常面临这样的困境:功能模块相互纠缠如同乱麻,调试时只能依赖点灯大法,低功耗设计需要反复修改硬件驱动。这种开发模式不仅效率低下&#…...

FlowiseAI:可视化低代码平台,快速构建LLM应用与AI智能体

1. 项目概述:用FlowiseAI,像搭积木一样构建你的AI智能体 如果你对AI应用开发感兴趣,但又觉得从零开始写代码调用API、处理复杂逻辑太麻烦,那么FlowiseAI(简称Flowise)这个项目,你绝对不能错过。…...

《源·觉·知·行·事·物:生成论视域下的统一认知语法》第五章 事:行在时空中的具体化

原创声明:本文为作者周林东原创学术理论著作《源觉知行事物:生成论视域下的统一认知语法》的博客连载版。本书所述技术方案已提交中国发明专利申请,受相关法律保护。任何形式的商业使用,请与作者联系取得授权。欢迎基于学术目的的…...

利用快马AI五分钟生成免费游戏合集网站原型验证创意

利用快马AI五分钟生成免费游戏合集网站原型验证创意 最近在琢磨一个游戏合集网站的想法,核心是想做个类似"免费游戏大全"的聚合平台。这种项目特别适合用InsCode(快马)平台来快速验证创意,因为: 原型开发痛点:传统方式…...

FPGA动态时钟禁用技术原理与节能实践

1. 动态时钟禁用技术背景与价值在数字电路设计中,时钟网络就像城市交通系统中的红绿灯控制系统,持续不断地向各个功能模块分发时序信号。但与传统交通灯不同,这些"红绿灯"即使在没有"车辆"(数据)需…...

RocketMQ系列第三篇:Java原生基础使用实操,手把手写生产者消费者Demo

文章目录一、本篇前言:理论落地,从部署到代码实操二、前置准备:项目环境必备配置1. 基础环境要求2. 导入RocketMQ核心Maven依赖三、核心基础:RocketMQ消息核心对象说明1. DefaultMQProducer:消息生产者核心类2. Defaul…...

告别VSCode C++插件卡顿!ROS开发用clangd实现丝滑补全的保姆级配置

告别VSCode C插件卡顿!ROS开发用clangd实现丝滑补全的保姆级配置 在ROS开发中,代码补全的流畅度直接影响开发效率。许多开发者习惯使用VSCode进行ROS项目开发,但原生的C/C插件在大型项目中的表现往往不尽如人意——补全速度慢、误报错误、占用…...

深度神经网络中的不等式紧性分析与工程实践

1. 项目背景与核心价值深度神经网络中的不等式分析一直是理论研究的难点和热点。子加性与子乘性不等式作为描述网络层间关系的重要数学工具,其紧性分析直接关系到我们对神经网络表达能力、泛化性能和优化过程的理解。在实际应用中,这类分析能够帮助我们设…...

3步搞定RTL8821CE无线网卡:Linux驱动安装终极指南

3步搞定RTL8821CE无线网卡:Linux驱动安装终极指南 【免费下载链接】rtl8821ce 项目地址: https://gitcode.com/gh_mirrors/rt/rtl8821ce 还在为Linux系统下Realtek RTL8821CE无线网卡无法正常工作而烦恼吗?这款高性能的802.11ac无线芯片在Window…...

KVCache-Factory:LLM推理加速的缓存工厂设计与实战

1. 项目概述:一个为LLM推理加速而生的缓存工厂如果你最近在折腾大语言模型(LLM)的本地部署或者API调用,大概率会遇到一个头疼的问题:推理速度慢,尤其是当输入序列(Prompt)很长&#…...

Command line is too long. Shorten the command line via JAR manifest or via a classpath file

这种情况一般是在本地通过windows启动才会触发的,原因是启动时是使用命令行启动,而windows的启动命令是8191 个字符,超过的话就会报这个异常 1.启动命令行:2.异常:Error running ${启动类} Error running ${启动类}. Command line is too long. Shorten the command line via …...

完美光标库原理与应用:贝塞尔曲线实现平滑跟随动画

1. 项目概述:从“完美光标”说起最近在折腾一个需要高度自定义光标交互的前端项目,遇到了一个挺有意思的库——caterpi11ar/perfect-cursor。乍一看这个名字,你可能会觉得它又是一个处理鼠标样式的CSS库,但实际上,它解…...

告别记忆负担:用快马ai将自然语言秒变精准gitbash命令

作为一个经常和Git打交道的开发者,我深知那些复杂的Git命令有多让人头疼。特别是刚入门的时候,光是记住git rebase和git merge的区别就够喝一壶的。最近我发现了一个特别实用的方法,用AI来帮我们生成Git命令,简直就像有个随身的Gi…...

Tessy单元测试避坑指南:手把手解决9个最常见的头文件导入与编译错误

Tessy单元测试避坑实战:9类头文件与编译错误的深度解析与解决方案 嵌入式开发者在初次接触Tessy进行C/C单元测试时,头文件导入与编译环节堪称"新手坟场"。本文将从工程配置底层逻辑出发,系统梳理九类高频错误的诊断方法与解决路径&…...

基于MCP协议的代码智能体:从代码理解到精准操作

1. 项目概述:一个为开发者赋能的代码生成与理解工具最近在GitHub上看到一个挺有意思的项目,叫opencode-mcp,作者是AlaeddineMessadi。第一眼看到这个仓库名,我下意识地以为又是一个基于大语言模型的代码生成工具,毕竟“…...

别再只用snmputil了!Windows下net-snmp 5.5.0完整安装与SNMPv3配置实战

别再只用snmputil了!Windows下net-snmp 5.5.0完整安装与SNMPv3配置实战 如果你还在用snmputil这类功能受限的工具管理Windows网络设备,可能会错过SNMP协议90%的高级功能。作为运维工程师,我经历过从snmputil到net-snmp的升级过程——就像从自…...

AI接口代理服务器:统一多模型调用,集成缓存与流式响应

1. 项目概述与核心价值最近在折腾AI应用开发,特别是想给现有系统快速集成一个智能对话或代码补全能力时,发现了一个宝藏级的开源项目:lucgagan/completions。这个项目在GitHub上不算特别火爆,但它的定位非常精准——它不是一个庞大…...

嵌入式系统电源与时钟管理技术解析

1. 嵌入式系统电源与时钟管理架构解析在移动设备和物联网终端爆炸式增长的今天,嵌入式系统的能效比成为产品竞争力的关键指标。我曾参与一款智能穿戴设备的开发,当系统在动态电压频率调节(DVFS)和SmartReflex技术加持下&#xff0…...

Blender顶点权重混合修改器,除了合并还能做什么?3个你可能不知道的实用技巧

Blender顶点权重混合修改器:超越合并的3个高阶应用技巧 在角色绑定和布料模拟中,顶点权重是控制模型变形的核心数据层。大多数Blender用户只把顶点权重混合修改器当作简单的合并工具,却忽略了它在权重微调领域的强大潜力。今天我们将打破常规…...

Go语言重构AI编码助手:gocode的极速架构与多智能体实战

1. 项目概述:为什么我们需要一个全新的AI编码助手如果你和我一样,每天都在终端里敲代码,那你肯定对AI编码助手不陌生。从早期的GitHub Copilot Chat到后来惊艳全场的Claude Code,这些工具确实改变了我们写代码的方式。但用久了&am…...

通过TaotokenCLI工具一键配置团队统一的大模型开发环境

通过TaotokenCLI工具一键配置团队统一的大模型开发环境 1. 安装Taotoken CLI工具 Taotoken CLI提供两种安装方式,适合不同使用场景。对于需要频繁调用CLI的团队管理员,推荐全局安装: npm install -g taotoken/taotoken若仅需临时使用或避免…...

维普 AIGC 率太高不用愁!这几款降重工具一次解决查重率和 AI 痕迹两个难题

毕业季论文查重、AIGC 检测双重压力拉满!不少同学熬大夜改稿,维普查重率仍飘红,AIGC 疑似率更是居高不下,反复修改却越改越乱,甚至影响论文核心逻辑。其实不用死磕手动改写,2026 年多款双效降重神器已实现 …...

一文帮你搞懂JavaScript的核心概念

JavaScript的核心概念介绍JavaScript作为现代Web开发的基石,掌握其核心概念对开发者至关重要。以下从语言特性、运行机制和关键组件三个维度展开分析。变量与作用域JavaScript采用var、let、const三种变量声明方式。var存在变量提升特性,函数作用域&…...

【农业物联网PHP可视化实战指南】:手把手教你用Laravel+Chart.js实时渲染土壤温湿度数据流

更多请点击: https://intelliparadigm.com 第一章:农业物联网数据可视化项目概述 农业物联网数据可视化项目旨在将田间部署的温湿度传感器、土壤水分探头、光照强度计及气象站等设备采集的实时数据,通过统一协议汇聚至边缘网关,并…...

保姆级避坑指南:在VMware虚拟机Ubuntu20.04上搞定RobotiQ 2F-85夹爪的ROS Noetic驱动

虚拟机环境下的RobotiQ夹爪ROS驱动避坑实战手册 在机器人开发领域,虚拟化环境与物理硬件的联动调试一直是令人头疼的难题。特别是当RobotiQ 2F-85这样的工业级夹爪遇上VMware虚拟化的Ubuntu系统,各种"坑"接踵而至——从rosdep的神秘报错到串口…...

为什么你的AI策略在R 4.5中年化衰减超42%?——揭秘RcppParallel加速失效、xts时区错位与回测引擎底层Bug

更多请点击: https://intelliparadigm.com 第一章:R 4.5量化投资AI策略回测的系统性失效诊断 当R语言升级至4.5版本后,大量基于quantstrat、blotter与TTR构建的AI驱动回测框架出现静默性失效——非报错崩溃,而是信号生成偏移、滑…...

Dify+PLC/SCADA文档智能检索落地全记录(含OPC UA语义对齐技术细节)

更多请点击: https://intelliparadigm.com 第一章:DifyPLC/SCADA文档智能检索落地全记录(含OPC UA语义对齐技术细节) 在工业自动化系统中,PLC与SCADA文档常以PDF、Word及HTML混合格式分散存储,导致运维人员…...