From 39fd416788a017f505c0e8a918ccf1e0449f575b Mon Sep 17 00:00:00 2001 From: ZYinNJU <201250182@smail.nju.edu.cn> Date: Wed, 27 Dec 2023 00:18:32 +0800 Subject: [PATCH 1/7] redis embedding store spring boot starter --- langchain4j-redis-spring-boot-starter/pom.xml | 82 +++++++++++++++++++ .../RedisEmbeddingStoreAutoConfiguration.java | 28 +++++++ .../redis/spring/RedisProperties.java | 24 ++++++ .../main/resources/META-INF/spring.factories | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + ...edisEmbeddingStoreAutoConfigurationIT.java | 74 +++++++++++++++++ pom.xml | 25 +++++- 7 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 langchain4j-redis-spring-boot-starter/pom.xml create mode 100644 langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java create mode 100644 langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java create mode 100644 langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories create mode 100644 langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java diff --git a/langchain4j-redis-spring-boot-starter/pom.xml b/langchain4j-redis-spring-boot-starter/pom.xml new file mode 100644 index 0000000..0232a6d --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + dev.langchain4j + langchain4j-spring + 0.26.0-SNAPSHOT + ../pom.xml + + + langchain4j-oredis-spring-boot-starter + LangChain4j Spring Boot starter for Redis Vector Store + jar + + + + + dev.langchain4j + langchain4j-redis + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-autoconfigure-processor + true + + + + + org.projectlombok + lombok + provided + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + dev.langchain4j + langchain4j-embeddings-all-minilm-l6-v2-q + test + + + + com.redis.testcontainers + testcontainers-redis + 1.6.4 + test + + + + org.tinylog + tinylog-impl + test + + + + org.tinylog + slf4j-tinylog + test + + + + + \ No newline at end of file diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java new file mode 100644 index 0000000..a57ae2a --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java @@ -0,0 +1,28 @@ +package dev.langchain4j.store.embedding.redis.spring; + +import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; + +import static dev.langchain4j.store.embedding.redis.spring.RedisProperties.PREFIX; + +@AutoConfiguration +@EnableConfigurationProperties(RedisProperties.class) +public class RedisEmbeddingStoreAutoConfiguration { + + @Bean + @ConditionalOnProperty(PREFIX + ".enabled") + public RedisEmbeddingStore redisEmbeddingStore(RedisProperties properties) { + return RedisEmbeddingStore.builder() + .host(properties.getHost()) + .port(properties.getPort()) + .user(properties.getUser()) + .password(properties.getPassword()) + .indexName(properties.getIndexName()) + .dimension(properties.getDimension()) + .metadataFieldsName(properties.getMetadataFieldsName()) + .build(); + } +} diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java new file mode 100644 index 0000000..7613afa --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java @@ -0,0 +1,24 @@ +package dev.langchain4j.store.embedding.redis.spring; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.ArrayList; +import java.util.List; + +@ConfigurationProperties(prefix = RedisProperties.PREFIX) +@Getter +@Setter +public class RedisProperties { + + static final String PREFIX = "langchain4j.redis"; + + private String host; + private Integer port; + private String user; + private String password; + private String indexName; + private Integer dimension; + private List metadataFieldsName = new ArrayList<>(); +} diff --git a/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories b/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..c03ec78 --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=dev.langchain4j.store.embedding.redis.spring.RedisEmbeddingStoreAutoConfiguration \ No newline at end of file diff --git a/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..b9f8b5e --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +dev.langchain4j.store.embedding.redis.spring.RedisEmbeddingStoreAutoConfiguration \ No newline at end of file diff --git a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java new file mode 100644 index 0000000..118ed1f --- /dev/null +++ b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java @@ -0,0 +1,74 @@ +package dev.langchain4j.store.embedding.redis.spring; + +import com.redis.testcontainers.RedisContainer; +import dev.langchain4j.data.embedding.Embedding; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.embedding.AllMiniLmL6V2QuantizedEmbeddingModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.store.embedding.EmbeddingMatch; +import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import java.util.List; + +import static com.redis.testcontainers.RedisStackContainer.DEFAULT_IMAGE_NAME; +import static com.redis.testcontainers.RedisStackContainer.DEFAULT_TAG; +import static dev.langchain4j.internal.Utils.randomUUID; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.Percentage.withPercentage; + +class RedisEmbeddingStoreAutoConfigurationIT { + + static RedisContainer redis = new RedisContainer(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)); + + EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel(); + + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(RedisEmbeddingStoreAutoConfiguration.class)); + + @BeforeAll + static void beforeAll() throws Exception { + redis.start(); + } + + @AfterAll + static void afterAll() { + redis.stop(); + } + + @Test + void should_provide_redis_vector_store() { + TextSegment segment = TextSegment.from("hello"); + Embedding embedding = embeddingModel.embed(segment.text()).content(); + contextRunner + .withPropertyValues( + "langchain4j.redis.enabled=true", + "langchain4j.redis.host=" + redis.getHost(), + "langchain4j.redis.port=" + redis.getFirstMappedPort(), + "langchain4j.redis.indexName=" + randomUUID(), + "langchain4j.redis.dimension=" + 384, + "langchain4j.redis.metadataFieldsName=test-key" + ) + .run(context -> { + EmbeddingStore embeddingStore = context.getBean(RedisEmbeddingStore.class); + assertThat(embeddingStore).isInstanceOf(RedisEmbeddingStore.class); + + String id = embeddingStore.add(embedding, segment); + assertThat(id).isNotBlank(); + + List> relevant = embeddingStore.findRelevant(embedding, 10); + assertThat(relevant).hasSize(1); + + EmbeddingMatch match = relevant.get(0); + assertThat(match.score()).isCloseTo(1, withPercentage(1)); + assertThat(match.embeddingId()).isEqualTo(id); + assertThat(match.embedding()).isEqualTo(embedding); + assertThat(match.embedded()).isEqualTo(segment); + }); + } +} diff --git a/pom.xml b/pom.xml index b459bb1..af71b4c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ langchain4j-open-ai-spring-boot-starter + langchain4j-redis-spring-boot-starter @@ -22,6 +23,8 @@ 1.8 UTF-8 2.7.18 + 2.6.2 + 0.25.0 @@ -29,8 +32,10 @@ dev.langchain4j - langchain4j-open-ai + langchain4j-bom ${project.version} + pom + import @@ -63,6 +68,24 @@ 1.18.30 + + dev.langchain4j + langchain4j-embeddings-all-minilm-l6-v2-q + ${langchain4j.embeddings.version} + + + + org.tinylog + tinylog-impl + ${tinylog.version} + + + + org.tinylog + slf4j-tinylog + ${tinylog.version} + + From 8148bbd9281e7d08979869d698dcc59d7a2992f2 Mon Sep 17 00:00:00 2001 From: ZYinNJU <201250182@smail.nju.edu.cn> Date: Wed, 27 Dec 2023 15:15:38 +0800 Subject: [PATCH 2/7] fix container start up wait strategy --- .../spring/RedisEmbeddingStoreAutoConfigurationIT.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java index 118ed1f..7d6bdf9 100644 --- a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java +++ b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.testcontainers.containers.wait.strategy.Wait; import java.util.List; @@ -24,7 +25,8 @@ class RedisEmbeddingStoreAutoConfigurationIT { - static RedisContainer redis = new RedisContainer(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)); + static RedisContainer redis = new RedisContainer(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) + .waitingFor(Wait.defaultWaitStrategy()); EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel(); @@ -32,7 +34,7 @@ class RedisEmbeddingStoreAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(RedisEmbeddingStoreAutoConfiguration.class)); @BeforeAll - static void beforeAll() throws Exception { + static void beforeAll() { redis.start(); } From 4a50138fd6c85f57590e9abc2324609453bb8deb Mon Sep 17 00:00:00 2001 From: ZYinNJU <201250182@smail.nju.edu.cn> Date: Wed, 27 Dec 2023 20:12:24 +0800 Subject: [PATCH 3/7] rename properties and change conditional --- .../spring/RedisEmbeddingStoreAutoConfiguration.java | 10 ++++++---- ...perties.java => RedisEmbeddingStoreProperties.java} | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) rename langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/{RedisProperties.java => RedisEmbeddingStoreProperties.java} (82%) diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java index a57ae2a..3606090 100644 --- a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java @@ -2,19 +2,21 @@ import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; import org.springframework.boot.autoconfigure.AutoConfiguration; +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 static dev.langchain4j.store.embedding.redis.spring.RedisProperties.PREFIX; +import static dev.langchain4j.store.embedding.redis.spring.RedisEmbeddingStoreProperties.PREFIX; @AutoConfiguration -@EnableConfigurationProperties(RedisProperties.class) +@EnableConfigurationProperties(RedisEmbeddingStoreProperties.class) +@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") public class RedisEmbeddingStoreAutoConfiguration { @Bean - @ConditionalOnProperty(PREFIX + ".enabled") - public RedisEmbeddingStore redisEmbeddingStore(RedisProperties properties) { + @ConditionalOnMissingBean + public RedisEmbeddingStore redisEmbeddingStore(RedisEmbeddingStoreProperties properties) { return RedisEmbeddingStore.builder() .host(properties.getHost()) .port(properties.getPort()) diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java similarity index 82% rename from langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java rename to langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java index 7613afa..ecd8a14 100644 --- a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisProperties.java +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java @@ -7,10 +7,10 @@ import java.util.ArrayList; import java.util.List; -@ConfigurationProperties(prefix = RedisProperties.PREFIX) +@ConfigurationProperties(prefix = RedisEmbeddingStoreProperties.PREFIX) @Getter @Setter -public class RedisProperties { +public class RedisEmbeddingStoreProperties { static final String PREFIX = "langchain4j.redis"; From 50899e56e07ef0328857a1900197022c6f6ae09c Mon Sep 17 00:00:00 2001 From: ZYinNJU <201250182@smail.nju.edu.cn> Date: Fri, 10 May 2024 09:48:47 +0800 Subject: [PATCH 4/7] config default value --- .../redis/spring/RedisEmbeddingStoreAutoConfiguration.java | 4 ++-- .../embedding/redis/spring/RedisEmbeddingStoreProperties.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java index 208150b..52800ab 100644 --- a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java @@ -11,7 +11,7 @@ @AutoConfiguration @EnableConfigurationProperties(RedisEmbeddingStoreProperties.class) -@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") +@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) public class RedisEmbeddingStoreAutoConfiguration { @Bean @@ -24,7 +24,7 @@ public RedisEmbeddingStore redisEmbeddingStore(RedisEmbeddingStoreProperties pro .password(properties.getPassword()) .indexName(properties.getIndexName()) .dimension(properties.getDimension()) - .metadataFieldsName(properties.getMetadataKeys()) + .metadataKeys(properties.getMetadataKeys()) .build(); } } diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java index 23b82d1..96c79b5 100644 --- a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreProperties.java @@ -14,8 +14,8 @@ public class RedisEmbeddingStoreProperties { static final String PREFIX = "langchain4j.redis"; - private String host; - private Integer port; + private String host = "localhost"; + private Integer port = 6379; private String user; private String password; private String indexName; From 31e893850aa189852042d7e920573b3f11b5488d Mon Sep 17 00:00:00 2001 From: Martin7-1 <1754350460@qq.com> Date: Sat, 22 Jun 2024 23:03:51 +0800 Subject: [PATCH 5/7] move spring boot baseline to 3.x --- ...gframework.boot.autoconfigure.AutoConfiguration.imports | 1 - pom.xml | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index b9f8b5e..0000000 --- a/langchain4j-redis-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -dev.langchain4j.store.embedding.redis.spring.RedisEmbeddingStoreAutoConfiguration \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8cbb791..dab9f6f 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,6 @@ 17 UTF-8 2.6.2 - 0.32.0-SNAPSHOT 3.2.6 @@ -74,12 +73,6 @@ 1.18.32 - - dev.langchain4j - langchain4j-embeddings-all-minilm-l6-v2-q - ${langchain4j.embeddings.version} - - org.tinylog tinylog-impl From 696effe8adf01afd97b6b5caacb6528def6dd1e2 Mon Sep 17 00:00:00 2001 From: Martin7-1 <1754350460@qq.com> Date: Sat, 22 Jun 2024 23:57:33 +0800 Subject: [PATCH 6/7] unified IT --- langchain4j-redis-spring-boot-starter/pom.xml | 9 +++ ...edisEmbeddingStoreAutoConfigurationIT.java | 57 ++++++------------- pom.xml | 12 ---- 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/langchain4j-redis-spring-boot-starter/pom.xml b/langchain4j-redis-spring-boot-starter/pom.xml index 4bb0f52..6e4a6e7 100644 --- a/langchain4j-redis-spring-boot-starter/pom.xml +++ b/langchain4j-redis-spring-boot-starter/pom.xml @@ -58,6 +58,15 @@ test + + dev.langchain4j + langchain4j-spring-boot-core + ${project.version} + tests + test-jar + test + + com.redis.testcontainers testcontainers-redis diff --git a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java index cdb7782..60390ad 100644 --- a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java +++ b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java @@ -1,35 +1,22 @@ package dev.langchain4j.store.embedding.redis.spring; import com.redis.testcontainers.RedisContainer; -import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; -import dev.langchain4j.model.embedding.AllMiniLmL6V2QuantizedEmbeddingModel; -import dev.langchain4j.model.embedding.EmbeddingModel; -import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; +import dev.langchain4j.store.embedding.spring.EmbeddingStoreAutoConfigurationIT; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.testcontainers.containers.wait.strategy.Wait; -import java.util.List; - import static com.redis.testcontainers.RedisStackContainer.DEFAULT_IMAGE_NAME; import static com.redis.testcontainers.RedisStackContainer.DEFAULT_TAG; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.data.Percentage.withPercentage; -class RedisEmbeddingStoreAutoConfigurationIT { +class RedisEmbeddingStoreAutoConfigurationIT extends EmbeddingStoreAutoConfigurationIT { static RedisContainer redis = new RedisContainer(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) .waitingFor(Wait.defaultWaitStrategy()); - ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(RedisEmbeddingStoreAutoConfiguration.class)); - @BeforeAll static void beforeAll() { redis.start(); @@ -40,33 +27,21 @@ static void afterAll() { redis.stop(); } - @Test - void should_provide_redis_vector_store() { - TextSegment segment = TextSegment.from("hello"); - - contextRunner - .withBean(AllMiniLmL6V2QuantizedEmbeddingModel.class) - .withPropertyValues( - "langchain4j.redis.host=" + redis.getHost(), - "langchain4j.redis.port=" + redis.getFirstMappedPort() - ) - .run(context -> { - EmbeddingModel embeddingModel = context.getBean(AllMiniLmL6V2QuantizedEmbeddingModel.class); - Embedding embedding = embeddingModel.embed(segment.text()).content(); - EmbeddingStore embeddingStore = context.getBean(RedisEmbeddingStore.class); - assertThat(embeddingStore).isInstanceOf(RedisEmbeddingStore.class); - - String id = embeddingStore.add(embedding, segment); - assertThat(id).isNotBlank(); + @Override + protected Class autoConfigurationClass() { + return RedisEmbeddingStoreAutoConfiguration.class; + } - List> relevant = embeddingStore.findRelevant(embedding, 10); - assertThat(relevant).hasSize(1); + @Override + protected Class> embeddingStoreClass() { + return RedisEmbeddingStore.class; + } - EmbeddingMatch match = relevant.get(0); - assertThat(match.score()).isCloseTo(1, withPercentage(1)); - assertThat(match.embeddingId()).isEqualTo(id); - assertThat(match.embedding()).isEqualTo(embedding); - assertThat(match.embedded()).isEqualTo(segment); - }); + @Override + protected String[] properties() { + return new String[]{ + "langchain4j.redis.host=" + redis.getHost(), + "langchain4j.redis.port=" + redis.getFirstMappedPort() + }; } } diff --git a/pom.xml b/pom.xml index 417dcf3..2902198 100644 --- a/pom.xml +++ b/pom.xml @@ -76,18 +76,6 @@ 1.18.32 - - org.tinylog - tinylog-impl - ${tinylog.version} - - - - org.tinylog - slf4j-tinylog - ${tinylog.version} - - org.testcontainers testcontainers-bom From e2c623a356e5553868991d49ec42f34e48d3b327 Mon Sep 17 00:00:00 2001 From: Martin7-1 <1754350460@qq.com> Date: Mon, 1 Jul 2024 14:46:27 +0800 Subject: [PATCH 7/7] update IT --- langchain4j-redis-spring-boot-starter/pom.xml | 4 ++-- .../RedisEmbeddingStoreAutoConfiguration.java | 7 +++---- .../RedisEmbeddingStoreAutoConfigurationIT.java | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/langchain4j-redis-spring-boot-starter/pom.xml b/langchain4j-redis-spring-boot-starter/pom.xml index 6e4a6e7..7227a0e 100644 --- a/langchain4j-redis-spring-boot-starter/pom.xml +++ b/langchain4j-redis-spring-boot-starter/pom.xml @@ -11,7 +11,7 @@ langchain4j-redis-spring-boot-starter - LangChain4j Spring Boot starter for Redis Vector Store + LangChain4j Spring Boot starter for Redis jar @@ -60,7 +60,7 @@ dev.langchain4j - langchain4j-spring-boot-core + langchain4j-spring-boot-tests ${project.version} tests test-jar diff --git a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java index fe2c2f3..bff93ac 100644 --- a/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java +++ b/langchain4j-redis-spring-boot-starter/src/main/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfiguration.java @@ -3,11 +3,11 @@ import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 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.lang.Nullable; import java.util.ArrayList; import java.util.List; @@ -26,13 +26,12 @@ public class RedisEmbeddingStoreAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnBean(EmbeddingModel.class) public RedisEmbeddingStore redisEmbeddingStore(RedisEmbeddingStoreProperties properties, - EmbeddingModel embeddingModel) { + @Nullable EmbeddingModel embeddingModel) { String host = Optional.ofNullable(properties.getHost()).orElse(DEFAULT_HOST); int port = Optional.ofNullable(properties.getPort()).orElse(DEFAULT_PORT); String indexName = Optional.ofNullable(properties.getIndexName()).orElse(DEFAULT_INDEX_NAME); - int dimension = Optional.ofNullable(properties.getDimension()).orElse(embeddingModel.dimension()); + Integer dimension = Optional.ofNullable(properties.getDimension()).orElseGet(() -> embeddingModel == null ? null : embeddingModel.dimension()); List metadataKeys = Optional.ofNullable(properties.getMetadataKeys()).orElse(new ArrayList<>()); return RedisEmbeddingStore.builder() diff --git a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java index 60390ad..aa05e4a 100644 --- a/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java +++ b/langchain4j-redis-spring-boot-starter/src/test/java/dev/langchain4j/store/embedding/redis/spring/RedisEmbeddingStoreAutoConfigurationIT.java @@ -7,7 +7,9 @@ import dev.langchain4j.store.embedding.spring.EmbeddingStoreAutoConfigurationIT; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.testcontainers.containers.wait.strategy.Wait; +import redis.clients.jedis.JedisPooled; import static com.redis.testcontainers.RedisStackContainer.DEFAULT_IMAGE_NAME; import static com.redis.testcontainers.RedisStackContainer.DEFAULT_TAG; @@ -27,6 +29,13 @@ static void afterAll() { redis.stop(); } + @BeforeEach + void beforeEach() { + try (JedisPooled jedis = new JedisPooled(redis.getHost(), redis.getFirstMappedPort())) { + jedis.flushDB(); // TODO fix: why redis returns embeddings from different indexes? + } + } + @Override protected Class autoConfigurationClass() { return RedisEmbeddingStoreAutoConfiguration.class; @@ -44,4 +53,9 @@ protected String[] properties() { "langchain4j.redis.port=" + redis.getFirstMappedPort() }; } + + @Override + protected String dimensionPropertyKey() { + return "langchain4j.redis.dimension"; + } }