1. 概述
現代應用程序越來越多地與大型語言模型 (LLM) 集成,以構建智能解決方案。雖然單個 LLM 可以處理多種任務,但僅僅依賴一個模型並不總是最佳方法。
不同模型在不同的能力方面表現出色,有些在技術分析方面表現突出,而另一些則在創意寫作方面表現更好。此外,我們可能更喜歡使用輕量級和成本效益更高的模型來處理簡單任務,並將強大的模型保留用於複雜任務。
在本教程中,我們將探索如何在 Spring Boot 應用程序中使用 Spring AI 集成多個 LLM。
我們將配置來自不同提供商的模型,以及來自同一提供商的多個模型。然後,我們將在此配置基礎上構建一個具有彈性聊天機器人,該聊天機器人在發生故障時能夠自動切換模型。
2. 配置不同提供商的LLM
讓我們從我們的應用程序中配置兩個來自不同提供商的LLM開始。
對於我們的演示,我們將 OpenAI 和 Anthropic 作為我們的 AI 模型提供商。
2.1. 配置主要 LLM
我們將首先配置 OpenAI 模型作為我們的主要 LLM。
首先,讓我們將必要的依賴項添加到項目的 pom.xml文件中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.0.2</version>
</dependency>OpenAI starter 依賴項是一個圍繞 OpenAI 模型啓動器 的封裝,使我們能夠在應用程序中與 OpenAI 模型進行交互。
接下來,讓我們在 OpenAI API 密鑰 和 聊天模型 中配置 OpenAI 模型,並在 application.yaml 文件中:
spring:
ai:
open-ai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: ${PRIMARY_LLM}
temperature: 1我們使用 ${} 屬性佔位符從環境變量中加載我們的屬性值。 此外,我們設置了温度為 1,因為較新的 OpenAI 模型 僅接受此默認值。
在配置上述屬性後,Spring AI 會自動創建一個類型為 OpenAiChatModel 的 Bean。 讓我們使用它來定義一個 ChatClient Bean,它作為與我們的 LLM 交互的主要入口點:
@Configuration
class ChatbotConfiguration {
@Bean
@Primary
ChatClient primaryChatClient(OpenAiChatModel chatModel) {
return ChatClient.create(chatModel);
}
}在我們的 ChatbotConfiguration 類中,我們使用 OpenAiChatModel Bean 創建 ChatClient Bean 作為我們主要的 LLM。
我們使用 @Primary 註解標記這個 Bean。 Spring Boot 會在自動注入 ChatClient Bean 時,自動注入它,而無需使用任何 Qualifier。
2.2. 配置輔助 LLM
現在,讓我們配置 Anthropic 提供的模型作為我們的輔助 LLM。
首先,讓我們將 Anthropic starter 依賴 添加到我們的 pom.xml 文件中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
<version>1.0.2</version>
</dependency>這個依賴項是一個包裝器,圍繞着 Anthropic Message API,併為我們提供必要的類,以便建立連接並與 Anthropic 模型進行交互。
接下來,讓我們定義我們輔助模型中的配置屬性:
spring:
ai:
anthropic:
api-key: ${ANTHROPIC_API_KEY}
chat:
options:
model: ${SECONDARY_LLM}類似於我們的主要LLM配置,我們加載Anthropic API密鑰和模型ID,均來自環境變量。
最後,讓我們為我們的次要模型創建一個專門的 ChatClient Bean:
@Bean
ChatClient secondaryChatClient(AnthropicChatModel chatModel) {
return ChatClient.create(chatModel);
}在這裏,我們使用 Spring AI 自動配置的 AnthropicChatModel 豆,創建了一個 secondaryChatClient 豆。
3. 同提供商的LLM配置
通常情況下,我們需要配置的LLM可能來自同一個AI提供商。
Spring AI 本身並不原生支持此場景,因為自動配置只會為每個提供商創建一個 ChatModel Bean。我們需要手動定義額外的模型(們)的 ChatModel Bean。
讓我們探索這個過程並配置應用程序中的第二個Anthropic模型:
spring:
ai:
anthropic:
chat:
options:
tertiary-model: ${TERTIARY_LLM}在我們的 application.yaml 中,在 Anthropic 配置下,我們添加了一個自定義屬性來存儲三級 LLM 的模型名稱。
接下來,讓我們定義我們三級 LLM 所需的 Bean:
@Bean
ChatModel tertiaryChatModel(
AnthropicApi anthropicApi,
AnthropicChatModel anthropicChatModel,
@Value("${spring.ai.anthropic.chat.options.tertiary-model}") String tertiaryModelName
) {
AnthropicChatOptions chatOptions = anthropicChatModel.getDefaultOptions().copy();
chatOptions.setModel(tertiaryModelName);
return AnthropicChatModel.builder()
.anthropicApi(anthropicApi)
.defaultOptions(chatOptions)
.build();
}
@Bean
ChatClient tertiaryChatClient(@Qualifier("tertiaryChatModel") ChatModel tertiaryChatModel) {
return ChatClient.create(tertiaryChatModel);
}首先,我們創建自定義的 ChatModel Bean 時,我們注入了自動配置的 AnthropicApi Bean,以及我們用於創建次級 LLM 的默認 AnthropicChatModel Bean,並使用 @Value 注入第三級模型名稱屬性。
我們從現有的 AnthropicChatModel Bean 中複製默認選項,並僅覆蓋模型名稱。
此配置假設 Anthropic 模型共享相同的 API 密鑰和其他配置。 如果需要指定不同的屬性,我們可以進一步自定義 AnthropicChatOptions。
最後,我們使用自定義的 tertiaryChatModel Bean 創建配置類中的第三個 ChatClient Bean。
4. 探索一個實際用例
有了我們多模型配置就緒,讓我們來實現一個實際用例。 我們將構建一個具有彈性回退功能的聊天機器人,當主模型失敗時,它將按順序回退到備用模型。
4.1. 構建健壯的聊天機器人
為了實現回退邏輯,我們將使用 Spring Retry。
讓我們創建一個新的 <em >ChatbotService</em> 類,並自動注入我們之前定義的三個 <em >ChatClient</em> Bean。然後,讓我們定義聊天機器人的入口點,該入口點使用主要的 LLM:
@Retryable(retryFor = Exception.class, maxAttempts = 3)
String chat(String prompt) {
logger.debug("Attempting to process prompt '{}' with primary LLM. Attempt #{}",
prompt, RetrySynchronizationManager.getContext().getRetryCount() + 1);
return primaryChatClient
.prompt(prompt)
.call()
.content();
}在這裏,我們創建一個 chat() 方法,它使用 primaryChatClient bean。我們用 @Retryable 註解標記此方法,配置其在任何 Exception 發生時最多嘗試三次。
接下來,讓我們定義一個恢復方法:
@Recover
String chat(Exception exception, String prompt) {
logger.warn("Primary LLM failure. Error received: {}", exception.getMessage());
logger.debug("Attempting to process prompt '{}' with secondary LLM", prompt);
try {
return secondaryChatClient
.prompt(prompt)
.call()
.content();
} catch (Exception e) {
logger.warn("Secondary LLM failure: {}", e.getMessage());
logger.debug("Attempting to process prompt '{}' with tertiary LLM", prompt);
return tertiaryChatClient
.prompt(prompt)
.call()
.content();
}
}@Recover 註解標記了我們的重載的 chat() 方法作為原始 chat() 方法失敗並耗盡配置的重試次數後的備用方法。
我們首先嚐試從 secondaryChatClient 獲取響應。如果這也失敗了,我們使用 tertiaryChatClient Bean 進行最終嘗試。
由於 Spring Retry 僅允許每個方法簽名一個恢復方法,因此我們使用這種基本的 try-catch 實現。然而,在生產應用程序中,我們應該考慮像 Resilience4j 這樣的更高級的解決方案。
現在我們已經實現了服務層,讓我們在之上暴露一個 REST API:
@PostMapping("/api/chatbot/chat")
ChatResponse chat(@RequestBody ChatRequest request) {
String response = chatbotService.chat(request.prompt);
return new ChatResponse(response);
}
record ChatRequest(String prompt) {}
record ChatResponse(String response) {}在這裏,我們定義了一個 POST /api/chatbot/chat 接口,它接受一個 prompt,將其傳遞給服務層,最後將其包裝並以 ChatResponse 記錄的形式返回 response。
4.2. 測試我們的聊天機器人
最後,讓我們測試我們的聊天機器人,以驗證回退機制是否正確工作。
讓我們使用環境變量啓動我們的應用程序,這些環境變量指定了我們主要和次要 LLM 的無效模型名稱,但對三級 LLM 卻指定了一個有效的名稱:
OPENAI_API_KEY=.... \
ANTHROPIC_API_KEY=.... \
PRIMARY_LLM=gpt-100 \
SECONDARY_LLM=claude-opus-200 \
TERTIARY_LLM=claude-3-haiku-20240307 \
mvn spring-boot:run在我們的命令中,gpt-100和claude-opus-200是無效的模型名稱,會導致API錯誤,而claude-3-haiku-20240307是Anthropic提供的有效模型。.
接下來,我們使用HTTPie CLI來調用API端點並與我們的聊天機器人進行交互:
http POST :8080/api/chatbot/chat prompt="What is the capital of France?"在這裏,我們向聊天機器人發送一個簡單的提示,讓我們看看我們收到什麼作為響應:
{
"response": "The capital of France is Paris."
}如我們所見,儘管配置了無效的主次級 LLM,我們的聊天機器人仍然提供了正確的響應,這證實了系統會回退到三級 LLM。
要查看回退邏輯在行動中的表現,我們也可以查看我們的應用程序日誌:
[2025-09-30 12:56:03] [DEBUG] [com.baeldung.multillm.ChatbotService] - Attempting to process prompt 'What is the capital of France?' with primary LLM. Attempt #1
[2025-09-30 12:56:05] [DEBUG] [com.baeldung.multillm.ChatbotService] - Attempting to process prompt 'What is the capital of France?' with primary LLM. Attempt #2
[2025-09-30 12:56:06] [DEBUG] [com.baeldung.multillm.ChatbotService] - Attempting to process prompt 'What is the capital of France?' with primary LLM. Attempt #3
[2025-09-30 12:56:07] [WARN] [com.baeldung.multillm.ChatbotService] - Primary LLM failure. Error received: HTTP 404 - {
"error": {
"message": "The model `gpt-100` does not exist or you do not have access to it.",
"type": "invalid_request_error",
"param": null,
"code": "model_not_found"
}
}
[2025-09-30 12:56:07] [DEBUG] [com.baeldung.multillm.ChatbotService] - Attempting to process prompt 'What is the capital of France?' with secondary LLM
[2025-09-30 12:56:07] [WARN] [com.baeldung.multillm.ChatbotService] - Secondary LLM failure: HTTP 404 - {"type":"error","error":{"type":"not_found_error","message":"model: claude-opus-200"},"request_id":"req_011CTeBrAY8rstsSPiJyv3sj"}
[2025-09-30 12:56:07] [DEBUG] [com.baeldung.multillm.ChatbotService] - Attempting to process prompt 'What is the capital of France?' with tertiary LLM日誌清晰地展示了我們的請求執行流程。
**我們觀察到三次與主要LLM的嘗試失敗。隨後,我們的服務嘗試使用次要LLM,但同樣失敗。最後,它調用了第三級LLM,該LLM處理了提示並返回了我們所見到的響應。**
這表明我們的備用機制完全按照設計工作,確保了聊天機器人即使在多個LLM失敗的情況下仍然可用。
5. 結論
在本文中,我們探討了如何在單個 Spring AI 應用程序中集成多個 LLM。
首先,我們展示了 Spring AI 的抽象層如何簡化配置來自不同提供商(如 OpenAI 和 Anthropic)的模型。
然後,我們解決了從同一提供商配置多個模型,並在 Spring AI 的自動配置不足以使用自定義 Bean 的更復雜場景。
最後,我們使用這種多模型配置構建了一個具有彈性且高可用性的聊天機器人。藉助 Spring Retry,我們配置了一個級聯回退模式,以便在發生故障時自動在 LLM 之間切換。