
随着生成式 AI 技术的迅猛发展,大语言模型(LLM)已从研究实验室走向企业生产环境。然而,如何将 LLM 能力安全、稳定、可维护地集成到现有系统中,仍是开发者面临的重大挑战。
对于广大的 Java 开发者而言,Spring 生态一直是企业级应用开发的基石。如今,Spring AI 的诞生,正是 Spring 团队对这一时代命题的有力回应——它不仅是一套工具库,更是一种全新的编程范式,旨在让 Java 工程师无需切换技术栈,即可高效构建智能应用。
本文将深入剖析 Spring AI 的核心架构、设计理念、关键组件与实战用法,并通过完整代码示例与部署方案,带你从零开始搭建一个支持 RAG、函数调用、流式响应的企业级 AI 服务。
Spring AI 的诞生,是 Spring 生态在生成式 AI 浪潮下的必然演进。其核心设计理念延续了 Spring 框架一贯的“抽象与解耦”思想——正如 JdbcTemplate 和 JPA 统一了数据库访问层,Spring AI 试图在 AI 领域建立一套通用编程模型,让开发者无需被特定模型、平台或 API 绑定。
这一哲学的落地体现为两大核心抽象:
ChatClient:提供统一的对话接口,屏蔽底层 LLM 提供商(如 OpenAI、Anthropic、阿里云通义、Ollama 等)的差异。PromptTemplate:将提示工程(Prompt Engineering)结构化,支持变量注入、模板复用和版本管理,提升可维护性。通过这些抽象,Spring AI 实现了“一次编码,多模型运行”的愿景,显著降低了厂商锁定(Vendor Lock-in)风险,也为未来模型迁移和 A/B 测试提供了坚实的技术基础。
抽象的意义在于自由:开发者可以专注于业务逻辑,而非 API 差异。
+-------------------------------------------------------+
| 应用层 (Applications) |
| - 智能客服 / 文档问答 / 代码助手 / Agent 工作流 |
+----------------------+--------------------------------+
|
+--------------v--------------+
| 功能增强层 (Enhancements) |
| - PromptTemplate |
| - Structured Output |
| - Function Calling |
| - RAG 流程编排 |
+---------------+---------------+
|
+--------------v--------------+
| 模型抽象层 (Abstractions) |
| - ChatClient / ChatModel |
| - EmbeddingModel |
| - ImageModel / AudioModel |
+---------------+---------------+
|
+-------------v-------------+
| 数据支撑层 (Data Layer) |
| - VectorStore (Milvus/Pinecone/Redis)|
| - DocumentReader & TextSplitter |
+---------------+---------------+
|
+------------v------------+
| 外部服务与模型提供者 |
| - OpenAI / Anthropic |
| - Alibaba Tongyi Qwen |
| - Ollama (Llama3, DeepSeek)|
| - Hugging Face Inference API |
+---------------------------+VectorStore、TextSplitter 或 ChatModel 实现。@ConfigurationProperties、Spring Security、Actuator、Micrometer 等企业级特性。graph TD
A[Applications\n(智能客服/Agent/代码生成)] --> B[功能增强层]
B --> C[模型抽象层]
C --> D[数据支撑层]
D --> E[外部模型服务]
subgraph 功能增强层
B1[PromptTemplate]
B2[Structured Output]
B3[Function Calling]
B4[RAG 编排]
end
subgraph 模型抽象层
C1[ChatClient / ChatModel]
C2[EmbeddingModel]
C3[ImageModel / AudioModel]
end
subgraph 数据支撑层
D1[VectorStore\n(Milvus/Pinecone/Redis)]
D2[DocumentReader]
D3[TextSplitter]
end
subgraph 外部服务
E1[OpenAI GPT-4o]
E2[Alibaba Qwen]
E3[Ollama (Llama3)]
E4[HuggingFace]
end
B --> C
C --> D
D --> E提示:将上述 Mermaid 代码粘贴到支持 Mermaid 的编辑器中(如 Typora、Notion、GitBook、Confluence 插件),即可渲染为图形化架构图,便于团队协作与文档展示。
组件类别 | 核心接口/类 | 主要职责 |
|---|---|---|
模型抽象 | ChatClient, ChatModel | 提供同步/流式调用大语言模型的能力,支持多种消息类型(User, Assistant, System) |
EmbeddingModel | 文本向量化,用于语义搜索与 RAG | |
ImageModel | 文生图模型调用(如 DALL·E、Stable Diffusion via API) | |
AudioModel | 语音识别(Speech-to-Text)与语音合成(Text-to-Speech) | |
数据支撑 | VectorStore | 向量数据库抽象,支持 Milvus、Pinecone、Redis、FAISS 等 |
DocumentReader, TextSplitter | 文档解析与分块,支持 PDF、Word、HTML、Markdown 等格式 | |
功能增强 | PromptTemplate | 提示词模板化,支持 SpEL 表达式和动态内容注入 |
Structured Output | 将模型输出自动映射为 Java POJO,避免手动解析 | |
Function Calling | 允许模型调用外部 Java 方法,实现工具链集成 | |
Retrieval Augmented Generation (RAG) | 检索增强生成,结合外部知识库提升回答准确性 |
该架构不仅支持基础对话,更可构建复杂的 AI Agent、知识问答系统、智能客服等企业级应用。
特性 | Spring AI | LangChain (Python) | LlamaIndex (Python) |
|---|---|---|---|
编程语言 | Java / Kotlin | Python | Python |
生态集成 | Spring 全家桶无缝集成 | 依赖 Python 包管理 | 依赖 Python 包管理 |
安全控制 | Spring Security 原生支持 | 需额外实现 | 需额外实现 |
监控与可观测性 | Micrometer + Actuator 支持 | 需集成 Prometheus 等工具 | 需集成 Prometheus 等工具 |
配置管理 | @ConfigurationProperties | .env 或手动加载 | .env 或手动加载 |
部署方式 | 可打包为 WAR/JAR,兼容传统部署 | 通常为独立服务或云函数 | 通常为独立服务或云函数 |
企业级支持 | 强(Spring 团队背书) | 社区驱动 | 社区驱动 |
Spring AI 的核心优势:
使用 Spring Initializr 快速创建项目:
spring init --dependencies=ai,web,actuator my-ai-app或通过 Web 界面选择 Spring AI Starter。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.0-M3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
</dependencies>📌 版本说明:根据 GitHub Releases 显示,当前最新版本为
v1.1.0-M3(2025-10-14),已升级至 MCP Java SDK 0.14.0。
server:
port: 8080
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: llama3.2
options:
temperature: 0.7
openai:
api-key: ${OPENAI_API_KEY:}
chat:
model: gpt-4o
chat:
default-model: ollamaChatClient(推荐用于简单调用)@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping("/ai/chat")
public String chat(@RequestParam String message) {
return chatClient.call(message);
}
}ChatModel(更精细控制)@Service
public class AdvancedChatService {
private final ChatModel chatModel;
public AdvancedChatService(ChatModel chatModel) {
this.chatModel = chatModel;
}
public String generate(String prompt) {
Prompt p = new Prompt(
new SystemMessage("你是一个专业的技术顾问。"),
new UserMessage(prompt)
);
return chatModel.call(p).getResult().getOutput().getContent();
}
}适用于聊天界面、语音助手等需要实时反馈的场景。
@Controller
public class StreamingController {
private final ChatModel chatModel;
public StreamingController(ChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping(value = "/ai/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter stream(@RequestParam String message) {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
chatModel.stream(new Prompt(message))
.doOnError(emitter::completeWithError)
.doOnComplete(emitter::complete)
.subscribe(response -> {
try {
emitter.send(response.getResult().getOutput().getContent());
} catch (IOException e) {
emitter.completeWithError(e);
}
});
return emitter;
}
}注意:SSE 不支持跨域,生产环境需配置
CorsConfiguration。
将模型输出自动解析为 Java 对象,避免 JSON 手动解析。
public class WeatherInfo {
private String city;
private double temperature;
private String condition;
private String unit = "Celsius";
// getters & setters
}
@Service
public class WeatherService {
private final ChatModel chatModel;
public WeatherInfo getWeather(String city) {
PromptTemplate template = new PromptTemplate(
"查询 {city} 的当前天气,返回 JSON 格式,包含 city, temperature, condition"
);
Prompt prompt = template.create(Map.of("city", city));
return chatModel.call(prompt)
.getResult()
.getOutput()
.getContentAs(WeatherInfo.class); // 自动反序列化
}
}前提:确保模型支持 JSON 模式输出(如 GPT-4o、Claude 3、Ollama llama3.2 等)。
允许 LLM 主动调用 Java 方法,实现“AI Agent”能力。
@Service
public class WeatherTool {
@Tool(description = "根据城市获取实时天气")
public String getCurrentWeather(String city) {
// 调用真实天气 API
return "{ \"temperature\": 25, \"condition\": \"Sunny\" }";
}
}Spring AI 会自动注册该工具,并在 ChatModel 调用时启用函数调用功能,实现“AI 决策 → 调用工具 → 返回结果”的闭环。
@Service
public class KnowledgeQaService {
private final VectorStore vectorStore;
private final ChatModel chatModel;
private final TextSplitter textSplitter;
private final EmbeddingModel embeddingModel;
public KnowledgeQaService(VectorStore vectorStore,
ChatModel chatModel,
TextSplitter textSplitter,
EmbeddingModel embeddingModel) {
this.vectorStore = vectorStore;
this.chatModel = chatModel;
this.textSplitter = textSplitter;
this.embeddingModel = embeddingModel;
}
// 文档注入
public void ingest(String filePath) throws IOException {
String content = Files.readString(Paths.get(filePath));
Document doc = new Document(content);
List<Document> chunks = textSplitter.split(List.of(doc));
List<Embedding> embeddings = embeddingModel.embed(chunks);
List<ScoredVector> vectors = IntStream.range(0, chunks.size())
.mapToObj(i -> ScoredVector.of(embeddings.get(i).vector(), chunks.get(i).getContent()))
.collect(Collectors.toList());
vectorStore.add(vectors);
}
// 问答
public String ask(String question) {
List<Document> docs = vectorStore.similaritySearch(question);
String context = docs.stream().map(Document::getContent).collect(Collectors.joining("\n\n"));
String prompt = """
基于以下知识回答问题,不要编造:
<context>
%s
</context>
问题:%s
""".formatted(context, question);
return chatModel.call(new Prompt(prompt)).getResult().getOutput().getContent();
}
}spring-ai-demo/
├── src/
│ ├── main/
│ │ ├── java/com/example/ai/
│ │ │ ├── controller/
│ │ │ │ └── AiController.java
│ │ │ ├── service/
│ │ │ │ ├── RagService.java
│ │ │ │ ├── WeatherTool.java
│ │ │ │ └── CodeAssistant.java
│ │ │ ├── config/
│ │ │ │ └── AiConfig.java
│ │ │ └── SpringAiDemoApplication.java
│ │ └── resources/
│ │ ├── application.yml
│ │ └── documents/knowledge.md
├── pom.xml
└── docker-compose.ymlAiController.java@RestController
@RequestMapping("/api/ai")
public class AiController {
private final ChatClient chatClient;
private final RagService ragService;
private final CodeAssistant codeAssistant;
public AiController(ChatClient chatClient,
RagService ragService,
CodeAssistant codeAssistant) {
this.chatClient = chatClient;
this.ragService = ragService;
this.codeAssistant = codeAssistant;
}
@GetMapping("/chat")
public String simpleChat(@RequestParam String msg) {
return chatClient.call(msg);
}
@PostMapping("/rag/query")
public String queryKnowledge(@RequestBody Map<String, String> request) {
return ragService.ask(request.get("question"));
}
@PostMapping("/code/generate")
public String generateCode(@RequestBody Map<String, String> request) {
return codeAssistant.generateCode(request.get("requirement"));
}
}docker-compose.ymlversion: '3.8'
services:
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
volumes:
- ollama:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0:11434
command: serve
spring-ai-app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_AI_OLLAMA_BASE_URL=http://ollama:11434
depends_on:
- ollama
volumes:
ollama:DockerfileFROM eclipse-temurin:17-jre-alpine
VOLUME /tmp
COPY target/spring-ai-demo.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]# 构建 JAR
./mvnw clean package -DskipTests
# 启动服务
docker-compose up -d
# 加载模型
docker exec -it springaidemo-ollama-1 ollama pull llama3.2# 简单对话
curl "http://localhost:8080/api/ai/chat?msg=讲个笑话"
# RAG 查询
curl -X POST http://localhost:8080/api/ai/rag/query \
-H "Content-Type: application/json" \
-d '{"question": "我们公司的核心技术是什么?"}'
# 代码生成
curl -X POST http://localhost:8080/api/ai/code/generate \
-H "Content-Type: application/json" \
-d '{"requirement": "创建一个带分页的用户查询接口"}'访问以下端点查看状态:
http://localhost:8080/actuator/health — 健康检查http://localhost:8080/actuator/metrics — 指标列表http://localhost:8080/actuator/prometheus — Prometheus 指标暴露可集成 Grafana 展示 ai.tokens.used、ai.request.duration 等关键指标,实现 AI 服务的全链路监控。
spring-ai-bom 统一版本M 版尝鲜。# 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull llama3.2推荐使用 llama3.2、qwen:7b、deepseek-coder 等轻量级模型进行本地测试。
q4_K_M)降低显存占用/ai/** 接口访问权限,防止滥用AIHealthIndicator,监控模型服务状态Spring AI 正在重新定义 Java 开发者与 AI 的关系。其核心价值在于:
Spring AI 的出现,标志着企业级开发正式进入“人机协作”时代。 掌握它,你将不仅是代码的构建者,更是智能系统的“指挥官”。
📌 源码地址:[GitHub 仓库链接](请替换为实际地址) 📚 官方文档:https://docs.spring.io/spring-ai/reference/index.html
如果你觉得这篇文章有帮助,欢迎点赞、收藏、转发!也欢迎在评论区交流你的 Spring AI 实践经验。