聊点儿实在的。Spring AI 这个框架,网上的资料确实不少,但很多要么太教条,要么直接甩你一堆官方文档链接。今天这篇不谈空话,就是把自己本地搭建的完整过程掰开揉碎了说,连我掉进去的那些坑都一并扒出来。
一、迈出第一步之前,先把"地基"夯实
说真的,本地跑大模型比想象中简单得多。你不需要一台几十万的企业级服务器,只要你手头的电脑配置不太拉跨就行。
硬件到底需要啥? 根据我自己的经历,如果你只是跑个本地 Demo,不需要 GPU,CPU 模式完全够用。我当初用的一台 8 核处理器、16G 内存的 MacBook Pro,跑起来顺畅得很。但如果你想本地跑个大点的模型(比如 7B 参数的 Llama 或者 Qwen),那就得看你的 GPU 了------有个 8G 以上显存的显卡,体验会舒服很多。如果你还在用 4G 显存的入门卡,别灰心,选个 1.5B 到 3B 的小模型,照样能玩转。
软件环境 :Spring AI 官方文档明确支持 Spring Boot 3.4.x 和 3.5.x,所以 JDK 必须是 17 或以上版本。构建工具我选的是 Maven(个人习惯,Gradle 也行),IDE 用的 IntelliJ IDEA,基本是 Java 开发的标配。
本地大模型怎么选? 我强烈推荐用 Ollama 来部署本地模型。Ollama 是一个专门在本地跑大模型的工具,安装极其简单,一条命令就能把 Llama、Mistral、Qwen 这些模型拉下来跑起来。
安装 Ollama:去 https://ollama.com 下载对应的安装包,双击一路 Next 就行。安装完成后,打开终端,输入这条命令来拉取一个比较轻量的模型:
bash
ollama pull qwen2.5:3b
这条命令会从 Ollama 的模型仓库里下载阿里通义千问 2.5 版本,参数规模 3B。这个模型对中文的支持特别好,而且 3B 的规模普通电脑 CPU 跑起来也毫无压力。下载完成后,可以用 ollama run qwen2.5:3b 先在命令行里测试一下,确保模型能正常对话,再开始下一步。
二、版本选择:选错了,后面全是坑
这里我想多唠叨几句。Spring AI 的版本迭代速度非常快,而且现在同时有 1.x 稳定线 和 2.x 预览线在并行推进。
当前版本的实际情况:
- Spring AI 1.0 已在 2025 年 5 月 GA,1.1 已在 2025 年 11 月 GA。1.1 版本带来了 MCP(模型上下文协议)集成、提示缓存等重量级功能。
- 2.0.0-M2 和 M3 也已发布,带来了向量存储的大幅升级、结构化输出增强、Redis 语义缓存等功能。
我的建议 :如果你现在新建项目,直接用 1.1.x 稳定版,别去踩 0.x 版本的坑。2.0 虽然新功能多,但还在里程碑阶段,API 可能随时调整,用在生产环境风险太大。
使用 BOM 来统一管理版本是最稳妥的方式:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Ollama 模型支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
<!-- Spring AI 核心 Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter</artifactId>
</dependency>
</dependencies>
注意这里的关键变化:Spring AI 1.0 之后,starter 模块的 artifact 名称发生了重大调整 。我之前踩过这个坑------照着网上老教程写 spring-ai-ollama-spring-boot-starter,结果编译直接报错找不到。正确的 artifactId 是 spring-ai-starter-model-ollama。
三、第一个 Hello World:让 Spring Boot 和大模型说上话
依赖配好了,写段代码跑起来试试。
先配置 application.yml:
yaml
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen2.5:3b
temperature: 0.7
然后写一个简单的 Service:
java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class AIService {
private final ChatClient chatClient;
public AIService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}
再写个 Controller 测试一下:
java
@RestController
@RequestMapping("/ai")
public class AIController {
private final AIService aiService;
public AIController(AIService aiService) {
this.aiService = aiService;
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return aiService.chat(message);
}
}
跑之前千万记得确认一件事 :你的 Ollama 服务必须已经启动并且 qwen2.5:3b 模型已经下载完毕。如果 Ollama 没跑起来,这段代码会直接报连接异常,这个坑我当初踩了至少三回。
如果你顺利跑通了,访问 http://localhost:8080/ai/chat?message=用一句话介绍Java的特点,应该能看到类似这样的输出:
Java 是一种跨平台的面向对象编程语言,以其"一次编写,到处运行"的特点而闻名。
看到这个输出,说明你的 Spring Boot 项目已经成功和本地大模型对话上了。
四、对话记忆:让 AI 不再"健忘"
上面那个例子,每次调用都是独立的,AI 不记得你刚才说过什么。要让对话有上下文,Spring AI 提供了 Advisor 机制来管理对话记忆。
java
@Service
public class ChatWithMemoryService {
private final ChatClient chatClient;
public ChatWithMemoryService(ChatClient.Builder chatClientBuilder) {
// 配置对话记忆,保留最近 10 条消息
this.chatClient = chatClientBuilder
.defaultAdvisors(new MessageChatMemoryAdvisor(
new InMemoryChatMemory(), 10))
.build();
}
public String chat(String userMessage, String conversationId) {
return chatClient.prompt()
.user(userMessage)
.advisors(advisor -> advisor.param("conversationId", conversationId))
.call()
.content();
}
}
这里的关键是 MessageChatMemoryAdvisor------它会自动管理对话上下文,你只需要传入一个 conversationId 就能区分不同的会话。InMemoryChatMemory 是内存版实现,适合开发和测试;生产环境可以换成 Redis 或数据库持久化版本。
跑一下多轮对话试试:
java
// 用户:我叫张三
// AI:你好张三,有什么我可以帮你的吗?
// 用户:我刚才说我叫什么来着?
// AI:你刚才说你叫张三。
// 用户:我的名字里第一个字是什么?
// AI:第一个字是"张"。
看到没?AI 能准确记住你之前说过的名字,这就是对话记忆在背后起的作用。
五、结构化输出:从"废话"到"数据"
大模型默认返回的是自然语言文本,但在实际业务中,你往往需要把模型输出映射成 Java 对象。Spring AI 对结构化输出的支持做得相当不错。
假设你想让模型识别用户意图并返回一个结构化的结果:
java
public record IntentResult(
String intent, // 意图类型:query / complaint / suggestion
String category, // 具体分类
double confidence // 置信度
) {}
@Service
public class IntentService {
private final ChatClient chatClient;
public IntentService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
public IntentResult analyzeIntent(String userMessage) {
return chatClient.prompt()
.user("分析以下用户消息的意图:\n" + userMessage)
.call()
.entity(IntentResult.class); // 直接映射到 Java Record
}
}
entity() 方法会告诉模型以 JSON 格式输出,并自动反序列化成你指定的 Java 类型。Spring AI 内部用的是 JSON Schema 验证,确保返回的数据结构符合预期。
这个能力在构建 Agent 或工作流时特别有用------你可以把模型的自然语言输出直接转化成结构化的业务数据,不用手动写正则解析了。
六、给 AI 配上"知识库":极简版 RAG
对话记忆只是让 AI 记住你刚才说了什么,但如果想让 AI 回答关于你公司内部文档、产品说明书之类的私有知识,就需要 RAG(检索增强生成)。Spring AI 通过 QuestionAnswerAdvisor 和向量存储来支持 RAG。
先添加向量存储依赖(以 PGVector 为例):
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>
配置向量存储(application.yml):
yaml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/vector_db
username: postgres
password: your_password
ai:
vectorstore:
pgvector:
initialize-schema: true
dimensions: 384 # 根据你的 Embedding 模型维度设置
然后实现 RAG 服务:
java
@Service
public class RAGService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
private final EmbeddingModel embeddingModel;
public RAGService(ChatClient.Builder chatClientBuilder,
VectorStore vectorStore,
EmbeddingModel embeddingModel) {
this.vectorStore = vectorStore;
this.embeddingModel = embeddingModel;
this.chatClient = chatClientBuilder.build();
}
// 将文档向量化并存入向量库
public void indexDocument(String content, String metadata) {
Document doc = new Document(content, Map.of("source", metadata));
List<Document> docs = List.of(doc);
vectorStore.add(docs);
}
// 基于知识库回答问题
public String askWithRAG(String question) {
return chatClient.prompt()
.user(question)
.advisors(new QuestionAnswerAdvisor(vectorStore, embeddingModel))
.call()
.content();
}
}
QuestionAnswerAdvisor 是 Spring AI 内置的 RAG Advisor,它会自动完成"检索相关文档 → 构建增强 Prompt → 调用模型"这一整套流程,省去了大量样板代码。
这套系统跑起来之后,你问"公司年假怎么申请"这种问题,AI 就不再是瞎编了,而是会从你导入的员工手册文档里找答案,准确性提升不是一星半点。
七、Tool Calling:让 AI 学会"干活"
RAG 让 AI 能"查资料",Tool Calling(函数调用)则让 AI 能"做事"------比如查数据库、调用外部 API、发邮件等。
假设你想让 AI 能帮用户查询天气:
java
@Configuration
public class ToolConfig {
@Bean
@Description("获取指定城市的天气信息")
public Function<WeatherRequest, WeatherResponse> getWeather() {
return request -> {
// 这里调用真实的天气 API
return new WeatherResponse(
request.city(),
"晴",
22,
"适合户外活动"
);
};
}
public record WeatherRequest(String city) {}
public record WeatherResponse(String city, String condition, int temperature, String suggestion) {}
}
然后在调用时启用工具:
java
@Service
public class AgentService {
private final ChatClient chatClient;
public AgentService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultFunctions("getWeather") // 注册工具函数
.build();
}
public String chatWithTool(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}
当用户问"上海今天天气怎么样"时,模型会识别出这是一个天气查询需求,自动调用你注册的 getWeather 函数,拿到结果后再组织成自然语言回复。
这个能力在构建 AI Agent 时特别关键------它让模型不再是一个"只能聊天的花瓶",而是能真正和业务系统交互的智能体。
八、MCP:AI 应用的"下一个大事件"
如果你关注 Spring AI 的版本动态,一定会注意到 MCP(模型上下文协议) 这个词。这是 Spring AI 1.1 最重要的功能集改进。
MCP 是 Anthropic 提出的一个开放协议,本质上是给 AI 模型提供了一套标准化的工具接入规范。Spring AI 对 MCP 的支持相当全面,提供了基于注解的编程模型和 Spring Boot 自动配置。
创建 MCP Server(让外部系统能被 AI 调用)
java
@McpTool
public String getOrderStatus(@McpToolParam(description = "订单号") String orderId) {
// 查询订单状态
return "订单 " + orderId + " 状态:已发货";
}
@McpResource(uri = "file:///db/schema.sql")
public String getDatabaseSchema() {
// 返回数据库 schema
return "CREATE TABLE orders...";
}
加上 MCP Server 启动器依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
创建 MCP Client(让 AI 能调用这些工具)
java
@Configuration
public class MCPClientConfig {
@Bean
public McpClient mcpClient() {
return McpClient.sync("http://localhost:8080")
.requestTimeout(Duration.ofSeconds(30))
.build();
}
}
MCP 的价值在于标准化。以前你要给 AI 接一个工具,得自己封装 HTTP 接口、处理认证、解析响应。有了 MCP,这些都有统一规范,AI Agent 可以自动发现和调用可用的工具。
官方提供了多种传输选项------STDIO 用于本地进程通信,HTTP SSE 用于 Web 集成,还支持 WebFlux 和 WebMVC 两种模式。
九、别踩这些坑
这几条是我用 Spring AI 过程中真实踩过的坑,希望能帮你省下好几个小时的 debug 时间。
坑一:artifact 名称变了。 Spring AI 1.0 之后,starter 模块的命名发生了重大变化。如果你看到老教程里的 spring-ai-ollama-spring-boot-starter,千万别直接用。正确的依赖是 spring-ai-starter-model-ollama。
坑二:BOM 版本管理。 官方强烈建议通过 BOM 统一管理版本,不要分别指定各个模块的版本号。不同模块版本不一致会导致各种奇奇怪怪的方法找不到。
坑三:Ollama 没启动就调用。 这个坑我踩了好几次。代码写得再漂亮,如果 Ollama 服务没跑起来或者模型没下载完,调用时会直接报 Connection refused 异常。运行前先用 ollama list 确认模型已下载,用 ollama ps 确认服务在运行。
坑四:Embedding 模型维度不匹配。 配置 PGVector 向量存储时,dimensions 参数必须和 Embedding 模型输出的向量维度一致。比如用 all-MiniLM-L6-v2 是 384 维,用 text-embedding-ada-002 是 1536 维。配错了向量存不进去,但错误信息往往不明显,排查起来很头疼。
坑五:Spring AI 和 Spring Boot 版本要对应。 官方文档明确写了支持 Spring Boot 3.4.x 和 3.5.x。如果你用的是 Spring Boot 2.x,那抱歉,Spring AI 跑不起来。
十、写在最后
说实话,Spring AI 这个框架确实不完美。1.x 版本刚 GA 没多久,有些功能还在完善中,文档也谈不上详尽。但话说回来,作为一个 Spring Boot 开发者,能在自己熟悉的生态里做大模型应用,而不用被迫切换到 Python,这本身就是一件很爽的事情。
Spring AI 的核心价值不是"能调模型",而是把 Spring 的工程化理念带到了 AI 场景里。依赖注入、自动配置、AOP、可观测性------这些你熟悉的东西,现在都能用在 AI 应用上了。
我自己的经验是:从一个最简单的 Hello World 开始,先跑通单次对话;然后慢慢引入 ChatMemory 做多轮对话;再试试结构化输出和 RAG,给应用加上知识库和工具调用能力。一步一步来,每往前走一步,你都会对这个框架的理解更深一点。
最后提一嘴版本选择 :如果你现在就动手实践,用 Spring AI 1.1.x 搭配 Spring Boot 3.4.x,是目前最稳妥的组合。2.0 虽然新功能诱人,但等它 GA 之后再升级也不迟。
希望这篇教程能帮你少走一些弯路。如果你在搭建过程中遇到什么问题,或者有什么好玩的实践想分享,欢迎留言交流------毕竟,Java 圈做大模型应用的人还是少数,咱们更需要互相帮衬。