Skip to content

Commit e9be5b5

Browse files
ilayaperumalgTheovanKraay
authored andcommitted
Fix AzureOpenAI auto-configuration opt-in
- Move AzureOpenAiClientBuilderAutoConfiguration to a simple AzureOpenAiClientBuilderConfiguration - This will make sure that the Azure OpenAI client builder will only be imported when the underlying Azure OpenAI auto-configuration is enabled - Update tests Signed-off-by: Ilayaperumal Gopinathan <ilayaperumal.gopinathan@broadcom.com> Signed-off-by: Theo van Kraay <theo.van@microsoft.com>
1 parent 6f83974 commit e9be5b5

File tree

6 files changed

+27
-8
lines changed

6 files changed

+27
-8
lines changed

auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/main/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAudioTranscriptionAutoConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2929
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3030
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Import;
3132

3233
/**
3334
* {@link AutoConfiguration Auto-configuration} for Azure OpenAI.
@@ -42,7 +43,7 @@
4243
@EnableConfigurationProperties(AzureOpenAiAudioTranscriptionProperties.class)
4344
@ConditionalOnProperty(name = SpringAIModelProperties.AUDIO_TRANSCRIPTION_MODEL,
4445
havingValue = SpringAIModels.AZURE_OPENAI, matchIfMissing = true)
45-
@ImportAutoConfiguration(classes = AzureOpenAiClientBuilderAutoConfiguration.class)
46+
@Import(AzureOpenAiClientBuilderConfiguration.class)
4647
public class AzureOpenAiAudioTranscriptionAutoConfiguration {
4748

4849
@Bean

auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/main/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiChatAutoConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3939
import org.springframework.context.ApplicationContext;
4040
import org.springframework.context.annotation.Bean;
41+
import org.springframework.context.annotation.Import;
4142

4243
/**
4344
* {@link AutoConfiguration Auto-configuration} for Azure OpenAI.
@@ -52,8 +53,8 @@
5253
@EnableConfigurationProperties({ AzureOpenAiChatProperties.class })
5354
@ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.AZURE_OPENAI,
5455
matchIfMissing = true)
55-
@ImportAutoConfiguration(
56-
classes = { AzureOpenAiClientBuilderAutoConfiguration.class, ToolCallingAutoConfiguration.class })
56+
@ImportAutoConfiguration(classes = { ToolCallingAutoConfiguration.class })
57+
@Import(AzureOpenAiClientBuilderConfiguration.class)
5758
public class AzureOpenAiChatAutoConfiguration {
5859

5960
@Bean
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,16 @@
3838
import org.springframework.util.StringUtils;
3939

4040
/**
41-
* {@link AutoConfiguration Auto-configuration} for Azure OpenAI.
41+
* Azure OpenAI Client Builder configuration.
4242
*
4343
* @author Piotr Olaszewski
4444
* @author Soby Chacko
4545
* @author Manuel Andreo Garcia
4646
* @author Ilayaperumal Gopinathan
4747
*/
48-
@AutoConfiguration
4948
@ConditionalOnClass({ OpenAIClientBuilder.class })
5049
@EnableConfigurationProperties(AzureOpenAiConnectionProperties.class)
51-
public class AzureOpenAiClientBuilderAutoConfiguration {
50+
public class AzureOpenAiClientBuilderConfiguration {
5251

5352
private static final String APPLICATION_ID = "spring-ai";
5453

auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/main/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiEmbeddingAutoConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3232
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3333
import org.springframework.context.annotation.Bean;
34+
import org.springframework.context.annotation.Import;
3435

3536
/**
3637
* {@link AutoConfiguration Auto-configuration} for Azure OpenAI.
@@ -45,7 +46,7 @@
4546
@EnableConfigurationProperties({ AzureOpenAiEmbeddingProperties.class })
4647
@ConditionalOnProperty(name = SpringAIModelProperties.EMBEDDING_MODEL, havingValue = SpringAIModels.AZURE_OPENAI,
4748
matchIfMissing = true)
48-
@ImportAutoConfiguration(classes = AzureOpenAiClientBuilderAutoConfiguration.class)
49+
@Import(AzureOpenAiClientBuilderConfiguration.class)
4950
public class AzureOpenAiEmbeddingAutoConfiguration {
5051

5152
@Bean

auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/main/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiImageAutoConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2929
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3030
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Import;
3132

3233
/**
3334
* {@link AutoConfiguration Auto-configuration} for Azure OpenAI.
@@ -42,7 +43,7 @@
4243
@ConditionalOnProperty(name = SpringAIModelProperties.IMAGE_MODEL, havingValue = SpringAIModels.AZURE_OPENAI,
4344
matchIfMissing = true)
4445
@EnableConfigurationProperties(AzureOpenAiImageOptionsProperties.class)
45-
@ImportAutoConfiguration(classes = AzureOpenAiClientBuilderAutoConfiguration.class)
46+
@Import(AzureOpenAiClientBuilderConfiguration.class)
4647
public class AzureOpenAiImageAutoConfiguration {
4748

4849
@Bean

auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiModelConfigurationTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.ai.model.azure.openai.autoconfigure;
1818

19+
import com.azure.ai.openai.OpenAIClientBuilder;
1920
import org.junit.jupiter.api.Test;
2021
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
2122

@@ -45,6 +46,7 @@ void chatModelActivation() {
4546
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class))
4647
.run(context -> {
4748
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty();
49+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
4850
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
4951
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
5052
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
@@ -55,6 +57,7 @@ void chatModelActivation() {
5557
.run(context -> {
5658
assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isEmpty();
5759
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty();
60+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty();
5861
});
5962

6063
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class))
@@ -70,6 +73,7 @@ void chatModelActivation() {
7073
"spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none")
7174
.run(context -> {
7275
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty();
76+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
7377
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
7478
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
7579
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
@@ -84,20 +88,23 @@ void embeddingModelActivation() {
8488
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty();
8589
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
8690
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
91+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
8792
});
8893

8994
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class))
9095
.withPropertyValues("spring.ai.model.embedding=none")
9196
.run(context -> {
9297
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isEmpty();
9398
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
99+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty();
94100
});
95101

96102
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class))
97103
.withPropertyValues("spring.ai.model.embedding=azure-openai")
98104
.run(context -> {
99105
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isNotEmpty();
100106
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty();
107+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
101108
});
102109

103110
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class))
@@ -107,6 +114,7 @@ void embeddingModelActivation() {
107114
.run(context -> {
108115
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty();
109116
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty();
117+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
110118
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
111119
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
112120
});
@@ -119,6 +127,7 @@ void imageModelActivation() {
119127
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty();
120128
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
121129
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isNotEmpty();
130+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
122131
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
123132
});
124133

@@ -127,13 +136,15 @@ void imageModelActivation() {
127136
.run(context -> {
128137
assertThat(context.getBeansOfType(AzureOpenAiImageOptionsProperties.class)).isEmpty();
129138
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
139+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty();
130140
});
131141

132142
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class))
133143
.withPropertyValues("spring.ai.model.image=azure-openai")
134144
.run(context -> {
135145
assertThat(context.getBeansOfType(AzureOpenAiImageOptionsProperties.class)).isNotEmpty();
136146
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isNotEmpty();
147+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
137148
});
138149

139150
this.contextRunner.withConfiguration(AutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class))
@@ -144,6 +155,7 @@ void imageModelActivation() {
144155
assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty();
145156
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
146157
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isNotEmpty();
158+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
147159
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
148160
});
149161
}
@@ -157,6 +169,7 @@ void audioTranscriptionModelActivation() {
157169
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
158170
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
159171
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty();
172+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
160173
});
161174

162175
this.contextRunner
@@ -165,6 +178,7 @@ void audioTranscriptionModelActivation() {
165178
.run(context -> {
166179
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionProperties.class)).isEmpty();
167180
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty();
181+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty();
168182
});
169183

170184
this.contextRunner
@@ -173,6 +187,7 @@ void audioTranscriptionModelActivation() {
173187
.run(context -> {
174188
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionProperties.class)).isNotEmpty();
175189
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty();
190+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
176191
});
177192

178193
this.contextRunner
@@ -185,6 +200,7 @@ void audioTranscriptionModelActivation() {
185200
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty();
186201
assertThat(context.getBeansOfType(AzureOpenAiImageModel.class)).isEmpty();
187202
assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty();
203+
assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty();
188204
});
189205
}
190206

0 commit comments

Comments
 (0)