diff --git a/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/java/org/springframework/ai/model/chat/client/autoconfigure/ChatClientAutoConfiguration.java b/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/java/org/springframework/ai/model/chat/client/autoconfigure/ChatClientAutoConfiguration.java index 9341ea1ae7b..7ca4c3bd54f 100644 --- a/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/java/org/springframework/ai/model/chat/client/autoconfigure/ChatClientAutoConfiguration.java +++ b/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/java/org/springframework/ai/model/chat/client/autoconfigure/ChatClientAutoConfiguration.java @@ -49,10 +49,23 @@ * @author Arjen Poutsma * @author Thomas Vitale * @author Jonatan Ivanov + * @author Yanming Zhou * @since 1.0.0 */ @AutoConfiguration( - afterName = { "org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration" }) + afterName = { "org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration", + "org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration", + "org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration", + "org.springframework.ai.model.bedrock.converse.autoconfigure.BedrockConverseProxyChatAutoConfiguration", + "org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration", + "org.springframework.ai.model.huggingface.autoconfigure.HuggingfaceChatAutoConfiguration", + "org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration", + "org.springframework.ai.model.mistralai.autoconfigure.MistralAiChatAutoConfiguration", + "org.springframework.ai.model.oci.genai.autoconfigure.OCIGenAiChatAutoConfiguration", + "org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration", + "org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration", + "org.springframework.ai.model.vertexai.autoconfigure.gemini.VertexAiGeminiChatAutoConfiguration", + "org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration" }) @ConditionalOnClass(ChatClient.class) @EnableConfigurationProperties(ChatClientBuilderProperties.class) @ConditionalOnProperty(prefix = ChatClientBuilderProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", @@ -77,6 +90,7 @@ ChatClientBuilderConfigurer chatClientBuilderConfigurer(ObjectProvider observationRegistry, ObjectProvider observationConvention) { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java index 40eeaab3397..a9890b68bc7 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.mockito.Mockito; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClientCustomizer; +import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration; import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -37,6 +40,7 @@ /** * @author Christian Tzolov + * @author Yanming Zhou */ @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".*") public class ChatClientAutoConfigurationIT { @@ -44,7 +48,7 @@ public class ChatClientAutoConfigurationIT { private static final Log logger = LogFactory.getLog(ChatClientAutoConfigurationIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"), + .withPropertyValues("spring.ai.openai.api-key=" + System.getenv("OPENAI_API_KEY"), "spring.ai.openai.chat.options.model=gpt-4o") .withConfiguration( AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, @@ -67,6 +71,12 @@ void explicitlyDisabled() { .run(context -> assertThat(context.getBeansOfType(ChatClient.Builder.class)).isEmpty()); } + @Test + void multipleModelsEnabled() { + this.contextRunner.withConfiguration(AutoConfigurations.of(AnotherAiChatAutoConfiguration.class)) + .run(context -> assertThat(context.getBeansOfType(ChatClient.Builder.class)).isEmpty()); + } + @Test void generate() { this.contextRunner.run(context -> { @@ -119,4 +129,14 @@ public ChatClientCustomizer chatClientCustomizer() { } + @AutoConfiguration(before = ChatClientAutoConfiguration.class) + static class AnotherAiChatAutoConfiguration { + + @Bean + ChatModel anotherAiChatModel() { + return Mockito.mock(ChatModel.class); + } + + } + }