探索Spring生态系统中的AI革命:从零开始构建智能应用
📖 技术背景介绍
在人工智能技术快速发展的今天,传统的Spring应用开发者面临着如何将AI能力集成到现有系统中的挑战。Spring AI作为Spring生态系统的重要组成部分,为Java开发者提供了一套完整的AI应用开发框架,让开发者能够以熟悉的Spring方式构建智能应用。
🎯 Spring AI的诞生背景
- 🔄 技术融合需求:传统企业应用需要集成AI能力
- 🛠️ 开发复杂性:AI模型集成涉及复杂的配置和管理
- 📈 生态系统完整性:Spring需要在AI时代保持技术领先
- 👥 开发者友好性:降低Java开发者使用AI的门槛
🧠 核心概念解析
🏗️ Spring AI 架构概览

🔑 核心组件详解
1. Chat Client(聊天客户端)
功能 :提供与大语言模型的对话接口
特点:
- 🎯 统一的API接口
- 🔄 多模型支持
- 📝 流式响应
- 🛠️ 函数调用支持
2. Embedding Client(嵌入客户端)
功能 :将文本转换为向量表示
应用场景:
- 🔍 语义搜索
- 📊 文档相似度计算
- 🎯 推荐系统
3. Vector Stores(向量存储)
功能 :存储和检索向量数据
支持的存储:
- 🗄️ Chroma
- 📊 Pinecone
- 🔍 Weaviate
- 💾 Redis
🛠️ 具体实现步骤
步骤1:项目初始化
Maven依赖配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Spring AI Demo</name>
<description>Spring AI基础示例项目</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<spring-ai.version>0.8.1</spring-ai.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Core -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
步骤2:配置文件设置
application.yml配置
yaml
# Spring AI 配置
spring:
application:
name: spring-ai-demo
# AI模型配置
ai:
openai:
api-key: ${OPENAI_API_KEY:your-api-key-here}
base-url: https://api.openai.com
chat:
options:
model: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
embedding:
options:
model: text-embedding-ada-002
# 服务器配置
server:
port: 8080
servlet:
context-path: /api
# 日志配置
logging:
level:
org.springframework.ai: DEBUG
com.example: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
步骤3:核心服务实现
AI服务接口定义
java
package com.example.service;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.embedding.EmbeddingResponse;
/**
* 🤖 AI服务接口
* 定义基础的AI功能
*/
public interface AIService {
/**
* 💬 简单聊天
* @param message 用户消息
* @return AI回复
*/
String simpleChat(String message);
/**
* 🎯 结构化聊天
* @param message 用户消息
* @return 完整的聊天响应
*/
ChatResponse structuredChat(String message);
/**
* 📊 文本嵌入
* @param text 输入文本
* @return 嵌入向量响应
*/
EmbeddingResponse generateEmbedding(String text);
/**
* 🔍 语义相似度计算
* @param text1 文本1
* @param text2 文本2
* @return 相似度分数
*/
double calculateSimilarity(String text1, String text2);
}
📋 完整代码展示
AI服务实现类
java
package com.example.service.impl;
import com.example.service.AIService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.embedding.EmbeddingClient;
import org.springframework.ai.embedding.EmbeddingRequest;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 🤖 AI服务实现类
* 提供基础的AI功能实现
*/
@Service
public class AIServiceImpl implements AIService {
private static final Logger logger = LoggerFactory.getLogger(AIServiceImpl.class);
private final ChatClient chatClient;
private final EmbeddingClient embeddingClient;
public AIServiceImpl(ChatClient chatClient, EmbeddingClient embeddingClient) {
this.chatClient = chatClient;
this.embeddingClient = embeddingClient;
logger.info("🚀 AI服务初始化完成");
}
@Override
public String simpleChat(String message) {
logger.debug("💬 处理简单聊天请求: {}", message);
try {
// 🎯 创建用户消息
UserMessage userMessage = new UserMessage(message);
// 📤 发送请求并获取响应
ChatResponse response = chatClient.call(new Prompt(userMessage));
// 📥 提取回复内容
String reply = response.getResult().getOutput().getContent();
logger.debug("✅ 聊天响应: {}", reply);
return reply;
} catch (Exception e) {
logger.error("❌ 聊天请求失败", e);
return "抱歉,我现在无法回答您的问题。请稍后再试。";
}
}
@Override
public ChatResponse structuredChat(String message) {
logger.debug("🎯 处理结构化聊天请求: {}", message);
try {
// 🎯 创建提示
Prompt prompt = new Prompt(new UserMessage(message));
// 📤 发送请求
ChatResponse response = chatClient.call(prompt);
logger.debug("✅ 结构化聊天完成,Token使用: {}",
response.getMetadata().getUsage());
return response;
} catch (Exception e) {
logger.error("❌ 结构化聊天失败", e);
throw new RuntimeException("聊天服务暂时不可用", e);
}
}
@Override
public EmbeddingResponse generateEmbedding(String text) {
logger.debug("📊 生成文本嵌入: {}", text.substring(0, Math.min(text.length(), 50)));
try {
// 🎯 创建嵌入请求
EmbeddingRequest request = new EmbeddingRequest(List.of(text));
// 📤 发送请求
EmbeddingResponse response = embeddingClient.call(request);
logger.debug("✅ 嵌入生成完成,维度: {}",
response.getResults().get(0).getOutput().size());
return response;
} catch (Exception e) {
logger.error("❌ 嵌入生成失败", e);
throw new RuntimeException("嵌入服务暂时不可用", e);
}
}
@Override
public double calculateSimilarity(String text1, String text2) {
logger.debug("🔍 计算文本相似度");
try {
// 📊 生成两个文本的嵌入
EmbeddingResponse embedding1 = generateEmbedding(text1);
EmbeddingResponse embedding2 = generateEmbedding(text2);
// 📐 提取向量
List<Double> vector1 = embedding1.getResults().get(0).getOutput();
List<Double> vector2 = embedding2.getResults().get(0).getOutput();
// 🧮 计算余弦相似度
double similarity = cosineSimilarity(vector1, vector2);
logger.debug("✅ 相似度计算完成: {}", similarity);
return similarity;
} catch (Exception e) {
logger.error("❌ 相似度计算失败", e);
return 0.0;
}
}
/**
* 🧮 计算余弦相似度
* @param vector1 向量1
* @param vector2 向量2
* @return 相似度分数
*/
private double cosineSimilarity(List<Double> vector1, List<Double> vector2) {
if (vector1.size() != vector2.size()) {
throw new IllegalArgumentException("向量维度不匹配");
}
double dotProduct = 0.0;
double norm1 = 0.0;
double norm2 = 0.0;
for (int i = 0; i < vector1.size(); i++) {
dotProduct += vector1.get(i) * vector2.get(i);
norm1 += Math.pow(vector1.get(i), 2);
norm2 += Math.pow(vector2.get(i), 2);
}
return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}
}
REST控制器
java
package com.example.controller;
import com.example.service.AIService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 🌐 AI API控制器
* 提供RESTful API接口
*/
@RestController
@RequestMapping("/ai")
@CrossOrigin(origins = "*")
public class AIController {
private static final Logger logger = LoggerFactory.getLogger(AIController.class);
private final AIService aiService;
public AIController(AIService aiService) {
this.aiService = aiService;
}
/**
* 💬 简单聊天接口
*/
@PostMapping("/chat/simple")
public ResponseEntity<Map<String, Object>> simpleChat(@RequestBody Map<String, String> request) {
logger.info("📥 收到简单聊天请求");
String message = request.get("message");
if (message == null || message.trim().isEmpty()) {
return ResponseEntity.badRequest()
.body(Map.of("error", "消息不能为空"));
}
try {
String response = aiService.simpleChat(message);
return ResponseEntity.ok(Map.of(
"success", true,
"message", message,
"response", response,
"timestamp", System.currentTimeMillis()
));
} catch (Exception e) {
logger.error("❌ 聊天处理失败", e);
return ResponseEntity.internalServerError()
.body(Map.of("error", "服务暂时不可用"));
}
}
/**
* 🎯 结构化聊天接口
*/
@PostMapping("/chat/structured")
public ResponseEntity<Map<String, Object>> structuredChat(@RequestBody Map<String, String> request) {
logger.info("📥 收到结构化聊天请求");
String message = request.get("message");
if (message == null || message.trim().isEmpty()) {
return ResponseEntity.badRequest()
.body(Map.of("error", "消息不能为空"));
}
try {
ChatResponse response = aiService.structuredChat(message);
return ResponseEntity.ok(Map.of(
"success", true,
"message", message,
"response", response.getResult().getOutput().getContent(),
"metadata", Map.of(
"model", response.getMetadata().getModel(),
"usage", response.getMetadata().getUsage()
),
"timestamp", System.currentTimeMillis()
));
} catch (Exception e) {
logger.error("❌ 结构化聊天处理失败", e);
return ResponseEntity.internalServerError()
.body(Map.of("error", "服务暂时不可用"));
}
}
/**
* 📊 文本嵌入接口
*/
@PostMapping("/embedding")
public ResponseEntity<Map<String, Object>> generateEmbedding(@RequestBody Map<String, String> request) {
logger.info("📥 收到嵌入生成请求");
String text = request.get("text");
if (text == null || text.trim().isEmpty()) {
return ResponseEntity.badRequest()
.body(Map.of("error", "文本不能为空"));
}
try {
EmbeddingResponse response = aiService.generateEmbedding(text);
return ResponseEntity.ok(Map.of(
"success", true,
"text", text,
"embedding", response.getResults().get(0).getOutput(),
"dimensions", response.getResults().get(0).getOutput().size(),
"timestamp", System.currentTimeMillis()
));
} catch (Exception e) {
logger.error("❌ 嵌入生成失败", e);
return ResponseEntity.internalServerError()
.body(Map.of("error", "服务暂时不可用"));
}
}
/**
* 🔍 相似度计算接口
*/
@PostMapping("/similarity")
public ResponseEntity<Map<String, Object>> calculateSimilarity(@RequestBody Map<String, String> request) {
logger.info("📥 收到相似度计算请求");
String text1 = request.get("text1");
String text2 = request.get("text2");
if (text1 == null || text1.trim().isEmpty() ||
text2 == null || text2.trim().isEmpty()) {
return ResponseEntity.badRequest()
.body(Map.of("error", "两个文本都不能为空"));
}
try {
double similarity = aiService.calculateSimilarity(text1, text2);
return ResponseEntity.ok(Map.of(
"success", true,
"text1", text1,
"text2", text2,
"similarity", similarity,
"timestamp", System.currentTimeMillis()
));
} catch (Exception e) {
logger.error("❌ 相似度计算失败", e);
return ResponseEntity.internalServerError()
.body(Map.of("error", "服务暂时不可用"));
}
}
/**
* 🏥 健康检查接口
*/
@GetMapping("/health")
public ResponseEntity<Map<String, Object>> health() {
return ResponseEntity.ok(Map.of(
"status", "UP",
"service", "Spring AI Demo",
"timestamp", System.currentTimeMillis()
));
}
}
主应用类
java
package com.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 🚀 Spring AI 演示应用
* 主启动类
*/
@SpringBootApplication
public class SpringAiDemoApplication {
private static final Logger logger = LoggerFactory.getLogger(SpringAiDemoApplication.class);
public static void main(String[] args) {
logger.info("🚀 启动 Spring AI 演示应用...");
ConfigurableApplicationContext context = SpringApplication.run(SpringAiDemoApplication.class, args);
logger.info("✅ Spring AI 演示应用启动成功!");
logger.info("🌐 API文档: http://localhost:8080/api");
logger.info("🏥 健康检查: http://localhost:8080/api/ai/health");
}
}
🔄 时序图分析
简单聊天流程时序图
🖥️ 客户端 🌐 AIController 🤖 AIService 💬 ChatClient 🧠 OpenAI API POST /ai/chat/simple {"message": "你好"} 📝 验证请求参数 simpleChat(message) 🎯 创建UserMessage call(Prompt) 📤 发送聊天请求 HTTP POST /v1/chat/completions 📥 返回AI响应 ChatResponse 📊 提取回复内容 String reply 📦 构建响应对象 200 OK {"success": true, "response": "你好!..."} 🖥️ 客户端 🌐 AIController 🤖 AIService 💬 ChatClient 🧠 OpenAI API
嵌入生成流程时序图
🖥️ 客户端 🌐 AIController 🤖 AIService 📊 EmbeddingClient 🧠 OpenAI API POST /ai/embedding {"text": "Spring AI很棒"} 📝 验证请求参数 generateEmbedding(text) 🎯 创建EmbeddingRequest call(EmbeddingRequest) 📤 发送嵌入请求 HTTP POST /v1/embeddings 📥 返回向量数据 EmbeddingResponse 📊 提取向量信息 EmbeddingResponse 📦 构建响应对象 200 OK {"success": true, "embedding": [0.1, 0.2, ...], "dimensions": 1536} 🖥️ 客户端 🌐 AIController 🤖 AIService 📊 EmbeddingClient 🧠 OpenAI API
📝 总结与扩展思考
🎯 本文核心要点
- 🏗️ 架构理解:Spring AI提供了统一的AI能力集成框架
- 🔧 配置简化:通过Spring Boot自动配置简化AI服务集成
- 🎯 接口统一:不同AI提供商的统一抽象接口
- 📊 功能丰富:支持聊天、嵌入、图像等多种AI能力
🚀 扩展思考
1. 性能优化方向
- 💾 缓存策略:对频繁请求的结果进行缓存
- 🔄 连接池:优化HTTP连接管理
- 📊 批处理:支持批量嵌入生成
- ⚡ 异步处理:使用响应式编程提升并发性能
2. 功能扩展方向
- 🛠️ 函数调用:集成外部工具和API
- 📝 提示模板:动态提示词管理
- 💾 向量存储:集成向量数据库
- 🔍 RAG系统:检索增强生成
3. 生产环境考虑
- 🔒 安全性:API密钥管理和访问控制
- 📊 监控告警:服务健康状态监控
- 🔄 容错处理:优雅的错误处理和重试机制
- 📈 扩展性:支持多实例部署和负载均衡
🔮 下期预告
在下一篇文章中,我们将深入探讨Spring AI的提示工程与模板管理,学习如何:
- 🎯 设计高效的提示模板
- 📝 实现动态提示词生成
- 🔄 管理提示词版本和A/B测试
- 🎨 构建领域特定的提示词库
标签 :#SpringAI
#人工智能
#Java开发
#微服务架构
#OpenAI