Spring-AI入门-Java开发者的AI落地捷径
对于基于 Spring Boot 构建的系统,如果需要在现有服务中集成 AI 问答功能,通常面临两种方案的选择:
Spring AI 入门:Java 开发者的 AI 落地捷径
对于基于 Spring Boot 构建的系统,如果需要在现有服务中集成 AI 问答功能,通常面临两种方案的选择:
方案一: 引入 Python 服务,使用 LangChain 或 LlamaIndex 实现 AI 能力,通过 HTTP 或 RPC(远程过程调用:让一个服务直接调用另一个服务的函数,就像调用本地函数一样)与 Java 服务通信。这条路可行,但代价明显——Python 服务需要单独维护,增加一套部署流程,跨语言排查问题成本高,团队需要同时具备两个技术栈的运维能力。
方案二: 使用 Spring AI。Spring 官方出品,与 Spring Boot 原生集成,用 Java 编写,无需引入新语言,对现有 Java 团队几乎没有额外学习成本。
本文以方案二为主线,介绍 Spring AI 的核心概念、快速上手步骤、RAG 实现,以及与 Python 框架的对比。
1. Spring AI 是什么
Spring AI 架构 — 核心组件与 Spring Boot 生态集成
Spring AI 不是一个大模型,而是一个调用各种 AI 服务的统一接口,是 Spring 生态针对 AI 应用开发的官方解决方案。
它的作用与 LangChain 类似:将不同 AI 服务商(OpenAI、Anthropic、Azure OpenAI、Ollama 本地模型等)的 API 统一封装,使得切换模型时无需修改业务代码。同时提供 RAG、Function Calling、流式输出等常用能力的标准实现。
与 Spring Boot 的整合是原生的——@Autowired 注入,application.yml 配置,与编写普通 Spring 服务没有区别。
2. 核心组件
ChatClient:调用 LLM 的统一接口。无论底层是 OpenAI 还是 Anthropic,上层代码保持一致,切换模型只需修改配置。
EmbeddingModel:将文本转换为向量(Embedding,嵌入:把文字转成一串数字,让计算机能计算文本之间的相似度),用于 RAG 场景下的语义检索。
VectorStore:向量数据库(专门存储向量数据并支持高效相似度搜索的数据库)的统一接口,支持 PgVector、Redis、Milvus、Weaviate、Chroma 等。
DocumentReader:文档加载器,支持 PDF、Word、HTML、Markdown、JSON、数据库等各类来源。
3. 快速入门
第一步,添加依赖。 Spring AI 目前需要 Spring Boot 3.x 和 Java 17+(具体版本要求请查阅 Spring AI 官方文档,以下 BOM 版本仅供参考)。
<!-- pom.xml -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.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>
<!-- OpenAI 支持 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
</dependencies>
第二步,配置。
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai.com # 国内可替换为代理地址
chat:
options:
model: gpt-4o-mini
temperature: 0.7
第三步,实现一个最基础的对话接口。
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是一个专业的客服助手,请用简洁友好的语气回答问题。")
.build();
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
完成以上三步后,启动服务,访问 /ai/chat?message=你好,即可收到 AI 的回复。
流式输出。 对话内容较长时,用流式输出让用户边看边等,比等全部生成完再显示体验好得多。
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.stream()
.content();
}
前端使用 EventSource(浏览器内置 API,用于接收服务端推送的实时事件流)接收,逐字显示,效果与 ChatGPT 的流式输出一致。
4. RAG 实现
RAG(检索增强生成)是 Spring AI 最常用的场景。将企业内部文档(产品手册、FAQ、政策文件)向量化存储,用户提问时先检索相关内容,再让 LLM 基于检索结果生成答案。
添加依赖:
<!-- PgVector 向量存储(PostgreSQL 的向量搜索扩展,让关系型数据库也能存储和检索向量) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
</dependency>
<!-- PDF 文档读取 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>
配置:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: password
ai:
vectorstore:
pgvector:
initialize-schema: true # 自动建表
dimensions: 1536 # OpenAI embedding 维度
文档入库:
@Service
public class DocumentIngestionService {
private final VectorStore vectorStore;
public DocumentIngestionService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
}
public void ingestPdf(String filePath) {
// 1. 读取 PDF
Resource resource = new FileSystemResource(filePath);
PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(resource);
List<Document> documents = pdfReader.get();
// 2. 切块(每块 500 token,重叠 100 token)
TokenTextSplitter splitter = new TokenTextSplitter(500, 100, 5, 10000, true);
List<Document> chunks = splitter.apply(documents);
// 3. 向量化并存入 PgVector(自动调用 Embedding API)
vectorStore.add(chunks);
System.out.println("入库完成,共 " + chunks.size() + " 个文本块");
}
}
查询时检索并生成答案:
@RestController
@RequestMapping("/ai")
public class RagController {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public RagController(ChatClient.Builder builder, VectorStore vectorStore) {
this.vectorStore = vectorStore;
this.chatClient = builder.build();
}
@GetMapping("/rag")
public String ragQuery(@RequestParam String question) {
// 1. 检索相关文档块
List<Document> relevantDocs = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(3)
);
// 2. 把检索结果拼成上下文
String context = relevantDocs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
// 3. 带上下文调用 LLM
String systemPrompt = """
你是一个专业的问答助手。请仅根据以下提供的资料回答问题。
如果资料中没有相关信息,请回答"我没有找到相关信息"。
参考资料:
{context}
""";
return chatClient.prompt()
.system(s -> s.param("context", context))
.user(question)
.call()
.content();
}
}
Spring AI 还提供了更高级的 QuestionAnswerAdvisor,可以自动完成检索和生成的完整流程,省去手动拼接的步骤。上面的手动实现方式有助于理解 RAG 的内部逻辑,在实际项目中可根据需求选择更简洁的封装。
5. Function Calling
Function Calling(函数调用:LLM 原生具备的能力,能识别何时需要调用外部工具,并输出结构化的调用指令)使 LLM 能够调用开发者定义的 Java 方法,是实现真正 Agent 能力的基础。
// 1. 定义工具函数
@Bean
@Description("查询指定城市的当前天气")
public Function<WeatherRequest, WeatherResponse> weatherFunction() {
return request -> {
// 调用真实的天气 API 或数据库
String weather = queryWeatherApi(request.city());
return new WeatherResponse(request.city(), weather, "28°C");
};
}
// 请求/响应类
record WeatherRequest(String city) {}
record WeatherResponse(String city, String condition, String temperature) {}
// 2. 注册工具并调用
@GetMapping("/agent")
public String agentChat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.functions("weatherFunction") // 注册工具
.call()
.content();
}
当用户询问"北京今天天气怎么样"时,LLM 会自动识别需要调用 weatherFunction,传入参数 {"city": "北京"},获取结果后组织成自然语言回答。整个过程对用户透明。
6. Spring AI vs Python 框架
Spring AI 的优势:
- 无需切换语言,Java 团队零成本上手
- 与 Spring Boot 生态完全融合,事务、权限、监控等能力开箱即用
- 类型安全,编译期即可发现大量潜在问题
- 部署和运维与现有服务保持一致,不增加额外复杂度
Python 框架(LangChain、LlamaIndex)的优势:
- 生态更成熟,各类模型和工具的集成覆盖更全
- 前沿特性更新更快,新出的能力 Python 版本往往优先支持
- RAG 功能更丰富,LlamaIndex 的索引类型远多于 Spring AI
- AI/ML 工具链大多属于 Python 生态,配合使用更流畅
选型建议:
Java 团队给现有系统加 AI 功能,Spring AI 是直接的选择——不引入新语言,不增加运维复杂度,功能够用。
想深入 AI 领域、跟进前沿进展,或者新项目没有语言限制,Python 是绕不开的。论文复现、开源工具、新框架,大多数都以 Python 为首。
两者不冲突。Spring AI 处理现有 Java 项目的集成,Python 处理需要深入的部分。