大模型工具集声明简介

84 阅读5分钟
# OpenAI-style tool schema (note the `type: function` wrapper).
TOOLS = [{
    "type": "function",
    "function": {
        "name": "bash",
        "description": "Run a shell command.",
        "parameters": {
            "type": "object",
            "properties": {"command": {"type": "string"}},
            "required": ["command"],
        },
    },
}]

这段代码是 告诉大模型"你有什么工具可用" 的声明,遵循 OpenAI Function Calling Schema。模型读完这段就知道:可以调一个叫 bash 的工具,怎么传参,要传什么。

整体结构(OpenAI 标准 Schema)

TOOLS = [                        # ← 工具列表(可以声明多个)
    {
        "type": "function",      # ← 工具类型:固定 "function"
        "function": {            # ← 工具元数据
            "name": ...,         # 工具名(模型靠它识别要调哪个)
            "description": ...,  # 工具描述(模型靠它判断何时调)
            "parameters": ...    # 入参 Schema(JSON Schema 格式)
        }
    }
]

逐字段拆解

TOOLS = [{

外层是数组,因为可以声明多个工具:

TOOLS = [
    {"type": "function", "function": {"name": "bash", ...}},
    {"type": "function", "function": {"name": "read_file", ...}},
    {"type": "function", "function": {"name": "search_web", ...}},
]

你目前只有一个 bash,但仍用数组包着,方便以后扩展。

"type": "function"

工具类型固定为 "function"。这是 OpenAI 设计上的留扩展位 —— 未来可能加 "retrieval""code_interpreter" 等内置工具。目前只有这一个合法值,按规矩写就行。

"function": {...}

工具元信息容器。三个核心字段:

"name": "bash" ⭐ 关键字段

工具的唯一标识,模型返回 tool_calls 时会用它指明调哪个:

"tool_calls": [{
    "id": "call_xxx",
    "function": {"name": "bash", "arguments": "..."}
}]

代码里靠 name 路由到具体执行函数:

if name == "bash":
    output = run_bash(command)
else:
    output = f"Error: unknown tool {name}"

命名规则(OpenAI 要求):

  • 只允许 a-z A-Z 0-9 _ -
  • 长度 ≤ 64
  • 不能有空格、中文、特殊字符
  • 区分大小写(bashBash

"description": "Run a shell command." ⭐ 关键字段

告诉模型这工具是干啥的,模型靠它判断何时该调

这是最重要的"提示"字段。写得好坏直接决定模型用工具的准确度。

本例太简略,模型不知道边界:

"description": "Run a shell command."   # ← 你现在的写法

优秀写法:

"description": (
    "Execute a bash shell command on the local machine and return its stdout/stderr. "
    "Use this for: listing files (ls), reading files (cat), searching (grep), "
    "running scripts. Do NOT use for destructive operations like 'rm -rf' "
    "or commands requiring sudo."
)

模型把这段当 "工具说明书" 读,写多详细都不亏(虽然占点 token)。当前写法够用,但生产级 agent 建议加上:

  • 何时该用
  • 何时不该用
  • 返回什么格式
  • 危险操作的警告

"parameters": {...} ⭐ 关键字段

入参定义,必须是合法的 JSON Schema

"parameters": {
    "type": "object",                                    # ← 顶层永远是 object
    "properties": {                                      # ← 各参数定义
        "command": {"type": "string"}
    },
    "required": ["command"],                             # ← 哪些参数必填
}

逐项拆:

"type": "object"

顶层永远是 object。OpenAI 协议规定参数必须是个对象(即字典),不能是裸字符串/数字/数组。即使只有一个参数,也要包成对象。

"properties": {"command": {"type": "string"}}

定义有哪些字段,每个字段什么类型。这里就一个 command,类型是字符串。

支持的 JSON Schema 类型:

type例子
string"ls -la"
integer42
number3.14
booleantrue/false
array["a", "b"]
object{"k": "v"}

也可以加更多约束:

"command": {
    "type": "string",
    "description": "The shell command to execute, e.g., 'ls -la /tmp'",
    "minLength": 1,
    "maxLength": 1000,
}

强烈建议给每个 property 加 description,模型生成 arguments 时质量会显著提升。你现在没加,是简化版。

"required": ["command"]

列出必填字段。没列在这里的就是可选。不写或写空数组 [] = 全部可选。

完整流程:模型怎么用这段声明

Step 1:声明发给模型

"tools": TOOLS

Step 2:模型读懂后决定要调

模型内部"读"到这段后心想:

"哦,我有个 bash 工具,可以执行 shell 命令。 用户问'当前目录有啥' → 我应该调 bash,传 command='ls'。"

Step 3:模型按 schema 生成 tool_calls

{
  "tool_calls": [{
    "id": "call_2e547...",
    "function": {
      "name": "bash",                           ← 跟你声明的 name 一致
      "arguments": "{\"command\": \"ls -la\"}"  ← 严格遵守 properties
    }
  }]
}

注意 argumentsJSON 字符串(不是对象),所以你代码里要 json.loads(raw_args) 解析。

Step 4:你执行并回传

args = json.loads(call["function"]["arguments"])
command = args["command"]                      # ← "ls -la"
output = run_bash(command)
messages.append({"role": "tool", "tool_call_id": call["id"], "content": output})

多工具示例

如果想加更多工具(比如读文件、网络搜索),就这样写:

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "bash",
            "description": "Run a shell command.",
            "parameters": {
                "type": "object",
                "properties": {"command": {"type": "string"}},
                "required": ["command"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "read_file",
            "description": "Read the contents of a file.",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "Absolute file path"},
                    "max_bytes": {"type": "integer", "description": "Max bytes to read", "default": 4096},
                },
                "required": ["path"],
            },
        },
    },
]

然后在 agent_loop 里加路由:

if name == "bash":
    output = run_bash(args.get("command", ""))
elif name == "read_file":
    output = read_file_safe(args.get("path"), args.get("max_bytes", 4096))
else:
    output = f"Error: unknown tool {name}"

这段写法的小优化建议(非必须)

当前

"description": "Run a shell command.",
"properties": {"command": {"type": "string"}},

升级版(提升模型调用准确度):

"description": (
    "Run a shell command on the local machine and return its output. "
    "Use for inspecting files, running scripts, system queries."
),
"properties": {
    "command": {
        "type": "string",
        "description": "The shell command to execute, e.g., 'ls -la' or 'cat README.md'.",
    }
},

加 description 的意义:模型知道怎么用何时用,幻觉率显著下降。token 多花一点点,收益巨大

一图速记

TOOLS = [
    {                                ┐
      "type": "function",            │ ← OpenAI 工具协议外壳(固定写法)
      "function": {                  ┘
        "name":    "bash",           ← 工具 ID(模型 tool_calls 用它)
        "description": "...",        ← 何时调(模型决策依据)
        "parameters": {              ┐
          "type": "object",          │
          "properties": {...},       │ ← JSON Schema:参数怎么传
          "required": [...]          │
        }                            ┘
      }
    }
]

一句话总结

本工具集是给模型的**"工具说明书"** —— 用 OpenAI Function Calling Schema 声明了一个名为 bash 的工具,告诉模型:"你可以执行 shell 命令,参数叫 command,类型字符串,必填"。模型读完后就能在合适时机生成 tool_calls 调用它。name 是路由 key,description 是决策依据,parameters 是 JSON Schema 入参契约,三者缺一不可。