Spring Boot 3整合Spring AI實戰:9輪面試對話解析AI應用開發
第1輪:基礎配置與模型調用
周先生:cc,先聊聊Spring AI的基礎配置吧。如何在Spring Boot 3項目中集成Ollama?
cc:我們可以通過OllamaConfig.java
實現基礎配置,示例代碼如下:
@Configuration
public class OllamaConfig {@Beanpublic OllamaChatModel ollamaChatModel(OllamaApi ollamaApi) {return new OllamaChatModel(ollamaApi, OllamaOptions.builder().model("llama3").build());}@Beanpublic OllamaApi ollamaApi(@Value("${spring.ai.ollama.base-url}") String baseUrl) {return new OllamaApi(baseUrl);}
}
周先生:那如何通過OpenAI進行文本生成呢?
cc:同樣,我們可以通過OpenAIConfig.java
配置OpenAI客戶端:
@Configuration
public class OpenAIConfig {@Beanpublic OpenAiChatModel openAiChatModel(OpenAiApi openAiApi) {return new OpenAiChatModel(openAiApi,OpenAiChatOptions.builder().model("gpt-4o").build());}@Beanpublic 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:我們可以設計一個模型路由器,根據查詢內容的特點選擇合適的模型:
@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的示例:
@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集成,實現監控:
@Configuration
public class ObservabilityConfig {@Beanpublic ObservationRegistry observationRegistry() {return ObservationRegistry.create();}@Beanpublic ChatClient.Builder chatClientBuilder(ChatModel chatModel) {return new DefaultChatClientBuilder(chatModel, observationRegistry(), ChatClientObservationConvention.DEFAULT);}
}
并在application.yml中添加配置:
management:endpoints:web:exposure:include: "*"tracing:sampling:probability: 1.0
周先生:這樣我們就能監控AI服務的請求響應時間、token消耗等指標了。
第5輪:模型版本管理
周先生:如何管理不同版本的AI模型?
cc:我們可以通過配置類管理不同版本的模型:
@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實現重試機制:
@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();}@Recoverpublic String recover(Exception ex, String prompt) {return "抱歉,AI服務暫時不可用,請稍后再試。";}
}
周先生:這個重試機制很重要,能提高服務的穩定性。
第7輪:流式響應處理
周先生:對于較長的AI響應,如何實現流式輸出以提升用戶體驗?
cc:Spring AI支持流式響應,我們可以這樣實現:
@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支持多模態輸入,可以處理圖像:
@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服務連接
- 實現結果緩存
- 異步處理請求
@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();}@Asyncpublic 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項目中的各種應用場景和實現方式。從基礎配置到高級特性,涵蓋了實際開發中可能遇到的大部分問題。希望這些內容能幫助你在面試中脫穎而出,也能在實際項目中發揮作用。