StabilityAI Autoconfiguration improvements
* Add IT Test * Add starter to Spring AI bom
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -37,6 +37,7 @@
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-azure-store</module>
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-weaviate-store</module>
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-redis</module>
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-stability-ai</module>
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-neo4j-store</module>
|
||||
<module>spring-ai-spring-boot-starters/spring-ai-starter-postgresml-embedding</module>
|
||||
<module>spring-ai-docs</module>
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boog Starters -->
|
||||
<!-- Spring Boot Starters -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
|
||||
@@ -236,6 +236,12 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-stability-ai-spring-boot-starter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-transformers-spring-boot-starter</artifactId>
|
||||
|
||||
@@ -17,27 +17,40 @@ package org.springframework.ai.autoconfigure.stabilityai;
|
||||
|
||||
import org.springframework.ai.stabilityai.StabilityAiImageClient;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Pollack
|
||||
* @since 0.8.0
|
||||
*/
|
||||
|
||||
@AutoConfiguration(after = { RestClientAutoConfiguration.class })
|
||||
@ConditionalOnClass(StabilityAiApi.class)
|
||||
@EnableConfigurationProperties({ StabilityAiImageProperties.class })
|
||||
@EnableConfigurationProperties({ StabilityAiConnectionProperties.class, StabilityAiImageProperties.class })
|
||||
public class StabilityAiImageAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public StabilityAiApi stabilityAiApi(StabilityAiImageProperties stabilityAiImageProperties,
|
||||
RestClient.Builder restClientBuilder) {
|
||||
return new StabilityAiApi(stabilityAiImageProperties.getApiKey(), stabilityAiImageProperties.getBaseUrl(),
|
||||
stabilityAiImageProperties.getOptions().getModel(), restClientBuilder);
|
||||
public StabilityAiApi stabilityAiApi(StabilityAiConnectionProperties commonProperties,
|
||||
StabilityAiImageProperties imageProperties) {
|
||||
|
||||
String apiKey = StringUtils.hasText(imageProperties.getApiKey()) ? imageProperties.getApiKey()
|
||||
: commonProperties.getApiKey();
|
||||
|
||||
String baseUrl = StringUtils.hasText(imageProperties.getBaseUrl()) ? imageProperties.getBaseUrl()
|
||||
: commonProperties.getBaseUrl();
|
||||
|
||||
Assert.hasText(apiKey, "StabilityAI API key must be set");
|
||||
Assert.hasText(baseUrl, "StabilityAI base URL must be set");
|
||||
|
||||
return new StabilityAiApi(apiKey, imageProperties.getOptions().getModel(), baseUrl);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.ai.autoconfigure.stabilityai;
|
||||
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
@@ -30,7 +29,10 @@ public class StabilityAiImageProperties extends StabilityAiParentProperties {
|
||||
public static final String CONFIG_PREFIX = "spring.ai.stabilityai.image";
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private StabilityAiImageOptions options;
|
||||
private StabilityAiImageOptions options = StabilityAiImageOptions.builder().build(); // stable-diffusion-v1-6
|
||||
// is
|
||||
// default
|
||||
// model
|
||||
|
||||
public StabilityAiImageOptions getOptions() {
|
||||
return this.options;
|
||||
|
||||
@@ -16,15 +16,9 @@
|
||||
|
||||
package org.springframework.ai.autoconfigure.bedrock.cohere;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties;
|
||||
import org.springframework.ai.autoconfigure.openai.OpenAiConnectionProperties;
|
||||
import org.springframework.ai.autoconfigure.openai.OpenAiEmbeddingProperties;
|
||||
import org.springframework.ai.bedrock.cohere.BedrockCohereEmbeddingClient;
|
||||
import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi.CohereEmbeddingModel;
|
||||
import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi.CohereEmbeddingRequest;
|
||||
@@ -32,6 +26,9 @@ import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi.Coher
|
||||
import org.springframework.ai.embedding.EmbeddingResponse;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.springframework.ai.autoconfigure.stabilityai;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.springframework.ai.image.*;
|
||||
import org.springframework.ai.stabilityai.StyleEnum;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@EnabledIfEnvironmentVariable(named = "STABILITYAI_API_KEY", matches = ".*")
|
||||
public class StabilityAiAutoConfigurationIT {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.ai.stabilityai.image.api-key=" + System.getenv("STABILITYAI_API_KEY"))
|
||||
.withConfiguration(AutoConfigurations.of(StabilityAiImageAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void generate() {
|
||||
contextRunner.run(context -> {
|
||||
ImageClient imageClient = context.getBean(ImageClient.class);
|
||||
StabilityAiImageOptions imageOptions = StabilityAiImageOptions.builder()
|
||||
.withStylePreset(StyleEnum.PHOTOGRAPHIC)
|
||||
.build();
|
||||
|
||||
var instructions = """
|
||||
A light cream colored mini golden doodle.
|
||||
""";
|
||||
|
||||
ImagePrompt imagePrompt = new ImagePrompt(instructions, imageOptions);
|
||||
ImageResponse imageResponse = imageClient.call(imagePrompt);
|
||||
|
||||
ImageGeneration imageGeneration = imageResponse.getResult();
|
||||
Image image = imageGeneration.getOutput();
|
||||
|
||||
assertThat(image.getB64Json()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.autoconfigure.stabilityai;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Christian Tzolov
|
||||
* @since 0.8.0
|
||||
*/
|
||||
public class StabilityAiImagePropertiesTests {
|
||||
|
||||
@Test
|
||||
public void chatPropertiesTest() {
|
||||
|
||||
new ApplicationContextRunner().withPropertyValues(
|
||||
// @formatter:off
|
||||
"spring.ai.stabilityai.image.api-key=API_KEY",
|
||||
"spring.ai.stabilityai.image.base-url=ENDPOINT",
|
||||
"spring.ai.stabilityai.image.options.n=10",
|
||||
"spring.ai.stabilityai.image.options.model=MODEL_XYZ",
|
||||
"spring.ai.stabilityai.image.options.width=512",
|
||||
"spring.ai.stabilityai.image.options.height=256",
|
||||
"spring.ai.stabilityai.image.options.response-format=application/json",
|
||||
"spring.ai.stabilityai.image.options.n=4",
|
||||
"spring.ai.stabilityai.image.options.cfg-scale=7",
|
||||
"spring.ai.stabilityai.image.options.clip-guidance-preset=SIMPLE",
|
||||
"spring.ai.stabilityai.image.options.sampler=K_EULER",
|
||||
"spring.ai.stabilityai.image.options.seed=0",
|
||||
"spring.ai.stabilityai.image.options.steps=30",
|
||||
"spring.ai.stabilityai.image.options.style-preset=neon-punk"
|
||||
)
|
||||
// @formatter:on
|
||||
.withConfiguration(AutoConfigurations.of(StabilityAiImageAutoConfiguration.class))
|
||||
.run(context -> {
|
||||
var chatProperties = context.getBean(StabilityAiImageProperties.class);
|
||||
|
||||
assertThat(chatProperties.getBaseUrl()).isEqualTo("ENDPOINT");
|
||||
assertThat(chatProperties.getApiKey()).isEqualTo("API_KEY");
|
||||
assertThat(chatProperties.getOptions().getModel()).isEqualTo("MODEL_XYZ");
|
||||
|
||||
assertThat(chatProperties.getOptions().getWidth()).isEqualTo(512);
|
||||
assertThat(chatProperties.getOptions().getHeight()).isEqualTo(256);
|
||||
assertThat(chatProperties.getOptions().getResponseFormat()).isEqualTo("application/json");
|
||||
assertThat(chatProperties.getOptions().getN()).isEqualTo(4);
|
||||
assertThat(chatProperties.getOptions().getCfgScale()).isEqualTo(7);
|
||||
assertThat(chatProperties.getOptions().getClipGuidancePreset()).isEqualTo("SIMPLE");
|
||||
assertThat(chatProperties.getOptions().getSampler()).isEqualTo("K_EULER");
|
||||
assertThat(chatProperties.getOptions().getSeed()).isEqualTo(0);
|
||||
assertThat(chatProperties.getOptions().getSteps()).isEqualTo(30);
|
||||
assertThat(chatProperties.getOptions().getStylePreset()).isEqualTo("neon-punk");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user