Skip to content

Commit 2d8ff36

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/openai-conv-embedding
# Conflicts: # sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/services/OpenAiServiceV2.java
2 parents 31120de + 8d264de commit 2d8ff36

File tree

9 files changed

+118
-30
lines changed

9 files changed

+118
-30
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
![build](https://github.com/SAP/ai-sdk-java/actions/workflows/continuous-integration.yaml/badge.svg?branch=main)
22
![CodeQL](https://github.com/SAP/ai-sdk-java/actions/workflows/github-code-scanning/codeql/badge.svg)
33
[![REUSE status](https://api.reuse.software/badge/git.fsfe.org/reuse/api)](https://api.reuse.software/info/git.fsfe.org/reuse/api)
4-
[![Fosstars security rating](https://github.com/SAP/ai-sdk-java/blob/fosstars-report/fosstars_badge.svg)](https://github.com/SAP/ai-sdk-java/blob/fosstars-report/fosstars_report.md)
4+
[![Fosstars security rating](https://github.com/SAP/ai-sdk-java/actions/workflows/fosstars-report.yml/badge.svg?branch=main)](https://github.com/SAP/ai-sdk-java/blob/fosstars-report/fosstars_report.md)
55

66
# <img src="https://sap.github.io/cloud-sdk/img/logo.svg" alt="SAP Cloud SDK" width="30"/> SAP Cloud SDK for AI (for Java)
77

docs/guides/SPRING_AI_INTEGRATION.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,11 @@ First, add the Spring AI dependency to your `pom.xml`:
3232
</repository>
3333
```
3434

35-
:::note Spring AI Milestone Version
36-
Note that currently no stable version of Spring AI exists just yet.
37-
The AI SDK currently uses the [M6 milestone](https://spring.io/blog/2025/02/14/spring-ai-1-0-0-m6-released).
38-
39-
Please be aware that future versions of the AI SDK may increase the Spring AI version.
40-
:::
35+
> [!NOTE]
36+
> Note that currently no stable version of Spring AI exists just yet.
37+
> The AI SDK currently uses the [M6 milestone](https://spring.io/blog/2025/02/14/spring-ai-1-0-0-m6-released).
38+
>
39+
> Please be aware that future versions of the AI SDK may increase the Spring AI version.
4140
4241
## Orchestration Chat Completion
4342

docs/release-notes/release_notes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
### 🔧 Compatibility Notes
1010

1111
- The constructors `UserMessage(MessageContent)` and `SystemMessage(MessageContent)` are removed. Use `Message.user(String)`, `Message.user(ImageItem)`, or `Message.system(String)` instead.
12+
- 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.*`
1215

1316
### ✨ New Functionality
1417

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiChatCompletionRequest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.google.common.annotations.Beta;
44
import com.google.common.collect.Lists;
5+
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoice;
6+
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoiceFunction;
57
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionStreamOptions;
68
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionTool;
79
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionToolChoiceOption;
@@ -126,7 +128,9 @@ public class OpenAiChatCompletionRequest {
126128
@Nullable List<ChatCompletionTool> tools;
127129

128130
/** Option to control which tool is invoked by the model. */
129-
@Nullable ChatCompletionToolChoiceOption toolChoice;
131+
@With(AccessLevel.PRIVATE)
132+
@Nullable
133+
ChatCompletionToolChoiceOption toolChoice;
130134

131135
/**
132136
* Creates an OpenAiChatCompletionPrompt with string as user message.
@@ -248,6 +252,51 @@ public OpenAiChatCompletionRequest withLogprobs(@Nonnull final Boolean logprobs)
248252
this.toolChoice);
249253
}
250254

255+
/**
256+
* Only message generation will be performed without calling any tool.
257+
*
258+
* @return the current OpenAiChatCompletionRequest instance.
259+
*/
260+
@Nonnull
261+
public OpenAiChatCompletionRequest withToolChoiceNone() {
262+
return this.withToolChoice(ChatCompletionToolChoiceOption.create("none"));
263+
}
264+
265+
/**
266+
* The model may decide whether to call a (one or more) tool.
267+
*
268+
* @return the current OpenAiChatCompletionRequest instance.
269+
*/
270+
@Nonnull
271+
public OpenAiChatCompletionRequest withToolChoiceOptional() {
272+
return this.withToolChoice(ChatCompletionToolChoiceOption.create("auto"));
273+
}
274+
275+
/**
276+
* The model must call one or more tools as part of its processing.
277+
*
278+
* @return the current OpenAiChatCompletionRequest instance.
279+
*/
280+
@Nonnull
281+
public OpenAiChatCompletionRequest withToolChoiceRequired() {
282+
return this.withToolChoice(ChatCompletionToolChoiceOption.create("required"));
283+
}
284+
285+
/**
286+
* The model must call the function specified by {@code functionName}.
287+
*
288+
* @param functionName the name of the function that must be called.
289+
* @return the current OpenAiChatCompletionRequest instance.
290+
*/
291+
@Nonnull
292+
public OpenAiChatCompletionRequest withToolChoiceFunction(@Nonnull final String functionName) {
293+
return this.withToolChoice(
294+
ChatCompletionToolChoiceOption.create(
295+
new ChatCompletionNamedToolChoice()
296+
.type(ChatCompletionNamedToolChoice.TypeEnum.FUNCTION)
297+
.function(new ChatCompletionNamedToolChoiceFunction().name(functionName))));
298+
}
299+
251300
/**
252301
* Converts the request to a generated model class CreateChatCompletionRequest.
253302
*

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ public record OpenAiModel(@Nonnull String name, @Nullable String version) implem
4040
/** Azure OpenAI GPT-4o Mini chat completions model */
4141
public static final OpenAiModel GPT_4O_MINI = new OpenAiModel("gpt-4o-mini", null);
4242

43+
/** Azure OpenAI GPT-o3 Mini chat completions model */
44+
public static final OpenAiModel GPT_O3_MINI = new OpenAiModel("o3-mini", null);
45+
46+
/** Azure OpenAI GPT-o1 chat completions model */
47+
public static final OpenAiModel GPT_O1 = new OpenAiModel("o1", null);
48+
4349
/** Azure OpenAI Text Embedding 3 Large model */
4450
public static final OpenAiModel TEXT_EMBEDDING_3_LARGE =
4551
new OpenAiModel("text-embedding-3-large", null);

foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiChatCompletionRequestTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionRequestUserMessage;
66
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionRequestUserMessageContent;
7+
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionToolChoiceOption;
78
import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionRequestAllOfStop;
89
import java.math.BigDecimal;
910
import java.util.List;
@@ -45,4 +46,51 @@ void createWithExistingRequest() {
4546
assertThat(lowlevelRequest.getSeed()).isEqualTo(123);
4647
assertThat(lowlevelRequest.getTemperature()).isEqualTo(BigDecimal.valueOf(0.5));
4748
}
49+
50+
@Test
51+
void withToolChoiceNone() {
52+
OpenAiChatCompletionRequest request =
53+
new OpenAiChatCompletionRequest("message").withToolChoiceNone();
54+
55+
var lowLevelRequest = request.createCreateChatCompletionRequest();
56+
var choice =
57+
((ChatCompletionToolChoiceOption.InnerString) lowLevelRequest.getToolChoice()).value();
58+
assertThat(choice).isEqualTo("none");
59+
}
60+
61+
@Test
62+
void withToolChoiceOptional() {
63+
OpenAiChatCompletionRequest request =
64+
new OpenAiChatCompletionRequest("message").withToolChoiceOptional();
65+
66+
var lowLevelRequest = request.createCreateChatCompletionRequest();
67+
var choice =
68+
((ChatCompletionToolChoiceOption.InnerString) lowLevelRequest.getToolChoice()).value();
69+
assertThat(choice).isEqualTo("auto");
70+
}
71+
72+
@Test
73+
void withToolChoiceRequired() {
74+
OpenAiChatCompletionRequest request =
75+
new OpenAiChatCompletionRequest("message").withToolChoiceRequired();
76+
77+
var lowLevelRequest = request.createCreateChatCompletionRequest();
78+
var choice =
79+
((ChatCompletionToolChoiceOption.InnerString) lowLevelRequest.getToolChoice()).value();
80+
assertThat(choice).isEqualTo("required");
81+
}
82+
83+
@Test
84+
void withToolChoiceFunction() {
85+
OpenAiChatCompletionRequest request =
86+
new OpenAiChatCompletionRequest("message").withToolChoiceFunction("functionName");
87+
88+
var lowLevelRequest = request.createCreateChatCompletionRequest();
89+
var choice =
90+
((ChatCompletionToolChoiceOption.InnerChatCompletionNamedToolChoice)
91+
lowLevelRequest.getToolChoice())
92+
.value();
93+
assertThat(choice.getType().getValue()).isEqualTo("function");
94+
assertThat(choice.getFunction().getName()).isEqualTo("functionName");
95+
}
4896
}

foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientGeneratedTest.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@
2525
import static org.mockito.Mockito.times;
2626
import static org.mockito.Mockito.when;
2727

28-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoice;
29-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoiceFunction;
3028
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionResponseMessageRole;
3129
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionTool;
32-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionToolChoiceOption;
3330
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ContentFilterPromptResults;
3431
import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionRequest;
3532
import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionStreamResponseChoicesInner;
@@ -526,17 +523,11 @@ void chatCompletionTool() {
526523
final var tool =
527524
new ChatCompletionTool().type(ChatCompletionTool.TypeEnum.FUNCTION).function(function);
528525

529-
final var toolChoice =
530-
ChatCompletionToolChoiceOption.create(
531-
new ChatCompletionNamedToolChoice()
532-
.type(ChatCompletionNamedToolChoice.TypeEnum.FUNCTION)
533-
.function(new ChatCompletionNamedToolChoiceFunction().name("fibonacci")));
534-
535526
final var request =
536527
new OpenAiChatCompletionRequest(
537528
"A pair of rabbits is placed in a field. Each month, every pair produces one new pair, starting from the second month. How many rabbits will there be after 12 months?")
538529
.withTools(List.of(tool))
539-
.withToolChoice(toolChoice);
530+
.withToolChoiceFunction("fibonacci");
540531

541532
var response = client.chatCompletion(request).getOriginalResponse();
542533

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
class ScenarioTest {
1515

1616
@Test
17-
@DisplayName("Declared OpenAI models must match AI Core's available OpenAI models")
17+
@DisplayName(
18+
"Declared OpenAI models must be superset of our AI Core account's available OpenAI models")
1819
@SneakyThrows
1920
void openAiModelAvailability() {
2021

@@ -39,6 +40,6 @@ void openAiModelAvailability() {
3940
}
4041

4142
// Assert that the declared OpenAI models match the expected list
42-
assertThat(declaredOpenAiModelList).hasSameElementsAs(availableOpenAiModels);
43+
assertThat(declaredOpenAiModelList).containsAll(availableOpenAiModels);
4344
}
4445
}

sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/services/OpenAiServiceV2.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import com.sap.ai.sdk.foundationmodels.openai.OpenAiEmbeddingResponse;
1515
import com.sap.ai.sdk.foundationmodels.openai.OpenAiImageItem;
1616
import com.sap.ai.sdk.foundationmodels.openai.OpenAiMessage;
17-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoice;
18-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionNamedToolChoiceFunction;
1917
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionTool;
20-
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionToolChoiceOption;
2118
import com.sap.ai.sdk.foundationmodels.openai.generated.model.FunctionObject;
2219
import java.util.List;
2320
import java.util.Map;
@@ -102,18 +99,12 @@ public OpenAiChatCompletionResponse chatCompletionTools(final int months) {
10299

103100
final var tool = new ChatCompletionTool().type(FUNCTION).function(function);
104101

105-
final var toolChoice =
106-
ChatCompletionToolChoiceOption.create(
107-
new ChatCompletionNamedToolChoice()
108-
.type(ChatCompletionNamedToolChoice.TypeEnum.FUNCTION)
109-
.function(new ChatCompletionNamedToolChoiceFunction().name("fibonacci")));
110-
111102
final var request =
112103
new OpenAiChatCompletionRequest(
113104
"A pair of rabbits is placed in a field. Each month, every pair produces one new pair, starting from the second month. How many rabbits will there be after %s months?"
114105
.formatted(months))
115106
.withTools(List.of(tool))
116-
.withToolChoice(toolChoice);
107+
.withToolChoiceFunction("fibonacci");
117108

118109
return OpenAiClient.forModel(GPT_35_TURBO).chatCompletion(request);
119110
}

0 commit comments

Comments
 (0)