Skip to content

Commit a528253

Browse files
ilayaperumalgtzolov
authored andcommitted
Use ApiKey for OpenAI Image/Audio/Moderation APIs
- Update to use ApiKey when instantiating OpenAI Image/Audio/Moderation APIs - Add Builders for OpenAI Image/Audio/Moderation APIs and deprecate existing constructors - Add/update tests - Replace hasText check with notNull for ApiKey with String value Signed-off-by: Ilayaperumal Gopinathan <ilayaperumal.gopinathan@broadcom.com>
1 parent c19287d commit a528253

20 files changed

+657
-49
lines changed

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,7 @@ public OpenAiApi(String baseUrl, String apiKey, MultiValueMap<String, String> he
186186
* @param restClientBuilder RestClient builder.
187187
* @param webClientBuilder WebClient builder.
188188
* @param responseErrorHandler Response error handler.
189-
* @deprecated since 1.0.0.M6 - use {@link #builder()} instead
190189
*/
191-
@Deprecated(since = "1.0.0.M6")
192190
public OpenAiApi(String baseUrl, ApiKey apiKey, MultiValueMap<String, String> headers, String completionsPath,
193191
String embeddingsPath, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
194192
ResponseErrorHandler responseErrorHandler) {
@@ -1680,7 +1678,7 @@ public Builder apiKey(ApiKey apiKey) {
16801678
}
16811679

16821680
public Builder apiKey(String simpleApiKey) {
1683-
Assert.notNull(simpleApiKey, "apiKey cannot be null");
1681+
Assert.notNull(simpleApiKey, "simpleApiKey cannot be null");
16841682
this.apiKey = new SimpleApiKey(simpleApiKey);
16851683
return this;
16861684
}

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import reactor.core.publisher.Flux;
2727
import reactor.core.publisher.Mono;
2828

29+
import org.springframework.ai.model.ApiKey;
30+
import org.springframework.ai.model.NoopApiKey;
31+
import org.springframework.ai.model.SimpleApiKey;
2932
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
3033
import org.springframework.ai.retry.RetryUtils;
3134
import org.springframework.core.io.ByteArrayResource;
@@ -45,6 +48,7 @@
4548
* <a href="https://platform.openai.com/docs/api-reference/audio">OpenAI Audio</a>
4649
*
4750
* @author Christian Tzolov
51+
* @author Ilayaperumal Gopinathan
4852
* @since 0.8.1
4953
*/
5054
public class OpenAiAudioApi {
@@ -56,7 +60,9 @@ public class OpenAiAudioApi {
5660
/**
5761
* Create a new audio api.
5862
* @param openAiToken OpenAI apiKey.
63+
* @deprecated use {@link Builder} instead.
5964
*/
65+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
6066
public OpenAiAudioApi(String openAiToken) {
6167
this(OpenAiApiConstants.DEFAULT_BASE_URL, openAiToken, RestClient.builder(), WebClient.builder(),
6268
RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER);
@@ -68,10 +74,11 @@ public OpenAiAudioApi(String openAiToken) {
6874
* @param openAiToken OpenAI apiKey.
6975
* @param restClientBuilder RestClient builder.
7076
* @param responseErrorHandler Response error handler.
77+
* @deprecated use {@link Builder} instead.
7178
*/
79+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
7280
public OpenAiAudioApi(String baseUrl, String openAiToken, RestClient.Builder restClientBuilder,
7381
ResponseErrorHandler responseErrorHandler) {
74-
7582
Consumer<HttpHeaders> authHeaders;
7683
if (openAiToken != null && !openAiToken.isEmpty()) {
7784
authHeaders = h -> h.setBearerAuth(openAiToken);
@@ -96,7 +103,9 @@ public OpenAiAudioApi(String baseUrl, String openAiToken, RestClient.Builder res
96103
* @param restClientBuilder RestClient builder.
97104
* @param webClientBuilder WebClient builder.
98105
* @param responseErrorHandler Response error handler.
106+
* @deprecated use {@link Builder} instead.
99107
*/
108+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
100109
public OpenAiAudioApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder,
101110
WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler) {
102111

@@ -112,14 +121,31 @@ public OpenAiAudioApi(String baseUrl, String apiKey, RestClient.Builder restClie
112121
* @param restClientBuilder RestClient builder.
113122
* @param webClientBuilder WebClient builder.
114123
* @param responseErrorHandler Response error handler.
124+
* @deprecated use {@link Builder} instead.
115125
*/
126+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
116127
public OpenAiAudioApi(String baseUrl, String apiKey, MultiValueMap<String, String> headers,
117128
RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
118129
ResponseErrorHandler responseErrorHandler) {
130+
this(baseUrl, new SimpleApiKey(apiKey), headers, restClientBuilder, webClientBuilder, responseErrorHandler);
131+
}
132+
133+
/**
134+
* Create a new audio api.
135+
* @param baseUrl api base URL.
136+
* @param apiKey OpenAI apiKey.
137+
* @param headers the http headers to use.
138+
* @param restClientBuilder RestClient builder.
139+
* @param webClientBuilder WebClient builder.
140+
* @param responseErrorHandler Response error handler.
141+
*/
142+
public OpenAiAudioApi(String baseUrl, ApiKey apiKey, MultiValueMap<String, String> headers,
143+
RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
144+
ResponseErrorHandler responseErrorHandler) {
119145

120146
Consumer<HttpHeaders> authHeaders = h -> {
121-
if (apiKey != null && !apiKey.isEmpty()) {
122-
h.setBearerAuth(apiKey);
147+
if (!(apiKey instanceof NoopApiKey)) {
148+
h.setBearerAuth(apiKey.getValue());
123149
}
124150
h.addAll(headers);
125151
// h.setContentType(MediaType.APPLICATION_JSON);
@@ -133,6 +159,10 @@ public OpenAiAudioApi(String baseUrl, String apiKey, MultiValueMap<String, Strin
133159
this.webClient = webClientBuilder.baseUrl(baseUrl).defaultHeaders(authHeaders).build();
134160
}
135161

162+
public static Builder builder() {
163+
return new Builder();
164+
}
165+
136166
/**
137167
* Request to generates audio from the input text.
138168
* @param requestBody The request body.
@@ -932,4 +962,71 @@ public record Segment(
932962

933963
}
934964

965+
/**
966+
* Builder to construct {@link OpenAiAudioApi} instance.
967+
*/
968+
public static class Builder {
969+
970+
private String baseUrl = OpenAiApiConstants.DEFAULT_BASE_URL;
971+
972+
private ApiKey apiKey;
973+
974+
private MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
975+
976+
private RestClient.Builder restClientBuilder = RestClient.builder();
977+
978+
private WebClient.Builder webClientBuilder = WebClient.builder();
979+
980+
private ResponseErrorHandler responseErrorHandler = RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER;
981+
982+
public Builder baseUrl(String baseUrl) {
983+
Assert.hasText(baseUrl, "baseUrl cannot be null or empty");
984+
this.baseUrl = baseUrl;
985+
return this;
986+
}
987+
988+
public Builder apiKey(ApiKey apiKey) {
989+
Assert.notNull(apiKey, "apiKey cannot be null");
990+
this.apiKey = apiKey;
991+
return this;
992+
}
993+
994+
public Builder apiKey(String simpleApiKey) {
995+
Assert.notNull(simpleApiKey, "simpleApiKey cannot be null");
996+
this.apiKey = new SimpleApiKey(simpleApiKey);
997+
return this;
998+
}
999+
1000+
public Builder headers(MultiValueMap<String, String> headers) {
1001+
Assert.notNull(headers, "headers cannot be null");
1002+
this.headers = headers;
1003+
return this;
1004+
}
1005+
1006+
public Builder restClientBuilder(RestClient.Builder restClientBuilder) {
1007+
Assert.notNull(restClientBuilder, "restClientBuilder cannot be null");
1008+
this.restClientBuilder = restClientBuilder;
1009+
return this;
1010+
}
1011+
1012+
public Builder webClientBuilder(WebClient.Builder webClientBuilder) {
1013+
Assert.notNull(webClientBuilder, "webClientBuilder cannot be null");
1014+
this.webClientBuilder = webClientBuilder;
1015+
return this;
1016+
}
1017+
1018+
public Builder responseErrorHandler(ResponseErrorHandler responseErrorHandler) {
1019+
Assert.notNull(responseErrorHandler, "responseErrorHandler cannot be null");
1020+
this.responseErrorHandler = responseErrorHandler;
1021+
return this;
1022+
}
1023+
1024+
public OpenAiAudioApi build() {
1025+
Assert.notNull(this.apiKey, "apiKey must be set");
1026+
return new OpenAiAudioApi(this.baseUrl, this.apiKey, this.headers, this.restClientBuilder,
1027+
this.webClientBuilder, this.responseErrorHandler);
1028+
}
1029+
1030+
}
1031+
9351032
}

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@
2222
import com.fasterxml.jackson.annotation.JsonInclude;
2323
import com.fasterxml.jackson.annotation.JsonProperty;
2424

25+
import org.springframework.ai.model.ApiKey;
26+
import org.springframework.ai.model.NoopApiKey;
27+
import org.springframework.ai.model.SimpleApiKey;
2528
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
2629
import org.springframework.ai.retry.RetryUtils;
2730
import org.springframework.http.MediaType;
2831
import org.springframework.http.ResponseEntity;
2932
import org.springframework.util.Assert;
3033
import org.springframework.util.CollectionUtils;
34+
import org.springframework.util.LinkedMultiValueMap;
3135
import org.springframework.util.MultiValueMap;
3236
import org.springframework.web.client.ResponseErrorHandler;
3337
import org.springframework.web.client.RestClient;
@@ -46,7 +50,9 @@ public class OpenAiImageApi {
4650
/**
4751
* Create a new OpenAI Image api with base URL set to {@code https://api.openai.com}.
4852
* @param openAiToken OpenAI apiKey.
53+
* @deprecated use {@link Builder} instead.
4954
*/
55+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
5056
public OpenAiImageApi(String openAiToken) {
5157
this(OpenAiApiConstants.DEFAULT_BASE_URL, openAiToken, RestClient.builder());
5258
}
@@ -55,8 +61,9 @@ public OpenAiImageApi(String openAiToken) {
5561
* Create a new OpenAI Image API with the provided base URL.
5662
* @param baseUrl the base URL for the OpenAI API.
5763
* @param openAiToken OpenAI apiKey.
58-
* @param restClientBuilder the rest client builder to use.
64+
* @deprecated use {@link Builder} instead.
5965
*/
66+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
6067
public OpenAiImageApi(String baseUrl, String openAiToken, RestClient.Builder restClientBuilder) {
6168
this(baseUrl, openAiToken, restClientBuilder, RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER);
6269
}
@@ -66,8 +73,9 @@ public OpenAiImageApi(String baseUrl, String openAiToken, RestClient.Builder res
6673
* @param baseUrl the base URL for the OpenAI API.
6774
* @param apiKey OpenAI apiKey.
6875
* @param restClientBuilder the rest client builder to use.
69-
* @param responseErrorHandler the response error handler to use.
76+
* @deprecated use {@link Builder} instead.
7077
*/
78+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
7179
public OpenAiImageApi(String baseUrl, String apiKey, RestClient.Builder restClientBuilder,
7280
ResponseErrorHandler responseErrorHandler) {
7381
this(baseUrl, apiKey, CollectionUtils.toMultiValueMap(Map.of()), restClientBuilder, responseErrorHandler);
@@ -80,15 +88,31 @@ public OpenAiImageApi(String baseUrl, String apiKey, RestClient.Builder restClie
8088
* @param headers the http headers to use.
8189
* @param restClientBuilder the rest client builder to use.
8290
* @param responseErrorHandler the response error handler to use.
91+
* @deprecated use {@link Builder} instead.
8392
*/
93+
@Deprecated(forRemoval = true, since = "1.0.0-M6")
8494
public OpenAiImageApi(String baseUrl, String apiKey, MultiValueMap<String, String> headers,
8595
RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) {
8696

97+
this(baseUrl, new SimpleApiKey(apiKey), headers, restClientBuilder, responseErrorHandler);
98+
}
99+
100+
/**
101+
* Create a new OpenAI Image API with the provided base URL.
102+
* @param baseUrl the base URL for the OpenAI API.
103+
* @param apiKey OpenAI apiKey.
104+
* @param headers the http headers to use.
105+
* @param restClientBuilder the rest client builder to use.
106+
* @param responseErrorHandler the response error handler to use.
107+
*/
108+
public OpenAiImageApi(String baseUrl, ApiKey apiKey, MultiValueMap<String, String> headers,
109+
RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) {
110+
87111
// @formatter:off
88112
this.restClient = restClientBuilder.baseUrl(baseUrl)
89113
.defaultHeaders(h -> {
90-
if(apiKey != null && !apiKey.isEmpty()) {
91-
h.setBearerAuth(apiKey);
114+
if(!(apiKey instanceof NoopApiKey)) {
115+
h.setBearerAuth(apiKey.getValue());
92116
}
93117
h.setContentType(MediaType.APPLICATION_JSON);
94118
h.addAll(headers);
@@ -169,4 +193,67 @@ public record Data(@JsonProperty("url") String url, @JsonProperty("b64_json") St
169193

170194
}
171195

196+
public static Builder builder() {
197+
return new Builder();
198+
}
199+
200+
/**
201+
* Builder to construct {@link OpenAiImageApi} instance.
202+
*/
203+
public static class Builder {
204+
205+
private String baseUrl = OpenAiApiConstants.DEFAULT_BASE_URL;
206+
207+
private ApiKey apiKey;
208+
209+
private MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
210+
211+
private RestClient.Builder restClientBuilder = RestClient.builder();
212+
213+
private ResponseErrorHandler responseErrorHandler = RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER;
214+
215+
public Builder baseUrl(String baseUrl) {
216+
Assert.hasText(baseUrl, "baseUrl cannot be null or empty");
217+
this.baseUrl = baseUrl;
218+
return this;
219+
}
220+
221+
public Builder apiKey(ApiKey apiKey) {
222+
Assert.notNull(apiKey, "apiKey cannot be null");
223+
this.apiKey = apiKey;
224+
return this;
225+
}
226+
227+
public Builder apiKey(String simpleApiKey) {
228+
Assert.notNull(simpleApiKey, "simpleApiKey cannot be null");
229+
this.apiKey = new SimpleApiKey(simpleApiKey);
230+
return this;
231+
}
232+
233+
public Builder headers(MultiValueMap<String, String> headers) {
234+
Assert.notNull(headers, "headers cannot be null");
235+
this.headers = headers;
236+
return this;
237+
}
238+
239+
public Builder restClientBuilder(RestClient.Builder restClientBuilder) {
240+
Assert.notNull(restClientBuilder, "restClientBuilder cannot be null");
241+
this.restClientBuilder = restClientBuilder;
242+
return this;
243+
}
244+
245+
public Builder responseErrorHandler(ResponseErrorHandler responseErrorHandler) {
246+
Assert.notNull(responseErrorHandler, "responseErrorHandler cannot be null");
247+
this.responseErrorHandler = responseErrorHandler;
248+
return this;
249+
}
250+
251+
public OpenAiImageApi build() {
252+
Assert.notNull(this.apiKey, "apiKey must be set");
253+
return new OpenAiImageApi(this.baseUrl, this.apiKey, this.headers, this.restClientBuilder,
254+
this.responseErrorHandler);
255+
}
256+
257+
}
258+
172259
}

0 commit comments

Comments
 (0)