Skip to content

Commit 66976a9

Browse files
author
Milder Hernandez Cagua
committed
Avoid notify thread when auto-invoke is not active
1 parent 3c39538 commit 66976a9

File tree

5 files changed

+98
-22
lines changed

5 files changed

+98
-22
lines changed

agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatCompletionAgent.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
import com.microsoft.semantickernel.agents.AgentThread;
77
import com.microsoft.semantickernel.agents.KernelAgent;
88
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
9+
import com.microsoft.semantickernel.functionchoice.AutoFunctionChoiceBehavior;
910
import com.microsoft.semantickernel.orchestration.InvocationContext;
1011
import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
1112
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
12-
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
1313
import com.microsoft.semantickernel.semanticfunctions.KernelArguments;
1414
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
1515
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
@@ -76,22 +76,20 @@ public Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(
7676
// Invoke the agent with the chat history
7777
return internalInvokeAsync(
7878
history,
79+
agentThread,
7980
options
8081
)
81-
.flatMapMany(Flux::fromIterable)
82-
// notify on the new thread instance
83-
.concatMap(agentMessage -> this.notifyThreadOfNewMessageAsync(agentThread, agentMessage).thenReturn(agentMessage))
84-
.collectList()
8582
.map(chatMessageContents ->
8683
chatMessageContents.stream()
87-
.map(message -> new AgentResponseItem<ChatMessageContent<?>>(message, agentThread))
88-
.collect(Collectors.toList())
84+
.map(message -> new AgentResponseItem<ChatMessageContent<?>>(message, agentThread))
85+
.collect(Collectors.toList())
8986
);
9087
});
9188
}
9289

9390
private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
9491
ChatHistory history,
92+
AgentThread thread,
9593
@Nullable AgentInvokeOptions options
9694
) {
9795
if (options == null) {
@@ -144,6 +142,20 @@ private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
144142
// Add the chat history to the new chat
145143
chat.addAll(history);
146144

145+
// Retrieve the chat message contents asynchronously and notify the thread
146+
if (shouldNotifyFunctionCalls(agentInvocationContext)) {
147+
// Notify all messages including function calls
148+
return chatCompletionService.getChatMessageContentsAsync(chat, kernel, agentInvocationContext)
149+
.flatMapMany(Flux::fromIterable)
150+
.concatMap(message -> notifyThreadOfNewMessageAsync(thread, message).thenReturn(message))
151+
// Filter out function calls and their results
152+
.filter(message -> message.getContent() != null && message.getAuthorRole() != AuthorRole.TOOL)
153+
.collect(Collectors.toList());
154+
}
155+
156+
// Return chat completion messages without notifying the thread
157+
// We shouldn't add the function call content to the thread, since
158+
// we don't know if the user will execute the call. They should add it themselves.
147159
return chatCompletionService.getChatMessageContentsAsync(chat, kernel, agentInvocationContext);
148160
}
149161
);
@@ -153,6 +165,22 @@ private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
153165
}
154166
}
155167

168+
boolean shouldNotifyFunctionCalls(InvocationContext invocationContext) {
169+
if (invocationContext == null) {
170+
return false;
171+
}
172+
173+
if (invocationContext.getFunctionChoiceBehavior() != null && invocationContext.getFunctionChoiceBehavior() instanceof AutoFunctionChoiceBehavior) {
174+
return ((AutoFunctionChoiceBehavior) invocationContext.getFunctionChoiceBehavior()).isAutoInvoke();
175+
}
176+
177+
if (invocationContext.getToolCallBehavior() != null) {
178+
return invocationContext.getToolCallBehavior().isAutoInvokeAllowed();
179+
}
180+
181+
return false;
182+
}
183+
156184

157185
@Override
158186
public Mono<Void> notifyThreadOfNewMessageAsync(AgentThread thread, ChatMessageContent<?> message) {

samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/agents/CompletionAgent.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@
66
import com.azure.core.credential.KeyCredential;
77
import com.microsoft.semantickernel.Kernel;
88
import com.microsoft.semantickernel.agents.AgentInvokeOptions;
9+
import com.microsoft.semantickernel.agents.AgentThread;
910
import com.microsoft.semantickernel.agents.chatcompletion.ChatCompletionAgent;
1011
import com.microsoft.semantickernel.agents.chatcompletion.ChatHistoryAgentThread;
1112
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
1213
import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
14+
import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
1315
import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior;
1416
import com.microsoft.semantickernel.implementation.templateengine.tokenizer.DefaultPromptTemplate;
1517
import com.microsoft.semantickernel.orchestration.InvocationContext;
1618
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
19+
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
1720
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
1821
import com.microsoft.semantickernel.samples.plugins.github.GitHubModel;
1922
import com.microsoft.semantickernel.samples.plugins.github.GitHubPlugin;
@@ -105,7 +108,7 @@ public static void main(String[] args) {
105108
)
106109
).build();
107110

108-
ChatHistoryAgentThread agentThread = new ChatHistoryAgentThread();
111+
AgentThread agentThread = new ChatHistoryAgentThread();
109112
Scanner scanner = new Scanner(System.in);
110113

111114
while (true) {
@@ -118,22 +121,19 @@ public static void main(String[] args) {
118121

119122
var message = new ChatMessageContent<>(AuthorRole.USER, input);
120123
KernelArguments arguments = KernelArguments.builder()
121-
.withVariable("now", System.currentTimeMillis())
122-
.build();
124+
.withVariable("now", System.currentTimeMillis())
125+
.build();
123126

124127
var response = agent.invokeAsync(
125-
List.of(message),
126-
agentThread,
127-
AgentInvokeOptions.builder()
128-
.withKernel(kernel)
129-
.withKernelArguments(arguments)
130-
.build()
131-
).block();
132-
133-
var lastResponse = response.get(response.size() - 1);
128+
message,
129+
agentThread,
130+
AgentInvokeOptions.builder()
131+
.withKernelArguments(arguments)
132+
.build()
133+
).block().get(0);
134134

135-
System.out.println("> " + lastResponse.getMessage());
136-
agentThread = (ChatHistoryAgentThread) lastResponse.getThread();
135+
System.out.println("> " + response.getMessage());
136+
agentThread = response.getThread();
137137
}
138138
}
139139
}

semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/Agent.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,33 @@ public interface Agent {
4343
*/
4444
String getDescription();
4545

46+
/**
47+
* Invokes the agent with the given message.
48+
*
49+
* @param message The message to process
50+
* @return A Mono containing the agent response
51+
*/
52+
Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message);
53+
54+
/**
55+
* Invokes the agent with the given message and thread.
56+
*
57+
* @param message The message to process
58+
* @param thread The agent thread to use
59+
* @return A Mono containing the agent response
60+
*/
61+
Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message, AgentThread thread);
62+
63+
/**
64+
* Invokes the agent with the given message, thread, and options.
65+
*
66+
* @param message The message to process
67+
* @param thread The agent thread to use
68+
* @param options The options for invoking the agent
69+
* @return A Mono containing the agent response
70+
*/
71+
Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message, AgentThread thread, AgentInvokeOptions options);
72+
4673
/**
4774
* Invoke the agent with the given chat history.
4875
*

semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentInvokeOptions.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
*/
1414
public class AgentInvokeOptions {
1515

16+
@Nullable
1617
private final KernelArguments kernelArguments;
18+
@Nullable
1719
private final Kernel kernel;
20+
@Nullable
1821
private final String additionalInstructions;
22+
@Nullable
1923
private final InvocationContext invocationContext;
2024

2125
/**

semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/KernelAgent.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import reactor.core.publisher.Flux;
1212
import reactor.core.publisher.Mono;
1313

14+
import java.util.ArrayList;
1415
import java.util.HashMap;
1516
import java.util.List;
1617
import java.util.Map;
@@ -114,7 +115,6 @@ public PromptTemplate getTemplate() {
114115
return template;
115116
}
116117

117-
118118
/**
119119
* Merges the provided arguments with the current arguments.
120120
* Provided arguments will override the current arguments.
@@ -167,4 +167,21 @@ protected <T extends AgentThread> Mono<T> ensureThreadExistsWithMessagesAsync(Li
167167
.then(Mono.just((T) newThread));
168168
});
169169
}
170+
171+
@Override
172+
public Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message) {
173+
return invokeAsync(message, null);
174+
}
175+
176+
@Override
177+
public Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message, AgentThread thread) {
178+
return invokeAsync(message, thread, AgentInvokeOptions.builder().build());
179+
}
180+
181+
@Override
182+
public Mono<List<AgentResponseItem<ChatMessageContent<?>>>> invokeAsync(ChatMessageContent<?> message, AgentThread thread, AgentInvokeOptions options) {
183+
ArrayList<ChatMessageContent<?>> messages = new ArrayList<>();
184+
messages.add(message);
185+
return invokeAsync(messages, thread, options);
186+
}
170187
}

0 commit comments

Comments
 (0)