diff --git a/easy-agents-spring-boot-starter/pom.xml b/easy-agents-spring-boot-starter/pom.xml index 759acb7..12f30e9 100644 --- a/easy-agents-spring-boot-starter/pom.xml +++ b/easy-agents-spring-boot-starter/pom.xml @@ -51,6 +51,25 @@ easy-agents-bom + + + org.springframework.boot + spring-boot-test + test + + + + org.assertj + assertj-core + test + + + + junit + junit + test + + diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/deepseek/DeepSeekAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/deepseek/DeepSeekAutoConfiguration.java index d8e8078..a9513c1 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/deepseek/DeepSeekAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/deepseek/DeepSeekAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.llm.deepseek.DeepseekConfig; import com.easyagents.llm.deepseek.DeepseekChatModel; 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.context.annotation.Configuration; @@ -13,6 +14,7 @@ import org.springframework.context.annotation.Configuration; * DeepSeek */ @ConditionalOnClass(DeepseekChatModel.class) +@ConditionalOnProperty(prefix = "easy-agents.llm.deepseek", name = "api-key") @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(DeepSeekProperties.class) public class DeepSeekAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaAutoConfiguration.java index c8f1fd6..e010c3a 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.llm.ollama.OllamaChatModel; import com.easyagents.llm.ollama.OllamaChatConfig; 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.context.annotation.Configuration; @@ -15,6 +16,7 @@ import org.springframework.context.annotation.Configuration; * @since 2025-02-11 */ @ConditionalOnClass(OllamaChatModel.class) +@ConditionalOnProperty(prefix = "easy-agents.llm.ollama", name = "model") @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(OllamaProperties.class) public class OllamaAutoConfiguration { @@ -26,7 +28,7 @@ public class OllamaAutoConfiguration { config.setApiKey(properties.getApiKey()); config.setEndpoint(properties.getEndpoint()); config.setModel(properties.getModel()); - config.setThinkingEnabled(properties.getThink()); + config.setThinkingEnabled(Boolean.TRUE.equals(properties.getThink())); return new OllamaChatModel(config); } diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaProperties.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaProperties.java index d0aad5a..c2eee42 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaProperties.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/ollama/OllamaProperties.java @@ -12,7 +12,7 @@ public class OllamaProperties { private String model; private String endpoint = "http://localhost:11434"; private String apiKey; - private Boolean think; + private Boolean think = Boolean.FALSE; public String getModel() { return model; diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/openai/OpenAIAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/openai/OpenAIAutoConfiguration.java index a023d01..5f5752e 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/openai/OpenAIAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/openai/OpenAIAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.llm.openai.OpenAIChatModel; import com.easyagents.llm.openai.OpenAIChatConfig; 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.context.annotation.Configuration; @@ -15,6 +16,7 @@ import org.springframework.context.annotation.Configuration; * @since 2024-04-10 */ @ConditionalOnClass(OpenAIChatModel.class) +@ConditionalOnProperty(prefix = "easy-agents.llm.openai", name = "api-key") @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(OpenAIProperties.class) public class OpenAIAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/qwen/QwenAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/qwen/QwenAutoConfiguration.java index 6e65606..158082d 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/qwen/QwenAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/llm/qwen/QwenAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.llm.qwen.QwenChatModel; import com.easyagents.llm.qwen.QwenChatConfig; 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.context.annotation.Configuration; @@ -15,6 +16,7 @@ import org.springframework.context.annotation.Configuration; * @since 2024-04-10 */ @ConditionalOnClass(QwenChatModel.class) +@ConditionalOnProperty(prefix = "easy-agents.llm.qwen", name = "api-key") @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(QwenProperties.class) public class QwenAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/aliyun/AliyunAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/aliyun/AliyunAutoConfiguration.java index 09e8016..daad443 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/aliyun/AliyunAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/aliyun/AliyunAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.store.aliyun.AliyunVectorStore; import com.easyagents.store.aliyun.AliyunVectorStoreConfig; 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.context.annotation.Configuration; @@ -14,6 +15,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(AliyunVectorStore.class) +@ConditionalOnProperty(prefix = "easy-agents.store.aliyun", name = "endpoint") @EnableConfigurationProperties(AliyunProperties.class) public class AliyunAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/chroma/ChromaAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/chroma/ChromaAutoConfiguration.java index 4775cc0..1f41783 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/chroma/ChromaAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/chroma/ChromaAutoConfiguration.java @@ -17,9 +17,9 @@ package com.easyagents.spring.boot.store.chroma; import com.easyagents.store.chroma.ChromaVectorStore; import com.easyagents.store.chroma.ChromaVectorStoreConfig; -import org.springframework.beans.factory.annotation.Autowired; 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.context.annotation.Configuration; @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(ChromaVectorStore.class) +@ConditionalOnProperty(prefix = "easy-agents.store.chroma", name = "host") @EnableConfigurationProperties(ChromaProperties.class) public class ChromaAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/elasticsearch/ElasticSearchAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/elasticsearch/ElasticSearchAutoConfiguration.java index 5ee3dc3..235cb08 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/elasticsearch/ElasticSearchAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/elasticsearch/ElasticSearchAutoConfiguration.java @@ -21,6 +21,7 @@ import com.easyagents.store.elasticsearch.ElasticSearchVectorStoreConfig; import org.springframework.beans.factory.annotation.Autowired; 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.context.annotation.Configuration; @@ -31,6 +32,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(ElasticSearchVectorStore.class) +@ConditionalOnProperty(prefix = "easy-agents.store.elasticsearch", name = "server-url") @EnableConfigurationProperties(ElasticSearchProperties.class) public class ElasticSearchAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/opensearch/OpenSearchAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/opensearch/OpenSearchAutoConfiguration.java index 4167d2c..04f9b9a 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/opensearch/OpenSearchAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/opensearch/OpenSearchAutoConfiguration.java @@ -21,6 +21,7 @@ import org.opensearch.client.opensearch.OpenSearchClient; import org.springframework.beans.factory.annotation.Autowired; 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.context.annotation.Configuration; @@ -31,13 +32,14 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(OpenSearchVectorStore.class) +@ConditionalOnProperty(prefix = "easy-agents.store.opensearch", name = "server-url") @EnableConfigurationProperties(OpenSearchProperties.class) public class OpenSearchAutoConfiguration { @Bean @ConditionalOnMissingBean public OpenSearchVectorStore openSearchVectorStore(OpenSearchProperties properties, - @Autowired(required = false) OpenSearchClient client) { + @Autowired(required = false) OpenSearchClient client) { OpenSearchVectorStoreConfig config = new OpenSearchVectorStoreConfig(); config.setServerUrl(properties.getServerUrl()); config.setApiKey(properties.getApiKey()); diff --git a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/qcloud/QCloudStoreAutoConfiguration.java b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/qcloud/QCloudStoreAutoConfiguration.java index 3d85790..a8ed529 100644 --- a/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/qcloud/QCloudStoreAutoConfiguration.java +++ b/easy-agents-spring-boot-starter/src/main/java/com/easyagents/spring/boot/store/qcloud/QCloudStoreAutoConfiguration.java @@ -4,6 +4,7 @@ import com.easyagents.store.qcloud.QCloudVectorStore; import com.easyagents.store.qcloud.QCloudVectorStoreConfig; 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.context.annotation.Configuration; @@ -14,6 +15,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(QCloudVectorStore.class) +@ConditionalOnProperty(prefix = "easy-agents.store.qcloud", name = "host") @EnableConfigurationProperties(QCloudProperties.class) public class QCloudStoreAutoConfiguration { diff --git a/easy-agents-spring-boot-starter/src/test/java/com/easyagents/spring/boot/autoconfigure/StarterConditionalAutoConfigurationTest.java b/easy-agents-spring-boot-starter/src/test/java/com/easyagents/spring/boot/autoconfigure/StarterConditionalAutoConfigurationTest.java new file mode 100644 index 0000000..0d38fc0 --- /dev/null +++ b/easy-agents-spring-boot-starter/src/test/java/com/easyagents/spring/boot/autoconfigure/StarterConditionalAutoConfigurationTest.java @@ -0,0 +1,31 @@ +package com.easyagents.spring.boot.autoconfigure; + +import com.easyagents.llm.ollama.OllamaChatModel; +import com.easyagents.spring.boot.llm.ollama.OllamaAutoConfiguration; +import com.easyagents.spring.boot.rag.ingestion.RagIngestionAutoConfiguration; +import com.easyagents.spring.boot.store.opensearch.OpenSearchAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +public class StarterConditionalAutoConfigurationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(RagIngestionAutoConfiguration.class, OllamaAutoConfiguration.class, OpenSearchAutoConfiguration.class); + + @Test + public void shouldNotCreateOptionalBeansWithoutExplicitProperties() { + contextRunner.run(context -> { + Assert.assertTrue(context.containsBean("ragIngestionService")); + Assert.assertFalse(context.containsBean("ollamaLlm")); + Assert.assertFalse(context.containsBean("openSearchVectorStore")); + }); + } + + @Test + public void shouldCreateOllamaBeanWhenModelConfigured() { + contextRunner + .withPropertyValues("easy-agents.llm.ollama.model=qwen3:8b") + .run(context -> Assert.assertNotNull(context.getBean(OllamaChatModel.class))); + } +}