Refine delineation of Embedding properties from OpenAI (client) properties.
Though the property names are different, for example 'spring.ai.openai.api-key' and 'spring.ai.openai.embedding-api-key, by introducing an additional property namespace, 'spring.ai.openai.embedding.*', this enables the configuration of embeddings to be properly encapsulated and related in Spring Boot fashion. Closes #102
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user