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 4c0d6790c..8f1190630 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 @@ -49,19 +49,25 @@ public class OpenAiAutoConfiguration { @Bean @ConditionalOnMissingBean public OpenAiClient openAiClient(OpenAiProperties openAiProperties) { - OpenAiClient openAiClient = new OpenAiClient(theoOpenAiService(openAiProperties.getBaseUrl(), - openAiProperties.getApiKey(), openAiProperties.getDuration())); + + OpenAiService openAiService = theoOpenAiService(openAiProperties.getBaseUrl(), openAiProperties.getApiKey(), + openAiProperties.getDuration()); + + OpenAiClient openAiClient = new OpenAiClient(openAiService); openAiClient.setTemperature(openAiProperties.getTemperature()); openAiClient.setModel(openAiProperties.getModel()); + return openAiClient; } @Bean @ConditionalOnMissingBean public EmbeddingClient openAiEmbeddingClient(OpenAiProperties openAiProperties) { - return new OpenAiEmbeddingClient(theoOpenAiService(openAiProperties.getEmbeddingBaseUrl(), - openAiProperties.getEmbeddingApiKey(), openAiProperties.getDuration()), - openAiProperties.getEmbeddingModel()); + + OpenAiService openAiService = theoOpenAiService(openAiProperties.getEmbedding().getBaseUrl(), + openAiProperties.getEmbedding().getApiKey(), openAiProperties.getDuration()); + + return new OpenAiEmbeddingClient(openAiService, openAiProperties.getEmbedding().getModel()); } private OpenAiService theoOpenAiService(String baseUrl, String apiKey, Duration duration) { 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 590a33aca..7cee1c011 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 @@ -16,12 +16,13 @@ package org.springframework.ai.autoconfigure.openai; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.StringUtils; +import static org.springframework.ai.autoconfigure.openai.OpenAiProperties.CONFIG_PREFIX; import java.time.Duration; -import static org.springframework.ai.autoconfigure.openai.OpenAiProperties.CONFIG_PREFIX; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; @ConfigurationProperties(CONFIG_PREFIX) public class OpenAiProperties { @@ -32,18 +33,14 @@ public class OpenAiProperties { private Duration duration = Duration.ofSeconds(60); + private final Embedding embedding = new Embedding(this); + private String apiKey; 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 this.apiKey; } @@ -60,6 +57,14 @@ public class OpenAiProperties { this.model = model; } + public String getBaseUrl() { + return this.baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + public Double getTemperature() { return this.temperature; } @@ -76,36 +81,53 @@ public class OpenAiProperties { this.duration = duration; } - public String getBaseUrl() { - return this.baseUrl; + public Embedding getEmbedding() { + return this.embedding; } - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } + public static class Embedding { - public String getEmbeddingModel() { - return this.embeddingModel; - } + private final OpenAiProperties openAiProperties; - public void setEmbeddingModel(String embeddingModel) { - this.embeddingModel = embeddingModel; - } + private String apiKey; - public void setEmbeddingBaseUrl(String embeddingBaseUrl) { - this.embeddingBaseUrl = embeddingBaseUrl; - } + private String model = "text-embedding-ada-002"; - public String getEmbeddingBaseUrl() { - return StringUtils.hasText(this.embeddingBaseUrl) ? this.embeddingBaseUrl : this.baseUrl; - } + private String baseUrl; - public String getEmbeddingApiKey() { - return StringUtils.hasText(this.embeddingApiKey) ? this.embeddingApiKey : this.apiKey; - } + protected Embedding(OpenAiProperties openAiProperties) { + Assert.notNull(openAiProperties, "OpenAiProperties must not be null"); + this.openAiProperties = openAiProperties; + } + + public OpenAiProperties getOpenAiProperties() { + return openAiProperties; + } + + public String getApiKey() { + return StringUtils.hasText(this.apiKey) ? this.apiKey : getOpenAiProperties().getApiKey(); + } + + public void setApiKey(String embeddingApiKey) { + this.apiKey = embeddingApiKey; + } + + public String getModel() { + return this.model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getBaseUrl() { + return StringUtils.hasText(this.baseUrl) ? this.baseUrl : getOpenAiProperties().getBaseUrl(); + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } - public void setEmbeddingApiKey(String embeddingApiKey) { - this.embeddingApiKey = embeddingApiKey; } } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java new file mode 100644 index 000000000..74390710a --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.openai; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * Unit Tests for {@link OpenAiProperties}. + * + * @author John Blum + * @since 0.7.1 + */ +@SpringBootTest(properties = { "spring.ai.openai.api-key=abc123", "spring.ai.openai.model=claudia-shiffer-5", + "spring.ai.openai.base-url=https://api.openai.spring.io/eieioh", "spring.ai.openai.temperature=0.5", + "spring.ai.openai.duration=30s", "spring.ai.openai.embedding.base-url=https://api.openai.spring.io/embedding" }) +@SuppressWarnings("unused") +class OpenAiPropertiesTests { + + @Autowired + private OpenAiProperties openAiProperties; + + @Test + void openAiPropertiesAreCorrect() { + + assertThat(this.openAiProperties).isNotNull(); + assertThat(this.openAiProperties.getApiKey()).isEqualTo("abc123"); + assertThat(this.openAiProperties.getModel()).isEqualTo("claudia-shiffer-5"); + assertThat(this.openAiProperties.getBaseUrl()).isEqualTo("https://api.openai.spring.io/eieioh"); + assertThat(this.openAiProperties.getTemperature()).isEqualTo(0.5d); + assertThat(this.openAiProperties.getDuration()).isEqualTo(Duration.ofSeconds(30L)); + + OpenAiProperties.Embedding embedding = this.openAiProperties.getEmbedding(); + + assertThat(embedding).isNotNull(); + assertThat(embedding.getApiKey()).isEqualTo(this.openAiProperties.getApiKey()); + assertThat(embedding.getModel()).isEqualTo("text-embedding-ada-002"); + assertThat(embedding.getBaseUrl()).isEqualTo("https://api.openai.spring.io/embedding"); + } + + @SpringBootConfiguration + @EnableConfigurationProperties(OpenAiProperties.class) + static class TestConfiguration { + + } + +}