diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java index d15a6469e41..1d65972f095 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java @@ -66,18 +66,33 @@ public class OpenAiChatAutoConfiguration { @Bean @ConditionalOnMissingBean - public OpenAiChatModel openAiChatModel(OpenAiConnectionProperties commonProperties, - OpenAiChatProperties chatProperties, ObjectProvider restClientBuilderProvider, - ObjectProvider webClientBuilderProvider, ToolCallingManager toolCallingManager, - RetryTemplate retryTemplate, ResponseErrorHandler responseErrorHandler, + public OpenAiApi openAiApi(OpenAiConnectionProperties commonProperties, OpenAiChatProperties chatProperties, + ObjectProvider restClientBuilderProvider, + ObjectProvider webClientBuilderProvider, ResponseErrorHandler responseErrorHandler) { + + OpenAIAutoConfigurationUtil.ResolvedConnectionProperties resolved = resolveConnectionProperties( + commonProperties, chatProperties, "chat"); + + return OpenAiApi.builder() + .baseUrl(resolved.baseUrl()) + .apiKey(new SimpleApiKey(resolved.apiKey())) + .headers(resolved.headers()) + .completionsPath(chatProperties.getCompletionsPath()) + .embeddingsPath(OpenAiEmbeddingProperties.DEFAULT_EMBEDDINGS_PATH) + .restClientBuilder(restClientBuilderProvider.getIfAvailable(RestClient::builder)) + .webClientBuilder(webClientBuilderProvider.getIfAvailable(WebClient::builder)) + .responseErrorHandler(responseErrorHandler) + .build(); + } + + @Bean + @ConditionalOnMissingBean + public OpenAiChatModel openAiChatModel(OpenAiApi openAiApi, OpenAiChatProperties chatProperties, + ToolCallingManager toolCallingManager, RetryTemplate retryTemplate, ObjectProvider observationRegistry, ObjectProvider observationConvention, ObjectProvider openAiToolExecutionEligibilityPredicate) { - var openAiApi = openAiApi(chatProperties, commonProperties, - restClientBuilderProvider.getIfAvailable(RestClient::builder), - webClientBuilderProvider.getIfAvailable(WebClient::builder), responseErrorHandler, "chat"); - var chatModel = OpenAiChatModel.builder() .openAiApi(openAiApi) .defaultOptions(chatProperties.getOptions()) @@ -93,23 +108,4 @@ public OpenAiChatModel openAiChatModel(OpenAiConnectionProperties commonProperti return chatModel; } - private OpenAiApi openAiApi(OpenAiChatProperties chatProperties, OpenAiConnectionProperties commonProperties, - RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, - ResponseErrorHandler responseErrorHandler, String modelType) { - - OpenAIAutoConfigurationUtil.ResolvedConnectionProperties resolved = resolveConnectionProperties( - commonProperties, chatProperties, modelType); - - return OpenAiApi.builder() - .baseUrl(resolved.baseUrl()) - .apiKey(new SimpleApiKey(resolved.apiKey())) - .headers(resolved.headers()) - .completionsPath(chatProperties.getCompletionsPath()) - .embeddingsPath(OpenAiEmbeddingProperties.DEFAULT_EMBEDDINGS_PATH) - .restClientBuilder(restClientBuilder) - .webClientBuilder(webClientBuilder) - .responseErrorHandler(responseErrorHandler) - .build(); - } - } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java index 19cf832fda8..04054484426 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java @@ -24,6 +24,7 @@ import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.OpenAiModerationModel; +import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -42,6 +43,7 @@ public class OpenAiModelConfigurationTests { @Test void chatModelActivation() { this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { + assertThat(context.getBeansOfType(OpenAiApi.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); @@ -303,4 +305,14 @@ void moderationModelActivation() { }); } + @Test + void openAiApiBean() { + // Test that OpenAiApi bean is registered and can be injected + this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { + assertThat(context.getBeansOfType(OpenAiApi.class)).hasSize(1); + OpenAiApi openAiApi = context.getBean(OpenAiApi.class); + assertThat(openAiApi).isNotNull(); + }); + } + }