Skip to content

Commit ad9ab1e

Browse files
committed
refactor auto config to follow openaichat auto config latest changes
Signed-off-by: Alexandros Pappas <[email protected]>
1 parent 5209d05 commit ad9ab1e

File tree

2 files changed

+32
-53
lines changed

2 files changed

+32
-53
lines changed

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.springframework.ai.model.SpringAIModelProperties;
2424
import org.springframework.ai.model.SpringAIModels;
2525
import org.springframework.ai.openai.OpenAiImageModel;
26-
import org.springframework.ai.openai.api.OpenAiApi;
2726
import org.springframework.ai.openai.api.OpenAiImageApi;
2827
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
2928
import org.springframework.beans.factory.ObjectProvider;
@@ -54,24 +53,22 @@
5453
*/
5554
@AutoConfiguration(after = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class,
5655
SpringAiRetryAutoConfiguration.class })
57-
@ConditionalOnClass(OpenAiApi.class)
56+
@ConditionalOnClass(OpenAiImageApi.class)
5857
@ConditionalOnProperty(name = SpringAIModelProperties.IMAGE_MODEL, havingValue = SpringAIModels.OPENAI,
5958
matchIfMissing = true)
6059
@EnableConfigurationProperties({ OpenAiConnectionProperties.class, OpenAiImageProperties.class })
6160
public class OpenAiImageAutoConfiguration {
6261

6362
@Bean
6463
@ConditionalOnMissingBean
65-
public OpenAiImageModel openAiImageModel(OpenAiConnectionProperties commonProperties,
64+
public OpenAiImageApi openAiImageApi(OpenAiConnectionProperties commonProperties,
6665
OpenAiImageProperties imageProperties, ObjectProvider<RestClient.Builder> restClientBuilderProvider,
67-
ObjectProvider<WebClient.Builder> webClientBuilderProvider, RetryTemplate retryTemplate,
68-
ResponseErrorHandler responseErrorHandler, ObjectProvider<ObservationRegistry> observationRegistry,
69-
ObjectProvider<ImageModelObservationConvention> observationConvention) {
66+
ObjectProvider<WebClient.Builder> webClientBuilderProvider, ResponseErrorHandler responseErrorHandler) {
7067

7168
OpenAIAutoConfigurationUtil.ResolvedConnectionProperties resolved = resolveConnectionProperties(
7269
commonProperties, imageProperties, "image");
7370

74-
var openAiImageApi = OpenAiImageApi.builder()
71+
return OpenAiImageApi.builder()
7572
.baseUrl(resolved.baseUrl())
7673
.apiKey(new SimpleApiKey(resolved.apiKey()))
7774
.headers(resolved.headers())
@@ -80,6 +77,14 @@ public OpenAiImageModel openAiImageModel(OpenAiConnectionProperties commonProper
8077
.webClientBuilder(webClientBuilderProvider.getIfAvailable(WebClient::builder))
8178
.responseErrorHandler(responseErrorHandler)
8279
.build();
80+
}
81+
82+
@Bean
83+
@ConditionalOnMissingBean
84+
public OpenAiImageModel openAiImageModel(OpenAiImageApi openAiImageApi, OpenAiImageProperties imageProperties,
85+
RetryTemplate retryTemplate, ObjectProvider<ObservationRegistry> observationRegistry,
86+
ObjectProvider<ImageModelObservationConvention> observationConvention) {
87+
8388
var imageModel = new OpenAiImageModel(openAiImageApi, imageProperties.getOptions(), retryTemplate,
8489
observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP));
8590

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

Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@
2020
import org.apache.commons.logging.LogFactory;
2121
import org.junit.jupiter.api.Test;
2222
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
23-
import reactor.core.publisher.Flux;
2423

2524
import org.springframework.ai.image.ImagePrompt;
2625
import org.springframework.ai.image.ImageResponse;
26+
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
2727
import org.springframework.ai.openai.OpenAiImageModel;
28-
import org.springframework.ai.openai.OpenAiImageOptions;
2928
import org.springframework.ai.openai.api.OpenAiImageApi;
3029
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
3130
import org.springframework.boot.autoconfigure.AutoConfigurations;
@@ -47,62 +46,37 @@ public class OpenAiImageAutoConfigurationIT {
4746
private static final Log logger = LogFactory.getLog(OpenAiImageAutoConfigurationIT.class);
4847

4948
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
50-
.withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"),
51-
"spring.ai.openai.image.options.model=gpt-image-1-mini")
49+
.withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"))
5250
.withConfiguration(
5351
AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class,
54-
WebClientAutoConfiguration.class, OpenAiImageAutoConfiguration.class));
52+
WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class));
5553

5654
@Test
5755
void imageModelAutoConfigured() {
58-
this.contextRunner.run(context -> {
56+
this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)).run(context -> {
5957
assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty();
6058
assertThat(context.getBeansOfType(OpenAiImageApi.class)).isNotEmpty();
6159
});
6260
}
6361

6462
@Test
6563
void generateImage() {
66-
this.contextRunner.run(context -> {
67-
OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class);
68-
69-
assertThat(imageModel).isNotNull();
70-
71-
ImagePrompt prompt = new ImagePrompt("A simple red circle");
72-
ImageResponse response = imageModel.call(prompt);
73-
74-
assertThat(response).isNotNull();
75-
assertThat(response.getResults()).isNotEmpty();
76-
assertThat(response.getResult().getOutput().getB64Json()).isNotEmpty();
77-
78-
logger
79-
.info("Generated image with base64 length: " + response.getResult().getOutput().getB64Json().length());
80-
});
81-
}
82-
83-
@Test
84-
void streamImage() {
85-
this.contextRunner.run(context -> {
86-
OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class);
87-
88-
assertThat(imageModel).isNotNull();
89-
90-
OpenAiImageOptions options = OpenAiImageOptions.builder()
91-
.model(OpenAiImageApi.ImageModel.GPT_IMAGE_1_MINI.getValue())
92-
.stream(true)
93-
.partialImages(1)
94-
.build();
95-
96-
ImagePrompt prompt = new ImagePrompt("A blue square", options);
97-
Flux<ImageResponse> imageStream = imageModel.stream(prompt);
98-
99-
ImageResponse response = imageStream.blockFirst();
100-
101-
assertThat(response).isNotNull();
102-
assertThat(response.getResults()).hasSize(1);
103-
assertThat(response.getResult().getOutput().getB64Json()).isNotEmpty();
104-
logger.info("Received streaming image chunk");
105-
});
64+
this.contextRunner
65+
.withPropertyValues("spring.ai.openai.image.options.model=dall-e-2",
66+
"spring.ai.openai.image.options.response-format=b64_json")
67+
.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class))
68+
.run(context -> {
69+
OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class);
70+
ImagePrompt prompt = new ImagePrompt("A simple red circle");
71+
ImageResponse response = imageModel.call(prompt);
72+
73+
assertThat(response).isNotNull();
74+
assertThat(response.getResults()).hasSize(1);
75+
assertThat(response.getResult().getOutput().getB64Json()).isNotEmpty();
76+
77+
logger.info("Generated image with base64 length: "
78+
+ response.getResult().getOutput().getB64Json().length());
79+
});
10680
}
10781

10882
@Test

0 commit comments

Comments
 (0)