Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ import jakarta.persistence.Table;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.jackson.Jacksonized;
import org.springframework.ai.vectorstore.HanaVectorEntity;
import org.springframework.ai.vectorstore.hanadb.HanaVectorEntity;

@Entity
@Table(name = "CRICKET_WORLD_CUP")
Expand All @@ -165,7 +165,7 @@ package com.interviewpedia.spring.ai.hana;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import org.springframework.ai.vectorstore.HanaVectorRepository;
import org.springframework.ai.vectorstore.hanadb.HanaVectorRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
Expand Down Expand Up @@ -246,7 +246,7 @@ import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.HanaCloudVectorStore;
import org.springframework.ai.vectorstore.hanadb.HanaCloudVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@
import io.micrometer.observation.ObservationRegistry;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.HanaCloudVectorStore;
import org.springframework.ai.vectorstore.HanaCloudVectorStoreConfig;
import org.springframework.ai.vectorstore.HanaVectorEntity;
import org.springframework.ai.vectorstore.HanaVectorRepository;
import org.springframework.ai.vectorstore.hanadb.HanaCloudVectorStore;
import org.springframework.ai.vectorstore.hanadb.HanaVectorEntity;
import org.springframework.ai.vectorstore.hanadb.HanaVectorRepository;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
Expand All @@ -39,6 +38,7 @@
*
* @author Rahul Mittal
* @author Christian Tzolov
* @author Soby Chacko
* @since 1.0.0
*/
@AutoConfiguration(after = { JpaRepositoriesAutoConfiguration.class })
Expand All @@ -53,13 +53,14 @@ public HanaCloudVectorStore vectorStore(HanaVectorRepository<? extends HanaVecto
ObjectProvider<ObservationRegistry> observationRegistry,
ObjectProvider<VectorStoreObservationConvention> customObservationConvention) {

return new HanaCloudVectorStore(repository, embeddingModel,
HanaCloudVectorStoreConfig.builder()
.tableName(properties.getTableName())
.topK(properties.getTopK())
.build(),
observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP),
customObservationConvention.getIfAvailable(() -> null));
return HanaCloudVectorStore.builder()
.repository(repository)
.embeddingModel(embeddingModel)
.tableName(properties.getTableName())
.topK(properties.getTopK())
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
.customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.ai.vectorstore;
package org.springframework.ai.vectorstore.hanadb;

import java.util.Collections;
import java.util.List;
Expand All @@ -34,10 +34,12 @@
import org.springframework.ai.observation.conventions.VectorStoreProvider;
import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric;
import org.springframework.ai.util.JacksonUtils;
import org.springframework.ai.vectorstore.AbstractVectorStoreBuilder;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext.Builder;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
import org.springframework.util.Assert;

/**
* The <b>SAP HANA Cloud vector engine</b> offers multiple use cases in AI scenarios.
Expand Down Expand Up @@ -68,6 +70,7 @@
* @author Rahul Mittal
* @author Christian Tzolov
* @author Sebastien Deleuze
* @author Soby Chacko
* @see <a href=
* "https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-vector-engine-guide/introduction">SAP
* HANA Database Vector Engine Guide</a>
Expand All @@ -79,30 +82,71 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore {

private final HanaVectorRepository<? extends HanaVectorEntity> repository;

private final EmbeddingModel embeddingModel;
private final String tableName;

private final HanaCloudVectorStoreConfig config;
private final int topK;

private final ObjectMapper objectMapper;

/**
* Creates a new HanaCloudVectorStore with basic configuration.
* @param repository the HANA vector repository
* @param embeddingModel the embedding model to use
* @param config the vector store configuration
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public HanaCloudVectorStore(HanaVectorRepository<? extends HanaVectorEntity> repository,
EmbeddingModel embeddingModel, HanaCloudVectorStoreConfig config) {

this(repository, embeddingModel, config, ObservationRegistry.NOOP, null);
}

/**
* Creates a new HanaCloudVectorStore with observation configuration.
* @param repository the HANA vector repository
* @param embeddingModel the embedding model to use
* @param config the vector store configuration
* @param observationRegistry the observation registry
* @param customObservationConvention the custom observation convention
* @deprecated Since 1.0.0-M5, use {@link #builder()} instead
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public HanaCloudVectorStore(HanaVectorRepository<? extends HanaVectorEntity> repository,
EmbeddingModel embeddingModel, HanaCloudVectorStoreConfig config, ObservationRegistry observationRegistry,
VectorStoreObservationConvention customObservationConvention) {

super(observationRegistry, customObservationConvention);
this(builder().repository(repository)
.embeddingModel(embeddingModel)
.tableName(config.getTableName())
.topK(config.getTopK())
.observationRegistry(observationRegistry)
.customObservationConvention(customObservationConvention));
}

/**
* Protected constructor that accepts a builder instance. This is the preferred way to
* create new HanaCloudVectorStore instances.
* @param builder the configured builder instance
*/
protected HanaCloudVectorStore(HanaCloudBuilder builder) {
super(builder);

this.repository = repository;
this.embeddingModel = embeddingModel;
this.config = config;
Assert.notNull(builder.repository, "Repository must not be null");

this.repository = builder.repository;
this.tableName = builder.tableName;
this.topK = builder.topK;
this.objectMapper = JsonMapper.builder().addModules(JacksonUtils.instantiateAvailableModules()).build();
}

/**
* Creates a new builder for configuring and creating HanaCloudVectorStore instances.
* @return a new builder instance
*/
public static HanaCloudBuilder builder() {
return new HanaCloudBuilder();
}

@Override
public void doAdd(List<Document> documents) {
int count = 1;
Expand All @@ -111,27 +155,27 @@ public void doAdd(List<Document> documents) {
document.getId());
String content = document.getContent().replaceAll("\\s+", " ");
String embedding = getEmbedding(document);
this.repository.save(this.config.getTableName(), document.getId(), embedding, content);
this.repository.save(this.tableName, document.getId(), embedding, content);
}
logger.info("Embeddings saved in HanaCloudVectorStore for {} documents", count - 1);
}

@Override
public Optional<Boolean> doDelete(List<String> idList) {
int deleteCount = this.repository.deleteEmbeddingsById(this.config.getTableName(), idList);
int deleteCount = this.repository.deleteEmbeddingsById(this.tableName, idList);
logger.info("{} embeddings deleted", deleteCount);
return Optional.of(deleteCount == idList.size());
}

public int purgeEmbeddings() {
int deleteCount = this.repository.deleteAllEmbeddings(this.config.getTableName());
int deleteCount = this.repository.deleteAllEmbeddings(this.tableName);
logger.info("{} embeddings deleted", deleteCount);
return deleteCount;
}

@Override
public List<Document> similaritySearch(String query) {
return similaritySearch(SearchRequest.query(query).withTopK(this.config.getTopK()));
return similaritySearch(SearchRequest.query(query).withTopK(this.topK));
}

@Override
Expand All @@ -142,8 +186,8 @@ public List<Document> doSimilaritySearch(SearchRequest request) {
}

String queryEmbedding = getEmbedding(request);
List<? extends HanaVectorEntity> searchResult = this.repository
.cosineSimilaritySearch(this.config.getTableName(), request.getTopK(), queryEmbedding);
List<? extends HanaVectorEntity> searchResult = this.repository.cosineSimilaritySearch(this.tableName,
request.getTopK(), queryEmbedding);
logger.info("Hana cosine-similarity for query={}, with topK={} returned {} results", request.getQuery(),
request.getTopK(), searchResult.size());

Expand Down Expand Up @@ -176,8 +220,63 @@ public VectorStoreObservationContext.Builder createObservationContextBuilder(Str

return VectorStoreObservationContext.builder(VectorStoreProvider.HANA.value(), operationName)
.withDimensions(this.embeddingModel.dimensions())
.withCollectionName(this.config.getTableName())
.withCollectionName(this.tableName)
.withSimilarityMetric(VectorStoreSimilarityMetric.COSINE.value());
}

/**
* Builder class for creating {@link HanaCloudVectorStore} instances.
* <p>
* Provides a fluent API for configuring all aspects of the HANA Cloud vector store.
*
* @since 1.0.0
*/
public static class HanaCloudBuilder extends AbstractVectorStoreBuilder<HanaCloudBuilder> {

private HanaVectorRepository<? extends HanaVectorEntity> repository;

private String tableName;

private int topK;

/**
* Sets the HANA vector repository.
* @param repository the repository to use
* @return the builder instance
* @throws IllegalArgumentException if repository is null
*/
public HanaCloudBuilder repository(HanaVectorRepository<? extends HanaVectorEntity> repository) {
Assert.notNull(repository, "Repository must not be null");
this.repository = repository;
return this;
}

/**
* Sets the table name for vector storage.
* @param tableName the name of the table to use
* @return the builder instance
*/
public HanaCloudBuilder tableName(String tableName) {
this.tableName = tableName;
return this;
}

/**
* Sets the number of top results to return.
* @param topK the number of results
* @return the builder instance
*/
public HanaCloudBuilder topK(int topK) {
this.topK = topK;
return this;
}

@Override
public HanaCloudVectorStore build() {
validate();
return new HanaCloudVectorStore(this);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.ai.vectorstore;
package org.springframework.ai.vectorstore.hanadb;

/**
* The {@code HanaCloudVectorStoreConfig} class represents the configuration for the
Expand All @@ -23,7 +23,9 @@
*
* @author Rahul Mittal
* @since 1.0.0
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public final class HanaCloudVectorStoreConfig {

private String tableName;
Expand All @@ -33,34 +35,64 @@ public final class HanaCloudVectorStoreConfig {
private HanaCloudVectorStoreConfig() {
}

/**
* Creates a new builder for HanaCloudVectorStoreConfig.
* @return a new builder instance
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public static HanaCloudVectorStoreConfigBuilder builder() {
return new HanaCloudVectorStoreConfigBuilder();
}

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public String getTableName() {
return this.tableName;
}

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public int getTopK() {
return this.topK;
}

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public static class HanaCloudVectorStoreConfigBuilder {

private String tableName;

private int topK;

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public HanaCloudVectorStoreConfigBuilder tableName(String tableName) {
this.tableName = tableName;
return this;
}

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public HanaCloudVectorStoreConfigBuilder topK(int topK) {
this.topK = topK;
return this;
}

/**
* @deprecated Since 1.0.0-M5, use {@link HanaCloudVectorStore#builder()}
*/
@Deprecated(since = "1.0.0-M5", forRemoval = true)
public HanaCloudVectorStoreConfig build() {
HanaCloudVectorStoreConfig config = new HanaCloudVectorStoreConfig();
config.tableName = this.tableName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.ai.vectorstore;
package org.springframework.ai.vectorstore.hanadb;

import jakarta.persistence.Column;
import jakarta.persistence.Id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.ai.vectorstore;
package org.springframework.ai.vectorstore.hanadb;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.ai.vectorstore;
package org.springframework.ai.vectorstore.hanadb;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand Down
Loading
Loading