006-Spring AI Alibaba Tool Calling 功能完整案例
本案例展示了 Spring AI Alibaba 中 Tool Calling 功能的四种不同实现方式,通过四个独立的示例来演示如何将外部工具集成到 AI 应用中,增强 AI 的能力。

本案例展示了 Spring AI Alibaba 中 Tool Calling 功能的四种不同实现方式,通过四个独立的示例来演示如何将外部工具集成到 AI 应用中,增强 AI 的能力。
1. 案例目标
我们将创建一个包含四种不同 Tool Calling 实现方式的 Web 应用:
- TimeController:演示如何将方法作为工具使用 (Methods as Tools)
- AddressController:演示如何使用 MethodToolCallback 将方法作为工具
- BaiduTranslateController:演示如何通过函数名将函数作为工具使用 (Function as Tools - Function Name)
- WeatherController:演示如何使用 FunctionCallBack 将函数作为工具
2. 技术栈与核心依赖
- Spring Boot 3.x
- Spring AI Alibaba (用于对接阿里云 DashScope 通义大模型)
- Maven (项目构建工具)
- 百度翻译 API (提供翻译功能)
- 百度地图 API (提供地址信息查询功能)
- Weather API (提供天气信息查询功能)
- 时间服务 (提供时间查询功能)
在 pom.xml 中,你需要引入以下核心依赖:
<dependencies>
<!-- Spring Web 用于构建 RESTful API -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Alibaba 核心启动器,集成 DashScope -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- 百度翻译工具 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-tool-calling-baidutranslate</artifactId>
</dependency>
<!-- 天气查询工具 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-tool-calling-weather</artifactId>
</dependency>
<!-- 百度地图工具 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-tool-calling-baidumap</artifactId>
</dependency>
<!-- 时间工具 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-tool-calling-time</artifactId>
</dependency>
<!-- GitHub 工具包 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-tool-calling-githubtoolkit</artifactId>
</dependency>
</dependencies>
3. 项目配置
在 src/main/resources/application.yml 文件中,配置你的 API Key。
spring:
ai:
alibaba:
toolcalling:
baidu:
translate:
enabled: true
app-id: ${BAIDU_TRANSLATE_APP_ID}
secret-key: ${BAIDU_TRANSLATE_SECRET_KEY}
map:
enabled: true
apiKey: ${BAIDU_MAP_API_KEY}
time:
enabled: true
weather:
enabled: true
api-key: ${WEATHER_API_KEY}
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY}
重要提示:请将上述环境变量设置为你从相应服务提供商获取的有效 API Key。你也可以直接将其写在配置文件中,但这不推荐用于生产环境。
4. 编写 Java 代码
4.1 主应用程序类
package com.alibaba.cloud.ai.toolcall;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ToolCallingApplication {
public static void main(String[] args) {
SpringApplication.run(ToolCallingApplication.class, args);
}
}
4.2 TimeController - Methods as Tools
package com.alibaba.cloud.ai.toolcall.controller;
import com.alibaba.cloud.ai.toolcall.component.TimeTools;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/time")
public class TimeController {
private final ChatClient dashScopeChatClient;
private final TimeTools timeTools;
public TimeController(ChatClient chatClient, TimeTools timeTools) {
this.dashScopeChatClient = chatClient;
this.timeTools = timeTools;
}
/**
* 不使用工具的普通聊天
*/
@GetMapping("/chat")
public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
return dashScopeChatClient.prompt(query).call().content();
}
/**
* 使用方法作为工具
*/
@GetMapping("/chat-tool-method")
public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "请告诉我现在北京时间几点了") String query) {
return dashScopeChatClient.prompt(query).tools(timeTools).call().content();
}
}
4.3 TimeTools 组件
package com.alibaba.cloud.ai.toolcall.component;
import com.alibaba.cloud.ai.toolcalling.time.GetTimeByZoneIdService;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
public class TimeTools {
private final GetTimeByZoneIdService timeService;
public TimeTools(GetTimeByZoneIdService timeService) {
this.timeService = timeService;
}
@Tool(description = "Get the time of a specified city.")
public String getCityTime(@ToolParam(description = "Time zone id, such as Asia/Shanghai") String timeZoneId) {
return timeService.apply(new GetTimeByZoneIdService.Request(timeZoneId)).description();
}
}
4.4 AddressController - Methods as Tools with MethodToolCallback
package com.alibaba.cloud.ai.toolcall.controller;
import com.alibaba.cloud.ai.toolcall.component.AddressInformationTools;
import com.alibaba.cloud.ai.toolcalling.baidumap.BaiduMapSearchInfoService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.method.MethodToolCallback;
import org.springframework.ai.util.json.schema.JsonSchemaGenerator;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
@RestController
@RequestMapping("/address")
public class AddressController {
private final ChatClient dashScopeChatClient;
private final AddressInformationTools addressTools;
public AddressController(ChatClient chatClient, AddressInformationTools addressTools) {
this.dashScopeChatClient = chatClient;
this.addressTools = addressTools;
}
/**
* 不使用工具的普通聊天
*/
@GetMapping("/chat")
public String chat(@RequestParam(value = "address", defaultValue = "北京") String address) throws JsonProcessingException {
BaiduMapSearchInfoService.Request query = new BaiduMapSearchInfoService.Request(address);
return dashScopeChatClient.prompt(new ObjectMapper().writeValueAsString(query))
.call()
.content();
}
/**
* 使用 MethodToolCallback 将方法作为工具
*/
@GetMapping("/chat-method-tool-callback")
public String chatWithBaiduMap(@RequestParam(value = "address", defaultValue = "北京") String address) throws JsonProcessingException {
Method method = ReflectionUtils.findMethod(AddressInformationTools.class, "getAddressInformation", String.class);
if (method == null) {
throw new RuntimeException("Method not found");
}
return dashScopeChatClient.prompt(address)
.toolCallbacks(MethodToolCallback.builder()
.toolDefinition(ToolDefinition.builder()
.description("Search for places using Baidu Maps API "
+ "or Get detail information of a address and facility query with baidu map or "
+ "Get address information of a place with baidu map or "
+ "Get detailed information about a specific place with baidu map")
.name("getAddressInformation")
.inputSchema(JsonSchemaGenerator.generateForMethodInput(method))
.build())
.toolMethod(method)
.toolObject(addressTools)
.build())
.call()
.content();
}
}
4.5 AddressInformationTools 组件
package com.alibaba.cloud.ai.toolcall.component;
import com.alibaba.cloud.ai.toolcalling.baidumap.BaiduMapSearchInfoService;
public class AddressInformationTools {
private final BaiduMapSearchInfoService service;
public AddressInformationTools(BaiduMapSearchInfoService service) {
this.service = service;
}
public String getAddressInformation(String address) {
return service.apply(new BaiduMapSearchInfoService.Request(address)).message();
}
}
4.6 BaiduTranslateController - Function as Tools with Function Name
package com.alibaba.cloud.ai.toolcall.controller;
import com.alibaba.cloud.ai.toolcalling.baidutranslate.BaiduTranslateService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/translate")
public class BaiduTranslateController {
private final ChatClient dashScopeChatClient;
public BaiduTranslateController(ChatClient chatClient, BaiduTranslateService baiduTranslateService) {
this.dashScopeChatClient = chatClient;
}
/**
* 不使用工具的普通聊天
*/
@GetMapping("/chat")
public String simpleChat(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:你好,世界。") String query) {
return dashScopeChatClient.prompt(query).call().content();
}
/**
* 使用函数名将函数作为工具
*/
@GetMapping("/chat-tool-function-callback")
public String chatTranslateFunction(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:你好,世界。") String query) {
return dashScopeChatClient.prompt(query)
.toolNames("baiduTranslate")
.call()
.content();
}
}
4.7 WeatherController - Function as Tools with FunctionCallBack
package com.alibaba.cloud.ai.toolcall.controller;
import com.alibaba.cloud.ai.toolcalling.weather.WeatherService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/weather")
public class WeatherController {
private final ChatClient dashScopeChatClient;
private final WeatherService weatherService;
public WeatherController(ChatClient chatClient, WeatherService weatherService) {
this.dashScopeChatClient = chatClient;
this.weatherService = weatherService;
}
/**
* 不使用工具的普通聊天
*/
@GetMapping("/chat")
public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我北京1天以后的天气") String query) {
return dashScopeChatClient.prompt(query).call().content();
}
/**
* 使用 FunctionCallBack 将函数作为工具
*/
@GetMapping("/chat-tool-function-name")
public String chatWithWeatherFunction(@RequestParam(value = "query", defaultValue = "请告诉我北京1天以后的天气") String query) {
return dashScopeChatClient.prompt(query).toolCallbacks(
FunctionToolCallback.builder("getWeather", weatherService)
.description("Use api.weather to get weather information.")
.inputType(WeatherService.Request.class)
.build()
).call().content();
}
}
5. 运行与测试
- 启动应用:运行你的 Spring Boot 主程序。
- 使用浏览器或 API 工具(如 Postman, curl)进行测试。
测试 1:时间工具 - 不使用工具
访问以下 URL,询问当前时间,但不使用工具。
GET http://127.0.0.1:8080/time/chat
预期响应:
AI 会基于其内置知识回答,可能无法提供准确的当前时间。
测试 2:时间工具 - 使用方法作为工具
访问以下 URL,询问当前时间,并使用方法作为工具。
GET http://127.0.0.1:8080/time/chat-tool-method
预期响应:
AI 会调用 TimeTools 中的 getCityTime 方法获取准确的当前时间并返回。
测试 3:地址工具 - 不使用工具
访问以下 URL,查询北京的信息,但不使用工具。
GET http://127.0.0.1:8080/address/chat?address=北京
预期响应:
AI 会基于其内置知识回答,可能无法提供详细的地址信息。
测试 4:地址工具 - 使用 MethodToolCallback
访问以下 URL,查询北京的信息,并使用 MethodToolCallback。
GET http://127.0.0.1:8080/address/chat-method-tool-callback?address=北京
预期响应:
AI 会调用 AddressInformationTools 中的 getAddressInformation 方法,通过百度地图 API 获取北京的详细信息并返回。
测试 5:翻译工具 - 不使用工具
访问以下 URL,请求翻译,但不使用工具。
GET http://127.0.0.1:8080/translate/chat?query=帮我把以下内容翻译成英文:你好,世界。
预期响应:
AI 会基于其语言能力尝试翻译,但可能不够准确。
测试 6:翻译工具 - 使用函数名
访问以下 URL,请求翻译,并使用函数名作为工具。
GET http://127.0.0.1:8080/translate/chat-tool-function-callback?query=帮我把以下内容翻译成英文:你好,世界。
预期响应:
AI 会调用百度翻译 API 进行准确的翻译,并返回结果。
测试 7:天气工具 - 不使用工具
访问以下 URL,查询天气,但不使用工具。
GET http://127.0.0.1:8080/weather/chat?query=请告诉我北京1天以后的天气
预期响应:
AI 会基于其内置知识回答,可能无法提供准确的天气预报。
测试 8:天气工具 - 使用 FunctionCallBack
访问以下 URL,查询天气,并使用 FunctionCallBack。
GET http://127.0.0.1:8080/weather/chat-tool-function-name?query=请告诉我北京1天以后的天气
预期响应:
AI 会调用天气 API 获取准确的天气预报信息并返回。
6. 实现思路与扩展建议
实现思路
本案例的核心思想是"工具集成"。通过将外部服务(如时间服务、地图服务、翻译服务、天气服务)作为工具集成到 AI 应用中,扩展 AI 的能力边界。这使得:
- 功能增强:AI 可以访问实时数据和服务,提供更准确、更及时的回答。
- 灵活性高:可以根据需要选择不同的工具集成方式,适应不同的使用场景。
- 可扩展性强:可以轻松添加新的工具,不断扩展 AI 的能力。
四种 Tool Calling 方式对比
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Methods as Tools | 简单方法调用 | 实现简单,代码直观 | 灵活性较低 |
| MethodToolCallback | 需要自定义工具定义 | 可以自定义工具描述和输入模式 | 实现稍复杂 |
| Function as Tools - Function Name | 已注册的函数 | 简单易用,只需函数名 | 需要预先注册函数 |
| FunctionCallBack | 需要自定义函数回调 | 灵活性高,可自定义描述和输入类型 | 实现最复杂 |
扩展建议
- 工具注册中心:可以设计一个工具注册中心,统一管理和发现可用的工具。
- 工具权限控制:为不同用户或角色分配不同的工具访问权限,增强安全性。
- 工具调用链:支持多个工具的链式调用,实现更复杂的业务逻辑。
- 工具调用监控:添加工具调用的监控和日志记录,便于问题排查和性能优化。
- 工具版本管理:支持工具的版本管理,便于工具的升级和回滚。
- 自定义工具开发:根据业务需求开发自定义工具,扩展 AI 的专业领域能力。
7. 相关资源
- 更多可用工具可以参考 工具文档
- MCP 风格的工具请参考 spring-ai-alibaba-mcp-example
- Spring AI 工具详细信息请参考 spring-ai-tools
- 百度翻译 API 访问文档:https://api.fanyi.baidu.com/product/113
- 百度地图 API 文档:https://lbs.baidu.com/faq/api
- 天气预报 API 访问文档:https://www.weatherapi.com/docs/
更多推荐

所有评论(0)