摘要:在AI Agent开发中,"工具调用"(Tool Calling,也叫Function Calling)是一项核心能力。很多Java开发者已经会用Spring AI Alibaba搭建带记忆的AI聊天应用,但这类应用通常只能回答预设范围内的问题------问"今天北京天气怎么样",它多半会说"我无法获取实时信息";问"帮我查一下订单",它只能说"请提供订单号"。
AI真正的价值不只是回答问题,而是执行动作。比如用户说"退订我最近一笔订单",AI自己判断要调用退订API,而不是让用户自己去后台操作。今天就来聊聊Java后端如何实现这种能力。
一、为什么需要工具调用
大模型本质上是一个"文本生成器",它看过海量数据,可以聊起很多话题,但能力边界很明显:没有实时数据,无法获取当前天气、实时股价;没有执行能力,不能发送邮件、创建订单;也不具备精确计算能力,复杂数学题容易出错。
工具调用就是解决这些局限的方案。简单说,开发者先把一些Java方法(比如查天气、查订单)注册为"工具",并把每个工具的作用和参数告诉模型。当用户提问需要用到某个工具时,模型会返回一个调用请求,后端执行对应方法,再把结果交给模型,让它组织成自然语言回答。
整个过程模型并不真正执行任何操作,它只负责"决策"------判断该不该用工具、用哪个工具、用什么参数。真正的执行由后端的Java代码完成。
二、工具调用的完整流程
理解工具调用的最好方式,是看一次完整的交互。
假如用户问"帮我查一下订单10086的物流状态",系统里有一个queryLogistics工具可以查物流。整个过程分四步:
- 用户提问 :用户说"查一下订单10086物流"。后端把问题连同工具清单(
queryLogistics工具的用途和参数要求)一起发给大模型。 - 模型决策 :大模型理解用户意图,返回一个调用请求------调用
queryLogistics,参数orderId=10086。 - 后端执行:后端收到请求,执行Java方法查物流,拿到"已发货,预计明天送达"这类结果。
- 模型生成回答:后端把结果返回给模型,模型整合信息,说"订单10086已发货,预计明天送达"。
如果模型判断不需要调用工具(比如问的是"什么是物流"),它会直接返回自然语言回答。
两步调用是工具调用的核心模式:第一次调用让模型决定调什么工具,第二次调用把工具执行结果带回来做最终回答。
三、用Spring AI Alibaba实现工具调用
下面通过Spring AI Alibaba + 通义千问,构建一个能查天气和查订单的智能助手。
3.1 添加依赖
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.10</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.1.2.0</version>
</dependency>
</dependencies>
3.2 配置API
yaml
# application.yml
spring:
ai:
dashscope:
api-key: sk-xxx-your-real-key
3.3 第一步:定义工具
用@Tool注解把Java方法标记为可被AI调用的工具。description参数很重要,模型依据它判断什么时候该用这个工具。
java
@Service
public class AssistantTools {
@Tool(description = "查询指定城市的实时天气信息,返回温度、天气状况和湿度")
public String getWeather(String city) {
// 实际生产环境调用真实天气API
return switch (city) {
case "北京" -> "{"city":"北京", "temperature":"25°C", "weather":"晴", "humidity":"40%"}";
case "上海" -> "{"city":"上海", "temperature":"22°C", "weather":"多云", "humidity":"60%"}";
case "广州" -> "{"city":"广州", "temperature":"28°C", "weather":"小雨", "humidity":"80%"}";
default -> "暂不支持该城市的天气查询";
};
}
@Tool(description = "根据订单ID查询订单状态,返回订单详情和物流信息")
public String getOrder(String orderId) {
// 实际生产环境调用订单服务
return "{"orderId":"" + orderId + "", "status":"已发货", "tracking":"预计明天送达"}";
}
}
两个工具分别返回JSON格式的数据,方便模型理解。工具方法返回值会被序列化后发给模型,格式越规整,模型提取信息的准确率越高。
3.4 第二步:注册工具并创建ChatClient
java
@Configuration
public class AiConfig {
@Bean
public ChatClient chatClient(DashScopeChatModel chatModel, AssistantTools assistantTools) {
return ChatClient.builder(chatModel)
.defaultSystem("你是一个智能助手,可以帮用户查询天气和订单信息。")
.defaultTools(assistantTools) // 注册工具,AI自动决定调用时机
.build();
}
}
3.5 第三步:实现聊天接口
java
@RestController
@RequestMapping("/api/chat")
public class ChatController {
@Autowired
private ChatClient chatClient;
@PostMapping("/send")
public String chat(@RequestBody ChatRequest request) {
return chatClient.prompt()
.user(request.getMessage())
.call()
.content();
}
}
只需三步:定义工具、注册工具、调用------框架会自动处理工具发现的请求、解析模型返回的调用指令、执行对应方法、回填结果。
3.6 效果测试
bash
# 查询天气
curl -X POST http://localhost:8080/api/chat/send \
-H "Content-Type: application/json" \
-d '{"message": "北京今天天气怎么样"}'
# 返回: 北京今天天气晴,气温25°C,湿度40%,适合外出活动。
# 查询订单
curl -X POST http://localhost:8080/api/chat/send \
-H "Content-Type: application/json" \
-d '{"message": "帮我查一下订单10086的物流"}'
# 返回: 订单10086已发货,预计明天送达。
用户用自然语言提问,AI自动识别意图并调用相应工具------体验就像人在替你操作。
四、多工具协同:一个请求调多个工具
较复杂的场景可能需要AI连续调用多个工具。比如"帮我查北京天气,顺便查一下订单20086",AI判断要同时调用getWeather和getOrder。两个工具并行执行,框架收集结果后一并返回给模型,整合成完整回答。
注册多工具的方式与单个工具完全相同------Spring AI Alibaba的defaultTools()方法支持传入多个工具实例。框架会自动管理调用链,支持工具间的并行执行和结果聚合。
五、工程落地的注意事项
分享几个在真实项目中踩过的坑:
高危操作须加权限 。@Tool注解的工具方法建议增加身份校验或二次确认,防止AI在上下文混淆时误触发。比如"删除数据"这类工具,可以增加"请确认"的交互环节。
返回值用JSON格式 。工具返回的数据最好以结构化JSON形式呈现,而非纯文本。模型更容易从JSON中提取字段,回答质量明显更高。
Token消耗翻倍要留意 。每次调用工具都涉及多次模型请求(分析是否需要工具→执行工具→生成最终回答),Token开销比普通对话高,建议给工具设置合理的调用频率限制。
描述要写清楚 。每个工具和参数的description是模型判断调用时机的核心依据,写得不清晰,模型会在不该调用工具的时候胡乱调用。建议遵循"动词+对象+场景"的格式,比如"根据订单ID查询订单的当前状态和物流信息"。
六、接入大模型的选择
工具调用的实现高度依赖底层模型的能力。目前主流的AI大模型对Function Calling的支持程度存在差异------OpenAI的GPT系列是最早推出这一能力的厂商;Google的Gemini模型也提供了类似的工具调用接口;Anthropic的Claude通过tool_use机制实现。
Spring AI Alibaba对各大模型厂家的统一抽象是其核心优势 。开发者只需通过配置切换ChatModel实现,业务代码无需任何修改。这意味着同一个工具方法,可以无缝对接通义千问、百川、DeepSeek等多种国产大模型,方便对比不同模型在具体业务场景下的表现。选型时建议优先考虑中文理解能力强的国产模型,在工具调用的准确率和响应速度上往往更有优势。
七、写在最后
工具调用是大模型从"聊天玩具"走向"生产力工具"的核心能力。有了它,AI不再只是陪你闲聊的网友,而是真正可以帮你干活的助手。
给Java开发者的几点建议:
- 先从小场景开始,做个支持天气查询的Demo,体验完整的工具注册和调用流程
- 逐步扩展工具类型,从查询类(信息检索)到操作类(发送邮件、创建工单)
- 生产环境务必加上权限校验、日志审计和成本控制
- 多尝试不同大模型,找到最适合业务场景的底座
AI Agent的下一步,是让多个Agent协同工作:一个Agent负责拆解任务,一个负责调工具,还有一个负责汇总结果。下次有机会聊聊多Agent协作的设计思路。
如果你对AI Agent开发感兴趣,欢迎在评论区交流。