diff --git a/document-readers/pdf-reader/src/main/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHints.java b/document-readers/pdf-reader/src/main/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHints.java new file mode 100644 index 00000000000..220160dd873 --- /dev/null +++ b/document-readers/pdf-reader/src/main/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHints.java @@ -0,0 +1,43 @@ +package org.springframework.ai.reader.pdf.aot; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +import java.io.IOException; +import java.util.Set; + +/** + * The PdfReaderRuntimeHints class is responsible for registering runtime hints for PDFBox + * resources. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class PdfReaderRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + try { + + var resolver = new PathMatchingResourcePatternResolver(); + + var patterns = Set.of("/org/apache/pdfbox/resources/glyphlist/zapfdingbats.txt", + "/org/apache/pdfbox/resources/glyphlist/glyphlist.txt", "/org/apache/fontbox/cmap/**", + "/org/apache/pdfbox/resources/afm/**", "/org/apache/pdfbox/resources/glyphlist/**", + "/org/apache/pdfbox/resources/icc/**", "/org/apache/pdfbox/resources/text/**", + "/org/apache/pdfbox/resources/ttf/**", "/org/apache/pdfbox/resources/version.properties"); + + for (var pattern : patterns) + for (var resourceMatch : resolver.getResources(pattern)) + hints.resources().registerResource(resourceMatch); + + } + catch (IOException e) { + throw new RuntimeException(e); + } + + } + +} diff --git a/document-readers/pdf-reader/src/main/resources/META-INF/spring/aot.factories b/document-readers/pdf-reader/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..88d1c90e8f4 --- /dev/null +++ b/document-readers/pdf-reader/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.reader.pdf.aot.PdfReaderRuntimeHints \ No newline at end of file diff --git a/document-readers/pdf-reader/src/test/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHintsTests.java b/document-readers/pdf-reader/src/test/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHintsTests.java new file mode 100644 index 00000000000..e924ab883dc --- /dev/null +++ b/document-readers/pdf-reader/src/test/java/org/springframework/ai/reader/pdf/aot/PdfReaderRuntimeHintsTests.java @@ -0,0 +1,36 @@ +package org.springframework.ai.reader.pdf.aot; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; + +import java.util.Set; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.resource; + +class PdfReaderRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + PdfReaderRuntimeHints pdfReaderRuntimeHints = new PdfReaderRuntimeHints(); + pdfReaderRuntimeHints.registerHints(runtimeHints, null); + + Assertions.assertThat(runtimeHints) + .matches(resource().forResource("/org/apache/pdfbox/resources/glyphlist/zapfdingbats.txt")); + Assertions.assertThat(runtimeHints) + .matches(resource().forResource("/org/apache/pdfbox/resources/glyphlist/glyphlist.txt")); + // Assertions.assertThat(runtimeHints).matches(resource().forResource("/org/apache/pdfbox/resources/afm/**")); + // Assertions.assertThat(runtimeHints).matches(resource().forResource("/org/apache/pdfbox/resources/glyphlist/**")); + // Assertions.assertThat(runtimeHints).matches(resource().forResource("/org/apache/pdfbox/resources/icc/**")); + // Assertions.assertThat(runtimeHints).matches(resource().forResource("/org/apache/pdfbox/resources/text/**")); + // Assertions.assertThat(runtimeHints).matches(resource().forResource("/org/apache/pdfbox/resources/ttf/**")); + Assertions.assertThat(runtimeHints) + .matches(resource().forResource("/org/apache/pdfbox/resources/version.properties")); + } + +} diff --git a/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHints.java b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHints.java new file mode 100644 index 00000000000..12eaa7cc474 --- /dev/null +++ b/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHints.java @@ -0,0 +1,45 @@ +package org.springframework.ai.bedrock.aot; + +import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi; +import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; +import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi; +import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; +import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi; +import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; +import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; + +/** + * The BedrockRuntimeHints class is responsible for registering runtime hints for Bedrock + * AI API classes. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class BedrockRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + var mcs = MemberCategory.values(); + for (var tr : findJsonAnnotatedClasses(Ai21Jurassic2ChatBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(CohereChatBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(CohereEmbeddingBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(Llama2ChatBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(TitanChatBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(TitanEmbeddingBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(AnthropicChatBedrockApi.class)) + hints.reflection().registerType(tr, mcs); + } + +} diff --git a/models/spring-ai-bedrock/src/main/resources/META-INF/spring/aot.factories b/models/spring-ai-bedrock/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..3b542896df5 --- /dev/null +++ b/models/spring-ai-bedrock/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.bedrock.aot.BedrockRuntimeHints \ No newline at end of file diff --git a/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHintsTests.java b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHintsTests.java new file mode 100644 index 00000000000..9f05da2a856 --- /dev/null +++ b/models/spring-ai-bedrock/src/test/java/org/springframework/ai/bedrock/aot/BedrockRuntimeHintsTests.java @@ -0,0 +1,43 @@ +package org.springframework.ai.bedrock.aot; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi; +import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; +import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi; +import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; +import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi; +import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; +import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; + +import java.util.List; +import java.util.Set; +import java.util.Arrays; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; + +class BedrockRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + BedrockRuntimeHints bedrockRuntimeHints = new BedrockRuntimeHints(); + bedrockRuntimeHints.registerHints(runtimeHints, null); + + List classList = Arrays.asList(Ai21Jurassic2ChatBedrockApi.class, CohereChatBedrockApi.class, + CohereEmbeddingBedrockApi.class, Llama2ChatBedrockApi.class, TitanChatBedrockApi.class, + TitanEmbeddingBedrockApi.class, AnthropicChatBedrockApi.class); + + for (Class aClass : classList) { + Set jsonAnnotatedClasses = findJsonAnnotatedClasses(aClass); + for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { + assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); + } + } + + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/aot/OllamaRuntimeHints.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/aot/OllamaRuntimeHints.java new file mode 100644 index 00000000000..f87ea541d59 --- /dev/null +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/aot/OllamaRuntimeHints.java @@ -0,0 +1,30 @@ +package org.springframework.ai.ollama.aot; + +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; + +/** + * The OllamaRuntimeHints class is responsible for registering runtime hints for Ollama AI + * API classes. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class OllamaRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + var mcs = MemberCategory.values(); + for (var tr : findJsonAnnotatedClasses(OllamaApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(OllamaOptions.class)) + hints.reflection().registerType(tr, mcs); + } + +} diff --git a/models/spring-ai-ollama/src/main/resources/META-INF/spring/aot.factories b/models/spring-ai-ollama/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..7529e30990c --- /dev/null +++ b/models/spring-ai-ollama/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.vertex.aot.OllamaRuntimeHints \ No newline at end of file diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/aot/OllamaRuntimeHintsTests.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/aot/OllamaRuntimeHintsTests.java new file mode 100644 index 00000000000..60446723b3b --- /dev/null +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/aot/OllamaRuntimeHintsTests.java @@ -0,0 +1,34 @@ +package org.springframework.ai.ollama.aot; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; + +import java.util.Set; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.*; + +class OllamaRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints(); + ollamaRuntimeHints.registerHints(runtimeHints, null); + + Set jsonAnnotatedClasses = findJsonAnnotatedClasses(OllamaApi.class); + for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { + assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); + } + + jsonAnnotatedClasses = findJsonAnnotatedClasses(OllamaOptions.class); + for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { + assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); + } + } + +} diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/aot/OpenAiRuntimeHints.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/aot/OpenAiRuntimeHints.java new file mode 100644 index 00000000000..e34c1ee1552 --- /dev/null +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/aot/OpenAiRuntimeHints.java @@ -0,0 +1,27 @@ +package org.springframework.ai.openai.aot; + +import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; + +/** + * The OpenAiRuntimeHints class is responsible for registering runtime hints for OpenAI + * API classes. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class OpenAiRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + var mcs = MemberCategory.values(); + for (var tr : findJsonAnnotatedClasses(OpenAiApi.class)) + hints.reflection().registerType(tr, mcs); + } + +} diff --git a/models/spring-ai-openai/src/main/resources/META-INF/spring/aot.factories b/models/spring-ai-openai/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..3d0043df69b --- /dev/null +++ b/models/spring-ai-openai/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.openai.aot.OpenAiRuntimeHints \ No newline at end of file diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/aot/OpenAiRuntimeHintsTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/aot/OpenAiRuntimeHintsTests.java new file mode 100644 index 00000000000..b5508553fd7 --- /dev/null +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/aot/OpenAiRuntimeHintsTests.java @@ -0,0 +1,28 @@ +package org.springframework.ai.openai.aot; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; + +import java.util.Set; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; + +class OpenAiRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + OpenAiRuntimeHints openAiRuntimeHints = new OpenAiRuntimeHints(); + openAiRuntimeHints.registerHints(runtimeHints, null); + + Set jsonAnnotatedClasses = findJsonAnnotatedClasses(OpenAiApi.class); + for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { + assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); + } + } + +} diff --git a/models/spring-ai-vertex-ai/src/main/java/org/springframework/ai/vertex/aot/VertexRuntimeHints.java b/models/spring-ai-vertex-ai/src/main/java/org/springframework/ai/vertex/aot/VertexRuntimeHints.java new file mode 100644 index 00000000000..e1510801eed --- /dev/null +++ b/models/spring-ai-vertex-ai/src/main/java/org/springframework/ai/vertex/aot/VertexRuntimeHints.java @@ -0,0 +1,27 @@ +package org.springframework.ai.vertex.aot; + +import org.springframework.ai.vertex.api.VertexAiApi; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; + +/** + * The VertexRuntimeHints class is responsible for registering runtime hints for Vertex AI + * API classes. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class VertexRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + var mcs = MemberCategory.values(); + for (var tr : findJsonAnnotatedClasses(VertexAiApi.class)) + hints.reflection().registerType(tr, mcs); + } + +} diff --git a/models/spring-ai-vertex-ai/src/main/resources/META-INF/spring/aot.factories b/models/spring-ai-vertex-ai/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..ffa4de50993 --- /dev/null +++ b/models/spring-ai-vertex-ai/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.vertex.aot.VertexRuntimeHints \ No newline at end of file diff --git a/models/spring-ai-vertex-ai/src/test/java/org/springframework/ai/vertex/aot/VertexRuntimeHintsTests.java b/models/spring-ai-vertex-ai/src/test/java/org/springframework/ai/vertex/aot/VertexRuntimeHintsTests.java new file mode 100644 index 00000000000..aafac0ad13e --- /dev/null +++ b/models/spring-ai-vertex-ai/src/test/java/org/springframework/ai/vertex/aot/VertexRuntimeHintsTests.java @@ -0,0 +1,27 @@ +package org.springframework.ai.vertex.aot; + +import org.junit.jupiter.api.Test; +import org.springframework.ai.vertex.api.VertexAiApi; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; + +import java.util.Set; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClasses; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; + +class VertexRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + VertexRuntimeHints vertexRuntimeHints = new VertexRuntimeHints(); + vertexRuntimeHints.registerHints(runtimeHints, null); + Set jsonAnnotatedClasses = findJsonAnnotatedClasses(VertexAiApi.class); + for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { + assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); + } + } + +} diff --git a/spring-ai-core/pom.xml b/spring-ai-core/pom.xml index 6f7090d8682..7a39a52d944 100644 --- a/spring-ai-core/pom.xml +++ b/spring-ai-core/pom.xml @@ -43,6 +43,14 @@ reactor-core + + + + org.springframework + spring-context + + + org.springframework spring-messaging diff --git a/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java b/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java new file mode 100644 index 00000000000..97bb90344d2 --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java @@ -0,0 +1,65 @@ +package org.springframework.ai.aot; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.type.filter.AnnotationTypeFilter; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Native runtime hints. See other modules for their respective native runtime hints. + * + * @author Josh Long + * @author Christian Tzolov + * @author Mark Pollack + */ +public class AiRuntimeHints implements RuntimeHintsRegistrar { + + static final Logger log = LoggerFactory.getLogger(AiRuntimeHints.class); + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + + for (var h : Set.of(new KnuddelsHints())) + h.registerHints(hints, classLoader); + + hints.resources().registerResource(new ClassPathResource("embedding/embedding-model-dimensions.properties")); + } + + static class KnuddelsHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + try { + hints.resources().registerResource(new ClassPathResource("/com/knuddels/jtokkit/cl100k_base.tiktoken")); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + } + + public static Set findJsonAnnotatedClasses(Class packageClass) { + var packageName = packageClass.getPackageName(); + var classPathScanningCandidateComponentProvider = new ClassPathScanningCandidateComponentProvider(false); + classPathScanningCandidateComponentProvider.addIncludeFilter(new AnnotationTypeFilter(JsonInclude.class)); + return classPathScanningCandidateComponentProvider.findCandidateComponents(packageName) + .stream() + .map(bd -> TypeReference.of(Objects.requireNonNull(bd.getBeanClassName()))) + .peek(tr -> { + if (log.isDebugEnabled()) + log.debug("registering [" + tr.getName() + ']'); + }) + .collect(Collectors.toUnmodifiableSet()); + } + +} diff --git a/spring-ai-core/src/main/resources/META-INF/spring/aot.factories b/spring-ai-core/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..301a12f7f11 --- /dev/null +++ b/spring-ai-core/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ + org.springframework.ai.aot.AiRuntimeHints \ No newline at end of file diff --git a/spring-ai-core/src/test/java/org/springframework/ai/aot/AiRuntimeHintsTests.java b/spring-ai-core/src/test/java/org/springframework/ai/aot/AiRuntimeHintsTests.java new file mode 100644 index 00000000000..9b7c7fdb827 --- /dev/null +++ b/spring-ai-core/src/test/java/org/springframework/ai/aot/AiRuntimeHintsTests.java @@ -0,0 +1,22 @@ +package org.springframework.ai.aot; + +import org.junit.jupiter.api.Test; +import org.springframework.aot.hint.RuntimeHints; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.*; + +import static org.assertj.core.api.Assertions.assertThat; + +class AiRuntimeHintsTests { + + @Test + void registerHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + AiRuntimeHints aiRuntimeHints = new AiRuntimeHints(); + aiRuntimeHints.registerHints(runtimeHints, null); + assertThat(runtimeHints).matches(resource().forResource("embedding/embedding-model-dimensions.properties")); + assertThat(runtimeHints).matches(resource().forResource("com/knuddels/jtokkit/cl100k_base.tiktoken")); + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java deleted file mode 100644 index 5952dd0314f..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.springframework.ai.autoconfigure; - -import com.fasterxml.jackson.annotation.JsonInclude; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi; -import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; -import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi; -import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi; -import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi; -import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; -import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi; -import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.ollama.api.OllamaOptions; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.vertex.api.VertexAiApi; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; -import org.springframework.aot.hint.TypeReference; -import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.type.filter.AnnotationTypeFilter; - -import java.io.IOException; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/*** - * Native hints - * - * @author Josh Long - */ -public class NativeHints implements RuntimeHintsRegistrar { - - static final Logger log = LoggerFactory.getLogger(NativeHints.class); - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - - for (var h : Set.of(new BedrockAiHints(), new VertexAiHints(), new OpenAiHints(), new PdfReaderHints(), - new KnuddelsHints(), new OllamaHints())) - h.registerHints(hints, classLoader); - - hints.resources().registerResource(new ClassPathResource("embedding/embedding-model-dimensions.properties")); - } - - private static Set findJsonAnnotatedClasses(Class packageClass) { - var packageName = packageClass.getPackageName(); - var classPathScanningCandidateComponentProvider = new ClassPathScanningCandidateComponentProvider(false); - classPathScanningCandidateComponentProvider.addIncludeFilter(new AnnotationTypeFilter(JsonInclude.class)); - return classPathScanningCandidateComponentProvider.findCandidateComponents(packageName) - .stream() - .map(bd -> TypeReference.of(Objects.requireNonNull(bd.getBeanClassName()))) - .peek(tr -> { - if (log.isDebugEnabled()) - log.debug("registering [" + tr.getName() + ']'); - }) - .collect(Collectors.toUnmodifiableSet()); - } - - static class VertexAiHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClasses(VertexAiApi.class)) - hints.reflection().registerType(tr, mcs); - } - - } - - static class OllamaHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClasses(OllamaApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(OllamaOptions.class)) - hints.reflection().registerType(tr, mcs); - } - - } - - static class BedrockAiHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClasses(Ai21Jurassic2ChatBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(CohereChatBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(CohereEmbeddingBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(Llama2ChatBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(TitanChatBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(TitanEmbeddingBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - for (var tr : findJsonAnnotatedClasses(AnthropicChatBedrockApi.class)) - hints.reflection().registerType(tr, mcs); - } - - } - - static class OpenAiHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClasses(OpenAiApi.class)) - hints.reflection().registerType(tr, mcs); - } - - } - - static class KnuddelsHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - hints.resources().registerResource(new ClassPathResource("/com/knuddels/jtokkit/cl100k_base.tiktoken")); - } - - } - - static class PdfReaderHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - try { - - var resolver = new PathMatchingResourcePatternResolver(); - - var patterns = Set.of("/org/apache/pdfbox/resources/glyphlist/zapfdingbats.txt", - "/org/apache/pdfbox/resources/glyphlist/glyphlist.txt", "/org/apache/fontbox/cmap/**", - "/org/apache/pdfbox/resources/afm/**", "/org/apache/pdfbox/resources/glyphlist/**", - "/org/apache/pdfbox/resources/icc/**", "/org/apache/pdfbox/resources/text/**", - "/org/apache/pdfbox/resources/ttf/**", "/org/apache/pdfbox/resources/version.properties"); - - for (var pattern : patterns) - for (var resourceMatch : resolver.getResources(pattern)) - hints.resources().registerResource(resourceMatch); - - } - catch (IOException e) { - throw new RuntimeException(e); - } - - } - - } - -} \ No newline at end of file diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java index 99768935c86..930a9957e59 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/anthropic/BedrockAnthropicChatAutoConfiguration.java @@ -17,10 +17,6 @@ package org.springframework.ai.autoconfigure.bedrock.anthropic; import com.fasterxml.jackson.databind.ObjectMapper; - -import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; - -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatClient; @@ -32,7 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Anthropic Chat Client. @@ -47,7 +43,6 @@ @EnableConfigurationProperties({ BedrockAnthropicChatProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockAnthropicChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockAnthropicChatAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java index ffeabeeee32..0cecdc277af 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereChatAutoConfiguration.java @@ -16,14 +16,10 @@ package org.springframework.ai.autoconfigure.bedrock.cohere; import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; - -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.cohere.BedrockCohereChatClient; import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi; -import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatRequest.LogitBias; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -31,7 +27,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Cohere Chat Client. @@ -44,7 +40,6 @@ @EnableConfigurationProperties({ BedrockCohereChatProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockCohereChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockCohereChatAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereEmbeddingAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereEmbeddingAutoConfiguration.java index 1477c60d680..2b8d8961772 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereEmbeddingAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/cohere/BedrockCohereEmbeddingAutoConfiguration.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.cohere.BedrockCohereEmbeddingClient; @@ -31,7 +30,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Cohere Embedding Client. @@ -44,7 +42,6 @@ @EnableConfigurationProperties({ BedrockCohereEmbeddingProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockCohereEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockCohereEmbeddingAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama2/BedrockLlama2ChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama2/BedrockLlama2ChatAutoConfiguration.java index 0d45de27279..7f37803f352 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama2/BedrockLlama2ChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/llama2/BedrockLlama2ChatAutoConfiguration.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.llama2.BedrockLlama2ChatClient; @@ -31,7 +30,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Llama2 Chat Client. @@ -46,7 +44,6 @@ @EnableConfigurationProperties({ BedrockLlama2ChatProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockLlama2ChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockLlama2ChatAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java index 539d87a88ce..94716a0753e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java @@ -16,9 +16,6 @@ package org.springframework.ai.autoconfigure.bedrock.titan; import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; - -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.titan.BedrockTitanChatClient; @@ -30,7 +27,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Titan Chat Client. @@ -43,7 +40,6 @@ @EnableConfigurationProperties({ BedrockTitanChatProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockTitanChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockTitanChatAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java index 001ac0fbe7a..a7d7986efa4 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration; import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties; import org.springframework.ai.bedrock.titan.BedrockTitanEmbeddingClient; @@ -31,7 +30,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; /** * {@link AutoConfiguration Auto-configuration} for Bedrock Titan Embedding Client. @@ -44,7 +42,6 @@ @EnableConfigurationProperties({ BedrockTitanEmbeddingProperties.class, BedrockAwsConnectionProperties.class }) @ConditionalOnProperty(prefix = BedrockTitanEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true") @Import(BedrockAwsConnectionConfiguration.class) -@ImportRuntimeHints(NativeHints.class) public class BedrockTitanEmbeddingAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java index 75859cc9046..044259c4be0 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java @@ -15,7 +15,6 @@ */ package org.springframework.ai.autoconfigure.ollama; -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.ai.ollama.OllamaEmbeddingClient; import org.springframework.ai.ollama.api.OllamaApi; @@ -25,7 +24,6 @@ import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.web.client.RestClient; /** @@ -38,7 +36,6 @@ @ConditionalOnClass(OllamaApi.class) @EnableConfigurationProperties({ OllamaChatProperties.class, OllamaEmbeddingProperties.class, OllamaConnectionProperties.class }) -@ImportRuntimeHints(NativeHints.class) public class OllamaAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java index b1c13a32379..cb8390c7728 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java @@ -16,9 +16,6 @@ package org.springframework.ai.autoconfigure.openai; -import java.util.List; - -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.model.ToolFunctionCallback; import org.springframework.ai.openai.OpenAiChatClient; @@ -32,17 +29,17 @@ import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.client.RestClient; +import java.util.List; + @AutoConfiguration(after = RestClientAutoConfiguration.class) @ConditionalOnClass(OpenAiApi.class) @EnableConfigurationProperties({ OpenAiConnectionProperties.class, OpenAiChatProperties.class, OpenAiEmbeddingProperties.class, OpenAiImageProperties.class }) -@ImportRuntimeHints(NativeHints.class) /** * @author Christian Tzolov */ diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiImageAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiImageAutoConfiguration.java index c4a8b2a8573..22ea1c0fc9e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiImageAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiImageAutoConfiguration.java @@ -15,7 +15,6 @@ */ package org.springframework.ai.autoconfigure.stabilityai; -import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.stabilityai.StabilityAiImageClient; import org.springframework.ai.stabilityai.api.StabilityAiApi; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -24,7 +23,6 @@ import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.web.client.RestClient; /** @@ -34,7 +32,6 @@ @AutoConfiguration(after = RestClientAutoConfiguration.class) @ConditionalOnClass(StabilityAiApi.class) @EnableConfigurationProperties({ StabilityAiProperties.class }) -@ImportRuntimeHints(NativeHints.class) public class StabilityAiImageAutoConfiguration { @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/VertexAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/VertexAiAutoConfiguration.java index 4749579a996..22ca248a653 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/VertexAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/VertexAiAutoConfiguration.java @@ -16,22 +16,19 @@ package org.springframework.ai.autoconfigure.vertexai; -import org.springframework.ai.autoconfigure.NativeHints; -import org.springframework.ai.vertex.api.VertexAiApi; -import org.springframework.ai.vertex.VertexAiEmbeddingClient; import org.springframework.ai.vertex.VertexAiChatClient; +import org.springframework.ai.vertex.VertexAiEmbeddingClient; +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.web.client.RestClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.web.client.RestClient; @AutoConfiguration(after = RestClientAutoConfiguration.class) @ConditionalOnClass(VertexAiApi.class) -@ImportRuntimeHints(NativeHints.class) @EnableConfigurationProperties({ VertexAiConnectionProperties.class, VertexAiChatProperties.class, VertexAiEmbeddingProperties.class }) public class VertexAiAutoConfiguration {