Qdrant improvements
- Update docs - Allow colleciton auto-creation if missing - Add cloud IT : QdrantVectorStoreCloudAutoConfigurationIT - Add auto-configuration properties tests: PgVectorStorePropertiesTests
This commit is contained in:
@@ -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]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
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]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
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=<host of your qdrant instance>
|
||||
spring.ai.vectorstore.qdrant.port=<the GRPC port of your qdrant instance>
|
||||
spring.ai.vectorstore.qdrant.api-key=<your api key>
|
||||
spring.ai.vectorstore.qdrant.collection-name=<The name of the collection to use in Qdrant>
|
||||
|
||||
# API key if needed, e.g. OpenAI
|
||||
spring.ai.openai.api.key=<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 <Document> 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<Document> 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=<host of your qdrant instance>
|
||||
spring.ai.vectorstore.qdrant.port=<port of your qdrant instance>
|
||||
spring.ai.vectorstore.qdrant.api-key=<your api key>
|
||||
spring.ai.vectorstore.qdrant.collection-name=<The name of the collection to use in Qdrant>
|
||||
|
||||
# API key if needed, e.g. OpenAI
|
||||
spring.ai.openai.api.key=<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
|
||||
|===
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public class QdrantVectorStoreProperties {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public boolean useTls() {
|
||||
public boolean isUseTls() {
|
||||
return this.useTls;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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<Document> 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<Document> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1,22 @@
|
||||
Qdrant Vector Store
|
||||
# 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user