From 2f20064ee133fb1fdbaa43e8d7c56a2d17b05c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=AD=90=E9=BB=98?= <925456043@qq.com> Date: Wed, 25 Mar 2026 15:26:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=B6=E7=B4=A7=20starter=20=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=A3=85=E9=85=8D=E5=B9=B6=E4=BF=AE=E5=A4=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E8=BF=9E=E6=8E=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 llm 与 store 自动配置增加显式属性门槛 - 修复 ollama think 为空时的启动空指针 - 补充 starter 条件装配测试 --- easy-agents-spring-boot-starter/pom.xml | 19 ++++++++++++ .../deepseek/DeepSeekAutoConfiguration.java | 2 ++ .../llm/ollama/OllamaAutoConfiguration.java | 4 ++- .../boot/llm/ollama/OllamaProperties.java | 2 +- .../llm/openai/OpenAIAutoConfiguration.java | 2 ++ .../boot/llm/qwen/QwenAutoConfiguration.java | 2 ++ .../store/aliyun/AliyunAutoConfiguration.java | 2 ++ .../store/chroma/ChromaAutoConfiguration.java | 3 +- .../ElasticSearchAutoConfiguration.java | 2 ++ .../OpenSearchAutoConfiguration.java | 4 ++- .../qcloud/QCloudStoreAutoConfiguration.java | 2 ++ ...arterConditionalAutoConfigurationTest.java | 31 +++++++++++++++++++ 12 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 easy-agents-spring-boot-starter/src/test/java/com/easyagents/spring/boot/autoconfigure/StarterConditionalAutoConfigurationTest.java 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))); + } +}