Upgrade Pinecone java client to 4.0.1 (#2328)
- Upgrade the java client from 0.8.0 to 4.0.1
- Use io.pinecone.clients.Pinecone to setup the client configuration with the API key
- Remove projectId, environment and other deprecated client configurations
- Update upsert, delete, search operations with the new client
- Remove the projectID and Environment configurations from the builder
- Updated the Pinecone vectorstore autoconfiguration
- Update tests
Signed-off-by: Ilayaperumal Gopinathan <ilayaperumal.gopinathan@broadcom.com>
Disable autoconfig IT until the auto-configuration is modularised
This commit is contained in:
committed by
GitHub
parent
96c8157cbe
commit
c91163b6a3
5
pom.xml
5
pom.xml
@@ -217,7 +217,10 @@
|
||||
<coherence.version>24.09</coherence.version>
|
||||
<milvus.version>2.5.4</milvus.version>
|
||||
<gemfire.testcontainers.version>2.3.0</gemfire.testcontainers.version>
|
||||
<pinecone.version>0.8.0</pinecone.version>
|
||||
|
||||
<pinecone.version>4.0.1</pinecone.version>
|
||||
<pinecone.protobuf-java-util.version>4.29.3</pinecone.protobuf-java-util.version>
|
||||
|
||||
<fastjson2.version>2.0.46</fastjson2.version>
|
||||
<azure-core.version>1.53.0</azure-core.version>
|
||||
<azure-json.version>1.3.0</azure-json.version>
|
||||
|
||||
@@ -7,15 +7,13 @@ link:https://www.pinecone.io/[Pinecone] is a popular cloud-based vector database
|
||||
== Prerequisites
|
||||
|
||||
1. Pinecone Account: Before you start, sign up for a link:https://app.pinecone.io/[Pinecone account].
|
||||
2. Pinecone Project: Once registered, create a new project, an index, and generate an API key. You'll need these details for configuration.
|
||||
2. Pinecone Project: Once registered, generate an API key and create and index. You'll need these details for configuration.
|
||||
3. `EmbeddingModel` instance to compute the document embeddings. Several options are available:
|
||||
- If required, an API key for the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] to generate the embeddings stored by the `PineconeVectorStore`.
|
||||
|
||||
To set up `PineconeVectorStore`, gather the following details from your Pinecone account:
|
||||
|
||||
* Pinecone API Key
|
||||
* Pinecone Environment
|
||||
* Pinecone Project ID
|
||||
* Pinecone Index Name
|
||||
* Pinecone Namespace
|
||||
|
||||
@@ -70,8 +68,6 @@ A simple configuration can either be provided via Spring Boot's _application.pro
|
||||
[source,properties]
|
||||
----
|
||||
spring.ai.vectorstore.pinecone.apiKey=<your api key>
|
||||
spring.ai.vectorstore.pinecone.environment=<your environment>
|
||||
spring.ai.vectorstore.pinecone.projectId=<your project id>
|
||||
spring.ai.vectorstore.pinecone.index-name=<your index name>
|
||||
|
||||
# API key if needed, e.g. OpenAI
|
||||
@@ -109,8 +105,6 @@ You can use the following properties in your Spring Boot configuration to custom
|
||||
|Property| Description | Default value
|
||||
|
||||
|`spring.ai.vectorstore.pinecone.api-key`| Pinecone API Key | -
|
||||
|`spring.ai.vectorstore.pinecone.environment`| Pinecone environment | `gcp-starter`
|
||||
|`spring.ai.vectorstore.pinecone.project-id`| Pinecone project ID | -
|
||||
|`spring.ai.vectorstore.pinecone.index-name`| Pinecone index name | -
|
||||
|`spring.ai.vectorstore.pinecone.namespace`| Pinecone namespace | -
|
||||
|`spring.ai.vectorstore.pinecone.content-field-name`| Pinecone metadata field name used to store the original text content. | `document_content`
|
||||
@@ -191,8 +185,6 @@ To configure Pinecone in your application, you can use the following setup:
|
||||
public VectorStore pineconeVectorStore(EmbeddingModel embeddingModel) {
|
||||
return PineconeVectorStore.builder(embeddingModel)
|
||||
.apiKey(PINECONE_API_KEY)
|
||||
.projectId(PINECONE_PROJECT_ID)
|
||||
.environment(PINECONE_ENVIRONMENT)
|
||||
.indexName(PINECONE_INDEX_NAME)
|
||||
.namespace(PINECONE_NAMESPACE) // the free tier doesn't support namespaces.
|
||||
.contentFieldName(CUSTOM_CONTENT_FIELD_NAME) // optional field to store the original content. Defaults to `document_content`
|
||||
|
||||
@@ -56,13 +56,10 @@ public class PineconeVectorStoreAutoConfiguration {
|
||||
|
||||
return PineconeVectorStore.builder(embeddingModel)
|
||||
.apiKey(properties.getApiKey())
|
||||
.projectId(properties.getProjectId())
|
||||
.environment(properties.getEnvironment())
|
||||
.indexName(properties.getIndexName())
|
||||
.namespace(properties.getNamespace())
|
||||
.contentFieldName(properties.getContentFieldName())
|
||||
.distanceMetadataFieldName(properties.getDistanceMetadataFieldName())
|
||||
.serverSideTimeout(properties.getServerSideTimeout())
|
||||
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
|
||||
.customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
|
||||
.batchingStrategy(batchingStrategy)
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import io.micrometer.observation.tck.TestObservationRegistry;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
|
||||
@@ -51,14 +52,13 @@ import static org.hamcrest.Matchers.hasSize;
|
||||
* @author Thomas Vitale
|
||||
*/
|
||||
@EnabledIfEnvironmentVariable(named = "PINECONE_API_KEY", matches = ".+")
|
||||
@Disabled("Can be re-enabled once the auto-configuration is modularised")
|
||||
public class PineconeVectorStoreAutoConfigurationIT {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(PineconeVectorStoreAutoConfiguration.class))
|
||||
.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.pinecone.apiKey=" + System.getenv("PINECONE_API_KEY"),
|
||||
"spring.ai.vectorstore.pinecone.environment=gcp-starter",
|
||||
"spring.ai.vectorstore.pinecone.projectId=814621f",
|
||||
"spring.ai.vectorstore.pinecone.indexName=spring-ai-test-index",
|
||||
"spring.ai.vectorstore.pinecone.contentFieldName=customContentField",
|
||||
"spring.ai.vectorstore.pinecone.distanceMetadataFieldName=customDistanceField");
|
||||
|
||||
@@ -18,8 +18,10 @@ package org.springframework.ai.test.vectorstore;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.anyOf;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.Matchers.either;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -50,43 +50,13 @@
|
||||
<dependency>
|
||||
<groupId>io.pinecone</groupId>
|
||||
<artifactId>pinecone-client</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-netty</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-protobuf</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-stub</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<version>${pinecone.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-netty</artifactId>
|
||||
<version>1.59.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-protobuf</artifactId>
|
||||
<version>1.59.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-stub</artifactId>
|
||||
<version>1.59.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
<version>${protobuf-java.version}</version>
|
||||
<version>${pinecone.protobuf-java-util.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TESTING -->
|
||||
@@ -113,7 +83,6 @@
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.pinecone;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -27,15 +27,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.protobuf.Struct;
|
||||
import com.google.protobuf.Value;
|
||||
import com.google.protobuf.util.JsonFormat;
|
||||
import io.pinecone.PineconeClient;
|
||||
import io.pinecone.PineconeClientConfig;
|
||||
import io.pinecone.PineconeConnection;
|
||||
import io.pinecone.PineconeConnectionConfig;
|
||||
import io.pinecone.proto.DeleteRequest;
|
||||
import io.pinecone.clients.Pinecone;
|
||||
import io.pinecone.proto.QueryRequest;
|
||||
import io.pinecone.proto.QueryResponse;
|
||||
import io.pinecone.proto.UpsertRequest;
|
||||
import io.pinecone.proto.Vector;
|
||||
import io.pinecone.unsigned_indices_model.QueryResponseWithUnsignedIndices;
|
||||
import io.pinecone.unsigned_indices_model.VectorWithUnsignedIndices;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -65,6 +60,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Adam Bchouti
|
||||
* @author Soby Chacko
|
||||
* @author Thomas Vitale
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
@@ -72,8 +68,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
public final FilterExpressionConverter filterExpressionConverter = new PineconeFilterExpressionConverter();
|
||||
|
||||
private final PineconeConnection pineconeConnection;
|
||||
|
||||
private final String pineconeNamespace;
|
||||
|
||||
private final String pineconeIndexName;
|
||||
@@ -82,6 +76,8 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
private final String pineconeDistanceMetadataFieldName;
|
||||
|
||||
private final Pinecone pinecone;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PineconeVectorStore.class);
|
||||
@@ -94,8 +90,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
super(builder);
|
||||
|
||||
Assert.hasText(builder.apiKey, "ApiKey must not be null or empty");
|
||||
Assert.hasText(builder.projectId, "ProjectId must not be null or empty");
|
||||
Assert.hasText(builder.environment, "Environment must not be null or empty");
|
||||
Assert.hasText(builder.indexName, "IndexName must not be null or empty");
|
||||
|
||||
this.pineconeNamespace = builder.namespace;
|
||||
@@ -103,28 +97,10 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
this.pineconeContentFieldName = builder.contentFieldName;
|
||||
this.pineconeDistanceMetadataFieldName = builder.distanceMetadataFieldName;
|
||||
|
||||
PineconeClientConfig clientConfig = new PineconeClientConfig().withApiKey(builder.apiKey)
|
||||
.withEnvironment(builder.environment)
|
||||
.withProjectName(builder.projectId)
|
||||
.withServerSideTimeoutSec((int) builder.serverSideTimeout.toSeconds());
|
||||
|
||||
PineconeConnectionConfig connectionConfig = new PineconeConnectionConfig().withIndexName(builder.indexName);
|
||||
|
||||
this.pineconeConnection = new PineconeClient(clientConfig).connect(connectionConfig);
|
||||
this.pinecone = new Pinecone.Builder(builder.apiKey).build();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new builder instance for configuring a PineconeVectorStore.
|
||||
* @return A new PineconeBuilder instance
|
||||
* @deprecated use {@link #builder(EmbeddingModel)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M6")
|
||||
public static Builder builder(EmbeddingModel embeddingModel, String apiKey, String projectId, String environment,
|
||||
String indexName) {
|
||||
return new Builder(embeddingModel, apiKey, projectId, environment, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new builder for constructing a PineconeVectorStore instance. This builder
|
||||
* implements a type-safe step pattern that guides users through the required
|
||||
@@ -134,8 +110,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
* <ol>
|
||||
* <li>embeddingModel (provided to this method)</li>
|
||||
* <li>apiKey</li>
|
||||
* <li>projectId</li>
|
||||
* <li>environment</li>
|
||||
* <li>indexName</li>
|
||||
* </ol>
|
||||
*
|
||||
@@ -145,8 +119,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
* Example usage: <pre>{@code
|
||||
* PineconeVectorStore store = PineconeVectorStore.builder(embeddingModel)
|
||||
* .apiKey("your-api-key")
|
||||
* .projectId("your-project")
|
||||
* .environment("your-env")
|
||||
* .indexName("your-index")
|
||||
* .namespace("optional") // optional configuration
|
||||
* .build();
|
||||
@@ -167,20 +139,13 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
public void add(List<Document> documents, String namespace) {
|
||||
List<float[]> embeddings = this.embeddingModel.embed(documents, EmbeddingOptionsBuilder.builder().build(),
|
||||
this.batchingStrategy);
|
||||
List<Vector> upsertVectors = documents.stream()
|
||||
.map(document -> Vector.newBuilder()
|
||||
.setId(document.getId())
|
||||
.addAllValues(EmbeddingUtils.toList(embeddings.get(documents.indexOf(document))))
|
||||
.setMetadata(metadataToStruct(document))
|
||||
.build())
|
||||
.toList();
|
||||
|
||||
UpsertRequest upsertRequest = UpsertRequest.newBuilder()
|
||||
.addAllVectors(upsertVectors)
|
||||
.setNamespace(namespace)
|
||||
.build();
|
||||
|
||||
this.pineconeConnection.getBlockingStub().upsert(upsertRequest);
|
||||
List<VectorWithUnsignedIndices> upsertVectors = new ArrayList<>();
|
||||
for (Document document : documents) {
|
||||
upsertVectors.add(io.pinecone.commons.IndexInterface.buildUpsertVectorWithUnsignedIndices(document.getId(),
|
||||
EmbeddingUtils.toList(embeddings.get(documents.indexOf(document))), null, null,
|
||||
metadataToStruct(document)));
|
||||
}
|
||||
this.pinecone.getIndexConnection(this.pineconeIndexName).upsert(upsertVectors, namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,14 +191,7 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
* @param namespace The namespace of the document IDs.
|
||||
*/
|
||||
public void delete(List<String> documentIds, String namespace) {
|
||||
|
||||
DeleteRequest deleteRequest = DeleteRequest.newBuilder()
|
||||
.setNamespace(namespace) // ignored for free tier.
|
||||
.addAllIds(documentIds)
|
||||
.setDeleteAll(false)
|
||||
.build();
|
||||
|
||||
this.pineconeConnection.getBlockingStub().delete(deleteRequest);
|
||||
this.pinecone.getIndexConnection(this.pineconeIndexName).delete(documentIds, false, namespace, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +220,9 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
queryRequestBuilder.setFilter(metadataFiltersToStruct(nativeExpressionFilters));
|
||||
}
|
||||
|
||||
QueryResponse queryResponse = this.pineconeConnection.getBlockingStub().query(queryRequestBuilder.build());
|
||||
QueryResponseWithUnsignedIndices queryResponse = this.pinecone.getIndexConnection(this.pineconeIndexName)
|
||||
.queryByVector(request.getTopK(), EmbeddingUtils.toList(queryEmbedding), namespace,
|
||||
metadataFiltersToStruct(nativeExpressionFilters), false, true);
|
||||
|
||||
return queryResponse.getMatchesList()
|
||||
.stream()
|
||||
@@ -321,9 +281,12 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
private Struct metadataFiltersToStruct(String metadataFilters) {
|
||||
try {
|
||||
var structBuilder = Struct.newBuilder();
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(metadataFilters, structBuilder);
|
||||
return structBuilder.build();
|
||||
if (StringUtils.hasText(metadataFilters)) {
|
||||
var structBuilder = Struct.newBuilder();
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(metadataFilters, structBuilder);
|
||||
return structBuilder.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -362,7 +325,7 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
@Override
|
||||
public <T> Optional<T> getNativeClient() {
|
||||
@SuppressWarnings("unchecked")
|
||||
T client = (T) this.pineconeConnection;
|
||||
T client = (T) this.pinecone;
|
||||
return Optional.of(client);
|
||||
}
|
||||
|
||||
@@ -372,7 +335,7 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
* specific order before optional configuration.
|
||||
*
|
||||
* The required fields must be provided in this sequence: 1. embeddingModel (via
|
||||
* builder method) 2. apiKey 3. projectId 4. environment 5. indexName
|
||||
* builder method) 2. apiKey 3. indexName
|
||||
*
|
||||
* After all required fields are set, optional configurations can be provided using
|
||||
* the fluent builder pattern.
|
||||
@@ -380,8 +343,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
* Example usage: <pre>{@code
|
||||
* PineconeVectorStore store = PineconeVectorStore.builder(embeddingModel)
|
||||
* .apiKey("your-api-key")
|
||||
* .projectId("your-project")
|
||||
* .environment("your-env")
|
||||
* .indexName("your-index")
|
||||
* .namespace("optional") // optional configuration
|
||||
* .build();
|
||||
@@ -392,12 +353,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
/** Required field for Pinecone API authentication */
|
||||
private final String apiKey;
|
||||
|
||||
/** Required field identifying the Pinecone project */
|
||||
private final String projectId;
|
||||
|
||||
/** Required field specifying the Pinecone environment (e.g. "gcp-starter") */
|
||||
private final String environment;
|
||||
|
||||
/** Required field specifying the Pinecone index name */
|
||||
private final String indexName;
|
||||
|
||||
@@ -408,14 +363,9 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
private String distanceMetadataFieldName = DocumentMetadata.DISTANCE.value();
|
||||
|
||||
private Duration serverSideTimeout = Duration.ofSeconds(20);
|
||||
|
||||
private Builder(EmbeddingModel embeddingModel, String apiKey, String projectId, String environment,
|
||||
String indexName) {
|
||||
private Builder(EmbeddingModel embeddingModel, String apiKey, String indexName) {
|
||||
super(embeddingModel);
|
||||
this.apiKey = apiKey;
|
||||
this.projectId = projectId;
|
||||
this.environment = environment;
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
@@ -451,16 +401,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server-side timeout.
|
||||
* @param serverSideTimeout The timeout duration to use
|
||||
* @return The builder instance
|
||||
*/
|
||||
public Builder serverSideTimeout(@Nullable Duration serverSideTimeout) {
|
||||
this.serverSideTimeout = serverSideTimeout != null ? serverSideTimeout : Duration.ofSeconds(20);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new PineconeVectorStore instance with the configured properties.
|
||||
* @return A new PineconeVectorStore instance
|
||||
@@ -477,42 +417,12 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
public interface BuilderWithApiKey {
|
||||
|
||||
/**
|
||||
* Sets the Pinecone API key and moves to project ID configuration.
|
||||
* Sets the Pinecone API key and moves to index name configuration.
|
||||
* @param apiKey The Pinecone API key
|
||||
* @return The next builder step for project ID
|
||||
* @return The next builder step for index name
|
||||
* @throws IllegalArgumentException if apiKey is null or empty
|
||||
*/
|
||||
BuilderWithProjectId apiKey(String apiKey);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Second step interface requiring project ID configuration.
|
||||
*/
|
||||
public interface BuilderWithProjectId {
|
||||
|
||||
/**
|
||||
* Sets the project ID and moves to environment configuration.
|
||||
* @param projectId The Pinecone project ID
|
||||
* @return The next builder step for environment
|
||||
* @throws IllegalArgumentException if projectId is null or empty
|
||||
*/
|
||||
BuilderWithEnvironment projectId(String projectId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Third step interface requiring environment configuration.
|
||||
*/
|
||||
public interface BuilderWithEnvironment {
|
||||
|
||||
/**
|
||||
* Sets the environment and moves to index name configuration.
|
||||
* @param environment The Pinecone environment
|
||||
* @return The next builder step for index name
|
||||
* @throws IllegalArgumentException if environment is null or empty
|
||||
*/
|
||||
BuilderWithIndexName environment(String environment);
|
||||
BuilderWithIndexName apiKey(String apiKey);
|
||||
|
||||
}
|
||||
|
||||
@@ -552,35 +462,17 @@ public class PineconeVectorStore extends AbstractObservationVectorStore {
|
||||
|
||||
private record ApiKeyStep(EmbeddingModel embeddingModel) implements BuilderWithApiKey {
|
||||
@Override
|
||||
public BuilderWithProjectId apiKey(String apiKey) {
|
||||
public BuilderWithIndexName apiKey(String apiKey) {
|
||||
Assert.hasText(apiKey, "ApiKey must not be null or empty");
|
||||
return new ProjectIdStep(this.embeddingModel, apiKey);
|
||||
return new IndexNameStep(this.embeddingModel, apiKey);
|
||||
}
|
||||
}
|
||||
|
||||
private record ProjectIdStep(EmbeddingModel embeddingModel, String apiKey) implements BuilderWithProjectId {
|
||||
@Override
|
||||
public BuilderWithEnvironment projectId(String projectId) {
|
||||
Assert.hasText(projectId, "ProjectId must not be null or empty");
|
||||
return new EnvironmentStep(this.embeddingModel, this.apiKey, projectId);
|
||||
}
|
||||
}
|
||||
|
||||
private record EnvironmentStep(EmbeddingModel embeddingModel, String apiKey,
|
||||
String projectId) implements BuilderWithEnvironment {
|
||||
@Override
|
||||
public BuilderWithIndexName environment(String environment) {
|
||||
Assert.hasText(environment, "Environment must not be null or empty");
|
||||
return new IndexNameStep(this.embeddingModel, this.apiKey, this.projectId, environment);
|
||||
}
|
||||
}
|
||||
|
||||
private record IndexNameStep(EmbeddingModel embeddingModel, String apiKey, String projectId,
|
||||
String environment) implements BuilderWithIndexName {
|
||||
private record IndexNameStep(EmbeddingModel embeddingModel, String apiKey) implements BuilderWithIndexName {
|
||||
@Override
|
||||
public Builder indexName(String indexName) {
|
||||
Assert.hasText(indexName, "IndexName must not be null or empty");
|
||||
return new Builder(this.embeddingModel, this.apiKey, this.projectId, this.environment, indexName);
|
||||
return new Builder(this.embeddingModel, this.apiKey, indexName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.ai.vectorstore.pinecone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -27,9 +28,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.pinecone.PineconeConnection;
|
||||
import io.pinecone.clients.Pinecone;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
@@ -56,16 +56,11 @@ import static org.hamcrest.Matchers.hasSize;
|
||||
* @author Christian Tzolov
|
||||
* @author Thomas Vitale
|
||||
* @author Soby Chacko
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@EnabledIfEnvironmentVariable(named = "PINECONE_API_KEY", matches = ".+")
|
||||
public class PineconeVectorStoreIT extends BaseVectorStoreTests {
|
||||
|
||||
// Replace the PINECONE_ENVIRONMENT, PINECONE_PROJECT_ID, PINECONE_INDEX_NAME and
|
||||
// PINECONE_API_KEY with your pinecone credentials.
|
||||
private static final String PINECONE_ENVIRONMENT = "gcp-starter";
|
||||
|
||||
private static final String PINECONE_PROJECT_ID = "814621f";
|
||||
|
||||
private static final String PINECONE_INDEX_NAME = "spring-ai-test-index";
|
||||
|
||||
// NOTE: Leave it empty as for free tier as later doesn't support namespaces.
|
||||
@@ -97,7 +92,7 @@ public class PineconeVectorStoreIT extends BaseVectorStoreTests {
|
||||
public static void beforeAll() {
|
||||
Awaitility.setDefaultPollInterval(2, TimeUnit.SECONDS);
|
||||
Awaitility.setDefaultPollDelay(Duration.ZERO);
|
||||
Awaitility.setDefaultTimeout(Duration.ONE_MINUTE);
|
||||
Awaitility.setDefaultTimeout(Duration.ofMinutes(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -332,7 +327,7 @@ public class PineconeVectorStoreIT extends BaseVectorStoreTests {
|
||||
void getNativeClientTest() {
|
||||
this.contextRunner.run(context -> {
|
||||
PineconeVectorStore vectorStore = context.getBean(PineconeVectorStore.class);
|
||||
Optional<PineconeConnection> nativeClient = vectorStore.getNativeClient();
|
||||
Optional<Pinecone> nativeClient = vectorStore.getNativeClient();
|
||||
assertThat(nativeClient).isPresent();
|
||||
});
|
||||
}
|
||||
@@ -395,8 +390,6 @@ public class PineconeVectorStoreIT extends BaseVectorStoreTests {
|
||||
|
||||
return PineconeVectorStore.builder(embeddingModel)
|
||||
.apiKey(apikey)
|
||||
.projectId(PINECONE_PROJECT_ID)
|
||||
.environment(PINECONE_ENVIRONMENT)
|
||||
.indexName(PINECONE_INDEX_NAME)
|
||||
.namespace(PINECONE_NAMESPACE)
|
||||
.contentFieldName(CUSTOM_CONTENT_FIELD_NAME)
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.ai.vectorstore.pinecone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -26,7 +27,6 @@ import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistryAssert;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
@@ -58,10 +58,6 @@ import static org.hamcrest.Matchers.hasSize;
|
||||
@EnabledIfEnvironmentVariable(named = "PINECONE_API_KEY", matches = ".+")
|
||||
public class PineconeVectorStoreObservationIT {
|
||||
|
||||
private static final String PINECONE_ENVIRONMENT = "gcp-starter";
|
||||
|
||||
private static final String PINECONE_PROJECT_ID = "814621f";
|
||||
|
||||
private static final String PINECONE_INDEX_NAME = "spring-ai-test-index";
|
||||
|
||||
// NOTE: Leave it empty as for free tier as later doesn't support namespaces.
|
||||
@@ -91,7 +87,7 @@ public class PineconeVectorStoreObservationIT {
|
||||
public static void beforeAll() {
|
||||
Awaitility.setDefaultPollInterval(2, TimeUnit.SECONDS);
|
||||
Awaitility.setDefaultPollDelay(Duration.ZERO);
|
||||
Awaitility.setDefaultTimeout(Duration.ONE_MINUTE);
|
||||
Awaitility.setDefaultTimeout(Duration.ofMinutes(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -190,8 +186,6 @@ public class PineconeVectorStoreObservationIT {
|
||||
public VectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) {
|
||||
return PineconeVectorStore.builder(embeddingModel)
|
||||
.apiKey(System.getenv("PINECONE_API_KEY"))
|
||||
.projectId(PINECONE_PROJECT_ID)
|
||||
.environment(PINECONE_ENVIRONMENT)
|
||||
.indexName(PINECONE_INDEX_NAME)
|
||||
.namespace(PINECONE_NAMESPACE)
|
||||
.contentFieldName(CUSTOM_CONTENT_FIELD_NAME)
|
||||
|
||||
Reference in New Issue
Block a user