1.1 Spring AI概述
1.1.1 什么是Spring AI
Spring AI是Spring生态系统中专门用于人工智能应用开发的框架。它提供了一套完整的抽象层和工具集,使开发者能够轻松地在Spring应用中集成各种AI模型和服务。
核心特性: - 统一的AI模型抽象接口 - 多种AI提供商支持(OpenAI、Azure、Ollama等) - 向量数据库集成 - 流式处理支持 - Spring生态系统无缝集成
1.1.2 Spring AI的优势
// 传统AI集成方式
public class TraditionalAIService {
private OpenAIClient openAIClient;
private AzureAIClient azureClient;
public String generateText(String prompt, String provider) {
if ("openai".equals(provider)) {
return openAIClient.complete(prompt);
} else if ("azure".equals(provider)) {
return azureClient.generate(prompt);
}
throw new UnsupportedOperationException("Provider not supported");
}
}
// Spring AI方式
@Service
public class SpringAIService {
private final ChatModel chatModel;
public SpringAIService(ChatModel chatModel) {
this.chatModel = chatModel;
}
public String generateText(String prompt) {
return chatModel.call(prompt);
}
}
优势对比: 1. 统一接口:无需关心底层AI提供商的差异 2. 配置驱动:通过配置文件切换AI提供商 3. Spring集成:享受依赖注入、AOP等Spring特性 4. 类型安全:强类型的API设计
1.2 核心概念
1.2.1 AI模型抽象
Spring AI定义了几个核心接口来抽象不同类型的AI模型:
// 聊天模型接口
public interface ChatModel extends Model<Prompt, ChatResponse> {
ChatResponse call(Prompt prompt);
Flux<ChatResponse> stream(Prompt prompt);
}
// 嵌入模型接口
public interface EmbeddingModel extends Model<EmbeddingRequest, EmbeddingResponse> {
EmbeddingResponse call(EmbeddingRequest request);
List<Double> embed(String text);
}
// 图像模型接口
public interface ImageModel extends Model<ImagePrompt, ImageResponse> {
ImageResponse call(ImagePrompt prompt);
}
1.2.2 提示词(Prompt)系统
// 简单提示词
Prompt simplePrompt = new Prompt("解释什么是Spring AI");
// 带参数的提示词模板
PromptTemplate template = new PromptTemplate(
"你是一个{role},请用{language}回答:{question}"
);
Map<String, Object> variables = Map.of(
"role", "Java专家",
"language", "中文",
"question", "什么是Spring Boot"
);
Prompt prompt = template.create(variables);
1.2.3 消息类型
Spring AI支持多种消息类型:
// 用户消息
UserMessage userMessage = new UserMessage("你好,我想学习Spring AI");
// 系统消息
SystemMessage systemMessage = new SystemMessage(
"你是一个专业的Java开发助手,专门帮助开发者学习Spring技术"
);
// 助手消息
AssistantMessage assistantMessage = new AssistantMessage(
"很高兴为您介绍Spring AI!"
);
// 组合消息
List<Message> messages = List.of(systemMessage, userMessage);
Prompt prompt = new Prompt(messages);
1.2.4 响应处理
@Service
public class ChatService {
private final ChatModel chatModel;
public ChatService(ChatModel chatModel) {
this.chatModel = chatModel;
}
// 同步调用
public String chat(String userInput) {
Prompt prompt = new Prompt(userInput);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
// 流式调用
public Flux<String> chatStream(String userInput) {
Prompt prompt = new Prompt(userInput);
return chatModel.stream(prompt)
.map(response -> response.getResult().getOutput().getContent());
}
// 获取元数据
public ChatResponseMetadata getChatMetadata(String userInput) {
Prompt prompt = new Prompt(userInput);
ChatResponse response = chatModel.call(prompt);
return response.getMetadata();
}
}
1.3 支持的AI提供商
1.3.1 OpenAI集成
// 配置
@Configuration
public class OpenAIConfig {
@Bean
public OpenAiChatModel openAiChatModel(
@Value("${spring.ai.openai.api-key}") String apiKey) {
return new OpenAiChatModel(
OpenAiApi.builder()
.withApiKey(apiKey)
.build()
);
}
}
// 使用
@RestController
public class ChatController {
private final OpenAiChatModel chatModel;
@PostMapping("/chat")
public String chat(@RequestBody String message) {
return chatModel.call(message);
}
}
1.3.2 Azure OpenAI集成
@Configuration
public class AzureOpenAIConfig {
@Bean
public AzureOpenAiChatModel azureOpenAiChatModel(
@Value("${spring.ai.azure.openai.api-key}") String apiKey,
@Value("${spring.ai.azure.openai.endpoint}") String endpoint) {
return new AzureOpenAiChatModel(
AzureOpenAiApi.builder()
.withApiKey(apiKey)
.withEndpoint(endpoint)
.build()
);
}
}
1.3.3 Ollama本地模型集成
@Configuration
public class OllamaConfig {
@Bean
public OllamaChatModel ollamaChatModel(
@Value("${spring.ai.ollama.base-url:http://localhost:11434}") String baseUrl) {
return new OllamaChatModel(
OllamaApi.builder()
.withBaseUrl(baseUrl)
.build(),
OllamaOptions.create()
.withModel("llama2")
.withTemperature(0.7f)
);
}
}
1.4 向量数据库支持
1.4.1 向量存储抽象
public interface VectorStore {
void add(List<Document> documents);
Optional<Boolean> delete(List<String> idList);
List<Document> similaritySearch(String query);
List<Document> similaritySearch(SearchRequest request);
}
1.4.2 文档处理
@Service
public class DocumentService {
private final VectorStore vectorStore;
private final EmbeddingModel embeddingModel;
public void addDocuments(List<String> texts) {
List<Document> documents = texts.stream()
.map(text -> new Document(text))
.collect(Collectors.toList());
vectorStore.add(documents);
}
public List<Document> searchSimilar(String query, int topK) {
SearchRequest request = SearchRequest.query(query)
.withTopK(topK)
.withSimilarityThreshold(0.7);
return vectorStore.similaritySearch(request);
}
}
1.4.3 支持的向量数据库
// Chroma配置
@Bean
public ChromaVectorStore chromaVectorStore(EmbeddingModel embeddingModel) {
return new ChromaVectorStore(embeddingModel, "http://localhost:8000");
}
// Pinecone配置
@Bean
public PineconeVectorStore pineconeVectorStore(
EmbeddingModel embeddingModel,
@Value("${pinecone.api-key}") String apiKey,
@Value("${pinecone.environment}") String environment) {
return new PineconeVectorStore(
PineconeApi.builder()
.withApiKey(apiKey)
.withEnvironment(environment)
.build(),
embeddingModel
);
}
// Redis配置
@Bean
public RedisVectorStore redisVectorStore(
EmbeddingModel embeddingModel,
RedisTemplate<String, Object> redisTemplate) {
return new RedisVectorStore(redisTemplate, embeddingModel);
}
1.5 函数调用(Function Calling)
1.5.1 函数定义
@Component
public class WeatherFunction implements Function<WeatherRequest, WeatherResponse> {
@Override
public WeatherResponse apply(WeatherRequest request) {
// 模拟天气查询
return new WeatherResponse(
request.getLocation(),
"晴天",
25.0,
"今天天气很好,适合外出"
);
}
}
// 请求和响应类
record WeatherRequest(String location) {}
record WeatherResponse(String location, String weather, Double temperature, String description) {}
1.5.2 函数注册和使用
@Service
public class FunctionCallingService {
private final ChatModel chatModel;
private final WeatherFunction weatherFunction;
public String chatWithFunctions(String userMessage) {
// 创建函数选项
OpenAiChatOptions options = OpenAiChatOptions.builder()
.withFunction("get_weather", "获取指定地点的天气信息", weatherFunction)
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
}
1.6 配置管理
1.6.1 应用配置文件
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
azure:
openai:
api-key: ${AZURE_OPENAI_API_KEY}
endpoint: ${AZURE_OPENAI_ENDPOINT}
chat:
options:
deployment-name: gpt-35-turbo
ollama:
base-url: http://localhost:11434
chat:
options:
model: llama2
temperature: 0.8
vectorstore:
chroma:
url: http://localhost:8000
pinecone:
api-key: ${PINECONE_API_KEY}
environment: ${PINECONE_ENVIRONMENT}
index-name: spring-ai-index
1.6.2 条件配置
@Configuration
public class AIModelConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.ai.provider", havingValue = "openai")
public ChatModel openAiChatModel() {
// OpenAI配置
return new OpenAiChatModel(/* ... */);
}
@Bean
@ConditionalOnProperty(name = "spring.ai.provider", havingValue = "azure")
public ChatModel azureOpenAiChatModel() {
// Azure OpenAI配置
return new AzureOpenAiChatModel(/* ... */);
}
@Bean
@ConditionalOnProperty(name = "spring.ai.provider", havingValue = "ollama")
public ChatModel ollamaChatModel() {
// Ollama配置
return new OllamaChatModel(/* ... */);
}
}
1.7 最佳实践
1.7.1 错误处理
@Service
public class RobustChatService {
private final ChatModel chatModel;
private final RetryTemplate retryTemplate;
public String chatWithRetry(String message) {
return retryTemplate.execute(context -> {
try {
Prompt prompt = new Prompt(message);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
} catch (Exception e) {
log.warn("Chat request failed, attempt: {}", context.getRetryCount() + 1, e);
throw e;
}
});
}
}
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
return RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2, 10000)
.retryOn(RuntimeException.class)
.build();
}
}
1.7.2 缓存策略
@Service
@CacheConfig(cacheNames = "ai-responses")
public class CachedChatService {
private final ChatModel chatModel;
@Cacheable(key = "#message.hashCode()")
public String chat(String message) {
Prompt prompt = new Prompt(message);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
@CacheEvict(allEntries = true)
public void clearCache() {
// 清除缓存
}
}
1.7.3 监控和指标
@Component
public class AIMetrics {
private final MeterRegistry meterRegistry;
private final Counter requestCounter;
private final Timer responseTimer;
public AIMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.requestCounter = Counter.builder("ai.requests.total")
.description("Total AI requests")
.register(meterRegistry);
this.responseTimer = Timer.builder("ai.response.time")
.description("AI response time")
.register(meterRegistry);
}
public String timedChat(ChatModel chatModel, String message) {
return responseTimer.recordCallable(() -> {
requestCounter.increment();
return chatModel.call(message);
});
}
}
1.8 本章总结
1.8.1 核心要点
- 统一抽象:Spring AI提供了统一的AI模型抽象接口
- 多提供商支持:支持OpenAI、Azure、Ollama等多种AI提供商
- Spring集成:完美融入Spring生态系统
- 向量数据库:内置多种向量数据库支持
- 函数调用:支持AI模型调用外部函数
1.8.2 最佳实践
- 配置管理:使用配置文件管理不同环境的AI提供商
- 错误处理:实现重试机制和优雅降级
- 性能优化:合理使用缓存和连接池
- 监控指标:添加必要的监控和日志
1.8.3 练习题
基础练习
- 创建一个简单的Spring Boot项目,集成OpenAI ChatGPT
- 实现一个基本的聊天接口,支持用户输入和AI回复
- 配置不同的AI模型参数(temperature、max-tokens等)
进阶练习
- 实现多AI提供商的动态切换
- 添加请求缓存和重试机制
- 创建自定义的函数调用示例
高级练习
- 设计一个AI服务的监控和指标收集系统
- 实现AI模型的负载均衡和故障转移
- 构建一个支持多租户的AI服务平台
下一章我们将学习如何搭建Spring AI开发环境并创建第一个AI应用。