什么是工具调用 Tool Calling?如何利用 Spring AI 实现工具调用?
- 标签:后端、编程导航
🏛 业务架构师
Tool Calling 的机制:把工具的名称、描述、参数 schema 告诉模型;模型在需要时"点名"调用某个工具并给出参数;框架执行真正的 Java 方法,把结果回填给模型继续生成。模型不执行任何东西——它只是决策"该用什么工具、传什么参数",执行权永远在程序手里。
Spring AI 实现:方法加 @Tool 注解(描述 + 参数说明写清楚),注册到 ChatClient;框架自动把工具定义注入请求、解析模型的工具调用请求、反射执行、结果回填——业务开发者只写 Java 方法本身。
业务架构视角,这是 AI 从"顾问"变"员工"的关键:
- 没有工具:模型只能"说"——"您可以上官网查询订单";
- 有工具:模型能"做"——真正调用订单系统查到结果,组织语言告诉你,还能顺手判断要不要发起退款流程。
我的三条落地纪律:
- 工具描述是产品文案:模型靠描述选工具——描述含糊,模型就选错。写工具描述的认真程度要等同于写用户文档("查询订单物流状态,输入订单号"优于"查订单");
- 工具要小而正交:一个工具做一件事,参数 schema 明确(枚举约束)——大而全的工具模型用不好;
- 权限与审计在工具层:工具执行前校验用户权限(查别人订单要拦)、执行全记录审计——模型会犯错,但工具层是确定性代码,安全边界必须建在这里,而不是指望模型自觉。
一句话:Tool Calling = 模型的决策力 × 代码的执行力,两者的边界设计就是安全性的设计。
🏗 系统架构师
Tool Calling = 让 LLM 能调用外部程序:把工具的名称、描述、参数 Schema 注册给模型,模型在对话中决策"需要调什么工具、传什么参数",程序执行后把结果回传,模型继续推理——这是从"聊天模型"到"能干事的 Agent"的分水岭。
Spring AI 实现三步:
- 定义工具(注解声明,自动生成 schema):
java
class SearchTools {
@Tool(description = "搜索互联网获取实时信息")
@ToolParams(...)
public String webSearch(@ToolParam(description = "搜索关键词") String query) {
return searchService.search(query);
}
}注册给 ChatClient:
.tools(new SearchTools())或.toolCallbacks(toolCallbacks)——工具描述与参数 schema 自动注入系统提示。执行循环(框架托管):模型返回 tool_call(函数名+参数 JSON)→ Spring AI 反射调用方法 → 结果作为 ToolResponseMessage 回传 → 模型继续(可能再调用或给出最终答案)——多轮工具调用循环框架自动完成。
我的工程要点:
- description 是第一提示词:写得越精确(何时用/何时不用/参数格式),模型选择越准;
- 参数校验兜底(模型可能传非法值),工具要幂等(可能被重复调用);
- 超时与失败处理:工具挂了返回结构化错误信息让模型自行决策(换工具或告知用户),不要直接抛异常断链;
- 敏感工具(写操作)加权限确认层;
- MCP 是工具生态的进一步标准化(跨进程复用工具)。
💻 全栈开发专家
Tool Calling = 模型不直接回答,而是输出一个"调用请求"(工具名 + JSON 参数),由框架执行真实的本地方法,把结果回传给模型继续生成。模型是"决策者",程序是"执行者"。
Spring AI 实现(1.0 的 @Tool 注解):
java
public class WeatherTool {
@Tool(description = "查询指定城市的实时天气,city 为城市名")
public String getWeather(@ToolParam(description = "城市名") String city) {
return weatherApi.fetch(city); // 模型决定何时调、传什么参数
}
}
// 注册后正常对话,模型自主调用
String answer = chatClient.prompt()
.user("北京今天适合跑步吗?")
.tools(new WeatherTool())
.call().content();底层流程:模型返回 tool_calls(name= getWeather, arguments={"city":"北京"})→ 框架反射执行方法 → 结果作为 tool message 追加到对话 → 再次调模型 → 得到最终自然语言回答。一次用户提问背后可能有多轮模型调用。
工程要点(踩坑):
- description 是给模型看的——写不清楚("查天气" vs "查实时天气,支持国内城市")模型就乱用或不用,工具选择准确率主要取决于描述质量;
- 流式调用注意:流式模式里工具调用会中断流,要处理"先收到 tool_call 再续流"的状态机;
- 参数校验兜底:模型生成的参数可能非法(空 city),工具内部校验返回错误信息让模型自纠;
- 超时控制:工具是真实 IO,包一层超时防止拖死整个会话。