From 95cbd737397ad9c3e6b4b1a182f759d94b450b10 Mon Sep 17 00:00:00 2001 From: Nicolas Krier <7557886+nicolaskrier@users.noreply.github.com> Date: Sat, 20 Dec 2025 18:29:26 +0100 Subject: [PATCH] Polish MistralAiOcrAutoConfiguration - Add OCR model constant in SpringAIModelProperties - Use OCR model constant in MistralAiOcrAutoConfiguration - Add spring.ai.model.ocr property in additional-spring-configuration-metadata.json file - Add a unit test verify OCR model activation feature Signed-off-by: Nicolas Krier <7557886+nicolaskrier@users.noreply.github.com> --- ...itional-spring-configuration-metadata.json | 6 +++ .../MistralAiOcrAutoConfiguration.java | 4 +- .../MistralModelConfigurationTests.java | 46 +++++++++++++++---- .../ai/model/SpringAIModelProperties.java | 2 + 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json index aec436ff817..c127123564f 100644 --- a/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/auto-configurations/models/chat/client/spring-ai-autoconfigure-model-chat-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -47,6 +47,12 @@ "type": "java.lang.String", "description": "The primary ModerationModel to autoconfigure. If not set, each ModerationModel auto-configuration is enabled by default.", "defaultValue": "" + }, + { + "name": "spring.ai.model.ocr", + "type": "java.lang.String", + "description": "The primary OcrModel to autoconfigure. If not set, each OcrModel auto-configuration is enabled by default.", + "defaultValue": "" } ] } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java index 4a92b82b015..4ae003a1830 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.ai.model.mistralai.autoconfigure; import org.springframework.ai.mistralai.ocr.MistralOcrApi; +import org.springframework.ai.model.SpringAIModelProperties; import org.springframework.ai.model.SpringAIModels; import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.beans.factory.ObjectProvider; @@ -40,7 +41,8 @@ */ @AutoConfiguration(after = { RestClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class }) @ConditionalOnClass(MistralOcrApi.class) -@ConditionalOnProperty(name = "spring.ai.model.ocr", havingValue = SpringAIModels.MISTRAL, matchIfMissing = true) +@ConditionalOnProperty(name = SpringAIModelProperties.OCR_MODEL, havingValue = SpringAIModels.MISTRAL, + matchIfMissing = true) @EnableConfigurationProperties({ MistralAiCommonProperties.class, MistralAiOcrProperties.class }) public class MistralAiOcrAutoConfiguration { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java index 4e9e4dc6de3..a712e2ac406 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java @@ -21,6 +21,7 @@ import org.springframework.ai.mistralai.MistralAiChatModel; import org.springframework.ai.mistralai.MistralAiEmbeddingModel; import org.springframework.ai.mistralai.moderation.MistralAiModerationModel; +import org.springframework.ai.mistralai.ocr.MistralOcrApi; import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -32,20 +33,27 @@ * @author Ilayaperumal Gopinathan * @author Ricken Bazolo * @author Issam El-atif + * @author Nicolas Krier */ -public class MistralModelConfigurationTests { +class MistralModelConfigurationTests { - private final ApplicationContextRunner chatContextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)); + private final ApplicationContextRunner chatContextRunner = createApplicationContextRunner( + MistralAiChatAutoConfiguration.class); - private final ApplicationContextRunner embeddingContextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)); + private final ApplicationContextRunner embeddingContextRunner = createApplicationContextRunner( + MistralAiEmbeddingAutoConfiguration.class); - private final ApplicationContextRunner moderationContextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiModerationAutoConfiguration.class)); + private final ApplicationContextRunner moderationContextRunner = createApplicationContextRunner( + MistralAiModerationAutoConfiguration.class); + + private final ApplicationContextRunner ocrContextRunner = createApplicationContextRunner( + MistralAiOcrAutoConfiguration.class); + + private static ApplicationContextRunner createApplicationContextRunner(Class autoConfigurationClass) { + return new ApplicationContextRunner() + .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) + .withConfiguration(SpringAiTestAutoConfigurations.of(autoConfigurationClass)); + } @Test void chatModelActivation() { @@ -122,4 +130,22 @@ void moderationModelActivation() { }); } + @Test + void ocrModelActivation() { + this.ocrContextRunner.run(context -> { + assertThat(context).hasNotFailed(); + assertThat(context).hasSingleBean(MistralOcrApi.class); + }); + + this.ocrContextRunner.withPropertyValues("spring.ai.model.ocr=mistral").run(context -> { + assertThat(context).hasNotFailed(); + assertThat(context).hasSingleBean(MistralOcrApi.class); + }); + + this.ocrContextRunner.withPropertyValues("spring.ai.model.ocr=none").run(context -> { + assertThat(context).hasNotFailed(); + assertThat(context).doesNotHaveBean(MistralOcrApi.class); + }); + } + } diff --git a/spring-ai-model/src/main/java/org/springframework/ai/model/SpringAIModelProperties.java b/spring-ai-model/src/main/java/org/springframework/ai/model/SpringAIModelProperties.java index 77aa39ca263..3c2e227cfc9 100644 --- a/spring-ai-model/src/main/java/org/springframework/ai/model/SpringAIModelProperties.java +++ b/spring-ai-model/src/main/java/org/springframework/ai/model/SpringAIModelProperties.java @@ -40,4 +40,6 @@ private SpringAIModelProperties() { public static final String MODERATION_MODEL = MODEL_PREFIX + ".moderation"; + public static final String OCR_MODEL = MODEL_PREFIX + ".ocr"; + }