6
6
import com .microsoft .semantickernel .agents .AgentThread ;
7
7
import com .microsoft .semantickernel .agents .KernelAgent ;
8
8
import com .microsoft .semantickernel .builders .SemanticKernelBuilder ;
9
- import com .microsoft .semantickernel .contextvariables .ContextVariable ;
10
9
import com .microsoft .semantickernel .orchestration .InvocationContext ;
11
10
import com .microsoft .semantickernel .orchestration .InvocationReturnMode ;
12
11
import com .microsoft .semantickernel .orchestration .PromptExecutionSettings ;
23
22
import reactor .core .publisher .Flux ;
24
23
import reactor .core .publisher .Mono ;
25
24
25
+ import javax .annotation .Nullable ;
26
26
import java .util .List ;
27
- import java .util .Map ;
28
- import java .util .function .Function ;
29
27
import java .util .stream .Collectors ;
30
28
31
29
public class ChatCompletionAgent extends KernelAgent {
32
30
33
- ChatCompletionAgent (
31
+ private ChatCompletionAgent (
34
32
String id ,
35
33
String name ,
36
34
String description ,
@@ -61,43 +59,49 @@ public class ChatCompletionAgent extends KernelAgent {
61
59
* @return A Mono containing the agent response
62
60
*/
63
61
@ Override
64
- public Mono <List <AgentResponseItem <ChatMessageContent <?>>>> invokeAsync (List <ChatMessageContent <?>> messages , AgentThread thread , AgentInvokeOptions options ) {
65
-
66
- Mono <ChatHistory > chatHistoryFromThread = this .<ChatHistoryAgentThread >ensureThreadExistsAsync (messages , thread , ChatHistoryAgentThread ::new )
67
- .cast (ChatHistoryAgentThread .class )
68
- .map (ChatHistoryAgentThread ::getChatHistory )
69
- .flatMap (threadChatHistory -> {
70
- return Mono .just (new ChatHistory (threadChatHistory .getMessages ()));
71
- });
72
-
73
-
74
- Mono <List <ChatMessageContent <?>>> updatedChatHistory = chatHistoryFromThread .flatMap (
75
- chatHistory -> internalInvokeAsync (
76
- this .getName (),
77
- chatHistory ,
78
- options
79
- )
80
- );
62
+ public Mono <List <AgentResponseItem <ChatMessageContent <?>>>> invokeAsync (
63
+ List <ChatMessageContent <?>> messages ,
64
+ AgentThread thread ,
65
+ @ Nullable AgentInvokeOptions options
66
+ ) {
67
+ return ensureThreadExistsWithMessagesAsync (messages , thread , ChatHistoryAgentThread ::new )
68
+ .cast (ChatHistoryAgentThread .class )
69
+ .flatMap (agentThread -> {
70
+ // Extract the chat history from the thread
71
+ ChatHistory history = new ChatHistory (
72
+ agentThread .getChatHistory ().getMessages ()
73
+ );
81
74
82
- return updatedChatHistory .flatMap (chatMessageContents -> {
83
- return Flux .fromIterable (chatMessageContents )
84
- .concatMap (chatMessageContent -> this .notifyThreadOfNewMessageAsync (thread , chatMessageContent ))
85
- .then (Mono .just (chatMessageContents )); // return the original list
86
- }).flatMap (chatMessageContents -> {
87
- return Mono .just (chatMessageContents .stream ()
88
- .map (chatMessageContent -> {
89
- return new AgentResponseItem <ChatMessageContent <?>>(
90
- chatMessageContent ,
91
- thread );
92
- }).collect (Collectors .toList ()));
93
- });
75
+ // Invoke the agent with the chat history
76
+ return internalInvokeAsync (
77
+ history ,
78
+ options
79
+ )
80
+ .flatMapMany (Flux ::fromIterable )
81
+ // notify on the new thread instance
82
+ .concatMap (agentMessage -> {
83
+ // Set the author name for the message
84
+ agentMessage .setAuthorName (this .name );
85
+
86
+ return this .notifyThreadOfNewMessageAsync (agentThread , agentMessage ).thenReturn (agentMessage );
87
+ })
88
+ .collectList ()
89
+ .map (chatMessageContents ->
90
+ chatMessageContents .stream ()
91
+ .map (message -> new AgentResponseItem <ChatMessageContent <?>>(message , agentThread ))
92
+ .collect (Collectors .toList ())
93
+ );
94
+ });
94
95
}
95
96
96
97
private Mono <List <ChatMessageContent <?>>> internalInvokeAsync (
97
- String agentName ,
98
98
ChatHistory history ,
99
- AgentInvokeOptions options
99
+ @ Nullable AgentInvokeOptions options
100
100
) {
101
+ if (options == null ) {
102
+ options = new AgentInvokeOptions ();
103
+ }
104
+
101
105
final Kernel kernel = options .getKernel () != null ? options .getKernel () : this .kernel ;
102
106
final KernelArguments arguments = mergeArguments (options .getKernelArguments ());
103
107
final String additionalInstructions = options .getAdditionalInstructions ();
@@ -112,13 +116,13 @@ private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
112
116
113
117
ToolCallBehavior toolCallBehavior = invocationContext != null
114
118
? invocationContext .getToolCallBehavior ()
115
- : ToolCallBehavior .allowAllKernelFunctions (false );
119
+ : ToolCallBehavior .allowAllKernelFunctions (true );
116
120
117
121
// Build base invocation context
118
122
InvocationContext .Builder builder = InvocationContext .builder ()
119
123
.withPromptExecutionSettings (executionSettings )
120
124
.withToolCallBehavior (toolCallBehavior )
121
- .withReturnMode (InvocationReturnMode .FULL_HISTORY );
125
+ .withReturnMode (InvocationReturnMode .NEW_MESSAGES_ONLY );
122
126
123
127
if (invocationContext != null ) {
124
128
builder = builder
@@ -129,7 +133,7 @@ private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
129
133
130
134
InvocationContext agentInvocationContext = builder .build ();
131
135
132
- return formatInstructionsAsync (kernel , arguments , agentInvocationContext ).flatMap (
136
+ return renderInstructionsAsync (kernel , arguments , agentInvocationContext ).flatMap (
133
137
instructions -> {
134
138
// Create a new chat history with the instructions
135
139
ChatHistory chat = new ChatHistory (
@@ -144,24 +148,26 @@ private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
144
148
));
145
149
}
146
150
151
+ // Add the chat history to the new chat
147
152
chat .addAll (history );
148
- int previousHistorySize = chat .getMessages ().size ();
149
-
150
- return chatCompletionService .getChatMessageContentsAsync (chat , kernel , agentInvocationContext )
151
- .map (chatMessageContents -> {
152
- return chatMessageContents .subList (
153
- previousHistorySize ,
154
- chatMessageContents .size ());
155
- });
153
+
154
+ return chatCompletionService .getChatMessageContentsAsync (chat , kernel , agentInvocationContext );
156
155
}
157
156
);
158
157
159
-
160
158
} catch (ServiceNotFoundException e ) {
161
159
throw new RuntimeException (e );
162
160
}
163
161
}
164
162
163
+
164
+ @ Override
165
+ public Mono <Void > notifyThreadOfNewMessageAsync (AgentThread thread , ChatMessageContent <?> message ) {
166
+ return Mono .defer (() -> {
167
+ return thread .onNewMessageAsync (message );
168
+ });
169
+ }
170
+
165
171
/**
166
172
* Builder for creating instances of ChatCompletionAgent.
167
173
*/
@@ -174,71 +180,123 @@ public static class Builder implements SemanticKernelBuilder<ChatCompletionAgent
174
180
private String name ;
175
181
private String description ;
176
182
private Kernel kernel ;
177
- private KernelArguments KernelArguments ;
183
+ private KernelArguments kernelArguments ;
178
184
private InvocationContext invocationContext ;
179
185
private String instructions ;
180
186
private PromptTemplate template ;
181
187
188
+ /**
189
+ * Set the ID of the agent.
190
+ *
191
+ * @param id The ID of the agent.
192
+ */
182
193
public Builder withId (String id ) {
183
194
this .id = id ;
184
195
return this ;
185
196
}
186
197
198
+ /**
199
+ * Set the name of the agent.
200
+ *
201
+ * @param name The name of the agent.
202
+ */
187
203
public Builder withName (String name ) {
188
204
this .name = name ;
189
205
return this ;
190
206
}
191
207
208
+ /**
209
+ * Set the description of the agent.
210
+ *
211
+ * @param description The description of the agent.
212
+ */
192
213
public Builder withDescription (String description ) {
193
214
this .description = description ;
194
215
return this ;
195
216
}
196
217
218
+ /**
219
+ * Set the kernel to use for the agent.
220
+ *
221
+ * @param kernel The kernel to use.
222
+ */
197
223
public Builder withKernel (Kernel kernel ) {
198
224
this .kernel = kernel ;
199
225
return this ;
200
226
}
201
227
228
+ /**
229
+ * Set the kernel arguments to use for the agent.
230
+ *
231
+ * @param KernelArguments The kernel arguments to use.
232
+ */
202
233
public Builder withKernelArguments (KernelArguments KernelArguments ) {
203
- this .KernelArguments = KernelArguments ;
234
+ this .kernelArguments = KernelArguments ;
204
235
return this ;
205
236
}
206
237
238
+ /**
239
+ * Set the instructions for the agent.
240
+ *
241
+ * @param instructions The instructions for the agent.
242
+ */
207
243
public Builder withInstructions (String instructions ) {
208
244
this .instructions = instructions ;
209
245
return this ;
210
246
}
211
247
248
+ /**
249
+ * Set the invocation context for the agent.
250
+ *
251
+ * @param invocationContext The invocation context to use.
252
+ */
212
253
public Builder withInvocationContext (InvocationContext invocationContext ) {
213
254
this .invocationContext = invocationContext ;
214
255
return this ;
215
256
}
216
257
258
+ /**
259
+ * Set the template for the agent.
260
+ *
261
+ * @param template The template to use.
262
+ */
217
263
public Builder withTemplate (PromptTemplate template ) {
218
264
this .template = template ;
219
265
return this ;
220
266
}
221
267
268
+ /**
269
+ * Build the ChatCompletionAgent instance.
270
+ *
271
+ * @return The ChatCompletionAgent instance.
272
+ */
222
273
public ChatCompletionAgent build () {
223
274
return new ChatCompletionAgent (
224
275
id ,
225
276
name ,
226
277
description ,
227
278
kernel ,
228
- KernelArguments ,
279
+ kernelArguments ,
229
280
invocationContext ,
230
281
instructions ,
231
282
template
232
283
);
233
284
}
234
285
286
+ /**
287
+ * Build the ChatCompletionAgent instance with the given prompt template config and factory.
288
+ *
289
+ * @param promptTemplateConfig The prompt template config to use.
290
+ * @param promptTemplateFactory The prompt template factory to use.
291
+ * @return The ChatCompletionAgent instance.
292
+ */
235
293
public ChatCompletionAgent build (PromptTemplateConfig promptTemplateConfig , PromptTemplateFactory promptTemplateFactory ) {
236
294
return new ChatCompletionAgent (
237
295
id ,
238
296
name ,
239
297
description ,
240
298
kernel ,
241
- KernelArguments ,
299
+ kernelArguments ,
242
300
invocationContext ,
243
301
promptTemplateConfig .getTemplate (),
244
302
promptTemplateFactory .tryCreate (promptTemplateConfig )
0 commit comments