← Back to 文字

Tool Calling 原理

本文来自《AI 应用开发课程》月份 1 课程文档,已整理为网站文章版本。

学习目标

学完本节后,你应当能够:

  • 理解 Tool Calling 在 AI 应用中的角色。
  • 区分模型职责和程序职责。
  • 理解完整工具调用闭环的每一步。

前置知识

  • 已完成 LLM API 与 Prompt 基础模块

1. Tool Calling 到底解决什么问题

普通聊天模型只能“说”,不能真正“做”。例如:

  • 读取本地文件
  • 查询时间
  • 调用内部服务
  • 执行规则化逻辑

Tool Calling 的价值在于:让模型决定“该用哪个工具、传什么参数”,再由程序真正执行。

2. 一次完整 Tool Calling 的参与者

  • 用户
  • 模型
  • 工具定义
  • 工具执行器
  • 模型二次推理

3. 工具调用闭环

flowchart TD
    A["用户输入任务"] --> B["模型判断是否需要工具"]
    B -->|不需要| C["直接回答"]
    B -->|需要| D["返回 tool name + arguments"]
    D --> E["程序校验并执行工具"]
    E --> F["将工具结果回填为 tool 消息"]
    F --> G["模型生成最终回答"]

4. 模型负责什么,程序负责什么

模型负责

  • 判断是否需要工具
  • 选择工具名
  • 组织工具参数
  • 在收到工具结果后生成最终回答

程序负责

  • 注册有哪些工具
  • 校验工具名与参数是否合法
  • 真正执行工具
  • 捕获工具错误
  • 把结果回填给模型

这里的边界非常关键。模型不直接执行真实程序。

5. 工具定义的核心要素

一个工具至少要说明:

  • 名称
  • 用途描述
  • 参数结构

例如:

{
  "name": "summarize_diff",
  "description": "总结 git diff 的核心变更点",
  "parameters": {
    "type": "object",
    "properties": {
      "diff_text": {"type": "string"}
    },
    "required": ["diff_text"]
  }
}

6. 月份 1 推荐的最小工具集合

围绕“研发助手”主线,可以先从下面 2 到 3 个工具开始:

  • summarize_diff
  • draft_commit_message
  • extract_todo_items

不要一开始就注册十几个工具。工具过多会干扰模型选择,也会抬高调试复杂度。

7. 实操任务

  1. 设计一个工具定义
  2. 用自然语言描述这个工具做什么
  3. 明确它的输入参数
  4. 明确如果工具执行失败,程序要返回什么

8. 自测题

  1. 为什么 Tool Calling 不是“模型自己执行代码”?
  2. 为什么工具数量不应一开始就太多?
  3. 为什么工具参数必须结构化?

9. 作业与验收

作业:

  • 设计 2 个围绕研发助手场景的工具定义

验收标准:

  • 每个工具都有清晰用途
  • 每个工具都有明确参数结构
  • 你能解释为什么它值得注册给模型

10. 常见错误

  • 工具描述太模糊
  • 工具参数随意用一大段文本代替结构化字段
  • 工具定义和真实执行函数不一致

11. 本章与前文关系

前面的 LLM API 模块,本质上都还停留在:

  • 模型接收输入
  • 模型生成输出

这一层。现在要进入月份 1 的下一层能力:让模型和程序能力发生协作。

也就是说,本章在解决一个更贴近真实助手的问题:

模型如果需要“做事”,它应该如何调用程序侧的能力?

12. 本章在研发助手项目中的位置

研发助手项目如果只有聊天能力,就很难真正变成“助手”。真正有价值的能力往往来自工具,例如:

  • 根据 diff 生成 commit message
  • 从需求描述中抽取待办项
  • 解析错误日志并整理步骤

这些能力里,一部分可以直接靠模型完成,一部分更适合走工具化路径。Tool Calling 就是把这两者连接起来的桥。

13. Tool Calling 的正确边界

这是月份 1 必须彻底搞清楚的一件事:

模型不会直接执行你的 Python 代码

模型只能:

  • 看到你注册给它的工具描述
  • 决定是否调用某个工具
  • 生成工具参数

真正执行工具的是程序

程序负责:

  • 维护工具注册表
  • 校验工具名
  • 校验参数
  • 调用真实 Python 函数
  • 记录日志
  • 把结果回填给模型

只要这条边界没有搞清楚,后面 Agent 会学得非常痛苦。

14. 错误示例 vs 正确示例

错误示例:把工具理解成“模型自己会做的魔法”

这种理解会导致你忽视:

  • 工具参数是否合法
  • 工具输出格式是否稳定
  • 工具失败时程序如何处理

正确示例:把工具调用看成“模型决策 + 程序执行”的分工

你应该始终能回答:

  • 模型在这里做了什么
  • 程序在这里做了什么

15. 一个更接近研发助手的工具集合

月份 1 推荐从这两个工具开始,而不是做一个庞大工具箱:

工具 1:extract_todo_items

输入:

  • 一段需求描述

输出:

  • 拆出的待办项列表

工具 2:draft_commit_message

输入:

  • 一段 diff 摘要或变更说明

输出:

  • 一条 commit message 草稿

这两个工具有两个优点:

  • 和研发助手场景高度贴合
  • 同时能覆盖结构化结果和文本结果两种类型

16. 模型返回工具请求时你应当关注什么

当模型决定调用工具时,你最应该看三件事:

  1. 返回的工具名是否存在于注册表中
  2. 参数结构是否符合预期
  3. 这次工具调用是否真的必要

也就是说,Tool Calling 不只是“会触发工具”,更是“会判断这个触发是否健康”。

17. 从最小原理到后续实现的递进

你可以把 Tool Calling 理解成四步:

  1. 向模型声明有哪些工具
  2. 模型选择工具并给出参数
  3. 程序执行工具
  4. 工具结果回填给模型,模型再生成最终回答

后面 02-工具循环实现.md 会把这四步落实到具体代码中。

18. 调试与排错:本章最常见误区

误区一:工具越多越好

月份 1 正好相反。工具一多,调试难度和选择歧义都上升。

误区二:工具描述越抽象越高级

实际上,工具描述越具体,模型越容易正确使用。

误区三:参数能靠自然语言凑合就行

如果参数结构不清晰,后面程序执行时一定会混乱。

19. 本章完成后你应该具备的能力

完成本章后,你应当做到:

  1. 能解释 Tool Calling 解决的问题。
  2. 能说清模型职责和程序职责。
  3. 能设计出 1 到 2 个围绕研发助手的最小工具。
  4. 能为后面实现工具循环建立清晰心智模型。

20. 如果你卡在这里,先回看哪几章

21. 从本章过渡到下一章的桥接说明

接下来进入 02-工具循环实现.md

这一章解决的是“原理和边界”,下一章将把它真正落成代码:定义工具、注册工具、执行工具、回填结果,并区分无工具、成功调用和失败调用等不同路径。

Fin