1010import com .sap .ai .sdk .core .common .ClientResponseHandler ;
1111import com .sap .ai .sdk .core .common .ClientStreamingHandler ;
1212import com .sap .ai .sdk .core .common .StreamedDelta ;
13+ import com .sap .ai .sdk .foundationmodels .openai .model .OpenAiChatCompletionOutput ;
14+ import com .sap .ai .sdk .foundationmodels .openai .model .OpenAiChatCompletionParameters ;
15+ import com .sap .ai .sdk .foundationmodels .openai .model .OpenAiEmbeddingOutput ;
16+ import com .sap .ai .sdk .foundationmodels .openai .model .OpenAiEmbeddingParameters ;
1317import com .sap .ai .sdk .foundationmodels .openai .model2 .ChatCompletionStreamOptions ;
1418import com .sap .ai .sdk .foundationmodels .openai .model2 .ChatCompletionsCreate200Response ;
1519import com .sap .ai .sdk .foundationmodels .openai .model2 .CreateChatCompletionRequest ;
1620import com .sap .ai .sdk .foundationmodels .openai .model2 .CreateChatCompletionResponse ;
1721import com .sap .ai .sdk .foundationmodels .openai .model2 .EmbeddingsCreate200Response ;
1822import com .sap .ai .sdk .foundationmodels .openai .model2 .EmbeddingsCreateRequest ;
23+ import com .sap .ai .sdk .foundationmodels .openai .model2 .EmbeddingsCreateRequestInput ;
1924import com .sap .cloud .sdk .cloudplatform .connectivity .ApacheHttpClient5Accessor ;
2025import com .sap .cloud .sdk .cloudplatform .connectivity .DefaultHttpDestination ;
2126import com .sap .cloud .sdk .cloudplatform .connectivity .Destination ;
@@ -110,13 +115,6 @@ public static OpenAiClient withCustomDestination(@Nonnull final Destination dest
110115 return client .withApiVersion (DEFAULT_API_VERSION );
111116 }
112117
113- private static void throwOnContentFilter (@ Nonnull final OpenAiChatCompletionDelta delta ) {
114- final String finishReason = delta .getFinishReason ();
115- if (finishReason != null && finishReason .equals ("content_filter" )) {
116- throw new OpenAiClientException ("Content filter filtered the output." );
117- }
118- }
119-
120118 /**
121119 * Use this method to set a system prompt that should be used across multiple chat completions
122120 * with basic string prompts {@link #streamChatCompletionDeltas(OpenAiChatCompletionRequest)}.
@@ -153,32 +151,39 @@ public OpenAiChatCompletionResponse chatCompletion(@Nonnull final String prompt)
153151 return chatCompletion (request .toCreateChatCompletionRequest ());
154152 }
155153
154+ private static void throwOnContentFilter (@ Nonnull final OpenAiChatCompletionDelta delta ) {
155+ final String finishReason = delta .getFinishReason ();
156+ if (finishReason != null && finishReason .equals ("content_filter" )) {
157+ throw new OpenAiClientException ("Content filter filtered the output." );
158+ }
159+ }
160+
156161 /**
157- * Generate a completion for the given conversation and other request parameters .
162+ * Generate a completion for the given low-level request object .
158163 *
159164 * @param request the completion request.
160165 * @return the completion output
161166 * @throws OpenAiClientException if the request fails
162167 */
163168 @ Nonnull
164169 public OpenAiChatCompletionResponse chatCompletion (
165- @ Nonnull final OpenAiChatCompletionRequest request ) throws OpenAiClientException {
166- warnIfUnsupportedUsage ();
167- return chatCompletion ( request . toCreateChatCompletionRequest ( ));
170+ @ Nonnull final CreateChatCompletionRequest request ) throws OpenAiClientException {
171+ return new OpenAiChatCompletionResponse (
172+ execute ( "/chat/completions" , request , CreateChatCompletionResponse . class ));
168173 }
169174
170175 /**
171- * Generate a completion for the given low-level request object .
176+ * Generate a completion for the given conversation and request parameters .
172177 *
173178 * @param request the completion request.
174179 * @return the completion output
175180 * @throws OpenAiClientException if the request fails
176181 */
177182 @ Nonnull
178183 public OpenAiChatCompletionResponse chatCompletion (
179- @ Nonnull final CreateChatCompletionRequest request ) throws OpenAiClientException {
180- return new OpenAiChatCompletionResponse (
181- execute ( "/chat/completions" , request , CreateChatCompletionResponse . class ));
184+ @ Nonnull final OpenAiChatCompletionRequest request ) throws OpenAiClientException {
185+ warnIfUnsupportedUsage ();
186+ return chatCompletion ( request . toCreateChatCompletionRequest ( ));
182187 }
183188
184189 /**
@@ -223,7 +228,23 @@ public Stream<String> streamChatCompletion(@Nonnull final String prompt)
223228 }
224229
225230 /**
226- * Stream a completion for the given conversation and other request parameters.
231+ * Generate a completion for the given conversation and request parameters.
232+ *
233+ * @param parameters the completion request.
234+ * @return the completion output
235+ * @throws OpenAiClientException if the request fails
236+ * @deprecated Use {@link #chatCompletion(OpenAiChatCompletionRequest)} instead.
237+ */
238+ @ Deprecated (since = "1.3.0" )
239+ @ Nonnull
240+ public OpenAiChatCompletionOutput chatCompletion (
241+ @ Nonnull final OpenAiChatCompletionParameters parameters ) throws OpenAiClientException {
242+ warnIfUnsupportedUsage ();
243+ return execute ("/chat/completions" , parameters , OpenAiChatCompletionOutput .class );
244+ }
245+
246+ /**
247+ * Stream a completion for the given conversation and request parameters.
227248 *
228249 * <p>Returns a <b>lazily</b> populated stream of delta objects. To simply stream the text chunks
229250 * use {@link #streamChatCompletion(String)}
@@ -272,13 +293,84 @@ public Stream<OpenAiChatCompletionDelta> streamChatCompletionDeltas(
272293 return executeStream ("/chat/completions" , request , OpenAiChatCompletionDelta .class );
273294 }
274295
296+ /**
297+ * Stream a completion for the given conversation and request parameters.
298+ *
299+ * <p>Returns a <b>lazily</b> populated stream of delta objects. To simply stream the text chunks
300+ * use {@link #streamChatCompletion(String)}
301+ *
302+ * <p>The stream should be consumed using a try-with-resources block to ensure that the underlying
303+ * HTTP connection is closed.
304+ *
305+ * <p>Example:
306+ *
307+ * <pre>{@code
308+ * try (var stream = client.streamChatCompletionDeltas(prompt)) {
309+ * stream
310+ * .peek(delta -> System.out.println(delta.getUsage()))
311+ * .map(com.sap.ai.sdk.foundationmodels.openai.model.OpenAiChatCompletionDelta::getDeltaContent)
312+ * .forEach(System.out::println);
313+ * }
314+ * }</pre>
315+ *
316+ * <p>Please keep in mind that using a terminal stream operation like {@link Stream#forEach} will
317+ * block until all chunks are consumed. Also, for obvious reasons, invoking {@link
318+ * Stream#parallel()} on this stream is not supported.
319+ *
320+ * @param parameters The prompt, including a list of messages.
321+ * @return A stream of message deltas
322+ * @throws OpenAiClientException if the request fails or if the finish reason is content_filter
323+ * @deprecated Use {@link #streamChatCompletionDeltas(OpenAiChatCompletionRequest)} instead.
324+ */
325+ @ Deprecated (since = "1.3.0" )
326+ @ Nonnull
327+ public Stream <com .sap .ai .sdk .foundationmodels .openai .model .OpenAiChatCompletionDelta >
328+ streamChatCompletionDeltas (@ Nonnull final OpenAiChatCompletionParameters parameters )
329+ throws OpenAiClientException {
330+ warnIfUnsupportedUsage ();
331+ parameters .enableStreaming ();
332+ return executeStream (
333+ "/chat/completions" ,
334+ parameters ,
335+ com .sap .ai .sdk .foundationmodels .openai .model .OpenAiChatCompletionDelta .class );
336+ }
337+
275338 private void warnIfUnsupportedUsage () {
276339 if (systemPrompt != null ) {
277340 log .warn (
278341 "Previously set messages will be ignored, set it as an argument of this method instead." );
279342 }
280343 }
281344
345+ /**
346+ * Get a vector representation of a given string input that can be easily consumed by machine
347+ * learning models and algorithms.
348+ *
349+ * @param input the input text.
350+ * @return the embedding output
351+ * @throws OpenAiClientException if the request fails
352+ */
353+ @ Nonnull
354+ public EmbeddingsCreate200Response embedding (@ Nonnull final String input )
355+ throws OpenAiClientException {
356+ return embedding (
357+ new EmbeddingsCreateRequest ().input (EmbeddingsCreateRequestInput .create (input )));
358+ }
359+
360+ /**
361+ * Get a vector representation of a given request with input that can be easily consumed by
362+ * machine learning models and algorithms.
363+ *
364+ * @param request the request with input text.
365+ * @return the embedding output
366+ * @throws OpenAiClientException if the request fails
367+ */
368+ @ Nonnull
369+ public EmbeddingsCreate200Response embedding (@ Nonnull final EmbeddingsCreateRequest request )
370+ throws OpenAiClientException {
371+ return execute ("/embeddings" , request , EmbeddingsCreate200Response .class );
372+ }
373+
282374 /**
283375 * Get a vector representation of a given input that can be easily consumed by machine learning
284376 * models and algorithms.
@@ -288,9 +380,9 @@ private void warnIfUnsupportedUsage() {
288380 * @throws OpenAiClientException if the request fails
289381 */
290382 @ Nonnull
291- public EmbeddingsCreate200Response embedding (@ Nonnull final EmbeddingsCreateRequest parameters )
383+ public OpenAiEmbeddingOutput embedding (@ Nonnull final OpenAiEmbeddingParameters parameters )
292384 throws OpenAiClientException {
293- return execute ("/embeddings" , parameters , EmbeddingsCreate200Response .class );
385+ return execute ("/embeddings" , parameters , OpenAiEmbeddingOutput .class );
294386 }
295387
296388 @ Nonnull
0 commit comments