diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc index e9308b1ca..4396dbfd9 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc @@ -6,24 +6,19 @@ link:https://neo4j.com[Neo4j] is an open-source NoSQL graph database. It is a fully transactional database (ACID) that stores data structured as graphs consisting of nodes, connected by relationships. Inspired by the structure of the real world, it allows for high query performance on complex data while remaining intuitive and simple for the developer. -The link:https://neo4j.com/docs/cypher-manual/current/indexes-for-vector-search/[Neo4j's Vector Search] allows users to query vector embeddings from large datasets. An embedding is a numerical representation of a data object, such as text, image, audio, or document. +The link:https://neo4j.com/docs/cypher-manual/current/indexes-for-vector-search/[Neo4j's Vector Search] allows users to query vector embeddings from large datasets. +An embedding is a numerical representation of a data object, such as text, image, audio, or document. Embeddings can be stored on _Node_ properties and can be queried with the `db.index.vector.queryNodes()` function. Those indexes are powered by Lucene using a Hierarchical Navigable Small World Graph (HNSW) to perform a k approximate nearest neighbors (k-ANN) query over the vector fields. == Prerequisites -* You would need an xref:api/embeddings.adoc#available-implementations[EmbeddingClient] to generate the embeddings stored in the `Neo4jVectorStore`. -* A running Neo4j (5.13+) instance. Following options are available: -** link:https://hub.docker.com/_/neo4j[Docker] image `neo4j:5.16.0` +* A running Neo4j (5.13+) instance. The following options are available: +** link:https://hub.docker.com/_/neo4j[Docker] image ** link:https://neo4j.com/download/[Neo4j Desktop] ** link:https://neo4j.com/cloud/aura-free/[Neo4j Aura] ** link:https://neo4j.com/deployment-center/[Neo4j Server] instance - -== Configuration - -To connect to Neo4j and use the `Neo4jVectorStore`, you need to provide (e.g. via environment variables) access details for your instance. - -TIP: Additionally, you will need a configured xref:api/embeddings.adoc#available-implementations[EmbeddingClient]. +* If required, an API key for the xref:api/embeddings.adoc#available-implementations[EmbeddingClient] to generate the embeddings stored by the `Neo4jVectorStore`. == Dependencies @@ -49,46 +44,93 @@ dependencies { TIP: Refer to the xref:getting-started.adoc#_dependency_management[Dependency Management] section to add Milestone and/or Snapshot Repositories to your build file. -== Sample Code +== Configuration -To configure `Neo4jVectorStore` in your application, you can use the following setup: +To connect to Neo4j and use the `Neo4jVectorStore`, you need to provide access details for your instance. +A simple configuration can either be provided via Spring Boot's _application.properties_, -Add to your environment (using your own Neo4j credentials and the appropriate access protocol+endpoint) the following properties either by updating and executing the following commands or creating a shell script to be run from your command prompt (Linux/Mac/WSL2): +[source,properties] +---- +spring.neo4j.uri= +spring.neo4j.authentication.username= +spring.neo4j.authentication.password= +# API key if needed, e.g. OpenAI +spring.ai.openai.api.key= +---- + +environment variables, [source,bash] ---- export SPRING_NEO4J_URI= export SPRING_NEO4J_AUTHENTICATION_USERNAME= export SPRING_NEO4J_AUTHENTICATION_PASSWORD= +# API key if needed, e.g. OpenAI +export SPRING_AI_OPENAI_API_KEY= ---- +or can be a mix of those. +For example, if you want to store your API key as an environment variable but keep the rest in the plain _application.properties_ file. + NOTE: If you choose to create a shell script for ease in future work, be sure to run it prior to starting your application by "sourcing" the file, i.e. `source .sh`. -You'll need a `VectorStore` to store the embeddings. You can use the `Neo4jVectorStore` for this purpose, but first, you must create two beans the `Neo4jVectorStore` constructor requires. Here are examples of all of the beans you'll need: +NOTE: Besides _application.properties_ and environment variables, Spring Boot offers https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config[additional configuration options]. + +Spring Boot's auto-configuration feature for the Neo4j Driver will create a bean instance that will be used by the `Neo4jVectorStore`. + +== Auto-configuration + +Spring AI provides Spring Boot auto-configuration for the Neo4j Vector Sore. +To enable it, add the following dependency to your project's Maven `pom.xml` file: + +[source, xml] +---- + + org.springframework.ai + spring-ai-neo4j-store-spring-boot-starter + 0.8.0-SNAPSHOT + +---- + +or to your Gradle `build.gradle` build file. + +[source,groovy] +---- +dependencies { + implementation 'org.springframework.ai:spring-ai-neo4j-store-spring-boot-starter:0.8.0-SNAPSHOT' +} +---- + +Please have a look at the list of xref:#_neo4jvectorstore_properties[configuration parameters] for the vector store to learn about the default values and configuration options. + +TIP: Refer to the xref:getting-started.adoc#_dependency_management[Dependency Management] section to add Milestone and/or Snapshot Repositories to your build file. + +Additionally, you will need a configured `EmbeddingClient` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingClient] section for more information. + +Here is an example of the needed bean: [source,java] ---- @Bean public EmbeddingClient embeddingClient() { - // Can be any other EmbeddingClient implementation. + // Can be any other EmbeddingClient implementation. return new OpenAiEmbeddingClient(new OpenAiApi(System.getenv("SPRING_AI_OPENAI_API_KEY"))); } - -@Bean -public Driver driver() { - return GraphDatabase.driver(System.getenv("SPRING_NEO4J_URI"), - AuthTokens.basic(System.getenv("SPRING_NEO4J_AUTHENTICATION_USERNAME"), - System.getenv("SPRING_NEO4J_AUTHENTICATION_PASSWORD"))); -} - -@Bean -public VectorStore vectorStore(Driver driver, EmbeddingClient embeddingClient) { - return new Neo4jVectorStore(driver, embeddingClient, - Neo4jVectorStore.Neo4jVectorStoreConfig.defaultConfig()); -} ---- -The `Neo4jVectorStore` is now ready to be used in your application. You can use it to store embeddings and perform similarity searches. +In cases where the Spring Boot auto-configured Neo4j `Driver` bean is not what you want or need, you can still define your own bean. +Please read the https://neo4j.com/docs/java-manual/current/client-applications/[Neo4j Java Driver reference] for more in-depth information about the configuration of a custom driver. + +[source,java] +---- +@Bean +public Driver driver() { + return GraphDatabase.driver("neo4j://:", + AuthTokens.basic("", "")); +} +---- + +Now you can auto-wire the `Neo4jVectorStore` as a vector store in your application. == Metadata filtering @@ -135,31 +177,17 @@ is converted into the proprietary Neo4j filter format: node.`metadata.author` IN ["john","jill"] AND node.`metadata.'article_type'` = "blog" ``` -== Auto-configuration +== Neo4jVectorStore properties -Spring AI provides Spring Boot auto-configuration for the Neo4j Vector Sore. -To enable it add the following dependency to your project's Maven `pom.xml` file: +You can use the following properties in your Spring Boot configuration to customize the Neo4j vector store. -[source, xml] ----- - - org.springframework.ai - spring-ai-neo4j-store-spring-boot-starter - 0.8.0-SNAPSHOT - ----- +|=== +|Property|Default value -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-neo4j-store-spring-boot-starter:0.8.0-SNAPSHOT' -} ----- - -TIP: Additionally, you will need a configured `EmbeddingClient` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingClient] section for more information. - -TIP: Refer to the xref:getting-started.adoc#_dependency_management[Dependency Management] section to add Milestone and/or Snapshot Repositories to your build file. - -Now you can auto-wire the `Neo4jVectorStore` as a vector store in your application. \ No newline at end of file +|`spring.ai.vectorstore.neo4j.database-name`|neo4j +|`spring.ai.vectorstore.neo4j.embedding-dimension`|1536 +|`spring.ai.vectorstore.neo4j.distance-type`|cosine +|`spring.ai.vectorstore.neo4j.label`|Document +|`spring.ai.vectorstore.neo4j.embedding-property`|embedding +|`spring.ai.vectorstore.neo4j.index-name`|spring-ai-document-index +|=== diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jDriverProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jDriverProperties.java deleted file mode 100644 index ce6246fc0..000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jDriverProperties.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2023-2023 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.autoconfigure.vectorstore.neo4j; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -import java.io.File; -import java.net.URI; -import java.time.Duration; - -/** - * Properties for Neo4j driver - * - * @author Jingzhou Ou - */ -@ConfigurationProperties(Neo4jDriverProperties.CONFIG_PREFIX) -public class Neo4jDriverProperties { - - public static final String CONFIG_PREFIX = "spring.ai.vectorstore.neo4j.driver"; - - /** - * supports bolt or neo4j as schemes. - */ - private URI uri; - - /** - * optional - */ - private Authentication authentication = new Authentication(); - - /** - * connection pool configuration - */ - private PoolSettings pool = new PoolSettings(); - - /** - * Detailed driver configuration of the driver - */ - private DriverSettings config = new DriverSettings(); - - public URI getUri() { - return this.uri; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - public Authentication getAuthentication() { - return this.authentication; - } - - public void setAuthentication(Authentication authentication) { - this.authentication = authentication; - } - - public PoolSettings getPool() { - return this.pool; - } - - public void setPool(PoolSettings pool) { - this.pool = pool; - } - - public DriverSettings getConfig() { - return this.config; - } - - public void setConfig(DriverSettings config) { - this.config = config; - } - - public static class Authentication { - - private String username; - - private String password; - - private String realm; - - /** - * kerberos authentication - */ - private String kerberosTicket; - - public String getUsername() { - return this.username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return this.password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getRealm() { - return this.realm; - } - - public void setRealm(String realm) { - this.realm = realm; - } - - public String getKerberosTicket() { - return this.kerberosTicket; - } - - public void setKerberosTicket(String kerberosTicket) { - this.kerberosTicket = kerberosTicket; - } - - } - - public static class PoolSettings { - - private boolean metricsEnabled = false; - - private boolean logLeakedSessions = false; - - private int maxConnectionPoolSize = org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_MAX_CONNECTION_POOL_SIZE; - - private Duration idleTimeBeforeConnectionTest; - - private Duration maxConnectionLifetime = Duration - .ofMillis(org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_MAX_CONNECTION_LIFETIME); - - private Duration connectionAcquisitionTimeout = Duration - .ofMillis(org.neo4j.driver.internal.async.pool.PoolSettings.DEFAULT_CONNECTION_ACQUISITION_TIMEOUT); - - public boolean isLogLeakedSessions() { - return this.logLeakedSessions; - } - - public void setLogLeakedSessions(boolean logLeakedSessions) { - this.logLeakedSessions = logLeakedSessions; - } - - public int getMaxConnectionPoolSize() { - return this.maxConnectionPoolSize; - } - - public void setMaxConnectionPoolSize(int maxConnectionPoolSize) { - this.maxConnectionPoolSize = maxConnectionPoolSize; - } - - public Duration getIdleTimeBeforeConnectionTest() { - return this.idleTimeBeforeConnectionTest; - } - - public void setIdleTimeBeforeConnectionTest(Duration idleTimeBeforeConnectionTest) { - this.idleTimeBeforeConnectionTest = idleTimeBeforeConnectionTest; - } - - public Duration getMaxConnectionLifetime() { - return this.maxConnectionLifetime; - } - - public void setMaxConnectionLifetime(Duration maxConnectionLifetime) { - this.maxConnectionLifetime = maxConnectionLifetime; - } - - public Duration getConnectionAcquisitionTimeout() { - return this.connectionAcquisitionTimeout; - } - - public void setConnectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) { - this.connectionAcquisitionTimeout = connectionAcquisitionTimeout; - } - - public boolean isMetricsEnabled() { - return this.metricsEnabled; - } - - public void setMetricsEnabled(boolean metricsEnabled) { - this.metricsEnabled = metricsEnabled; - } - - } - - public static class DriverSettings { - - private boolean encrypted = false; - - private TrustSettings trustSettings = new TrustSettings(); - - private Duration connectionTimeout = Duration.ofSeconds(30); - - private Duration maxTransactionRetryTime = Duration - .ofMillis(org.neo4j.driver.internal.retry.RetrySettings.DEFAULT.maxRetryTimeMs()); - - public boolean isEncrypted() { - return this.encrypted; - } - - public void setEncrypted(boolean encrypted) { - this.encrypted = encrypted; - } - - public TrustSettings getTrustSettings() { - return this.trustSettings; - } - - public void setTrustSettings(TrustSettings trustSettings) { - this.trustSettings = trustSettings; - } - - public Duration getConnectionTimeout() { - return this.connectionTimeout; - } - - public void setConnectionTimeout(Duration connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - public Duration getMaxTransactionRetryTime() { - return this.maxTransactionRetryTime; - } - - public void setMaxTransactionRetryTime(Duration maxTransactionRetryTime) { - this.maxTransactionRetryTime = maxTransactionRetryTime; - } - - } - - public static class TrustSettings { - - public enum Strategy { - - TRUST_ALL_CERTIFICATES, - - TRUST_CUSTOM_CA_SIGNED_CERTIFICATES, - - TRUST_SYSTEM_CA_SIGNED_CERTIFICATES - - } - - private TrustSettings.Strategy strategy = Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES; - - private File certFile; - - private boolean hostnameVerificationEnabled = false; - - public TrustSettings.Strategy getStrategy() { - return this.strategy; - } - - public void setStrategy(TrustSettings.Strategy strategy) { - this.strategy = strategy; - } - - public File getCertFile() { - return this.certFile; - } - - public void setCertFile(File certFile) { - this.certFile = certFile; - } - - public boolean isHostnameVerificationEnabled() { - return this.hostnameVerificationEnabled; - } - - public void setHostnameVerificationEnabled(boolean hostnameVerificationEnabled) { - this.hostnameVerificationEnabled = hostnameVerificationEnabled; - } - - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java index b412530bc..0aad48b46 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java @@ -16,34 +16,23 @@ package org.springframework.ai.autoconfigure.vectorstore.neo4j; -import org.neo4j.driver.AuthToken; -import org.neo4j.driver.AuthTokens; -import org.neo4j.driver.Config; import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.internal.Scheme; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.vectorstore.Neo4jVectorStore; import org.springframework.ai.vectorstore.VectorStore; 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.neo4j.Neo4jAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import org.springframework.context.annotation.Bean; -import org.springframework.util.StringUtils; - -import java.io.File; -import java.net.URI; -import java.util.Locale; -import java.util.concurrent.TimeUnit; /** * @author Jingzhou Ou */ -@AutoConfiguration -@ConditionalOnClass({ Neo4jVectorStore.class, EmbeddingClient.class }) -@EnableConfigurationProperties({ Neo4jVectorStoreProperties.class, Neo4jDriverProperties.class }) +@AutoConfiguration(after = Neo4jAutoConfiguration.class) +@ConditionalOnClass({ Neo4jVectorStore.class, EmbeddingClient.class, Driver.class }) +@EnableConfigurationProperties({ Neo4jVectorStoreProperties.class }) public class Neo4jVectorStoreAutoConfiguration { @Bean @@ -62,128 +51,4 @@ public class Neo4jVectorStoreAutoConfiguration { return new Neo4jVectorStore(driver, embeddingClient, config); } - @Bean - @ConditionalOnMissingBean(Driver.class) - Driver neo4jDriver(Neo4jDriverProperties driverProperties) { - AuthToken authToken = getAuthToken(driverProperties); - Config config = getDriverConfig(driverProperties); - return GraphDatabase.driver(driverProperties.getUri(), authToken, config); - } - - private Config getDriverConfig(Neo4jDriverProperties driverProperties) { - Config.ConfigBuilder builder = Config.builder(); - buildWithPoolSettings(builder, driverProperties.getPool()); - URI uri = driverProperties.getUri(); - String scheme = uri == null ? "bolt" : uri.getScheme(); - buildWithDriverSettings(builder, driverProperties.getConfig(), isSimpleScheme(scheme)); - return builder.build(); - } - - private AuthToken getAuthToken(Neo4jDriverProperties driverProperties) { - String username = driverProperties.getAuthentication().getUsername(); - String password = driverProperties.getAuthentication().getPassword(); - String kerberosTicket = driverProperties.getAuthentication().getKerberosTicket(); - String realm = driverProperties.getAuthentication().getRealm(); - - boolean hasUsername = StringUtils.hasText(username); - boolean hasPassword = StringUtils.hasText(password); - boolean hasKerberosTicket = StringUtils.hasText(kerberosTicket); - - if (hasUsername && hasKerberosTicket) { - throw new InvalidConfigurationPropertyValueException("spring.ai.vectorstore.neo4j.driver.authentication", - "username=" + username + ",kerberos-ticket=" + kerberosTicket, - "Cannot specify both username and kerberos ticket."); - } - - if (hasUsername && hasPassword) { - return AuthTokens.basic(username, password, realm); - } - - if (hasKerberosTicket) { - return AuthTokens.kerberos(kerberosTicket); - } - - return AuthTokens.none(); - } - - private void buildWithPoolSettings(Config.ConfigBuilder builder, Neo4jDriverProperties.PoolSettings poolSettings) { - if (poolSettings.isLogLeakedSessions()) { - builder.withLeakedSessionsLogging(); - } - builder.withMaxConnectionPoolSize(poolSettings.getMaxConnectionPoolSize()); - if (poolSettings.getIdleTimeBeforeConnectionTest() != null) { - builder.withConnectionLivenessCheckTimeout(poolSettings.getIdleTimeBeforeConnectionTest().toMillis(), - TimeUnit.MILLISECONDS); - } - builder.withMaxConnectionLifetime(poolSettings.getMaxConnectionLifetime().toMillis(), TimeUnit.MILLISECONDS); - builder.withConnectionAcquisitionTimeout(poolSettings.getConnectionAcquisitionTimeout().toMillis(), - TimeUnit.MILLISECONDS); - - if (poolSettings.isMetricsEnabled()) { - builder.withDriverMetrics(); - } - else { - builder.withoutDriverMetrics(); - } - } - - private void buildWithDriverSettings(Config.ConfigBuilder builder, - Neo4jDriverProperties.DriverSettings driverSettings, boolean withEncryptionAndTrustSettings) { - if (withEncryptionAndTrustSettings) { - if (driverSettings.isEncrypted()) { - builder.withEncryption(); - } - else { - builder.withoutEncryption(); - } - builder.withTrustStrategy(getTrustStrategy(driverSettings.getTrustSettings())); - } - builder.withConnectionTimeout(driverSettings.getConnectionTimeout().toMillis(), TimeUnit.MILLISECONDS); - builder.withMaxTransactionRetryTime(driverSettings.getMaxTransactionRetryTime().toMillis(), - TimeUnit.MILLISECONDS); - } - - private boolean isSimpleScheme(String scheme) { - String lowerCaseScheme = scheme.toLowerCase(Locale.ENGLISH); - try { - Scheme.validateScheme(lowerCaseScheme); - } - catch (IllegalArgumentException ex) { - throw new IllegalArgumentException(String.format("'%s' is not a supported scheme.", scheme)); - } - return lowerCaseScheme.equals("bolt") || lowerCaseScheme.equals("neo4j"); - } - - private Config.TrustStrategy getTrustStrategy(Neo4jDriverProperties.TrustSettings trustSettings) { - String propertyName = "spring.ai.vectorstore.neo4j.driver.config.trust-settings"; - Config.TrustStrategy internalRepresentation; - File certFile = trustSettings.getCertFile(); - switch (trustSettings.getStrategy()) { - case TRUST_ALL_CERTIFICATES: - internalRepresentation = Config.TrustStrategy.trustAllCertificates(); - break; - case TRUST_SYSTEM_CA_SIGNED_CERTIFICATES: - internalRepresentation = Config.TrustStrategy.trustSystemCertificates(); - break; - case TRUST_CUSTOM_CA_SIGNED_CERTIFICATES: - if (certFile == null || !certFile.isFile()) { - throw new InvalidConfigurationPropertyValueException(propertyName, - trustSettings.getStrategy().name(), - "Configured trust strategy requires a certificate file."); - } - internalRepresentation = Config.TrustStrategy.trustCustomCertificateSignedBy(certFile); - break; - default: - throw new InvalidConfigurationPropertyValueException(propertyName, trustSettings.getStrategy().name(), - "Unknown strategy."); - } - if (trustSettings.isHostnameVerificationEnabled()) { - internalRepresentation.withHostnameVerification(); - } - else { - internalRepresentation.withoutHostnameVerification(); - } - return internalRepresentation; - } - } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfigurationIT.java index 23393a859..d42b3e005 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfigurationIT.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration; import org.testcontainers.containers.Neo4jContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -56,11 +57,11 @@ public class Neo4jVectorStoreAutoConfigurationIT { ResourceUtils.getText("classpath:/test/data/great.depression.txt"), Map.of("depression", "bad"))); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(Neo4jVectorStoreAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(Neo4jAutoConfiguration.class, Neo4jVectorStoreAutoConfiguration.class)) .withUserConfiguration(Config.class) - .withPropertyValues("spring.ai.vectorstore.neo4j.driver.uri=" + neo4jContainer.getBoltUrl(), - "spring.ai.vectorstore.neo4j.driver.authentication.username=" + "neo4j", - "spring.ai.vectorstore.neo4j.driver.authentication.password=" + neo4jContainer.getAdminPassword()); + .withPropertyValues("spring.neo4j.uri=" + neo4jContainer.getBoltUrl(), + "spring.neo4j.authentication.username=" + "neo4j", + "spring.neo4j.authentication.password=" + neo4jContainer.getAdminPassword()); @Test void addAndSearch() {