Add activation/deactivation auto-config property to all Model clients

Property is of format `*.enabled=` and is true by default.
 Note: the Bedrock clients are disabled by default.

 - Add deactivation support for Vertex AI PaLM2 clients
 - Add deactivation support for Azure OpenAI clients
 - Add deactivation support for huggingface chat client
 - Add deactivation support for Ollama clients
 - Add deactivation support for OpenAI clients
 - Add deactivation support for Stability Image and PostgresML clients
 - Add deactivation support for ONNX Transformers Embedding client

 Resolves #363
This commit is contained in:
Christian Tzolov
2024-02-26 16:29:50 +01:00
parent 288ef449d6
commit 4e270ac75a
42 changed files with 557 additions and 50 deletions

View File

@@ -94,6 +94,7 @@ The prefix `spring.ai.azure.openai.chat` is the property prefix that configures
|====
| Property | Description | Default
| spring.ai.azure.openai.chat.enabled | Enable Azure OpenAI chat client. | true
| spring.ai.azure.openai.chat.options.model | * In use with Azure, this actually refers to the "Deployment Name" of your model, which you can find at https://oai.azure.com/portal. It's important to note that within an Azure OpenAI deployment, the "Deployment Name" is distinct from the model itself. The confusion around these terms stems from the intention to make the Azure OpenAI client library compatible with the original OpenAI endpoint. The deployment structures offered by Azure OpenAI and Sam Altman's OpenAI differ significantly. To clarify this distinction, we plan to rename this attribute to `deployment-name` in future updates.
Deployments model name to provide as part of this completions request.
| gpt-35-turbo

View File

@@ -55,8 +55,9 @@ The prefix `spring.ai.openai.image` is the property prefix that lets you configu
[cols="3,5,1"]
|====
| Property | Description | Default
| spring.ai.openai.chat.base-url | Optional overrides the spring.ai.openai.base-url to provide chat specific url | -
| spring.ai.openai.chat.api-key | Optional overrides the spring.ai.openai.api-key to provide chat specific api-key | -
| spring.ai.openai.image.enabled | Enable OpenAI image client. | true
| spring.ai.openai.image.base-url | Optional overrides the spring.ai.openai.base-url to provide chat specific url | -
| spring.ai.openai.image.api-key | Optional overrides the spring.ai.openai.api-key to provide chat specific api-key | -
| spring.ai.openai.image.options.n | The number of images to generate. Must be between 1 and 10. For dall-e-3, only n=1 is supported. | -
| spring.ai.openai.image.options.model | The model to use for image generation. | OpenAiImageApi.DEFAULT_IMAGE_MODEL
| spring.ai.openai.image.options.quality | The quality of the image that will be generated. HD creates images with finer details and greater consistency across the image. This parameter is only supported for dall-e-3. | -

View File

@@ -57,19 +57,20 @@ The prefix `spring.ai.stabilityai.image` is the property prefix that lets you co
|====
| Property | Description | Default
| `spring.ai.stabilityai.image.base-url` | Optional overrides the spring.ai.openai.base-url to provide a specific url | `https://api.stability.ai/v1`
| `spring.ai.stabilityai.image.api-key` | Optional overrides the spring.ai.openai.api-key to provide a specific api-key | -
| `spring.ai.stabilityai.image.option.n` | The number of images to be generated. Must be between 1 and 10. | 1
| `spring.ai.stabilityai.image.option.model` | The engine/model to use in Stability AI. The model is passed in the URL as a path parameter. | `stable-diffusion-v1-6`
| `spring.ai.stabilityai.image.option.width` | Width of the image to generate, in pixels, in an increment divisible by 64. Engine-specific dimension validation applies. | 512
| `spring.ai.stabilityai.image.option.height` | Height of the image to generate, in pixels, in an increment divisible by 64. Engine-specific dimension validation applies.| 512
| `spring.ai.stabilityai.image.option.responseFormat` | The format in which the generated images are returned. Must be "application/json" or "image/png". | -
| `spring.ai.stabilityai.image.option.cfg_scale` | The strictness level of the diffusion process adherence to the prompt text. Range: 0 to 35. | 7
| `spring.ai.stabilityai.image.option.clip_guidance_preset` | Pass in a style preset to guide the image model towards a particular style. This list of style presets is subject to change. | `NONE`
| `spring.ai.stabilityai.image.option.sampler` | Which sampler to use for the diffusion process. If this value is omitted, an appropriate sampler will be automatically selected. | -
| `spring.ai.stabilityai.image.option.seed` | Random noise seed (omit this option or use 0 for a random seed). Valid range: 0 to 4294967295. | 0
| `spring.ai.stabilityai.image.option.steps` | Number of diffusion steps to run. Valid range: 10 to 50. | 30
| `spring.ai.stabilityai.image.option.style_preset` | Pass in a style preset to guide the image model towards a particular style. This list of style presets is subject to change. | -
| spring.ai.stabilityai.image.enabled | Enable Stability AI image client. | true
| spring.ai.stabilityai.image.base-url | Optional overrides the spring.ai.openai.base-url to provide a specific url | `https://api.stability.ai/v1`
| spring.ai.stabilityai.image.api-key | Optional overrides the spring.ai.openai.api-key to provide a specific api-key | -
| spring.ai.stabilityai.image.option.n | The number of images to be generated. Must be between 1 and 10. | 1
| spring.ai.stabilityai.image.option.model | The engine/model to use in Stability AI. The model is passed in the URL as a path parameter. | `stable-diffusion-v1-6`
| spring.ai.stabilityai.image.option.width | Width of the image to generate, in pixels, in an increment divisible by 64. Engine-specific dimension validation applies. | 512
| spring.ai.stabilityai.image.option.height | Height of the image to generate, in pixels, in an increment divisible by 64. Engine-specific dimension validation applies.| 512
| spring.ai.stabilityai.image.option.responseFormat | The format in which the generated images are returned. Must be "application/json" or "image/png". | -
| spring.ai.stabilityai.image.option.cfg_scale | The strictness level of the diffusion process adherence to the prompt text. Range: 0 to 35. | 7
| spring.ai.stabilityai.image.option.clip_guidance_preset | Pass in a style preset to guide the image model towards a particular style. This list of style presets is subject to change. | `NONE`
| spring.ai.stabilityai.image.option.sampler | Which sampler to use for the diffusion process. If this value is omitted, an appropriate sampler will be automatically selected. | -
| spring.ai.stabilityai.image.option.seed | Random noise seed (omit this option or use 0 for a random seed). Valid range: 0 to 4294967295. | 0
| spring.ai.stabilityai.image.option.steps | Number of diffusion steps to run. Valid range: 10 to 50. | 30
| spring.ai.stabilityai.image.option.style_preset | Pass in a style preset to guide the image model towards a particular style. This list of style presets is subject to change. | -
|====

View File

@@ -60,6 +60,7 @@ NOTE: The `options` properties are based on the link:https://github.com/jmorganc
|====
| Property | Description | Default
| spring.ai.ollama.chat.enabled | Enable Ollama chat client. | true
| spring.ai.ollama.chat.model (DEPRECATED) | The name of the model to use. Deprecated use the `spring.ai.ollama.chat.options.model` instead | mistral
| spring.ai.ollama.chat.options.model | The name of the https://github.com/ollama/ollama?tab=readme-ov-file#model-library[supported models] to use. | mistral
| spring.ai.ollama.chat.options.numa | Whether to use NUMA. | false

View File

@@ -65,6 +65,7 @@ The prefix `spring.ai.openai.chat` is the property prefix that lets you configur
|====
| Property | Description | Default
| spring.ai.openai.chat.enabled | Enable OpenAI chat client. | true
| spring.ai.openai.chat.base-url | Optional overrides the spring.ai.openai.base-url to provide chat specific url | -
| spring.ai.openai.chat.api-key | Optional overrides the spring.ai.openai.api-key to provide chat specific api-key | -
| spring.ai.openai.chat.options.model | This is the OpenAI Chat model to use | `gpt-3.5-turbo` (the `gpt-3.5-turbo`, `gpt-4`, and `gpt-4-32k` point to the latest model versions)

View File

@@ -67,6 +67,7 @@ The prefix `spring.ai.vertex.ai.chat` is the property prefix that lets you confi
|====
| Property | Description | Default
| spring.ai.vertex.ai.chat.enabled | Enable Vertex AI PaLM API Chat client. | true
| spring.ai.vertex.ai.chat.model | This is the https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-chat[Vertex Chat model] to use | chat-bison-001
| spring.ai.vertex.ai.chat.options.temperature | Controls the randomness of the output. Values can range over [0.0,1.0], inclusive. A value closer to 1.0 will produce responses that are more varied, while a value closer to 0.0 will typically result in less surprising responses from the generative. This value specifies default to be used by the backend while making the call to the generative. | 0.7
| spring.ai.vertex.ai.chat.options.topK | The maximum number of tokens to consider when sampling. The generative uses combined Top-k and nucleus sampling. Top-k sampling considers the set of topK most probable tokens. | 20

View File

@@ -72,6 +72,7 @@ The prefix `spring.ai.azure.openai.embeddings` is the property prefix that confi
|====
| Property | Description | Default
| spring.ai.azure.openai.embedding.enabled | Enable Azure OpenAI embedding client. | true
| spring.ai.azure.openai.embedding.metadata-mode | Document content extraction mode | EMBED
| spring.ai.azure.openai.embedding.options.model | This is the value of the 'Deployment Name' as presented in the Azure AI Portal | text-embedding-ada-002
| spring.ai.azure.openai.embedding.options.user | An identifier for the caller or end user of the operation. This may be used for tracking or rate-limiting purposes. | -

View File

@@ -66,6 +66,7 @@ The prefix `spring.ai.ollama.embedding.options` is the property prefix that conf
|====
| Property | Description | Default
| spring.ai.ollama.embedding.enabled | Enable Ollama embedding client. | true
| spring.ai.ollama.embedding.model (DEPRECATED) | The name of the model to use. Deprecated use the `spring.ai.ollama.embedding.options.model` instead | mistral
| spring.ai.ollama.embedding.options.model | The name of the https://github.com/ollama/ollama?tab=readme-ov-file#model-library[supported models] to use. | mistral
| spring.ai.ollama.embedding.options.numa | Whether to use NUMA. | false

View File

@@ -127,6 +127,8 @@ The complete list of supported properties are:
[cols="3*"]
|===
| Property | Description | Default
| spring.ai.embedding.transformer.enabled | Enable the Transformer Embedding client. | true
| spring.ai.embedding.transformer.tokenizer.uri | URI of a pre-trained HuggingFaceTokenizer created by the ONNX engine (e.g. tokenizer.json). | onnx/all-MiniLM-L6-v2/tokenizer.json
| spring.ai.embedding.transformer.tokenizer.options | HuggingFaceTokenizer options such as '`addSpecialTokens`', '`modelMaxLength`', '`truncation`', '`padding`', '`maxLength`', '`stride`', '`padToMultipleOf`'. Leave empty to fallback to the defaults. | empty
| spring.ai.embedding.transformer.cache.enabled | Enable remote Resource caching. | true

View File

@@ -65,6 +65,8 @@ The prefix `spring.ai.openai.embedding` is property prefix that configures the `
[cols="3,5,1"]
|====
| Property | Description | Default
| spring.ai.openai.embedding.enabled | Enable OpenAI embedding client. | true
| spring.ai.openai.embedding.base-url | Optional overrides the spring.ai.openai.base-url to provide embedding specific url | -
| spring.ai.openai.embedding.api-key | Optional overrides the spring.ai.openai.api-key to provide embedding specific api-key | -
| spring.ai.openai.embedding.metadata-mode | Document content extraction mode. | EMBED

View File

@@ -49,6 +49,7 @@ The prefix `spring.ai.postgresml.embedding` is property prefix that configures t
[cols="3,5,1"]
|====
| Property | Description | Default
| spring.ai.postgresml.embedding.enabled | Enable PostgresML embedding client. | true
| spring.ai.postgresml.embedding.options.transformer | The Huggingface transformer model to use for the embedding. | distilbert-base-uncased
| spring.ai.postgresml.embedding.options.kwargs | Additional transformer specific options. | empty map
| spring.ai.postgresml.embedding.options.vectorType | PostgresML vector type to use for the embedding. Two options are supported: `PG_ARRAY` and `PG_VECTOR`. | PG_ARRAY

View File

@@ -49,7 +49,7 @@ dependencies {
TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.
=== Chat Properties
=== Embedding Properties
The prefix `spring.ai.vertex.ai` is used as the property prefix that lets you connect to VertexAI.
@@ -61,13 +61,14 @@ The prefix `spring.ai.vertex.ai` is used as the property prefix that lets you co
| spring.ai.vertex.ai.api-key | The API Key | -
|====
The prefix `spring.ai.vertex.ai.chat` is the property prefix that lets you configure the chat client implementation for VertexAI Chat.
The prefix `spring.ai.vertex.ai.embedding` is the property prefix that lets you configure the embedding client implementation for VertexAI Chat.
[cols="3,5,1"]
|====
| Property | Description | Default
| spring.ai.vertex.ai.chat.model | This is the https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-embeddings[Vertex Embedding model] to use | chat-bison-001
| spring.ai.vertex.ai.embedding.enabled | Enable Vertex AI PaLM API Embedding client. | true
| spring.ai.vertex.ai.embedding.model | This is the https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-embeddings[Vertex Embedding model] to use | embedding-gecko-001
|====
@@ -80,13 +81,13 @@ Add a `application.properties` file, under the `src/main/resources` directory, t
[source,application.properties]
----
spring.ai.vertex.ai.api-key=YOUR_API_KEY
spring.ai.vertex.ai.embedding.model=chat-bison-001
spring.ai.vertex.ai.embedding.model=embedding-gecko-001
----
TIP: replace the `api-key` with your VertexAI credentials.
This will create a `VertexAiEmbeddingClient` implementation that you can inject into your class.
Here is an example of a simple `@Controller` class that uses the chat client for text generations.
Here is an example of a simple `@Controller` class that uses the embedding client for text generations.
[source,java]
----
@@ -149,7 +150,7 @@ EmbeddingResponse embeddingResponse = embeddingClient
The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai/src/main/java/org/springframework/ai/vertex/api/VertexAiApi.java[VertexAiApi] provides is lightweight Java client for VertexAiApi Chat API.
Following class diagram illustrates the `VertexAiApi` chat interfaces and building blocks:
Following class diagram illustrates the `VertexAiApi` embedding interfaces and building blocks:
image::vertex-ai-chat-low-level-api.jpg[w=800,align="center"]

View File

@@ -26,6 +26,7 @@ import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingClient;
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.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.util.Assert;
@@ -50,6 +51,8 @@ public class AzureOpenAiAutoConfiguration {
}
@Bean
@ConditionalOnProperty(prefix = AzureOpenAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public AzureOpenAiChatClient azureOpenAiChatClient(OpenAIClient openAIClient,
AzureOpenAiChatProperties chatProperties) {
@@ -60,6 +63,8 @@ public class AzureOpenAiAutoConfiguration {
}
@Bean
@ConditionalOnProperty(prefix = AzureOpenAiEmbeddingProperties.CONFIG_PREFIX, name = "enabled",
havingValue = "true", matchIfMissing = true)
public AzureOpenAiEmbeddingClient azureOpenAiEmbeddingClient(OpenAIClient openAIClient,
AzureOpenAiEmbeddingProperties embeddingProperties) {
return new AzureOpenAiEmbeddingClient(openAIClient, embeddingProperties.getMetadataMode(),

View File

@@ -29,6 +29,11 @@ public class AzureOpenAiChatProperties {
private static final Double DEFAULT_TEMPERATURE = 0.7;
/**
* Enable Azure OpenAI chat client.
*/
private boolean enabled = true;
@NestedConfigurationProperty
private AzureOpenAiChatOptions options = AzureOpenAiChatOptions.builder()
.withModel(DEFAULT_CHAT_MODEL)
@@ -43,4 +48,12 @@ public class AzureOpenAiChatProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -26,6 +26,11 @@ public class AzureOpenAiEmbeddingProperties {
public static final String CONFIG_PREFIX = "spring.ai.azure.openai.embedding";
/**
* Enable Azure OpenAI embedding client.
*/
private boolean enabled = true;
private AzureOpenAiEmbeddingOptions options = AzureOpenAiEmbeddingOptions.builder()
.withModel("text-embedding-ada-002")
.build();
@@ -50,4 +55,12 @@ public class AzureOpenAiEmbeddingProperties {
this.metadataMode = metadataMode;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2023 the original author or authors.
* 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.
@@ -19,6 +19,8 @@ package org.springframework.ai.autoconfigure.huggingface;
import org.springframework.ai.huggingface.HuggingfaceChatClient;
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.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -27,13 +29,10 @@ import org.springframework.context.annotation.Bean;
@EnableConfigurationProperties(HuggingfaceChatProperties.class)
public class HuggingfaceChatAutoConfiguration {
private final HuggingfaceChatProperties huggingfaceChatProperties;
public HuggingfaceChatAutoConfiguration(HuggingfaceChatProperties huggingfaceChatProperties) {
this.huggingfaceChatProperties = huggingfaceChatProperties;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = HuggingfaceChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public HuggingfaceChatClient huggingfaceChatClient(HuggingfaceChatProperties huggingfaceChatProperties) {
return new HuggingfaceChatClient(huggingfaceChatProperties.getApiKey(), huggingfaceChatProperties.getUrl());
}

View File

@@ -11,6 +11,11 @@ public class HuggingfaceChatProperties {
private String url;
/**
* Enable Huggingface chat client.
*/
private boolean enabled = true;
public String getApiKey() {
return apiKey;
}
@@ -27,4 +32,12 @@ public class HuggingfaceChatProperties {
this.url = url;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.ollama.api.OllamaApi;
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.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -45,6 +46,9 @@ public class OllamaAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = OllamaChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi, OllamaChatProperties properties) {
return new OllamaChatClient(ollamaApi).withModel(properties.getModel())
@@ -53,6 +57,8 @@ public class OllamaAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = OllamaEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public OllamaEmbeddingClient ollamaEmbeddingClient(OllamaApi ollamaApi, OllamaEmbeddingProperties properties) {
return new OllamaEmbeddingClient(ollamaApi).withModel(properties.getModel())

View File

@@ -31,6 +31,11 @@ public class OllamaChatProperties {
public static final String CONFIG_PREFIX = "spring.ai.ollama.chat";
/**
* Enable Ollama chat client.
*/
private boolean enabled = true;
/**
* Client lever Ollama options. Use this property to configure generative temperature,
* topK and topP and alike parameters. The null values are ignored defaulting to the
@@ -51,4 +56,12 @@ public class OllamaChatProperties {
return this.options;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return this.enabled;
}
}

View File

@@ -31,6 +31,11 @@ public class OllamaEmbeddingProperties {
public static final String CONFIG_PREFIX = "spring.ai.ollama.embedding";
/**
* Enable Ollama embedding client.
*/
private boolean enabled = true;
/**
* Client lever Ollama options. Use this property to configure generative temperature,
* topK and topP and alike parameters. The null values are ignored defaulting to the
@@ -48,7 +53,15 @@ public class OllamaEmbeddingProperties {
}
public OllamaOptions getOptions() {
return options;
return this.options;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return this.enabled;
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.ai.openai.api.OpenAiImageApi;
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.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
@@ -53,6 +54,8 @@ public class OpenAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = OpenAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public OpenAiChatClient openAiChatClient(OpenAiConnectionProperties commonProperties,
OpenAiChatProperties chatProperties, RestClient.Builder restClientBuilder,
List<FunctionCallback> toolFunctionCallbacks, FunctionCallbackContext functionCallbackContext) {
@@ -77,6 +80,8 @@ public class OpenAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = OpenAiEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public EmbeddingClient openAiEmbeddingClient(OpenAiConnectionProperties commonProperties,
OpenAiEmbeddingProperties embeddingProperties, RestClient.Builder restClientBuilder) {
@@ -96,6 +101,8 @@ public class OpenAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = OpenAiImageProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public OpenAiImageClient openAiImageClient(OpenAiConnectionProperties commonProperties,
OpenAiImageProperties imageProperties, RestClient.Builder restClientBuilder) {
String apiKey = StringUtils.hasText(imageProperties.getApiKey()) ? imageProperties.getApiKey()

View File

@@ -29,6 +29,11 @@ public class OpenAiChatProperties extends OpenAiParentProperties {
private static final Double DEFAULT_TEMPERATURE = 0.7;
/**
* Enable OpenAI chat client.
*/
private boolean enabled = true;
@NestedConfigurationProperty
private OpenAiChatOptions options = OpenAiChatOptions.builder()
.withModel(DEFAULT_CHAT_MODEL)
@@ -43,4 +48,12 @@ public class OpenAiChatProperties extends OpenAiParentProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2023 the original author or authors.
* 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.
@@ -28,6 +28,11 @@ public class OpenAiEmbeddingProperties extends OpenAiParentProperties {
public static final String DEFAULT_EMBEDDING_MODEL = "text-embedding-ada-002";
/**
* Enable OpenAI embedding client.
*/
private boolean enabled = true;
private MetadataMode metadataMode = MetadataMode.EMBED;
@NestedConfigurationProperty
@@ -36,7 +41,7 @@ public class OpenAiEmbeddingProperties extends OpenAiParentProperties {
.build();
public OpenAiEmbeddingOptions getOptions() {
return options;
return this.options;
}
public void setOptions(OpenAiEmbeddingOptions options) {
@@ -44,11 +49,19 @@ public class OpenAiEmbeddingProperties extends OpenAiParentProperties {
}
public MetadataMode getMetadataMode() {
return metadataMode;
return this.metadataMode;
}
public void setMetadataMode(MetadataMode metadataMode) {
this.metadataMode = metadataMode;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -31,6 +31,11 @@ public class OpenAiImageProperties extends OpenAiParentProperties {
public static final String CONFIG_PREFIX = "spring.ai.openai.image";
/**
* Enable OpenAI Image client.
*/
private boolean enabled = true;
/**
* Options for OpenAI Image API.
*/
@@ -45,4 +50,12 @@ public class OpenAiImageProperties extends OpenAiParentProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2024 - 2024 the original author or authors.
* Copyright 2024-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.
@@ -20,6 +20,7 @@ import org.springframework.ai.postgresml.PostgresMlEmbeddingClient;
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.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -38,6 +39,8 @@ public class PostgresMlAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = PostgresMlEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public EmbeddingClient postgresMlEmbeddingClient(JdbcTemplate jdbcTemplate,
PostgresMlEmbeddingProperties embeddingProperties) {

View File

@@ -35,6 +35,11 @@ public class PostgresMlEmbeddingProperties {
public static final String CONFIG_PREFIX = "spring.ai.postgresml.embedding";
/**
* Enable Postgres ML embedding client.
*/
private boolean enabled = true;
@NestedConfigurationProperty
private PostgresMlEmbeddingOptions options = PostgresMlEmbeddingOptions.builder()
.withTransformer(PostgresMlEmbeddingClient.DEFAULT_TRANSFORMER_MODEL)
@@ -57,4 +62,12 @@ public class PostgresMlEmbeddingProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -20,6 +20,7 @@ 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.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -28,9 +29,9 @@ import org.springframework.util.StringUtils;
/**
* @author Mark Pollack
* @author Christian Tzolov
* @since 0.8.0
*/
@AutoConfiguration(after = { RestClientAutoConfiguration.class })
@ConditionalOnClass(StabilityAiApi.class)
@EnableConfigurationProperties({ StabilityAiConnectionProperties.class, StabilityAiImageProperties.class })
@@ -55,6 +56,8 @@ public class StabilityAiImageAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = StabilityAiImageProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public StabilityAiImageClient stabilityAiImageClient(StabilityAiApi stabilityAiApi,
StabilityAiImageProperties stabilityAiImageProperties) {
return new StabilityAiImageClient(stabilityAiApi, stabilityAiImageProperties.getOptions());

View File

@@ -21,6 +21,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
/**
* @author Mark Pollack
* @author Christian Tzolov
* @since 0.8.0
*/
@ConfigurationProperties(StabilityAiImageProperties.CONFIG_PREFIX)
@@ -28,6 +29,11 @@ public class StabilityAiImageProperties extends StabilityAiParentProperties {
public static final String CONFIG_PREFIX = "spring.ai.stabilityai.image";
/**
* Enable Stability Image client.
*/
private boolean enabled = true;
@NestedConfigurationProperty
private StabilityAiImageOptions options = StabilityAiImageOptions.builder().build(); // stable-diffusion-v1-6
// is
@@ -42,4 +48,12 @@ public class StabilityAiImageProperties extends StabilityAiParentProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.ai.transformers.TransformersEmbeddingClient;
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.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -37,6 +38,8 @@ public class TransformersEmbeddingClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = TransformersEmbeddingClientProperties.CONFIG_PREFIX, name = "enabled",
havingValue = "true", matchIfMissing = true)
public EmbeddingClient embeddingClient(TransformersEmbeddingClientProperties properties) {
TransformersEmbeddingClient embeddingClient = new TransformersEmbeddingClient(properties.getMetadataMode());

View File

@@ -43,6 +43,19 @@ public class TransformersEmbeddingClientProperties {
"spring-ai-onnx-generative")
.getAbsolutePath();
/**
* Enable the Transformer Embedding client.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* Configurations for the {@link HuggingFaceTokenizer} used to convert sentences into
* tokens.

View File

@@ -22,6 +22,7 @@ import org.springframework.ai.vertex.api.VertexAiApi;
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.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -45,12 +46,16 @@ public class VertexAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = VertexAiChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public VertexAiChatClient vertexAiChatClient(VertexAiApi vertexAiApi, VertexAiChatProperties chatProperties) {
return new VertexAiChatClient(vertexAiApi, chatProperties.getOptions());
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = VertexAiEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public VertexAiEmbeddingClient vertexAiEmbeddingClient(VertexAiApi vertexAiApi) {
return new VertexAiEmbeddingClient(vertexAiApi);
}

View File

@@ -25,6 +25,11 @@ public class VertexAiChatProperties {
public static final String CONFIG_PREFIX = "spring.ai.vertex.ai.chat";
/**
* Enable Vertex AI PaLM API chat client.
*/
private boolean enabled = true;
/**
* Vertex AI PaLM API generative name. Defaults to chat-bison-001
*/
@@ -56,4 +61,12 @@ public class VertexAiChatProperties {
this.options = options;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -24,6 +24,11 @@ public class VertexAiEmbeddingProperties {
public static final String CONFIG_PREFIX = "spring.ai.vertex.ai.embedding";
/**
* Enable Vertex AI PaLM API embedding client.
*/
private boolean enabled = true;
/**
* Vertex AI PaLM API embedding generative name. Defaults to embedding-gecko-001.
*/
@@ -37,4 +42,12 @@ public class VertexAiEmbeddingProperties {
this.model = model;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@@ -123,4 +123,42 @@ public class AzureOpenAiAutoConfigurationIT {
});
}
@Test
public void chatActivation() {
// Disable the chat auto-configuration.
contextRunner.withPropertyValues("spring.ai.azure.openai.chat.enabled=false").run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isEmpty();
});
// The chat auto-configuration is enabled by default.
contextRunner.run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isNotEmpty();
});
// Explicitly enable the chat auto-configuration.
contextRunner.withPropertyValues("spring.ai.azure.openai.chat.enabled=true").run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiChatClient.class)).isNotEmpty();
});
}
@Test
public void embeddingActivation() {
// Disable the embedding auto-configuration.
contextRunner.withPropertyValues("spring.ai.azure.openai.embedding.enabled=false").run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingClient.class)).isEmpty();
});
// The embedding auto-configuration is enabled by default.
contextRunner.run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingClient.class)).isNotEmpty();
});
// Explicitly enable the embedding auto-configuration.
contextRunner.withPropertyValues("spring.ai.azure.openai.embedding.enabled=true").run(context -> {
assertThat(context.getBeansOfType(AzureOpenAiEmbeddingClient.class)).isNotEmpty();
});
}
}

View File

@@ -50,9 +50,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@Disabled("For manual smoke testing only.")
@Testcontainers
public class OllamaAutoConfigurationIT {
public class OllamaChatAutoConfigurationIT {
private static final Log logger = LogFactory.getLog(OllamaAutoConfigurationIT.class);
private static final Log logger = LogFactory.getLog(OllamaChatAutoConfigurationIT.class);
private static String MODEL_NAME = "mistral";
@@ -120,4 +120,22 @@ public class OllamaAutoConfigurationIT {
});
}
@Test
void chatActivation() {
contextRunner.withPropertyValues("spring.ai.ollama.chat.enabled=false").run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaChatClient.class)).isEmpty();
});
contextRunner.run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty();
});
contextRunner.withPropertyValues("spring.ai.ollama.chat.enabled=true").run(context -> {
assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty();
});
}
}

View File

@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Christian Tzolov
* @since 0.8.0
*/
public class OllamaAutoConfigurationTests {
public class OllamaChatAutoConfigurationTests {
@Test
public void propertiesTest() {

View File

@@ -16,22 +16,23 @@
package org.springframework.ai.autoconfigure.ollama;
import java.io.IOException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.ai.ollama.OllamaEmbeddingClient;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.IOException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -78,4 +79,23 @@ public class OllamaEmbeddingAutoConfigurationIT {
});
}
@Test
void embeddingActivation() {
contextRunner.withPropertyValues("spring.ai.ollama.embedding.enabled=false").run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isEmpty();
});
contextRunner.run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isNotEmpty();
});
contextRunner.withPropertyValues("spring.ai.ollama.embedding.enabled=true").run(context -> {
assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isNotEmpty();
});
}
}

View File

@@ -20,6 +20,9 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.OpenAiEmbeddingClient;
import org.springframework.ai.openai.OpenAiImageClient;
import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ResponseFormat;
import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoice;
import org.springframework.ai.openai.api.OpenAiApi.FunctionTool.Type;
@@ -348,4 +351,94 @@ public class OpenAiPropertiesTests {
});
}
@Test
void embeddingActivation() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.embedding.enabled=false")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiEmbeddingClient.class)).isEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiEmbeddingClient.class)).isNotEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.embedding.enabled=true")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiEmbeddingClient.class)).isNotEmpty();
});
}
@Test
void chatActivation() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.chat.enabled=false")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiChatClient.class)).isEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiChatClient.class)).isNotEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.chat.enabled=true")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiChatClient.class)).isNotEmpty();
});
}
@Test
void imageActivation() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.image.enabled=false")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiImageClient.class)).isEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiImageClient.class)).isNotEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL",
"spring.ai.openai.image.enabled=true")
.withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class, OpenAiAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(OpenAiImageClient.class)).isNotEmpty();
});
}
}

View File

@@ -84,4 +84,31 @@ public class PostgresMlAutoConfigurationIT {
});
}
@Test
void embeddingActivation() {
new ApplicationContextRunner().withBean(JdbcTemplate.class, () -> jdbcTemplate)
.withConfiguration(AutoConfigurations.of(PostgresMlAutoConfiguration.class))
.withPropertyValues("spring.ai.postgresml.embedding.enabled=false")
.run(context -> {
assertThat(context.getBeansOfType(PostgresMlEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(PostgresMlEmbeddingClient.class)).isEmpty();
});
new ApplicationContextRunner().withBean(JdbcTemplate.class, () -> jdbcTemplate)
.withConfiguration(AutoConfigurations.of(PostgresMlAutoConfiguration.class))
.withPropertyValues("spring.ai.postgresml.embedding.enabled=true")
.run(context -> {
assertThat(context.getBeansOfType(PostgresMlEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(PostgresMlEmbeddingClient.class)).isNotEmpty();
});
new ApplicationContextRunner().withBean(JdbcTemplate.class, () -> jdbcTemplate)
.withConfiguration(AutoConfigurations.of(PostgresMlAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(PostgresMlEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(PostgresMlEmbeddingClient.class)).isNotEmpty();
});
}
}

View File

@@ -17,10 +17,8 @@
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.ai.stabilityai.StabilityAiImageClient;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -37,9 +35,9 @@ public class StabilityAiImagePropertiesTests {
new ApplicationContextRunner().withPropertyValues(
// @formatter:off
"spring.ai.stabilityai.image.api-key=API_KEY",
"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.n=10",
"spring.ai.stabilityai.image.options.model=MODEL_XYZ",
"spring.ai.stabilityai.image.options.width=512",
"spring.ai.stabilityai.image.options.height=256",
@@ -74,4 +72,39 @@ public class StabilityAiImagePropertiesTests {
});
}
@Test
void stabilityImageActivation() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.stabilityai.image.api-key=API_KEY",
"spring.ai.stabilityai.image.base-url=ENDPOINT", "spring.ai.stabilityai.image.enabled=false")
.withConfiguration(AutoConfigurations.of(StabilityAiImageAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(StabilityAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(StabilityAiImageClient.class)).isEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.stabilityai.image.api-key=API_KEY",
"spring.ai.stabilityai.image.base-url=ENDPOINT")
.withConfiguration(AutoConfigurations.of(StabilityAiImageAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(StabilityAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(StabilityAiImageClient.class)).isNotEmpty();
});
new ApplicationContextRunner()
.withPropertyValues("spring.ai.stabilityai.image.api-key=API_KEY",
"spring.ai.stabilityai.image.base-url=ENDPOINT", "spring.ai.stabilityai.image.enabled=true")
.withConfiguration(AutoConfigurations.of(StabilityAiImageAutoConfiguration.class))
.run(context -> {
assertThat(context.getBeansOfType(StabilityAiImageProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(StabilityAiImageClient.class)).isNotEmpty();
});
}
}

View File

@@ -89,4 +89,23 @@ public class TransformersEmbeddingClientAutoConfigurationIT {
});
}
@Test
void embeddingActivation() {
contextRunner.withPropertyValues("spring.ai.embedding.transformer.enabled=false").run(context -> {
assertThat(context.getBeansOfType(TransformersEmbeddingClientProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(TransformersEmbeddingClient.class)).isEmpty();
});
contextRunner.withPropertyValues("spring.ai.embedding.transformer.enabled=true").run(context -> {
assertThat(context.getBeansOfType(TransformersEmbeddingClientProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(TransformersEmbeddingClient.class)).isNotEmpty();
});
contextRunner.run(context -> {
assertThat(context.getBeansOfType(TransformersEmbeddingClientProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(TransformersEmbeddingClient.class)).isNotEmpty();
});
}
}

View File

@@ -24,8 +24,8 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.ai.vertex.VertexAiEmbeddingClient;
import org.springframework.ai.vertex.VertexAiChatClient;
import org.springframework.ai.vertex.VertexAiEmbeddingClient;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -73,4 +73,48 @@ public class VertexAiAutoConfigurationIT {
});
}
@Test
public void embeddingActivation() {
// Disable the embedding auto-configuration.
contextRunner.withPropertyValues("spring.ai.vertex.ai.embedding.enabled=false").run(context -> {
assertThat(context.getBeansOfType(VertexAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiEmbeddingClient.class)).isEmpty();
});
// The embedding auto-configuration is enabled by default.
contextRunner.run(context -> {
assertThat(context.getBeansOfType(VertexAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiEmbeddingClient.class)).isNotEmpty();
});
// Explicitly enable the embedding auto-configuration.
contextRunner.withPropertyValues("spring.ai.vertex.ai.embedding.enabled=true").run(context -> {
assertThat(context.getBeansOfType(VertexAiEmbeddingProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiEmbeddingClient.class)).isNotEmpty();
});
}
@Test
public void chatActivation() {
// Disable the chat auto-configuration.
contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=false").run(context -> {
assertThat(context.getBeansOfType(VertexAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiChatClient.class)).isEmpty();
});
// The chat auto-configuration is enabled by default.
contextRunner.run(context -> {
assertThat(context.getBeansOfType(VertexAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiChatClient.class)).isNotEmpty();
});
// Explicitly enable the chat auto-configuration.
contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=true").run(context -> {
assertThat(context.getBeansOfType(VertexAiChatProperties.class)).isNotEmpty();
assertThat(context.getBeansOfType(VertexAiChatClient.class)).isNotEmpty();
});
}
}