diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java index 9d5bd857a8..b75801cb56 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java @@ -17,28 +17,23 @@ import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.MongoDBAtlasVectorStore; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.ai.vectorstore.convert.MimeTypeConverters; 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.data.mongo.MongoDataAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; -import org.springframework.util.MimeType; import org.springframework.util.StringUtils; -import java.util.Arrays; - /** * @author Eddú Meléndez * @author Christian Tzolov * @since 1.0.0 */ -@AutoConfiguration(after = MongoDataAutoConfiguration.class) +@AutoConfiguration(before = MongoDataAutoConfiguration.class) @ConditionalOnClass({ MongoDBAtlasVectorStore.class, EmbeddingModel.class, MongoTemplate.class }) @EnableConfigurationProperties(MongoDBAtlasVectorStoreProperties.class) public class MongoDBAtlasVectorStoreAutoConfiguration { @@ -65,37 +60,8 @@ MongoDBAtlasVectorStore vectorStore(MongoTemplate mongoTemplate, EmbeddingModel } @Bean - public Converter mimeTypeToStringConverter() { - return new Converter() { - @Override - public String convert(MimeType source) { - return source.toString(); - } - }; - } - - @Bean - public Converter stringToMimeTypeConverter() { - return new Converter() { - @Override - public MimeType convert(String source) { - return MimeType.valueOf(source); - } - }; - } - - @Bean - public BeanPostProcessor mongoCustomConversionsPostProcessor() { - return new BeanPostProcessor() { - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof MongoCustomConversions) { - return new MongoCustomConversions( - Arrays.asList(mimeTypeToStringConverter(), stringToMimeTypeConverter())); - } - return bean; - } - }; + public MongoCustomConversions mongoCustomConversions() { + return new MongoCustomConversions(MimeTypeConverters.getConvertersToRegister()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfigurationIT.java index c77b97579d..4399d646ad 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfigurationIT.java @@ -16,6 +16,7 @@ package org.springframework.ai.autoconfigure.vectorstore.mongo; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; import org.springframework.ai.document.Document; @@ -42,6 +43,7 @@ * @author Eddú Meléndez */ @Testcontainers +@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") class MongoDBAtlasVectorStoreAutoConfigurationIT { @Container diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/MimeTypeConverters.java b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/MimeTypeConverters.java new file mode 100644 index 0000000000..2d99fcd57f --- /dev/null +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/MimeTypeConverters.java @@ -0,0 +1,72 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.vectorstore.convert; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.ReadingConverter; +import org.springframework.data.convert.WritingConverter; +import org.springframework.util.MimeType; + +import java.util.List; + +import static java.util.Arrays.asList; + +/** + * Provides converters for {@link org.springframework.util.MimeType } for use with Mongo. + * + * @author Ross Lawley + * @since 1.0.0 + */ +public class MimeTypeConverters { + + /** + * @return the converters to be registered. + */ + public static List> getConvertersToRegister() { + return asList(MimeTypeReadConverter.INSTANCE, MimeTypeWriteConverter.INSTANCE); + } + + /** + * Simple singleton to convert {@link String}s to their {@link MimeType} + * representation. + */ + @ReadingConverter + enum MimeTypeReadConverter implements Converter { + + INSTANCE; + + public MimeType convert(String source) { + return MimeType.valueOf(source); + } + + } + + /** + * Simple singleton to convert {@link MimeType}s to their {@link String} + * representation. + */ + @WritingConverter + enum MimeTypeWriteConverter implements Converter { + + INSTANCE; + + public String convert(MimeType source) { + return source.toString(); + } + + } + +} diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/package-info.java b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/package-info.java new file mode 100644 index 0000000000..0f36c7a3bf --- /dev/null +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/convert/package-info.java @@ -0,0 +1,17 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@org.springframework.lang.NonNullApi +package org.springframework.ai.vectorstore.convert; diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasContainer.java b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasContainer.java index 60dfec22f2..8760de3cf8 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasContainer.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasContainer.java @@ -23,7 +23,7 @@ public class MongoDBAtlasContainer extends GenericContainer { public MongoDBAtlasContainer() { - super("mongodb/atlas:v1.15.1"); + super("mongodb/atlas:v1.24.0"); withPrivilegedMode(true); withCommand("/bin/bash", "-c", "atlas deployments setup local-test --type local --port 27778 --bindIpAll --username root --password root --force && tail -f /dev/null"); diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java index e804ff4fdb..533efe6386 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java @@ -15,20 +15,21 @@ */ package org.springframework.ai.vectorstore; -import com.mongodb.client.MongoClient; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.vectorstore.convert.MimeTypeConverters; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -42,9 +43,10 @@ /** * @author Chris Smith + * @author Ross Lawley */ @Testcontainers -@Disabled("Disabled due to https://github.com/spring-projects/spring-ai/issues/698") +@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") class MongoDBAtlasVectorStoreIT { @Container @@ -191,6 +193,17 @@ void searchWithFilters() { @EnableAutoConfiguration public static class TestApplication { + @Value("${spring.data.mongodb.uri}") + String mongoUri; + + @Value("${spring.data.mongodb.database}") + String databaseName; + + @Bean + public MongoCustomConversions mongoCustomConversions() { + return new MongoCustomConversions(MimeTypeConverters.getConvertersToRegister()); + } + @Bean public VectorStore vectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel, @@ -200,11 +213,6 @@ public VectorStore vectorStore(MongoTemplate mongoTemplate, EmbeddingModel embed true); } - @Bean - public MongoTemplate mongoTemplate(MongoClient mongoClient) { - return new MongoTemplate(mongoClient, "springaisample"); - } - @Bean public EmbeddingModel embeddingModel() { return new OpenAiEmbeddingModel(new OpenAiApi(System.getenv("OPENAI_API_KEY")));