Skip to content

Commit e0b34a1

Browse files
geetrawatLouis Jacomejhuynh1
authored andcommitted
Adds GemFireVectorStore Auto-Configuration
- 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 Co-authored-by: Louis Jacome <louis.jacome@broadcom.com> Co-authored-by: Jason Huyn <jason.huynh@broadcom.com>
1 parent 20c6a1a commit e0b34a1

File tree

14 files changed

+985
-246
lines changed

14 files changed

+985
-246
lines changed

spring-ai-bom/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,12 @@
403403
<version>${project.version}</version>
404404
</dependency>
405405

406+
<dependency>
407+
<groupId>org.springframework.ai</groupId>
408+
<artifactId>spring-ai-gemfire-store-spring-boot-starter</artifactId>
409+
<version>${project.version}</version>
410+
</dependency>
411+
406412
<dependency>
407413
<groupId>org.springframework.ai</groupId>
408414
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
Lines changed: 73 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,131 @@
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 that performs 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 with no downtime. As your data size requirements increase to support high-performance, real-time apps, GemFire can scale linearly with ease.
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]
13+
14+
2. An `EmbeddingModel` bean to compute the document embeddings. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information.
1815

1916
== Dependencies
2017

21-
Add these dependencies to your project:
18+
=== Maven
2219

23-
- Embedding Client boot starter, required for calculating embeddings.
24-
- Transformers Embedding (Local) and follow the ONNX Transformers Embedding instructions.
20+
To use just the `GemFireVectorStore`, add the following dependency to your project’s Maven `pom.xml`:
2521

26-
[source,xml]
22+
[source, xml]
2723
----
2824
<dependency>
29-
<groupId>org.springframework.ai</groupId>
30-
<artifactId>spring-ai-transformers</artifactId>
25+
<groupId>org.springframework.ai</groupId>
26+
<artifactId>spring-ai-gemfire-store</artifactId>
3127
</dependency>
3228
----
3329

34-
- Add the GemFire VectorDB dependencies
30+
To enable Spring Boot’s Auto-Configuration for the `GemFireVectorStore`, also add the following to your project’s Maven `pom.xml`:
3531

36-
[source,xml]
32+
[source, xml]
3733
----
3834
<dependency>
3935
<groupId>org.springframework.ai</groupId>
40-
<artifactId>spring-ai-gemfire-store</artifactId>
36+
<artifactId>spring-ai-gemfire-store-spring-boot-starter</artifactId>
4137
</dependency>
38+
4239
----
4340

4441

45-
TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file.
42+
=== Gradle
4643

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

48-
== Sample Code
46+
[souce, xml]
47+
----
48+
dependencies {
49+
implementation 'org.springframework.ai:spring-ai-gemfire-store'
50+
}
51+
----
4952

50-
- To configure GemFire in your application, use the following setup:
53+
To enable Spring Boot’s Auto-Configuration for the `GemFireVectorStore`, also include this dependency:
5154

52-
[source,java]
55+
[source, xml]
5356
----
54-
@Bean
55-
public GemFireVectorStoreConfig gemFireVectorStoreConfig() {
56-
return GemFireVectorStoreConfig.builder()
57-
.withUrl("http://localhost:8080")
58-
.withIndexName("spring-ai-test-index")
59-
.build();
57+
dependencies {
58+
implementation 'org.springframework.ai:spring-ai-gemfire-store-spring-boot-starter'
6059
}
6160
----
6261

63-
- Create a GemFireVectorStore instance connected to your GemFire VectorDB:
62+
== Usage
63+
64+
- Create a `GemFireVectorStore` instance connected to the GemFire cluster:
6465

6566
[source,java]
6667
----
6768
@Bean
68-
public VectorStore vectorStore(GemFireVectorStoreConfig config, EmbeddingModel embeddingModel) {
69-
return new GemFireVectorStore(config, embeddingModel);
69+
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
70+
return new GemFireVectorStore(new GemFireVectorStoreConfig()
71+
.setIndexName("my-vector-index")
72+
.setPort(7071), embeddingClient);
7073
}
7174
----
72-
- Create a Vector Index which will configure GemFire region.
75+
76+
[NOTE]
77+
====
78+
The default configuration connects to a GemFire cluster at `localhost:8080`
79+
====
80+
81+
- In your application, create a few documents:
7382

7483
[source,java]
7584
----
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:
85+
List<Document> documents = List.of(
86+
new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("country", "UK", "year", 2020)),
87+
new Document("The World is Big and Salvation Lurks Around the Corner", Map.of()),
88+
new Document("You walk forward facing the past and you turn back toward the future.", Map.of("country", "NL", "year", 2023)));
89+
----
90+
91+
- Add the documents to the vector store:
9892

9993
[source,java]
10094
----
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")));
95+
vectorStore.add(documents);
10596
----
10697

107-
- Add the documents to GemFire VectorDB:
98+
- And to retrieve documents using similarity search:
10899

109100
[source,java]
110101
----
111-
vectorStore.add(List.of(document));
102+
List<Document> results = vectorStore.similaritySearch(
103+
SearchRequest.query("Spring").withTopK(5));
112104
----
113105

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

108+
You can also limit the number of results using a similarity threshold:
116109
[source,java]
117110
----
118-
List<Document> results = vectorStore.similaritySearch("Spring", 5);
111+
List<Document> results = vectorStore.similaritySearch(
112+
SearchRequest.query("Spring").withTopK(5)
113+
.withSimilarityThreshold(0.5d));
119114
----
120115

121-
If all goes well, you should retrieve the document containing the text "Spring AI rocks!!".
116+
== GemFireVectorStore properties
117+
118+
You can use the following properties in your Spring Boot configuration to further configure the `GemFireVectorStore`.
119+
120+
|===
121+
|Property|Default value
122122

123+
|`spring.ai.vectorstore.gemfire.host`|localhost
124+
|`spring.ai.vectorstore.gemfire.port`|8080
125+
|`spring.ai.vectorstore.gemfire.index-name`|spring-ai-gemfire-store
126+
|`spring.ai.vectorstore.gemfire.beam-width`|100
127+
|`spring.ai.vectorstore.gemfire.max-connections`|16
128+
|`spring.ai.vectorstore.gemfire.vector-similarity-function`|COSINE
129+
|`spring.ai.vectorstore.gemfire.fields`|[]
130+
|`spring.ai.vectorstore.gemfire.buckets`|0
131+
|===

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
<connection>git://github.com/spring-projects/spring-ai.git</connection>
1919
<developerConnection>git@github.com:spring-projects/spring-ai.git</developerConnection>
2020
</scm>
21+
<repositories>
22+
<repository>
23+
<id>gemfire-release-repo</id>
24+
<name>Pivotal GemFire Release Repository</name>
25+
<url>https://commercial-repo.pivotal.io/data3/gemfire-release-repo/gemfire</url>
26+
</repository>
27+
</repositories>
2128

2229
<dependencies>
2330

@@ -267,6 +274,13 @@
267274
<optional>true</optional>
268275
</dependency>
269276

277+
<dependency>
278+
<groupId>org.springframework.ai</groupId>
279+
<artifactId>spring-ai-gemfire-store</artifactId>
280+
<version>${project.parent.version}</version>
281+
<optional>true</optional>
282+
</dependency>
283+
270284
<dependency>
271285
<groupId>org.springframework.ai</groupId>
272286
<artifactId>spring-ai-minimax</artifactId>
@@ -381,6 +395,13 @@
381395
<scope>test</scope>
382396
</dependency>
383397

398+
<dependency>
399+
<groupId>com.vmware.gemfire</groupId>
400+
<artifactId>gemfire-testcontainers</artifactId>
401+
<version>2.0.0</version>
402+
<scope>test</scope>
403+
</dependency>
404+
384405
</dependencies>
385406

386407
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
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,84 @@
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 vectorStore(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+
69+
this.properties = properties;
70+
}
71+
72+
@Override
73+
public String getHost() {
74+
return this.properties.getHost();
75+
}
76+
77+
@Override
78+
public int getPort() {
79+
return this.properties.getPort();
80+
}
81+
82+
}
83+
84+
}

0 commit comments

Comments
 (0)