Tool Calling 概念

截屏20260607 23.23.49.png

Tool Calling 的核心是让模型在需要外部能力时,先提出工具调用请求,由后端执行工具,再把工具结果交回模型生成最终回答。

Tool Calling 是什么

Tool Calling,中文一般翻译为“工具调用”。

Function Calling,中文一般翻译为“函数调用”。

在大模型应用里,这两个词经常表示同一类能力。

它不是让模型直接执行代码。

模型做的是:

判断是否需要工具
选择工具名称
生成工具参数
等待工具结果
基于工具结果继续回答

真正执行工具的是后端应用。

结论:

模型只负责提出“要调用什么工具、参数是什么”,工具执行必须由后端完成。

为什么需要 Tool Calling

大模型本身不适合直接回答这些问题:

当前订单状态是什么
库存还剩多少
用户余额是多少
今天的实时天气是什么
数据库里有没有这条记录
是否需要创建工单

原因是:

模型没有实时业务数据
模型不能直接访问数据库
模型不能直接调用内部系统
模型可能会编造结果

Tool Calling 的作用是把模型和业务系统连接起来。

比如:

用户:帮我查一下订单 A10001 到哪了
模型:需要调用 query_order 工具
后端:执行 query_order(orderId=A10001)
工具结果:订单已发货,物流单号 xxx
模型:根据工具结果回复用户

Tool Calling 基本流程

完整流程:

1. 后端把工具定义发给模型
2. 用户提出问题
3. 模型判断是否需要调用工具
4. 模型返回工具名和参数
5. 后端执行对应工具
6. 后端把工具结果回填给模型
7. 模型生成最终回答

注意:

工具定义不是工具代码
模型不会直接访问数据库
工具执行权在后端
工具结果要回填给模型

工具 Schema 是什么

Schema,中文一般翻译为“模式”或“结构定义”。

工具 Schema 用来告诉模型:

工具叫什么
工具能做什么
需要哪些参数
参数是什么类型
哪些参数必填

示例:

{
  "name": "query_order",
  "description": "根据订单号查询订单状态",
  "parameters": {
    "type": "object",
    "properties": {
      "orderId": {
        "type": "string",
        "description": "订单号"
      }
    },
    "required": ["orderId"]
  }
}

这不是业务接口返回值。

它是给模型看的工具说明。

工具 Schema 写得越清楚,模型越容易选对工具和参数。

工具选择

模型会根据用户问题和工具描述来判断是否调用工具。

比如可用工具:

query_order:查询订单状态
query_stock:查询商品库存
create_ticket:创建售后工单

用户问题:

我的订单 A10001 发货了吗?

模型应该选择:

query_order

用户问题:

这个商品还有库存吗?

模型应该选择:

query_stock

工具选择依赖:

工具名称
工具描述
参数描述
用户问题
system prompt

工具结果回填

工具执行完以后,后端要把结果发回模型。

比如工具结果:

{
  "orderId": "A10001",
  "status": "SHIPPED",
  "trackingNo": "SF123456"
}

模型再生成用户能看懂的回答:

订单 A10001 已发货,物流单号是 SF123456。

不要直接把原始内部字段全部丢给用户。

工具结果回填的价值是:

模型能把结构化结果转成自然语言
模型能结合上下文回答
模型能解释下一步操作

Spring AI 里的 Tool Calling

Spring AI 支持把 Java 方法定义成工具。

常见方式是使用 @Tool 注解。

Annotation,中文一般翻译为“注解”。

示例:

import org.springframework.ai.tool.annotation.Tool;

public class OrderTools {

    @Tool(description = "根据订单号查询订单状态")
    public String queryOrder(String orderId) {
        return "订单 " + orderId + " 已发货";
    }
}

调用时把工具传给 ChatClient:

String answer = chatClient.prompt()
        .user("帮我查一下订单 A10001")
        .tools(new OrderTools())
        .call()
        .content();

这时模型可以根据用户问题决定是否调用 queryOrder

Tool Calling 和 RAG 的区别

RAG,全称是 Retrieval-Augmented Generation,中文一般翻译为“检索增强生成”。

两者都能增强模型能力,但用途不同。

RAG:从知识库检索资料,再让模型回答
Tool Calling:调用业务工具或接口,再让模型回答

示例:

问产品说明书内容:适合 RAG
问订单状态:适合 Tool Calling
问是否创建售后工单:适合 Tool Calling
问制度文件里的报销规则:适合 RAG

后面 Agent 项目通常会同时使用:

RAG 查资料
Tool Calling 查订单
Tool Calling 创建工单
模型负责判断流程

安全边界

Tool Calling 必须有安全边界。

原因:

工具可能访问真实业务数据
工具可能修改系统状态
工具可能产生费用
工具可能触发外部动作

后端需要控制:

哪些工具能暴露给模型
工具参数是否校验
用户是否有权限
工具是否需要人工确认
工具调用是否记录审计日志
失败是否能回滚

模型不能直接拥有无限工具权限。

尤其是这些操作:

删除数据
付款退款
发送通知
创建工单
修改订单

需要额外确认或权限校验。

常见问题

模型会直接执行工具吗

不会。

模型只返回工具调用请求。

执行工具的是后端应用。

工具 Schema 是不是越多越好

不是。

工具太多会增加模型选择难度。

学习阶段先放少量明确工具:

订单查询
库存查询
工单创建

工具描述怎么写

工具描述要清楚说明用途和边界。

比如:

根据订单号查询订单状态,只用于订单状态查询,不用于退款或售后处理。

比下面这种更好:

订单工具

工具参数要不要校验

必须校验。

模型生成的参数不能直接信任。

需要检查:

参数是否为空
格式是否正确
用户是否有权限查询
是否超过调用频率

练习清单

完成几件事情:

知道 Tool Calling 是工具调用
知道 Function Calling 是函数调用
知道模型只提出调用请求,不直接执行工具
知道工具 Schema 包含名称、描述、参数
知道工具执行结果要回填给模型
能区分 RAG 和 Tool Calling
知道工具调用要做权限、参数和日志控制

建议准备三个工具:

query_order:查询订单状态
query_stock:查询库存
create_ticket:创建工单

小结

Day08 的结论:

Tool Calling 是模型和业务系统之间的桥,模型负责判断和生成参数,后端负责执行和安全控制。

最小流程:

工具定义
  -> 模型选择工具
  -> 后端执行工具
  -> 工具结果回填
  -> 模型生成最终回答

Day09 会把这个概念落到 Java 代码里。

代码实现

截屏20260608 00.15.30.png
这个是实现tool

截屏20260608 00.18.36.png
请求大模型的时候tools(businessTools)会把相应的tool给大模型,大模型会判断

执行顺序

  1. Spring AI 扫描 businessTools 里的 @Tool 方法
  2. 生成工具定义 schema
  3. 把用户问题 + 工具定义发给大模型
  4. 大模型返回:我要调用 query_weather,参数 city=杭州
  5. Spring AI 根据工具名找到对应 Java 方法
  6. 反射调用 businessTools.queryWeather("杭州")
  7. 拿到 Java 方法返回值 WeatherInfo
  8. 把工具结果再发回模型
  9. 模型生成最终自然语言回答
  10. content() 取出最终回答文本
sequenceDiagram participant User as 用户/页面 participant Controller as Day08Controller participant Service as Day08Service participant SpringAI as Spring AI participant Model as 千问模型 participant Tools as Day08BusinessTools User->>Controller: POST /api/08/tool-calling/ai-tools Controller->>Service: aiToolChat(message) Service->>SpringAI: user(message).tools(businessTools).call() SpringAI->>SpringAI: 扫描 @Tool 方法,生成工具说明 SpringAI->>Model: 用户问题 + 可用工具列表 Model-->>SpringAI: 决定是否调用工具,返回 tool_call SpringAI->>Tools: 调用对应 Java 方法 Tools-->>SpringAI: 返回工具结果 SpringAI->>Model: 把工具结果回填给模型 Model-->>SpringAI: 生成最终回答 SpringAI-->>Service: answer Service-->>Controller: Day08ToolResponse Controller-->>User: 页面展示 answer/toolCalls/steps

截屏20260608 00.26.39.png


{
    "messages": [
        {
            "content": "你是一个严谨的 Tool Calling 学习助手。\n当用户询问订单、库存、天气、油价或售后工单时,应该优先基于工具结果回答。\n工具结果如果标明是本地 mock 数据,回答中必须说明它不是实时真实数据。\n不要编造没有工具结果支持的业务数据。\n",
            "role": "system"
        },
        {
            "content": "帮我查一下杭州今天的天气",
            "role": "user"
        }
    ],
    "model": "qwen-plus",
    "max_tokens": 512,
    "temperature": 0.3,
    "tools": [
        {
            "function": {
                "name": "query_weather",
                "description": "根据城市查询本地 mock 天气。只用于 Tool Calling 学习演示,不是真实实时天气。",
                "parameters": {
                    "$schema": "https://json-schema.org/draft/2020-12/schema",
                    "type": "object",
                    "properties": {
                        "city": {
                            "type": "string",
                            "description": "城市名,例如 北京、上海、杭州"
                        }
                    },
                    "required": [
                        "city"
                    ],
                    "additionalProperties": false,
                    "strict": true
                }
            },
            "type": "function"
        },
        {
            "function": {
                "name": "query_fuel_price",
                "description": "根据地区查询本地 mock 今日油价。只用于 Tool Calling 学习演示,不是真实实时油价。",
                "parameters": {
                    "$schema": "https://json-schema.org/draft/2020-12/schema",
                    "type": "object",
                    "properties": {
                        "region": {
                            "type": "string",
                            "description": "地区名,例如 北京、上海、杭州"
                        }
                    },
                    "required": [
                        "region"
                    ],
                    "additionalProperties": false,
                    "strict": true
                }
            },
            "type": "function"
        },
        {
            "function": {
                "name": "create_ticket",
                "description": "创建本地 mock 售后工单。用于演示需要后端执行的写操作,不会写入真实系统。",
                "parameters": {
                    "$schema": "https://json-schema.org/draft/2020-12/schema",
                    "type": "object",
                    "properties": {
                        "orderId": {
                            "type": "string",
                            "description": "订单号,例如 A10001"
                        },
                        "issue": {
                            "type": "string",
                            "description": "用户遇到的问题"
                        }
                    },
                    "required": [
                        "orderId",
                        "issue"
                    ],
                    "additionalProperties": false,
                    "strict": true
                }
            },
            "type": "function"
        },
        {
            "function": {
                "name": "query_order",
                "description": "根据订单号查询本地 mock 订单状态。只用于订单发货、物流和当前处理状态查询,不用于退款或删除订单。",
                "parameters": {
                    "$schema": "https://json-schema.org/draft/2020-12/schema",
                    "type": "object",
                    "properties": {
                        "orderId": {
                            "type": "string",
                            "description": "订单号,例如 A10001"
                        }
                    },
                    "required": [
                        "orderId"
                    ],
                    "additionalProperties": false,
                    "strict": true
                }
            },
            "type": "function"
        },
        {
            "function": {
                "name": "query_stock",
                "description": "根据商品 SKU 查询本地 mock 可售库存。只用于库存数量查询。",
                "parameters": {
                    "$schema": "https://json-schema.org/draft/2020-12/schema",
                    "type": "object",
                    "properties": {
                        "skuId": {
                            "type": "string",
                            "description": "商品 SKU,例如 SKU-001"
                        }
                    },
                    "required": [
                        "skuId"
                    ],
                    "additionalProperties": false,
                    "strict": true
                }
            },
            "type": "function"
        }
    ]
}

参考资料


这个家伙很懒,啥也没有留下😋