Skip to content

Commit 067a33d

Browse files
geetrawatLouis Jacomejhuynh1
authored andcommitted
Improved GemFire support
- Adds spring boot auto-configuration support for GemFireVectorStore - Adds integration test GemFireVectorStoreAutoConfigurationIT - Includes gemfire-testcontainers in integration tests - Adds unit test GemFireVectorStorePropertiesTests - Refactors GemFireVectorStore.java extracting GemFireVectorStoreConfig.java - Renames spring-ai-gemfire to spring-ai-gemfire-store - Adds GemFireConnectionDetails - Adds GemFireVectorStoreProperties with default values - Remove gemfire-release-repo maven repository Co-authored-by: Louis Jacome <[email protected]> Co-authored-by: Jason Huyn <[email protected]>
1 parent 58a30f7 commit 067a33d

File tree

15 files changed

+979
-251
lines changed

15 files changed

+979
-251
lines changed

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<module>spring-ai-spring-boot-starters/spring-ai-starter-cassandra-store</module>
4949
<module>spring-ai-spring-boot-starters/spring-ai-starter-chroma-store</module>
5050
<module>spring-ai-spring-boot-starters/spring-ai-starter-elasticsearch-store</module>
51+
<module>spring-ai-spring-boot-starters/spring-ai-starter-gemfire-store</module>
5152
<module>spring-ai-spring-boot-starters/spring-ai-starter-hanadb-store</module>
5253
<module>spring-ai-spring-boot-starters/spring-ai-starter-milvus-store</module>
5354
<module>spring-ai-spring-boot-starters/spring-ai-starter-mongodb-atlas-store</module>
@@ -166,6 +167,7 @@
166167
<postgresql.version>42.7.2</postgresql.version>
167168
<elasticsearch-java.version>8.13.3</elasticsearch-java.version>
168169
<milvus.version>2.3.4</milvus.version>
170+
<gemfire.testcontainers.version>2.3.0</gemfire.testcontainers.version>
169171
<pinecone.version>0.8.0</pinecone.version>
170172
<fastjson.version>2.0.46</fastjson.version>
171173
<azure-search.version>11.6.1</azure-search.version>

spring-ai-bom/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@
446446
<version>${project.version}</version>
447447
</dependency>
448448

449+
<dependency>
450+
<groupId>org.springframework.ai</groupId>
451+
<artifactId>spring-ai-gemfire-store-spring-boot-starter</artifactId>
452+
<version>${project.version}</version>
453+
</dependency>
454+
449455
<dependency>
450456
<groupId>org.springframework.ai</groupId>
451457
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/gemfire.adoc

Lines changed: 81 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,135 @@
11
= GemFire Vector Store
22

3-
This section walks you through setting up the GemFire VectorStore to store document embeddings and perform similarity searches.
3+
This section walks you through setting up the `GemFireVectorStore` to store document embeddings and perform similarity searches.
44

5-
link:https://tanzu.vmware.com/gemfire[GemFire] is an ultra high speed in-memory data and compute grid, with vector extensions to store and search vectors efficiently.
5+
link:https://tanzu.vmware.com/gemfire[GemFire] is a distributed, in-memory, key-value store performing read and write operations at blazingly fast speeds. It offers highly available parallel message queues, continuous availability, and an event-driven architecture you can scale dynamically without downtime. As your data size requirements increase to support high-performance, real-time apps, GemFire can easily scale linearly.
66

7-
link:https://docs.vmware.com/en/VMware-GemFire-VectorDB/1.0/gemfire-vectordb/overview.html[GemFire VectorDB] extends GemFire's capabilities, serving as a versatile vector database that efficiently stores, retrieves, and performs vector searches through a distributed and resilient infrastructure:
8-
9-
Capabilities:
10-
- Create Indexes
11-
- Store vectors and the associated metadata
12-
- Perform vector searches based on similarity
7+
link:https://docs.vmware.com/en/VMware-GemFire-VectorDB/1.0/gemfire-vectordb/overview.html[GemFire VectorDB] extends GemFire's capabilities, serving as a versatile vector database that efficiently stores, retrieves, and performs vector similarity searches.
138

149
== Prerequisites
1510

16-
Access to a GemFire cluster with the link:https://docs.vmware.com/en/VMware-GemFire-VectorDB/1.0/gemfire-vectordb/install.html[GemFire Vector Database] extension installed.
17-
You can download the GemFire VectorDB extension from the link:https://network.pivotal.io/products/gemfire-vectordb/[VMware Tanzu Network] after signing in.
11+
1. A GemFire cluster with the GemFire VectorDB extension enabled
12+
- link:https://docs.vmware.com/en/VMware-GemFire-VectorDB/1.0/gemfire-vectordb/install.html[Install GemFire VectorDB extension]
1813

19-
== Dependencies
14+
2. An `EmbeddingModel` bean to compute the document embeddings. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information.
15+
An option that runs locally on your machine is xref:api/embeddings/onnx.adoc[ONNX] and the all-MiniLM-L6-v2 Sentence Transformers.
2016

21-
Add these dependencies to your project:
17+
== Auto-configuration
2218

23-
- Embedding Model boot starter, required for calculating embeddings.
24-
- Transformers Embedding (Local) and follow the ONNX Transformers Embedding instructions.
19+
Add the GemFire VectorStore Spring Boot starter to you project's Maven build file `pom.xml`:
2520

26-
[source,xml]
21+
[source, xml]
2722
----
2823
<dependency>
29-
<groupId>org.springframework.ai</groupId>
30-
<artifactId>spring-ai-transformers</artifactId>
24+
<groupId>org.springframework.ai</groupId>
25+
<artifactId>spring-ai-gemfire-store-spring-boot-starter</artifactId>
3126
</dependency>
3227
----
3328

34-
- Add the GemFire VectorDB dependencies
29+
or to your Gradle `build.gradle` file
30+
31+
[source, xml]
32+
----
33+
dependencies {
34+
implementation 'org.springframework.ai:spring-ai-gemfire-store-spring-boot-starter'
35+
}
36+
----
37+
38+
=== Configuration properties
39+
40+
You can use the following properties in your Spring Boot configuration to further configure the `GemFireVectorStore`.
41+
42+
|===
43+
|Property|Default value
44+
45+
|`spring.ai.vectorstore.gemfire.host`|localhost
46+
|`spring.ai.vectorstore.gemfire.port`|8080
47+
|`spring.ai.vectorstore.gemfire.index-name`|spring-ai-gemfire-store
48+
|`spring.ai.vectorstore.gemfire.beam-width`|100
49+
|`spring.ai.vectorstore.gemfire.max-connections`|16
50+
|`spring.ai.vectorstore.gemfire.vector-similarity-function`|COSINE
51+
|`spring.ai.vectorstore.gemfire.fields`|[]
52+
|`spring.ai.vectorstore.gemfire.buckets`|0
53+
|===
54+
55+
56+
== Manual Configuration
3557

36-
[source,xml]
58+
To use just the `GemFireVectorStore`, without Spring Boot's Auto-configuration add the following dependency to your project’s Maven `pom.xml`:
59+
60+
[source, xml]
3761
----
3862
<dependency>
3963
<groupId>org.springframework.ai</groupId>
4064
<artifactId>spring-ai-gemfire-store</artifactId>
4165
</dependency>
4266
----
4367

68+
For Gradle users, add the following to your `build.gradle` file under the dependencies block to use just the `GemFireVectorStore`:
4469

45-
TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.
46-
70+
[souce, xml]
71+
----
72+
dependencies {
73+
implementation 'org.springframework.ai:spring-ai-gemfire-store'
74+
}
75+
----
4776

48-
== Sample Code
77+
== Usage
4978

50-
- To configure GemFire in your application, use the following setup:
79+
Here is a sample that creates an instance of the `GemfireVectorStore` instead of using AutoConfiguration
5180

5281
[source,java]
5382
----
5483
@Bean
55-
public GemFireVectorStoreConfig gemFireVectorStoreConfig() {
56-
return GemFireVectorStoreConfig.builder()
57-
.withUrl("http://localhost:8080")
58-
.withIndexName("spring-ai-test-index")
59-
.build();
84+
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
85+
return new GemFireVectorStore(new GemFireVectorStoreConfig()
86+
.setIndexName("my-vector-index")
87+
.setPort(7071), embeddingClient);
6088
}
6189
----
6290

63-
- Create a GemFireVectorStore instance connected to your GemFire VectorDB:
91+
[NOTE]
92+
====
93+
The GemFire VectorStore does not yet support xref:api/vectordbs.adoc#metadata-filters[metadata filters].
94+
====
95+
96+
[NOTE]
97+
====
98+
The default configuration connects to a GemFire cluster at `localhost:8080`
99+
====
100+
101+
- In your application, create a few documents:
64102

65103
[source,java]
66104
----
67-
@Bean
68-
public VectorStore vectorStore(GemFireVectorStoreConfig config, EmbeddingModel embeddingModel) {
69-
return new GemFireVectorStore(config, embeddingModel);
70-
}
105+
List<Document> documents = List.of(
106+
new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("country", "UK", "year", 2020)),
107+
new Document("The World is Big and Salvation Lurks Around the Corner", Map.of()),
108+
new Document("You walk forward facing the past and you turn back toward the future.", Map.of("country", "NL", "year", 2023)));
71109
----
72-
- Create a Vector Index which will configure GemFire region.
73110

74-
[source,java]
75-
----
76-
public void createIndex() {
77-
try {
78-
CreateRequest createRequest = new CreateRequest();
79-
createRequest.setName(INDEX_NAME);
80-
createRequest.setBeamWidth(20);
81-
createRequest.setMaxConnections(16);
82-
ObjectMapper objectMapper = new ObjectMapper();
83-
String index = objectMapper.writeValueAsString(createRequest);
84-
client.post()
85-
.contentType(MediaType.APPLICATION_JSON)
86-
.bodyValue(index)
87-
.retrieve()
88-
.bodyToMono(Void.class)
89-
.block();
90-
}
91-
catch (Exception e) {
92-
logger.warn("An unexpected error occurred while creating the index");
93-
}
94-
}
95-
----
96-
97-
- Create some documents:
111+
- Add the documents to the vector store:
98112

99113
[source,java]
100114
----
101-
List<Document> documents = List.of(
102-
new Document("1", getText("classpath:/test/data/spring.ai.txt"), Map.of("meta1", "meta1")),
103-
new Document("2", getText("classpath:/test/data/time.shelter.txt"), Map.of()),
104-
new Document("3", getText("classpath:/test/data/great.depression.txt"), Map.of("meta2", "meta2")));
115+
vectorStore.add(documents);
105116
----
106117

107-
- Add the documents to GemFire VectorDB:
118+
- And to retrieve documents using similarity search:
108119

109120
[source,java]
110121
----
111-
vectorStore.add(List.of(document));
122+
List<Document> results = vectorStore.similaritySearch(
123+
SearchRequest.query("Spring").withTopK(5));
112124
----
113125

114-
- And finally, retrieve documents similar to a query:
126+
You should retrieve the document containing the text "Spring AI rocks!!".
115127

128+
You can also limit the number of results using a similarity threshold:
116129
[source,java]
117130
----
118-
List<Document> results = vectorStore.similaritySearch("Spring", 5);
131+
List<Document> results = vectorStore.similaritySearch(
132+
SearchRequest.query("Spring").withTopK(5)
133+
.withSimilarityThreshold(0.5d));
119134
----
120135

121-
If all goes well, you should retrieve the document containing the text "Spring AI rocks!!".
122-

spring-ai-spring-boot-autoconfigure/pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,13 @@
297297
<optional>true</optional>
298298
</dependency>
299299

300+
<dependency>
301+
<groupId>org.springframework.ai</groupId>
302+
<artifactId>spring-ai-gemfire-store</artifactId>
303+
<version>${project.parent.version}</version>
304+
<optional>true</optional>
305+
</dependency>
306+
300307
<dependency>
301308
<groupId>org.springframework.ai</groupId>
302309
<artifactId>spring-ai-minimax</artifactId>
@@ -458,6 +465,13 @@
458465
<scope>test</scope>
459466
</dependency>
460467

468+
<dependency>
469+
<groupId>dev.gemfire</groupId>
470+
<artifactId>gemfire-testcontainers</artifactId>
471+
<version>2.3.0</version>
472+
<scope>test</scope>
473+
</dependency>
474+
461475
</dependencies>
462476

463477
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2024 - 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+
package org.springframework.ai.autoconfigure.vectorstore.gemfire;
17+
18+
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
19+
20+
/**
21+
* @author Geet Rawat
22+
*/
23+
public interface GemFireConnectionDetails extends ConnectionDetails {
24+
25+
String getHost();
26+
27+
int getPort();
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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+
package org.springframework.ai.autoconfigure.vectorstore.gemfire;
18+
19+
import org.springframework.ai.embedding.EmbeddingModel;
20+
import org.springframework.ai.vectorstore.GemFireVectorStore;
21+
import org.springframework.ai.vectorstore.GemFireVectorStoreConfig;
22+
import org.springframework.boot.autoconfigure.AutoConfiguration;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
26+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
27+
import org.springframework.context.annotation.Bean;
28+
29+
/**
30+
* @author Geet Rawat
31+
*/
32+
@AutoConfiguration
33+
@ConditionalOnClass({ GemFireVectorStore.class, EmbeddingModel.class })
34+
@EnableConfigurationProperties(GemFireVectorStoreProperties.class)
35+
@ConditionalOnProperty(prefix = "spring.ai.vectorstore.gemfire", value = { "index-name" })
36+
public class GemFireVectorStoreAutoConfiguration {
37+
38+
@Bean
39+
@ConditionalOnMissingBean(GemFireConnectionDetails.class)
40+
GemFireVectorStoreAutoConfiguration.PropertiesGemFireConnectionDetails gemfireConnectionDetails(
41+
GemFireVectorStoreProperties properties) {
42+
return new GemFireVectorStoreAutoConfiguration.PropertiesGemFireConnectionDetails(properties);
43+
}
44+
45+
@Bean
46+
@ConditionalOnMissingBean
47+
public GemFireVectorStore gemfireVectorStore(EmbeddingModel embeddingModel, GemFireVectorStoreProperties properties,
48+
GemFireConnectionDetails gemFireConnectionDetails) {
49+
var config = new GemFireVectorStoreConfig();
50+
51+
config.setHost(gemFireConnectionDetails.getHost())
52+
.setPort(gemFireConnectionDetails.getPort())
53+
.setIndexName(properties.getIndexName())
54+
.setBeamWidth(properties.getBeamWidth())
55+
.setMaxConnections(properties.getMaxConnections())
56+
.setBuckets(properties.getBuckets())
57+
.setVectorSimilarityFunction(properties.getVectorSimilarityFunction())
58+
.setFields(properties.getFields())
59+
.setSslEnabled(properties.isSslEnabled());
60+
return new GemFireVectorStore(config, embeddingModel);
61+
}
62+
63+
private static class PropertiesGemFireConnectionDetails implements GemFireConnectionDetails {
64+
65+
private final GemFireVectorStoreProperties properties;
66+
67+
PropertiesGemFireConnectionDetails(GemFireVectorStoreProperties properties) {
68+
this.properties = properties;
69+
}
70+
71+
@Override
72+
public String getHost() {
73+
return this.properties.getHost();
74+
}
75+
76+
@Override
77+
public int getPort() {
78+
return this.properties.getPort();
79+
}
80+
81+
}
82+
83+
}

0 commit comments

Comments
 (0)