工具设计的坏味道:什么样的定义会让模型乱调

什么样的工具定义会让模型乱调 ,一句话:模型乱调工具,多半不是模型分不清,而是你的定义写得像一段坏代码------名字糊、描述空、参数乱,模型捉摸不准。

前言

「模型调错工具」不能只归咎于「模型能力不行」------「这个模型不会用我的工具」,可能换更强的模型、调温度、加系统提示词......折腾一圈,问题还在。其实大多数「乱调」的根子,在你写的工具定义 上。因为模型看不到你的代码,它唯一能看到的,是你塞进上下文的那段 JSON------名字、描述、参数。这段 JSON 就是模型手里的「API 文档」;文档写得烂,再聪明的模型也只能瞎猜。 而工具定义的「烂」,是有迹可循的,下面按四个维度一个个说。

一、名字:模型检索工具的第一信号

名字是模型「要不要用这个工具、这是干嘛的」的第一判断。它不好,模型根本不会点进来,或者点错了对象。

jsonc 复制代码
// 坏味道
{ "name": "search", "description": "..." }      // 太泛,搜什么?文件?网页?
{ "name": "get_file" }, { "name": "read_file" } // 两个名字几乎一样,模型分不清
{ "name": "process", "description": "..." }     // 动作不明确,process 是什么动作?
jsonc 复制代码
// 好一点:动词开头 + 明确宾语,一眼看出「做什么 + 动什么」
{ "name": "read_file" }
{ "name": "web_search" }
{ "name": "delete_file" }

取舍点 :一个通用的起名规则是「动词 + 宾语 」,而且动词要具体------read_fileget_file 清楚,delete_fileprocess_file 清楚。两个工具名字太像,是重灾区:模型会「觉得差不多」而乱选。名字不是给人类看的简称,是给模型看的检索关键词。

二、描述:模型决定「用不用、何时用」的依据

如果说名字是「点不点进来」,描述就是「点进来之后,该不该真的用、什么场景用」。描述写不好,工具要么被滥用、要么被闲置。

jsonc 复制代码
// 坏味道
{ "name": "search_files", "description": "search files" }        // 等于没说
{ "name": "send_email", "description": "当用户要求时发送邮件" }  // 废话:模型当然知道「用户要求时」
{ "name": "delete_file", "description": "删除文件" }             // 没写副作用
jsonc 复制代码
// 好一点:说清「做什么 + 什么时候用 + 有什么后果」
{
  "name": "delete_file",
  "description": "永久删除指定路径的文件,不可恢复。仅在用户明确要求删除时才调用,不要因为内容冗余就主动删除。"
}

取舍点 :一条好的描述,至少回答三件事------做什么、什么时候该用、用了有什么后果(副作用) 。尤其是副作用:delete_filesend_emailrun_command 这种「不可逆 / 花钱 / 对外发送」的工具,不写明后果,模型会轻率地调用。描述的价值不在「解释工具」,而在「约束模型什么时候不该用」。

三、参数:让模型「填得对」

工具定义的另一半,是参数 schema。模型要往里填值,schema 含糊,填出来的值就乱。

jsonc 复制代码
// 坏味道
{ "properties": { "p": { "type": "string" } } }        // 参数名是缩写,p 是什么?
{ "properties": { "path": { "type": "string" } } }     // 没标必填/可选
{ "properties": { "mode": { "type": "string" } } }     // 枚举不列全,模型会编一个
jsonc 复制代码
// 好一点:每个参数都有名字、类型、说明、是否必填、枚举/默认值/示例
{
  "name": "write_file",
  "parameters": {
    "type": "object",
    "required": ["path", "content"],
    "properties": {
      "path":    { "type": "string", "description": "要写入的文件路径" },
      "content": { "type": "string", "description": "要写入的完整内容" },
      "mode": {
        "type": "string",
        "enum": ["overwrite", "append"],
        "default": "overwrite",
        "description": "覆盖写入还是追加写入"
      }
    }
  }
}

取舍点 :三个最容易被忽略的点------必填要显式标 required (否则模型不确定哪些能省);枚举要给全 enum (否则模型会自己编一个不在列表里的值);给默认值或示例 (能显著降低模型乱填的概率)。参数的描述不是装饰,是模型「填值的依据」。

四、粒度:一个工具只干一件事

最后一个坏味道,是「粒度」------工具切得太粗或太细,都会让模型困惑。

jsonc 复制代码
// 太粗:一个工具干太多,行为取决于参数组合,模型很难预测它到底会做什么
{ "name": "do_file_operation", "description": "读写删改文件都靠它" }

// 太细:三个工具其实是同一件事,模型不知道选哪个
{ "name": "read_file" }, { "name": "open_file" }, { "name": "load_file" }

取舍点 :好工具的粒度,跟好函数一样------一个工具一个明确动作 。太粗,模型得先推理「这一堆参数怎么组合出我想要的动作」,容易组合错;太细,模型在几个等价工具之间反复横跳。判断标准:一个工具能不能用一句话说清「它只做一件事」。说不清,就说明该拆或该并。

五、原点:工具定义,就是「写给模型的 API 文档」

把四节收拢成一个判断:

模型不看你写的代码,只看你塞进上下文的那段 JSON 定义。所以「设计工具」本质上是「给模型写 API 文档」------名字是标题、描述是正文、参数是字段说明。

这也是为什么工具设计的坏味道,和代码的坏味道几乎一一对应:名字含糊(像坏变量名)、描述空(像没注释)、参数乱(像没类型)、粒度烂(像上帝函数)。区别只在于:代码的坏味道,你迟早会重构;工具定义的坏味道,你却常常以为「是模型不行」,结果一直怪错了对象。

所以判断一个工具的「定义」写得好不好,就一条:把一个不认识这个工具的人(或者模型)叫来,光看这段 JSON,能不能说出「它做什么、什么时候用、参数怎么填」。能,就合格;不能,就是坏味道。

结语

坏味道就四样------名字糊、描述空、参数乱、粒度烂 。对应的药方也就四条:名字「动词 + 宾语」、描述「做什么 + 何时用 + 副作用」、参数「类型 + 必填 + 枚举 + 示例」、粒度「一个工具一件事」

工具定义是模型手里唯一的「API 文档」,你把文档写清楚了,模型才可能「调得对」。而这件事,恰恰是 Agent 工程里最便宜、也最被低估的一环。


参考:

相关推荐
洞见新研社1 小时前
豆包手机发售,AI代理进入“终端”竞赛
人工智能·ai
QC777LX1 小时前
中文专业在AI行业的新岗位:从Prompt到人文训练
人工智能
知几蜗牛1 小时前
2.8万亿参数上云之后,Kimi K3的门槛变低了吗
人工智能
jingli91 小时前
微信自动回复怎么设置?重复问题怎么自动回答——私域FAQ自动应答搭建全流程(关键词匹配+知识库+语义AI,2026实操版)
人工智能·自动化·用户运营
产品设计大观2 小时前
墨刀AI客户端怎么干活?派任务、本地执行、交付PRD和原型
agent·原型·墨刀·prd·ai工作台·墨刀ai客户端·产研
用户3134672143542 小时前
Agent 开发学习笔记(七):RAG: 从建库到检索到生成
langchain·agent
Ai_easygo2 小时前
AI下半场_09_CSDN版_Agent安全攻防
人工智能
速易达网络2 小时前
宇树机器人和Microduck仿真区别
人工智能
PNP Robotics2 小时前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人