发布于2026-07-01 阅读(0)
扫一扫,手机访问
设想一个经典场景:你丢给大模型一句“帮我查查北京的天气,然后用英文回答”。传统做法是先写一段代码调天气API,再写一段代码调翻译API,串起来。但在 Spring AI 的世界里,你只需要把两个工具注册进去,模型自己就能判断什么时候该调天气,什么时候该调翻译,甚至把两个工具的调用顺序和参数拼接得妥妥当当。这就是 Tool Calling 的魅力——让智能体自主决策、自动组合,完成多步骤任务,比如“查询北京天气并用英文回答”,模型会先走天气工具拿到数据,再走翻译工具输出英文。
要理解这套机制,得先摸清几个关键术语。下面这张表做了快速总结:
| 概念 | 说明 |
|---|---|
| Tool Calling | 大模型根据用户问题,生成函数调用请求(含函数名和参数),Spring AI 拦截后执行对应的 Ja va 方法,将结果返回模型。 |
| @Tool 注解 | 标记在方法上,Spring AI 自动解析方法签名和注释,生成 JSON Schema 供模型理解。 |
| 多工具注册 | 通过 defaultTools(...) 同时注册多个工具,模型可自主选择调用顺序和组合。 |
| 链式调用 | 模型在一次响应中先后调用多个工具,前一个的输出作为后一个的输入,形成“链”。 |
简单说,你把工具描述和方法签名告诉模型,模型就能像人一样“看说明书”来使用它们。
接下来我们一步步搭建一个能处理链式调用的智能体。整个项目基于 Spring Boot 3.3.3 + Spring AI 1.1.2 + Ollama(模型用 qwen2.5:7b-instruct)。先从依赖和配置说起。
org.springframework.boot spring-boot-starter-parent 3.3.3 com.example spring-ai-ollama-tool-chain 1.0 17 1.1.2 org.springframework.boot spring-boot-starter-web org.springframework.ai spring-ai-starter-model-ollama ${spring-ai.version}
版本号特意锁到 3.3.3 和 1.1.2,避免踩到某些兼容性坑。依赖只加了 web 和 ollama 模型 starter,干净利落。
server:
port: 886
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: qwen2.5:7b-instruct
options:
temperature: 0.7
num-ctx: 4096 # 上下文窗口大小
logging:
level:
org.springframework.ai.chat.client: DEBUG # 查看工具调用详情
日志级别设成 DEBUG 方便调试,这样工具调用时每一步都会打印出来,对理解模型决策很有帮助。
package com.badao.ai.tools;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
@Component
public class WeatherTool {
@Tool(name = "get_weather", description = "查询指定城市的实时天气")
public String getWeather(@ToolParam(description = "城市名称") String city) {
System.out.println("调用了天气工具");
// 模拟天气数据
return String.format("%s当前天气:晴,温度22℃,湿度45%%。", city);
}
}
用 @Tool 注解标记方法,name 和 description 是关键——模型就是靠这些描述来决定是否调用。这里模拟了天气返回,实际你可以换成真实 API。
package com.badao.ai.tools;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
@Component
public class TranslateTool {
@Tool(name = "translate_to_english", description = "将中文文本翻译成英文")
public String translate(@ToolParam(description = "待翻译的中文文本") String text) {
System.out.println("调用了翻译工具");
// 模拟翻译,实际可接入翻译API
return "Translated: " + text + " (This is the English version.)";
}
}
翻译工具同样标注清楚,模型看到“translate_to_english”就能理解它的职责。
package com.badao.ai.config;
import com.badao.ai.tools.WeatherTool;
import com.badao.ai.tools.TranslateTool;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ToolConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel,
WeatherTool weatherTool,
TranslateTool translateTool) {
return ChatClient.builder(chatModel)
.defaultTools(weatherTool, translateTool) // 注册天气和翻译工具
.build();
}
}
关键点在于 defaultTools() 方法,你可以传入任意多个工具 Bean,Spring AI 会自动收集它们的方法签名和注解信息,生成对应的 JSON Schema 传给模型。模型拿到这些描述,就能自主决策调用哪个、调用顺序如何。
package com.badao.ai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class AgentService {
private final ChatClient chatClient;
public AgentService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String ask(String question) {
return chatClient.prompt()
.user(question+ "(请先用天气工具,再用翻译工具)")
.call()
.content();
}
}
注意这里我们在 user 问题后面追加了“请先用天气工具,再用翻译工具”的提示——这是一种“软约束”,让模型按照预期顺序执行。实际场景中模型也可能自己推理出顺序,但明确提示能提高成功率。
package com.badao.ai.controller;
import com.badao.ai.service.AgentService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class AgentController {
private final AgentService agentService;
public AgentController(AgentService agentService) {
this.agentService = agentService;
}
@PostMapping("/agent")
public String ask(@RequestBody String question) {
return agentService.ask(question);
}
}
暴露一个 POST 接口,接收问题文本,返回模型处理结果。整个链条到此跑通。
跑一下看看效果。先测试单个工具——直接问天气:

再测试工具链——问“北京天气怎么样,用英文回答”:

从日志可以看到,模型先调用了 get_weather 拿到天气数据,接着调用了 translate_to_english 进行翻译,最终输出英文结果。整个顺序完全由模型自主决策,代码层面没有硬编码任何调用顺序,这正是 Tool Calling 链式调用的灵活之处。
有了这套基础,你可以扩展更多的工具——比如查数据库、调第三方 API、执行脚本等等。模型会根据问题场景自动组合,实现真正的“智能体”效果。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8