Skip to content

Commit 263b1de

Browse files
rpanackalJonas-Isr
andauthored
docs: [OpenAI] Update documentation and release notes for new api (#354)
* Add parallel documentation for new openai api * Updating release notes and ToC in docs * fixes missed test and format change * Make version mentions bold * Fixing docs formatting, sample messages and release notes module tagging --------- Co-authored-by: Roshin Rajan Panackal <[email protected]> Co-authored-by: Jonas-Isr <[email protected]>
1 parent fb2e716 commit 263b1de

File tree

3 files changed

+114
-18
lines changed

3 files changed

+114
-18
lines changed

docs/guides/OPENAI_CHAT_COMPLETION.md

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Table of Contents
44

55
- [Introduction](#introduction)
6+
- [New User Interface (v1.4.0)](#new-user-interface-v140)
67
- [Prerequisites](#prerequisites)
78
- [Maven Dependencies](#maven-dependencies)
89
- [Usage](#usage)
@@ -18,6 +19,20 @@
1819

1920
This guide demonstrates how to use the SAP AI SDK for Java to perform chat completion tasks using OpenAI models deployed on SAP AI Core.
2021

22+
### New User Interface (v1.4.0)
23+
24+
We're excited to introduce a new user interface for OpenAI chat completions starting with **version 1.4.0**. This update is designed to improve the SDK by:
25+
26+
- **Decoupling Layers:** Separating the convenience layer from the model classes to deliver a more stable and maintainable experience.
27+
- **Staying Current:** Making it easier for the SDK to adapt to the latest changes in the OpenAI API specification.
28+
- **Consistent Design:** Aligning with the Orchestrator convenience API for a smoother transition and easier adoption.
29+
30+
**Please Note:**
31+
32+
- The new interface is gradually being rolled out across the SDK.
33+
- We welcome your feedback to help us refine this interface.
34+
- The existing interface (v1.0.0) remains available for compatibility.
35+
2136
## Prerequisites
2237

2338
Before using the AI Core module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements).
@@ -109,6 +124,20 @@ OpenAiClient.withCustomDestination(destination);
109124

110125
## Message history
111126

127+
**Since v1.4.0**
128+
129+
```java
130+
var request =
131+
new OpenAiChatCompletionRequest(
132+
OpenAiMessage.system("You are a helpful assistant"),
133+
OpenAiMessage.user("Hello World! Why is this phrase so famous?"));
134+
135+
var response = OpenAiClient.forModel(GPT_4O).chatCompletion(request).getContent();
136+
```
137+
138+
<details>
139+
<summary><b>Since v1.0.0</b></summary>
140+
112141
```java
113142
var systemMessage =
114143
new OpenAiChatSystemMessage().setContent("You are a helpful assistant");
@@ -124,6 +153,8 @@ String resultMessage = result.getContent();
124153

125154
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java)
126155

156+
</details>
157+
127158
## Chat Completion with Specific Model Version
128159

129160
By default, when no version is specified, the system selects one of the available deployments of the specified model, regardless of its version.
@@ -149,7 +180,7 @@ Ensure that the custom model is deployed in SAP AI Core.
149180

150181
It's possible to pass a stream of chat completion delta elements, e.g. from the application backend to the frontend in real-time.
151182

152-
### Asynchronous Streaming
183+
### Asynchronous Streaming - Blocking
153184

154185
This is a blocking example for streaming and printing directly to the console:
155186

@@ -168,16 +199,58 @@ try (Stream<String> stream = client.streamChatCompletion(msg)) {
168199
}
169200
```
170201

171-
### Aggregating Total Output
202+
### Asynchronous Streaming - Non-blocking
203+
204+
**Since v1.4.0**
205+
206+
The following example demonstrate how you can leverage a concurrency-safe container (like an AtomicReference) to "listen" for usage information in any incoming delta.
207+
208+
```java
209+
String question = "Can you give me the first 100 numbers of the Fibonacci sequence?";
210+
var userMessage = OpenAiMessage.user(question);
211+
var request = new OpenAiChatCompletionRequest(userMessage);
212+
213+
OpenAiClient client = OpenAiClient.forModel(GPT_4O);
214+
var usageRef = new AtomicReference<CompletionUsage>();
215+
216+
// Prepare the stream before starting the thread to handle any initialization exceptions
217+
Stream<OpenAiChatCompletionDelta> stream = client.streamChatCompletionDeltas(request);
218+
219+
// Create a new thread for asynchronous, non-blocking processing
220+
Thread streamProcessor =
221+
new Thread(
222+
() -> {
223+
// try-with-resources ensures the stream is closed after processing
224+
try (stream) {
225+
stream.forEach(
226+
delta -> {
227+
usageRef.compareAndExchange(null, delta.getCompletionUsage());
228+
System.out.println("Content: " + delta.getDeltaContent());
229+
});
230+
}
231+
});
232+
233+
// Start the processing thread; the main thread remains free (non-blocking)
234+
streamProcessor.start();
235+
// Wait for the thread to finish (blocking)
236+
streamProcessor.join();
237+
238+
// Access information caught from completion usage
239+
Integer tokensUsed = usageRef.get().getCompletionTokens();
240+
System.out.println("Tokens used: " + tokensUsed);
241+
```
242+
243+
<details>
244+
<summary><b>Since v1.0.0</b></summary>
172245

173246
The following example is non-blocking and demonstrates how to aggregate the complete response.
174247
Any asynchronous library can be used, such as the classic Thread API.
175248

176249
```java
177-
var message = "Can you give me the first 100 numbers of the Fibonacci sequence?";
250+
var question = "Can you give me the first 100 numbers of the Fibonacci sequence?";
178251

179252
var userMessage =
180-
new OpenAiChatMessage.OpenAiChatUserMessage().addText(message);
253+
new OpenAiChatMessage.OpenAiChatUserMessage().addText(question);
181254
var requestParameters =
182255
new OpenAiChatCompletionParameters().addMessages(userMessage);
183256

@@ -208,14 +281,32 @@ System.out.println("Tokens used: " + tokensUsed);
208281
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java). It shows the usage of Spring
209282
Boot's `ResponseBodyEmitter` to stream the chat completion delta messages to the frontend in real-time.
210283

284+
</details>
285+
211286
## Embedding
212287

288+
**Since v1.4.0**
289+
213290
Get the embeddings of a text input in list of float values:
214291

292+
```java
293+
var request = new OpenAiEmbeddingRequest(List.of("Hello World"));
294+
295+
OpenAiEmbeddingResponse response = OpenAiClient.forModel(TEXT_EMBEDDING_ADA_002).embedding(request);
296+
float[] embedding = embedding.getEmbeddings().get(0);
297+
```
298+
299+
<details>
300+
<summary><b>Since v1.0.0</b></summary>
301+
215302
```java
216303
var request = new OpenAiEmbeddingParameters().setInput("Hello World");
217304

218305
OpenAiEmbeddingOutput embedding = OpenAiClient.forModel(TEXT_EMBEDDING_ADA_002).embedding(request);
306+
307+
float[] embedding = embedding.getData().get(0).getEmbedding();
219308
```
220309

221310
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java)
311+
312+
</details>

docs/release-notes/release_notes.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@
88

99
### 🔧 Compatibility Notes
1010

11-
- The constructors `UserMessage(MessageContent)` and `SystemMessage(MessageContent)` are removed. Use `Message.user(String)`, `Message.user(ImageItem)`, or `Message.system(String)` instead.
11+
- [Orchestration] The constructors `UserMessage(MessageContent)` and `SystemMessage(MessageContent)` are removed. Use `Message.user(String)`, `Message.user(ImageItem)`, or `Message.system(String)` instead.
1212
- Deprecate `getCustomField(String)` in favor of `toMap()` on generated model classes.
13-
- `com.sap.ai.sdk.core.model.*`
14-
- `com.sap.ai.sdk.orchestration.model.*`
13+
- `com.sap.ai.sdk.core.model.*`
14+
- `com.sap.ai.sdk.orchestration.model.*`
1515

1616
### ✨ New Functionality
1717

18-
- [Add Spring AI tool calling](../guides/SPRING_AI_INTEGRATION.md#tool-calling).
19-
- [Add Document Grounding Client](https://github.com/SAP/ai-sdk-java/tree/main/docs/guides/GROUNDING.md)
20-
- `com.sap.ai.sdk:document-grounding:1.4.0`
18+
- [Orchestration] [Add Spring AI tool calling](../guides/SPRING_AI_INTEGRATION.md#tool-calling).
19+
- [Document Grounding] [Add Document Grounding Client](https://github.com/SAP/ai-sdk-java/tree/main/docs/guides/GROUNDING.md)
20+
- `com.sap.ai.sdk:document-grounding:1.4.0`
21+
- [OpenAI]
22+
- New generated model classes introduced for _AzureOpenAI_ specification dated 2024-10-21.
23+
- Introducing [new user interface](../guides/OPENAI_CHAT_COMPLETION.md/#new-user-interface-v140) for chat completion wrapping the generated model classes.
24+
- `OpenAiChatCompletionRequest` and `OpenAiChatCompletionResponse`' for high level request and response handling.
25+
- `OpenAiUserMessage`, `OpenAiSystemMessage`, `OpenAiAssistantMessage` and `OpenAiToolMessage` for message creation for different content types.
26+
- `OpenAiToolChoice` for configuring chat completion requests with tool selection strategy.
27+
- Introducing new user interface for embedding calls using `OpenAiEmbeddingRequest` and `OpenAiEmbeddingResponse`.
2128

2229
### 📈 Improvements
2330

sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiV2Test.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,27 @@ void streamChatCompletion() {
4848
final var userMessage = OpenAiMessage.user("Who is the prettiest?");
4949
final var prompt = new OpenAiChatCompletionRequest(userMessage);
5050

51-
final var totalOutput = new AtomicReference<CompletionUsage>();
51+
final var usageRef = new AtomicReference<CompletionUsage>();
5252
final var filledDeltaCount = new AtomicInteger(0);
53+
5354
OpenAiClient.forModel(GPT_35_TURBO)
5455
.streamChatCompletionDeltas(prompt)
5556
// foreach consumes all elements, closing the stream at the end
5657
.forEach(
5758
delta -> {
58-
final var usage = delta.getCompletionUsage();
59-
totalOutput.compareAndExchange(null, usage);
59+
usageRef.compareAndExchange(null, delta.getCompletionUsage());
6060
final String deltaContent = delta.getDeltaContent();
6161
log.info("delta: {}", delta);
6262
if (!deltaContent.isEmpty()) {
6363
filledDeltaCount.incrementAndGet();
6464
}
6565
});
6666

67-
// the first two and the last delta don't have any content
68-
// see OpenAiChatCompletionDelta#getDeltaContent
6967
assertThat(filledDeltaCount.get()).isGreaterThan(0);
7068

71-
assertThat(totalOutput.get().getTotalTokens()).isGreaterThan(0);
72-
assertThat(totalOutput.get().getPromptTokens()).isEqualTo(14);
73-
assertThat(totalOutput.get().getCompletionTokens()).isGreaterThan(0);
69+
assertThat(usageRef.get().getTotalTokens()).isGreaterThan(0);
70+
assertThat(usageRef.get().getPromptTokens()).isEqualTo(14);
71+
assertThat(usageRef.get().getCompletionTokens()).isGreaterThan(0);
7472
}
7573

7674
@Test

0 commit comments

Comments
 (0)