LangChain 工具调用异常:arg1 参数错误的成因与解决方案

发布时间 - 2026-01-20 00:00:00    点击率:

langchain 代理在调用自定义工具时意外传入 `arg1` 参数,导致 `typeerror`,根本原因是工具签名未被正确识别——使用 `basetool` 子类时未声明 `args_schema`,而 langchain v0.1+ 默认采用 pydantic 模型解析参数,需显式定义输入结构。

在 LangChain(尤其是 v0.1.x 及以上版本)中,当 Agent 执行工具调用时,它不再简单地将字典解包为位置参数,而是基于工具的输入 schema 进行结构化解析。若你继承 BaseTool 但未定义 args_schema,LangChain 会 fallback 到一个默认行为:将传入的单个参数字典(如 {'arg1': '...'})强行映射为名为 arg1 的关键字参数,从而引发 _run() 方法接收未声明参数的错误。

✅ 正确做法:为 BaseTool 显式声明 args_schema

你需要使用 Pydantic BaseModel 定义输入结构,并将其赋值给 args_schema 类属性:

from langchain.tools import BaseTool
from pydantic import BaseModel, Field

class SQLFilterInput(BaseModel):
    query_input: str = Field(..., description="用户自然语言查询,例如 '2025年8月计算机设备的平均温度'")

class SQLFilterTool(BaseTool):
    name = "filter_user_query"
    description = "根据用户自然语言问题生成结构化SQL过滤条件(用于后端数据筛选)

" args_schema: type[BaseModel] = SQLFilterInput # ← 关键!必须显式声明 def _run(self, query_input: str) -> str: return sql_filter_vanna(query_input) async def _arun(self, query_input: str) -> str: # 注意:_arun 应为 async def,且返回 awaitable 或使用 asyncio.to_thread(如需同步函数) return await asyncio.to_thread(sql_filter_vanna, query_input)
⚠️ 注意事项:args_schema 必须是 pydantic.BaseModel 的子类,字段名需与 _run 方法参数名严格一致(此处为 query_input);若 _run 接收多个参数(如 query_input: str, db_name: str),则 SQLFilterInput 中需对应定义全部字段;async def _arun 的签名也应与 _run 保持语义一致(参数名可不同,但逻辑输入应匹配);

✅ 更简洁方案:优先使用 @tool 装饰器(推荐)

正如答案中所示,@tool 是 LangChain 官方推荐的轻量级工具定义方式,它自动推导 schema(基于类型注解 + docstring),无需手动管理 BaseModel:

from langchain.agents import tool

@tool
def filter_user_query(query_input: str) -> str:
    """根据用户自然语言问题生成SQL过滤条件。

    例如输入:"2025年8月计算机设备的平均温度" → 输出:"WHERE device_type = 'computer' AND month = 8 AND year = 2025"
    """
    return sql_filter_vanna(query_input)

该方式自动注册为 Tool 实例,支持多参数、类型校验、描述提取,且与最新 Agent(如 OpenAIToolsAgent、ReactAgent)完全兼容。

? 补充说明:为什么之前能运行,现在报错?

  • 你提到“几天前代码正常”,大概率是升级了 LangChain 版本(如从 0.0.x 升至 0.1.0+);
  • 旧版 LangChain 对 BaseTool 的参数解析较宽松,新版强化了 schema 驱动机制以提升可靠性与可调试性;
  • @tool 装饰器在各版本中行为更稳定,是生产环境首选。

✅ 总结

方案 是否推荐 关键要求
BaseTool 子类 ⚠️ 仅需高度定制时用 必须实现 args_schema,字段名与 _run 参数严格对齐
@tool 装饰器 ✅ 强烈推荐 使用类型注解 + docstring,零配置即用

选择 @tool 可大幅降低维护成本,避免隐式参数映射陷阱。如需扩展功能(如异步支持、自定义序列化),再考虑 BaseTool 并严格遵循 schema 规范。


# react  # 计算机  # 工具  # 后端  # ai  # openai  # 为什么  # 子类  # 继承  # 异步  # langchain  # 自然语言  # 自定义  # 如需  # 结构化  # 字段名  # 尤其是  # 多个  # 几天  # 所示 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: JS弹性运动实现方法分析  Laravel PHP版本要求一览_Laravel各版本环境要求对照  利用JavaScript实现拖拽改变元素大小  php打包exe后无法访问网络共享_共享权限设置方法【教程】  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  如何在 Pandas 中基于一列条件计算另一列的分组均值  如何在自有机房高效搭建专业网站?  如何快速生成凡客建站的专业级图册?  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  LinuxCD持续部署教程_自动发布与回滚机制  使用spring连接及操作mongodb3.0实例  JavaScript如何实现路由_前端路由原理是什么  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)  Laravel如何实现用户密码重置功能?(完整流程代码)  如何在阿里云香港服务器快速搭建网站?  Laravel如何为API生成Swagger或OpenAPI文档  javascript基于原型链的继承及call和apply函数用法分析  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  桂林网站制作公司有哪些,桂林马拉松怎么报名?  大同网页,大同瑞慈医院官网?  做企业网站制作流程,企业网站制作基本流程有哪些?  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  文字头像制作网站推荐软件,醒图能自动配文字吗?  Android中AutoCompleteTextView自动提示  Laravel如何发送系统通知?(Notification渠道示例)  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  北京的网站制作公司有哪些,哪个视频网站最好?  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  JavaScript实现Fly Bird小游戏  Swift开发中switch语句值绑定模式  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  重庆市网站制作公司,重庆招聘网站哪个好?  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  简单实现jsp分页  如何快速生成ASP一键建站模板并优化安全性?  怎么用AI帮你设计一套个性化的手机App图标?  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  如何快速上传自定义模板至建站之星?  详解Android图表 MPAndroidChart折线图