Spring Boot 3整合Spring AI实战:9轮面试对话解析AI应用开发
第1轮:基础配置与模型调用
周先生:cc,先聊聊Spring AI的基础配置吧。如何在Spring Boot 3项目中集成Ollama?
cc :我们可以通过OllamaConfig.java
实现基础配置,示例代码如下:
java
@Configuration
public class OllamaConfig {
@Bean
public OllamaChatModel ollamaChatModel(OllamaApi ollamaApi) {
return new OllamaChatModel(ollamaApi,
OllamaOptions.builder().model("llama3").build());
}
@Bean
public OllamaApi ollamaApi(@Value("${spring.ai.ollama.base-url}") String baseUrl) {
return new OllamaApi(baseUrl);
}
}
周先生:那如何通过OpenAI进行文本生成呢?
cc :同样,我们可以通过OpenAIConfig.java
配置OpenAI客户端:
java
@Configuration
public class OpenAIConfig {
@Bean
public OpenAiChatModel openAiChatModel(OpenAiApi openAiApi) {
return new OpenAiChatModel(openAiApi,
OpenAiChatOptions.builder().model("gpt-4o").build());
}
@Bean
public OpenAiApi openAiApi(@Value("${spring.ai.openai.base-url}") String baseUrl,
@Value("${spring.ai.openai.api-key}") String apiKey) {
return new OpenAiApi(baseUrl, apiKey);
}
}
周先生:很好,这样我们就能灵活配置不同的AI模型了。
第2轮:多模型路由设计
周先生:在实际项目中,我们可能需要根据不同的查询内容选择不同的模型,如何实现这种智能路由?
cc:我们可以设计一个模型路由器,根据查询内容的特点选择合适的模型:
java
@Service
public class ModelRouter {
private final Map<String, ChatModel> models;
public ModelRouter(Map<String, ChatModel> models) {
this.models = models;
}
public ChatModel getPreferredModel(String query) {
// 根据查询内容选择模型
if (query.contains("code") || query.contains("technical")) {
return models.get("ollama"); // 本地技术问题用Ollama
}
return models.get("openai"); // 复杂问题用OpenAI
}
}
周先生:这个设计很实用,能够根据查询内容的特点选择最适合的模型。
第3轮:RAG架构实现
周先生:如何在Spring AI中实现RAG(Retrieval-Augmented Generation)架构?
cc:我们可以通过向量存储实现RAG架构,以下是一个基于PgVectorStore的示例:
java
@Service
public class DocumentService {
private final PgVectorStore vectorStore;
private final OllamaEmbeddingModel embeddingModel;
public DocumentService(PgVectorStore vectorStore,
OllamaEmbeddingModel embeddingModel) {
this.vectorStore = vectorStore;
this.embeddingModel = embeddingModel;
}
public void uploadDocument(String content) {
// 创建文档
Document document = new Document(content);
// 分词处理
TokenTextSplitter textSplitter = new TokenTextSplitter();
List<Document> splitDocuments = textSplitter.apply(List.of(document));
// 存储到向量数据库
vectorStore.add(splitDocuments);
}
public List<Document> searchRelevantDocs(String query) {
// 相似性搜索
return vectorStore.similaritySearch(query, 5);
}
}
周先生:非常棒!这样就能让AI在回答问题时参考相关文档内容了。
第4轮:可观测性实现
周先生:在生产环境中,我们需要监控AI服务的性能,如何实现可观测性?
cc:Spring AI支持与Micrometer集成,实现监控:
java
@Configuration
public class ObservabilityConfig {
@Bean
public ObservationRegistry observationRegistry() {
return ObservationRegistry.create();
}
@Bean
public ChatClient.Builder chatClientBuilder(ChatModel chatModel) {
return new DefaultChatClientBuilder(chatModel,
observationRegistry(),
ChatClientObservationConvention.DEFAULT);
}
}
并在application.yml中添加配置:
yaml
management:
endpoints:
web:
exposure:
include: "*"
tracing:
sampling:
probability: 1.0
周先生:这样我们就能监控AI服务的请求响应时间、token消耗等指标了。
第5轮:模型版本管理
周先生:如何管理不同版本的AI模型?
cc:我们可以通过配置类管理不同版本的模型:
java
@Configuration
public class ModelVersionConfig {
@Bean("ollamaLlama3_1")
public OllamaChatModel ollamaLlama3_1(OllamaApi ollamaApi) {
return new OllamaChatModel(ollamaApi,
OllamaOptions.builder().model("llama3:latest").build());
}
@Bean("ollamaLlama3_2")
public OllamaChatModel ollamaLlama3_2(OllamaApi ollamaApi) {
return new OllamaChatModel(ollamaApi,
OllamaOptions.builder().model("llama3:70b").build());
}
@Bean("openAiGpt4")
public OpenAiChatModel openAiGpt4(OpenAiApi openAiApi) {
return new OpenAiChatModel(openAiApi,
OpenAiChatOptions.builder().model("gpt-4").build());
}
@Bean("openAiGpt4Turbo")
public OpenAiChatModel openAiGpt4Turbo(OpenAiApi openAiApi) {
return new OpenAiChatModel(openAiApi,
OpenAiChatOptions.builder().model("gpt-4-turbo").build());
}
}
周先生:这样就可以灵活切换和比较不同版本的模型了。
第6轮:错误处理与重试机制
周先生:在调用AI服务时可能会出现网络问题或服务不可用,如何处理这些异常情况?
cc:我们可以使用Spring Retry实现重试机制:
java
@Service
public class AiService {
private final ChatClient chatClient;
public AiService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public String generateText(String prompt) {
return chatClient.prompt(prompt).call().content();
}
@Recover
public String recover(Exception ex, String prompt) {
return "抱歉,AI服务暂时不可用,请稍后再试。";
}
}
周先生:这个重试机制很重要,能提高服务的稳定性。
第7轮:流式响应处理
周先生:对于较长的AI响应,如何实现流式输出以提升用户体验?
cc:Spring AI支持流式响应,我们可以这样实现:
java
@RestController
public class AiController {
private final ChatClient chatClient;
@GetMapping(value = "/ai/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamResponse(@RequestParam String prompt) {
return chatClient.prompt(prompt)
.stream()
.map(chatResponse -> chatResponse.getResult().getOutput().getContent());
}
}
周先生:流式响应能让用户更快看到部分结果,体验更好。
第8轮:多模态处理
周先生:如何处理图像等非文本输入?
cc:Spring AI支持多模态输入,可以处理图像:
java
@Service
public class MultimodalService {
private final OllamaChatModel ollamaChatModel;
public String analyzeImage(Resource imageResource, String prompt) {
UserMessage userMessage = new UserMessage(prompt,
new Media(MimeType.valueOf("image/png"), imageResource));
Prompt aiPrompt = new Prompt(userMessage,
OllamaOptions.builder().model("llava").build());
ChatResponse response = ollamaChatModel.call(aiPrompt);
return response.getResult().getOutput().getContent();
}
}
周先生:多模态处理能力让AI应用更加丰富。
第9轮:性能优化
周先生:在高并发场景下,如何优化AI服务的性能?
cc:我们可以从多个方面进行优化:
- 使用连接池管理AI服务连接
- 实现结果缓存
- 异步处理请求
java
@Service
public class OptimizedAiService {
private final ChatClient chatClient;
private final Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
public OptimizedAiService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@Async
public CompletableFuture<String> generateTextAsync(String prompt) {
return CompletableFuture.supplyAsync(() -> {
String cached = cache.getIfPresent(prompt);
if (cached != null) {
return cached;
}
String result = chatClient.prompt(prompt).call().content();
cache.put(prompt, result);
return result;
});
}
}
周先生:这些优化措施能显著提升AI服务的性能和响应速度。
通过这9轮的深入对话,我们系统地探讨了Spring AI在Spring Boot 3项目中的各种应用场景和实现方式。从基础配置到高级特性,涵盖了实际开发中可能遇到的大部分问题。希望这些内容能帮助你在面试中脱颖而出,也能在实际项目中发挥作用。