Skip to content

Commit afcfc21

Browse files
author
Milder Hernandez
authored
Merge pull request #320 from milderhc/function-call-content
Add FunctionCallContent
2 parents 5dd662f + 43cb503 commit afcfc21

File tree

9 files changed

+216
-102
lines changed

9 files changed

+216
-102
lines changed

aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.microsoft.semantickernel.aiservices.openai.OpenAiService;
3939
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.responseformat.ChatCompletionsJsonSchemaResponseFormat;
4040
import com.microsoft.semantickernel.aiservices.openai.implementation.OpenAIRequestSettings;
41+
import com.microsoft.semantickernel.contents.FunctionCallContent;
4142
import com.microsoft.semantickernel.contextvariables.ContextVariable;
4243
import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
4344
import com.microsoft.semantickernel.exceptions.AIException;
@@ -468,7 +469,6 @@ private Mono<ChatMessages> internalChatMessageContentsAsync(
468469
.doOnTerminate(span::close);
469470
})
470471
.flatMap(completions -> {
471-
472472
List<ChatResponseMessage> responseMessages = completions
473473
.getChoices()
474474
.stream()
@@ -488,6 +488,7 @@ private Mono<ChatMessages> internalChatMessageContentsAsync(
488488
completions);
489489
return Mono.just(messages.addChatMessage(chatMessageContents));
490490
}
491+
491492
// Or if there are no tool calls to be done
492493
ChatResponseMessage response = responseMessages.get(0);
493494
List<ChatCompletionsToolCall> toolCalls = response.getToolCalls();
@@ -633,21 +634,21 @@ private Mono<FunctionResult<String>> invokeFunctionTool(
633634
ContextVariableTypes contextVariableTypes) {
634635

635636
try {
636-
OpenAIFunctionToolCall openAIFunctionToolCall = extractOpenAIFunctionToolCall(toolCall);
637-
String pluginName = openAIFunctionToolCall.getPluginName();
637+
FunctionCallContent functionCallContent = extractFunctionCallContent(toolCall);
638+
String pluginName = functionCallContent.getPluginName();
638639
if (pluginName == null || pluginName.isEmpty()) {
639640
return Mono.error(
640641
new SKException("Plugin name is required for function tool call"));
641642
}
642643

643644
KernelFunction<?> function = kernel.getFunction(
644645
pluginName,
645-
openAIFunctionToolCall.getFunctionName());
646+
functionCallContent.getFunctionName());
646647

647648
PreToolCallEvent hookResult = executeHook(invocationContext, kernel,
648649
new PreToolCallEvent(
649-
openAIFunctionToolCall.getFunctionName(),
650-
openAIFunctionToolCall.getArguments(),
650+
functionCallContent.getFunctionName(),
651+
functionCallContent.getArguments(),
651652
function,
652653
contextVariableTypes));
653654

@@ -686,7 +687,7 @@ private static <T extends KernelHookEvent> T executeHook(
686687
}
687688

688689
@SuppressWarnings("StringSplitter")
689-
private OpenAIFunctionToolCall extractOpenAIFunctionToolCall(
690+
private FunctionCallContent extractFunctionCallContent(
690691
ChatCompletionsFunctionToolCall toolCall)
691692
throws JsonProcessingException {
692693

@@ -712,10 +713,10 @@ private OpenAIFunctionToolCall extractOpenAIFunctionToolCall(
712713
}
713714
});
714715

715-
return new OpenAIFunctionToolCall(
716-
toolCall.getId(),
717-
pluginName,
716+
return new FunctionCallContent(
718717
fnName,
718+
pluginName,
719+
toolCall.getId(),
719720
arguments);
720721
}
721722

@@ -744,7 +745,7 @@ private List<OpenAIChatMessageContent<?>> getChatMessageContentsAsync(
744745
null,
745746
null,
746747
completionMetadata,
747-
formOpenAiToolCalls(response));
748+
formFunctionCallContents(response));
748749
} catch (SKCheckedException e) {
749750
LOGGER.warn("Failed to form chat message content", e);
750751
return null;
@@ -784,7 +785,7 @@ private List<ChatMessageContent<?>> toOpenAIChatMessageContent(
784785
null);
785786
} else if (message instanceof ChatRequestAssistantMessage) {
786787
try {
787-
List<OpenAIFunctionToolCall> calls = getToolCalls(
788+
List<FunctionCallContent> calls = getFunctionCallContents(
788789
((ChatRequestAssistantMessage) message).getToolCalls());
789790
return new OpenAIChatMessageContent<>(
790791
AuthorRole.ASSISTANT,
@@ -823,7 +824,7 @@ private List<ChatMessageContent<?>> toOpenAIChatMessageContent(
823824
}
824825

825826
@Nullable
826-
private List<OpenAIFunctionToolCall> getToolCalls(
827+
private List<FunctionCallContent> getFunctionCallContents(
827828
@Nullable List<ChatCompletionsToolCall> toolCalls) throws SKCheckedException {
828829
if (toolCalls == null || toolCalls.isEmpty()) {
829830
return null;
@@ -835,7 +836,7 @@ private List<OpenAIFunctionToolCall> getToolCalls(
835836
.map(call -> {
836837
if (call instanceof ChatCompletionsFunctionToolCall) {
837838
try {
838-
return extractOpenAIFunctionToolCall(
839+
return extractFunctionCallContent(
839840
(ChatCompletionsFunctionToolCall) call);
840841
} catch (JsonProcessingException e) {
841842
throw SKException.build("Failed to parse tool arguments", e);
@@ -852,7 +853,7 @@ private List<OpenAIFunctionToolCall> getToolCalls(
852853
}
853854

854855
@Nullable
855-
private List<OpenAIFunctionToolCall> formOpenAiToolCalls(
856+
private List<FunctionCallContent> formFunctionCallContents(
856857
ChatResponseMessage response) throws SKCheckedException {
857858
if (response.getToolCalls() == null || response.getToolCalls().isEmpty()) {
858859
return null;
@@ -864,7 +865,7 @@ private List<OpenAIFunctionToolCall> formOpenAiToolCalls(
864865
.map(call -> {
865866
if (call instanceof ChatCompletionsFunctionToolCall) {
866867
try {
867-
return extractOpenAIFunctionToolCall(
868+
return extractFunctionCallContent(
868869
(ChatCompletionsFunctionToolCall) call);
869870
} catch (JsonProcessingException e) {
870871
throw SKException.build("Failed to parse tool arguments", e);
@@ -1251,10 +1252,7 @@ private static ChatRequestAssistantMessage formAssistantMessage(
12511252
// TODO: handle tools other than function calls
12521253
ChatRequestAssistantMessage asstMessage = new ChatRequestAssistantMessage(content);
12531254

1254-
List<OpenAIFunctionToolCall> toolCalls = null;
1255-
if (message instanceof OpenAIChatMessageContent) {
1256-
toolCalls = ((OpenAIChatMessageContent<?>) message).getToolCall();
1257-
}
1255+
List<FunctionCallContent> toolCalls = FunctionCallContent.getFunctionCalls(message);
12581256

12591257
if (toolCalls != null) {
12601258
asstMessage.setToolCalls(

aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatMessageContent.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
33

4+
import com.microsoft.semantickernel.contents.FunctionCallContent;
45
import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
6+
import com.microsoft.semantickernel.services.KernelContent;
57
import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
68
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
79
import java.nio.charset.Charset;
810
import java.util.Collections;
911
import java.util.List;
12+
import java.util.stream.Collectors;
1013
import javax.annotation.Nullable;
1114

1215
/**
@@ -16,6 +19,7 @@
1619
*/
1720
public class OpenAIChatMessageContent<T> extends ChatMessageContent<T> {
1821

22+
@Deprecated
1923
@Nullable
2024
private final List<OpenAIFunctionToolCall> toolCall;
2125

@@ -28,7 +32,7 @@ public class OpenAIChatMessageContent<T> extends ChatMessageContent<T> {
2832
* @param innerContent The inner content.
2933
* @param encoding The encoding.
3034
* @param metadata The metadata.
31-
* @param toolCall The tool call.
35+
* @param functionCalls The tool call.
3236
*/
3337
public OpenAIChatMessageContent(
3438
AuthorRole authorRole,
@@ -37,21 +41,36 @@ public OpenAIChatMessageContent(
3741
@Nullable T innerContent,
3842
@Nullable Charset encoding,
3943
@Nullable FunctionResultMetadata<?> metadata,
40-
@Nullable List<OpenAIFunctionToolCall> toolCall) {
41-
super(authorRole, content, modelId, innerContent, encoding, metadata);
44+
@Nullable List<? extends FunctionCallContent> functionCalls) {
45+
super(authorRole, content, (List<? extends KernelContent<T>>) functionCalls, modelId,
46+
innerContent, encoding, metadata);
4247

43-
if (toolCall == null) {
48+
if (functionCalls == null) {
4449
this.toolCall = null;
4550
} else {
46-
this.toolCall = Collections.unmodifiableList(toolCall);
51+
// Keep OpenAIFunctionToolCall list for legacy
52+
this.toolCall = Collections.unmodifiableList(functionCalls.stream().map(t -> {
53+
if (t instanceof OpenAIFunctionToolCall) {
54+
return (OpenAIFunctionToolCall) t;
55+
} else {
56+
return new OpenAIFunctionToolCall(
57+
t.getId(),
58+
t.getPluginName(),
59+
t.getFunctionName(),
60+
t.getArguments());
61+
}
62+
}).collect(Collectors.toList()));
4763
}
4864
}
4965

5066
/**
5167
* Gets any tool calls requested.
5268
*
5369
* @return The tool call.
70+
*
71+
* @deprecated Use {@link FunctionCallContent#getFunctionCalls(ChatMessageContent)} instead.
5472
*/
73+
@Deprecated
5574
@Nullable
5675
public List<OpenAIFunctionToolCall> getToolCall() {
5776
return toolCall;
Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
33

4+
import com.microsoft.semantickernel.contents.FunctionCallContent;
45
import com.microsoft.semantickernel.semanticfunctions.KernelArguments;
56
import javax.annotation.Nullable;
67

78
/**
89
* Represents a call to a function in the OpenAI tool.
10+
*
11+
* @deprecated Use {@link FunctionCallContent} instead.
912
*/
10-
public class OpenAIFunctionToolCall {
11-
12-
/// <summary>Gets the ID of the tool call.</summary>
13-
@Nullable
14-
private final String id;
15-
16-
/// <summary>Gets the name of the plugin with which this function is associated, if any.</summary>
17-
18-
@Nullable
19-
private final String pluginName;
20-
21-
/// <summary>Gets the name of the function.</summary>
22-
private final String functionName;
23-
24-
/// <summary>Gets a name/value collection of the arguments to the function, if any.</summary>
25-
@Nullable
26-
private final KernelArguments arguments;
13+
@Deprecated
14+
public class OpenAIFunctionToolCall extends FunctionCallContent {
2715

2816
/**
2917
* Creates a new instance of the {@link OpenAIFunctionToolCall} class.
@@ -38,55 +26,6 @@ public OpenAIFunctionToolCall(
3826
@Nullable String pluginName,
3927
String functionName,
4028
@Nullable KernelArguments arguments) {
41-
this.id = id;
42-
this.pluginName = pluginName;
43-
this.functionName = functionName;
44-
if (arguments == null) {
45-
this.arguments = null;
46-
} else {
47-
this.arguments = arguments.copy();
48-
}
49-
}
50-
51-
/**
52-
* Gets the ID of the tool call.
53-
*
54-
* @return The ID of the tool call.
55-
*/
56-
@Nullable
57-
public String getId() {
58-
return id;
59-
}
60-
61-
/**
62-
* Gets the name of the plugin with which this function is associated, if any.
63-
*
64-
* @return The name of the plugin with which this function is associated, if any.
65-
*/
66-
@Nullable
67-
public String getPluginName() {
68-
return pluginName;
69-
}
70-
71-
/**
72-
* Gets the name of the function.
73-
*
74-
* @return The name of the function.
75-
*/
76-
public String getFunctionName() {
77-
return functionName;
78-
}
79-
80-
/**
81-
* Gets a name/value collection of the arguments to the function, if any.
82-
*
83-
* @return A name/value collection of the arguments to the function, if any.
84-
*/
85-
@Nullable
86-
public KernelArguments getArguments() {
87-
if (arguments == null) {
88-
return null;
89-
}
90-
return arguments.copy();
29+
super(functionName, pluginName, id, arguments);
9130
}
9231
}

0 commit comments

Comments
 (0)