Skip to content

Commit e7415ee

Browse files
committed
Initial port to semantic kernel v1.0.0
1 parent 6e69cbb commit e7415ee

22 files changed

+308
-229
lines changed

app/backend/pom.xml

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818

1919
<spring-cloud-azure.version>4.9.0</spring-cloud-azure.version>
2020
<azure-search.version>11.6.0-beta.8</azure-search.version>
21-
<azure-openai.version>1.0.0-beta.2</azure-openai.version>
22-
<semantic-kernel.version>0.2.9-alpha</semantic-kernel.version>
21+
<semantic-kernel.version>1.0.0-rc3-SNAPSHOT</semantic-kernel.version>
2322
<mockito-inline.version>4.5.1</mockito-inline.version>
2423
<maven.compiler-plugin.version>3.11.0</maven.compiler-plugin.version>
2524

@@ -81,18 +80,24 @@
8180
<dependency>
8281
<groupId>com.azure</groupId>
8382
<artifactId>azure-identity</artifactId>
83+
<version>1.11.2</version>
8484
</dependency>
85-
8685
<dependency>
8786
<groupId>com.azure</groupId>
88-
<artifactId>azure-search-documents</artifactId>
89-
<version>${azure-search.version}</version>
87+
<artifactId>azure-core</artifactId>
88+
<version>1.45.1</version>
9089
</dependency>
9190

9291
<dependency>
9392
<groupId>com.azure</groupId>
94-
<artifactId>azure-ai-openai</artifactId>
95-
<version>${azure-openai.version}</version>
93+
<artifactId>azure-search-documents</artifactId>
94+
<version>${azure-search.version}</version>
95+
<exclusions>
96+
<exclusion>
97+
<groupId>com.azure</groupId>
98+
<artifactId>azure-core-serializer-json-jackson</artifactId>
99+
</exclusion>
100+
</exclusions>
96101
</dependency>
97102

98103
<dependency>
@@ -107,22 +112,7 @@
107112
</dependency>
108113
<dependency>
109114
<groupId>com.microsoft.semantic-kernel</groupId>
110-
<artifactId>semantickernel-core</artifactId>
111-
<!-- TODO: scope should be runtime, but VolatileMemoryStore is an issue -->
112-
<!-- <scope>runtime</scope> -->
113-
</dependency>
114-
<dependency>
115-
<groupId>com.microsoft.semantic-kernel</groupId>
116-
<artifactId>semantickernel-connectors-ai-openai</artifactId>
117-
</dependency>
118-
119-
<dependency>
120-
<groupId>com.microsoft.semantic-kernel</groupId>
121-
<artifactId>semantickernel-planners</artifactId>
122-
</dependency>
123-
<dependency>
124-
<groupId>com.microsoft.semantic-kernel</groupId>
125-
<artifactId>semantickernel-connectors-memory-azurecognitivesearch</artifactId>
115+
<artifactId>semantickernel-aiservices-openai</artifactId>
126116
</dependency>
127117
<!-- Semantic Kernel end -->
128118
</dependencies>
@@ -239,4 +229,4 @@
239229
</profile>
240230
</profiles>
241231

242-
</project>
232+
</project>

app/backend/src/main/java/com/microsoft/openai/samples/rag/approaches/RAGApproachFactorySpringBootImpl.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22

33
import com.microsoft.openai.samples.rag.ask.approaches.PlainJavaAskApproach;
44
import com.microsoft.openai.samples.rag.ask.approaches.semantickernel.JavaSemanticKernelChainsApproach;
5-
import com.microsoft.openai.samples.rag.ask.approaches.semantickernel.JavaSemanticKernelPlannerApproach;
6-
import com.microsoft.openai.samples.rag.ask.approaches.semantickernel.JavaSemanticKernelWithMemoryApproach;
75
import com.microsoft.openai.samples.rag.chat.approaches.PlainJavaChatApproach;
86
import com.microsoft.openai.samples.rag.chat.approaches.semantickernel.JavaSemanticKernelChainsChatApproach;
9-
import com.microsoft.openai.samples.rag.chat.approaches.semantickernel.JavaSemanticKernelWithMemoryChatApproach;
107
import org.springframework.context.ApplicationContext;
118
import org.springframework.context.ApplicationContextAware;
129
import org.springframework.stereotype.Component;
@@ -32,8 +29,6 @@ public RAGApproach createApproach(String approachName, RAGType ragType, RAGOptio
3229
if (ragType.equals(RAGType.CHAT)) {
3330
if (JAVA_OPENAI_SDK.equals(approachName)) {
3431
return applicationContext.getBean(PlainJavaChatApproach.class);
35-
} else if (JAVA_SEMANTIC_KERNEL.equals(approachName)) {
36-
return applicationContext.getBean(JavaSemanticKernelWithMemoryChatApproach.class);
3732
} else if (
3833
JAVA_SEMANTIC_KERNEL_PLANNER.equals(approachName) &&
3934
ragOptions != null &&
@@ -44,10 +39,6 @@ public RAGApproach createApproach(String approachName, RAGType ragType, RAGOptio
4439
} else if (ragType.equals(RAGType.ASK)) {
4540
if (JAVA_OPENAI_SDK.equals(approachName))
4641
return applicationContext.getBean(PlainJavaAskApproach.class);
47-
else if (JAVA_SEMANTIC_KERNEL.equals(approachName))
48-
return applicationContext.getBean(JavaSemanticKernelWithMemoryApproach.class);
49-
else if (JAVA_SEMANTIC_KERNEL_PLANNER.equals(approachName) && ragOptions.getSemantickKernelMode() != null && ragOptions.getSemantickKernelMode() == SemanticKernelMode.planner)
50-
return applicationContext.getBean(JavaSemanticKernelPlannerApproach.class);
5142
else if (JAVA_SEMANTIC_KERNEL_PLANNER.equals(approachName) && ragOptions != null && ragOptions.getSemantickKernelMode() != null && ragOptions.getSemantickKernelMode() == SemanticKernelMode.chains)
5243
return applicationContext.getBean(JavaSemanticKernelChainsApproach.class);
5344
}

app/backend/src/main/java/com/microsoft/openai/samples/rag/ask/approaches/AnswerQuestionChatTemplate.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
package com.microsoft.openai.samples.rag.ask.approaches;
33

4-
import com.azure.ai.openai.models.ChatMessage;
5-
import com.azure.ai.openai.models.ChatRole;
4+
import com.azure.ai.openai.models.ChatRequestAssistantMessage;
5+
import com.azure.ai.openai.models.ChatRequestMessage;
6+
import com.azure.ai.openai.models.ChatRequestSystemMessage;
7+
import com.azure.ai.openai.models.ChatRequestUserMessage;
68
import com.microsoft.openai.samples.rag.approaches.ContentSource;
9+
710
import java.util.ArrayList;
811
import java.util.List;
912

1013
public class AnswerQuestionChatTemplate {
1114

12-
private final List<ChatMessage> conversationHistory = new ArrayList<>();
15+
private final List<ChatRequestMessage> conversationHistory = new ArrayList<>();
1316

1417
private String customPrompt = "";
1518
private String systemMessage;
@@ -71,22 +74,19 @@ public AnswerQuestionChatTemplate(String customPrompt, Boolean replacePrompt) {
7174
}
7275

7376
// Add system message
74-
ChatMessage chatSystemMessage = new ChatMessage(ChatRole.SYSTEM);
75-
chatSystemMessage.setContent(systemMessage);
77+
ChatRequestMessage chatSystemMessage = new ChatRequestSystemMessage(systemMessage);
7678

7779
this.conversationHistory.add(chatSystemMessage);
7880

7981
// Add few shoot learning with chat
80-
ChatMessage fewShotUserMessage = new ChatMessage(ChatRole.USER);
81-
fewShotUserMessage.setContent(FEW_SHOT_USER_MESSAGE);
82+
ChatRequestMessage fewShotUserMessage = new ChatRequestUserMessage(FEW_SHOT_USER_MESSAGE);
8283
this.conversationHistory.add(fewShotUserMessage);
8384

84-
ChatMessage fewShotAssistantMessage = new ChatMessage(ChatRole.ASSISTANT);
85-
fewShotAssistantMessage.setContent(FEW_SHOT_ASSISTANT_MESSAGE);
85+
ChatRequestMessage fewShotAssistantMessage = new ChatRequestAssistantMessage(FEW_SHOT_ASSISTANT_MESSAGE);
8686
this.conversationHistory.add(fewShotAssistantMessage);
8787
}
8888

89-
public List<ChatMessage> getMessages(String question, List<ContentSource> sources) {
89+
public List<ChatRequestMessage> getMessages(String question, List<ContentSource> sources) {
9090
if (sources == null || sources.isEmpty())
9191
throw new IllegalStateException("sources cannot be null or empty");
9292
if (question == null || question.isEmpty())
@@ -107,8 +107,7 @@ public List<ChatMessage> getMessages(String question, List<ContentSource> source
107107
String groundedUserQuestion =
108108
GROUNDED_USER_QUESTION_TEMPLATE.formatted(
109109
question, sourcesStringBuilder.toString());
110-
ChatMessage groundedUserMessage = new ChatMessage(ChatRole.USER);
111-
groundedUserMessage.setContent(groundedUserQuestion);
110+
ChatRequestMessage groundedUserMessage = new ChatRequestUserMessage(groundedUserQuestion);
112111
this.conversationHistory.add(groundedUserMessage);
113112

114113
return this.conversationHistory;

app/backend/src/main/java/com/microsoft/openai/samples/rag/ask/approaches/semantickernel/JavaSemanticKernelChainsApproach.java

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,25 @@
66
import com.microsoft.openai.samples.rag.approaches.RAGApproach;
77
import com.microsoft.openai.samples.rag.approaches.RAGOptions;
88
import com.microsoft.openai.samples.rag.approaches.RAGResponse;
9-
import com.microsoft.openai.samples.rag.retrieval.semantickernel.CognitiveSearchPlugin;
109
import com.microsoft.openai.samples.rag.proxy.CognitiveSearchProxy;
1110
import com.microsoft.openai.samples.rag.proxy.OpenAIProxy;
11+
import com.microsoft.openai.samples.rag.retrieval.semantickernel.CognitiveSearchPlugin;
1212
import com.microsoft.semantickernel.Kernel;
13-
import com.microsoft.semantickernel.SKBuilders;
14-
import com.microsoft.semantickernel.orchestration.SKContext;
13+
import com.microsoft.semantickernel.orchestration.FunctionResult;
14+
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
15+
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
16+
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
import org.springframework.beans.factory.annotation.Value;
20+
import org.springframework.stereotype.Component;
21+
1522
import java.io.OutputStream;
1623
import java.util.Arrays;
1724
import java.util.Collections;
1825
import java.util.List;
1926
import java.util.Objects;
2027
import java.util.stream.Collectors;
21-
import org.slf4j.Logger;
22-
import org.slf4j.LoggerFactory;
23-
import org.springframework.beans.factory.annotation.Value;
24-
import org.springframework.stereotype.Component;
2528

2629
/**
2730
* Use Java Semantic Kernel framework with semantic and native functions chaining. It uses an
@@ -36,8 +39,8 @@ public class JavaSemanticKernelChainsApproach implements RAGApproach<String, RAG
3639
LoggerFactory.getLogger(JavaSemanticKernelChainsApproach.class);
3740
private static final String PLAN_PROMPT =
3841
"""
39-
Take the input as a question and answer it finding any information needed
40-
""";
42+
Take the input as a question and answer it finding any information needed
43+
""";
4144
private final CognitiveSearchProxy cognitiveSearchProxy;
4245

4346
private final OpenAIProxy openAIProxy;
@@ -69,21 +72,24 @@ public RAGResponse run(String question, RAGOptions options) {
6972

7073
// STEP 1: Retrieve relevant documents using user question. It reuses the
7174
// CognitiveSearchRetriever appraoch through the CognitiveSearchPlugin native function.
72-
SKContext searchContext =
73-
semanticKernel
74-
.runAsync(
75-
question,
76-
semanticKernel
77-
.getSkill("InformationFinder")
78-
.getFunction("SearchFromQuestion", null))
79-
.block();
75+
FunctionResult<String> searchContext = semanticKernel
76+
.getPlugin("InformationFinder")
77+
.get("SearchFromQuestion")
78+
.invokeAsync(semanticKernel)
79+
.withArguments(
80+
KernelFunctionArguments.builder()
81+
.withInput(question)
82+
.build()
83+
)
84+
.withResultType(String.class)
85+
.block();
8086

8187
var sources = formSourcesList(searchContext.getResult());
8288

8389
// STEP 2: Build a SK context with the sources retrieved from the memory store and the user
8490
// question.
8591
var answerVariables =
86-
SKBuilders.variables()
92+
KernelFunctionArguments.builder()
8793
.withVariable("sources", searchContext.getResult())
8894
.withVariable("input", question)
8995
.build();
@@ -93,12 +99,12 @@ public RAGResponse run(String question, RAGOptions options) {
9399
* (a.k.a. skill) from the SK skills registry and provide it with the pre-built context.
94100
* Triggering Open AI to get an answerVariables.
95101
*/
96-
SKContext answerExecutionContext =
97-
semanticKernel
98-
.runAsync(
99-
answerVariables,
100-
semanticKernel.getSkill("RAG").getFunction("AnswerQuestion", null))
101-
.block();
102+
FunctionResult<String> answerExecutionContext = semanticKernel
103+
.invokeAsync("RAG", "AnswerQuestion")
104+
.withArguments(answerVariables)
105+
.withResultType(String.class)
106+
.block();
107+
102108
return new RAGResponse.Builder()
103109
.prompt("Prompt is managed by Semantic Kernel")
104110
.answer(answerExecutionContext.getResult())
@@ -144,20 +150,28 @@ private List<ContentSource> formSourcesList(String result) {
144150
* @return
145151
*/
146152
private Kernel buildSemanticKernel(RAGOptions options) {
147-
Kernel kernel =
148-
SKBuilders.kernel()
149-
.withDefaultAIService(
150-
SKBuilders.chatCompletion()
151-
.withModelId(gptChatDeploymentModelId)
152-
.withOpenAIClient(this.openAIAsyncClient)
153-
.build())
154-
.build();
155-
156-
kernel.importSkill(
157-
new CognitiveSearchPlugin(this.cognitiveSearchProxy, this.openAIProxy, options),
158-
"InformationFinder");
159-
kernel.importSkillFromResources("semantickernel/Plugins", "RAG", "AnswerQuestion", null);
160-
161-
return kernel;
153+
return Kernel.builder()
154+
.withAIService(
155+
ChatCompletionService.class,
156+
ChatCompletionService.builder()
157+
.withModelId(gptChatDeploymentModelId)
158+
.withOpenAIAsyncClient(this.openAIAsyncClient)
159+
.build()
160+
)
161+
.withPlugin(
162+
KernelPluginFactory.createFromObject(
163+
new CognitiveSearchPlugin(this.cognitiveSearchProxy, this.openAIProxy, options),
164+
"InformationFinder")
165+
)
166+
.withPlugin(
167+
KernelPluginFactory.importPluginFromResourcesDirectory(
168+
"semantickernel/Plugins",
169+
"RAG",
170+
"AnswerQuestion",
171+
null,
172+
String.class
173+
)
174+
)
175+
.build();
162176
}
163177
}

0 commit comments

Comments
 (0)