Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding pinecone sdk #70

Merged
merged 1 commit into from
May 20, 2023
Merged
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
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ dependencies {
implementation 'com.google.inject:guice:5.1.0'
// Environment variables
implementation 'io.github.cdimascio:java-dotenv:5.2.2'
// Gson retrofit converter
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
// Retrofit guava adapter
// Retrofit
implementation 'com.squareup.retrofit2:adapter-guava:2.9.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0'
testImplementation 'com.squareup.retrofit2:retrofit-mock:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2'
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
}

// Testing related dependencies
Expand Down
34 changes: 0 additions & 34 deletions src/main/java/ai/knowly/langtorch/llm/Utils.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ai.knowly.langtorch.llm.processor.openai;

import ai.knowly.langtorch.llm.Utils;
import ai.knowly.langtorch.utils.ApiKeyUtils;
import ai.knowly.langtorch.llm.integration.openai.service.OpenAIApi;
import ai.knowly.langtorch.llm.integration.openai.service.OpenAIService;
import com.google.common.flogger.FluentLogger;
Expand All @@ -17,7 +17,7 @@ public static OpenAIApi createOpenAiAPI(String apiKey) {

public static OpenAIApi createOpenAiAPI() {
return OpenAIService.buildApi(
Utils.getOpenAIApiKeyFromEnv(Optional.of(logger)), DEFAULT_TIMEOUT);
ApiKeyUtils.getOpenAIApiKeyFromEnv(Optional.of(logger)), DEFAULT_TIMEOUT);
}

public static OpenAIService createOpenAIService(String apiKey) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone;

import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.delete.DeleteRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.delete.DeleteResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.fetch.FetchResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.query.QueryRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.query.QueryResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.update.UpdateRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.update.UpdateResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.upsert.UpsertRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.upsert.UpsertResponse;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;

public interface PineconeAPI {

@POST("/vectors/upsert")
ListenableFuture<UpsertResponse> upsert(@Body UpsertRequest request);

@POST("/query")
ListenableFuture<QueryResponse> query(@Body QueryRequest request);

@POST("/vectors/delete")
ListenableFuture<DeleteResponse> delete(@Body DeleteRequest request);

@GET("/vectors/fetch")
ListenableFuture<FetchResponse> fetch(
@Query("namespace") String namespace, @Query("ids") List<String> ids);

@POST("/vectors/update")
ListenableFuture<UpdateResponse> update(@Body UpdateRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone;

import java.io.IOException;
import java.util.Objects;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/** OkHttp Interceptor that adds an authorization header */
public class PineconeAuthenticationInterceptor implements Interceptor {

private final String apiKey;

PineconeAuthenticationInterceptor(String apiKey) {
Objects.requireNonNull(apiKey, "Pinecone API required");
this.apiKey = apiKey;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request =
chain
.request()
.newBuilder()
.header("accept", "application/json")
.header("content-type", "application/json")
.header("Api-Key", apiKey)
.build();
return chain.proceed(request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone;

import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.PineconeServiceConfig;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.delete.DeleteRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.delete.DeleteResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.fetch.FetchRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.fetch.FetchResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.query.QueryRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.query.QueryResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.update.UpdateRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.update.UpdateResponse;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.upsert.UpsertRequest;
import ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.upsert.UpsertResponse;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import okhttp3.*;
import okhttp3.OkHttpClient.Builder;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.guava.GuavaCallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;

public class PineconeService {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();

private static final ObjectMapper mapper = defaultObjectMapper();
private final PineconeAPI api;
private final ExecutorService executorService;

public PineconeService(final PineconeServiceConfig pineconeServiceConfig) {
ObjectMapper mapper = defaultObjectMapper();
OkHttpClient client = buildClient(pineconeServiceConfig);
Retrofit retrofit = defaultRetrofit(pineconeServiceConfig.endpoint(), client, mapper);

this.api = retrofit.create(PineconeAPI.class);
this.executorService = client.dispatcher().executorService();
}

public PineconeService(final PineconeAPI api) {
this.api = api;
this.executorService = null;
}

public PineconeService(final PineconeAPI api, final ExecutorService executorService) {
this.api = api;
this.executorService = executorService;
}

public static <T> T execute(ListenableFuture<T> apiCall) {
try {
return apiCall.get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
if (e.getCause() instanceof HttpException) {
HttpException httpException = (HttpException) e.getCause();
try {
String errorBody = httpException.response().errorBody().string();
logger.atSevere().log("HTTP Error: %s", errorBody);
throw new RuntimeException(errorBody);
} catch (IOException ioException) {
logger.atSevere().withCause(ioException).log("Error while reading errorBody");
}
}
throw new RuntimeException(e);
}
}

public static ObjectMapper defaultObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return mapper;
}

public static OkHttpClient buildClient(PineconeServiceConfig pineconeServiceConfig) {
logger.atInfo().log("Pinecone:" + pineconeServiceConfig.apiKey());
Builder builder =
new Builder()
.addInterceptor(new PineconeAuthenticationInterceptor(pineconeServiceConfig.apiKey()))
.connectionPool(new ConnectionPool(5, 1, TimeUnit.SECONDS))
.readTimeout(pineconeServiceConfig.timeoutDuration().toMillis(), TimeUnit.MILLISECONDS);

if (pineconeServiceConfig.enableLogging()) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
builder.addInterceptor(logging.setLevel(HttpLoggingInterceptor.Level.BODY));
}
return builder.build();
}

public static Retrofit defaultRetrofit(
String endpoint, OkHttpClient client, ObjectMapper mapper) {
return new Retrofit.Builder()
.baseUrl(endpoint.startsWith("https://") ? endpoint : "https://" + endpoint)
.client(client)
.addConverterFactory(JacksonConverterFactory.create(mapper))
.addCallAdapterFactory(GuavaCallAdapterFactory.create())
.build();
}

public UpsertResponse upsert(UpsertRequest request) {
return execute(api.upsert(request));
}

public ListenableFuture<UpsertResponse> upsertAsync(UpsertRequest request) {
return api.upsert(request);
}

public QueryResponse query(QueryRequest request) {
return execute(api.query(request));
}

public ListenableFuture<QueryResponse> queryAsync(QueryRequest request) {
return api.query(request);
}

public DeleteResponse delete(DeleteRequest request) {
return execute(api.delete(request));
}

public ListenableFuture<DeleteResponse> queryAsync(DeleteRequest request) {
return api.delete(request);
}

public FetchResponse fetch(FetchRequest request) {
return execute(api.fetch(request.getNamespace(), request.getIds()));
}

public ListenableFuture<FetchResponse> fetchAsync(FetchRequest request) {
return api.fetch(request.getNamespace(), request.getIds());
}

public UpdateResponse update(UpdateRequest request) {
return execute(api.update(request));
}

public ListenableFuture<UpdateResponse> updateAsync(UpdateRequest request) {
return api.update(request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone.schema;

import com.google.auto.value.AutoValue;
import java.time.Duration;

@AutoValue
public abstract class PineconeServiceConfig {
public static Builder builder() {
return new AutoValue_PineconeServiceConfig.Builder()
.setTimeoutDuration(Duration.ofSeconds(10))
.setEnableLogging(false);
}

public abstract String apiKey();

public abstract String endpoint();

public abstract Duration timeoutDuration();

public abstract boolean enableLogging();

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setEndpoint(String endpoint);

public abstract Builder setApiKey(String newApiKey);

public abstract Builder setTimeoutDuration(Duration timeoutDuration);

public abstract Builder setEnableLogging(boolean enableLogging);

public abstract PineconeServiceConfig build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder(toBuilder = true, setterPrefix = "set")
@NoArgsConstructor
@AllArgsConstructor
public class SparseValues {
@JsonProperty("indices")
private List<Integer> indices;

@JsonProperty("values")
private List<Double> values;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder(toBuilder = true, setterPrefix = "set")
@NoArgsConstructor
@AllArgsConstructor
public class Vector {
@JsonProperty("id")
private String id;

@JsonProperty("values")
private List<Double> values;

@JsonProperty("sparseValues")
private SparseValues sparseValues;

@JsonProperty("metadata")
private Map<String, String> metadata;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ai.knowly.langtorch.store.vectordb.integration.pinecone.schema.dto.delete;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Data;

@Data
@Builder(toBuilder = true, setterPrefix = "set")
public class DeleteRequest {
@JsonProperty("ids")
private List<String> ids;

@JsonProperty("deleteAll")
private boolean deleteAll;

@JsonProperty("namespace")
private String namespace;

@JsonProperty("filter")
private Map<String, String> filter;
}
Loading