Appearance
10. Spring AI 中如何实现工具调用(Tool Calling)?
难度 P1 高频 · 岗位 应用 · 频率 ★★★ · 预计阅读 11 min
本题阅读地图
- 💡 简要回答
- 📝 详细解析
- 🎯 面试总结
👔面试官:Spring AI 里怎么实现工具调用?跟 Function Calling 有什么区别?
🙋♂️我:就是给模型配几个工具,让模型自己决定调哪个。
👔面试官:具体怎么定义工具?模型怎么告诉你要调哪个工具?Spring AI 的工具管理和原生 Function Calling 比有什么优势?
🙋♂️我:……具体 API 不太清楚。
Spring AI 的工具调用机制比原生 Function Calling 更工程化。下面把完整实现讲清楚。
💡 简要回答
Spring AI 的工具调用基于 Function Calling 标准,但提供了更友好的封装:
- 用
@Tool注解定义工具(不需要手写 JSON Schema) - 框架自动生成工具描述和参数定义
- 支持工具回调的自动执行和结果回传
- 与 Spring 生态无缝集成(依赖注入、Bean 管理)
📝 详细解析
定义工具:@Tool 注解
java
@Service
public class WeatherTools {
@Tool(description = "查询指定城市的实时天气,包括气温、天气状况、风向")
public WeatherInfo getWeather(
@ToolParam(description = "城市名称,如北京、上海、广州") String city,
@ToolParam(description = "温度单位,celsius 或 fahrenheit", required = false) String unit) {
// 调用天气 API
return weatherApiClient.query(city, unit);
}
}
public record WeatherInfo(
String city,
double temperature,
String condition,
String windDirection
) {}@Tool 和 @ToolParam 注解让框架自动生成 JSON Schema,不需要手写。
注册工具到 ChatClient
java
@Configuration
public class ChatClientConfig {
@Bean
public ChatClient chatClient(ChatModel model, WeatherTools weatherTools) {
return ChatClient.builder(model)
.defaultTools(weatherTools) // 注册工具 Bean
.build();
}
}工具调用的完整流程
java
@Service
public class TravelAssistant {
@Autowired
private ChatClient chatClient;
public String planTrip(String destination) {
return chatClient.prompt()
.user("我打算去%s旅游,帮我查一下天气" .formatted(destination))
.call() // Spring AI 自动处理工具调用循环
.content();
}
}
// 执行流程:
// 1. 用户问「我打算去杭州旅游,帮我查一下天气」
// 2. 模型判断需要调用 getWeather 工具,参数 city="杭州"
// 3. Spring AI 自动执行 WeatherTools.getWeather("杭州")
// 4. 结果回传给模型
// 5. 模型生成最终回答「杭州今天晴,25°C,适合出游」工具调用的内部机制
用户提问
↓
LLM 判断:是否需要工具?
↓ 需要
生成 tool_calls JSON
↓
Spring AI 解析 tool_calls
↓
找到对应 Bean 方法,反射调用
↓
获取返回结果
↓
把结果塞进对话上下文
↓
再次调用 LLM
↓
返回最终答案这个过程叫做 Tool Calling Loop,Spring AI 自动完成,开发者只需要写工具逻辑。
多工具管理
java
@Configuration
public class ToolConfig {
@Bean
public ChatClient chatClient(
ChatModel model,
WeatherTools weatherTools,
SearchTools searchTools,
CalculatorTools calculatorTools) {
return ChatClient.builder(model)
.defaultTools(weatherTools, searchTools, calculatorTools)
.build();
}
}工具数量多时,建议:
- 按业务模块拆分 Tool 类
- 用 Bean 名称做命名空间
- 工具描述要精确,避免模型选错
工具上下文传递
java
// 在多轮对话中保持工具状态
ChatClient chatClient = ChatClient.builder(model)
.defaultTools(weatherTools)
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
.build();
// 第一轮
chatClient.prompt()
.user("杭州天气怎么样?")
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID, "session-001"))
.call().content();
// 第二轮(模型记得上下文)
chatClient.prompt()
.user("那边适合穿什么衣服?") // 模型知道「那边」指杭州
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID, "session-001"))
.call().content();🎯 面试总结
Spring AI 工具调用的核心优势:注解驱动,自动 Schema 生成,Loop 自动处理。
三步使用:
- 定义:
@Tool+@ToolParam注解 - 注册:
ChatClient.defaultTools() - 调用:框架自动处理 Tool Calling Loop
与原生 Function Calling 对比:
- 更少的样板代码:不需要手写 JSON Schema
- 更好的 Spring 集成:依赖注入、Bean 管理
- 更简单的多轮对话:配合 Advisor 自动维护上下文
面试时要能说出 Tool Calling Loop 的概念和 @Tool 注解的价值(省掉手写 Schema)。