Skip to content

Commit 1a6e79c

Browse files
sobychackomarkpollack
authored andcommitted
Enhance vector stores with consistent APIs and null safety
- Replace Document.getContent() with getText() across all vector store implementations - Fix incorrect package declarations in package-info.java files - Make builder constructors private and implement proper builder patterns - Add @nullable annotations for better null safety - Simplify PineconeVectorStore builder API by requiring essential parameters in factory method - Make static Map fields final - Clean up code and improve JavaDoc documentation The changes focus on making the vector store APIs more consistent, type-safe, and maintainable while following best practices for builder patterns and null safety.
1 parent ee8bf37 commit 1a6e79c

File tree

39 files changed

+695
-256
lines changed

39 files changed

+695
-256
lines changed

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pinecone/PineconeVectorStoreAutoConfiguration.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,9 @@ public PineconeVectorStore vectorStore(EmbeddingModel embeddingModel, PineconeVe
5555
ObjectProvider<VectorStoreObservationConvention> customObservationConvention,
5656
BatchingStrategy batchingStrategy) {
5757

58-
return PineconeVectorStore.builder(embeddingModel)
59-
.apiKey(properties.getApiKey())
60-
.environment(properties.getEnvironment())
61-
.projectId(properties.getProjectId())
62-
.indexName(properties.getIndexName())
58+
return PineconeVectorStore
59+
.builder(embeddingModel, properties.getApiKey(), properties.getProjectId(), properties.getEnvironment(),
60+
properties.getIndexName())
6361
.namespace(properties.getNamespace())
6462
.contentFieldName(properties.getContentFieldName())
6563
.distanceMetadataFieldName(properties.getDistanceMetadataFieldName())

vector-stores/spring-ai-azure-cosmos-db-store/src/main/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStore.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore;
7070
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
7171
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
72+
import org.springframework.lang.Nullable;
7273
import org.springframework.util.Assert;
7374

7475
/**
@@ -108,7 +109,8 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen
108109
* @param cosmosClient the Cosmos DB client
109110
* @param properties the configuration properties
110111
* @param embeddingModel the embedding model
111-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
112+
* @deprecated Since 1.0.0-M5, use {@link #builder(CosmosAsyncClient, EmbeddingModel)}
113+
* ()} instead
112114
*/
113115
@Deprecated(since = "1.0.0-M5", forRemoval = true)
114116
public CosmosDBVectorStore(ObservationRegistry observationRegistry,
@@ -126,7 +128,8 @@ public CosmosDBVectorStore(ObservationRegistry observationRegistry,
126128
* @param properties the configuration properties
127129
* @param embeddingModel the embedding model
128130
* @param batchingStrategy the batching strategy
129-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
131+
* @deprecated Since 1.0.0-M5, use {@link #builder(CosmosAsyncClient, EmbeddingModel)}
132+
* ()} instead
130133
*/
131134
@Deprecated(since = "1.0.0-M5", forRemoval = true)
132135
public CosmosDBVectorStore(ObservationRegistry observationRegistry,
@@ -241,7 +244,7 @@ private JsonNode mapCosmosDocument(Document document, float[] queryEmbedding) {
241244
ObjectMapper objectMapper = new ObjectMapper();
242245

243246
String id = document.getId();
244-
String content = document.getContent();
247+
String content = document.getText();
245248

246249
// Convert metadata and embedding directly to JsonNode
247250
JsonNode metadataNode = objectMapper.valueToTree(document.getMetadata());
@@ -430,10 +433,13 @@ public static class CosmosDBBuilder extends AbstractVectorStoreBuilder<CosmosDBB
430433

431434
private final CosmosAsyncClient cosmosClient;
432435

436+
@Nullable
433437
private String containerName;
434438

439+
@Nullable
435440
private String databaseName;
436441

442+
@Nullable
437443
private String partitionKeyPath;
438444

439445
private int vectorStoreThroughput = 400;
@@ -444,13 +450,7 @@ public static class CosmosDBBuilder extends AbstractVectorStoreBuilder<CosmosDBB
444450

445451
private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy();
446452

447-
/**
448-
* Sets the Cosmos DB client.
449-
* @param cosmosClient the client to use
450-
* @return the builder instance
451-
* @throws IllegalArgumentException if cosmosClient is null
452-
*/
453-
public CosmosDBBuilder(CosmosAsyncClient cosmosClient, EmbeddingModel embeddingModel) {
453+
private CosmosDBBuilder(CosmosAsyncClient cosmosClient, EmbeddingModel embeddingModel) {
454454
super(embeddingModel);
455455
Assert.notNull(cosmosClient, "CosmosClient must not be null");
456456
this.cosmosClient = cosmosClient;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Provides the API for embedding observations.
19+
*/
20+
@NonNullApi
21+
@NonNullFields
22+
package org.springframework.ai.vectorstore.cosmosdb;
23+
24+
import org.springframework.lang.NonNullApi;
25+
import org.springframework.lang.NonNullFields;

vector-stores/spring-ai-azure-store/src/main/java/org/springframework/ai/vectorstore/azure/AzureVectorStore.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
6363
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
6464
import org.springframework.beans.factory.InitializingBean;
65+
import org.springframework.lang.Nullable;
6566
import org.springframework.util.Assert;
6667
import org.springframework.util.CollectionUtils;
6768
import org.springframework.util.StringUtils;
@@ -122,6 +123,7 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements
122123
*/
123124
private final List<MetadataField> filterMetadataFields;
124125

126+
@Nullable
125127
private SearchClient searchClient;
126128

127129
private int defaultTopK;
@@ -135,7 +137,8 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements
135137
* @param searchIndexClient the Azure search index client
136138
* @param embeddingModel the embedding model to use
137139
* @param initializeSchema whether to initialize schema
138-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
140+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
141+
* ()} instead
139142
*/
140143
@Deprecated(since = "1.0.0-M5", forRemoval = true)
141144
public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel,
@@ -149,7 +152,8 @@ public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embe
149152
* @param embeddingModel the embedding model to use
150153
* @param initializeSchema whether to initialize schema
151154
* @param filterMetadataFields list of metadata fields for filtering
152-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
155+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
156+
* ()} instead
153157
*/
154158
@Deprecated(since = "1.0.0-M5", forRemoval = true)
155159
public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel,
@@ -166,7 +170,8 @@ public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embe
166170
* @param filterMetadataFields list of metadata fields for filtering
167171
* @param observationRegistry the observation registry
168172
* @param customObservationConvention the custom observation convention
169-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
173+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
174+
* ()} instead
170175
*/
171176
@Deprecated(since = "1.0.0-M5", forRemoval = true)
172177
public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel,
@@ -208,8 +213,8 @@ public static AzureBuilder builder(SearchIndexClient searchIndexClient, Embeddin
208213
/**
209214
* Change the Index Name.
210215
* @param indexName The Azure VectorStore index name to use.
211-
* @deprecated Since 1.0.0-M5, use {@link #builder()} with
212-
* {@link AzureBuilder#indexName(String)} instead
216+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
217+
* ()} with {@link AzureBuilder#indexName(String)} instead
213218
*/
214219
@Deprecated(since = "1.0.0-M5", forRemoval = true)
215220
public void setIndexName(String indexName) {
@@ -220,8 +225,8 @@ public void setIndexName(String indexName) {
220225
/**
221226
* Sets the a default maximum number of similar documents returned.
222227
* @param topK The default maximum number of similar documents returned.
223-
* @deprecated Since 1.0.0-M5, use {@link #builder()} with
224-
* {@link AzureBuilder#indexName(String)} instead
228+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
229+
* ()} with {@link AzureBuilder#indexName(String)} instead
225230
*/
226231
@Deprecated(since = "1.0.0-M5", forRemoval = true)
227232
public void setDefaultTopK(int topK) {
@@ -233,8 +238,8 @@ public void setDefaultTopK(int topK) {
233238
* Sets the a default similarity threshold for returned documents.
234239
* @param similarityThreshold The a default similarity threshold for returned
235240
* documents.
236-
* @deprecated Since 1.0.0-M5, use {@link #builder()} with
237-
* {@link AzureBuilder#indexName(String)} instead
241+
* @deprecated Since 1.0.0-M5, use {@link #builder(SearchIndexClient, EmbeddingModel)}
242+
* ()} with {@link AzureBuilder#indexName(String)} instead
238243
*/
239244
@Deprecated(since = "1.0.0-M5", forRemoval = true)
240245
public void setDefaultSimilarityThreshold(Double similarityThreshold) {
@@ -258,7 +263,7 @@ public void doAdd(List<Document> documents) {
258263
SearchDocument searchDocument = new SearchDocument();
259264
searchDocument.put(ID_FIELD_NAME, document.getId());
260265
searchDocument.put(EMBEDDING_FIELD_NAME, embeddings.get(documents.indexOf(document)));
261-
searchDocument.put(CONTENT_FIELD_NAME, document.getContent());
266+
searchDocument.put(CONTENT_FIELD_NAME, document.getText());
262267
searchDocument.put(METADATA_FIELD_NAME, new JSONObject(document.getMetadata()).toJSONString());
263268

264269
// Add the filterable metadata fields as top level fields, allowing filler
@@ -481,13 +486,7 @@ public static class AzureBuilder extends AbstractVectorStoreBuilder<AzureBuilder
481486

482487
private String indexName = DEFAULT_INDEX_NAME;
483488

484-
/**
485-
* Sets the Azure search index client.
486-
* @param searchIndexClient the client to use
487-
* @return the builder instance
488-
* @throws IllegalArgumentException if searchIndexClient is null
489-
*/
490-
public AzureBuilder(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) {
489+
private AzureBuilder(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) {
491490
super(embeddingModel);
492491
Assert.notNull(searchIndexClient, "SearchIndexClient must not be null");
493492
this.searchIndexClient = searchIndexClient;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Provides the API for embedding observations.
19+
*/
20+
@NonNullApi
21+
@NonNullFields
22+
package org.springframework.ai.vectorstore.azure;
23+
24+
import org.springframework.lang.NonNullApi;
25+
import org.springframework.lang.NonNullFields;

vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,15 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
235235
private final boolean returnEmbeddings;
236236

237237
/**
238-
* @deprecated since 1.0.0-M5, use {@link #builder()} instead
238+
* @deprecated since 1.0.0-M5, use {@link #builder(EmbeddingModel)} ()} instead
239239
*/
240240
@Deprecated(since = "1.0.0-M5", forRemoval = true)
241241
public CassandraVectorStore(CassandraVectorStoreConfig conf, EmbeddingModel embeddingModel) {
242242
this(conf, embeddingModel, ObservationRegistry.NOOP, null, new TokenCountBatchingStrategy());
243243
}
244244

245245
/**
246-
* @deprecated since 1.0.0-M5, use {@link #builder()} instead
246+
* @deprecated since 1.0.0-M5, use {@link #builder(EmbeddingModel)} ()} instead
247247
*/
248248
@Deprecated(since = "1.0.0-M5", forRemoval = true)
249249
public CassandraVectorStore(CassandraVectorStoreConfig conf, EmbeddingModel embeddingModel,
@@ -319,7 +319,7 @@ public void doAdd(List<Document> documents) {
319319
builder = builder.set(keyColumn.name(), primaryKeyValues.get(k), keyColumn.javaType());
320320
}
321321

322-
builder = builder.setString(this.schema.content(), d.getContent())
322+
builder = builder.setString(this.schema.content(), d.getText())
323323
.setVector(this.schema.embedding(),
324324
CqlVector.newInstance(EmbeddingUtils.toList(embeddings.get(documents.indexOf(d)))),
325325
Float.class);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Provides the API for embedding observations.
19+
*/
20+
@NonNullApi
21+
@NonNullFields
22+
package org.springframework.ai.vectorstore.cassandra;
23+
24+
import org.springframework.lang.NonNullApi;
25+
import org.springframework.lang.NonNullFields;

vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStore.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ public enum DistanceType {
143143
* Creates a new CoherenceVectorStore with minimal configuration.
144144
* @param embeddingModel the embedding model to use
145145
* @param session the Coherence session
146-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
146+
* @deprecated Since 1.0.0-M5, use {@link #builder(Session, EmbeddingModel)} ()}
147+
* instead
147148
*/
148149
@Deprecated(since = "1.0.0-M5", forRemoval = true)
149150
public CoherenceVectorStore(EmbeddingModel embeddingModel, Session session) {
@@ -177,7 +178,8 @@ public static CoherenceBuilder builder(Session session, EmbeddingModel embedding
177178
}
178179

179180
/**
180-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
181+
* @deprecated Since 1.0.0-M5, use {@link #builder(Session, EmbeddingModel)} ()}
182+
* instead
181183
*/
182184
@Deprecated(since = "1.0.0-M5", forRemoval = true)
183185
public CoherenceVectorStore setMapName(String mapName) {
@@ -186,7 +188,8 @@ public CoherenceVectorStore setMapName(String mapName) {
186188
}
187189

188190
/**
189-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
191+
* @deprecated Since 1.0.0-M5, use {@link #builder(Session, EmbeddingModel)} ()}
192+
* instead
190193
*/
191194
@Deprecated(since = "1.0.0-M5", forRemoval = true)
192195
public CoherenceVectorStore setDistanceType(DistanceType distanceType) {
@@ -195,7 +198,8 @@ public CoherenceVectorStore setDistanceType(DistanceType distanceType) {
195198
}
196199

197200
/**
198-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
201+
* @deprecated Since 1.0.0-M5, use {@link #builder(Session, EmbeddingModel)} ()}
202+
* instead
199203
*/
200204
@Deprecated(since = "1.0.0-M5", forRemoval = true)
201205
public CoherenceVectorStore setIndexType(IndexType indexType) {
@@ -204,7 +208,8 @@ public CoherenceVectorStore setIndexType(IndexType indexType) {
204208
}
205209

206210
/**
207-
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
211+
* @deprecated Since 1.0.0-M5, use {@link #builder(Session, EmbeddingModel)} ()}
212+
* instead
208213
*/
209214
@Deprecated(since = "1.0.0-M5", forRemoval = true)
210215
public CoherenceVectorStore setForcedNormalization(boolean forcedNormalization) {
@@ -217,7 +222,7 @@ public void doAdd(final List<Document> documents) {
217222
Map<DocumentChunk.Id, DocumentChunk> chunks = new HashMap<>((int) Math.ceil(documents.size() / 0.75f));
218223
for (Document doc : documents) {
219224
var id = toChunkId(doc.getId());
220-
var chunk = new DocumentChunk(doc.getContent(), doc.getMetadata(),
225+
var chunk = new DocumentChunk(doc.getText(), doc.getMetadata(),
221226
toFloat32Vector(this.embeddingModel.embed(doc)));
222227
chunks.put(id, chunk);
223228
}
@@ -342,13 +347,7 @@ public static class CoherenceBuilder extends AbstractVectorStoreBuilder<Coherenc
342347

343348
private IndexType indexType = IndexType.NONE;
344349

345-
/**
346-
* Sets the Coherence session.
347-
* @param session the session to use
348-
* @return the builder instance
349-
* @throws IllegalArgumentException if session is null
350-
*/
351-
public CoherenceBuilder(Session session, EmbeddingModel embeddingModel) {
350+
private CoherenceBuilder(Session session, EmbeddingModel embeddingModel) {
352351
super(embeddingModel);
353352
Assert.notNull(session, "Session must not be null");
354353
this.session = session;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2023-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Provides the API for embedding observations.
19+
*/
20+
@NonNullApi
21+
@NonNullFields
22+
package org.springframework.ai.vectorstore.coherence;
23+
24+
import org.springframework.lang.NonNullApi;
25+
import org.springframework.lang.NonNullFields;

0 commit comments

Comments
 (0)