diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java index a7eee06fd3d..e9d4a3e04f2 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java @@ -49,6 +49,7 @@ * @author Stefan Vassilev * @author Thomas Vitale * @author Ilayaperumal Gopinathan + * @author lambochen */ @AutoConfiguration(after = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class }) @@ -75,6 +76,7 @@ public OpenAiImageModel openAiImageModel(OpenAiConnectionProperties commonProper .baseUrl(resolved.baseUrl()) .apiKey(new SimpleApiKey(resolved.apiKey())) .headers(resolved.headers()) + .imagesPath(imageProperties.getImagesPath()) .restClientBuilder(restClientBuilderProvider.getIfAvailable(RestClient::builder)) .responseErrorHandler(responseErrorHandler) .build(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageProperties.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageProperties.java index ff96b49ddfb..43b80f52f8e 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageProperties.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageProperties.java @@ -25,6 +25,7 @@ * OpenAI Image autoconfiguration properties. * * @author Thomas Vitale + * @author lambochen * @since 0.8.0 */ @ConfigurationProperties(OpenAiImageProperties.CONFIG_PREFIX) @@ -32,6 +33,10 @@ public class OpenAiImageProperties extends OpenAiParentProperties { public static final String CONFIG_PREFIX = "spring.ai.openai.image"; + public static final String DEFAULT_IMAGES_PATH = "v1/images/generations"; + + private String imagesPath = DEFAULT_IMAGES_PATH; + public static final String DEFAULT_IMAGE_MODEL = OpenAiImageApi.ImageModel.DALL_E_3.getValue(); /** @@ -48,4 +53,12 @@ public void setOptions(OpenAiImageOptions options) { this.options = options; } + public String getImagesPath() { + return imagesPath; + } + + public void setImagesPath(String imagesPath) { + this.imagesPath = imagesPath; + } + } diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java index c6e79b70b64..bd32d42d9f6 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java @@ -39,6 +39,7 @@ * OpenAI Image API. * * @see Images + * @author lambochen */ public class OpenAiImageApi { @@ -46,15 +47,18 @@ public class OpenAiImageApi { private final RestClient restClient; + private final String imagesPath; + /** * Create a new OpenAI Image API with the provided base URL. * @param baseUrl the base URL for the OpenAI API. * @param apiKey OpenAI apiKey. * @param headers the http headers to use. + * @param imagesPath the images path to use. * @param restClientBuilder the rest client builder to use. * @param responseErrorHandler the response error handler to use. */ - public OpenAiImageApi(String baseUrl, ApiKey apiKey, MultiValueMap headers, + public OpenAiImageApi(String baseUrl, ApiKey apiKey, MultiValueMap headers, String imagesPath, RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) { // @formatter:off @@ -69,6 +73,8 @@ public OpenAiImageApi(String baseUrl, ApiKey apiKey, MultiValueMap createImage(OpenAiImageRequest openAiImageRequest) { @@ -76,7 +82,7 @@ public ResponseEntity createImage(OpenAiImageRequest openAi Assert.hasLength(openAiImageRequest.prompt(), "Prompt cannot be empty."); return this.restClient.post() - .uri("v1/images/generations") + .uri(this.imagesPath) .body(openAiImageRequest) .retrieve() .toEntity(OpenAiImageResponse.class); @@ -163,12 +169,20 @@ public static class Builder { private ResponseErrorHandler responseErrorHandler = RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER; + private String imagesPath = "v1/images/generations"; + public Builder baseUrl(String baseUrl) { Assert.hasText(baseUrl, "baseUrl cannot be null or empty"); this.baseUrl = baseUrl; return this; } + public Builder imagesPath(String imagesPath) { + Assert.hasText(imagesPath, "imagesPath cannot be null or empty"); + this.imagesPath = imagesPath; + return this; + } + public Builder apiKey(ApiKey apiKey) { Assert.notNull(apiKey, "apiKey cannot be null"); this.apiKey = apiKey; @@ -201,7 +215,7 @@ public Builder responseErrorHandler(ResponseErrorHandler responseErrorHandler) { public OpenAiImageApi build() { Assert.notNull(this.apiKey, "apiKey must be set"); - return new OpenAiImageApi(this.baseUrl, this.apiKey, this.headers, this.restClientBuilder, + return new OpenAiImageApi(this.baseUrl, this.apiKey, this.headers, this.imagesPath, this.restClientBuilder, this.responseErrorHandler); }