Skip to content

Commit ed651d6

Browse files
author
Milder Hernandez Cagua
committed
Add draft changes for agents
1 parent 69af29b commit ed651d6

File tree

17 files changed

+1314
-0
lines changed

17 files changed

+1314
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.microsoft.semantic-kernel</groupId>
8+
<artifactId>semantickernel-parent</artifactId>
9+
<version>1.4.4-SNAPSHOT</version>
10+
<relativePath>../../pom.xml</relativePath>
11+
</parent>
12+
13+
<artifactId>semantickernel-agents-core</artifactId>
14+
15+
<name>Semantic Kernel Chat Completion Agent</name>
16+
<description>Chat Completion Agent for Semantic Kernel</description>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>com.microsoft.semantic-kernel</groupId>
21+
<artifactId>semantickernel-api</artifactId>
22+
</dependency>
23+
</dependencies>
24+
25+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
package com.microsoft.semantickernel.agents.chatcompletion;
2+
3+
import com.microsoft.semantickernel.Kernel;
4+
import com.microsoft.semantickernel.agents.AgentInvokeOptions;
5+
import com.microsoft.semantickernel.agents.AgentResponseItem;
6+
import com.microsoft.semantickernel.agents.AgentThread;
7+
import com.microsoft.semantickernel.agents.KernelAgent;
8+
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
9+
import com.microsoft.semantickernel.contextvariables.ContextVariable;
10+
import com.microsoft.semantickernel.orchestration.InvocationContext;
11+
import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
12+
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
13+
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
14+
import com.microsoft.semantickernel.semanticfunctions.KernelArguments;
15+
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
16+
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
17+
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateFactory;
18+
import com.microsoft.semantickernel.services.ServiceNotFoundException;
19+
import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
20+
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
21+
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
22+
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
23+
import reactor.core.publisher.Flux;
24+
import reactor.core.publisher.Mono;
25+
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.function.Function;
29+
import java.util.stream.Collectors;
30+
31+
public class ChatCompletionAgent extends KernelAgent {
32+
33+
ChatCompletionAgent(
34+
String id,
35+
String name,
36+
String description,
37+
Kernel kernel,
38+
KernelArguments kernelArguments,
39+
InvocationContext context,
40+
String instructions,
41+
PromptTemplate template
42+
) {
43+
super(
44+
id,
45+
name,
46+
description,
47+
kernel,
48+
kernelArguments,
49+
context,
50+
instructions,
51+
template
52+
);
53+
}
54+
55+
/**
56+
* Invoke the agent with the given chat history.
57+
*
58+
* @param messages The chat history to process
59+
* @param thread The agent thread to use
60+
* @param options The options for invoking the agent
61+
* @return A Mono containing the agent response
62+
*/
63+
@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+
);
81+
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+
});
94+
}
95+
96+
private Mono<List<ChatMessageContent<?>>> internalInvokeAsync(
97+
String agentName,
98+
ChatHistory history,
99+
AgentInvokeOptions options
100+
) {
101+
final Kernel kernel = options.getKernel() != null ? options.getKernel() : this.kernel;
102+
final KernelArguments arguments = mergeArguments(options.getKernelArguments());
103+
final String additionalInstructions = options.getAdditionalInstructions();
104+
final InvocationContext invocationContext = options.getInvocationContext() != null ? options.getInvocationContext() : this.invocationContext;
105+
106+
try {
107+
ChatCompletionService chatCompletionService = kernel.getService(ChatCompletionService.class, arguments);
108+
109+
PromptExecutionSettings executionSettings = invocationContext.getPromptExecutionSettings() != null
110+
? invocationContext.getPromptExecutionSettings()
111+
: kernelArguments.getExecutionSettings().get(chatCompletionService.getServiceId());
112+
113+
final InvocationContext newMessagesContext = InvocationContext.builder()
114+
.withPromptExecutionSettings(executionSettings)
115+
.withToolCallBehavior(invocationContext.getToolCallBehavior())
116+
.withTelemetry(invocationContext.getTelemetry())
117+
.withContextVariableConverter(invocationContext.getContextVariableTypes())
118+
.withKernelHooks(invocationContext.getKernelHooks())
119+
.withReturnMode(InvocationReturnMode.FULL_HISTORY)
120+
.build();
121+
122+
return formatInstructionsAsync(kernel, arguments, newMessagesContext).flatMap(
123+
instructions -> {
124+
// Create a new chat history with the instructions
125+
ChatHistory chat = new ChatHistory(
126+
instructions
127+
);
128+
129+
// Add agent additional instructions
130+
if (additionalInstructions != null) {
131+
chat.addMessage(new ChatMessageContent<>(
132+
AuthorRole.SYSTEM,
133+
additionalInstructions
134+
));
135+
}
136+
137+
chat.addAll(history);
138+
int previousHistorySize = chat.getMessages().size();
139+
140+
return chatCompletionService.getChatMessageContentsAsync(chat, kernel, newMessagesContext)
141+
.map(chatMessageContents -> {
142+
return chatMessageContents.subList(
143+
previousHistorySize,
144+
chatMessageContents.size());
145+
});
146+
}
147+
);
148+
149+
150+
} catch (ServiceNotFoundException e) {
151+
throw new RuntimeException(e);
152+
}
153+
}
154+
155+
/**
156+
* Builder for creating instances of ChatCompletionAgent.
157+
*/
158+
public static Builder builder() {
159+
return new Builder();
160+
}
161+
162+
public static class Builder implements SemanticKernelBuilder<ChatCompletionAgent> {
163+
private String id;
164+
private String name;
165+
private String description;
166+
private Kernel kernel;
167+
private KernelArguments KernelArguments;
168+
private InvocationContext invocationContext;
169+
private String instructions;
170+
private PromptTemplate template;
171+
172+
public Builder withId(String id) {
173+
this.id = id;
174+
return this;
175+
}
176+
177+
public Builder withName(String name) {
178+
this.name = name;
179+
return this;
180+
}
181+
182+
public Builder withDescription(String description) {
183+
this.description = description;
184+
return this;
185+
}
186+
187+
public Builder withKernel(Kernel kernel) {
188+
this.kernel = kernel;
189+
return this;
190+
}
191+
192+
public Builder withKernelArguments(KernelArguments KernelArguments) {
193+
this.KernelArguments = KernelArguments;
194+
return this;
195+
}
196+
197+
public Builder withInstructions(String instructions) {
198+
this.instructions = instructions;
199+
return this;
200+
}
201+
202+
public Builder withInvocationContext(InvocationContext invocationContext) {
203+
this.invocationContext = invocationContext;
204+
return this;
205+
}
206+
207+
public Builder withTemplate(PromptTemplate template) {
208+
this.template = template;
209+
return this;
210+
}
211+
212+
public ChatCompletionAgent build() {
213+
return new ChatCompletionAgent(
214+
id,
215+
name,
216+
description,
217+
kernel,
218+
KernelArguments,
219+
invocationContext,
220+
instructions,
221+
template
222+
);
223+
}
224+
225+
public ChatCompletionAgent build(PromptTemplateConfig promptTemplateConfig, PromptTemplateFactory promptTemplateFactory) {
226+
return new ChatCompletionAgent(
227+
id,
228+
name,
229+
description,
230+
kernel,
231+
KernelArguments,
232+
invocationContext,
233+
promptTemplateConfig.getTemplate(),
234+
promptTemplateFactory.tryCreate(promptTemplateConfig)
235+
);
236+
}
237+
}
238+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.microsoft.semantickernel.agents.chatcompletion;
2+
3+
import com.microsoft.semantickernel.agents.AgentThread;
4+
import com.microsoft.semantickernel.agents.BaseAgentThread;
5+
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
6+
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
7+
import reactor.core.publisher.Mono;
8+
9+
import javax.annotation.Nonnull;
10+
import javax.annotation.Nullable;
11+
import java.util.List;
12+
import java.util.UUID;
13+
14+
public class ChatHistoryAgentThread extends BaseAgentThread {
15+
private ChatHistory chatHistory;
16+
17+
public ChatHistoryAgentThread() {
18+
}
19+
20+
/**
21+
* Constructor for com.microsoft.semantickernel.agents.chatcompletion.ChatHistoryAgentThread.
22+
*
23+
* @param id The ID of the thread.
24+
* @param chatHistory The chat history.
25+
*/
26+
public ChatHistoryAgentThread(String id, @Nullable ChatHistory chatHistory) {
27+
super(id);
28+
this.chatHistory = chatHistory;
29+
}
30+
31+
/**
32+
* Get the chat history.
33+
*
34+
* @return The chat history.
35+
*/
36+
public ChatHistory getChatHistory() {
37+
return chatHistory;
38+
}
39+
40+
@Override
41+
public Mono<String> createAsync() {
42+
if (this.id == null) {
43+
this.id = UUID.randomUUID().toString();
44+
chatHistory = new ChatHistory();
45+
}
46+
return Mono.just(id);
47+
}
48+
49+
@Override
50+
public Mono<Void> deleteAsync() {
51+
return Mono.fromRunnable(chatHistory::clear);
52+
}
53+
54+
@Override
55+
public Mono<Void> onNewMessageAsync(ChatMessageContent<?> newMessage) {
56+
return Mono.fromRunnable(() -> {
57+
chatHistory.addMessage(newMessage);
58+
});
59+
}
60+
61+
public List<ChatMessageContent<?>> getMessages() {
62+
return chatHistory.getMessages();
63+
}
64+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.microsoft.semantic-kernel</groupId>
8+
<artifactId>semantickernel-parent</artifactId>
9+
<version>1.4.4-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>semantickernel-agents-openai</artifactId>
13+
14+
<properties>
15+
<maven.compiler.source>17</maven.compiler.source>
16+
<maven.compiler.target>17</maven.compiler.target>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
</properties>
19+
<dependencies>
20+
<dependency>
21+
<groupId>com.microsoft.semantic-kernel</groupId>
22+
<artifactId>semantickernel-api</artifactId>
23+
</dependency>
24+
</dependencies>
25+
26+
</project>

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
<module>data/semantickernel-data-azureaisearch</module>
7878
<module>data/semantickernel-data-jdbc</module>
7979
<module>data/semantickernel-data-redis</module>
80+
<module>agents/semantickernel-agents-openai</module>
81+
<module>agents/semantickernel-agents-core</module>
8082
</modules>
8183

8284
<dependencyManagement>

samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@
4949
<artifactId>semantickernel-data-redis</artifactId>
5050
</dependency>
5151

52+
<dependency>
53+
<groupId>com.microsoft.semantic-kernel</groupId>
54+
<artifactId>semantickernel-agents-core</artifactId>
55+
</dependency>
56+
5257
<dependency>
5358
<groupId>com.microsoft.semantic-kernel</groupId>
5459
<artifactId>semantickernel-experimental</artifactId>

0 commit comments

Comments
 (0)