diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc
index f4df0fe0e..9adc9e3ea 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc
@@ -9,49 +9,14 @@ link:https://www.qdrant.tech/[Qdrant] is an open-source, high-performance vector
* Qdrant Instance: Set up a Qdrant instance by following the link:https://qdrant.tech/documentation/guides/installation/[installation instructions] in the Qdrant documentation.
* If required, an API key for the xref:api/embeddings.adoc#available-implementations[EmbeddingClient] to generate the embeddings stored by the `QdrantVectorStore`.
-== Configuration
+To set up `QdrantVectorStore`, you'll need the following information from your Qdrant instance: `Host`, `GRPC Port`, `Collection Name`, and `API Key` (if required).
-To set up `QdrantVectorStore`, you'll need the following information from your Qdrant instance:
-
-* Qdrant Host
-* Qdrant GRPC Port
-* Qdrant Collection Name
-* Optional Qdrant API Key (not required for local development)
-
-[NOTE]
-====
-A Qdrant collection has to be link:https://qdrant.tech/documentation/concepts/collections/#create-a-collection[created] in advance with the appropriate dimensions and configurations.
-
-For example if using the OpenAI `text-embedding-ada-002` embedding model, create a collection with a vector size of `1536`.
-====
+NOTE: It is recommended that the Qdrant collection is link:https://qdrant.tech/documentation/concepts/collections/#create-a-collection[created] in advance with the appropriate dimensions and configurations.
+If the collection is not created, the `QdrantVectorStore` will attempt to create one using the `Cosine` similarity and the dimension of the configured `EmbeddingClient`.
== Dependencies
-* The Vector Store requires an `EmbeddingClient` instance to calculate embeddings for the documents.
-You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingClient Implementations]. For example ou can use the OpenAI boot starter:
-
-[source,xml]
-----
-
- org.springframework.ai
- spring-ai-openai-spring-boot-starter
-
-----
-
-or to your Gradle `build.gradle` build file.
-
-[source,groovy]
-----
-dependencies {
- implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
-}
-----
-
-TIP: Additionally, you'll need to provide your OpenAI API Key. Set it as an environment variable like so:
-`export SPRING_AI_OPENAI_API_KEY='Your_OpenAI_API_Key`
-
-
-* Add the Qdrant Boot Starter dependency to your project:
+Then add the Qdrant boot starter dependency to your project:
[source,xml]
----
@@ -70,21 +35,55 @@ dependencies {
}
----
+The Vector Store, also requires an `EmbeddingClient` instance to calculate embeddings for the documents.
+You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingClient Implementations].
+
+For example to use the xref:api/embeddings/openai-embeddings.adoc[OpenAI EmbeddingClient] add the following dependency to your project:
+
+[source,xml]
+----
+
+ org.springframework.ai
+ spring-ai-openai-spring-boot-starter
+
+----
+
+or to your Gradle `build.gradle` build file.
+
+[source,groovy]
+----
+dependencies {
+ implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
+}
+----
+
TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.
+Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file.
-Please have a look at the list of xref:#qdrant-vectorstore-properties[configuration parameters] for the vector store to learn about the default values and configuration options.
+To connect to Qdrant and use the `QdrantVectorStore`, you need to provide access details for your instance.
+A simple configuration can either be provided via Spring Boot's _application.properties_,
-TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file.
+[source,properties]
+----
+spring.ai.vectorstore.qdrant.host=
+spring.ai.vectorstore.qdrant.port=
+spring.ai.vectorstore.qdrant.api-key=
+spring.ai.vectorstore.qdrant.collection-name=
+# API key if needed, e.g. OpenAI
+spring.ai.openai.api.key=
+----
+
+TIP: Check the list of xref:#qdrant-vectorstore-properties[configuration parameters] to learn about the default values and configuration options.
Now you can Auto-wire the Qdrant Vector Store in your application and use it
[source,java]
----
-@Autowired
-VectorStore vectorStore;
+@Autowired VectorStore vectorStore;
+
+// ...
-...
List documents = List.of(
new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")),
new Document("The World is Big and Salvation Lurks Around the Corner"),
@@ -97,24 +96,7 @@ vectorStore.add(List.of(document));
List results = vectorStore.similaritySearch(SearchRequest.query("Spring").withTopK(5));
----
-== Configuration
-
-To connect to Qdrant and use the `QdrantVectorStore`, you need to provide access details for your instance.
-A simple configuration can either be provided via Spring Boot's _application.properties_,
-
-[source,properties]
-----
-spring.ai.vectorstore.qdrant.host=
-spring.ai.vectorstore.qdrant.port=
-spring.ai.vectorstore.qdrant.api-key=
-spring.ai.vectorstore.qdrant.collection-name=
-
-# API key if needed, e.g. OpenAI
-spring.ai.openai.api.key=
-----
-
-
-== Manual Configuration
+=== Manual Configuration
Instead of using the Spring Boot auto-configuration, you can manually configure the `QdrantVectorStore`. For this you need to add the `spring-ai-qdrant` dependency to your project:
@@ -162,7 +144,7 @@ public VectorStore vectorStore(QdrantVectorStoreConfig config, EmbeddingClient e
}
----
-=== Metadata filtering
+== Metadata filtering
You can leverage the generic, portable link:https://docs.spring.io/spring-ai/reference/api/vectordbs.html#_metadata_filters[metadata filters] with the Qdrant vector store.
@@ -195,18 +177,18 @@ vectorStore.similaritySearch(SearchRequest.defaults()
NOTE: These filter expressions are converted into the equivalent Qdrant link:https://qdrant.tech/documentation/concepts/filtering/[filters].
-
[[qdrant-vectorstore-properties]]
-== Qdrant VectorStore properties
+== Configuration properties
You can use the following properties in your Spring Boot configuration to customize the Qdrant vector store.
+[cols="3,5,1"]
|===
|Property| Description | Default value
|`spring.ai.vectorstore.qdrant.host`| The host of the Qdrant server. | localhost
-|`spring.ai.vectorstore.qdrant.port`| The port of the Qdrant server. | 6334
+|`spring.ai.vectorstore.qdrant.port`| The gRPC port of the Qdrant server. | 6334
|`spring.ai.vectorstore.qdrant.api-key`| The API key to use for authentication with the Qdrant server. | -
|`spring.ai.vectorstore.qdrant.collection-name`| The name of the collection to use in Qdrant. | -
-|`spring.ai.vectorstore.qdrant.use-tls`| Whether to use TLS(HTTPS). Defaults to false. | false
+|`spring.ai.vectorstore.qdrant.use-tls`| Whether to use TLS(HTTPS). | false
|===
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java
index ad2e0143c..f0f9beda9 100644
--- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java
@@ -43,7 +43,7 @@ public class QdrantVectorStoreAutoConfiguration {
.withCollectionName(properties.getCollectionName())
.withHost(properties.getHost())
.withPort(properties.getPort())
- .withTls(properties.useTls())
+ .withTls(properties.isUseTls())
.withApiKey(properties.getApiKey())
.build();
diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java
index 46ee9b5d5..d67c537ab 100644
--- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java
+++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java
@@ -76,7 +76,7 @@ public class QdrantVectorStoreProperties {
this.port = port;
}
- public boolean useTls() {
+ public boolean isUseTls() {
return this.useTls;
}
diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/PgVectorStorePropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/PgVectorStorePropertiesTests.java
new file mode 100644
index 000000000..8eb6a555d
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/PgVectorStorePropertiesTests.java
@@ -0,0 +1,56 @@
+/*
+ * 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.qdrant;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Christian Tzolov
+ */
+public class PgVectorStorePropertiesTests {
+
+ @Test
+ public void defaultValues() {
+ var props = new QdrantVectorStoreProperties();
+
+ assertThat(props.getCollectionName()).isNull();
+ assertThat(props.getHost()).isEqualTo("localhost");
+ assertThat(props.getPort()).isEqualTo(6334);
+ assertThat(props.isUseTls()).isFalse();
+ assertThat(props.getApiKey()).isNull();
+ }
+
+ @Test
+ public void customValues() {
+ var props = new QdrantVectorStoreProperties();
+
+ props.setCollectionName("MY_COLLECTION");
+ props.setHost("MY_HOST");
+ props.setPort(999);
+ props.setUseTls(true);
+ props.setApiKey("MY_API_KEY");
+
+ assertThat(props.getCollectionName()).isEqualTo("MY_COLLECTION");
+ assertThat(props.getHost()).isEqualTo("MY_HOST");
+ assertThat(props.getPort()).isEqualTo(999);
+ assertThat(props.isUseTls()).isTrue();
+ assertThat(props.getApiKey()).isEqualTo("MY_API_KEY");
+ }
+
+}
diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfigurationIT.java
index 35d3239e9..9146852a1 100644
--- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfigurationIT.java
+++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfigurationIT.java
@@ -54,8 +54,6 @@ public class QdrantVectorStoreAutoConfigurationIT {
private static final String COLLECTION_NAME = "test_collection";
- private static final int EMBEDDING_DIMENSION = 384;
-
private static final int QDRANT_GRPC_PORT = 6334;
@Container
@@ -66,31 +64,6 @@ public class QdrantVectorStoreAutoConfigurationIT {
new Document(getText("classpath:/test/data/time.shelter.txt")),
new Document(getText("classpath:/test/data/great.depression.txt"), Map.of("depression", "bad")));
- @BeforeAll
- static void setup() throws InterruptedException, ExecutionException {
-
- String host = qdrantContainer.getHost();
- int port = qdrantContainer.getMappedPort(QDRANT_GRPC_PORT);
- QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder(host, port, false).build());
-
- client
- .createCollectionAsync(COLLECTION_NAME,
- VectorParams.newBuilder().setDistance(Distance.Cosine).setSize(EMBEDDING_DIMENSION).build())
- .get();
-
- client.close();
- }
-
- public static String getText(String uri) {
- var resource = new DefaultResourceLoader().getResource(uri);
- try {
- return resource.getContentAsString(StandardCharsets.UTF_8);
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(QdrantVectorStoreAutoConfiguration.class))
.withUserConfiguration(Config.class)
@@ -121,6 +94,16 @@ public class QdrantVectorStoreAutoConfigurationIT {
});
}
+ public static String getText(String uri) {
+ var resource = new DefaultResourceLoader().getResource(uri);
+ try {
+ return resource.getContentAsString(StandardCharsets.UTF_8);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Configuration(proxyBeanMethods = false)
static class Config {
diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreCloudAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreCloudAutoConfigurationIT.java
new file mode 100644
index 000000000..6573b723f
--- /dev/null
+++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreCloudAutoConfigurationIT.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2024-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.autoconfigure.vectorstore.qdrant;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import io.qdrant.client.QdrantClient;
+import io.qdrant.client.QdrantGrpcClient;
+import io.qdrant.client.grpc.Collections.Distance;
+import io.qdrant.client.grpc.Collections.VectorParams;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+
+import org.springframework.ai.document.Document;
+import org.springframework.ai.embedding.EmbeddingClient;
+import org.springframework.ai.transformers.TransformersEmbeddingClient;
+import org.springframework.ai.vectorstore.SearchRequest;
+import org.springframework.ai.vectorstore.VectorStore;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.DefaultResourceLoader;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test using a free tier Qdrant Cloud instance: https://cloud.qdrant.io
+ *
+ * @author Christian Tzolov
+ * @since 0.8.1
+ */
+// NOTE: The free Qdrant Cluster and the QDRANT_API_KEY expire after 4 weeks of
+// inactivity.
+@EnabledIfEnvironmentVariable(named = "QDRANT_API_KEY", matches = ".+")
+@EnabledIfEnvironmentVariable(named = "QDRANT_HOST", matches = ".+")
+public class QdrantVectorStoreCloudAutoConfigurationIT {
+
+ private static final String COLLECTION_NAME = "test_collection";
+
+ // Because we pre-create the collection.
+ private static final int EMBEDDING_DIMENSION = 384;
+
+ private static final String CLOUD_API_KEY = System.getenv("QDRANT_API_KEY");
+
+ private static final String CLOUD_HOST = System.getenv("QDRANT_HOST");
+
+ // NOTE: The GRPC port (usually 6334) is different from the HTTP port (usually 6333)!
+ private static final int CLOUD_GRPC_PORT = 6334;
+
+ List documents = List.of(
+ new Document(getText("classpath:/test/data/spring.ai.txt"), Map.of("spring", "great")),
+ new Document(getText("classpath:/test/data/time.shelter.txt")),
+ new Document(getText("classpath:/test/data/great.depression.txt"), Map.of("depression", "bad")));
+
+ @BeforeAll
+ static void setup() throws InterruptedException, ExecutionException {
+
+ // Create a new test collection
+ try (QdrantClient client = new QdrantClient(
+ QdrantGrpcClient.newBuilder(CLOUD_HOST, CLOUD_GRPC_PORT, true).withApiKey(CLOUD_API_KEY).build())) {
+
+ if (client.listCollectionsAsync().get().stream().anyMatch(c -> c.equals(COLLECTION_NAME))) {
+ client.deleteCollectionAsync(COLLECTION_NAME).get();
+ }
+
+ var vectorParams = VectorParams.newBuilder()
+ .setDistance(Distance.Cosine)
+ .setSize(EMBEDDING_DIMENSION)
+ .build();
+
+ client.createCollectionAsync(COLLECTION_NAME, vectorParams).get();
+ }
+ }
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(QdrantVectorStoreAutoConfiguration.class))
+ .withUserConfiguration(Config.class)
+ .withPropertyValues("spring.ai.vectorstore.qdrant.port=" + CLOUD_GRPC_PORT,
+ "spring.ai.vectorstore.qdrant.host=" + CLOUD_HOST,
+ "spring.ai.vectorstore.qdrant.api-key=" + CLOUD_API_KEY,
+ "spring.ai.vectorstore.qdrant.collection-name=" + COLLECTION_NAME,
+ "spring.ai.vectorstore.qdrant.use-tls=true");
+
+ @Test
+ public void addAndSearch() {
+ contextRunner.run(context -> {
+
+ VectorStore vectorStore = context.getBean(VectorStore.class);
+
+ vectorStore.add(documents);
+
+ List results = vectorStore
+ .similaritySearch(SearchRequest.query("What is Great Depression?").withTopK(1));
+
+ assertThat(results).hasSize(1);
+ Document resultDoc = results.get(0);
+ assertThat(resultDoc.getId()).isEqualTo(documents.get(2).getId());
+ assertThat(resultDoc.getMetadata()).containsKeys("depression", "distance");
+
+ // Remove all documents from the store
+ vectorStore.delete(documents.stream().map(doc -> doc.getId()).toList());
+ results = vectorStore.similaritySearch(SearchRequest.query("Great Depression").withTopK(1));
+ assertThat(results).hasSize(0);
+ });
+ }
+
+ public static String getText(String uri) {
+ var resource = new DefaultResourceLoader().getResource(uri);
+ try {
+ return resource.getContentAsString(StandardCharsets.UTF_8);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class Config {
+
+ @Bean
+ public EmbeddingClient embeddingClient() {
+ return new TransformersEmbeddingClient();
+ }
+
+ }
+
+}
diff --git a/vector-stores/spring-ai-qdrant/README.md b/vector-stores/spring-ai-qdrant/README.md
index 00bf74013..ea76c677e 100644
--- a/vector-stores/spring-ai-qdrant/README.md
+++ b/vector-stores/spring-ai-qdrant/README.md
@@ -1 +1,22 @@
-Qdrant Vector Store
\ No newline at end of file
+# Qdrant Vector Store
+
+[Reference Documentation](https://docs.spring.io/spring-ai/reference/0.8-SNAPSHOT/api/vectordbs/qdrant.html#qdrant-vectorstore-properties)
+
+## Run locally
+
+### Accessing the Web UI
+
+First, run the Docker container:
+
+```
+docker run -p 6333:6333 -p 6334:6334 \
+ -v $(pwd)/qdrant_storage:/qdrant/storage:z \
+ qdrant/qdrant
+```
+
+The GUI is available at http://localhost:6333/dashboard
+
+## Qdrant references
+
+- https://qdrant.tech/documentation/interfaces/
+- https://github.com/qdrant/java-client
diff --git a/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java b/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java
index aea487d5c..9ddcca6be 100644
--- a/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java
+++ b/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java
@@ -30,10 +30,13 @@ import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingClient;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
+import io.qdrant.client.grpc.Collections.Distance;
+import io.qdrant.client.grpc.Collections.VectorParams;
import io.qdrant.client.grpc.JsonWithInt.Value;
import io.qdrant.client.grpc.Points.Filter;
import io.qdrant.client.grpc.Points.PointId;
@@ -47,9 +50,10 @@ import io.qdrant.client.grpc.Points.UpdateStatus;
* and similarity searching of documents in a Qdrant collection.
*
* @author Anush Shetty
+ * @author Christian Tzolov
* @since 0.8.1
*/
-public class QdrantVectorStore implements VectorStore {
+public class QdrantVectorStore implements VectorStore, InitializingBean {
private static final String CONTENT_FIELD_NAME = "doc_content";
@@ -326,4 +330,25 @@ public class QdrantVectorStore implements VectorStore {
return doubleList.stream().map(d -> d.floatValue()).toList();
}
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ // Create the collection if it does not exist.
+ if (!isCollectionExists()) {
+ var vectorParams = VectorParams.newBuilder()
+ .setDistance(Distance.Cosine)
+ .setSize(this.embeddingClient.dimensions())
+ .build();
+ this.qdrantClient.createCollectionAsync(this.collectionName, vectorParams).get();
+ }
+ }
+
+ private boolean isCollectionExists() {
+ try {
+ return this.qdrantClient.listCollectionsAsync().get().stream().anyMatch(c -> c.equals(this.collectionName));
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
}