From 8f1826aef6b8d6c6297bb148a3d4fe882f4fc3ee Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Thu, 19 Oct 2023 16:25:41 +0200 Subject: [PATCH] Allow the openai embedding client to use different model, key and url from the completion one --- .../openai/OpenAiAutoConfiguration.java | 57 +++++++++---------- .../openai/OpenAiProperties.java | 55 ++++++++++++------ 2 files changed, 66 insertions(+), 46 deletions(-) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java index ba60f0a84..4c0d6790c 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java @@ -16,10 +16,11 @@ package org.springframework.ai.autoconfigure.openai; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.theokanning.openai.OpenAiApi; -import com.theokanning.openai.service.OpenAiService; +import java.time.Duration; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.theokanning.openai.client.OpenAiApi; +import com.theokanning.openai.service.OpenAiService; import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; @@ -27,10 +28,11 @@ import retrofit2.converter.jackson.JacksonConverterFactory; import org.springframework.ai.autoconfigure.NativeHints; import org.springframework.ai.embedding.EmbeddingClient; -import org.springframework.ai.openai.embedding.OpenAiEmbeddingClient; import org.springframework.ai.openai.client.OpenAiClient; +import org.springframework.ai.openai.embedding.OpenAiEmbeddingClient; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ImportRuntimeHints; @@ -44,27 +46,37 @@ import static org.springframework.ai.autoconfigure.openai.OpenAiProperties.CONFI @ImportRuntimeHints(NativeHints.class) public class OpenAiAutoConfiguration { - private final OpenAiProperties openAiProperties; - - public OpenAiAutoConfiguration(OpenAiProperties openAiProperties) { - this.openAiProperties = openAiProperties; + @Bean + @ConditionalOnMissingBean + public OpenAiClient openAiClient(OpenAiProperties openAiProperties) { + OpenAiClient openAiClient = new OpenAiClient(theoOpenAiService(openAiProperties.getBaseUrl(), + openAiProperties.getApiKey(), openAiProperties.getDuration())); + openAiClient.setTemperature(openAiProperties.getTemperature()); + openAiClient.setModel(openAiProperties.getModel()); + return openAiClient; } @Bean - public OpenAiService theoOpenAiService(OpenAiProperties openAiProperties) { - if ("https://api.openai.com".equals(openAiProperties.getBaseUrl())) { - if (!StringUtils.hasText(openAiProperties.getApiKey())) { - throw new IllegalArgumentException( - "You must provide an API key with the property name " + CONFIG_PREFIX + ".api-key"); - } + @ConditionalOnMissingBean + public EmbeddingClient openAiEmbeddingClient(OpenAiProperties openAiProperties) { + return new OpenAiEmbeddingClient(theoOpenAiService(openAiProperties.getEmbeddingBaseUrl(), + openAiProperties.getEmbeddingApiKey(), openAiProperties.getDuration()), + openAiProperties.getEmbeddingModel()); + } + + private OpenAiService theoOpenAiService(String baseUrl, String apiKey, Duration duration) { + + if ("https://api.openai.com".equals(baseUrl) && !StringUtils.hasText(apiKey)) { + throw new IllegalArgumentException( + "You must provide an API key with the property name " + CONFIG_PREFIX + ".api-key"); } ObjectMapper mapper = OpenAiService.defaultObjectMapper(); - OkHttpClient client = OpenAiService.defaultClient(openAiProperties.getApiKey(), openAiProperties.getDuration()); + OkHttpClient client = OpenAiService.defaultClient(apiKey, duration); // Waiting for https://github.com/TheoKanning/openai-java/issues/249 to be // resolved. - Retrofit retrofit = new Retrofit.Builder().baseUrl(openAiProperties.getBaseUrl()) + Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl) .client(client) .addConverterFactory(JacksonConverterFactory.create(mapper)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) @@ -75,17 +87,4 @@ public class OpenAiAutoConfiguration { return new OpenAiService(api); } - @Bean - public OpenAiClient openAiClient(OpenAiProperties openAiProperties, OpenAiService theoOpenAiService) { - OpenAiClient openAiClient = new OpenAiClient(theoOpenAiService); - openAiClient.setTemperature(openAiProperties.getTemperature()); - openAiClient.setModel(openAiProperties.getModel()); - return openAiClient; - } - - @Bean - public EmbeddingClient openAiEmbeddingClient(OpenAiService theoOpenAiService) { - return new OpenAiEmbeddingClient(theoOpenAiService, openAiProperties.getEmbeddingModel()); - } - } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiProperties.java index 8a228e75a..590a33aca 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiProperties.java @@ -17,6 +17,7 @@ package org.springframework.ai.autoconfigure.openai; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.StringUtils; import java.time.Duration; @@ -27,20 +28,24 @@ public class OpenAiProperties { public static final String CONFIG_PREFIX = "spring.ai.openai"; - private String apiKey; - private Double temperature = 0.7; private Duration duration = Duration.ofSeconds(60); - private String model = "gpt-3.5-turbo"; + private String apiKey; - private String embeddingModel = "text-embedding-ada-002"; + private String model = "gpt-3.5-turbo"; private String baseUrl = "https://api.openai.com"; + private String embeddingModel = "text-embedding-ada-002"; + + private String embeddingBaseUrl; + + private String embeddingApiKey; + public String getApiKey() { - return apiKey; + return this.apiKey; } public void setApiKey(String apiKey) { @@ -48,23 +53,15 @@ public class OpenAiProperties { } public String getModel() { - return model; + return this.model; } public void setModel(String model) { this.model = model; } - public String getEmbeddingModel() { - return embeddingModel; - } - - public void setEmbeddingModel(String embeddingModel) { - this.embeddingModel = embeddingModel; - } - public Double getTemperature() { - return temperature; + return this.temperature; } public void setTemperature(Double temperature) { @@ -72,7 +69,7 @@ public class OpenAiProperties { } public Duration getDuration() { - return duration; + return this.duration; } public void setDuration(Duration duration) { @@ -80,11 +77,35 @@ public class OpenAiProperties { } public String getBaseUrl() { - return baseUrl; + return this.baseUrl; } public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; } + public String getEmbeddingModel() { + return this.embeddingModel; + } + + public void setEmbeddingModel(String embeddingModel) { + this.embeddingModel = embeddingModel; + } + + public void setEmbeddingBaseUrl(String embeddingBaseUrl) { + this.embeddingBaseUrl = embeddingBaseUrl; + } + + public String getEmbeddingBaseUrl() { + return StringUtils.hasText(this.embeddingBaseUrl) ? this.embeddingBaseUrl : this.baseUrl; + } + + public String getEmbeddingApiKey() { + return StringUtils.hasText(this.embeddingApiKey) ? this.embeddingApiKey : this.apiKey; + } + + public void setEmbeddingApiKey(String embeddingApiKey) { + this.embeddingApiKey = embeddingApiKey; + } + }