Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1662ae7
Tool call full e2e unverified
rpanackal Mar 14, 2025
9ef8e6f
CI
rpanackal Mar 14, 2025
ef9bdc4
Reuse tool
rpanackal Mar 17, 2025
fd6acdc
Remove unnecessary line inserts
rpanackal Mar 17, 2025
a6a209b
Create schema with jackson
rpanackal Mar 24, 2025
9ad7225
Merge remote-tracking branch 'refs/remotes/origin/main' into test/ope…
rpanackal Mar 25, 2025
9a5aec3
First version
rpanackal Mar 26, 2025
275eee5
Formatting
bot-sdk-js Mar 26, 2025
ad9ef65
Testing and javadocs
rpanackal Mar 27, 2025
e70eb29
improve test clarity
rpanackal Mar 27, 2025
a13b183
Merge remote-tracking branch 'refs/remotes/origin/main' into test/ope…
rpanackal Mar 27, 2025
03a14a4
Merge branch 'refs/heads/test/openai/tool-call-execute' into feat/ope…
rpanackal Mar 27, 2025
bf2ce11
Remove strict tool invocation config
rpanackal Mar 27, 2025
f74a0a7
Merge branch 'refs/heads/test/openai/tool-call-execute' into feat/ope…
rpanackal Mar 27, 2025
698eab8
Fix maven dependency scope issue
rpanackal Mar 28, 2025
f694f40
Fix maven dependency scope issue + 1
rpanackal Mar 28, 2025
4e388e2
Merge branch 'refs/heads/test/openai/tool-call-execute' into feat/ope…
rpanackal Mar 31, 2025
78aa10e
Refactor. toolCalls get dedicated field in assistant message
rpanackal Mar 31, 2025
49b8be4
minor fixes
rpanackal Mar 31, 2025
78c2909
Merge branch 'refs/heads/test/openai/tool-call-execute' into feat/ope…
rpanackal Mar 31, 2025
05d6218
minor fixes
rpanackal Mar 31, 2025
23a247a
Test message list in request externally unmodifiable
rpanackal Mar 31, 2025
4642de0
Test message list in request externally unmodifiable
rpanackal Mar 31, 2025
96647f5
minor javadoc update
rpanackal Mar 31, 2025
f8ee9d4
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/ope…
rpanackal Mar 31, 2025
bf7d86a
Remove sample app changes
rpanackal Mar 31, 2025
26b7dae
@beta annotation
rpanackal Mar 31, 2025
f616263
Update foundation-models/openai/src/main/java/com/sap/ai/sdk/foundati…
rpanackal Apr 1, 2025
cd11f37
Apply suggestions from code review
rpanackal Apr 1, 2025
b95b960
update getMessage method impl readability
rpanackal Apr 1, 2025
9062e3a
Move test to generated client test class
rpanackal Apr 1, 2025
69b49ea
Extend tests
rpanackal Apr 1, 2025
d26ecbf
Reduce test
rpanackal Apr 1, 2025
40f1e22
Refactor test
rpanackal Apr 1, 2025
bd61ce2
Formatting
bot-sdk-js Apr 1, 2025
d440c28
import statement
rpanackal Apr 1, 2025
c6969f4
Merge branch 'refs/heads/main' into feat/openai/tool-call-execute
rpanackal Apr 1, 2025
a36bef0
Merge branch 'feat/openai/tool-call-execute' of https://github.com/SA…
rpanackal Apr 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,25 @@ public String getContent() {
*/
@Nonnull
public OpenAiAssistantMessage getMessage() {
final var toolCalls = getChoice().getMessage().getToolCalls();

if (toolCalls == null) {
return OpenAiMessage.assistant(getContent());
}

final List<OpenAiContentItem> contentItems =
getContent().isEmpty() ? List.of() : List.of(new OpenAiTextItem(getContent()));

final List toolCalls =
getChoice().getMessage().getToolCalls().stream()
.map(
final var openAiToolCalls =
toolCalls.stream()
.<OpenAiToolCall>map(
toolCall ->
new OpenAiFunctionCall(
toolCall.getId(),
toolCall.getFunction().getName(),
toolCall.getFunction().getArguments()))
.map(OpenAiToolCall.class::cast)
.toList();

return new OpenAiAssistantMessage(new OpenAiMessageContent(contentItems), toolCalls);
return new OpenAiAssistantMessage(new OpenAiMessageContent(contentItems), openAiToolCalls);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,29 +239,6 @@ void throwOnSystemMessageWithImage() {
"Unknown content type for class com.sap.ai.sdk.foundationmodels.openai.OpenAiImageItem messages.");
}

@Test
void assistantMessageGetToolCalls() {
var message =
new OpenAiAssistantMessage(
new OpenAiMessageContent(List.of(new OpenAiTextItem("text"))),
List.of(
new OpenAiFunctionCall("id1", "name1", "arguments1"),
new OpenAiFunctionCall("id2", "name2", "arguments2")));

var toolCalls = message.toolCalls();
assertThat(toolCalls).hasSize(2);

var functionCallItem1 = (OpenAiFunctionCall) toolCalls.get(0);
assertThat(functionCallItem1.getId()).isEqualTo("id1");
assertThat(functionCallItem1.getName()).isEqualTo("name1");
assertThat(functionCallItem1.getArguments()).isEqualTo("arguments1");

var functionCallItem2 = (OpenAiFunctionCall) toolCalls.get(1);
assertThat(functionCallItem2.getId()).isEqualTo("id2");
assertThat(functionCallItem2.getName()).isEqualTo("name2");
assertThat(functionCallItem2.getArguments()).isEqualTo("arguments2");
}

@ParameterizedTest
@MethodSource("provideValidTextMessageByRole")
void testCreateChatCompletionRequestMessage(OpenAiMessage message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,4 +583,45 @@ void chatCompletionTool() {
}
""")));
}

@Test
void chatCompletionResponseGetMessage() {
stubForChatCompletion();

final var response = client.chatCompletion(new OpenAiChatCompletionRequest("Some text"));
final var simpleMessage = response.getMessage();

assertThat(simpleMessage).isNotNull();
assertThat(simpleMessage.toolCalls()).isEmpty();
assertThat(simpleMessage.content().items()).hasSize(1);
assertThat(simpleMessage.content().items().get(0)).isInstanceOf(OpenAiTextItem.class);
assertThat(((OpenAiTextItem) simpleMessage.content().items().get(0)).text())
.isEqualTo(
"I'm an AI and cannot answer that question as beauty is subjective and varies from person to person.");

stubForChatCompletionTool();

final var responseWithToolCall =
client.chatCompletion(new OpenAiChatCompletionRequest("Some tool request"));
var messageWithToolCall = responseWithToolCall.getMessage();

assertThat(messageWithToolCall).isNotNull();
assertThat(messageWithToolCall.content().items()).hasSize(0);
OpenAiFunctionCall functionCallItem =
(OpenAiFunctionCall) messageWithToolCall.toolCalls().get(0);
assertThat(functionCallItem.getId()).isEqualTo("call_CUYGJf2j7FRWJMHT3PN3aGxK");
assertThat(functionCallItem.getName()).isEqualTo("fibonacci");
assertThat(functionCallItem.getArguments()).isEqualTo("{\"N\":12}");

// case: both content and tool calls are present
responseWithToolCall.getChoice().getMessage().content("Some content");
var messageWithToolCallsAndContent = responseWithToolCall.getMessage();

assertThat(messageWithToolCallsAndContent).isNotNull();
assertThat(messageWithToolCallsAndContent.content().items()).hasSize(1);
assertThat(messageWithToolCallsAndContent.content().items().get(0))
.isInstanceOf(OpenAiTextItem.class);
assertThat(messageWithToolCallsAndContent.toolCalls().get(0))
.isInstanceOf(OpenAiFunctionCall.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -480,40 +480,4 @@ void chatCompletionTool() {
}
""")));
}

@Test
void chatCompletionResponseGetMessage() {
stubForChatCompletion();

final var response = client.chatCompletion(new OpenAiChatCompletionRequest("Some text"));
final var simpleMessage = response.getMessage();

assertThat(simpleMessage).isNotNull();
assertThat(simpleMessage.toolCalls()).isEmpty();

stubForChatCompletionTool();

final var responseWithToolCall =
client.chatCompletion(new OpenAiChatCompletionRequest("Some tool request"));
var messageWithToolCall = responseWithToolCall.getMessage();

assertThat(messageWithToolCall).isNotNull();
assertThat(messageWithToolCall.content().items()).hasSize(0);
OpenAiFunctionCall functionCallItem =
(OpenAiFunctionCall) messageWithToolCall.toolCalls().get(0);
assertThat(functionCallItem.getId()).isEqualTo("call_CUYGJf2j7FRWJMHT3PN3aGxK");
assertThat(functionCallItem.getName()).isEqualTo("fibonacci");
assertThat(functionCallItem.getArguments()).isEqualTo("{\"N\":12}");

// case: both content and tool calls are present
responseWithToolCall.getChoice().getMessage().content("Some content");
var messageWithToolCallsAndContent = responseWithToolCall.getMessage();

assertThat(messageWithToolCallsAndContent).isNotNull();
assertThat(messageWithToolCallsAndContent.content().items()).hasSize(1);
assertThat(messageWithToolCallsAndContent.content().items().get(0))
.isInstanceOf(OpenAiTextItem.class);
assertThat(messageWithToolCallsAndContent.toolCalls().get(0))
.isInstanceOf(OpenAiFunctionCall.class);
}
}