Skip to content

Commit 0c7ade2

Browse files
committed
Qdrant vector store builder refactoring
1 parent 9e18652 commit 0c7ade2

File tree

4 files changed

+135
-17
lines changed

4 files changed

+135
-17
lines changed

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,14 @@ public QdrantVectorStore vectorStore(EmbeddingModel embeddingModel, QdrantVector
7777
QdrantClient qdrantClient, ObjectProvider<ObservationRegistry> observationRegistry,
7878
ObjectProvider<VectorStoreObservationConvention> customObservationConvention,
7979
BatchingStrategy batchingStrategy) {
80-
return new QdrantVectorStore(qdrantClient, properties.getCollectionName(), embeddingModel,
81-
properties.isInitializeSchema(), observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP),
82-
customObservationConvention.getIfAvailable(() -> null), batchingStrategy);
80+
return QdrantVectorStore.builder(qdrantClient)
81+
.collectionName(properties.getCollectionName())
82+
.embeddingModel(embeddingModel)
83+
.initializeSchema(properties.isInitializeSchema())
84+
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
85+
.customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
86+
.batchingStrategy(batchingStrategy)
87+
.build();
8388
}
8489

8590
static class PropertiesQdrantConnectionDetails implements QdrantConnectionDetails {

vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java

Lines changed: 114 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
4343
import org.springframework.ai.model.EmbeddingUtils;
4444
import org.springframework.ai.observation.conventions.VectorStoreProvider;
45+
import org.springframework.ai.vectorstore.AbstractVectorStoreBuilder;
4546
import org.springframework.ai.vectorstore.SearchRequest;
4647
import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore;
4748
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
@@ -67,8 +68,6 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements
6768

6869
private static final String CONTENT_FIELD_NAME = "doc_content";
6970

70-
private final EmbeddingModel embeddingModel;
71-
7271
private final QdrantClient qdrantClient;
7372

7473
private final String collectionName;
@@ -85,7 +84,9 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements
8584
* @param collectionName The name of the collection to use in Qdrant.
8685
* @param embeddingModel The client for embedding operations.
8786
* @param initializeSchema A boolean indicating whether to initialize the schema.
87+
* @deprecated Use {@link #builder(QdrantClient)}
8888
*/
89+
@Deprecated(forRemoval = true, since = "1.0.0-M5")
8990
public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel,
9091
boolean initializeSchema) {
9192
this(qdrantClient, collectionName, embeddingModel, initializeSchema, ObservationRegistry.NOOP, null,
@@ -100,22 +101,48 @@ public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, Embed
100101
* @param initializeSchema A boolean indicating whether to initialize the schema.
101102
* @param observationRegistry The observation registry to use.
102103
* @param customObservationConvention The custom search observation convention to use.
104+
* @deprecated Use {@link #builder(QdrantClient)}
103105
*/
106+
@Deprecated(forRemoval = true, since = "1.0.0-M5")
104107
public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel,
105108
boolean initializeSchema, ObservationRegistry observationRegistry,
106109
VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) {
107110

108-
super(observationRegistry, customObservationConvention);
111+
this(builder(qdrantClient).embeddingModel(embeddingModel)
112+
.collectionName(collectionName)
113+
.initializeSchema(initializeSchema)
114+
.observationRegistry(observationRegistry)
115+
.customObservationConvention(customObservationConvention)
116+
.batchingStrategy(batchingStrategy));
117+
}
109118

110-
Assert.notNull(qdrantClient, "QdrantClient must not be null");
111-
Assert.notNull(collectionName, "collectionName must not be null");
112-
Assert.notNull(embeddingModel, "EmbeddingModel must not be null");
119+
/**
120+
* Protected constructor for creating a QdrantVectorStore instance using the builder
121+
* pattern.
122+
* @param builder the {@link QdrantBuilder} containing all configuration settings
123+
* @throws IllegalArgumentException if qdrant client is missing
124+
* @see QdrantBuilder
125+
* @since 1.0.0
126+
*/
127+
protected QdrantVectorStore(QdrantBuilder builder) {
128+
super(builder);
129+
130+
Assert.notNull(builder.qdrantClient, "QdrantClient must not be null");
131+
132+
this.qdrantClient = builder.qdrantClient;
133+
this.collectionName = builder.collectionName;
134+
this.initializeSchema = builder.initializeSchema;
135+
this.batchingStrategy = builder.batchingStrategy;
136+
}
113137

114-
this.initializeSchema = initializeSchema;
115-
this.embeddingModel = embeddingModel;
116-
this.collectionName = collectionName;
117-
this.qdrantClient = qdrantClient;
118-
this.batchingStrategy = batchingStrategy;
138+
/**
139+
* Creates a new QdrantBuilder instance. This is the recommended way to instantiate a
140+
* QdrantVectorStore.
141+
* @param qdrantClient the client for interfacing with Qdrant
142+
* @return a new QdrantBuilder instance
143+
*/
144+
public static QdrantBuilder builder(QdrantClient qdrantClient) {
145+
return new QdrantBuilder(qdrantClient);
119146
}
120147

121148
/**
@@ -272,4 +299,80 @@ public VectorStoreObservationContext.Builder createObservationContextBuilder(Str
272299

273300
}
274301

302+
/**
303+
* Builder for creating instances of {@link QdrantVectorStore}. This builder provides
304+
* a fluent API for configuring all aspects of the vector store.
305+
*
306+
* @since 1.0.0
307+
*/
308+
public static final class QdrantBuilder extends AbstractVectorStoreBuilder<QdrantBuilder> {
309+
310+
private final QdrantClient qdrantClient;
311+
312+
private String collectionName = DEFAULT_COLLECTION_NAME;
313+
314+
private boolean initializeSchema = false;
315+
316+
private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy();
317+
318+
/**
319+
* Creates a new builder instance with the required QdrantClient and
320+
* EmbeddingModel.
321+
* @param qdrantClient the client for Qdrant operations
322+
* @throws IllegalArgumentException if qdrantClient is null
323+
*/
324+
QdrantBuilder(QdrantClient qdrantClient) {
325+
Assert.notNull(qdrantClient, "QdrantClient must not be null");
326+
this.qdrantClient = qdrantClient;
327+
}
328+
329+
/**
330+
* Configures the Qdrant collection name.
331+
* @param collectionName the name of the collection to use (defaults to
332+
* {@value DEFAULT_COLLECTION_NAME})
333+
* @return this builder instance
334+
* @throws IllegalArgumentException if collectionName is null or empty
335+
*/
336+
public QdrantBuilder collectionName(String collectionName) {
337+
Assert.hasText(collectionName, "collectionName must not be empty");
338+
this.collectionName = collectionName;
339+
return this;
340+
}
341+
342+
/**
343+
* Configures whether to initialize the collection schema.
344+
* @param initializeSchema true to initialize schema automatically
345+
* @return this builder instance
346+
*/
347+
public QdrantBuilder initializeSchema(boolean initializeSchema) {
348+
this.initializeSchema = initializeSchema;
349+
return this;
350+
}
351+
352+
/**
353+
* Configures the strategy for batching operations.
354+
* @param batchingStrategy the batching strategy to use
355+
* @return this builder instance
356+
* @throws IllegalArgumentException if batchingStrategy is null
357+
*/
358+
public QdrantBuilder batchingStrategy(BatchingStrategy batchingStrategy) {
359+
Assert.notNull(batchingStrategy, "BatchingStrategy must not be null");
360+
this.batchingStrategy = batchingStrategy;
361+
return this;
362+
}
363+
364+
/**
365+
* Builds and returns a new QdrantVectorStore instance with the configured
366+
* settings.
367+
* @return a new QdrantVectorStore instance
368+
* @throws IllegalStateException if the builder configuration is invalid
369+
*/
370+
@Override
371+
public QdrantVectorStore build() {
372+
validate();
373+
return new QdrantVectorStore(this);
374+
}
375+
376+
}
377+
275378
}

vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,11 @@ public QdrantClient qdrantClient() {
254254

255255
@Bean
256256
public VectorStore qdrantVectorStore(EmbeddingModel embeddingModel, QdrantClient qdrantClient) {
257-
return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true);
257+
return QdrantVectorStore.builder(qdrantClient)
258+
.collectionName(COLLECTION_NAME)
259+
.embeddingModel(embeddingModel)
260+
.initializeSchema(true)
261+
.build();
258262
}
259263

260264
@Bean

vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreObservationIT.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,14 @@ public QdrantClient qdrantClient() {
195195
@Bean
196196
public VectorStore qdrantVectorStore(EmbeddingModel embeddingModel, QdrantClient qdrantClient,
197197
ObservationRegistry observationRegistry) {
198-
return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true, observationRegistry, null,
199-
new TokenCountBatchingStrategy());
198+
return QdrantVectorStore.builder(qdrantClient)
199+
.collectionName(COLLECTION_NAME)
200+
.embeddingModel(embeddingModel)
201+
.initializeSchema(true)
202+
.observationRegistry(observationRegistry)
203+
.customObservationConvention(null)
204+
.batchingStrategy(new TokenCountBatchingStrategy())
205+
.build();
200206
}
201207

202208
@Bean

0 commit comments

Comments
 (0)