Replace the theokanning with custom OpenAi API client

- Introducing a new OpenAiApi native client for OpenAI API and get rid of the theokanning library.
   Amongst others the OpenAiApi allows:
    - easy base-url configuration (e.g. TAS-AI)
    - Flux response for streaming OpenAI results.
    - Exposes the http headers containing important metadata
    - Pure Spring ecosystem, making it easier for  Graal VM
 - Define a new  AiStreamClient interface returning Flux<AiResponse>
 - Refactor OpenAiClient and to use the new OpenAiApi and implement the AiStreamClient.
 - Use spring-retry to improve the OpenAI EmbeddingClient stability on 503 error.

 - Remove the OpenAI http header interceptor as the OpenAiApi returns ResponseEntity<T> that provides direct access to the headers.
 - Refactor the metadata headers and usage extraction.
 - Remove redundant and obsolete classes.
 - Fix dependency issue with Pinecone, netty-codec-http2 and Spring Boot 3.2
This commit is contained in:
Christian Tzolov
2023-12-13 15:48:28 +01:00
parent 7aad51da7f
commit e30be94a56
37 changed files with 1449 additions and 1190 deletions

View File

@@ -18,7 +18,6 @@ package org.springframework.ai.vectorstore;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -27,8 +26,6 @@ import java.util.UUID;
import javax.sql.DataSource;
import com.theokanning.openai.client.OpenAiApi;
import com.theokanning.openai.service.OpenAiService;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.Assert;
import org.junit.jupiter.api.Assertions;
@@ -38,12 +35,10 @@ import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingClient;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.openai.embedding.OpenAiEmbeddingClient;
import org.springframework.ai.vectorstore.PgVectorStore.PgIndexType;
import org.springframework.ai.vectorstore.filter.FilterExpressionTextParser.FilterExpressionParseException;
@@ -337,16 +332,7 @@ public class PgVectorStoreIT {
@Bean
public EmbeddingClient embeddingClient() {
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.openai.com")
.client(OpenAiService.defaultClient(System.getenv("OPENAI_API_KEY"), Duration.ofSeconds(60)))
.addConverterFactory(JacksonConverterFactory.create(OpenAiService.defaultObjectMapper()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
OpenAiApi api = retrofit.create(OpenAiApi.class);
return new OpenAiEmbeddingClient(new OpenAiService(api), "text-embedding-ada-002");
return new OpenAiEmbeddingClient(new OpenAiApi(System.getenv("OPENAI_API_KEY")));
}
}