大模型接入 Java 项目并不难,真正麻烦的是:不同模型的请求格式不同、流式响应处理复杂、工具调用还要自己维护参数解析和执行循环。
Spring AI 的价值,就是为 Java 开发者提供一套相对统一的抽象。我们可以继续使用熟悉的 Spring Boot、依赖注入和注解,把大模型能力接入现有系统。
本文通过一个"天气助手"示例,快速实现两项能力:
-
使用
ChatClient完成大模型对话; -
使用
@Tool让模型调用 Java 方法查询天气。
一、Spring AI 解决了什么问题?
如果直接调用模型厂商的 HTTP 接口,我们通常要处理请求体、响应解析、流式输出、工具参数、上下文和异常。更换模型时,还可能重新适配一套接口。
Spring AI 对这些能力进行了统一封装,核心包括:
-
ChatModel:屏蔽不同聊天模型的调用差异; -
ChatClient:提供类似 SpringWebClient的流式 API; -
Tool Calling:把 Java 方法暴露给大模型选择和调用;
-
Advisors:以拦截器方式扩展记忆、RAG、日志等能力;
-
Vector Store:对接向量数据库,构建知识库问答;
-
MCP:以标准协议连接外部工具和资源。
需要注意:Spring AI 不是一个大模型,也不会替代业务代码。它更像 Java 应用和模型服务之间的适配层。
二、创建 Spring Boot 项目
在 pom.xml 中导入 Spring AI BOM,并添加 Web 和模型 Starter。下面以 OpenAI 兼容模型为例:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>2.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
然后在 application.yml 中配置模型:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: your-model-name
temperature: 0.2
API Key 不要直接写进配置文件并提交到 Git,推荐通过环境变量或密钥管理服务注入。
三、使用 ChatClient 实现基础对话
Spring Boot 会根据模型 Starter 自动配置 ChatClient.Builder。我们可以将其注入 Controller:
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是一个严谨的 Java 技术助手,请简洁回答问题。")
.build();
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
访问:
GET /ai/chat?message=什么是依赖注入
调用链很直观:Controller 接收问题,ChatClient 构造 Prompt 并调用模型,最后从响应中取出文本内容。
但普通对话只能依赖模型已有知识。如果用户询问实时天气、订单状态或数据库数据,模型本身无法得到最新结果。这时就需要 Tool Calling。
四、使用 @Tool 声明 Java 工具
先定义一个天气工具。为了让示例可以独立运行,这里使用模拟数据;实际项目中可替换为第三方天气接口。
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
@Component
public class WeatherTools {
@Tool(description = "查询指定城市的当前天气")
public WeatherResult getCurrentWeather(
@ToolParam(description = "城市名称,例如杭州、北京") String city) {
if (city == null || city.isBlank()) {
throw new IllegalArgumentException("城市名称不能为空");
}
// 实际项目中在这里调用天气 API
return new WeatherResult(city.trim(), 28, "晴", "东南风2级");
}
public record WeatherResult(
String city,
int temperature,
String condition,
String wind) {
}
}
@Tool 告诉 Spring AI:这个方法可以作为工具提供给模型。description 非常重要,因为模型会根据工具名称、说明和参数结构判断是否调用它。
@ToolParam 则补充参数语义。描述越清楚,模型生成错误参数的概率越低。
接着把工具注册到本次调用:
@RestController
@RequestMapping("/ai")
public class WeatherController {
private final ChatClient chatClient;
private final WeatherTools weatherTools;
public WeatherController(ChatClient.Builder builder,
WeatherTools weatherTools) {
this.chatClient = builder.build();
this.weatherTools = weatherTools;
}
@GetMapping("/weather")
public String weather(@RequestParam String question) {
return chatClient.prompt()
.system("你是天气助手。涉及实时天气时必须使用工具,不要编造数据。")
.user(question)
.tools(weatherTools)
.call()
.content();
}
}
现在请求:
GET /ai/weather?question=杭州今天天气怎么样,适合跑步吗
模型会识别出需要实时天气,生成类似 getCurrentWeather(city="杭州") 的工具调用。Spring AI 执行 Java 方法,再把结果交给模型组织为自然语言回答。
五、Tool Calling 的完整执行链路
很多初学者会误以为:大模型看到 @Tool 后直接执行了 Java 代码。实际流程并不是这样。
-
应用把工具名称、描述和参数 Schema 一起发送给模型;
-
模型判断是否需要工具,并返回工具名和 JSON 参数;
-
Spring AI 根据工具名定位并执行本地 Java 方法;
-
工具返回结构化结果;
-
Spring AI 将结果作为工具响应再次发送给模型;
-
模型结合工具结果生成最终回答。
因此,模型负责"做决策和填参数",Java 应用负责"真正执行"。ChatClient 默认可通过框架托管方式完成这一循环,我们不需要手动解析每一次工具调用。
这也意味着:工具调用是否安全,不能只靠 Prompt。权限校验、参数校验和执行限制必须放在 Java 代码中。
六、Spring AI 和 LangChain4j 怎么选?
二者都能在 Java 中接入大模型、RAG 和工具调用,没有绝对优劣。
如果项目本身就是 Spring Boot,希望复用自动配置、Bean 管理、Advisor 和 Spring 生态,Spring AI 通常更自然。若更看重声明式 AI Service、框架独立性或现有 LangChain4j 组件,也可以选择 LangChain4j。
比"选哪个框架"更重要的是:模型调用、工具执行和业务服务之间要保持清晰边界。业务逻辑不应全部堆进 Controller,也不应与某个模型 SDK 强绑定。
七、总结
使用 Spring AI 实现 Tool Calling,核心只有三步:
-
通过
ChatClient接入大模型; -
使用
@Tool和@ToolParam描述 Java 工具; -
在调用时通过
.tools(...)将工具提供给模型。
但真正上线时,重点不是"模型成功调用了一次工具",而是这次调用是否可校验、可超时、可审计、可重试,并且不会绕过业务权限。
Spring AI 降低了 Java 接入大模型的门槛,却不会替我们解决所有工程问题。把模型当作不确定的决策组件,把 Java 服务当作可靠的执行边界,才是 Tool Calling 能稳定落地的关键。