Skip to content

Latest commit

 

History

History
226 lines (171 loc) · 5.91 KB

File metadata and controls

226 lines (171 loc) · 5.91 KB

8.2 工具定义与设计

8.2.1 优秀工具定义的特征

一个优秀的工具定义应该:

  • 清晰明确:模型能准确理解工具的用途
  • 参数完整:所有必要参数都有定义
  • 易于使用:参数设计简洁合理
  • 文档充分:描述和示例足够详细

8.2.2 工具定义结构

{
  "name": "search_products",
  "description": "在产品数据库中搜索商品",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "搜索关键词"
      },
      "category": {
        "type": ["string", "null"],
        "enum": ["electronics", "clothing", "books", null],
        "description": "产品类别"
      },
      "price_max": {
        "type": ["number", "null"],
        "description": "最高价格限制"
      },
      "sort_by": {
        "type": ["string", "null"],
        "enum": ["price", "rating", "newest", null],
        "description": "排序方式;为空时由服务端使用默认排序"
      }
    },
    "required": ["query", "category", "price_max", "sort_by"],
    "additionalProperties": false
  }
}

生产环境应优先使用严格 JSON Schema:关闭额外字段、明确所有属性的 required 语义,并用 null 或显式枚举表达可选值。不同供应商对 strict mode、默认值、流式部分 JSON 和复杂 schema 关键字的支持不完全一致,工具层仍需使用成熟 JSON Schema 库做服务端校验,不能只依赖模型“按格式输出”。

8.2.3 设计原则

原则一:单一职责

每个工具只做一件事,避免功能过于复杂:

❌ 不好:process_order(action, ...)  # 可创建、更新、取消
✓ 好:create_order(...)、update_order(...)、cancel_order(...)

原则二:参数设计清晰

参数应该直观、类型明确:

❌ 不好:date="20260301"  # 字符串,格式不清
✓ 好:date="2026-03-01"  # ISO 格式,有说明

原则三:提供足够的描述

描述应该帮助模型理解何时以及如何使用:

{
  "name": "calculate_shipping",
  "description": "计算订单的运费。当用户询问运费或下单时需要计算运费时调用。需要提供收货地址和商品重量。"
}

原则四:合理使用枚举

受限的参数使用枚举限制:

{
  "priority": {
    "type": "string",
    "enum": ["low", "medium", "high"],
    "description": "任务优先级"
  }
}

8.2.4 常见工具类型

类型 示例 特点
查询类 搜索、获取信息 只读,无副作用
操作类 创建、更新、删除 有副作用,需确认
计算类 数学运算、转换 确定性输出
通信类 发送邮件、消息 外部影响

8.2.5 工具数量的权衡

工具数量影响效果和成本:

  • 太少:能力受限
  • 太多:模型选择困难、Token 开销大

建议:

  • 核心场景所需工具优先
  • 动态加载相关工具
  • 按场景分组管理

8.2.6 工具分组策略

将工具按功能分组,动态加载:

graph TB
    A["全部工具"] --> B["通用工具组"]
    A --> C["数据查询组"]
    A --> D["订单操作组"]
    A --> E["客服工具组"]
Loading

图 8-2:工具分组策略

根据对话场景选择加载哪个工具组。

8.2.7 工具文档最佳实践

描述模板

[用途]。当[触发条件]时调用。[返回内容概述]。

示例:

获取用户的订单历史。当用户询问过去的订单或购买记录时调用。返回订单列表,包含订单号、日期、金额和状态。

参数说明

每个参数都应有清晰的描述,必要时给出示例:

{
  "phone": {
    "type": "string",
    "description": "用户手机号码,格式如 13812345678"
  }
}

8.2.8 工具测试

工具定义需要测试:

  1. 理解测试:模型是否能正确理解何时调用
  2. 参数测试:参数提取是否准确
  3. 边界测试:模糊情况如何处理
  4. 拒绝测试:无关请求是否不会调用

8.2.9 上下文感知的工具设计

下面是一些业界常用的高级工具设计技巧,重点在于优化上下文使用效率。

命名空间

当智能体需要访问数十个 MCP 服务器和数百个工具时,工具功能重叠或用途模糊会导致选择困难。

命名空间策略:

  • 按服务分组asana_searchjira_searchgithub_search
  • 按资源分组asana_projects_searchasana_users_search
✓ 好:github.createPullRequest、slack.sendMessage
❌ 不好:create_pr、send_msg

响应格式优化

工具返回信息应优先考虑上下文相关性,避免低级技术标识符:

❌ 避免:uuid、256px_image_url、mime_type
✓ 推荐:name、image_url、file_type

灵活的响应格式

通过添加 response_format 参数,让智能体控制返回详细程度:

{
  "response_format": {
    "type": "string",
    "enum": ["concise", "detailed"],
    "description": "concise 返回精简信息;detailed 包含完整 ID 和元数据"
  }
}
模式 Token 消耗 适用场景
concise 低(相对) 最终展示、无后续操作
detailed 需要 ID 进行后续工具调用

工具使用示例

JSON Schema 能定义结构有效性,但无法表达使用模式。通过提供示例,展示:

  • 格式约定:日期用 YYYY-MM-DD,ID 用 USR-XXXXX
  • 可选参数相关性:关键任务填写所有字段,简单任务只需核心字段
  • 嵌套结构用法
{
  "name": "create_ticket",
  "input_schema": {...},
  "input_examples": [
    {"title": "紧急:登录页面 500 错误", "priority": "critical", "labels": ["bug"]},
    {"title": "添加暗色模式支持", "labels": ["feature-request"]},
    {"title": "更新文档"}
  ]
}