From 152593ea03faa0113c39cbda48403ec042d0a0d2 Mon Sep 17 00:00:00 2001
From: John Oliver <1615532+johnoliver@users.noreply.github.com>
Date: Wed, 5 Jul 2023 18:34:56 +0100
Subject: [PATCH] Java: Add sequential planner (#1526)
### Motivation and Context
### Description
### Contribution Checklist
- [ ] The code builds clean without any errors or warnings
- [ ] The PR follows SK Contribution Guidelines
(https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
- [ ] The code follows the .NET coding conventions
(https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions)
verified with `dotnet format`
- [ ] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone :smile:
---
.../src/main/java/InlineFunctionExample.java | 57 +-
...nlineFunctionWithPreBuiltSkillExample.java | 121 ++--
.../e2e/AbstractKernelTest.java | 29 +-
.../e2e/ContextVariableFunctionTest.java | 17 +-
.../semantickernel/e2e/FunSkillTest.java | 10 +-
.../e2e/InlineFunctionTest.java | 8 +-
.../semantickernel/e2e/KernelTest.java | 50 +-
.../semantickernel/e2e/PlannerTest.java | 20 +-
.../e2e/TextEmbeddingsTest.java | 239 ++++----
java/pom.xml | 7 +-
java/samples/pom.xml | 109 ++++
.../com/microsoft/semantickernel/Config.java | 31 +-
.../Example00_GettingStarted.java | 73 ++-
.../Example02_RunnningPromptsFromFile.java | 45 +-
.../Example03_SemanticFunctionInline.java | 17 +-
.../Example04_ContextVariablesChat.java | 25 +-
.../Example05_UsingThePlanner.java | 12 +-
.../Example06_MemoryAndEmbeddings.java | 4 +-
.../syntaxexamples/Example02_Pipeline.java | 2 +-
.../syntaxexamples/Example03_Variables.java | 60 ++
...mple04_CombineLLMPromptsAndNativeCode.java | 57 ++
.../Example05_InlineFunctionDefinition.java | 77 +++
.../Example06_TemplateLanguage.java | 145 ++---
.../Example08_RetryHandler.java | 137 ++---
.../Example09_FunctionTypes.java | 280 +++++++++
.../Example12_SequentialPlanner.java | 211 +++++++
.../Example13_ConversationSummarySkill.java | 10 +-
.../syntaxexamples/Example17_ChatGPT.java | 2 +-
.../Example28_ActionPlanner.java | 59 ++
.../semantickernel/syntaxexamples/RunAll.java | 32 +
.../sample-code/src/main/resources/log4j2.xml | 20 +
.../guice/SemanticKernelModule.java | 2 -
.../guice/CompletionFunctionExample.java | 6 +-
.../com/microsoft/semantickernel/Kernel.java | 56 +-
.../semantickernel/KernelConfig.java | 41 +-
.../semantickernel/SkillExecutor.java | 70 +++
.../com/microsoft/semantickernel/Verify.java | 6 +
.../semantickernel/ai/AIException.java | 28 +-
.../ai/embeddings/Embedding.java | 11 +-
.../builders/BuildersSingleton.java | 125 ++--
.../builders/FunctionBuilders.java | 10 +-
.../semantickernel/builders/SKBuilders.java | 9 +-
.../builders/ServiceLoadUtil.java | 40 +-
.../extensions/KernelExtensions.java | 29 +-
.../semantickernel/memory/MemoryRecord.java | 2 +-
.../memory/MemoryRecordMetadata.java | 2 +-
.../memory/SemanticTextMemory.java | 28 +-
.../orchestration/AbstractSKContext.java | 25 +-
.../orchestration/AbstractSkFunction.java | 70 ++-
.../orchestration/ContextVariables.java | 5 +
.../FunctionNotRegisteredException.java | 14 +-
.../InternalBuildersSingleton.java | 7 +-
.../orchestration/SKContext.java | 54 +-
.../orchestration/SKFunction.java | 120 +---
.../orchestration/SemanticSKContext.java | 5 -
.../WritableContextVariables.java | 14 +-
.../planner/PlanningException.java | 79 +++
.../semanticfunctions/PromptTemplate.java | 9 +-
.../PromptTemplateConfig.java | 148 ++++-
.../skilldefinition/FunctionView.java | 66 ++
.../skilldefinition/ParameterView.java | 4 +
.../ReadOnlyFunctionCollection.java | 4 +-
.../ReadOnlySkillCollection.java | 9 +-
.../templateengine/PromptTemplateEngine.java | 12 +
.../CompletionRequestSettings.java | 53 +-
.../textcompletion/CompletionSKContext.java | 6 -
.../textcompletion/CompletionSKFunction.java | 15 +-
.../util/AzureOpenAISettings.java | 20 +-
.../semantickernel/util/OpenAISettings.java | 12 +-
java/semantickernel-bom/pom.xml | 13 +-
.../chatcompletion/OpenAIChatCompletion.java | 7 +-
.../textcompletion/OpenAITextCompletion.java | 5 +-
.../OpenAITextEmbeddingGeneration.java | 3 +-
.../AzureCognitiveSearchMemory.java | 42 +-
.../AzureCognitiveSearchRecord.java | 16 +-
.../coreskills/ConversationSummarySkill.java | 26 +-
.../coreskills/FileIOSkill.java | 26 +-
.../semantickernel/coreskills/MathSkill.java | 40 +-
.../semantickernel/coreskills/TextSkill.java | 2 +-
.../semantickernel/coreskills/TimeSkill.java | 18 +-
.../coreskills/FileIOSkillTest.java | 17 +-
.../coreskills/TimeSkillTest.java | 15 +-
java/semantickernel-core/pom.xml | 5 +
.../semantickernel/DefaultKernel.java | 115 +++-
.../semantickernel/SkFunctionBuilders.java | 44 +-
.../memory/DefaultSemanticTextMemory.java | 45 +-
.../memory/VolatileMemoryStore.java | 6 +-
.../DefaultCompletionSKContext.java | 36 --
.../DefaultCompletionSKFunction.java | 114 ++--
.../DefaultContextVariables.java | 29 +
.../orchestration/DefaultSKContext.java | 105 ++++
.../DefaultSemanticSKContext.java | 45 --
.../DefaultSemanticSKFunction.java | 26 +-
.../orchestration/NativeSKFunction.java | 134 +++--
.../DefaultPromptTemplate.java | 72 ++-
.../skilldefinition/CaseInsensitiveMap.java | 30 +-
.../DefaultSkillCollection.java | 27 +-
.../skilldefinition/FunctionCollection.java | 30 +-
.../DefaultPromptTemplateEngine.java | 2 +-
.../templateengine/blocks/CodeBlock.java | 21 +-
.../templateengine/blocks/CodeRendering.java | 18 +-
.../blocks/FunctionIdBlock.java | 3 +-
.../templateengine/blocks/VarBlock.java | 4 +
....semantickernel.memory.MemoryStore$Builder | 1 +
...el.orchestration.ContextVariables$Builder} | 0
...ntickernel.orchestration.SKContext$Builder | 2 +-
...stration.WritableContextVariables$Builder} | 0
.../semantickernel/DefaultKernelTest.java | 92 ++-
.../OpenAIChatCompletionTest.java | 10 -
.../memory/VolatileMemoryStoreTests.java | 9 +-
.../orchestration/NativeSKFunctionTest.java | 22 +-
.../syntaxexamples/Example02PipelineTest.java | 2 +-
.../Example03VariablesTest.java | 2 +-
...e04CombineLLMPromptsAndNativeCodeTest.java | 8 +-
.../Example05UsingThePlannerTest.java | 17 +-
.../Example06TemplateLanguageTest.java | 23 +-
.../Example12SequentialPlanner.java | 196 ++++++
.../Example28ActionPlanner.java | 144 +++++
.../actionplanner-extension/pom.xml | 29 +
.../actionplanner/ActionPlanResponse.java | 47 ++
.../planner/actionplanner/ActionPlanner.java | 339 +++++++++++
.../planner/actionplanner/Plan.java | 569 ++++++++++++++++++
.../planner/actionplanner/skprompt.txt | 11 +
java/semantickernel-extensions-parent/pom.xml | 1 +
.../sequentialplanner-extensions/pom.xml | 4 +
.../planner/SequentialPlannerSKContext.java | 19 -
.../DefaultSequentialPlannerSKContext.java | 46 +-
.../SequentialPlanParser.java | 213 +++++++
.../sequentialplanner/SequentialPlanner.java | 97 +--
.../SequentialPlannerRequestSettings.java | 2 +-
.../planner/sequentialplanner/skprompt.txt | 4 +-
131 files changed, 4670 insertions(+), 1562 deletions(-)
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example03_Variables.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example05_InlineFunctionDefinition.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example09_FunctionTypes.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example12_SequentialPlanner.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example28_ActionPlanner.java
create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/RunAll.java
create mode 100644 java/samples/sample-code/src/main/resources/log4j2.xml
create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java
delete mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SemanticSKContext.java
create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java
create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java
delete mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKContext.java
delete mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKContext.java
create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java
delete mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKContext.java
create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.memory.MemoryStore$Builder
rename java/semantickernel-core/src/main/resources/META-INF/services/{com.microsoft.semantickernel.orchestration.ContextVariables$Builder.java => com.microsoft.semantickernel.orchestration.ContextVariables$Builder} (100%)
rename java/semantickernel-core/src/main/resources/META-INF/services/{com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder.java => com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder} (100%)
create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example12SequentialPlanner.java
create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example28ActionPlanner.java
create mode 100644 java/semantickernel-extensions-parent/actionplanner-extension/pom.xml
create mode 100644 java/semantickernel-extensions-parent/actionplanner-extension/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanResponse.java
create mode 100644 java/semantickernel-extensions-parent/actionplanner-extension/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanner.java
create mode 100644 java/semantickernel-extensions-parent/actionplanner-extension/src/main/java/com/microsoft/semantickernel/planner/actionplanner/Plan.java
create mode 100644 java/semantickernel-extensions-parent/actionplanner-extension/src/main/resources/com/microsoft/semantickernel/planner/actionplanner/skprompt.txt
delete mode 100644 java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/SequentialPlannerSKContext.java
create mode 100644 java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java
rename java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/{ => sequentialplanner}/SequentialPlannerRequestSettings.java (98%)
diff --git a/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java b/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java
index 916f3d42ee..5c83485d09 100644
--- a/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java
+++ b/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java
@@ -1,16 +1,4 @@
-
// Copyright (c) Microsoft. All rights reserved.
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
@@ -21,6 +9,16 @@ import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+
public class InlineFunctionExample {
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionExample.class);
@@ -28,7 +26,8 @@ public class InlineFunctionExample {
private static final String API_KEY;
private static final String ENDPOINT;
- private static final String TEXT_TO_SUMMARIZE = """
+ private static final String TEXT_TO_SUMMARIZE =
+ """
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
@@ -94,28 +93,30 @@ public class InlineFunctionExample {
}
public static void main(String[] args) {
- OpenAIAsyncClient client = new OpenAIClientBuilder()
- .endpoint(ENDPOINT)
- .credential(new AzureKeyCredential(API_KEY))
- .buildAsyncClient();
+ OpenAIAsyncClient client =
+ new OpenAIClientBuilder()
+ .endpoint(ENDPOINT)
+ .credential(new AzureKeyCredential(API_KEY))
+ .buildAsyncClient();
TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, MODEL);
String prompt = "{{$input}}\n" + "Summarize the content above.";
- KernelConfig kernelConfig = new KernelConfig.Builder()
- .addTextCompletionService(MODEL, kernel -> textCompletion)
- .build();
+ KernelConfig kernelConfig =
+ new KernelConfig.Builder()
+ .addTextCompletionService(MODEL, kernel -> textCompletion)
+ .build();
Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
- CompletionSKFunction summarize = kernel.getSemanticFunctionBuilder()
- .createFunction(
- prompt,
- "summarize",
- null,
- null,
- new PromptTemplateConfig.CompletionConfig(
- 0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
+ CompletionSKFunction summarize =
+ kernel.getSemanticFunctionBuilder()
+ .createFunction(
+ prompt,
+ "summarize",
+ null,
+ null,
+ new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000));
if (summarize == null) {
LOGGER.error("Null function");
diff --git a/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java b/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java
index 5d7b75dfa6..bdf02ae5fe 100644
--- a/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java
+++ b/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java
@@ -1,16 +1,4 @@
-
// Copyright (c) Microsoft. All rights reserved.
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
@@ -21,43 +9,55 @@ import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+
public class InlineFunctionWithPreBuiltSkillExample {
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
- private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class);
+ private static final Logger LOGGER =
+ LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class);
private static final String MODEL = "text-davinci-003";
private static final String API_KEY;
private static final String ENDPOINT;
- private static final String TEXT_TO_SUMMARIZE = """
- Demo (ancient Greek poet)
- From Wikipedia, the free encyclopedia
- Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
- Roman period, known for a single epigram, engraved upon the Colossus of
- Memnon, which bears her name. She speaks of herself therein as a lyric
- poetess dedicated to the Muses, but nothing is known of her life.[1]
- Identity
- Demo was evidently Greek, as her name, a traditional epithet of Demeter,
- signifies. The name was relatively common in the Hellenistic world, in
- Egypt and elsewhere, and she cannot be further identified. The date of her
- visit to the Colossus of Memnon cannot be established with certainty, but
- internal evidence on the left leg suggests her poem was inscribed there at
- some point in or after AD 196.[2]
- Epigram
- There are a number of graffiti inscriptions on the Colossus of Memnon.
- Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
- couplets, entitled and presumably authored by "Demo" or "Damo" (the
- Greek inscription is difficult to read), is a dedication to the Muses.[2]
- The poem is traditionally published with the works of Balbilla, though the
- internal evidence suggests a different author.[1]
- In the poem, Demo explains that Memnon has shown her special respect. In
- return, Demo offers the gift for poetry, as a gift to the hero. At the end
- of this epigram, she addresses Memnon, highlighting his divine status by
- recalling his strength and holiness.[2]
- Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
- dialect. The language indicates she was knowledgeable in Homeric
- poetry—'bearing a pleasant gift', for example, alludes to the use of that
- phrase throughout the Iliad and Odyssey.[a][2];
- """;
+ private static final String TEXT_TO_SUMMARIZE =
+ """
+ Demo (ancient Greek poet)
+ From Wikipedia, the free encyclopedia
+ Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
+ Roman period, known for a single epigram, engraved upon the Colossus of
+ Memnon, which bears her name. She speaks of herself therein as a lyric
+ poetess dedicated to the Muses, but nothing is known of her life.[1]
+ Identity
+ Demo was evidently Greek, as her name, a traditional epithet of Demeter,
+ signifies. The name was relatively common in the Hellenistic world, in
+ Egypt and elsewhere, and she cannot be further identified. The date of her
+ visit to the Colossus of Memnon cannot be established with certainty, but
+ internal evidence on the left leg suggests her poem was inscribed there at
+ some point in or after AD 196.[2]
+ Epigram
+ There are a number of graffiti inscriptions on the Colossus of Memnon.
+ Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
+ couplets, entitled and presumably authored by "Demo" or "Damo" (the
+ Greek inscription is difficult to read), is a dedication to the Muses.[2]
+ The poem is traditionally published with the works of Balbilla, though the
+ internal evidence suggests a different author.[1]
+ In the poem, Demo explains that Memnon has shown her special respect. In
+ return, Demo offers the gift for poetry, as a gift to the hero. At the end
+ of this epigram, she addresses Memnon, highlighting his divine status by
+ recalling his strength and holiness.[2]
+ Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
+ dialect. The language indicates she was knowledgeable in Homeric
+ poetry—'bearing a pleasant gift', for example, alludes to the use of that
+ phrase throughout the Iliad and Odyssey.[a][2];
+ """;
static {
try {
@@ -94,31 +94,30 @@ public class InlineFunctionWithPreBuiltSkillExample {
}
public static void main(String[] args) {
- OpenAIAsyncClient client = new OpenAIClientBuilder()
- .endpoint(ENDPOINT)
- .credential(new AzureKeyCredential(API_KEY))
- .buildAsyncClient();
+ OpenAIAsyncClient client =
+ new OpenAIClientBuilder()
+ .endpoint(ENDPOINT)
+ .credential(new AzureKeyCredential(API_KEY))
+ .buildAsyncClient();
TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, MODEL);
String prompt = "{{$input}}\nSummarize the content above.";
- CompletionSKFunction summarizeFunc = SKBuilders.completionFunctions()
- .createFunction(
- prompt,
- "summarize",
- null,
- null,
- new PromptTemplateConfig.CompletionConfig(
- 0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
-
- KernelConfig kernelConfig = new KernelConfig.Builder()
- .addTextCompletionService(MODEL, kernel -> textCompletion)
- .addSkill(summarizeFunc)
- .build();
+ KernelConfig kernelConfig =
+ new KernelConfig.Builder()
+ .addTextCompletionService(MODEL, kernel -> textCompletion)
+ .build();
Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
- CompletionSKFunction summarize = kernel.getSkills().getFunction("summarize", CompletionSKFunction.class);
+ CompletionSKFunction summarize =
+ SKBuilders.completionFunctions(kernel)
+ .createFunction(
+ prompt,
+ "summarize",
+ null,
+ null,
+ new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000));
if (summarize == null) {
LOGGER.error("Null function");
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java
index 515a839e74..2fd4b1dbb7 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java
@@ -11,6 +11,7 @@ import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+
import org.junit.jupiter.api.condition.EnabledIf;
import java.io.File;
@@ -29,12 +30,15 @@ public class AbstractKernelTest {
final OpenAIAsyncClient openAIClient = getAzureOpenAIClient();
TextCompletion textCompletion = new OpenAITextCompletion(openAIClient, model);
- KernelConfig kernelConfig = SKBuilders.kernelConfig()
- .addTextCompletionService(model, kernel -> textCompletion)
- .addTextEmbeddingsGenerationService(
- model,
- kernel -> SKBuilders.textEmbeddingGenerationService().build(openAIClient, model))
- .build();
+ KernelConfig kernelConfig =
+ SKBuilders.kernelConfig()
+ .addTextCompletionService(model, kernel -> textCompletion)
+ .addTextEmbeddingsGenerationService(
+ model,
+ kernel ->
+ SKBuilders.textEmbeddingGenerationService()
+ .build(openAIClient, model))
+ .build();
return SKBuilders.kernel()
.setKernelConfig(kernelConfig)
@@ -45,18 +49,17 @@ public class AbstractKernelTest {
public static OpenAIAsyncClient getOpenAIClient() throws IOException {
String apiKey = getToken(CONF_OPENAI_PROPERTIES);
NonAzureOpenAIKeyCredential credential = new NonAzureOpenAIKeyCredential(apiKey);
- return new OpenAIClientBuilder()
- .credential(credential)
- .buildAsyncClient();
+ return new OpenAIClientBuilder().credential(credential).buildAsyncClient();
}
public static OpenAIAsyncClient getAzureOpenAIClient() throws IOException {
String apiKey = getToken(AZURE_CONF_PROPERTIES);
- OpenAIAsyncClient client = new OpenAIClientBuilder()
- .endpoint(getEndpoint(AZURE_CONF_PROPERTIES))
- .credential(new AzureKeyCredential(apiKey))
- .buildAsyncClient();
+ OpenAIAsyncClient client =
+ new OpenAIClientBuilder()
+ .endpoint(getEndpoint(AZURE_CONF_PROPERTIES))
+ .credential(new AzureKeyCredential(apiKey))
+ .buildAsyncClient();
return client;
}
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java
index 117998ef8a..3453861820 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java
@@ -2,8 +2,9 @@
package com.microsoft.semantickernel.e2e;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import org.junit.jupiter.api.Test;
@@ -14,7 +15,6 @@ import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
@@ -50,10 +50,9 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
"ChatBot",
null,
null,
- new PromptTemplateConfig.CompletionConfig(
- 0.7, 0.5, 0, 0, 2000, new ArrayList<>()));
+ new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000));
- CompletionSKContext readOnlySkContext = chat.buildContext();
+ SKContext readOnlySkContext = SKBuilders.context().build(kernel);
chat("Hi, I'm looking for book suggestions?", chat, readOnlySkContext)
.flatMap(
@@ -72,8 +71,7 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
.block();
}
- private Function> chat(
- String input, CompletionSKFunction chat) {
+ private Function> chat(String input, CompletionSKFunction chat) {
return (context) -> {
try {
return chat(input, chat, context);
@@ -83,14 +81,13 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
};
}
- private Mono chat(
- String input, CompletionSKFunction chat, CompletionSKContext context)
+ private Mono chat(String input, CompletionSKFunction chat, SKContext context)
throws ExecutionException, InterruptedException, TimeoutException {
context = context.setVariable("user_input", input);
LOGGER.info("User:\n" + input);
- CompletionSKContext finalContext = context;
+ SKContext finalContext = context;
return chat.invokeAsync(context, null)
.map(
result -> {
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java
index 43df7a521d..b788f0e712 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java
@@ -1,8 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.e2e;
-import com.microsoft.semantickernel.extensions.KernelExtensions;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import org.junit.jupiter.api.Test;
@@ -20,12 +19,9 @@ public class FunSkillTest extends AbstractKernelTest {
@Test
public void tellAJoke() throws IOException {
- Mono result =
+ Mono result =
buildTextCompletionKernel()
- .importSkill(
- "FunSkill",
- KernelExtensions.importSemanticSkillFromDirectory(
- "../../../samples/skills", "FunSkill"))
+ .importSkillFromDirectory("FunSkill", "../../../samples/skills")
.getFunction("joke", CompletionSKFunction.class)
.invokeAsync("time travel to dinosaur age");
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java
index 87eb864459..6c941756d0 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java
@@ -2,8 +2,8 @@
package com.microsoft.semantickernel.e2e;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import org.junit.jupiter.api.Test;
@@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import java.io.IOException;
-import java.util.ArrayList;
public class InlineFunctionTest extends AbstractKernelTest {
@@ -33,8 +32,7 @@ public class InlineFunctionTest extends AbstractKernelTest {
"summarize",
null,
null,
- new PromptTemplateConfig.CompletionConfig(
- 0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
+ new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000));
String text =
"""
@@ -49,7 +47,7 @@ public class InlineFunctionTest extends AbstractKernelTest {
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2]
""";
- Mono result = summarize.invokeAsync(text);
+ Mono result = summarize.invokeAsync(text);
LOGGER.info("Result: " + result.block().getResult());
}
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java
index 64a01c0b1c..e7524e8e5d 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java
@@ -1,61 +1,61 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.e2e;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import reactor.core.publisher.Mono;
+import java.io.IOException;
+
public class KernelTest extends AbstractKernelTest {
private static final Logger LOGGER = LoggerFactory.getLogger(KernelTest.class);
private static void executeCompletion(Kernel kernel) {
- CompletionSKFunction summarize = kernel.getSemanticFunctionBuilder()
- .createFunction(
- """
+ CompletionSKFunction summarize =
+ kernel.getSemanticFunctionBuilder()
+ .createFunction(
+ """
{{$input}}
One line TLDR with the fewest words.""",
- null,
- "",
- null,
- new PromptTemplateConfig.CompletionConfig(
- 0, 0, 0, 0, 256, new ArrayList<>()));
+ null,
+ "",
+ null,
+ new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256));
- String text1 = """
+ String text1 =
+ """
1st Law of Thermodynamics - Energy cannot be created or destroyed.
2nd Law of Thermodynamics - For a spontaneous process, the entropy of the universe increases.
3rd Law of Thermodynamics - A perfect crystal at zero Kelvin has zero entropy""";
- Mono mono = summarize.invokeAsync(text1);
- CompletionSKContext result = mono.block();
+ Mono mono = summarize.invokeAsync(text1);
+ SKContext result = mono.block();
- if (result != null)
- LOGGER.info("Result: " + result.getResult());
+ if (result != null) LOGGER.info("Result: " + result.getResult());
}
public static Kernel buildKernel(OpenAIAsyncClient client, String model) {
TextCompletion textCompletion = new OpenAITextCompletion(client, model);
- KernelConfig kernelConfig = SKBuilders.kernelConfig()
- .addTextCompletionService(model, kernel -> textCompletion)
- .build();
+ KernelConfig kernelConfig =
+ SKBuilders.kernelConfig()
+ .addTextCompletionService(model, kernel -> textCompletion)
+ .build();
return SKBuilders.kernel().setKernelConfig(kernelConfig).build();
}
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java
index bffb2a3680..1788f4b0b8 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java
@@ -2,9 +2,9 @@
package com.microsoft.semantickernel.e2e;
import com.microsoft.semantickernel.Kernel;
-import com.microsoft.semantickernel.extensions.KernelExtensions;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.planner.actionplanner.Plan;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
@@ -21,21 +21,19 @@ public class PlannerTest extends AbstractKernelTest {
@EnabledIf("isAzureTestEnabled")
public void executeInlineFunction() throws IOException {
Kernel kernel = buildTextCompletionKernel();
- kernel.importSkill(
- "SummarizeSkill",
- KernelExtensions.importSemanticSkillFromDirectory(
- "../../../samples/skills", "SummarizeSkill"));
- kernel.importSkill(
- "WriterSkill",
- KernelExtensions.importSemanticSkillFromDirectory(
- "../../../samples/skills", "WriterSkill"));
+ kernel.importSkillFromDirectory(
+ "SummarizeSkill", "../../../samples/skills", "SummarizeSkill");
+ kernel.importSkillFromDirectory("WriterSkill", "../../../samples/skills", "WriterSkill");
SequentialPlanner planner = new SequentialPlanner(kernel, null, null);
- CompletionSKContext result =
+ Plan plan =
planner.createPlanAsync(
"Write a poem about John Doe, then translate it into Italian.")
.block();
+
+ SKContext result = plan.invokeAsync().block();
+
LOGGER.info("Result: " + result.getResult());
}
}
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java
index 2220e4efc5..5de815a0d9 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java
+++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java
@@ -1,9 +1,16 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.e2e;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration;
+import com.microsoft.semantickernel.coreskills.TextMemorySkill;
+import com.microsoft.semantickernel.memory.MemoryQueryResult;
+import com.microsoft.semantickernel.memory.SemanticTextMemory;
+import com.microsoft.semantickernel.memory.VolatileMemoryStore;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -11,155 +18,141 @@ import org.junit.jupiter.api.condition.EnabledIf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.azure.ai.openai.OpenAIAsyncClient;
-import com.microsoft.semantickernel.Kernel;
-import com.microsoft.semantickernel.KernelConfig;
-import com.microsoft.semantickernel.builders.SKBuilders;
-import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration;
-import com.microsoft.semantickernel.coreskills.TextMemorySkill;
-import com.microsoft.semantickernel.memory.MemoryQueryResult;
-import com.microsoft.semantickernel.memory.SemanticTextMemory;
-import com.microsoft.semantickernel.memory.VolatileMemoryStore;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
-import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
public class TextEmbeddingsTest extends AbstractKernelTest {
- private static final Logger LOGGER = LoggerFactory.getLogger(TextEmbeddingsTest.class);
- private static final int EXPECTED_EMBEDDING_SIZE = 1536;
+ private static final Logger LOGGER = LoggerFactory.getLogger(TextEmbeddingsTest.class);
+ private static final int EXPECTED_EMBEDDING_SIZE = 1536;
- @Test
- @EnabledIf("isOpenAIComTestEnabled")
- public void testEmbeddingGenerationOpenAI() throws IOException {
- testEmbeddingGeneration(getOpenAIClient(), EXPECTED_EMBEDDING_SIZE);
- }
+ @Test
+ @EnabledIf("isOpenAIComTestEnabled")
+ public void testEmbeddingGenerationOpenAI() throws IOException {
+ testEmbeddingGeneration(getOpenAIClient(), EXPECTED_EMBEDDING_SIZE);
+ }
- @Test
- @EnabledIf("isAzureTestEnabled")
- public void testEmbeddingGenerationAzure() throws IOException {
- testEmbeddingGeneration(getAzureOpenAIClient(), EXPECTED_EMBEDDING_SIZE);
- }
+ @Test
+ @EnabledIf("isAzureTestEnabled")
+ public void testEmbeddingGenerationAzure() throws IOException {
+ testEmbeddingGeneration(getAzureOpenAIClient(), EXPECTED_EMBEDDING_SIZE);
+ }
- @Test
- @EnabledIf("isAzureTestEnabled")
- public void testEmbeddingGeneration() throws IOException {
- String model = "text-embedding-ada-002";
- OpenAITextEmbeddingGeneration embeddingGeneration = new OpenAITextEmbeddingGeneration(getOpenAIClient(),
- model);
+ @Test
+ @EnabledIf("isAzureTestEnabled")
+ public void testEmbeddingGeneration() throws IOException {
+ String model = "text-embedding-ada-002";
+ OpenAITextEmbeddingGeneration embeddingGeneration =
+ new OpenAITextEmbeddingGeneration(getOpenAIClient(), model);
- List data = new ArrayList<>();
- data.add("This is just a test");
+ List data = new ArrayList<>();
+ data.add("This is just a test");
- LOGGER.info(String.valueOf(embeddingGeneration.generateEmbeddingsAsync(data).block()));
- }
+ LOGGER.info(String.valueOf(embeddingGeneration.generateEmbeddingsAsync(data).block()));
+ }
@Test
@EnabledIf("isAzureTestEnabled")
public void testMemory() throws IOException {
- Kernel kernel = buildTextCompletionKernel();
- kernel.importSkill(new TextMemorySkill(), "aboutMe");
+ Kernel kernel = buildTextCompletionKernel();
+ kernel.importSkill(new TextMemorySkill(), "aboutMe");
- String skPrompt = """
+ String skPrompt =
+ """
- ChatBot can have a conversation with you about any topic.
- It can give explicit instructions or say 'I don't know' if it does not have an answer.
+ ChatBot can have a conversation with you about any topic.
+ It can give explicit instructions or say 'I don't know' if it does not have an answer.
- Information about me, from previous conversations:
- - {{$fact1}} {{recall $fact1}}
- - {{$fact2}} {{recall $fact2}}
- - {{$fact3}} {{recall $fact3}}
- - {{$fact4}} {{recall $fact4}}
- - {{$fact5}} {{recall $fact5}}
+ Information about me, from previous conversations:
+ - {{$fact1}} {{recall $fact1}}
+ - {{$fact2}} {{recall $fact2}}
+ - {{$fact3}} {{recall $fact3}}
+ - {{$fact4}} {{recall $fact4}}
+ - {{$fact5}} {{recall $fact5}}
- Chat:
- {{$history}}
- User: {{$userInput}}
- ChatBot:\s""";
+ Chat:
+ {{$history}}
+ User: {{$userInput}}
+ ChatBot:\s""";
- CompletionSKFunction chat = kernel.getSemanticFunctionBuilder()
- .createFunction(
- skPrompt, "recall", "aboutMe", "TextEmbeddingTest#testMemory");
+ CompletionSKFunction chat =
+ kernel.getSemanticFunctionBuilder()
+ .createFunction(
+ skPrompt, "recall", "aboutMe", "TextEmbeddingTest#testMemory");
- VolatileMemoryStore volatileMemoryStore = new VolatileMemoryStore();
- volatileMemoryStore.createCollectionAsync("aboutMe").block();
+ VolatileMemoryStore volatileMemoryStore = new VolatileMemoryStore();
+ volatileMemoryStore.createCollectionAsync("aboutMe").block();
- OpenAITextEmbeddingGeneration embeddingGeneration = new OpenAITextEmbeddingGeneration(
- getAzureOpenAIClient(), "text-embedding-ada-002");
+ OpenAITextEmbeddingGeneration embeddingGeneration =
+ new OpenAITextEmbeddingGeneration(getAzureOpenAIClient(), "text-embedding-ada-002");
- SemanticTextMemory memory = SKBuilders.semanticTextMemory()
- .setEmbeddingGenerator(embeddingGeneration)
- .setStorage(volatileMemoryStore)
- .build();
+ SemanticTextMemory memory =
+ SKBuilders.semanticTextMemory()
+ .setEmbeddingGenerator(embeddingGeneration)
+ .setStorage(volatileMemoryStore)
+ .build();
- CompletionSKContext context = chat.buildContext(SKBuilders.variables().build(), memory,
- kernel.getSkills());
+ SKContext context =
+ SKBuilders.context()
+ .with(SKBuilders.variables().build())
+ .with(memory)
+ .with(kernel.getSkills())
+ .build();
- context.getSemanticMemory()
- .saveInformationAsync("aboutMe", "My name is Andrea", "fact1", null, null)
- .block();
+ context.getSemanticMemory()
+ .saveInformationAsync("aboutMe", "My name is Andrea", "fact1", null, null)
+ .block();
- context.getSemanticMemory()
- .saveInformationAsync(
- "aboutMe", "I currently work as a tour guide", "fact2", null, null)
- .block();
+ context.getSemanticMemory()
+ .saveInformationAsync(
+ "aboutMe", "I currently work as a tour guide", "fact2", null, null)
+ .block();
- context.getSemanticMemory()
- .saveInformationAsync(
- "aboutMe", "I've been living in Seattle since 2005", "fact3", null,
- null)
- .block();
+ context.getSemanticMemory()
+ .saveInformationAsync(
+ "aboutMe", "I've been living in Seattle since 2005", "fact3", null, null)
+ .block();
- context.getSemanticMemory()
- .saveInformationAsync(
- "aboutMe",
- "I visited France and Italy five times since 2015",
- "fact4",
- null,
- null)
- .block();
+ context.getSemanticMemory()
+ .saveInformationAsync(
+ "aboutMe",
+ "I visited France and Italy five times since 2015",
+ "fact4",
+ null,
+ null)
+ .block();
- context.getSemanticMemory()
- .saveInformationAsync("aboutMe", "My family is from New York", "fact5", null, null)
- .block();
+ context.getSemanticMemory()
+ .saveInformationAsync("aboutMe", "My family is from New York", "fact5", null, null)
+ .block();
- String query = "Where are you from originally?";
- List results = memory.searchAsync("aboutMe", query, 10, .5, false).block();
- results.forEach(
- result -> System.out.printf(
- "%s %s (relevance=%f)%n",
- query, result.getMetadata().getText(), result.getRelevance()));
- }
+ String query = "Where are you from originally?";
+ List results =
+ memory.searchAsync("aboutMe", query, 10, .5, false).block();
+ results.forEach(
+ result ->
+ System.out.printf(
+ "%s %s (relevance=%f)%n",
+ query, result.getMetadata().getText(), result.getRelevance()));
+ }
- public void testEmbeddingGeneration(OpenAIAsyncClient client, int expectedEmbeddingSize) {
- String model = "text-embedding-ada-002";
- OpenAITextEmbeddingGeneration embeddingGeneration = new OpenAITextEmbeddingGeneration(client, model);
+ public void testEmbeddingGeneration(OpenAIAsyncClient client, int expectedEmbeddingSize) {
+ String model = "text-embedding-ada-002";
+ OpenAITextEmbeddingGeneration embeddingGeneration =
+ new OpenAITextEmbeddingGeneration(client, model);
- List data = new ArrayList<>();
- data.add("This is just");
- data.add("a test");
+ List data = new ArrayList<>();
+ data.add("This is just");
+ data.add("a test");
- embeddingGeneration
- .generateEmbeddingsAsync(data)
- .block()
- .forEach(
- embedding -> Assertions.assertEquals(
- expectedEmbeddingSize, embedding.getVector().size()));
- }
-
- private Kernel buildTextEmbeddingsKernel() throws IOException {
- String model = "text-embedding-ada-002";
- OpenAITextEmbeddingGeneration embeddingGeneration = new OpenAITextEmbeddingGeneration(getOpenAIClient(),
- model);
-
- KernelConfig kernelConfig = SKBuilders.kernelConfig()
- .addTextEmbeddingsGenerationService(model, kernel -> embeddingGeneration)
- .build();
-
- // TODO: .WithMemoryStorage(new VolatileMemoryStore())
-
- // TODO: .WithMemoryStorage(new VolatileMemoryStore())
-
- return SKBuilders.kernel().setKernelConfig(kernelConfig).build();
- }
+ embeddingGeneration
+ .generateEmbeddingsAsync(data)
+ .block()
+ .forEach(
+ embedding ->
+ Assertions.assertEquals(
+ expectedEmbeddingSize, embedding.getVector().size()));
+ }
}
diff --git a/java/pom.xml b/java/pom.xml
index 080af27679..6dab4acac4 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -12,7 +12,7 @@
https://www.github.com/microsoft/semantic-kernel
- 1.0.0-beta.1
+ 1.0.0-beta.210.11.00.10.102.19.1
@@ -131,6 +131,11 @@
sequentialplanner-extensions${project.version}
+
+ com.microsoft.semantickernel.extensions
+ actionplanner-extension
+ ${project.version}
+
diff --git a/java/samples/pom.xml b/java/samples/pom.xml
index 5eb1f46b66..96d2b50856 100644
--- a/java/samples/pom.xml
+++ b/java/samples/pom.xml
@@ -35,4 +35,113 @@
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven.compiler-plugin.version}
+
+ ${maven.compiler.release}
+ ${maven.compiler.release}
+ ${maven.compiler.release}
+
+
+
+
+
+
+
+ com.microsoft.semantickernel
+ semantickernel-api
+
+
+ com.microsoft.semantickernel.connectors
+ semantickernel-connectors
+
+
+ com.microsoft.semantickernel
+ semantickernel-core
+ runtime
+
+
+ com.microsoft.semantickernel
+ semantickernel-core-skills
+ ${project.version}
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j2.version}
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j2.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j2.version}
+
+
+ com.microsoft.semantickernel.extensions
+ sequentialplanner-extensions
+ compile
+
+
+ com.microsoft.semantickernel.extensions
+ actionplanner-extension
+ compile
+
+
+
+
+
+ bug-check
+
+
+ false
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven.compiler-plugin.version}
+
+ ${maven.compiler.release}
+ ${maven.compiler.release}
+ ${project.build.sourceEncoding}
+ true
+
+ -XDcompilePolicy=simple
+
+
+ -Xplugin:ErrorProne
+ -XepOpt:NullAway:AnnotatedPackages=com.microsoft.semantickernel
+ -Xep:AlmostJavadoc:OFF -Xep:MissingSummary:OFF
+ -Xep:UnusedVariable:OFF -Xep:EmptyBlockTag:OFF
+
+
+
+
+ com.google.errorprone
+ error_prone_core
+ ${google.errorprone.core.version}
+
+
+ com.uber.nullaway
+ nullaway
+ ${com.uber.nullaway.version}
+
+
+
+
+
+
+
+
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Config.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Config.java
index 6b3c792d7b..c53f75bb83 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Config.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Config.java
@@ -16,11 +16,24 @@ public class Config {
public static final String CONF_PROPERTIES =
System.getProperty("CONF_PROPERTIES", "java/samples/conf.properties");
+ public static final String OPENAI_CLIENT_TYPE =
+ System.getProperty("OPENAI_CLIENT_TYPE", "OPEN_AI");
+
+ public static OpenAIAsyncClient getClient() throws IOException {
+ return ClientType.valueOf(OPENAI_CLIENT_TYPE).getClient();
+ }
+
public enum ClientType {
OPEN_AI {
@Override
public OpenAIAsyncClient getClient() throws IOException {
- OpenAISettings settings = AIProviderSettings.getOpenAISettingsFromFile(CONF_PROPERTIES);
+ return getClient(CONF_PROPERTIES);
+ }
+
+ @Override
+ public OpenAIAsyncClient getClient(String file) throws IOException {
+ OpenAISettings settings = AIProviderSettings.getOpenAISettingsFromFile(file);
+
return new OpenAIClientBuilder()
.credential(new NonAzureOpenAIKeyCredential(settings.getKey()))
.buildAsyncClient();
@@ -28,9 +41,14 @@ public class Config {
},
AZURE_OPEN_AI {
@Override
- public OpenAIAsyncClient getClient()
+ public OpenAIAsyncClient getClient() throws IOException {
+ return getClient(CONF_PROPERTIES);
+ }
+
+ @Override
+ public OpenAIAsyncClient getClient(String file)
throws IOException {
- AzureOpenAISettings settings = AIProviderSettings.getAzureOpenAISettingsFromFile(CONF_PROPERTIES);
+ AzureOpenAISettings settings = AIProviderSettings.getAzureOpenAISettingsFromFile(file);
return new OpenAIClientBuilder()
.endpoint(settings.getEndpoint())
@@ -40,5 +58,12 @@ public class Config {
};
public abstract OpenAIAsyncClient getClient() throws IOException;
+
+ /**
+ * Returns the client that will handle AzureOpenAI or OpenAI requests.
+ *
+ * @return client to be used by the kernel.
+ */
+ public abstract OpenAIAsyncClient getClient(String file) throws IOException;
}
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example00_GettingStarted.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example00_GettingStarted.java
index 1b6d279340..641d303673 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example00_GettingStarted.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example00_GettingStarted.java
@@ -4,9 +4,8 @@ import java.io.IOException;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.builders.SKBuilders;
-import com.microsoft.semantickernel.extensions.KernelExtensions;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import reactor.core.publisher.Mono;
@@ -24,54 +23,52 @@ import reactor.core.publisher.Mono;
*/
public class Example00_GettingStarted {
- /**
- * Returns a Semantic Kernel with Text Completion.
- *
- * @param client Client that will handle requests to AzureOpenAI or OpenAI.
- * @return
- */
- public static Kernel getKernel(OpenAIAsyncClient client) {
- KernelConfig config = SKBuilders.kernelConfig()
+ /**
+ * Returns a Semantic Kernel with Text Completion.
+ *
+ * @param client Client that will handle requests to AzureOpenAI or OpenAI.
+ * @return
+ */
+ public static Kernel getKernel(OpenAIAsyncClient client) {
+ KernelConfig config = SKBuilders.kernelConfig()
.addTextCompletionService("davinci",
kernel -> SKBuilders.textCompletionService().build(client, "text-davinci-003"))
- .build();
+ .build();
- Kernel kernel = SKBuilders.kernel()
- .setKernelConfig(config)
- .build();
+ Kernel kernel = SKBuilders.kernel()
+ .setKernelConfig(config)
+ .build();
- return kernel;
- }
+ return kernel;
+ }
- /**
+ /**
* Imports 'FunSkill' from directory examples and runs the 'Joke' function
* within it.
- *
- * @param kernel Kernel with Text Completion.
- */
- public static void joke(Kernel kernel) {
+ *
+ * @param kernel Kernel with Text Completion.
+ */
+ public static void joke(Kernel kernel) {
- ReadOnlyFunctionCollection skill = kernel
- .importSkill("FunSkill", KernelExtensions.importSemanticSkillFromDirectory(
- "samples/skills", "FunSkill"));
+ ReadOnlyFunctionCollection skill = kernel.importSkillFromDirectory("FunSkill", "samples/skills", "FunSkill");
- CompletionSKFunction function = skill.getFunction("Joke",
- CompletionSKFunction.class);
+ CompletionSKFunction function = skill.getFunction("Joke",
+ CompletionSKFunction.class);
- Mono result = function.invokeAsync("time travel to dinosaur age");
+ Mono result = function.invokeAsync("time travel to dinosaur age");
- if (result != null) {
- System.out.println(result.block().getResult());
+ if (result != null) {
+ System.out.println(result.block().getResult());
+ }
}
- }
- public static void run(Config.ClientType clientType) throws IOException {
- Kernel kernel = getKernel(clientType.getClient());
- joke(kernel);
- }
+ public static void run(Config.ClientType clientType) throws IOException {
+ Kernel kernel = getKernel(clientType.getClient());
+ joke(kernel);
+ }
- public static void main(String args[]) throws IOException {
- // Send one of Config.ClientType.OPEN_AI or Config.ClientType.AZURE_OPEN_AI
- run(Config.ClientType.OPEN_AI);
- }
+ public static void main(String args[]) throws IOException {
+ // Send one of Config.ClientType.OPEN_AI or Config.ClientType.AZURE_OPEN_AI
+ run(Config.ClientType.OPEN_AI);
+ }
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example02_RunnningPromptsFromFile.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example02_RunnningPromptsFromFile.java
index 506586715d..405b5c3191 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example02_RunnningPromptsFromFile.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example02_RunnningPromptsFromFile.java
@@ -1,12 +1,10 @@
package com.microsoft.semantickernel;
-import java.io.IOException;
-
-import com.azure.ai.openai.OpenAIAsyncClient;
-import com.microsoft.semantickernel.extensions.KernelExtensions;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
+import java.io.IOException;
+
/**
* Using Semantic Functions stored on disk
*
@@ -22,30 +20,29 @@ import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
*/
public class Example02_RunnningPromptsFromFile {
- /**
+ /**
* Imports skill 'FunSkill' stored in the samples folder and then returns the
* semantic function 'Joke' within it.
- *
- * @param kernel Kernel with Text Completion
- * @return Joke function
- */
- public static CompletionSKFunction getJokeFunction(Kernel kernel) {
- ReadOnlyFunctionCollection skill = kernel
- .importSkill("FunSkill", KernelExtensions.importSemanticSkillFromDirectory(
- "samples/skills", "FunSkill"));
+ *
+ * @param kernel Kernel with Text Completion
+ * @return Joke function
+ */
+ public static CompletionSKFunction getJokeFunction(Kernel kernel) {
+ ReadOnlyFunctionCollection skill = kernel
+ .importSkillFromDirectory("FunSkill", "samples/skills", "FunSkill");
- return skill.getFunction("Joke", CompletionSKFunction.class);
- }
+ return skill.getFunction("Joke", CompletionSKFunction.class);
+ }
- public static void run(Config.ClientType clientType) throws IOException {
- Kernel kernel = Example00_GettingStarted.getKernel(clientType.getClient());
- CompletionSKFunction jokeFunction = getJokeFunction(kernel);
+ public static void run(Config.ClientType clientType) throws IOException {
+ Kernel kernel = Example00_GettingStarted.getKernel(clientType.getClient());
+ CompletionSKFunction jokeFunction = getJokeFunction(kernel);
- System.out.println(jokeFunction.invokeAsync("time travel to dinosaur age").block().getResult());
- }
+ System.out.println(jokeFunction.invokeAsync("time travel to dinosaur age").block().getResult());
+ }
- public static void main(String args[]) throws IOException {
- // Send one of Config.ClientType.OPEN_AI or Config.ClientType.AZURE_OPEN_AI
- run(Config.ClientType.OPEN_AI);
- }
+ public static void main(String args[]) throws IOException {
+ // Send one of Config.ClientType.OPEN_AI or Config.ClientType.AZURE_OPEN_AI
+ run(Config.ClientType.OPEN_AI);
+ }
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example03_SemanticFunctionInline.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example03_SemanticFunctionInline.java
index db984fab72..9bdc7b8f63 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example03_SemanticFunctionInline.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example03_SemanticFunctionInline.java
@@ -1,15 +1,13 @@
package com.microsoft.semantickernel;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.orchestration.SKFunction;
+import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
+import reactor.core.publisher.Mono;
+
import java.io.IOException;
import java.util.ArrayList;
-import com.azure.ai.openai.OpenAIAsyncClient;
-import com.microsoft.semantickernel.orchestration.SKFunction;
-import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
-
-import reactor.core.publisher.Mono;
-
/**
* Define a Semantic Function inline with Java code.
*/
@@ -36,10 +34,9 @@ public class Example03_SemanticFunctionInline {
0.5,
0,
0,
- 2000,
- new ArrayList<>()));
+ 2000));
- Mono result = summarize.invokeAsync(text);
+ Mono result = summarize.invokeAsync(text);
if (result != null) {
System.out.println(result.block().getResult());
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example04_ContextVariablesChat.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example04_ContextVariablesChat.java
index b2efae5f94..0a773da15f 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example04_ContextVariablesChat.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example04_ContextVariablesChat.java
@@ -1,17 +1,17 @@
package com.microsoft.semantickernel;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
+import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
+import reactor.core.publisher.Mono;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
-import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
-import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
-
-import reactor.core.publisher.Mono;
-
/**
* Chatbot using context variables
*
@@ -43,10 +43,9 @@ public class Example04_ContextVariablesChat {
0.5,
0,
0,
- 2000,
- new ArrayList<>()));
+ 2000));
- CompletionSKContext readOnlySkContext = chat.buildContext();
+ SKContext readOnlySkContext = SKBuilders.context().build(kernel);
chat("Hi, I'm looking for book suggestions?", chat, readOnlySkContext)
.flatMap(
@@ -65,14 +64,14 @@ public class Example04_ContextVariablesChat {
.block();
}
- private static Mono chat(
- String input, CompletionSKFunction chat, CompletionSKContext context)
+ private static Mono chat(
+ String input, CompletionSKFunction chat, SKContext context)
throws ExecutionException, InterruptedException, TimeoutException {
context = context.setVariable("user_input", input);
System.out.println("User: " + input);
- CompletionSKContext finalContext = context;
+ SKContext finalContext = context;
return chat.invokeAsync(context, null)
.map(
result -> {
@@ -87,7 +86,7 @@ public class Example04_ContextVariablesChat {
});
}
- private static Function> chat(
+ private static Function> chat(
String input, CompletionSKFunction chat) {
return (context) -> {
try {
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example05_UsingThePlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example05_UsingThePlanner.java
index 05314283fe..9055ebd830 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example05_UsingThePlanner.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example05_UsingThePlanner.java
@@ -1,7 +1,5 @@
package com.microsoft.semantickernel;
-import com.azure.ai.openai.OpenAIAsyncClient;
-import com.microsoft.semantickernel.extensions.KernelExtensions;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import java.io.IOException;
@@ -9,21 +7,19 @@ import java.io.IOException;
public class Example05_UsingThePlanner {
public static SequentialPlanner getPlanner(Kernel kernel) {
- kernel.importSkill("SummarizeSkill", KernelExtensions.importSemanticSkillFromDirectory(
- "samples/skills", "SummarizeSkill"));
- kernel.importSkill("WriterSkill", KernelExtensions.importSemanticSkillFromDirectory(
- "samples/skills", "WriterSkill"));
+ kernel.importSkillFromDirectory("SummarizeSkill", "samples/skills", "SummarizeSkill");
+ kernel.importSkillFromDirectory("WriterSkill", "samples/skills", "WriterSkill");
return new SequentialPlanner(kernel, null, null);
}
- public static void run (Config.ClientType clientType) throws IOException {
+ public static void run(Config.ClientType clientType) throws IOException {
Kernel kernel = Example00_GettingStarted.getKernel(clientType.getClient());
SequentialPlanner planner = getPlanner(kernel);
System.out.println(planner.createPlanAsync(
"Write a poem about John Doe, then translate it into Italian.")
- .block().getResult());
+ .block().invokeAsync().block());
// TODO: execute the plan
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example06_MemoryAndEmbeddings.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example06_MemoryAndEmbeddings.java
index c3c463ed10..052191e79d 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example06_MemoryAndEmbeddings.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example06_MemoryAndEmbeddings.java
@@ -11,9 +11,7 @@ public class Example06_MemoryAndEmbeddings {
KernelConfig config = SKBuilders.kernelConfig()
.addTextCompletionService(
"davinci", kernel -> SKBuilders.textCompletionService().build(client, "text-davinci-003"))
- .addTextEmbeddingsGenerationService(
- "embeddings", kernel -> SKBuilders.textEmbeddingGenerationService().build(client, "text-embedding-ada-002"))
- .build();
+ .build();
// TODO: Add Volatile memory
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example02_Pipeline.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example02_Pipeline.java
index bb32dac071..6996c0ed7c 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example02_Pipeline.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example02_Pipeline.java
@@ -16,7 +16,7 @@ public class Example02_Pipeline {
// Load native skill
ReadOnlyFunctionCollection text = kernel.importSkill(new TextSkill(), null);
- Mono> result =
+ Mono result =
kernel.runAsync(
" i n f i n i t e s p a c e ",
text.getFunction("LStrip"),
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example03_Variables.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example03_Variables.java
new file mode 100644
index 0000000000..ba12ef73a3
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example03_Variables.java
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.syntaxexamples;
+
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.KernelConfig;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.ContextVariables;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
+import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
+import reactor.core.publisher.Mono;
+
+import java.util.Locale;
+
+public class Example03_Variables {
+
+ public static class StaticTextSkill {
+ @DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase")
+ public static Mono uppercase(
+ @SKFunctionInputAttribute
+ @SKFunctionParameters(description = "Text to uppercase", name = "input")
+ String text) {
+ return Mono.just(text.toUpperCase(Locale.ROOT));
+ }
+
+ @DefineSKFunction(description = "Append the day variable", name = "appendDay")
+ public Mono appendDay(
+ @SKFunctionInputAttribute
+ @SKFunctionParameters(description = "Text to append to", name = "input")
+ String input,
+ @SKFunctionParameters(description = "Current day", name = "day") String day) {
+ return Mono.just(input + day);
+ }
+ }
+
+ public static void main(String[] args) {
+ KernelConfig kernelConfig = SKBuilders.kernelConfig().build();
+ Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
+
+ // Load native skill
+ ReadOnlyFunctionCollection functionCollection =
+ kernel.importSkill(new StaticTextSkill(), "text");
+
+ ContextVariables variables =
+ SKBuilders.variables()
+ .build("Today is: ")
+ .writableClone()
+ .setVariable("day", "Monday");
+
+ Mono result =
+ kernel.runAsync(
+ variables,
+ functionCollection.getFunction("AppendDay"),
+ functionCollection.getFunction("Uppercase"));
+
+ System.out.println(result.block().getResult());
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java
new file mode 100644
index 0000000000..6e37a0bcb8
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.syntaxexamples;
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Config;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.KernelConfig;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
+import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+
+public class Example04_CombineLLMPromptsAndNativeCode {
+
+ public static class SearchEngineSkill {
+ @DefineSKFunction(description = "Append the day variable", name = "search")
+ public Mono search(
+ @SKFunctionInputAttribute
+ @SKFunctionParameters(description = "Text to search", name = "input")
+ String input) {
+ return Mono.just("Gran Torre Santiago is the tallest building in South America");
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
+
+ TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, "text-davinci-003");
+
+ KernelConfig kernelConfig = new KernelConfig.Builder()
+ .addTextCompletionService("text-davinci-003", kernel -> textCompletion)
+ .build();
+
+ Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
+ kernel.importSkill(new SearchEngineSkill(), null);
+ kernel.importSkillFromDirectory("SummarizeSkill", "./samples/skills", "SummarizeSkill");
+
+ // Run
+ String ask = "What's the tallest building in South America?";
+
+ Mono result =
+ kernel.runAsync(ask, kernel.getSkills().getFunction("Search", null));
+
+ result =
+ kernel.runAsync(
+ ask,
+ kernel.getSkills().getFunction("Search", null),
+ kernel.getSkill("SummarizeSkill").getFunction("Summarize", null));
+
+ System.out.println(result.block().getResult());
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example05_InlineFunctionDefinition.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example05_InlineFunctionDefinition.java
new file mode 100644
index 0000000000..2906daa35f
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example05_InlineFunctionDefinition.java
@@ -0,0 +1,77 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+package com.microsoft.semantickernel.syntaxexamples;
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Config;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.KernelConfig;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
+import com.microsoft.semantickernel.textcompletion.TextCompletion;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+
+public class Example05_InlineFunctionDefinition {
+ public static void main(String[] args) throws IOException {
+ OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
+
+ TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, "text-davinci-003");
+
+ KernelConfig kernelConfig = new KernelConfig.Builder()
+ .addTextCompletionService("text-davinci-003", kernel -> textCompletion)
+ .build();
+
+ Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
+
+ System.out.println("======== Inline Function Definition ========");
+
+ // Function defined using few-shot design pattern
+ String functionDefinition = """
+ Generate a creative reason or excuse for the given event.
+ Be creative and be funny. Let your imagination run wild.
+
+ Event: I am running late.
+ Excuse: I was being held ransom by giraffe gangsters.
+
+ Event: I haven't been to the gym for a year
+ Excuse: I've been too busy training my pet dragon.
+
+ Event: {{$input}}
+ """.stripIndent();
+
+ // Create function via builder
+ var excuseFunction = SKBuilders
+ .completionFunctions(kernel)
+ .createFunction(
+ functionDefinition,
+ new PromptTemplateConfig.CompletionConfigBuilder()
+ .maxTokens(100)
+ .temperature(0.4)
+ .topP(1)
+ .build());
+
+
+ var result = excuseFunction.invokeAsync("I missed the F1 final race").block();
+ System.out.println(result.getResult());
+
+ result = excuseFunction.invokeAsync("sorry I forgot your birthday").block();
+ System.out.println(result.getResult());
+
+ // Create function via kernel
+ var fixedFunction = kernel.
+ getSemanticFunctionBuilder()
+ .createFunction("Translate this date " +
+ DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(LocalDateTime.now()) + " to French format",
+ new PromptTemplateConfig.CompletionConfigBuilder()
+ .maxTokens(100)
+ .temperature(0.4)
+ .topP(1)
+ .build());
+
+ System.out.println(fixedFunction.invokeAsync().block().getResult());
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example06_TemplateLanguage.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example06_TemplateLanguage.java
index 917e0f0d7d..e136edad4c 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example06_TemplateLanguage.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example06_TemplateLanguage.java
@@ -4,91 +4,100 @@ package com.microsoft.semantickernel.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Config;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.coreskills.TimeSkill;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
+
import java.io.IOException;
-import java.util.ArrayList;
public class Example06_TemplateLanguage {
- ///
- /// Show how to invoke a Native Function written in C#
- /// from a Semantic Function written in natural language
- ///
+ ///
+ /// Show how to invoke a Native Function written in C#
+ /// from a Semantic Function written in natural language
+ ///
- public static void main(String[] args) throws IOException {
- System.out.println("======== TemplateLanguage ========");
+ public static void main(String[] args) throws IOException {
+ System.out.println("======== TemplateLanguage ========");
- OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
+ OpenAIAsyncClient client = Config.getClient();
+ KernelConfig kernelConfig = SKBuilders
+ .kernelConfig()
+ .addTextCompletionService("text-davinci-003", kernel1 -> SKBuilders.textCompletionService()
+ .build(client, "text-davinci-003"))
+ .build();
- Kernel kernel = SKBuilders.kernel().build();
+ Kernel kernel = SKBuilders.kernel()
+ .setKernelConfig(kernelConfig)
+ .build();
- // Load native skill into the kernel skill collection, sharing its functions
- // with prompt templates
- // Functions loaded here are available as "time.*"
- kernel.importSkill(new TimeSkill(), "time");
+ // Load native skill into the kernel skill collection, sharing its functions
+ // with prompt templates
+ // Functions loaded here are available as "time.*"
+ kernel.importSkill(new TimeSkill(), "time");
- // Semantic Function invoking time.Date and time.Time native functions
- String functionDefinition = """
- Today is: {{time.Date}}
- Current time is: {{time.Time}}
+ // Semantic Function invoking time.Date and time.Time native functions
+ String functionDefinition = """
+ Today is: {{time.Date}}
+ Current time is: {{time.Time}}
- Answer to the following questions using JSON syntax, including the data used.
- Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)?
- Is it weekend time (weekend/not weekend)?
- """;
+ Answer to the following questions using JSON syntax, including the data used.
+ Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)?
+ Is it weekend time (weekend/not weekend)?
+ """;
- // This allows to see the prompt before it's sent to OpenAI
- System.out.println("--- Rendered Prompt");
+ // This allows to see the prompt before it's sent to OpenAI
+ System.out.println("--- Rendered Prompt");
- var promptRenderer = SKBuilders.promptTemplate().build(functionDefinition, null);
+ var promptRenderer = SKBuilders.promptTemplate()
+ .withPromptTemplateConfig(new PromptTemplateConfig())
+ .withPromptTemplate(functionDefinition)
+ .build(kernel.getPromptTemplateEngine());
- SKContext skContext = SKBuilders
- .context()
- .build(kernel.getSkills());
+ SKContext skContext = SKBuilders
+ .context()
+ .build(kernel.getSkills());
- PromptTemplateEngine promptTemplateEngine = SKBuilders.promptTemplateEngine().build();
+ var renderedPrompt = promptRenderer.renderAsync(skContext);
+ System.out.println(renderedPrompt.block());
- var renderedPrompt = promptRenderer.renderAsync(skContext, promptTemplateEngine);
- System.out.println(renderedPrompt.block());
+ // Run the prompt / semantic function
+ var kindOfDay = kernel
+ .getSemanticFunctionBuilder()
+ .createFunction(
+ functionDefinition,
+ null,
+ null,
+ null,
+ new PromptTemplateConfig.CompletionConfig(
+ 0, 0, 0, 0, 256));
- // Run the prompt / semantic function
- var kindOfDay = kernel.getSemanticFunctionBuilder()
- .createFunction(
- functionDefinition,
- null,
- null,
- null,
- new PromptTemplateConfig.CompletionConfig(
- 0, 0, 0, 0, 256, new ArrayList<>()));
-
- // Show the result
- System.out.println("--- Semantic Function result");
- var result = kindOfDay.invokeAsync("").block().getResult();
- System.out.println(result);
- /*
- * OUTPUT:
- *
- * --- Rendered Prompt
- *
- * Today is: Friday, April 28, 2023
- * Current time is: 11:04:30 PM
- *
- * Answer to the following questions using JSON syntax, including the data used.
- * Is it morning, afternoon, evening, or night
- * (morning/afternoon/evening/night)?
- * Is it weekend time (weekend/not weekend)?
- *
- * --- Semantic Function result
- *
- * {
- * "date": "Friday, April 28, 2023",
- * "time": "11:04:30 PM",
- * "period": "night",
- * "weekend": "weekend"
- * }
- */
- }
+ // Show the result
+ System.out.println("--- Semantic Function result");
+ var result = kindOfDay.invokeAsync("").block().getResult();
+ System.out.println(result);
+ /*
+ * OUTPUT:
+ *
+ * --- Rendered Prompt
+ *
+ * Today is: Friday, April 28, 2023
+ * Current time is: 11:04:30 PM
+ *
+ * Answer to the following questions using JSON syntax, including the data used.
+ * Is it morning, afternoon, evening, or night
+ * (morning/afternoon/evening/night)?
+ * Is it weekend time (weekend/not weekend)?
+ *
+ * --- Semantic Function result
+ *
+ * {
+ * "date": "Friday, April 28, 2023",
+ * "time": "11:04:30 PM",
+ * "period": "night",
+ * "weekend": "weekend"
+ * }
+ */
+ }
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example08_RetryHandler.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example08_RetryHandler.java
index f23db9e5b2..502c79f21f 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example08_RetryHandler.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example08_RetryHandler.java
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.syntaxexamples;
-import static com.microsoft.semantickernel.Config.CONF_PROPERTIES;
-
-import java.io.IOException;
-import java.time.Duration;
-import java.util.ArrayList;
-
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
@@ -15,84 +9,91 @@ import com.azure.core.http.policy.RetryOptions;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import com.microsoft.semantickernel.util.AIProviderSettings;
import com.microsoft.semantickernel.util.AzureOpenAISettings;
+import java.io.IOException;
+import java.time.Duration;
+
+import static com.microsoft.semantickernel.Config.CONF_PROPERTIES;
+
public class Example08_RetryHandler {
- public static void main(String[] args) throws IOException {
- RetryOptions retryOptions = new RetryOptions(new ExponentialBackoffOptions()
- .setMaxDelay(Duration.ofSeconds(180))
- .setBaseDelay(Duration.ofSeconds(60))
- .setMaxRetries(3));
+ public static void main(String[] args) throws IOException {
+ RetryOptions retryOptions = new RetryOptions(new ExponentialBackoffOptions()
+ .setMaxDelay(Duration.ofSeconds(180))
+ .setBaseDelay(Duration.ofSeconds(60))
+ .setMaxRetries(3));
- AzureOpenAISettings settings = AIProviderSettings.getAzureOpenAISettingsFromFile(CONF_PROPERTIES);
- OpenAIAsyncClient client = new OpenAIClientBuilder()
- .retryOptions(retryOptions)
- .endpoint(settings.getEndpoint())
- .credential(new AzureKeyCredential(settings.getKey()))
- .buildAsyncClient();
+ AzureOpenAISettings settings = AIProviderSettings.getAzureOpenAISettingsFromFile(CONF_PROPERTIES);
+ OpenAIAsyncClient client = new OpenAIClientBuilder()
+ .retryOptions(retryOptions)
+ .endpoint(settings.getEndpoint())
+ .credential(new AzureKeyCredential(settings.getKey()))
+ .buildAsyncClient();
- String text = """
- Demo (ancient Greek poet)
- From Wikipedia, the free encyclopedia
- Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
- Roman period, known for a single epigram, engraved upon the Colossus of
- Memnon, which bears her name. She speaks of herself therein as a lyric
- poetess dedicated to the Muses, but nothing is known of her life.[1]
- Identity
- Demo was evidently Greek, as her name, a traditional epithet of Demeter,
- signifies. The name was relatively common in the Hellenistic world, in
- Egypt and elsewhere, and she cannot be further identified. The date of her
- visit to the Colossus of Memnon cannot be established with certainty, but
- internal evidence on the left leg suggests her poem was inscribed there at
- some point in or after AD 196.[2]
- Epigram
- There are a number of graffiti inscriptions on the Colossus of Memnon.
- Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
- couplets, entitled and presumably authored by "Demo" or "Damo" (the
- Greek inscription is difficult to read), is a dedication to the Muses.[2]
- The poem is traditionally published with the works of Balbilla, though the
- internal evidence suggests a different author.[1]
- In the poem, Demo explains that Memnon has shown her special respect. In
- return, Demo offers the gift for poetry, as a gift to the hero. At the end
- of this epigram, she addresses Memnon, highlighting his divine status by
- recalling his strength and holiness.[2]
- Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
- dialect. The language indicates she was knowledgeable in Homeric
- poetry—'bearing a pleasant gift', for example, alludes to the use of that
- phrase throughout the Iliad and Odyssey.[a][2];
- """;
+ String text = """
+ Demo (ancient Greek poet)
+ From Wikipedia, the free encyclopedia
+ Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
+ Roman period, known for a single epigram, engraved upon the Colossus of
+ Memnon, which bears her name. She speaks of herself therein as a lyric
+ poetess dedicated to the Muses, but nothing is known of her life.[1]
+ Identity
+ Demo was evidently Greek, as her name, a traditional epithet of Demeter,
+ signifies. The name was relatively common in the Hellenistic world, in
+ Egypt and elsewhere, and she cannot be further identified. The date of her
+ visit to the Colossus of Memnon cannot be established with certainty, but
+ internal evidence on the left leg suggests her poem was inscribed there at
+ some point in or after AD 196.[2]
+ Epigram
+ There are a number of graffiti inscriptions on the Colossus of Memnon.
+ Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
+ couplets, entitled and presumably authored by "Demo" or "Damo" (the
+ Greek inscription is difficult to read), is a dedication to the Muses.[2]
+ The poem is traditionally published with the works of Balbilla, though the
+ internal evidence suggests a different author.[1]
+ In the poem, Demo explains that Memnon has shown her special respect. In
+ return, Demo offers the gift for poetry, as a gift to the hero. At the end
+ of this epigram, she addresses Memnon, highlighting his divine status by
+ recalling his strength and holiness.[2]
+ Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
+ dialect. The language indicates she was knowledgeable in Homeric
+ poetry—'bearing a pleasant gift', for example, alludes to the use of that
+ phrase throughout the Iliad and Odyssey.[a][2];
+ """;
- String prompt = "{{$input}}\nSummarize the content above.";
+ String prompt = "{{$input}}\nSummarize the content above.";
- TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, "text-davinci-003");
+ TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, "text-davinci-003");
- CompletionSKFunction summarizeFunc = SKBuilders.completionFunctions()
- .createFunction(
- prompt,
- "summarize",
- null,
- null,
- new PromptTemplateConfig.CompletionConfig(
- 0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
+ KernelConfig kernelConfig = new KernelConfig.Builder()
+ .addTextCompletionService("text-davinci-003", kernel -> textCompletion)
+ .build();
- KernelConfig kernelConfig = new KernelConfig.Builder()
- .addTextCompletionService("text-davinci-003", kernel -> textCompletion)
- .addSkill(summarizeFunc)
- .build();
+ Kernel kernel = SKBuilders
+ .kernel()
+ .setKernelConfig(kernelConfig)
+ .build();
- Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
+ CompletionSKFunction summarizeFunc = SKBuilders.completionFunctions(kernel)
+ .createFunction(
+ prompt,
+ "summarize",
+ null,
+ null,
+ new PromptTemplateConfig.CompletionConfig(
+ 0.2, 0.5, 0, 0, 2000));
- CompletionSKFunction summarize = kernel.getSkills().getFunction("summarize",
- CompletionSKFunction.class);
- CompletionSKContext context = summarize.invokeAsync(text).block();
+ kernel.registerSemanticFunction(summarizeFunc);
- System.out.println(context.getResult());
- }
+ SKContext context = summarizeFunc.invokeAsync(text).block();
+
+ System.out.println(context.getResult());
+ }
}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example09_FunctionTypes.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example09_FunctionTypes.java
new file mode 100644
index 0000000000..721aadb8ce
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example09_FunctionTypes.java
@@ -0,0 +1,280 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.syntaxexamples;
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Config;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.KernelConfig;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
+import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.time.Duration;
+
+public class Example09_FunctionTypes {
+ public static void main(String[] args) throws IOException {
+ OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
+
+ TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, "text-davinci-003");
+
+ KernelConfig kernelConfig = new KernelConfig.Builder()
+ .addTextCompletionService("text-davinci-003", kernel -> textCompletion)
+ .build();
+
+ Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
+
+ System.out.println("======== Native function types ========");
+
+ // Load native skill into the kernel skill collection, sharing its functions with prompt templates
+ var test = kernel
+ .importSkill(new LocalExampleSkill(), "test");
+
+ kernel.importSkillsFromDirectory("./samples/skills", "SummarizeSkill");
+
+
+ var fakeContext = SKBuilders.context()
+ .with(kernel.getSkills())
+ .build();
+
+ // The kernel takes care of wiring the input appropriately
+ SKContext result = kernel.runAsync(
+ "",
+ test.getFunction("type01"),
+ test.getFunction("type02"),
+ test.getFunction("type03"),
+ test.getFunction("type04"),
+ test.getFunction("type05"),
+ test.getFunction("type06"),
+ test.getFunction("type07"),
+ test.getFunction("type08"),
+ test.getFunction("type09"),
+ test.getFunction("type10"),
+ test.getFunction("type11"),
+ test.getFunction("type12"),
+ test.getFunction("type13"),
+ test.getFunction("type14"),
+ test.getFunction("type15"),
+ test.getFunction("type16"),
+ test.getFunction("type17"),
+ test.getFunction("type18")
+ )
+ .block();
+
+ kernel.getFunction("test", "type01").invokeAsync().block();
+ test.getFunction("type01").invokeAsync().block();
+
+ kernel.getFunction("test", "type02").invokeAsync().block();
+ test.getFunction("type02").invokeAsync().block();
+
+ kernel.getFunction("test", "type03").invokeAsync().block();
+ test.getFunction("type03").invokeAsync().block();
+
+ kernel.getFunction("test", "type04").invokeAsync(fakeContext).block();
+ test.getFunction("type04").invokeAsync(fakeContext).block();
+
+ kernel.getFunction("test", "type05").invokeAsync(fakeContext).block();
+ test.getFunction("type05").invokeAsync(fakeContext).block();
+
+ kernel.getFunction("test", "type06").invokeAsync(fakeContext).block();
+ test.getFunction("type06").invokeAsync(fakeContext).block();
+
+ kernel.getFunction("test", "type07").invokeAsync(fakeContext).block();
+ test.getFunction("type07").invokeAsync(fakeContext).block();
+
+ kernel.getFunction("test", "type08").invokeAsync("").block();
+ test.getFunction("type08").invokeAsync("").block();
+
+ kernel.getFunction("test", "type09").invokeAsync("").block();
+ test.getFunction("type09").invokeAsync("").block();
+
+ kernel.getFunction("test", "type10").invokeAsync("").block();
+ test.getFunction("type10").invokeAsync("").block();
+
+ kernel.getFunction("test", "type11").invokeAsync("").block();
+ test.getFunction("type11").invokeAsync("").block();
+
+ kernel.getFunction("test", "type12").invokeAsync("").block();
+ test.getFunction("type12").invokeAsync("").block();
+
+ kernel.getFunction("test", "type13").invokeAsync("").block();
+ test.getFunction("type13").invokeAsync("").block();
+
+ kernel.getFunction("test", "type14").invokeAsync("").block();
+ test.getFunction("type14").invokeAsync("").block();
+
+ kernel.getFunction("test", "type15").invokeAsync("").block();
+ test.getFunction("type15").invokeAsync("").block();
+
+ kernel.getFunction("test", "type16").invokeAsync("").block();
+ test.getFunction("type16").invokeAsync("").block();
+
+ kernel.getFunction("test", "type17").invokeAsync("").block();
+ test.getFunction("type17").invokeAsync("").block();
+
+ kernel.getFunction("test", "type18").invokeAsync("").block();
+ test.getFunction("type18").invokeAsync("").block();
+ }
+
+
+ public static class LocalExampleSkill {
+
+ @DefineSKFunction(name = "type01")
+ public void Type01() {
+ System.out.println("Running function type 1");
+ }
+
+ @DefineSKFunction(name = "type02")
+ public String Type02() {
+ System.out.println("Running function type 2");
+ return "";
+ }
+
+ @DefineSKFunction(name = "type03")
+ public Mono Type03Async() {
+ return Mono.delay(Duration.ZERO)
+ .map(x -> {
+ System.out.println("Running function type 3");
+ return "";
+ });
+ }
+
+
+ @DefineSKFunction(name = "type04")
+ public void Type04(SKContext context) {
+ System.out.println("Running function type 4");
+ }
+
+
+ @DefineSKFunction(name = "type05")
+ public String Type05(SKContext context) {
+ System.out.println("Running function type 5");
+ return "";
+ }
+
+
+ @DefineSKFunction(name = "type06")
+ public Mono Type06Async(SKContext context) {
+ var summarizer = context.getSkills().getFunction("SummarizeSkill", "Summarize", null);
+
+ return summarizer
+ .invokeAsync("blah blah blah")
+ .map(summary -> {
+ System.out.println("Running function type 6 " + summary.getResult());
+ return "";
+ });
+ }
+
+ @DefineSKFunction(name = "type07")
+ public Mono Type07Async(SKContext context) {
+ return Mono.delay(Duration.ZERO)
+ .map(x -> {
+ System.out.println("Running function type 7");
+ return context;
+ });
+ }
+
+ @DefineSKFunction(name = "type08")
+ public void Type08(
+ @SKFunctionInputAttribute
+ String x) {
+ System.out.println("Running function type 8");
+ }
+
+
+ @DefineSKFunction(name = "type09")
+ public String Type09(
+ @SKFunctionInputAttribute
+ String x) {
+ System.out.println("Running function type 9");
+ return "";
+ }
+
+ @DefineSKFunction(name = "type10")
+ public Mono Type10Async(
+ @SKFunctionInputAttribute
+ String x) {
+ return Mono.delay(Duration.ZERO)
+ .map(x2 -> {
+ System.out.println("Running function type 10");
+ return "";
+ });
+ }
+
+ @DefineSKFunction(name = "type11")
+ public void Type11(
+ @SKFunctionInputAttribute
+ String x,
+ SKContext context) {
+ System.out.println("Running function type 11");
+ }
+
+
+ @DefineSKFunction(name = "type12")
+ public String Type12(
+ @SKFunctionInputAttribute
+ String x,
+ SKContext context) {
+ System.out.println("Running function type 12");
+ return "";
+ }
+
+ @DefineSKFunction(name = "type13")
+ public Mono Type13Async(
+ @SKFunctionInputAttribute
+ String x, SKContext context) {
+ return Mono.delay(Duration.ZERO)
+ .map(x2 -> {
+ System.out.println("Running function type 13");
+ return "";
+ });
+ }
+
+ @DefineSKFunction(name = "type14")
+ public Mono Type14Async(
+ @SKFunctionInputAttribute
+ String x, SKContext context) {
+ return Mono.delay(Duration.ZERO)
+ .ignoreElement()
+ .map(x2 -> {
+ System.out.println("Running function type 14");
+ return context;
+ });
+ }
+
+ @DefineSKFunction(name = "type15")
+ public Mono Type15Async(String x) {
+ return Mono.delay(Duration.ZERO)
+ .ignoreElement()
+ .doFinally(ignore -> System.out.println("Running function type 15"))
+ .then();
+ }
+
+ @DefineSKFunction(name = "type16")
+ public Mono Type16Async(SKContext context) {
+ return Mono.delay(Duration.ZERO)
+ .ignoreElement()
+ .doFinally(ignore -> System.out.println("Running function type 16"))
+ .then();
+ }
+
+ @DefineSKFunction(name = "type17")
+ public Mono Type17Async(String x, SKContext context) {
+ return Mono.delay(Duration.ZERO)
+ .ignoreElement()
+ .doFinally(ignore -> System.out.println("Running function type 17"))
+ .then();
+ }
+
+ @DefineSKFunction(name = "type18")
+ public Mono Type18Async() {
+ return Mono.delay(Duration.ZERO)
+ .ignoreElement()
+ .doFinally(ignore -> System.out.println("Running function type 18"))
+ .then();
+ }
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example12_SequentialPlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example12_SequentialPlanner.java
new file mode 100644
index 0000000000..735252a632
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example12_SequentialPlanner.java
@@ -0,0 +1,211 @@
+package com.microsoft.semantickernel.syntaxexamples;// Copyright (c) Microsoft. All rights reserved.
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Config;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.coreskills.TextSkill;
+import com.microsoft.semantickernel.memory.VolatileMemoryStore;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
+import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlannerRequestSettings;
+import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
+import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class Example12_SequentialPlanner {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Example12_SequentialPlanner.class);
+
+ public static void main(String[] args) throws IOException {
+ poetrySamplesAsync();
+ emailSamplesAsync();
+ bookSamplesAsync();
+ //MemorySampleAsync();
+ }
+
+ private static void poetrySamplesAsync() throws IOException {
+ System.out.println("======== Sequential Planner - Create and Execute Poetry Plan ========");
+ var kernel = initializeKernel();
+
+ kernel.importSkill(new TextSkill(), "TextSkill");
+
+ var planner = new SequentialPlanner(kernel, null, null);
+
+ var plan = planner.createPlanAsync("Write a poem about John Doe, then translate it into Italian, then convert it to uppercase.").block();
+
+ // Original plan:
+ // Goal: Write a poem about John Doe, then translate it into Italian.
+
+ // Steps:
+ // - WriterSkill.ShortPoem INPUT='John Doe is a friendly guy who likes to help others and enjoys reading books.' =>
+ // - WriterSkill.Translate language='Italian' INPUT='' =>
+
+ SKContext result = plan.invokeAsync().block();
+
+ System.out.println("Result:");
+ System.out.println(result.getResult());
+ }
+
+ public static class EmailSkill {
+ @DefineSKFunction(name = "SendEmail", description = "Given an e-mail and message body, send an email")
+ public void sendEmail(
+ @SKFunctionInputAttribute()
+ @SKFunctionParameters(description = "The body of the email message to send.", name = "input")
+ String input,
+ @SKFunctionParameters(description = "The email address to send email to.", name = "email_address")
+ String emailAddress
+ ) {
+ LOGGER.info("Emailing to " + emailAddress + "\n" + input);
+ }
+
+ @DefineSKFunction(name = "GetEmailAddressAsync", description = "Lookup an email address for a person given a name")
+ public String getEmailAddressAsync(
+ @SKFunctionInputAttribute()
+ @SKFunctionParameters(description = "The name of the person to email.", name = "input")
+ String input) {
+ return "fake@example.com";
+ }
+ }
+
+ private static void emailSamplesAsync() throws IOException {
+ System.out.println("======== Sequential Planner - Create and Execute Email Plan ========");
+ var kernel = initializeKernel();
+
+ kernel.importSkill(new EmailSkill(), "email");
+
+
+ SequentialPlanner planner = initPlanner(kernel, 1024);
+
+ var plan = planner.createPlanAsync("Summarize an input, translate to french, and e-mail to John Doe").block();
+
+ // Original plan:
+ // Goal: Summarize an input, translate to french, and e-mail to John Doe
+
+ // Steps:
+ // - SummarizeSkill.Summarize INPUT='' =>
+ // - WriterSkill.Translate language='French' INPUT='' => TRANSLATED_SUMMARY
+ // - email.GetEmailAddress INPUT='John Doe' => EMAIL_ADDRESS
+ // - email.SendEmail INPUT='$TRANSLATED_SUMMARY' email_address='$EMAIL_ADDRESS' =>
+
+ System.out.println("Original plan:");
+ System.out.println(plan.toPlanString());
+
+ var input =
+ "Once upon a time, in a faraway kingdom, there lived a kind and just king named Arjun. " +
+ "He ruled over his kingdom with fairness and compassion, earning him the love and admiration of his people. " +
+ "However, the kingdom was plagued by a terrible dragon that lived in the nearby mountains and terrorized the nearby villages, " +
+ "burning their crops and homes. The king had tried everything to defeat the dragon, but to no avail. " +
+ "One day, a young woman named Mira approached the king and offered to help defeat the dragon. She was a skilled archer " +
+ "and claimed that she had a plan to defeat the dragon once and for all. The king was skeptical, but desperate for a solution, " +
+ "so he agreed to let her try. Mira set out for the dragon's lair and, with the help of her trusty bow and arrow, " +
+ "she was able to strike the dragon with a single shot through its heart, killing it instantly. The people rejoiced " +
+ "and the kingdom was at peace once again. The king was so grateful to Mira that he asked her to marry him and she agreed. " +
+ "They ruled the kingdom together, ruling with fairness and compassion, just as Arjun had done before. They lived " +
+ "happily ever after, with the people of the kingdom remembering Mira as the brave young woman who saved them from the dragon.";
+
+ System.out.println(plan.invokeAsync(input).block());
+ }
+
+ private static void bookSamplesAsync() throws IOException {
+ System.out.println("======== Sequential Planner - Create and Execute Book Creation Plan ========");
+ var kernel = initializeKernel();
+
+ SequentialPlanner planner = initPlanner(kernel, 1024);
+
+ var plan = planner.createPlanAsync("Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'").block();
+
+ // Original plan:
+ // Goal: Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'
+
+ // Steps:
+ // - WriterSkill.NovelOutline chapterCount='3' INPUT='A group of kids in a club called 'The Thinking Caps' that solve mysteries and puzzles using their creativity and logic.' endMarker='' => OUTLINE
+ // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='0' => CHAPTER_1_SYNOPSIS
+ // - WriterSkill.NovelChapter chapterIndex='1' previousChapter='' INPUT='$CHAPTER_1_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_1
+ // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='1' => CHAPTER_2_SYNOPSIS
+ // - WriterSkill.NovelChapter chapterIndex='2' previousChapter='$CHAPTER_1_SYNOPSIS' INPUT='$CHAPTER_2_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_2
+ // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='2' => CHAPTER_3_SYNOPSIS
+ // - WriterSkill.NovelChapter chapterIndex='3' previousChapter='$CHAPTER_2_SYNOPSIS' INPUT='$CHAPTER_3_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_3
+ System.out.println(plan.invokeAsync().block().getResult());
+ }
+
+ /*
+ TODO
+ private static void memorySampleAsync() throws IOException {
+ System.out.println("======== Sequential Planner - Create and Execute Plan using Memory ========");
+ var kernel = initializeKernel();
+
+ SequentialPlanner planner = initPlanner(kernel, 1024);
+
+ kernel.importSkillsFromDirectory("samples/skills",
+ "CalendarSkill",
+ "ChatSkill",
+ "ChildrensBookSkill",
+ "ClassificationSkill",
+ "CodingSkill",
+ "FunSkill",
+ "IntentDetectionSkill",
+ "MiscSkill",
+ "QASkill");
+
+ kernel.importSkill(new EmailSkill(), "email");
+ kernel.importSkill(new StaticTextSkill(), "statictext");
+ kernel.importSkill(new TextSkill(), "text");
+ kernel.importSkill(new Microsoft.SemanticKernel.CoreSkills.TextSkill(), "coretext");
+
+ var goal = "Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'";
+
+ var planner = new SequentialPlanner(kernel, new SequentialPlannerConfig {
+ RelevancyThreshold =0.78
+ });
+
+ var plan = await planner.CreatePlanAsync(goal);
+
+ System.out.println("Original plan:");
+ System.out.println(plan.ToPlanString());
+ }
+
+ */
+
+ private static Kernel initializeKernel() throws IOException {
+ OpenAIAsyncClient client = Config.getClient();
+ var kernel = SKBuilders.kernel()
+ .setKernelConfig(SKBuilders
+ .kernelConfig()
+ .addTextCompletionService("text-davinci-003", kernel1 -> SKBuilders.textCompletionService()
+ .build(client, "text-davinci-003"))
+ .build())
+ .withMemory(SKBuilders
+ .semanticTextMemory()
+ .setEmbeddingGenerator(
+ SKBuilders.textEmbeddingGenerationService().build(client, "text-davinci-003")
+ )
+ .setStorage(new VolatileMemoryStore())
+ .build())
+ .build();
+
+
+ // Load additional skills to enable planner to do non-trivial asks.
+ kernel.importSkillFromDirectory("SummarizeSkill", "samples/skills", "SummarizeSkill");
+ kernel.importSkillFromDirectory("WriterSkill", "samples/skills", "WriterSkill");
+ kernel.importSkillFromDirectory("MiscSkill", "samples/skills", "MiscSkill");
+
+ return kernel;
+ }
+
+ private static SequentialPlanner initPlanner(Kernel kernel, int maxTokens) {
+ return new SequentialPlanner(kernel, new SequentialPlannerRequestSettings(
+ null,
+ 100,
+ Set.of(),
+ Set.of(),
+ Set.of(),
+ maxTokens
+ ), null);
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example13_ConversationSummarySkill.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example13_ConversationSummarySkill.java
index 2b4476c8a9..478d72bb86 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example13_ConversationSummarySkill.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example13_ConversationSummarySkill.java
@@ -7,9 +7,9 @@ import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.coreskills.ConversationSummarySkill;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import reactor.core.publisher.Mono;
@@ -127,7 +127,7 @@ public class Example13_ConversationSummarySkill {
""".stripIndent();
public static void main(String[] args) throws IOException {
- Config.ClientType clientType = Config.ClientType.OPEN_AI;
+ Config.ClientType clientType = Config.ClientType.AZURE_OPEN_AI;
conversationSummarySkillAsync(clientType);
getConversationActionItemsAsync(clientType);
@@ -141,7 +141,7 @@ public class Example13_ConversationSummarySkill {
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
- Mono summary = conversationSummarySkill
+ Mono summary = conversationSummarySkill
.getFunction("SummarizeConversation", SKFunction.class)
.invokeAsync(ChatTranscript);
@@ -157,7 +157,7 @@ public class Example13_ConversationSummarySkill {
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
- Mono summary = conversationSummarySkill
+ Mono summary = conversationSummarySkill
.getFunction("GetConversationActionItems", SKFunction.class)
.invokeAsync(ChatTranscript);
@@ -171,7 +171,7 @@ public class Example13_ConversationSummarySkill {
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
- Mono summary = conversationSummarySkill
+ Mono summary = conversationSummarySkill
.getFunction("GetConversationTopics", SKFunction.class)
.invokeAsync(ChatTranscript);
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example17_ChatGPT.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example17_ChatGPT.java
index ece04a99b8..a851fb64b3 100644
--- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example17_ChatGPT.java
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example17_ChatGPT.java
@@ -19,7 +19,7 @@ import java.io.IOException;
public class Example17_ChatGPT {
public static void main(String[] args) throws IOException {
- OpenAIAsyncClient client = Config.ClientType.OPEN_AI.getClient();
+ OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
KernelConfig kernelConfig = SKBuilders.kernelConfig()
.addChatCompletionService(
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example28_ActionPlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example28_ActionPlanner.java
new file mode 100644
index 0000000000..533a6b0912
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/Example28_ActionPlanner.java
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.syntaxexamples;
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.Config;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.coreskills.TextSkill;
+import com.microsoft.semantickernel.planner.actionplanner.ActionPlanner;
+
+import java.io.IOException;
+
+public class Example28_ActionPlanner {
+ public static void main(String[] args) throws IOException {
+ OpenAIAsyncClient client = Config.ClientType.AZURE_OPEN_AI.getClient();
+
+ System.out.println("======== Action Planner ========");
+
+ var kernel = SKBuilders.kernel()
+ .setKernelConfig(SKBuilders
+ .kernelConfig()
+ .addTextCompletionService("text-davinci-002", kernel1 -> SKBuilders.textCompletionService()
+ .build(client, "text-davinci-002"))
+ .build())
+ .build();
+
+ kernel.importSkillFromDirectory("SummarizeSkill", "./samples/skills", "SummarizeSkill");
+
+ kernel.importSkillFromDirectory("WriterSkill", "./samples/skills", "WriterSkill");
+
+ kernel.importSkill(new TextSkill(), "TextSkill");
+
+ // Create an instance of ActionPlanner.
+ // The ActionPlanner takes one goal and returns a single function to execute.
+ var planner = new ActionPlanner(kernel, null);
+
+ // We're going to ask the planner to find a function to achieve this goal.
+ var goal = "Write a poem about Cleopatra.";
+
+ // The planner returns a plan, consisting of a single function
+ // to execute and achieve the goal requested.
+ var plan = planner.createPlanAsync(goal).block();
+
+ // Show the result, which should match the given goal
+ System.out.println(plan.getName());
+
+ System.out.println(plan.invokeAsync(goal).block().getResult());
+
+ /* Output:
+ *
+ * Cleopatra was a queen
+ * But she didn't act like one
+ * She was more like a teen
+
+ * She was always on the scene
+ * And she loved to be seen
+ * But she didn't have a queenly bone in her body
+ */
+ }
+}
diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/RunAll.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/RunAll.java
new file mode 100644
index 0000000000..1700dd8255
--- /dev/null
+++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/syntaxexamples/RunAll.java
@@ -0,0 +1,32 @@
+package com.microsoft.semantickernel.syntaxexamples;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class RunAll {
+ public interface MainMethod {
+ void run(String[] args) throws Exception;
+ }
+
+ public static void main(String[] args) {
+ List mains = Arrays.asList(
+ Example01_NativeFunctions::main,
+ Example02_Pipeline::main,
+ Example06_TemplateLanguage::main,
+ Example08_RetryHandler::main,
+ Example12_SequentialPlanner::main,
+ Example13_ConversationSummarySkill::main,
+ Example14_SemanticMemory::main,
+ Example17_ChatGPT::main,
+ Example28_ActionPlanner::main
+ );
+
+ mains.forEach(mainMethod -> {
+ try {
+ mainMethod.run(args);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+}
diff --git a/java/samples/sample-code/src/main/resources/log4j2.xml b/java/samples/sample-code/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..dfe2ccca7e
--- /dev/null
+++ b/java/samples/sample-code/src/main/resources/log4j2.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java/samples/semantickernel-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java b/java/samples/semantickernel-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java
index 1778e0c8d5..d6838ae511 100644
--- a/java/samples/semantickernel-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java
+++ b/java/samples/semantickernel-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java
@@ -98,8 +98,6 @@ public class SemanticKernelModule extends AbstractModule {
if (embeddingsGenerationServiceId != null) {
OpenAITextEmbeddingGeneration embeddings = new OpenAITextEmbeddingGeneration(client,
embeddingsGenerationServiceId);
- kernelConfig.addTextEmbeddingsGenerationService(
- embeddingsGenerationServiceId, kernel -> embeddings);
bind(new TypeLiteral>() {
}).toInstance(embeddings);
}
diff --git a/java/samples/semantickernel-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java b/java/samples/semantickernel-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java
index 41a236f999..33a96b8d26 100644
--- a/java/samples/semantickernel-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java
+++ b/java/samples/semantickernel-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java
@@ -4,8 +4,8 @@ package com.microsoft.semantickernel.guice;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import java.util.ArrayList;
@@ -61,13 +61,13 @@ public class CompletionFunctionExample {
+ "poetry—'bearing a pleasant gift', for example, alludes to the use of that\n"
+ "phrase throughout the Iliad and Odyssey.[a][2];";
- CompletionSKContext summary =
+ SKContext summary =
completionFunctionFactory
.createFunction(
prompt,
"summarize",
new PromptTemplateConfig.CompletionConfig(
- 0.2, 0.5, 0, 0, 2000, new ArrayList<>()))
+ 0.2, 0.5, 0, 0, 2000))
.invokeAsync(text)
.block();
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
index 2fa469bc5b..efa60eb10f 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
@@ -2,26 +2,20 @@
package com.microsoft.semantickernel;
import com.microsoft.semantickernel.builders.BuildersSingleton;
-import com.microsoft.semantickernel.exceptions.SkillsNotFoundException;
import com.microsoft.semantickernel.memory.MemoryStore;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
-import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
-import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
-import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import reactor.core.publisher.Mono;
-import java.util.Map;
-
import javax.annotation.Nullable;
/** Interface for the semantic kernel. */
-public interface Kernel {
+public interface Kernel extends SkillExecutor {
/**
* Settings required to execute functions, including details about AI dependencies, e.g.
@@ -49,7 +43,7 @@ public interface Kernel {
* @param pipeline List of functions
* @return Result of the function composition
*/
- Mono> runAsync(SKFunction, ?>... pipeline);
+ Mono runAsync(SKFunction>... pipeline);
/**
* Run a pipeline composed of synchronous and asynchronous functions.
@@ -58,7 +52,7 @@ public interface Kernel {
* @param pipeline List of functions
* @return Result of the function composition
*/
- Mono> runAsync(String input, SKFunction, ?>... pipeline);
+ Mono runAsync(String input, SKFunction>... pipeline);
/**
* Run a pipeline composed of synchronous and asynchronous functions.
@@ -67,42 +61,7 @@ public interface Kernel {
* @param pipeline List of functions
* @return Result of the function composition
*/
- Mono> runAsync(ContextVariables variables, SKFunction, ?>... pipeline);
-
- /**
- * Import a set of skills
- *
- * @param skillName
- * @param skills
- * @return
- * @throws SkillsNotFoundException
- */
- ReadOnlyFunctionCollection importSkill(
- String skillName, Map skills)
- throws SkillsNotFoundException;
-
- /**
- * Get function collection with the skill name
- *
- * @param skillName
- * @return
- * @throws SkillsNotFoundException
- */
- ReadOnlyFunctionCollection getSkill(String skillName) throws SkillsNotFoundException;
-
- /**
- * Imports the native functions annotated on the given object as a skill.
- *
- * @param nativeSkill
- * @param skillName
- * @return
- */
- ReadOnlyFunctionCollection importSkill(Object nativeSkill, @Nullable String skillName);
-
- /**
- * @return Reference to the read-only skill collection containing all the imported functions
- */
- ReadOnlySkillCollection getSkills();
+ Mono runAsync(ContextVariables variables, SKFunction>... pipeline);
CompletionSKFunction.Builder getSemanticFunctionBuilder();
@@ -110,12 +69,11 @@ public interface Kernel {
T getService(@Nullable String name, Class clazz) throws KernelException;
/** Registers a semantic functon on this kernel */
- <
- RequestConfiguration,
- ContextType extends SKContext,
- FunctionType extends SKFunction>
+ >
FunctionType registerSemanticFunction(FunctionType semanticFunctionDefinition);
+ SKFunction getFunction(String skill, String function);
+
// > T createNewContext();
class Builder {
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java
index 31a95ba8c1..39a4663d69 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java
@@ -3,17 +3,13 @@ package com.microsoft.semantickernel;
import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
-import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
-import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.function.Function;
+import javax.annotation.Nullable;
+
public final class KernelConfig {
private static final String DEFAULT_SERVICE_ID = "__SK_DEFAULT";
@@ -22,19 +18,16 @@ public final class KernelConfig {
private final Map>>
textEmbeddingGenerationServices;
- private final ArrayList> skills;
public KernelConfig(
Map> textCompletionServices,
Map>>
textEmbeddingGenerationServices,
- Map> chatCompletionServices,
- List> skills) {
+ Map> chatCompletionServices) {
this.textCompletionServices = new HashMap<>();
this.textCompletionServices.putAll(textCompletionServices);
this.textEmbeddingGenerationServices = new HashMap<>(textEmbeddingGenerationServices);
this.chatCompletionServices = new HashMap<>(chatCompletionServices);
- this.skills = new ArrayList<>(skills);
}
@Nullable
@@ -42,10 +35,6 @@ public final class KernelConfig {
return textCompletionServices.get(serviceId);
}
- public List> getSkills() {
- return Collections.unmodifiableList(skills);
- }
-
public Function getTextCompletionServiceOrDefault(
@Nullable String serviceId) {
if (serviceId == null) {
@@ -55,7 +44,10 @@ public final class KernelConfig {
if (!this.textCompletionServices.containsKey(serviceId)) {
throw new KernelException(
KernelException.ErrorCodes.ServiceNotFound,
- "A text completion service id '" + serviceId + "' doesn't exist");
+ "A text completion service id '"
+ + serviceId
+ + "' doesn't exist. This likely means a text completion service was not"
+ + " registered on this kernel.");
}
return this.textCompletionServices.get(serviceId);
@@ -76,8 +68,8 @@ public final class KernelConfig {
return this.chatCompletionServices.get(serviceId);
}
- public Function> getTextEmbeddingGenerationServiceOrDefault(
- @Nullable String serviceId) {
+ public Function>
+ getTextEmbeddingGenerationServiceOrDefault(@Nullable String serviceId) {
if (serviceId == null) {
serviceId = DEFAULT_SERVICE_ID;
@@ -96,18 +88,11 @@ public final class KernelConfig {
private Map> textCompletionServices =
new HashMap<>();
- private List> skillBuilders = new ArrayList<>();
-
private Map>>
textEmbeddingGenerationServices = new HashMap<>();
private final Map> chatCompletionServices =
new HashMap<>();
- public Builder addSkill(SKFunction, ?> functionDefinition) {
- skillBuilders.add(functionDefinition);
- return this;
- }
-
// TODO, is there a need for this to be a factory?
public Builder addTextCompletionService(
String serviceId, Function serviceFactory) {
@@ -160,7 +145,8 @@ public final class KernelConfig {
*/
public Builder addChatCompletionService(
@Nullable String serviceId, Function serviceFactory) {
- if (serviceId != null && serviceId.toUpperCase().equals(DEFAULT_SERVICE_ID)) {
+ if (serviceId != null
+ && serviceId.toUpperCase(Locale.ROOT).equals(DEFAULT_SERVICE_ID)) {
String msg =
"The service id '"
+ serviceId
@@ -185,8 +171,7 @@ public final class KernelConfig {
return new KernelConfig(
Collections.unmodifiableMap(textCompletionServices),
textEmbeddingGenerationServices,
- chatCompletionServices,
- skillBuilders);
+ chatCompletionServices);
}
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java
new file mode 100644
index 0000000000..1b83d0785a
--- /dev/null
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel;
+
+import com.microsoft.semantickernel.exceptions.SkillsNotFoundException;
+import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
+import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
+import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
+
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+public interface SkillExecutor {
+
+ /**
+ * Import a set of skills
+ *
+ * @param skillName
+ * @param skills
+ * @return
+ * @throws SkillsNotFoundException
+ */
+ ReadOnlyFunctionCollection importSkill(
+ String skillName, Map skills)
+ throws SkillsNotFoundException;
+
+ /**
+ * Get function collection with the skill name
+ *
+ * @param skillName
+ * @return
+ * @throws SkillsNotFoundException
+ */
+ ReadOnlyFunctionCollection getSkill(String skillName) throws SkillsNotFoundException;
+
+ /**
+ * Imports the native functions annotated on the given object as a skill.
+ *
+ * @param skillName
+ * @return
+ */
+ ReadOnlyFunctionCollection importSkillFromDirectory(
+ String skillName, String parentDirectory, String skillDirectoryName);
+
+ /** Imports the native functions annotated on the given object as a skill. */
+ void importSkillsFromDirectory(String parentDirectory, String... skillNames);
+
+ /**
+ * Imports the native functions annotated on the given object as a skill. Assumes that the
+ * directory that contains the skill is the same as skillName
+ *
+ * @param skillName
+ * @return
+ */
+ ReadOnlyFunctionCollection importSkillFromDirectory(String skillName, String parentDirectory);
+
+ /**
+ * Imports the native functions annotated on the given object as a skill.
+ *
+ * @param nativeSkill
+ * @param skillName
+ * @return
+ */
+ ReadOnlyFunctionCollection importSkill(Object nativeSkill, @Nullable String skillName);
+
+ /**
+ * @return Reference to the read-only skill collection containing all the imported functions
+ */
+ ReadOnlySkillCollection getSkills();
+}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java
index 2ff77e5a35..f03a61e481 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java
@@ -1,8 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel;
+import javax.annotation.Nullable;
+
public class Verify {
public static void notNull(Object object) {
assert object != null;
}
+
+ public static boolean isNullOrEmpty(@Nullable String s) {
+ return s == null || s.isEmpty();
+ }
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java
index 226ef8847a..c4e2a5ccf1 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java
@@ -11,14 +11,32 @@ public class AIException extends SKException {
@Nonnull private final ErrorCodes errorCode;
+ /**
+ * Initializes a new instance of the {@link AIException} class.
+ *
+ * @param error The error code.
+ */
public AIException(@Nonnull ErrorCodes error) {
this(error, null, null);
}
+ /**
+ * Initializes a new instance of the {@link AIException} class.
+ *
+ * @param errorCode The error code.
+ * @param message The message.
+ */
public AIException(@Nonnull ErrorCodes errorCode, @Nullable String message) {
this(errorCode, message, null);
}
+ /**
+ * Initializes a new instance of the {@link AIException} class.
+ *
+ * @param errorCode The error code.
+ * @param message The message.
+ * @param innerException The cause of the exception.
+ */
public AIException(
@Nonnull ErrorCodes errorCode,
@Nullable String message,
@@ -27,19 +45,21 @@ public class AIException extends SKException {
this.errorCode = errorCode;
}
+ /**
+ * Gets the error code.
+ *
+ * @return The error code.
+ */
public ErrorCodes getErrorCode() {
return errorCode;
}
- /* Translate the error code into a default message */
+ /** Translate the error code into a default message */
private static String getDefaultMessage(
@Nonnull ErrorCodes errorCode, @Nullable String message) {
return String.format("%s: %s", errorCode.getMessage(), message);
}
- ///
- /// Possible error codes for exceptions
- ///
public enum ErrorCodes {
UnknownError("Unknown error"),
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java
index 05c0e78710..5abbd25d3b 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java
@@ -19,14 +19,6 @@ public class Embedding {
private final List vector;
- // ///
- // /// An empty instance.
- // ///
- // [SuppressMessage("Design", "CA1000:Do not declare static members on generic types",
- // Justification = "Static empty struct instance.")]
- // public static Embedding Empty { get; } = new
- // Embedding(Array.Empty());
-
private static final Embedding EMPTY =
new Embedding(Collections.unmodifiableList(new ArrayList<>()));
@@ -43,6 +35,7 @@ public class Embedding {
// /// Type is
// unsupported.
// /// A null vector is passed in.
+
public Embedding() {
this.vector = Collections.emptyList();
}
@@ -62,7 +55,7 @@ public class Embedding {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof Embedding)) return false;
Embedding> embedding = (Embedding>) o;
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java
index 749d5d6178..8232a9a238 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java
@@ -16,7 +16,12 @@ import com.microsoft.semantickernel.textcompletion.TextCompletion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
/** Enum singleton that service loads builder implementations */
+@SuppressWarnings("ImmutableEnumChecker")
public enum BuildersSingleton {
INST;
@@ -27,94 +32,46 @@ public enum BuildersSingleton {
"com.microsoft.semantickernel.DefaultKernel$Builder";
private static final String FALLBACK_TEXT_COMPLETION_BUILDER_CLASS =
"com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion$Builder";
-
private static final String FALLBACK_TEXT_EMBEDDING_GENERATION_BUILDER_CLASS =
"com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration$Builder";
private static final String FALLBACK_SKILL_COLLECTION_BUILDER_CLASS =
- "com.microsoft.semantickernel.skilldefinition.DefaultCollection$Builder";
-
+ "com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection$Builder";
private static final String FALLBACK_PROMPT_TEMPLATE_BUILDER_CLASS =
"com.microsoft.semantickernel.semanticfunctions.DefaultPromptTemplate$Builder";
-
private static final String FALLBACK_VARIABLE_BUILDER_CLASS =
"com.microsoft.semantickernel.orchestration.DefaultContextVariables$Builder";
-
private static final String FALLBACK_CONTEXT_BUILDER_CLASS =
- "com.microsoft.semantickernel.orchestration.DefaultSemanticSKContext$Builder";
+ "com.microsoft.semantickernel.orchestration.DefaultSKContext$Builder";
private static final String FALLBACK_PROMPT_TEMPLATE_ENGINE_BUILDER_CLASS =
"com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine$Builder";
private static final String FALLBACK_SEMANTIC_TEXT_MEMORY_CLASS =
"com.microsoft.semantickernel.memory.DefaultSemanticTextMemory$Builder";
private static final String FALLBACK_CHAT_COMPLETION_BUILDER_CLASS =
"com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatCompletion$Builder";
-
private static final String FALLBACK_MEMORY_STORE_BUILDER_CLASS =
"com.microsoft.semantickernel.memory.VolatileMemoryStore$Builder";
- private final FunctionBuilders functionBuilders;
- private final Kernel.InternalBuilder kernelBuilder;
- private final TextCompletion.Builder textCompletionBuilder;
- private final EmbeddingGeneration.Builder textEmbeddingGenerationBuilder;
- private final ReadOnlySkillCollection.Builder readOnlySkillCollection;
- private final PromptTemplate.Builder promptTemplate;
- private final ContextVariables.Builder variables;
- private final SKContext.Builder context;
- private final PromptTemplateEngine.Builder promptTemplateEngine;
- private final ChatCompletion.Builder chatCompletion;
- private final SemanticTextMemory.Builder semanticTextMemoryBuilder;
- private final MemoryStore.Builder memoryStoreBuilder;
+ private final Map builders = new HashMap<>();
BuildersSingleton() {
try {
- functionBuilders =
- ServiceLoadUtil.findServiceLoader(
- FunctionBuilders.class, FALLBACK_FUNCTION_BUILDER_CLASS);
-
- kernelBuilder =
- ServiceLoadUtil.findServiceLoader(
- Kernel.InternalBuilder.class, FALLBACK_KERNEL_BUILDER_CLASS);
-
- textCompletionBuilder =
- ServiceLoadUtil.findServiceLoader(
- TextCompletion.Builder.class, FALLBACK_TEXT_COMPLETION_BUILDER_CLASS);
-
- textEmbeddingGenerationBuilder =
- ServiceLoadUtil.findServiceLoader(
- EmbeddingGeneration.Builder.class,
- FALLBACK_TEXT_EMBEDDING_GENERATION_BUILDER_CLASS);
-
- readOnlySkillCollection =
- ServiceLoadUtil.findServiceLoader(
- ReadOnlySkillCollection.Builder.class,
- FALLBACK_SKILL_COLLECTION_BUILDER_CLASS);
-
- promptTemplate =
- ServiceLoadUtil.findServiceLoader(
- PromptTemplate.Builder.class, FALLBACK_PROMPT_TEMPLATE_BUILDER_CLASS);
-
- variables =
- ServiceLoadUtil.findServiceLoader(
- ContextVariables.Builder.class, FALLBACK_VARIABLE_BUILDER_CLASS);
- semanticTextMemoryBuilder =
- ServiceLoadUtil.findServiceLoader(
- SemanticTextMemory.Builder.class, FALLBACK_SEMANTIC_TEXT_MEMORY_CLASS);
-
- context =
- ServiceLoadUtil.findServiceLoader(
- SKContext.Builder.class, FALLBACK_CONTEXT_BUILDER_CLASS);
-
- promptTemplateEngine =
- ServiceLoadUtil.findServiceLoader(
- PromptTemplateEngine.Builder.class,
- FALLBACK_PROMPT_TEMPLATE_ENGINE_BUILDER_CLASS);
-
- chatCompletion =
- ServiceLoadUtil.findServiceLoader(
- ChatCompletion.Builder.class, FALLBACK_CHAT_COMPLETION_BUILDER_CLASS);
-
- memoryStoreBuilder =
- ServiceLoadUtil.findServiceLoader(
- MemoryStore.Builder.class, FALLBACK_MEMORY_STORE_BUILDER_CLASS);
+ registerBuilder(FunctionBuilders.class, FALLBACK_FUNCTION_BUILDER_CLASS);
+ registerBuilder(Kernel.InternalBuilder.class, FALLBACK_KERNEL_BUILDER_CLASS);
+ registerBuilder(TextCompletion.Builder.class, FALLBACK_TEXT_COMPLETION_BUILDER_CLASS);
+ registerBuilder(
+ EmbeddingGeneration.Builder.class,
+ FALLBACK_TEXT_EMBEDDING_GENERATION_BUILDER_CLASS);
+ registerBuilder(
+ ReadOnlySkillCollection.Builder.class, FALLBACK_SKILL_COLLECTION_BUILDER_CLASS);
+ registerBuilder(PromptTemplate.Builder.class, FALLBACK_PROMPT_TEMPLATE_BUILDER_CLASS);
+ registerBuilder(ContextVariables.Builder.class, FALLBACK_VARIABLE_BUILDER_CLASS);
+ registerBuilder(SemanticTextMemory.Builder.class, FALLBACK_SEMANTIC_TEXT_MEMORY_CLASS);
+ registerBuilder(SKContext.Builder.class, FALLBACK_CONTEXT_BUILDER_CLASS);
+ registerBuilder(
+ PromptTemplateEngine.Builder.class,
+ FALLBACK_PROMPT_TEMPLATE_ENGINE_BUILDER_CLASS);
+ registerBuilder(ChatCompletion.Builder.class, FALLBACK_CHAT_COMPLETION_BUILDER_CLASS);
+ registerBuilder(MemoryStore.Builder.class, FALLBACK_MEMORY_STORE_BUILDER_CLASS);
} catch (Throwable e) {
Logger LOGGER = LoggerFactory.getLogger(BuildersSingleton.class);
@@ -141,51 +98,59 @@ public enum BuildersSingleton {
}
}
+ private void registerBuilder(Class> clazz, String fallbackClassName) {
+ builders.put(clazz, ServiceLoadUtil.findServiceLoader(clazz, fallbackClassName));
+ }
+
+ private T getInstance(Class clazz) {
+ return (T) builders.get(clazz).get();
+ }
+
public FunctionBuilders getFunctionBuilders() {
- return functionBuilders;
+ return getInstance(FunctionBuilders.class);
}
public Kernel.InternalBuilder getKernelBuilder() {
- return kernelBuilder;
+ return getInstance(Kernel.InternalBuilder.class);
}
public TextCompletion.Builder getTextCompletionBuilder() {
- return textCompletionBuilder;
+ return getInstance(TextCompletion.Builder.class);
}
public EmbeddingGeneration.Builder getTextEmbeddingGenerationBuilder() {
- return textEmbeddingGenerationBuilder;
+ return getInstance(EmbeddingGeneration.Builder.class);
}
public ReadOnlySkillCollection.Builder getReadOnlySkillCollection() {
- return readOnlySkillCollection;
+ return getInstance(ReadOnlySkillCollection.Builder.class);
}
public PromptTemplate.Builder getPromptTemplateBuilder() {
- return promptTemplate;
+ return getInstance(PromptTemplate.Builder.class);
}
public PromptTemplateEngine.Builder getPromptTemplateEngineBuilder() {
- return promptTemplateEngine;
+ return getInstance(PromptTemplateEngine.Builder.class);
}
public ContextVariables.Builder variables() {
- return variables;
+ return getInstance(ContextVariables.Builder.class);
}
public SKContext.Builder context() {
- return context;
+ return getInstance(SKContext.Builder.class);
}
public SemanticTextMemory.Builder getSemanticTextMemoryBuilder() {
- return semanticTextMemoryBuilder;
+ return getInstance(SemanticTextMemory.Builder.class);
}
public ChatCompletion.Builder getChatCompletion() {
- return chatCompletion;
+ return getInstance(ChatCompletion.Builder.class);
}
public MemoryStore.Builder getMemoryStoreBuilder() {
- return memoryStoreBuilder;
+ return getInstance(MemoryStore.Builder.class);
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/FunctionBuilders.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/FunctionBuilders.java
index 0e8be1aacd..a77bcf1ee6 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/FunctionBuilders.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/FunctionBuilders.java
@@ -4,18 +4,12 @@ package com.microsoft.semantickernel.builders;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
-import javax.annotation.Nullable;
-
/** Provides various builders for completion functions */
public interface FunctionBuilders {
- static CompletionSKFunction.Builder getCompletionBuilder() {
- return getCompletionBuilder(null);
- }
-
- static CompletionSKFunction.Builder getCompletionBuilder(@Nullable Kernel kernel) {
+ static CompletionSKFunction.Builder getCompletionBuilder(Kernel kernel) {
return BuildersSingleton.INST.getFunctionBuilders().completionBuilders(kernel);
}
- CompletionSKFunction.Builder completionBuilders(@Nullable Kernel kernel);
+ CompletionSKFunction.Builder completionBuilders(Kernel kernel);
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SKBuilders.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SKBuilders.java
index 95c9c17853..7a0ff4f4cf 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SKBuilders.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SKBuilders.java
@@ -16,23 +16,18 @@ import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
-import javax.annotation.Nullable;
-
public class SKBuilders {
// Prevent creating object
private SKBuilders() {}
- public static CompletionSKFunction.Builder completionFunctions() {
- return completionFunctions(null);
- }
-
/**
* A CompletionSKFunction builder, the created function will be registered on the kernel
* provided
*
* @param kernel The kernel to register the function on
+ * @return a function builder
*/
- public static CompletionSKFunction.Builder completionFunctions(@Nullable Kernel kernel) {
+ public static CompletionSKFunction.Builder completionFunctions(Kernel kernel) {
return FunctionBuilders.getCompletionBuilder(kernel);
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java
index 72c1a09687..3113482753 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java
@@ -4,21 +4,26 @@ package com.microsoft.semantickernel.builders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
+import java.util.function.Supplier;
public class ServiceLoadUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceLoadUtil.class);
private ServiceLoadUtil() {}
- public static T findServiceLoader(Class clazz, String alternativeClassName) {
+ public static Supplier findServiceLoader(Class clazz, String alternativeClassName) {
List services = findAllServiceLoaders(clazz);
+
+ T impl = null;
+
if (services.size() > 0) {
- return services.get(0);
+ impl = services.get(0);
}
try {
@@ -26,7 +31,7 @@ public class ServiceLoadUtil {
Object instance =
Class.forName(alternativeClassName).getDeclaredConstructor().newInstance();
if (clazz.isInstance(instance)) {
- return (T) instance;
+ impl = (T) instance;
}
} catch (ClassNotFoundException
| InvocationTargetException
@@ -37,7 +42,34 @@ public class ServiceLoadUtil {
LOGGER.error("Unable to load service " + clazz.getName() + " ", e);
}
- throw new RuntimeException("Service not found: " + clazz.getName());
+ if (impl == null) {
+ throw new RuntimeException("Service not found: " + clazz.getName());
+ }
+
+ try {
+ Constructor> constructor = impl.getClass().getConstructor();
+
+ // Test that we can construct the builder
+ if (!clazz.isInstance(constructor.newInstance())) {
+ throw new RuntimeException(
+ "Builder creates instance of the wrong type: " + clazz.getName());
+ }
+
+ return () -> {
+ try {
+ return (T) constructor.newInstance();
+ } catch (InstantiationException
+ | IllegalAccessException
+ | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(
+ "Builder requires a no args constructor: " + clazz.getName());
+ } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException("Builder is of wrong type: " + clazz.getName());
+ }
}
static List findAllServiceLoaders(Class clazz) {
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java
index c4e3348f7b..a125c38185 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java
@@ -2,10 +2,12 @@
package com.microsoft.semantickernel.extensions;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.semantickernel.KernelException;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
+import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -14,7 +16,6 @@ import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -24,7 +25,9 @@ public class KernelExtensions {
private KernelExtensions() {}
public static Map importSemanticSkillFromDirectory(
- String parentDirectory, String skillDirectoryName) {
+ String parentDirectory,
+ String skillDirectoryName,
+ PromptTemplateEngine promptTemplateEngine) {
String CONFIG_FILE = "config.json";
String PROMPT_FILE = "skprompt.txt";
@@ -35,7 +38,9 @@ public class KernelExtensions {
File[] files = skillDir.listFiles();
if (files == null) {
- return Collections.unmodifiableMap(new HashMap<>());
+ throw new KernelException(
+ KernelException.ErrorCodes.FunctionNotAvailable,
+ "No Skills found in directory " + skillDir.getAbsolutePath());
}
HashMap skills = new HashMap<>();
@@ -64,15 +69,17 @@ public class KernelExtensions {
// config.ToJson());
// Load prompt template
- PromptTemplate template =
- SKBuilders.promptTemplate()
- .build(
- new String(
- Files.readAllBytes(promptPath.toPath()),
- Charset.defaultCharset()),
- config);
+ String template =
+ new String(
+ Files.readAllBytes(promptPath.toPath()), Charset.defaultCharset());
- skills.put(dir.getName(), new SemanticFunctionConfig(config, template));
+ PromptTemplate promptTemplate =
+ SKBuilders.promptTemplate()
+ .withPromptTemplate(template)
+ .withPromptTemplateConfig(config)
+ .build(promptTemplateEngine);
+
+ skills.put(dir.getName(), new SemanticFunctionConfig(config, promptTemplate));
} catch (IOException e) {
LOGGER.error("Failed to read file", e);
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java
index dead651d72..756e94d626 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java
@@ -143,7 +143,7 @@ public class MemoryRecord extends DataEntryBase {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof MemoryRecord)) return false;
MemoryRecord that = (MemoryRecord) o;
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java
index 3fcb26073a..dac959bf2b 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java
@@ -97,7 +97,7 @@ public class MemoryRecordMetadata {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof MemoryRecordMetadata)) return false;
MemoryRecordMetadata that = (MemoryRecordMetadata) o;
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java
index 05cca76c6a..eaa2f1c2c8 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java
@@ -8,7 +8,6 @@ import reactor.core.publisher.Mono;
import java.util.List;
import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** An interface for semantic memory that creates and recalls memories associated with text. */
@@ -28,9 +27,9 @@ public interface SemanticTextMemory {
* @return Unique identifier of the saved memory record.
*/
public Mono saveInformationAsync(
- @Nonnull String collection,
- @Nonnull String text,
- @Nonnull String externalId,
+ String collection,
+ String text,
+ String externalId,
@Nullable String description,
@Nullable String additionalMetadata);
@@ -48,10 +47,10 @@ public interface SemanticTextMemory {
* @return Unique identifier of the saved memory record.
*/
public Mono saveReferenceAsync(
- @Nonnull String collection,
- @Nonnull String text,
- @Nonnull String externalId,
- @Nonnull String externalSourceName,
+ String collection,
+ String text,
+ String externalId,
+ String externalSourceName,
@Nullable String description,
@Nullable String additionalMetadata);
@@ -64,8 +63,7 @@ public interface SemanticTextMemory {
* @param withEmbedding Whether to return the embedding of the memory found.
* @return Memory record, or null when nothing is found
*/
- public Mono getAsync(
- @Nonnull String collection, @Nonnull String key, boolean withEmbedding);
+ public Mono getAsync(String collection, String key, boolean withEmbedding);
/**
* Remove a memory by key. For local memories the key is the "id" used when saving the record.
@@ -75,7 +73,7 @@ public interface SemanticTextMemory {
* @param key Unique memory record identifier.
* @return Mono completion.
*/
- public Mono removeAsync(@Nonnull String collection, @Nonnull String key);
+ public Mono removeAsync(String collection, String key);
/**
* Find some information in memory
@@ -88,8 +86,8 @@ public interface SemanticTextMemory {
* @return Memories found
*/
public Mono> searchAsync(
- @Nonnull String collection,
- @Nonnull String query,
+ String collection,
+ String query,
int limit,
double minRelevanceScore,
boolean withEmbeddings);
@@ -102,10 +100,10 @@ public interface SemanticTextMemory {
public Mono> getCollectionsAsync();
interface Builder {
- Builder setStorage(@Nonnull MemoryStore storage);
+ Builder setStorage(MemoryStore storage);
Builder setEmbeddingGenerator(
- @Nonnull EmbeddingGeneration embeddingGenerator);
+ EmbeddingGeneration embeddingGenerator);
SemanticTextMemory build();
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java
index 24286fa614..1351feeaeb 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java
@@ -15,8 +15,8 @@ import javax.annotation.CheckReturnValue;
///
/// Semantic Kernel context.
/// memory
-public abstract class AbstractSKContext> implements SKContext {
- @Nullable private final ReadOnlySkillCollection skills;
+public abstract class AbstractSKContext implements SKContext {
+ private final ReadOnlySkillCollection skills;
private final WritableContextVariables variables;
@Nullable private final SemanticTextMemory memory;
@@ -59,15 +59,19 @@ public abstract class AbstractSKContext> implements SKCon
this.memory = null;
}
- this.skills = skills;
+ if (skills == null) {
+ this.skills = SKBuilders.skillCollection().build();
+ } else {
+ this.skills = skills;
+ }
}
@CheckReturnValue
@Override
- public T copy() {
+ public SKContext copy() {
ReadOnlySkillCollection clonedSkill;
if (skills == null) {
- clonedSkill = skills;
+ clonedSkill = null;
} else {
clonedSkill = skills.copy();
}
@@ -80,20 +84,19 @@ public abstract class AbstractSKContext> implements SKCon
return memory != null ? memory.copy() : null;
}
- @Nullable
@Override
public ReadOnlySkillCollection getSkills() {
return skills;
}
@Override
- public T setVariable(@NonNull String key, @NonNull String content) {
+ public SKContext setVariable(@NonNull String key, @NonNull String content) {
variables.setVariable(key, content);
return getThis();
}
@Override
- public T appendToVariable(@NonNull String key, @NonNull String content) {
+ public SKContext appendToVariable(@NonNull String key, @NonNull String content) {
variables.appendToVariable(key, content);
return getThis();
}
@@ -106,16 +109,16 @@ public abstract class AbstractSKContext> implements SKCon
/// if the pipeline reached the end.
/// The current instance
@Override
- public T update(@NonNull String content) {
+ public SKContext update(@NonNull String content) {
variables.update(content);
return getThis();
}
@Override
- public T update(@NonNull ContextVariables newData) {
+ public SKContext update(@NonNull ContextVariables newData) {
variables.update(newData, true);
return getThis();
}
- protected abstract T getThis();
+ protected abstract SKContext getThis();
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java
index 87631883d2..b1d5222870 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java
@@ -17,9 +17,8 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
-public abstract class AbstractSkFunction<
- RequestConfiguration, ContextType extends SKContext>
- implements SKFunction, RegistrableSkFunction {
+public abstract class AbstractSkFunction
+ implements SKFunction, RegistrableSkFunction {
private final DelegateTypes delegateType;
private final List parameters;
@@ -60,36 +59,43 @@ public abstract class AbstractSkFunction<
}
@Override
- public Mono invokeAsync(
- String input, @Nullable ContextType context, @Nullable RequestConfiguration settings) {
+ public Mono invokeAsync(
+ @Nullable String input,
+ @Nullable SKContext context,
+ @Nullable RequestConfiguration settings) {
if (context == null) {
assertSkillSupplierRegistered();
+
context =
- buildContext(
- SKBuilders.variables().build(),
- NullMemory.getInstance(),
- skillsSupplier.get());
+ SKBuilders.context()
+ .with(NullMemory.getInstance())
+ .with(skillsSupplier == null ? null : skillsSupplier.get())
+ .build();
} else {
context = context.copy();
}
- context = context.update(input);
+ if (input != null) {
+ context = context.update(input);
+ }
return this.invokeAsync(context, settings);
}
@Override
- public Mono invokeAsync(String input) {
+ public Mono invokeAsync(String input) {
return invokeAsync(input, null, null);
}
@Override
- public Mono invokeAsync(
- ContextType context, @Nullable RequestConfiguration settings) {
- // return new FutureTask(() -> function.run(null, settings, context));
-
+ public Mono invokeAsync(
+ @Nullable SKContext context, @Nullable RequestConfiguration settings) {
if (context == null) {
- context = buildContext(SKBuilders.variables().build(), NullMemory.getInstance(), null);
+ context =
+ SKBuilders.context()
+ .with(SKBuilders.variables().build())
+ .with(NullMemory.getInstance())
+ .build();
} else {
context = context.copy();
}
@@ -97,8 +103,8 @@ public abstract class AbstractSkFunction<
return this.invokeAsyncInternal(context, settings);
}
- protected abstract Mono invokeAsyncInternal(
- ContextType context, @Nullable RequestConfiguration settings);
+ protected abstract Mono invokeAsyncInternal(
+ SKContext context, @Nullable RequestConfiguration settings);
@Override
public String getSkillName() {
@@ -157,6 +163,7 @@ public abstract class AbstractSkFunction<
}
@Override
+ @Nullable
public String getDescription() {
return description;
}
@@ -205,18 +212,31 @@ public abstract class AbstractSkFunction<
+ inputs;
}
- @Override
- public ContextType buildContext() {
+ protected SKContext buildContext() {
assertSkillSupplierRegistered();
- return buildContext(SKBuilders.variables().build(), null, getSkillsSupplier().get());
+ return SKBuilders.context()
+ .with(SKBuilders.variables().build())
+ .with(skillsSupplier == null ? null : skillsSupplier.get())
+ .build();
}
@Override
- public Mono invokeWithCustomInputAsync(
+ public Mono invokeWithCustomInputAsync(
ContextVariables input,
- SemanticTextMemory semanticMemory,
- ReadOnlySkillCollection skills) {
- ContextType tmpContext = buildContext(input, semanticMemory, skills);
+ @Nullable SemanticTextMemory semanticMemory,
+ @Nullable ReadOnlySkillCollection skills) {
+ SKContext tmpContext =
+ SKBuilders.context().with(input).with(semanticMemory).with(skills).build();
return invokeAsync(tmpContext, null);
}
+
+ @Override
+ public Mono invokeAsync() {
+ return invokeAsync(null, null, null);
+ }
+
+ @Override
+ public Mono invokeAsync(SKContext context) {
+ return invokeAsync(context, null);
+ }
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java
index 0020815c25..f7f81d07cf 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java
@@ -21,6 +21,11 @@ public interface ContextVariables {
@CheckReturnValue
WritableContextVariables writableClone();
+ @Nullable
+ String getInput();
+
+ String prettyPrint();
+
interface Builder {
ContextVariables build();
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java
index 0fc8d2ef59..910aa513e7 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java
@@ -5,13 +5,13 @@ import com.microsoft.semantickernel.SKException;
public class FunctionNotRegisteredException extends SKException {
- private static final String format =
- "It does not appear this function(%s) has been registered on a kernel.%n"
- + "Register it on a kernel either by passing it to "
- + "KernelConfig.Builder().addSkill() when building the kernel, or%n"
- + "passing it to Kernel.registerSemanticFunction";
-
public FunctionNotRegisteredException(String name) {
- super(String.format(format, name));
+ super(
+ String.format(
+ "It does not appear this function(%s) has been registered on a kernel.%n"
+ + "Register it on a kernel either by passing it to "
+ + "KernelConfig.Builder().addSkill() when building the kernel, or%n"
+ + "passing it to Kernel.registerSemanticFunction",
+ name));
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InternalBuildersSingleton.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InternalBuildersSingleton.java
index 059f0f974b..23062257e2 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InternalBuildersSingleton.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InternalBuildersSingleton.java
@@ -6,6 +6,9 @@ import com.microsoft.semantickernel.builders.ServiceLoadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.function.Supplier;
+
+@SuppressWarnings("ImmutableEnumChecker")
enum InternalBuildersSingleton {
INST;
@@ -14,7 +17,7 @@ enum InternalBuildersSingleton {
private static final String FALLBACK_VARIABLE_BUILDER_CLASS =
"com.microsoft.semantickernel.orchestration.DefaultContextVariables$WritableBuilder";
- private final WritableContextVariables.Builder variables;
+ private final Supplier variables;
InternalBuildersSingleton() {
try {
@@ -49,6 +52,6 @@ enum InternalBuildersSingleton {
}
public static WritableContextVariables.Builder variables() {
- return INST.variables;
+ return INST.variables.get();
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java
index b32148acd6..c75fb30208 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java
@@ -1,18 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.orchestration;
+import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
-import reactor.util.annotation.NonNull;
import reactor.util.annotation.Nullable;
+import java.util.function.Supplier;
+
import javax.annotation.CheckReturnValue;
/** Semantic Kernel context. */
-public interface SKContext> {
+public interface SKContext {
- Type build(
+ SKContext build(
ContextVariables variables,
@Nullable SemanticTextMemory memory,
@Nullable ReadOnlySkillCollection skills);
@@ -42,7 +44,6 @@ public interface SKContext> {
*
* @return
*/
- @Nullable
ReadOnlySkillCollection getSkills();
/**
@@ -52,7 +53,7 @@ public interface SKContext> {
* @param content
* @return Context for fluent calls
*/
- Type setVariable(@NonNull String key, @NonNull String content);
+ SKContext setVariable(String key, String content);
/**
* Appends data to the given key
@@ -61,7 +62,7 @@ public interface SKContext> {
* @param content
* @return Context for fluent calls
*/
- Type appendToVariable(@NonNull String key, @NonNull String content);
+ SKContext appendToVariable(String key, String content);
/**
* Updates the input entry with the given data
@@ -70,7 +71,7 @@ public interface SKContext> {
* @return Context for fluent calls
*/
@CheckReturnValue
- Type update(@NonNull String content);
+ SKContext update(String content);
/**
* Merges in the given variables. Duplicate keys provided by newData will overwrite existing
@@ -80,11 +81,46 @@ public interface SKContext> {
* @return Context for fluent calls
*/
@CheckReturnValue
- Type update(@NonNull ContextVariables newData);
+ SKContext update(ContextVariables newData);
- Type copy();
+ SKContext copy();
+
+ interface BuilderSupplier extends Supplier {}
interface Builder {
SKContext build(ReadOnlySkillCollection skills);
+
+ SKContext build();
+
+ SKContext build(Class extends SKContext> clazz);
+
+ Builder with(ContextVariables variables);
+
+ /**
+ * Sets the skills
+ *
+ * @param skills null argument will be ignored
+ * @return Context for fluent calls
+ */
+ Builder with(@Nullable ReadOnlySkillCollection skills);
+
+ /**
+ * Sets the memory
+ *
+ * @param memory null argument will be ignored
+ * @return Context for fluent calls
+ */
+ Builder with(@Nullable SemanticTextMemory memory);
+
+ Builder clone(SKContext context);
+
+ /**
+ * Builds a context from the given kernel. If not explicitly set, the skills and memory will
+ * be used from the kernel.
+ *
+ * @param kernel
+ * @return
+ */
+ SKContext build(Kernel kernel);
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java
index 3aeb43ed43..53dd3410ba 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java
@@ -2,6 +2,7 @@
package com.microsoft.semantickernel.orchestration;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
+import com.microsoft.semantickernel.skilldefinition.FunctionView;
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
import reactor.core.publisher.Mono;
@@ -15,52 +16,14 @@ import javax.annotation.Nullable;
* @param The type of the configuration argument that will be provided when
* the function is invoked
*/
-public interface SKFunction> {
- /*
- ///
- /// Name of the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}
- ///
- string Name { get; }
-
- ///
- /// Name of the skill containing the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}
- ///
- string SkillName { get; }
-
- ///
- /// Function description. The description is used in combination with embeddings when searching relevant functions.
- ///
- string Description { get; }
-
- ///
- /// Whether the function is defined using a prompt template.
- /// IMPORTANT: native functions might use semantic functions internally,
- /// so when this property is False, executing the function might still involve AI calls.
- ///
- public bool IsSemantic { get; }
-
- ///
- /// AI service settings
- ///
- public CompleteRequestSettings RequestSettings { get; }
-
- ///
- /// Returns a description of the function, including parameters.
- ///
- /// An instance of describing the function
- FunctionView Describe();
- */
- // TODO: CancellationToken
- ///
- /// Invoke the internal delegate with an explicit string input
- ///
- /// String input
- /// SK context
- /// LLM completion settings
- /// Application logger
- /// Cancellation token
- /// The updated context, potentially a new one if context switching is
- // implemented.
+public interface SKFunction {
+ /**
+ * Returns a description of the function, including parameters.
+ *
+ * @return An instance of {@link FunctionView} describing the function
+ */
+ @Nullable
+ FunctionView describe();
/**
* Invokes the function with the given input, context and settings
@@ -71,7 +34,9 @@ public interface SKFunction invokeAsync(String input, ContextType context, RequestConfiguration settings);
+ Mono invokeAsync(String input, SKContext context, RequestConfiguration settings);
+
+ Mono invokeAsync();
/**
* Invokes the function with the given input
@@ -80,10 +45,20 @@ public interface SKFunction invokeAsync(String input);
+ Mono invokeAsync(String input);
+ @Nullable
Class getType();
+ /**
+ * Invokes the function with the given context and settings
+ *
+ * @param context Request context
+ * @return an updated context with the result of the request
+ */
+ @CheckReturnValue
+ Mono invokeAsync(SKContext context);
+
/**
* Invokes the function with the given context and settings
*
@@ -92,31 +67,7 @@ public interface SKFunction invokeAsync(ContextType context, @Nullable RequestConfiguration settings);
-
- ///
- /// Set the default skill collection to use when the function is invoked
- /// without a context or with a context that doesn't have a collection.
- ///
- /// Kernel's skill collection
- /// Self instance
- /*
- SKFunction setDefaultSkillCollection(SkillCollection skills);
- ///
- /// Set the AI service used by the semantic function, passing a factory method.
- /// The factory allows to lazily instantiate the client and to properly handle its disposal.
- ///
- /// AI service factory
- /// Self instance
- SKFunction setAIService(Supplier serviceFactory);
-
- ///
- /// Set the AI completion settings used with LLM requests
- ///
- /// LLM completion settings
- /// Self instance
- SKFunction setAIConfiguration(CompleteRequestSettings settings);
- */
+ Mono invokeAsync(SKContext context, @Nullable RequestConfiguration settings);
/**
* @return The name of the skill that this function is within
@@ -135,28 +86,17 @@ public interface SKFunction invokeWithCustomInputAsync(
+ Mono invokeWithCustomInputAsync(
ContextVariables variablesClone,
- SemanticTextMemory semanticMemory,
- ReadOnlySkillCollection skills);
+ @Nullable SemanticTextMemory semanticMemory,
+ @Nullable ReadOnlySkillCollection skills);
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SemanticSKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SemanticSKContext.java
deleted file mode 100644
index d7f003a7bd..0000000000
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SemanticSKContext.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.orchestration;
-
-/** Semantic Kernel context. */
-public interface SemanticSKContext extends SKContext {}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java
index 0dd49bf983..408775588c 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.orchestration;
-import reactor.util.annotation.NonNull;
-
import java.util.Map;
/**
@@ -16,11 +14,11 @@ public interface WritableContextVariables extends ContextVariables {
*
* @param key variable name
* @param content value to set
- * @return Contect for fluent calls
+ * @return Context for fluent calls
*/
- ContextVariables setVariable(@NonNull String key, @NonNull String content);
+ ContextVariables setVariable(String key, String content);
- ContextVariables appendToVariable(@NonNull String key, @NonNull String content);
+ ContextVariables appendToVariable(String key, String content);
///
/// Updates the main input text with the new value after a function is complete.
@@ -29,9 +27,11 @@ public interface WritableContextVariables extends ContextVariables {
// result for the user
/// if the pipeline reached the end.
/// The current instance
- ContextVariables update(@NonNull String content);
+ ContextVariables update(String content);
- ContextVariables update(@NonNull ContextVariables newData, boolean merge);
+ ContextVariables update(ContextVariables newData, boolean merge);
+
+ ContextVariables remove(String key);
interface Builder {
/**
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java
new file mode 100644
index 0000000000..e225d8e8d7
--- /dev/null
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.planner;
+
+import com.microsoft.semantickernel.SKException;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/** Exception thrown for errors related to planning. */
+public class PlanningException extends SKException {
+ @Nonnull private final ErrorCodes errorCode;
+
+ public PlanningException(@Nonnull ErrorCodes error) {
+ this(error, null, null);
+ }
+
+ /**
+ * Initializes a new instance of the PlanningException class with a provided error code and
+ * message
+ *
+ * @param errorCode Error code
+ * @param message The exception message
+ */
+ public PlanningException(@Nonnull ErrorCodes errorCode, @Nullable String message) {
+ this(errorCode, message, null);
+ }
+
+ /**
+ * Initializes a new instance of the class with a provided error
+ * code, message, and inner exception.
+ *
+ * @param errorCode The error code
+ * @param message A string that describes the error
+ * @param innerException The exception that is the cause of the current exception
+ */
+ public PlanningException(
+ @Nonnull ErrorCodes errorCode,
+ @Nullable String message,
+ @Nullable Throwable innerException) {
+ super(getDefaultMessage(errorCode, message), innerException);
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Gets the error code
+ *
+ * @return The error code
+ */
+ public ErrorCodes getErrorCode() {
+ return errorCode;
+ }
+
+ /* Translate the error code into a default message */
+ private static String getDefaultMessage(
+ @Nonnull ErrorCodes errorCode, @Nullable String message) {
+ return String.format("%s: %s", errorCode.getMessage(), message);
+ }
+
+ /** Error codes for PlanningException */
+ public enum ErrorCodes {
+ UnknownError("Unknown error"),
+
+ InvalidGoal("Invalid goal"),
+
+ InvalidPlan("Invalid plan"),
+
+ InvalidConfiguration("Invalid configuration");
+
+ private final String message;
+
+ ErrorCodes(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java
index d92e240b2e..b5e70eead0 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java
@@ -22,14 +22,17 @@ public interface PromptTemplate {
* Render the template using the information in the context
*
* @param executionContext Kernel execution context helpers
- * @param promptTemplateEngine
* @return Prompt rendered to string
*/
- Mono renderAsync(SKContext executionContext, PromptTemplateEngine promptTemplateEngine);
+ Mono renderAsync(SKContext executionContext);
abstract class Builder {
protected Builder() {}
- public abstract PromptTemplate build(String promptTemplate, PromptTemplateConfig config);
+ public abstract PromptTemplate build(PromptTemplateEngine promptTemplateEngine);
+
+ public abstract Builder withPromptTemplate(String promptTemplate);
+
+ public abstract Builder withPromptTemplateConfig(PromptTemplateConfig config);
}
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java
index 7b75a727db..ebf9cf3ebe 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java
@@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import reactor.util.annotation.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/** Prompt template configuration */
@@ -44,6 +45,8 @@ public class PromptTemplateConfig {
completionConfig.presencePenalty,
completionConfig.frequencyPenalty,
completionConfig.maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
completionConfig.stopSequences));
}
@@ -55,6 +58,8 @@ public class PromptTemplateConfig {
completionConfig.presencePenalty,
completionConfig.frequencyPenalty,
completionConfig.maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
completionConfig.stopSequences));
}
@@ -66,6 +71,8 @@ public class PromptTemplateConfig {
presencePenalty,
completionConfig.frequencyPenalty,
completionConfig.maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
completionConfig.stopSequences));
}
@@ -77,6 +84,8 @@ public class PromptTemplateConfig {
completionConfig.presencePenalty,
frequencyPenalty,
completionConfig.maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
completionConfig.stopSequences));
}
@@ -88,6 +97,8 @@ public class PromptTemplateConfig {
completionConfig.presencePenalty,
completionConfig.frequencyPenalty,
maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
completionConfig.stopSequences));
}
@@ -99,6 +110,8 @@ public class PromptTemplateConfig {
completionConfig.presencePenalty,
completionConfig.frequencyPenalty,
completionConfig.maxTokens,
+ completionConfig.bestOf,
+ completionConfig.user,
stopSequences));
}
@@ -107,6 +120,10 @@ public class PromptTemplateConfig {
}
}
+ public InputConfig getInput() {
+ return input;
+ }
+
/** Completion configuration parameters */
public static class CompletionConfig {
/*
@@ -166,8 +183,37 @@ public class PromptTemplateConfig {
*/
public final List stopSequences; // { get; set; } = new();
+ /**
+ * The maximum number of completions to generate for each prompt. This is used by the
+ * CompletionService to generate multiple completions for a single prompt.
+ */
+ private final Integer bestOf;
+
+ /**
+ * A unique identifier representing your end-user, which can help OpenAI to monitor and
+ * detect abuse
+ */
+ private final String user;
+
public CompletionConfig() {
- this(0.0, 0.0, 0.0, 0.0, 256, new ArrayList<>());
+ this(0.0, 0.0, 0.0, 0.0, 256, 1, "", new ArrayList<>());
+ }
+
+ public CompletionConfig(
+ double temperature,
+ double topP,
+ double presencePenalty,
+ double frequencyPenalty,
+ int maxTokens) {
+ this(
+ temperature,
+ topP,
+ presencePenalty,
+ frequencyPenalty,
+ maxTokens,
+ 1,
+ "",
+ new ArrayList<>());
}
@JsonCreator
@@ -177,12 +223,22 @@ public class PromptTemplateConfig {
@JsonProperty("presence_penalty") double presencePenalty,
@JsonProperty("frequency_penalty") double frequencyPenalty,
@JsonProperty("max_tokens") int maxTokens,
+ @JsonProperty("best_of") int bestOf,
+ @JsonProperty("user") String user,
@JsonProperty(value = "stop_sequences") List stopSequences) {
this.temperature = temperature;
this.topP = topP;
this.presencePenalty = presencePenalty;
this.frequencyPenalty = frequencyPenalty;
this.maxTokens = maxTokens;
+
+ // bestOf must be at least 1
+ this.bestOf = Math.max(1, bestOf);
+
+ if (user == null) {
+ user = "";
+ }
+ this.user = user;
if (stopSequences == null) {
stopSequences = new ArrayList<>();
}
@@ -208,6 +264,22 @@ public class PromptTemplateConfig {
public int getMaxTokens() {
return maxTokens;
}
+
+ /**
+ * The maximum number of completions to generate for each prompt. This is used by the
+ * CompletionService to generate multiple completions for a single prompt.
+ */
+ public int getBestOf() {
+ return bestOf;
+ }
+
+ /**
+ * A unique identifier representing your end-user, which can help OpenAI to monitor and
+ * detect abuse
+ */
+ public String getUser() {
+ return user;
+ }
}
/** Input parameter for semantic functions */
@@ -226,6 +298,34 @@ public class PromptTemplateConfig {
this.description = description;
this.defaultValue = defaultValue;
}
+
+ /**
+ * Name of the parameter to pass to the function. e.g. when using "{{$input}}" the name is
+ * "input", when using "{{$style}}" the name is "style", etc.
+ *
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Parameter description for UI apps and planner. Localization is not supported here.
+ *
+ * @return description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Default value when nothing is provided
+ *
+ * @return the default value
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
}
/** Input configuration (list of all input parameters for a semantic function). */
@@ -235,37 +335,27 @@ public class PromptTemplateConfig {
@JsonCreator
public InputConfig(@JsonProperty("parameters") List parameters) {
- this.parameters = parameters;
+ this.parameters = Collections.unmodifiableList(parameters);
+ }
+
+ public List getParameters() {
+ return parameters;
}
}
- /*
- ///
- /// Schema - Not currently used.
- ///
- [JsonPropertyName("schema")]
- [JsonPropertyOrder(1)]
- public int Schema { get; set; } = 1;
-
- ///
- /// Type, such as "completion", "embeddings", etc.
- ///
- /// TODO: use enum
- [JsonPropertyName("type")]
- [JsonPropertyOrder(2)]
- */
private final int schema;
private final String type; // { get; set; } = "completion";
- /*
- ///
- /// Description
- ///
- [JsonPropertyName("description")]
- [JsonPropertyOrder(3)]
- */
private final String description;
+ public PromptTemplateConfig() {
+ this("", "", null);
+ }
+
+ public PromptTemplateConfig(CompletionConfig completionConfig) {
+ this(1, "", "", completionConfig, new InputConfig(new ArrayList<>()));
+ }
+
public PromptTemplateConfig(
String description, String type, @Nullable CompletionConfig completionConfig) {
this(1, description, type, completionConfig, new InputConfig(new ArrayList<>()));
@@ -277,7 +367,7 @@ public class PromptTemplateConfig {
@JsonProperty("description") String description,
@JsonProperty("type") String type,
@Nullable @JsonProperty("completion") CompletionConfig completionConfig,
- @JsonProperty("input") InputConfig input) {
+ @Nullable @JsonProperty("input") InputConfig input) {
if (completionConfig == null) {
completionConfig = new CompletionConfig();
}
@@ -285,9 +375,17 @@ public class PromptTemplateConfig {
this.description = description;
this.type = type;
this.completionConfig = completionConfig;
+ if (input == null) {
+ input = new InputConfig(new ArrayList<>());
+ }
this.input = input;
}
+ /**
+ * Description
+ *
+ * @return Description
+ */
public String getDescription() {
return description;
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java
new file mode 100644
index 0000000000..69abb789ff
--- /dev/null
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.skilldefinition;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Class used to copy and export data from the skill collection. The data is mutable, but changes do
+ * not affect the skill collection.
+ */
+public class FunctionView {
+ // Name of the function. The name is used by the skill collection and in prompt templates e.g.
+ // {{skillName.functionName}}
+ private final String name;
+
+ /// Name of the skill containing the function. The name is used by the skill collection and in
+ // prompt templates e.g. {{skillName.functionName}}
+ private final String skillName;
+
+ // Function description. The description is used in combination with embeddings when searching
+ // relevant functions.
+ private final String description;
+
+ // Whether the delegate points to a semantic function
+ private final boolean isSemantic;
+
+ // Whether the delegate is an asynchronous function
+ private final boolean isAsynchronous;
+
+ // List of function parameters
+ private final List parameters;
+
+ /**
+ * Create a function view.
+ *
+ * @param name Function name
+ * @param skillName Skill name, e.g. the function namespace
+ * @param description Function description
+ * @param parameters List of function parameters provided by the skill developer
+ * @param isSemantic Whether the function is a semantic one (or native is False)
+ * @param isAsynchronous Whether the function is async. Note: all semantic functions are async
+ */
+ public FunctionView(
+ String name,
+ String skillName,
+ String description,
+ List parameters,
+ boolean isSemantic,
+ boolean isAsynchronous) {
+ this.name = name;
+ this.skillName = skillName;
+ this.description = description;
+ this.parameters = Collections.unmodifiableList(parameters);
+ this.isSemantic = isSemantic;
+ this.isAsynchronous = isAsynchronous;
+ }
+
+ /**
+ * List of function parameters
+ *
+ * @return the list of function parameters
+ */
+ public List getParameters() {
+ return parameters;
+ }
+}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java
index 717dfaaef1..5c7651692a 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java
@@ -28,6 +28,10 @@ public class ParameterView {
this.defaultValue = defaultValue;
}
+ public ParameterView(String name) {
+ this(name, "", "");
+ }
+
public String getName() {
return name;
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java
index 4b5bdf9a34..a13576a8cb 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java
@@ -12,7 +12,7 @@ public interface ReadOnlyFunctionCollection {
String getSkillName();
- SKFunction, ?> getFunction(String functionName);
+ SKFunction> getFunction(String functionName);
/**
* Get function with the given SKFunction type argument.
@@ -34,5 +34,5 @@ public interface ReadOnlyFunctionCollection {
/**
* @return An unmodifiable list of all functions
*/
- List> getAll();
+ List> getAll();
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java
index 2d1a7e52f0..ccd4e0e3b8 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java
@@ -35,18 +35,19 @@ public interface ReadOnlySkillCollection {
/** Get function with name from the global scope */
@Nullable
- > T getFunction(
- String functionName, @Nullable Class functionType);
+ > T getFunction(String functionName, @Nullable Class functionType);
@Nullable
- > T getFunction(
- String skillName, String funName, Class functionClazz);
+ > T getFunction(
+ String skillName, String funName, @Nullable Class functionClazz);
@Nullable
ReadOnlyFunctionCollection getFunctions(String skillName);
boolean hasFunction(String functionName);
+ boolean hasFunction(String skillName, String functionName);
+
public interface Builder {
public ReadOnlySkillCollection build();
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java
index 220a5a1d45..0a92adeff6 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java
@@ -2,9 +2,12 @@
package com.microsoft.semantickernel.templateengine;
import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.templateengine.blocks.Block;
import reactor.core.publisher.Mono;
+import java.util.List;
+
/** Prompt template engine interface */
public interface PromptTemplateEngine {
@@ -30,6 +33,15 @@ public interface PromptTemplateEngine {
*/
Mono renderAsync(String templateText, SKContext context);
+ /**
+ * Given a prompt template string, extract all the blocks (text, variables, function calls)
+ *
+ * @param promptTemplate Prompt template (see skprompt.txt files)
+ * @return A list of all the blocks, ie the template tokenized in text, variables and function
+ * calls
+ */
+ List extractBlocks(String promptTemplate);
+
abstract class Builder {
protected Builder() {}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java
index 5885a6f256..653ea2f44c 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java
@@ -40,23 +40,56 @@ public class CompletionRequestSettings {
/** Sequences where the completion will stop generating further tokens. */
private final List stopSequences; // { get; set; } = Array.Empty();
+ /**
+ * The maximum number of completions to generate for each prompt. This is used by the
+ * CompletionService to generate multiple completions for a single prompt.
+ */
+ private final int bestOf;
+
+ /**
+ * A unique identifier representing your end-user, which can help OpenAI to monitor and detect
+ * abuse
+ */
+ private final String user;
+
+ public CompletionRequestSettings(
+ double temperature,
+ double topP,
+ double presencePenalty,
+ double frequencyPenalty,
+ int maxTokens) {
+ this(
+ temperature,
+ topP,
+ presencePenalty,
+ frequencyPenalty,
+ maxTokens,
+ 1,
+ "",
+ Collections.emptyList());
+ }
+
public CompletionRequestSettings(
double temperature,
double topP,
double presencePenalty,
double frequencyPenalty,
int maxTokens,
+ int bestOf,
+ String user,
List stopSequences) {
this.temperature = temperature;
this.topP = topP;
this.presencePenalty = presencePenalty;
this.frequencyPenalty = frequencyPenalty;
this.maxTokens = maxTokens;
+ this.bestOf = bestOf;
+ this.user = user;
this.stopSequences = new ArrayList<>(stopSequences);
}
public CompletionRequestSettings() {
- this(0, 0, 0, 0, 256, new ArrayList<>());
+ this(0, 0, 0, 0, 256, 1, "", new ArrayList<>());
}
///
@@ -72,6 +105,8 @@ public class CompletionRequestSettings {
config.getPresencePenalty(),
config.getFrequencyPenalty(),
config.getMaxTokens(),
+ config.getBestOf(),
+ config.getUser(),
new ArrayList<>());
}
@@ -117,4 +152,20 @@ public class CompletionRequestSettings {
public List getStopSequences() {
return Collections.unmodifiableList(stopSequences);
}
+
+ /**
+ * The maximum number of completions to generate for each prompt. This is used by the
+ * CompletionService to generate multiple completions for a single prompt.
+ */
+ public Integer getBestOf() {
+ return bestOf;
+ }
+
+ /**
+ * A unique identifier representing your end-user, which can help OpenAI to monitor and detect
+ * abuse
+ */
+ public String getUser() {
+ return user;
+ }
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKContext.java
deleted file mode 100644
index 46840ec9ee..0000000000
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKContext.java
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.textcompletion;
-
-import com.microsoft.semantickernel.orchestration.SKContext;
-
-public interface CompletionSKContext extends SKContext {}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java
index 886391527c..d19cf76278 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.textcompletion;
-import com.microsoft.semantickernel.builders.BuildersSingleton;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
@@ -12,8 +12,7 @@ import java.util.List;
import javax.annotation.Nullable;
-public interface CompletionSKFunction
- extends SKFunction {
+public interface CompletionSKFunction extends SKFunction {
/**
* Method to aggregate partitioned results of a semantic function.
@@ -22,12 +21,8 @@ public interface CompletionSKFunction
* @param context Semantic Kernel context
* @return Aggregated results
*/
- Mono aggregatePartitionedResultsAsync(
- List partitionedInput, @Nullable CompletionSKContext context);
-
- static CompletionSKFunction.Builder builder() {
- return BuildersSingleton.INST.getFunctionBuilders().completionBuilders(null);
- }
+ Mono aggregatePartitionedResultsAsync(
+ List partitionedInput, @Nullable SKContext context);
abstract class Builder {
@@ -40,7 +35,7 @@ public interface CompletionSKFunction
@Nullable String skillName);
public abstract CompletionSKFunction createFunction(
- String functionName, SemanticFunctionConfig functionConfig);
+ String prompt, PromptTemplateConfig.CompletionConfig functionConfig);
public abstract CompletionSKFunction createFunction(
@Nullable String skillNameFinal,
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/AzureOpenAISettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/AzureOpenAISettings.java
index 48a6ff63f6..e6b24d77b1 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/AzureOpenAISettings.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/AzureOpenAISettings.java
@@ -3,12 +3,17 @@ package com.microsoft.semantickernel.util;
import java.io.IOException;
+import javax.annotation.Nullable;
+
public class AzureOpenAISettings extends ClientSettings {
private static final String DEFAULT_CLIENT_ID = "azureopenai";
- private String key;
- private String endpoint;
- private String deploymentName;
+
+ @Nullable private String key = null;
+
+ @Nullable private String endpoint = null;
+
+ @Nullable private String deploymentName = null;
public enum Property {
AZURE_OPEN_AI_KEY("key"),
@@ -26,14 +31,23 @@ public class AzureOpenAISettings extends ClientSettings {
}
public String getKey() {
+ if (key == null) {
+ throw new RuntimeException("Azure OpenAI key is not set");
+ }
return key;
}
public String getEndpoint() {
+ if (endpoint == null) {
+ throw new RuntimeException("Azure OpenAI endpoint is not set");
+ }
return endpoint;
}
public String getDeploymentName() {
+ if (deploymentName == null) {
+ throw new RuntimeException("Azure OpenAI deployment name is not set");
+ }
return deploymentName;
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/OpenAISettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/OpenAISettings.java
index bf6b13875f..0f0b77ce36 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/OpenAISettings.java
+++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/OpenAISettings.java
@@ -3,10 +3,12 @@ package com.microsoft.semantickernel.util;
import java.io.IOException;
+import javax.annotation.Nullable;
+
public class OpenAISettings extends ClientSettings {
- private String key;
- private String organizationId;
private static final String DEFAULT_CLIENT_ID = "openai";
+ @Nullable private String key = null;
+ @Nullable private String organizationId = null;
private enum Property {
OPEN_AI_KEY("key"),
@@ -23,10 +25,16 @@ public class OpenAISettings extends ClientSettings {
}
public String getKey() {
+ if (key == null) {
+ throw new RuntimeException("OpenAI key is not set");
+ }
return key;
}
public String getOrganizationId() {
+ if (organizationId == null) {
+ throw new RuntimeException("OpenAI organization id is not set");
+ }
return organizationId;
}
diff --git a/java/semantickernel-bom/pom.xml b/java/semantickernel-bom/pom.xml
index afa834d4d1..caab26e358 100644
--- a/java/semantickernel-bom/pom.xml
+++ b/java/semantickernel-bom/pom.xml
@@ -1,8 +1,8 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0com.microsoft.semantickernel
@@ -44,10 +44,17 @@
semantickernel-core-skills${project.version}
+
+ com.microsoft.semantickernel.extensions
+ actionplanner-extension
+ ${project.version}
+
+
+
com.azureazure-ai-openai
- 1.0.0-beta.1
+ 1.0.0-beta.2org.slf4j
diff --git a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java
index bff9474a2d..cc9df2e36a 100644
--- a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java
+++ b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java
@@ -14,6 +14,7 @@ import com.microsoft.semantickernel.connectors.ai.openai.azuresdk.ClientBase;
import reactor.core.publisher.Mono;
+import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
@@ -28,6 +29,7 @@ public class OpenAIChatCompletion extends ClientBase implements ChatCompletion build(OpenAIAsyncClient client, String modelId) {
return new OpenAIChatCompletion(client, modelId);
}
@@ -40,6 +42,7 @@ public class OpenAIChatCompletion extends ClientBase implements ChatCompletion generateMessageAsync(
OpenAIChatHistory chat, @Nullable ChatRequestSettings requestSettings) {
@@ -98,7 +101,9 @@ public class OpenAIChatCompletion extends ClientBase implements ChatCompletion());
+ options.setN(requestSettings.getBestOf());
+ options.setUser(requestSettings.getUser());
return options;
}
diff --git a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java
index 7560f0817f..9a54c23505 100644
--- a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java
+++ b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java
@@ -15,6 +15,7 @@ import jakarta.inject.Inject;
import reactor.core.publisher.Mono;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
///
@@ -59,7 +60,9 @@ public class OpenAITextCompletion extends ClientBase implements TextCompletion {
.setFrequencyPenalty(requestSettings.getFrequencyPenalty())
.setPresencePenalty(requestSettings.getPresencePenalty())
.setModel(getModelId())
- .setUser(null);
+ .setUser(requestSettings.getUser())
+ .setBestOf(requestSettings.getBestOf())
+ .setLogitBias(new HashMap<>());
return getClient()
.getCompletions(getModelId(), completionsOptions)
diff --git a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java
index 50b565c1d9..3e30a4fdb0 100644
--- a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java
+++ b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java
@@ -27,7 +27,8 @@ public class OpenAITextEmbeddingGeneration extends ClientBase
}
protected Mono>> internalGenerateTextEmbeddingsAsync(List data) {
- EmbeddingsOptions options = new EmbeddingsOptions(data).setModel(getModelId()).setUser("default");
+ EmbeddingsOptions options =
+ new EmbeddingsOptions(data).setModel(getModelId()).setUser("default");
return getClient()
.getEmbeddings(getModelId(), options)
diff --git a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemory.java b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemory.java
index 30ef9184c2..ab5e1715b8 100644
--- a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemory.java
+++ b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemory.java
@@ -19,14 +19,12 @@ import com.azure.search.documents.models.QueryLanguage;
import com.azure.search.documents.models.QueryType;
import com.azure.search.documents.models.SearchOptions;
import com.azure.search.documents.util.SearchPagedResponse;
-import com.microsoft.semantickernel.exceptions.NotSupportedException;
import com.microsoft.semantickernel.memory.MemoryQueryResult;
import com.microsoft.semantickernel.memory.MemoryRecordMetadata;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
+
import reactor.core.publisher.Mono;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -40,6 +38,9 @@ import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
/**
* Semantic Memory implementation using Azure Cognitive Search. For more information about Azure
* Cognitive Search {@see https://learn.microsoft.com/azure/search/search-what-is-azure-search}
@@ -57,7 +58,8 @@ public class AzureCognitiveSearchMemory implements SemanticTextMemory {
* Create a new instance of semantic memory using Azure Cognitive Search.
*
* @param endpoint Azure Cognitive Search URI, e.g. {@code "https://contoso.search.windows.net"}
- * @param apiKey The key used to authenticate HTTP requests sent to the Azure Cognitive Search service.
+ * @param apiKey The key used to authenticate HTTP requests sent to the Azure Cognitive Search
+ * service.
*/
public AzureCognitiveSearchMemory(String endpoint, String apiKey) {
AzureKeyCredential credentials = new AzureKeyCredential(apiKey);
@@ -72,7 +74,8 @@ public class AzureCognitiveSearchMemory implements SemanticTextMemory {
* Create a new instance of semantic memory using Azure Cognitive Search.
*
* @param endpoint Azure Cognitive Search URI, e.g. {@code "https://contoso.search.windows.net"}
- * @param credentials TokenCredential used to authorize requests sent to the Azure Cognitive Search service.
+ * @param credentials TokenCredential used to authorize requests sent to the Azure Cognitive
+ * Search service.
*/
public AzureCognitiveSearchMemory(String endpoint, TokenCredential credentials) {
this._adminClient =
@@ -255,21 +258,18 @@ public class AzureCognitiveSearchMemory implements SemanticTextMemory {
PrioritizedFields prioritizedFields =
new PrioritizedFields()
- .setTitleField(titleField)
- .setPrioritizedContentFields(prioritizedContentFields);
+ .setTitleField(titleField)
+ .setPrioritizedContentFields(prioritizedContentFields);
SemanticConfiguration semanticConfiguration =
new SemanticConfiguration("default", prioritizedFields);
SemanticSettings semanticSettings =
new SemanticSettings()
- .setConfigurations(
- Collections.singletonList(semanticConfiguration)
- );
+ .setConfigurations(Collections.singletonList(semanticConfiguration));
SearchIndex newIndex =
- new SearchIndex(indexName, fields)
- .setSemanticSettings(semanticSettings);
+ new SearchIndex(indexName, fields).setSemanticSettings(semanticSettings);
return this._adminClient.createIndex(newIndex);
}
@@ -292,15 +292,17 @@ public class AzureCognitiveSearchMemory implements SemanticTextMemory {
return response.getValue().getResults().get(0).getKey();
};
- return client.mergeOrUploadDocumentsWithResponse(Collections.singleton(record), throwOnAnyError)
+ return client.mergeOrUploadDocumentsWithResponse(
+ Collections.singleton(record), throwOnAnyError)
.map(transform)
- .onErrorResume(e ->
- createIndexAsync(indexName)
- .then(client.mergeOrUploadDocumentsWithResponse(
- Collections.singleton(record), throwOnAnyError))
- .map(transform)
- );
-
+ .onErrorResume(
+ e ->
+ createIndexAsync(indexName)
+ .then(
+ client.mergeOrUploadDocumentsWithResponse(
+ Collections.singleton(record),
+ throwOnAnyError))
+ .map(transform));
}
private static MemoryRecordMetadata toMemoryRecordMetadata(AzureCognitiveSearchRecord data) {
diff --git a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchRecord.java b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchRecord.java
index 58b0fa409f..6d0b3ebeaf 100644
--- a/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchRecord.java
+++ b/java/semantickernel-connectors-parent/semantickernel-connectors/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchRecord.java
@@ -12,7 +12,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
import java.util.List;
-
/**
* Azure Cognitive Search record and index definition. Note: once defined, index cannot be modified.
*/
@@ -37,12 +36,12 @@ public final class AzureCognitiveSearchRecord {
@JsonCreator
public AzureCognitiveSearchRecord(
- @JsonProperty("Id") String id,
- @JsonProperty("Text") String text,
- @JsonProperty("Description") String description,
- @JsonProperty("AdditionalMetadata") String additionalMetadata,
- @JsonProperty("ExternalSourceName") String externalSourceName,
- @JsonProperty("Reference") boolean isReference) {
+ @JsonProperty("Id") String id,
+ @JsonProperty("Text") String text,
+ @JsonProperty("Description") String description,
+ @JsonProperty("AdditionalMetadata") String additionalMetadata,
+ @JsonProperty("ExternalSourceName") String externalSourceName,
+ @JsonProperty("Reference") boolean isReference) {
this.id = id;
this.text = text;
this.description = description;
@@ -126,8 +125,7 @@ public final class AzureCognitiveSearchRecord {
new SearchField("ExternalSourceName", SearchFieldDataType.STRING)
.setSearchable(true)
.setAnalyzerName(LexicalAnalyzerName.EN_LUCENE),
- new SearchField("Reference", SearchFieldDataType.BOOLEAN).setFilterable(true)
- );
+ new SearchField("Reference", SearchFieldDataType.BOOLEAN).setFilterable(true));
}
// TODO: add one more field with the vector, float array, mark it as searchable
diff --git a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java
index 3185659abd..de4179b916 100644
--- a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java
+++ b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java
@@ -8,7 +8,6 @@ import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.text.TextChunker;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import reactor.core.publisher.Mono;
@@ -25,6 +24,7 @@ public class ConversationSummarySkill {
private final CompletionSKFunction summarizeConversationFunction;
private final CompletionSKFunction conversationActionItemsFunction;
private final CompletionSKFunction conversationTopicsFunction;
+ private final Kernel kernel;
/**
* Initializes a new instance of the ConversationSummarySkill class
@@ -32,6 +32,7 @@ public class ConversationSummarySkill {
* @param kernel Kernel instance
*/
public ConversationSummarySkill(Kernel kernel) {
+ this.kernel = kernel;
this.summarizeConversationFunction =
SKBuilders.completionFunctions(kernel)
.createFunction(
@@ -85,17 +86,22 @@ public class ConversationSummarySkill {
@DefineSKFunction(
description = "Given a long conversation transcript, summarize the conversation.",
name = "SummarizeConversation")
- public Mono summarizeConversationAsync(
+ public Mono summarizeConversationAsync(
@SKFunctionInputAttribute
@SKFunctionParameters(
description = "A long conversation transcript.",
name = "input")
String input,
- @Nullable SKContext> context) {
+ @Nullable SKContext context) {
List lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
- CompletionSKContext completionContext = summarizeConversationFunction.buildContext(context);
+ if (context == null) {
+ context =
+ SKBuilders.context().with(kernel.getSkills()).with(kernel.getMemory()).build();
+ }
+
+ SKContext completionContext = context.copy();
return this.summarizeConversationFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
@@ -111,17 +117,17 @@ public class ConversationSummarySkill {
@DefineSKFunction(
description = "Given a long conversation transcript, identify action items.",
name = "GetConversationActionItems")
- public Mono getConversationActionItemsAsync(
+ public Mono getConversationActionItemsAsync(
@SKFunctionInputAttribute
@SKFunctionParameters(
description = "A long conversation transcript.",
name = "input")
String input,
- SKContext> context) {
+ SKContext context) {
List lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
- CompletionSKContext completionContext = summarizeConversationFunction.buildContext(context);
+ SKContext completionContext = context.copy();
return this.conversationActionItemsFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
@@ -138,17 +144,17 @@ public class ConversationSummarySkill {
description =
"Given a long conversation transcript, identify topics worth remembering.",
name = "GetConversationTopics")
- public Mono getConversationTopicsAsync(
+ public Mono getConversationTopicsAsync(
@SKFunctionInputAttribute
@SKFunctionParameters(
description = "A long conversation transcript.",
name = "input")
String input,
- SKContext> context) {
+ SKContext context) {
List lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
- CompletionSKContext completionContext = summarizeConversationFunction.buildContext(context);
+ SKContext completionContext = context.copy();
return this.conversationTopicsFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
diff --git a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java
index 9881baa612..ec43eb5bfd 100644
--- a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java
+++ b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java
@@ -6,6 +6,7 @@ import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputA
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.io.IOException;
+import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -41,12 +42,16 @@ public class FileIOSkill {
@SKFunctionInputAttribute
@SKFunctionParameters(name = "path", description = "Source file")
String path,
- @SKFunctionParameters(name = "charset", description = "Character set to use to read the file", defaultValue="UTF-8")
- String charset) throws IOException {
+ @SKFunctionParameters(
+ name = "charset",
+ description = "Character set to use to read the file",
+ defaultValue = "UTF-8")
+ String charset)
+ throws IOException {
Path filePath = Paths.get(path);
byte[] fileBytes;
fileBytes = Files.readAllBytes(filePath);
- String fileContents = new String(fileBytes, charset);
+ String fileContents = new String(fileBytes, Charset.forName(charset));
return fileContents;
}
@@ -61,22 +66,25 @@ public class FileIOSkill {
*
* @param path The destination file.
* @param content Contains the 'content' to write
- * @return An awaitable task.
*/
@DefineSKFunction(description = "Write a file", name = "writeAsync")
public void writeFileAsync(
@SKFunctionInputAttribute
@SKFunctionParameters(name = "path", description = "Destination file")
String path,
- @SKFunctionParameters(
+ @SKFunctionParameters(
name = "content",
description = "File content",
defaultValue = "",
type = String.class)
String content,
- @SKFunctionParameters(name = "charset", description = "Character set to use to read the file", defaultValue="UTF-8")
- String charset) throws IOException {
- Path filePath = Paths.get(path);
- Files.write(filePath, content.getBytes(charset));
+ @SKFunctionParameters(
+ name = "charset",
+ description = "Character set to use to read the file",
+ defaultValue = "UTF-8")
+ String charset)
+ throws IOException {
+ Path filePath = Paths.get(path);
+ Files.write(filePath, content.getBytes(charset));
}
}
diff --git a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java
index 0587d2fa96..d1f15f2275 100644
--- a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java
+++ b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java
@@ -9,31 +9,35 @@ import java.math.BigDecimal;
/**
* MathSkill provides a set of functions to make Math calculations.
- *
+ *
*
- *
input is the first number in the operation.
- *
amount is the second number in the operation.
+ *
input is the first number in the operation.
+ *
amount is the second number in the operation.
*
- *
+ *
*
Usage:
- *
+ *
+ *
+ *
+ *
* kernel.ImportSkill("math", new MathSkill());
- *
+ *
* {{math.add}} => Returns the sum of input and amount
* {{math.subtract}} => Returns the differentce of input from amount
- *
- *
- *
+ *
+ *
+ *
+ *
* @implNote This skill uses BigDecimal to perform the number conversion and the calculations.
*/
public class MathSkill {
/**
* Returns the addition result of input and amount values provided.
- *
- * This skill attempts to convert the numbers to BigDecimal and then add them.
- *
- * If a conversion error occurs, the skill will throw an exception.
+ *
+ *
This skill attempts to convert the numbers to BigDecimal and then add them.
+ *
+ *
If a conversion error occurs, the skill will throw an exception.
*
* @param input Initial value as string to add the specified amount
* @param amount The amount to be added to input
@@ -54,11 +58,11 @@ public class MathSkill {
/**
* Returns the subtraction result of input and amount values provided.
- *
- * This skill attempts to convert the numbers to BigDecimal and then subtract them.
- *
- * If a conversion error occurs, the skill will throw an exception.
- *
+ *
+ *
This skill attempts to convert the numbers to BigDecimal and then subtract them.
+ *
+ *
If a conversion error occurs, the skill will throw an exception.
+ *
* @param input Initial value as string to subtract the specified amount
* @param amount The amount to be subtracted from input
* @return The resulting difference as a String.
diff --git a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java
index 949afcd4b6..6ae9e392c9 100644
--- a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java
+++ b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java
@@ -49,6 +49,6 @@ public class TextSkill {
@SKFunctionInputAttribute
@SKFunctionParameters(description = "Text to lowercase", name = "input")
String input) {
- return input.toLowerCase();
+ return input.toLowerCase(Locale.ROOT);
}
}
diff --git a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java
index d2fc4fb445..8efa98212d 100644
--- a/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java
+++ b/java/semantickernel-core-skills/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java
@@ -7,7 +7,6 @@ import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
import java.time.format.TextStyle;
import java.util.Locale;
@@ -55,6 +54,9 @@ import java.util.Locale;
*
{{time.timeZoneName}} => Pacific Time
*/
public class TimeSkill {
+
+ public static final String DAY_MONTH_DAY_YEAR = "EEEE, MMMM d, yyyy";
+
/**
* Get the current date.
*
@@ -64,7 +66,8 @@ public class TimeSkill {
*/
@DefineSKFunction(name = "date", description = "Get the current date")
public String date() {
- return DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(ZonedDateTime.now());
+ // Example: Sunday, 12 January, 2025
+ return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR).format(ZonedDateTime.now());
}
/**
@@ -76,6 +79,7 @@ public class TimeSkill {
*/
@DefineSKFunction(name = "time", description = "Get the current time")
public String time() {
+ // Example: 09:15:07 PM
return DateTimeFormatter.ofPattern("hh:mm:ss a").format(ZonedDateTime.now());
}
@@ -88,7 +92,7 @@ public class TimeSkill {
*/
@DefineSKFunction(name = "utcNow", description = "Get the current UTC date and time")
public String utcNow() {
- return DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy h:mm a")
+ return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a")
.format(ZonedDateTime.now().withZoneSameInstant(ZoneOffset.UTC));
}
@@ -115,7 +119,7 @@ public class TimeSkill {
name = "now",
description = "Get the current date and time in the local time zone")
public String now() {
- return DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy h:mm a")
+ return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a")
.format(ZonedDateTime.now());
}
@@ -164,7 +168,7 @@ public class TimeSkill {
*/
@DefineSKFunction(name = "day", description = "Get the current day of the month")
public String day() {
- return DateTimeFormatter.ofPattern("dd").format(ZonedDateTime.now());
+ return DateTimeFormatter.ofPattern("d").format(ZonedDateTime.now());
}
/**
@@ -217,7 +221,7 @@ public class TimeSkill {
description = "Get the date of offset from today by a provided number of days")
public static String daysAgo(String days) {
int offsetDays = Integer.parseInt(days);
- return DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
+ return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR)
.format(ZonedDateTime.now().minusDays(offsetDays));
}
@@ -241,7 +245,7 @@ public class TimeSkill {
currentDate.getDayOfWeek().getDisplayName(TextStyle.FULL, systemLocale);
if (currentDayName.equalsIgnoreCase(dayName)) {
- return DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(currentDate);
+ return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR).format(currentDate);
}
}
throw new IllegalArgumentException("dayName is not recognized");
diff --git a/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java b/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java
index 184c83db38..9fc0ef0633 100644
--- a/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java
+++ b/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java
@@ -1,18 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import com.microsoft.semantickernel.orchestration.ContextVariables;
-import com.microsoft.semantickernel.orchestration.SKContext;
-
-import reactor.test.StepVerifier;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
public class FileIOSkillTest {
@@ -21,7 +16,7 @@ public class FileIOSkillTest {
// Create a temporary file with some content
String content = "Hello, World!";
Path tempFile = Files.createTempFile("test", ".txt");
- Files.write(tempFile, content.getBytes());
+ Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8));
// Create an instance of FileIOSkill
FileIOSkill fileIOSkill = new FileIOSkill();
@@ -52,7 +47,7 @@ public class FileIOSkillTest {
fileIOSkill.writeFileAsync(tempFile.toAbsolutePath().toString(), content, "UTF-8");
// Read the written file to verify the content
- String fileContents = new String(Files.readAllBytes(tempFile));
+ String fileContents = new String(Files.readAllBytes(tempFile), StandardCharsets.UTF_8);
Assertions.assertEquals(content, fileContents);
// Delete the temporary file
diff --git a/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java b/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java
index 2ccf2212c1..8ceb15c677 100644
--- a/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java
+++ b/java/semantickernel-core-skills/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java
@@ -4,10 +4,13 @@ package com.microsoft.semantickernel.coreskills;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
-import java.time.*;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Locale;
@SuppressWarnings("ReturnValueIgnored")
public class TimeSkillTest {
@@ -37,7 +40,7 @@ public class TimeSkillTest {
mocked.when(ZonedDateTime::now).thenReturn(mockDateTime);
String result = timeSkill.time();
- assertEquals("09:15:07 AM", result);
+ assertEqualsIgnoreCase("09:15:07 AM", result);
}
}
@@ -61,7 +64,7 @@ public class TimeSkillTest {
mocked.when(ZonedDateTime::now).thenReturn(mockDateTime);
String result = timeSkill.now();
- assertEquals("Sunday, January 12, 2025 9:15 AM", result);
+ assertEqualsIgnoreCase("Sunday, January 12, 2025 9:15 AM", result);
}
}
@@ -125,6 +128,10 @@ public class TimeSkillTest {
}
}
+ public void assertEqualsIgnoreCase(String a, String b) {
+ Assertions.assertEquals(a.toUpperCase(Locale.ROOT), b.toUpperCase(Locale.ROOT));
+ }
+
@Test
public void testHour() {
TimeSkill timeSkill = new TimeSkill();
@@ -133,7 +140,7 @@ public class TimeSkillTest {
mocked.when(ZonedDateTime::now).thenReturn(mockDateTime);
String result = timeSkill.hour();
- assertEquals("9 AM", result);
+ assertEqualsIgnoreCase("9 AM", result);
}
}
diff --git a/java/semantickernel-core/pom.xml b/java/semantickernel-core/pom.xml
index 071560572b..f17ab320c1 100644
--- a/java/semantickernel-core/pom.xml
+++ b/java/semantickernel-core/pom.xml
@@ -87,6 +87,11 @@
sequentialplanner-extensionstest
+
+ com.microsoft.semantickernel.extensions
+ actionplanner-extension
+ test
+ jakarta.inject
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java
index ef961886f1..f198f42896 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java
@@ -9,14 +9,12 @@ import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.coreskills.SkillImporter;
import com.microsoft.semantickernel.exceptions.NotSupportedException;
import com.microsoft.semantickernel.exceptions.SkillsNotFoundException;
+import com.microsoft.semantickernel.extensions.KernelExtensions;
import com.microsoft.semantickernel.memory.MemoryConfiguration;
import com.microsoft.semantickernel.memory.MemoryStore;
+import com.microsoft.semantickernel.memory.NullMemory;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
-import com.microsoft.semantickernel.orchestration.ContextVariables;
-import com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction;
-import com.microsoft.semantickernel.orchestration.RegistrableSkFunction;
-import com.microsoft.semantickernel.orchestration.SKContext;
-import com.microsoft.semantickernel.orchestration.SKFunction;
+import com.microsoft.semantickernel.orchestration.*;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection;
import com.microsoft.semantickernel.skilldefinition.FunctionNotFound;
@@ -26,15 +24,18 @@ import com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine;
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+
import jakarta.inject.Inject;
+
import reactor.core.publisher.Mono;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
public class DefaultKernel implements Kernel {
private final KernelConfig kernelConfig;
@@ -46,7 +47,7 @@ public class DefaultKernel implements Kernel {
public DefaultKernel(
KernelConfig kernelConfig,
PromptTemplateEngine promptTemplateEngine,
- SemanticTextMemory memory) {
+ @Nullable SemanticTextMemory memoryStore) {
if (kernelConfig == null) {
throw new IllegalArgumentException();
}
@@ -54,13 +55,16 @@ public class DefaultKernel implements Kernel {
this.kernelConfig = kernelConfig;
this.promptTemplateEngine = promptTemplateEngine;
this.defaultSkillCollection = new DefaultSkillCollection();
- this.memory = memory;
- kernelConfig.getSkills().forEach(this::registerSemanticFunction);
+ if (memoryStore != null) {
+ this.memory = memoryStore.copy();
+ } else {
+ this.memory = new NullMemory();
+ }
}
@Override
- public T getService(String serviceId, Class clazz) {
+ public T getService(@Nullable String serviceId, Class clazz) {
if (TextCompletion.class.isAssignableFrom(clazz)) {
Function factory =
kernelConfig.getTextCompletionServiceOrDefault(serviceId);
@@ -82,7 +86,7 @@ public class DefaultKernel implements Kernel {
return (T) factory.apply(this);
} else if (EmbeddingGeneration.class.isAssignableFrom(clazz)) {
- Function> factory =
+ Function> factory =
kernelConfig.getTextEmbeddingGenerationServiceOrDefault(serviceId);
if (factory == null) {
throw new KernelException(
@@ -91,7 +95,7 @@ public class DefaultKernel implements Kernel {
}
return (T) factory.apply(this);
- }else {
+ } else {
// TODO correct exception
throw new NotSupportedException(
"The kernel service collection doesn't support the type " + clazz.getName());
@@ -104,10 +108,7 @@ public class DefaultKernel implements Kernel {
}
@Override
- public <
- RequestConfiguration,
- ContextType extends SKContext,
- FunctionType extends SKFunction>
+ public >
FunctionType registerSemanticFunction(FunctionType func) {
if (!(func instanceof RegistrableSkFunction)) {
throw new RuntimeException("This function does not implement RegistrableSkFunction");
@@ -117,6 +118,11 @@ public class DefaultKernel implements Kernel {
return func;
}
+ @Override
+ public SKFunction> getFunction(String skill, String function) {
+ return defaultSkillCollection.getFunction(skill, function, null);
+ }
+
/*
///
public SKFunction registerSemanticFunction(
@@ -149,7 +155,10 @@ public class DefaultKernel implements Kernel {
.map(
(entry) -> {
return DefaultCompletionSKFunction.createFunction(
- skillName, entry.getKey(), entry.getValue());
+ skillName,
+ entry.getKey(),
+ entry.getValue(),
+ promptTemplateEngine);
})
.forEach(this::registerSemanticFunction);
@@ -163,6 +172,13 @@ public class DefaultKernel implements Kernel {
@Override
public ReadOnlyFunctionCollection importSkill(
Object skillInstance, @Nullable String skillName) {
+ if (skillInstance instanceof String) {
+ throw new KernelException(
+ KernelException.ErrorCodes.FunctionNotAvailable,
+ "Called importSkill with a string argument, it is likely the intention was to"
+ + " call importSkillFromDirectory");
+ }
+
if (skillName == null || skillName.isEmpty()) {
skillName = ReadOnlySkillCollection.GlobalSkill;
}
@@ -203,6 +219,30 @@ public class DefaultKernel implements Kernel {
return functions;
}
+ @Override
+ public ReadOnlyFunctionCollection importSkillFromDirectory(
+ String skillName, String parentDirectory, String skillDirectoryName) {
+ Map skills =
+ KernelExtensions.importSemanticSkillFromDirectory(
+ parentDirectory, skillDirectoryName, promptTemplateEngine);
+ return importSkill(skillName, skills);
+ }
+
+ @Override
+ public void importSkillsFromDirectory(String parentDirectory, String... skillNames) {
+ Arrays.stream(skillNames)
+ .forEach(
+ skill -> {
+ importSkillFromDirectory(skill, parentDirectory, skill);
+ });
+ }
+
+ @Override
+ public ReadOnlyFunctionCollection importSkillFromDirectory(
+ String skillName, String parentDirectory) {
+ return importSkillFromDirectory(skillName, parentDirectory, skillName);
+ }
+
@Override
public PromptTemplateEngine getPromptTemplateEngine() {
return promptTemplateEngine;
@@ -218,36 +258,47 @@ public class DefaultKernel implements Kernel {
}
@Override
- public Mono> runAsync(SKFunction, ?>... pipeline) {
+ public Mono runAsync(SKFunction>... pipeline) {
return runAsync(SKBuilders.variables().build(), pipeline);
}
@Override
- public Mono> runAsync(String input, SKFunction, ?>... pipeline) {
+ public Mono runAsync(String input, SKFunction>... pipeline) {
return runAsync(SKBuilders.variables().build(input), pipeline);
}
@Override
- public Mono> runAsync(ContextVariables variables, SKFunction, ?>... pipeline) {
+ public Mono runAsync(ContextVariables variables, SKFunction>... pipeline) {
if (pipeline == null || pipeline.length == 0) {
throw new SKException("No parameters provided to pipeline");
}
// TODO: The SemanticTextMemory can be null, but there should be a way to provide it.
// Not sure registerMemory is the right way.
- Mono> pipelineBuilder =
- Mono.just(pipeline[0].buildContext(variables, null, getSkills()));
+ Mono pipelineBuilder =
+ Mono.just(SKBuilders.context().with(variables).with(getSkills()).build());
for (SKFunction f : Arrays.asList(pipeline)) {
pipelineBuilder =
- pipelineBuilder.flatMap(
- newContext -> {
- SKContext context =
- f.buildContext(
- newContext.getVariables(),
- newContext.getSemanticMemory(),
- newContext.getSkills());
- return f.invokeAsync(context, null);
- });
+ pipelineBuilder
+ .switchIfEmpty(
+ Mono.fromCallable(
+ () -> {
+ // Previous pipeline did not produce a result
+ return SKBuilders.context()
+ .with(variables)
+ .with(getSkills())
+ .build();
+ }))
+ .flatMap(
+ newContext -> {
+ SKContext context =
+ SKBuilders.context()
+ .with(newContext.getVariables())
+ .with(newContext.getSemanticMemory())
+ .with(newContext.getSkills())
+ .build();
+ return f.invokeAsync(context, null);
+ });
}
return pipelineBuilder;
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java
index 8aad398bb3..0415fde19e 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel;
+import com.microsoft.semantickernel.ai.AIException;
import com.microsoft.semantickernel.builders.FunctionBuilders;
import com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
@@ -12,13 +13,10 @@ import javax.annotation.Nullable;
public class SkFunctionBuilders implements FunctionBuilders {
public SkFunctionBuilders() {}
- public static final CompletionSKFunction.Builder COMPLETION_BUILDERS =
- new InternalCompletionBuilder(null);
-
private static class InternalCompletionBuilder extends CompletionSKFunction.Builder {
- private final @Nullable Kernel kernel;
+ private final Kernel kernel;
- private InternalCompletionBuilder(@Nullable Kernel kernel) {
+ private InternalCompletionBuilder(Kernel kernel) {
this.kernel = kernel;
}
@@ -37,14 +35,17 @@ public class SkFunctionBuilders implements FunctionBuilders {
@Nullable String skillName) {
return register(
DefaultCompletionSKFunction.createFunction(
- promptTemplate, config, functionName, skillName));
+ promptTemplate,
+ config,
+ functionName,
+ skillName,
+ kernel.getPromptTemplateEngine()));
}
@Override
public CompletionSKFunction createFunction(
- String functionName, SemanticFunctionConfig functionConfig) {
- return register(
- DefaultCompletionSKFunction.createFunction(functionName, functionConfig));
+ String prompt, PromptTemplateConfig.CompletionConfig functionConfig) {
+ return createFunction(prompt, null, null, null, functionConfig);
}
@Override
@@ -54,7 +55,10 @@ public class SkFunctionBuilders implements FunctionBuilders {
SemanticFunctionConfig functionConfig) {
return register(
DefaultCompletionSKFunction.createFunction(
- skillNameFinal, functionName, functionConfig));
+ skillNameFinal,
+ functionName,
+ functionConfig,
+ kernel.getPromptTemplateEngine()));
}
@Override
@@ -78,19 +82,25 @@ public class SkFunctionBuilders implements FunctionBuilders {
@Nullable String skillName,
@Nullable String description,
PromptTemplateConfig.CompletionConfig completionConfig) {
+ if (kernel == null) {
+ throw new AIException(
+ AIException.ErrorCodes.InvalidConfiguration,
+ "Called builder to create a function that");
+ }
return register(
DefaultCompletionSKFunction.createFunction(
- prompt, functionName, skillName, description, completionConfig));
+ prompt,
+ functionName,
+ skillName,
+ description,
+ completionConfig,
+ kernel.getPromptTemplateEngine()));
}
}
@Override
- public CompletionSKFunction.Builder completionBuilders(@Nullable Kernel kernel) {
- if (kernel == null) {
- return COMPLETION_BUILDERS;
- } else {
- return new InternalCompletionBuilder(kernel);
- }
+ public CompletionSKFunction.Builder completionBuilders(Kernel kernel) {
+ return new InternalCompletionBuilder(kernel);
}
}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java
index 86288d2ca6..1f94a5e583 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java
@@ -4,17 +4,19 @@ package com.microsoft.semantickernel.memory;
import com.microsoft.semantickernel.ai.embeddings.Embedding;
import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration;
import com.microsoft.semantickernel.exceptions.NotSupportedException;
+
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
///
/// Implementation of ./>.
///
@@ -136,23 +138,28 @@ public class DefaultSemanticTextMemory implements SemanticTextMemory {
@Nullable String description,
@Nullable String additionalMetadata) {
- return this._storage.doesCollectionExistAsync(collection)
- .map(exists -> {
- if (!exists) {
- return this._storage.createCollectionAsync(collection);
- }
- return Mono.empty();
- })
- .then(this._embeddingGenerator.generateEmbeddingsAsync(Collections.singletonList(text)))
- .map(embeddings -> MemoryRecord.referenceRecord(
- externalId,
- externalSourceName,
- description,
- (Embedding) embeddings.iterator().next(),
- additionalMetadata,
- null,
- null)
- )
+ return this._storage
+ .doesCollectionExistAsync(collection)
+ .map(
+ exists -> {
+ if (!exists) {
+ return this._storage.createCollectionAsync(collection);
+ }
+ return Mono.empty();
+ })
+ .then(
+ this._embeddingGenerator.generateEmbeddingsAsync(
+ Collections.singletonList(text)))
+ .map(
+ embeddings ->
+ MemoryRecord.referenceRecord(
+ externalId,
+ externalSourceName,
+ description,
+ (Embedding) embeddings.iterator().next(),
+ additionalMetadata,
+ null,
+ null))
.flatMap(record -> this._storage.upsertAsync(collection, record));
}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java
index 0241cccbb5..26a1a257ea 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java
@@ -3,11 +3,11 @@ package com.microsoft.semantickernel.memory;
import com.microsoft.semantickernel.ai.EmbeddingVector;
import com.microsoft.semantickernel.ai.embeddings.Embedding;
+
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
-import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -20,6 +20,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.function.ToDoubleFunction;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+
/** A simple volatile memory embeddings store. */
public class VolatileMemoryStore implements MemoryStore {
@@ -159,6 +161,7 @@ public class VolatileMemoryStore implements MemoryStore {
return new EmbeddingVector((List) list);
}
+ @SuppressWarnings("UnnecessaryLambda")
private static final ToDoubleFunction>
extractSimilarity = tuple -> tuple.getT2().doubleValue();
@@ -246,6 +249,7 @@ public class VolatileMemoryStore implements MemoryStore {
public static class Builder implements MemoryStore.Builder {
public Builder() {}
+
@Override
public MemoryStore build() {
return new VolatileMemoryStore();
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKContext.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKContext.java
deleted file mode 100644
index 2352e98b38..0000000000
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKContext.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.orchestration;
-
-import com.microsoft.semantickernel.memory.SemanticTextMemory;
-import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
-
-import javax.annotation.Nullable;
-
-public class DefaultCompletionSKContext extends AbstractSKContext
- implements CompletionSKContext {
-
- DefaultCompletionSKContext(ContextVariables variables) {
- super(variables);
- }
-
- public DefaultCompletionSKContext(
- ContextVariables variables,
- @Nullable SemanticTextMemory memory,
- @Nullable ReadOnlySkillCollection skills) {
- super(variables, memory, skills);
- }
-
- @Override
- protected CompletionSKContext getThis() {
- return this;
- }
-
- @Override
- public CompletionSKContext build(
- ContextVariables variables,
- @Nullable SemanticTextMemory memory,
- @Nullable ReadOnlySkillCollection skills) {
- return new DefaultCompletionSKContext(variables, memory, skills);
- }
-}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java
index 37470a82ad..2a6e6e86bb 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java
@@ -2,19 +2,22 @@
package com.microsoft.semantickernel.orchestration;
import com.microsoft.semantickernel.Kernel;
-import com.microsoft.semantickernel.memory.SemanticTextMemory;
-import com.microsoft.semantickernel.semanticfunctions.DefaultPromptTemplate;
+import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
+import com.microsoft.semantickernel.skilldefinition.FunctionView;
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
import com.microsoft.semantickernel.skilldefinition.ParameterView;
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
+import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -32,10 +35,12 @@ import javax.annotation.Nullable;
/// with additional methods required by the kernel.
///
public class DefaultCompletionSKFunction
- extends DefaultSemanticSKFunction
+ extends DefaultSemanticSKFunction
implements CompletionSKFunction {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompletionSKFunction.class);
+
private final SemanticFunctionConfig functionConfig;
- private SKSemanticAsyncTask function;
+ private SKSemanticAsyncTask function;
private final CompletionRequestSettings requestSettings;
@Nullable private DefaultTextCompletionSupplier aiService;
@@ -107,10 +112,10 @@ public class DefaultCompletionSKFunction
* @return Aggregated results
*/
@Override
- public Mono aggregatePartitionedResultsAsync(
- List partitionedInput, @Nullable CompletionSKContext contextIn) {
+ public Mono aggregatePartitionedResultsAsync(
+ List partitionedInput, @Nullable SKContext contextIn) {
- CompletionSKContext context;
+ SKContext context;
if (contextIn == null) {
context = buildContext();
} else {
@@ -119,15 +124,15 @@ public class DefaultCompletionSKFunction
// Function that takes the current context, updates it with the latest input and invokes the
// function
- BiFunction, String, Flux> executeNextChunk =
+ BiFunction, String, Flux> executeNextChunk =
(contextInput, input) ->
contextInput.flatMap(
newContext -> {
- CompletionSKContext updated = newContext.update(input);
+ SKContext updated = newContext.update(input);
return invokeAsync(updated, null);
});
- Mono> results =
+ Mono> results =
Flux.fromIterable(partitionedInput)
.reduceWith(() -> Flux.just(context), executeNextChunk)
.flatMap(Flux::collectList);
@@ -140,24 +145,10 @@ public class DefaultCompletionSKFunction
.map(context::update);
}
- @Override
- public CompletionSKContext buildContext(
- ContextVariables variables,
- @Nullable SemanticTextMemory memory,
- @Nullable ReadOnlySkillCollection skills) {
- return new DefaultCompletionSKContext(variables, memory, skills);
- }
-
- @Override
- public CompletionSKContext buildContext(SKContext toClone) {
- return new DefaultCompletionSKContext(
- toClone.getVariables(), toClone.getSemanticMemory(), toClone.getSkills());
- }
-
// Run the semantic function
@Override
- protected Mono invokeAsyncInternal(
- CompletionSKContext context, @Nullable CompletionRequestSettings settings) {
+ protected Mono invokeAsyncInternal(
+ SKContext context, @Nullable CompletionRequestSettings settings) {
// TODO
// this.VerifyIsSemantic();
// this.ensureContextHasSkills(context);
@@ -188,15 +179,17 @@ public class DefaultCompletionSKFunction
this.function =
(TextCompletion client,
CompletionRequestSettings requestSettings,
- CompletionSKContext contextInput) -> {
- CompletionSKContext context = contextInput.copy();
+ SKContext contextInput) -> {
+ SKContext context = contextInput.copy();
// TODO
// Verify.NotNull(client, "AI LLM backed is empty");
- return functionConfig
- .getTemplate()
- .renderAsync(context, kernel.getPromptTemplateEngine())
+
+ PromptTemplate func = functionConfig.getTemplate();
+
+ return func.renderAsync(context)
.flatMapMany(
prompt -> {
+ LOGGER.debug("RENDERED PROMPT: \n" + prompt);
return client.completeAsync(prompt, requestSettings);
})
.single()
@@ -206,15 +199,13 @@ public class DefaultCompletionSKFunction
})
.doOnError(
ex -> {
- System.err.println(ex.getMessage());
- ex.printStackTrace();
- // TODO
- /*
- log ?.LogWarning(ex,
- "Something went wrong while rendering the semantic function or while executing the text completion. Function: {0}.{1}. Error: {2}",
- skillName, functionName, ex.Message);
- context.Fail(ex.Message, ex);
- */
+ LOGGER.warn(
+ "Something went wrong while rendering the semantic"
+ + " function or while executing the text"
+ + " completion. Function: {}.{}. Error: {}",
+ getSkillName(),
+ getName(),
+ ex.getMessage());
});
};
@@ -236,7 +227,8 @@ public class DefaultCompletionSKFunction
@Nullable String functionName,
@Nullable String skillName,
@Nullable String description,
- PromptTemplateConfig.CompletionConfig completion) {
+ PromptTemplateConfig.CompletionConfig completion,
+ PromptTemplateEngine promptTemplateEngine) {
if (functionName == null) {
functionName = randomFunctionName();
@@ -249,14 +241,16 @@ public class DefaultCompletionSKFunction
PromptTemplateConfig config =
new PromptTemplateConfig(description, "completion", completion);
- return createFunction(promptTemplate, config, functionName, skillName);
+ return createFunction(
+ promptTemplate, config, functionName, skillName, promptTemplateEngine);
}
public static DefaultCompletionSKFunction createFunction(
String promptTemplate,
PromptTemplateConfig config,
String functionName,
- @Nullable String skillName) {
+ @Nullable String skillName,
+ PromptTemplateEngine promptTemplateEngine) {
if (functionName == null) {
functionName = randomFunctionName();
}
@@ -267,17 +261,23 @@ public class DefaultCompletionSKFunction
// Verify.ValidSkillName(skillName);
// }
- PromptTemplate template = new DefaultPromptTemplate(promptTemplate, config);
+ PromptTemplate template =
+ SKBuilders.promptTemplate()
+ .withPromptTemplateConfig(config)
+ .withPromptTemplate(promptTemplate)
+ .build(promptTemplateEngine);
// Prepare lambda wrapping AI logic
SemanticFunctionConfig functionConfig = new SemanticFunctionConfig(config, template);
- return createFunction(skillName, functionName, functionConfig);
+ return createFunction(skillName, functionName, functionConfig, promptTemplateEngine);
}
public static DefaultCompletionSKFunction createFunction(
- String functionName, SemanticFunctionConfig functionConfig) {
- return createFunction(null, functionName, functionConfig);
+ String functionName,
+ SemanticFunctionConfig functionConfig,
+ PromptTemplateEngine promptTemplateEngine) {
+ return createFunction(null, functionName, functionConfig, promptTemplateEngine);
}
///
@@ -291,7 +291,8 @@ public class DefaultCompletionSKFunction
public static DefaultCompletionSKFunction createFunction(
@Nullable String skillNameFinal,
String functionName,
- SemanticFunctionConfig functionConfig) {
+ SemanticFunctionConfig functionConfig,
+ PromptTemplateEngine promptTemplateEngine) {
String skillName = skillNameFinal;
// Verify.NotNull(functionConfig, "Function configuration is empty");
if (skillName == null) {
@@ -302,9 +303,11 @@ public class DefaultCompletionSKFunction
CompletionRequestSettings.fromCompletionConfig(
functionConfig.getConfig().getCompletionConfig());
+ PromptTemplate promptTemplate = functionConfig.getTemplate();
+
return new DefaultCompletionSKFunction(
DelegateTypes.ContextSwitchInSKContextOutTaskSKContext,
- functionConfig.getTemplate().getParameters(),
+ promptTemplate.getParameters(),
skillName,
functionName,
functionConfig.getConfig().getDescription(),
@@ -312,4 +315,15 @@ public class DefaultCompletionSKFunction
functionConfig,
null);
}
+
+ @Override
+ public FunctionView describe() {
+ return new FunctionView(
+ super.getName(),
+ super.getSkillName(),
+ super.getDescription(),
+ super.getParameters(),
+ true,
+ false);
+ }
}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java
index 19e975af3e..9473cca069 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java
@@ -42,6 +42,7 @@ class DefaultContextVariables implements ContextVariables, WritableContextVariab
return this;
}
+ @Override
public ContextVariables appendToVariable(@NonNull String key, @NonNull String content) {
String existing = this.variables.get(key);
@@ -67,6 +68,7 @@ class DefaultContextVariables implements ContextVariables, WritableContextVariab
// result for the user
/// if the pipeline reached the end.
/// The current instance
+ @Override
public ContextVariables update(@NonNull String content) {
return setVariable(MAIN_KEY, content);
}
@@ -84,6 +86,7 @@ class DefaultContextVariables implements ContextVariables, WritableContextVariab
// data.
/// The current instance
+ @Override
public DefaultContextVariables update(@NonNull ContextVariables newData, boolean merge) {
/*
// If requested, discard old data and keep only the new one.
@@ -99,11 +102,37 @@ class DefaultContextVariables implements ContextVariables, WritableContextVariab
return this;
}
+ @Override
+ public ContextVariables remove(String key) {
+ variables.remove(key);
+ return this;
+ }
+
@Override
public WritableContextVariables writableClone() {
return new DefaultContextVariables(variables);
}
+ @Override
+ @Nullable
+ public String getInput() {
+ return get(MAIN_KEY);
+ }
+
+ @Override
+ public String prettyPrint() {
+ return variables.entrySet().stream()
+ .reduce(
+ "",
+ (str, entry) ->
+ str
+ + System.lineSeparator()
+ + entry.getKey()
+ + ": "
+ + entry.getValue(),
+ (a, b) -> a + b);
+ }
+
@Override
@Nullable
public String get(String key) {
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java
new file mode 100644
index 0000000000..edda3a8eb8
--- /dev/null
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java
@@ -0,0 +1,105 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.orchestration;
+
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.memory.NullMemory;
+import com.microsoft.semantickernel.memory.SemanticTextMemory;
+import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
+
+import javax.annotation.Nullable;
+
+public class DefaultSKContext extends AbstractSKContext {
+ public DefaultSKContext(ContextVariables variables) {
+ super(variables);
+ }
+
+ public DefaultSKContext(
+ ContextVariables variables,
+ @Nullable SemanticTextMemory memory,
+ @Nullable ReadOnlySkillCollection skillCollection) {
+ super(variables, memory, skillCollection);
+ }
+
+ @Override
+ protected SKContext getThis() {
+ return this;
+ }
+
+ @Override
+ public SKContext build(
+ ContextVariables variables,
+ @Nullable SemanticTextMemory memory,
+ @Nullable ReadOnlySkillCollection skillCollection) {
+ return new DefaultSKContext(variables, memory, skillCollection);
+ }
+
+ public static class Builder implements SKContext.Builder {
+
+ private ContextVariables variables;
+ private ReadOnlySkillCollection skills;
+ private SemanticTextMemory memory = NullMemory.getInstance();
+
+ @Override
+ public SKContext build(ReadOnlySkillCollection skills) {
+ return new DefaultSKContext(
+ SKBuilders.variables().build(), NullMemory.getInstance(), skills);
+ }
+
+ @Override
+ public SKContext build() {
+ if (variables == null) {
+ variables = SKBuilders.variables().build();
+ }
+ return new DefaultSKContext(variables, memory, skills);
+ }
+
+ @Override
+ public SKContext build(Class extends SKContext> clazz) {
+ return null;
+ }
+
+ @Override
+ public SKContext.Builder with(ContextVariables variables) {
+ this.variables = variables;
+ return this;
+ }
+
+ @Override
+ public SKContext.Builder with(@Nullable ReadOnlySkillCollection skills) {
+ if (skills != null) {
+ this.skills = skills;
+ }
+ return this;
+ }
+
+ @Override
+ public SKContext.Builder with(@Nullable SemanticTextMemory memory) {
+ if (memory != null) {
+ this.memory = memory.copy();
+ }
+ return this;
+ }
+
+ @Override
+ public SKContext.Builder clone(SKContext context) {
+ return with(context.getVariables())
+ .with(context.getSkills())
+ .with(context.getSemanticMemory());
+ }
+
+ @Override
+ public SKContext build(Kernel kernel) {
+ if (memory == null) {
+ memory = kernel.getMemory();
+ }
+ if (skills == null) {
+ skills = kernel.getSkills();
+ }
+ if (variables == null) {
+ variables = SKBuilders.variables().build();
+ }
+ return build();
+ }
+ }
+}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKContext.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKContext.java
deleted file mode 100644
index aef950fee9..0000000000
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.orchestration;
-
-import com.microsoft.semantickernel.builders.SKBuilders;
-import com.microsoft.semantickernel.memory.NullMemory;
-import com.microsoft.semantickernel.memory.SemanticTextMemory;
-import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
-
-import javax.annotation.Nullable;
-
-public class DefaultSemanticSKContext extends AbstractSKContext
- implements SemanticSKContext {
- public DefaultSemanticSKContext(ContextVariables variables) {
- super(variables);
- }
-
- public DefaultSemanticSKContext(
- ContextVariables variables,
- @Nullable SemanticTextMemory memory,
- @Nullable ReadOnlySkillCollection skillCollection) {
- super(variables, memory, skillCollection);
- }
-
- @Override
- protected SemanticSKContext getThis() {
- return this;
- }
-
- @Override
- public SemanticSKContext build(
- ContextVariables variables,
- @Nullable SemanticTextMemory memory,
- @Nullable ReadOnlySkillCollection skillCollection) {
- return new DefaultSemanticSKContext(variables, memory, skillCollection);
- }
-
- public static class Builder implements SKContext.Builder {
-
- @Override
- public SKContext build(ReadOnlySkillCollection skills) {
- return new DefaultSemanticSKContext(
- SKBuilders.variables().build(), NullMemory.getInstance(), skills);
- }
- }
-}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java
index 0fe413fc1c..89b2771756 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java
@@ -18,10 +18,9 @@ import javax.annotation.Nullable;
// cref="Action"/>,
/// with additional methods required by the kernel.
///
-public abstract class DefaultSemanticSKFunction<
- RequestConfiguration, ContextType extends SKContext>
- extends AbstractSkFunction
- implements SKFunction {
+public abstract class DefaultSemanticSKFunction
+ extends AbstractSkFunction
+ implements SKFunction {
public DefaultSemanticSKFunction(
DelegateTypes delegateType,
@@ -34,20 +33,25 @@ public abstract class DefaultSemanticSKFunction<
}
@Override
- public Mono invokeAsync(
- String input, @Nullable ContextType context, @Nullable RequestConfiguration settings) {
+ public Mono invokeAsync(
+ @Nullable String input,
+ @Nullable SKContext context,
+ @Nullable RequestConfiguration settings) {
if (context == null) {
assertSkillSupplierRegistered();
context =
- buildContext(
- SKBuilders.variables().build(),
- NullMemory.getInstance(),
- super.getSkillsSupplier().get());
+ SKBuilders.context()
+ .with(SKBuilders.variables().build())
+ .with(NullMemory.getInstance())
+ .with(super.getSkillsSupplier().get())
+ .build();
} else {
context = context.copy();
}
- context = context.update(input);
+ if (input != null) {
+ context = context.update(input);
+ }
return this.invokeAsync(context, settings);
}
diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java
index c1ec88be83..b3ccc57308 100644
--- a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java
+++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java
@@ -5,7 +5,7 @@ import static com.microsoft.semantickernel.skilldefinition.annotations.SKFunctio
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.ai.AIException;
-import com.microsoft.semantickernel.memory.SemanticTextMemory;
+import com.microsoft.semantickernel.skilldefinition.FunctionView;
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
import com.microsoft.semantickernel.skilldefinition.ParameterView;
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
@@ -17,6 +17,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -32,15 +33,15 @@ import javax.annotation.Nullable;
// cref="Action"/>,
/// with additional methods required by the kernel.
///
-public class NativeSKFunction extends AbstractSkFunction {
+public class NativeSKFunction extends AbstractSkFunction {
private static final Logger LOGGER = LoggerFactory.getLogger(NativeSKFunction.class);
- private final SKNativeTask function;
+ private final SKNativeTask function;
public NativeSKFunction(
AbstractSkFunction.DelegateTypes delegateType,
- SKNativeTask delegateFunction,
+ SKNativeTask delegateFunction,
List parameters,
String skillName,
String functionName,
@@ -56,6 +57,17 @@ public class NativeSKFunction extends AbstractSkFunction getType() {
return Void.class;
@@ -69,7 +81,7 @@ public class NativeSKFunction extends AbstractSkFunction function;
+ public final SKNativeTask function;
public final List parameters;
public final String name;
public final String description;
@@ -77,7 +89,7 @@ public class NativeSKFunction extends AbstractSkFunction function,
+ SKNativeTask function,
List parameters,
String name,
String description) {
@@ -116,24 +128,9 @@ public class NativeSKFunction extends AbstractSkFunction invokeAsyncInternal(
- SemanticSKContext context, @Nullable Void settings) {
+ protected Mono invokeAsyncInternal(SKContext context, @Nullable Void settings) {
return this.function.run(context);
}
@@ -142,7 +139,6 @@ public class NativeSKFunction extends AbstractSkFunction parameters = new ArrayList<>();
boolean hasSkFunctionAttribute =
methodSignature.isAnnotationPresent(DefineSKFunction.class);
@@ -151,8 +147,7 @@ public class NativeSKFunction extends AbstractSkFunction function =
- getFunction(methodSignature, methodContainerInstance);
+ SKNativeTask function = getFunction(methodSignature, methodContainerInstance);
// boolean hasStringParam =
// Arrays.asList(methodSignature.getGenericParameterTypes()).contains(String.class);
@@ -165,18 +160,61 @@ public class NativeSKFunction extends AbstractSkFunction parameters = getParameters(methodSignature);
+
return new MethodDetails(
hasSkFunctionAttribute, type, function, parameters, name, description);
}
- private static SKNativeTask getFunction(Method method, Object instance) {
+ private static List getParameters(Method method) {
+
+ List params =
+ Arrays.stream(method.getParameters())
+ .filter(
+ parameter ->
+ parameter.isAnnotationPresent(SKFunctionParameters.class)
+ || parameter.isAnnotationPresent(
+ SKFunctionInputAttribute.class))
+ .map(
+ parameter -> {
+ if (parameter.isAnnotationPresent(SKFunctionParameters.class)) {
+ SKFunctionParameters annotation =
+ parameter.getAnnotation(SKFunctionParameters.class);
+ return new ParameterView(
+ annotation.name(),
+ annotation.description(),
+ annotation.defaultValue());
+ } else {
+ return new ParameterView("input");
+ }
+ })
+ .collect(Collectors.toList());
+
+ HashSet out = new HashSet<>(params);
+
+ boolean hasInput = params.stream().anyMatch(p -> p.getName().equals("input"));
+
+ if (!hasInput) {
+ List inputArgs =
+ determineInputArgs(method).stream()
+ .map(
+ parameter -> {
+ return new ParameterView("input");
+ })
+ .collect(Collectors.toList());
+ out.addAll(inputArgs);
+ }
+
+ return new ArrayList<>(out);
+ }
+
+ private static SKNativeTask getFunction(Method method, Object instance) {
return (contextInput) -> {
- SemanticSKContext context = contextInput.copy();
+ SKContext context = contextInput.copy();
Set inputArgs = determineInputArgs(method);
try {
-
List
+
+ com.microsoft.semantickernel.extensions
+ actionplanner-extension
+
diff --git a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/SequentialPlannerSKContext.java b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/SequentialPlannerSKContext.java
deleted file mode 100644
index 3d4c132a3b..0000000000
--- a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/SequentialPlannerSKContext.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.planner;
-
-import com.microsoft.semantickernel.orchestration.SKContext;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
-
-import reactor.core.publisher.Mono;
-
-import javax.annotation.Nullable;
-
-public interface SequentialPlannerSKContext extends SKContext {
-
- public static final String PlannerMemoryCollectionName = "Planning.SKFunctionsManual";
-
- public static final String PlanSKFunctionsAreRemembered = "Planning.SKFunctionsAreRemembered";
-
- public Mono getFunctionsManualAsync(
- @Nullable String semanticQuery, @Nullable SequentialPlannerRequestSettings config);
-}
diff --git a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java
index 89bbe9b584..80a8d50351 100644
--- a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java
+++ b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java
@@ -1,16 +1,12 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.planner.sequentialplanner;
-import static com.microsoft.semantickernel.planner.SequentialPlannerSKContext.PlanSKFunctionsAreRemembered;
-import static com.microsoft.semantickernel.planner.SequentialPlannerSKContext.PlannerMemoryCollectionName;
-
import com.microsoft.semantickernel.memory.MemoryQueryResult;
import com.microsoft.semantickernel.memory.NullMemory;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
+import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
-import com.microsoft.semantickernel.planner.SequentialPlannerRequestSettings;
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -21,9 +17,12 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class DefaultSequentialPlannerSKContext {
- private final CompletionSKContext delegate;
+ public static final String PlannerMemoryCollectionName = "Planning.SKFunctionsManual";
- public DefaultSequentialPlannerSKContext(CompletionSKContext delegate) {
+ public static final String PlanSKFunctionsAreRemembered = "Planning.SKFunctionsAreRemembered";
+ private final SKContext delegate;
+
+ public DefaultSequentialPlannerSKContext(SKContext delegate) {
this.delegate = delegate;
}
@@ -41,7 +40,7 @@ public class DefaultSequentialPlannerSKContext {
config = new SequentialPlannerRequestSettings();
}
- Mono>> functions =
+ Mono>> functions =
getAvailableFunctionsAsync(config, semanticQuery);
return functions.map(
@@ -61,7 +60,7 @@ public class DefaultSequentialPlannerSKContext {
// functions
/// A list of functions that are available to the user based on the semantic query and
// the excluded skills and functions.
- public Mono>> getAvailableFunctionsAsync(
+ public Mono>> getAvailableFunctionsAsync(
SequentialPlannerRequestSettings config, @Nullable String semanticQuery) {
Set excludedSkills = config.getExcludedSkills();
Set excludedFunctions = config.getExcludedFunctions();
@@ -70,14 +69,14 @@ public class DefaultSequentialPlannerSKContext {
// context.ThrowIfSkillCollectionNotSet();
ReadOnlySkillCollection skills = delegate.getSkills();
- List> functions;
+ List> functions;
if (skills != null) {
functions = skills.getAllFunctions().getAll();
} else {
functions = Collections.emptyList();
}
- List> availableFunctions =
+ List> availableFunctions =
functions.stream()
/*
// Is there any function that should be excluded?
@@ -93,8 +92,8 @@ public class DefaultSequentialPlannerSKContext {
&& !excludedFunctions.contains(s.getName()))
.collect(Collectors.toList());
- Comparator> comparator =
- Comparator., String>comparing(SKFunction::getSkillName)
+ Comparator> comparator =
+ Comparator., String>comparing(SKFunction::getSkillName)
.thenComparing(SKFunction::getName);
if (semanticQuery == null
@@ -104,7 +103,7 @@ public class DefaultSequentialPlannerSKContext {
|| config.getRelevancyThreshold() == null) {
// If no semantic query is provided, return all available functions.
// If a Memory provider has not been registered, return all available functions.
- TreeSet> result = new TreeSet<>(comparator);
+ TreeSet> result = new TreeSet<>(comparator);
result.addAll(availableFunctions);
return Mono.just(result);
} else {
@@ -115,8 +114,7 @@ public class DefaultSequentialPlannerSKContext {
SemanticTextMemory updatedMemory =
updatedContext.getSemanticMemory();
if (updatedMemory == null) {
- return Mono.just(
- new ArrayList>());
+ return Mono.just(new ArrayList>());
}
// Search for functions that match the semantic query.
return updatedMemory
@@ -138,26 +136,26 @@ public class DefaultSequentialPlannerSKContext {
.map(SKFunction::getName)
.collect(Collectors.toList());
- List> missingFunctions =
+ List> missingFunctions =
getMissingFunctions(
includedFunctions, availableFunctions, added);
- ArrayList> res = new ArrayList<>(memories);
+ ArrayList> res = new ArrayList<>(memories);
res.addAll(missingFunctions);
return res;
})
.map(
res -> {
- TreeSet> result = new TreeSet<>(comparator);
+ TreeSet> result = new TreeSet<>(comparator);
result.addAll(availableFunctions);
return result;
});
}
}
- private static List> getMissingFunctions(
+ private static List> getMissingFunctions(
Set includedFunctions,
- List> availableFunctions,
+ List> availableFunctions,
List added) {
return includedFunctions.stream()
.filter(func -> !added.contains(func))
@@ -168,8 +166,8 @@ public class DefaultSequentialPlannerSKContext {
.collect(Collectors.toList());
}
- public Mono extends List extends SKFunction, ?>>> getRelevantFunctionsAsync(
- List> availableFunctions, List memories) {
+ public Mono extends List extends SKFunction>>> getRelevantFunctionsAsync(
+ List> availableFunctions, List memories) {
return Flux.fromIterable(memories)
.map(
memoryEntry ->
@@ -190,7 +188,7 @@ public class DefaultSequentialPlannerSKContext {
///
/// The SKContext to save the functions to.
/// The available functions to save.
- Mono rememberFunctionsAsync(List> availableFunctions) {
+ Mono rememberFunctionsAsync(List> availableFunctions) {
// Check if the functions have already been saved to memory.
if (delegate.getVariables().asMap().containsKey(PlanSKFunctionsAreRemembered)) {
return Mono.just(delegate);
diff --git a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java
new file mode 100644
index 0000000000..618f96db1c
--- /dev/null
+++ b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java
@@ -0,0 +1,213 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.planner.sequentialplanner;
+
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.orchestration.SKFunction;
+import com.microsoft.semantickernel.orchestration.WritableContextVariables;
+import com.microsoft.semantickernel.planner.PlanningException;
+import com.microsoft.semantickernel.planner.actionplanner.Plan;
+import com.microsoft.semantickernel.skilldefinition.FunctionView;
+import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+/** Parse sequential plan text into a plan. */
+public class SequentialPlanParser {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SequentialPlanParser.class);
+
+ // The tag name used in the plan xml for the user's goal/ask.
+ private static final String GoalTag = "goal";
+
+ // The tag name used in the plan xml for the solution.
+ private static final String SolutionTag = "plan";
+
+ // The tag name used in the plan xml for a step that calls a skill function.
+ private static final String FunctionTag = "function.";
+
+ // The attribute tag used in the plan xml for setting the context variable name to set the
+ // output of a function to.
+ private static final String SetContextVariableTag =
+ "setContextVariable".toLowerCase(Locale.ROOT);
+
+ // The attribute tag used in the plan xml for appending the output of a function to the final
+ // result for a plan.
+ private static final String AppendToResultTag = "appendToResult".toLowerCase(Locale.ROOT);
+
+ /**
+ * Convert a plan xml string to a plan
+ *
+ * @param xmlString The plan xml string
+ * @param goal The goal for the plan
+ * @param context The semantic kernel context
+ * @return The plan
+ * @throws PlanningException
+ */
+ public static Plan toPlanFromXml(String xmlString, String goal, SKContext context)
+ throws PlanningException {
+
+ try {
+ DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ Document doc =
+ db.parse(
+ new ByteArrayInputStream(
+ ("" + xmlString + "")
+ .getBytes(StandardCharsets.UTF_8)));
+
+ NodeList solution = doc.getElementsByTagName(SolutionTag);
+
+ Plan plan = new Plan(goal, context::getSkills);
+
+ for (int i = 0; i < solution.getLength(); i++) {
+ Node solutionNode = solution.item(i);
+ String parentNodeName = solutionNode.getNodeName();
+
+ for (int j = 0; j < solutionNode.getChildNodes().getLength(); j++) {
+ Node childNode = solutionNode.getChildNodes().item(j);
+ if (childNode.getNodeName().equals("#text")) {
+ if (childNode.getNodeValue() != null
+ && !childNode.getNodeValue().trim().isEmpty()) {
+ plan.addSteps(
+ new Plan(childNode.getNodeValue().trim(), context::getSkills));
+ }
+ continue;
+ }
+
+ if (childNode.getNodeName().toLowerCase(Locale.ROOT).startsWith(FunctionTag)) {
+ String[] skillFunctionNameParts =
+ childNode.getNodeName().split(FunctionTag, -1);
+ String skillFunctionName = "";
+
+ if (skillFunctionNameParts.length > 1) {
+ skillFunctionName = skillFunctionNameParts[1];
+ }
+
+ String skillName = getSkillName(skillFunctionName);
+ String functionName = getFunctionName(skillFunctionName);
+
+ ReadOnlySkillCollection skills = context.getSkills();
+ if (functionName != null
+ && !functionName.isEmpty()
+ && skills.hasFunction(skillName, functionName)) {
+ SKFunction skillFunction =
+ Objects.requireNonNull(
+ context.getSkills().getFunctions(skillName))
+ .getFunction(functionName, SKFunction.class);
+
+ WritableContextVariables functionVariables =
+ getFunctionVariables(skillFunction, childNode);
+ List functionOutputs = getFunctionOutputs(childNode);
+ List functionResults = getFunctionResults(childNode);
+
+ Plan planStep =
+ new Plan(
+ skillFunction,
+ functionVariables,
+ SKBuilders.variables().build(),
+ functionOutputs,
+ context::getSkills);
+
+ plan.addOutputs(functionResults);
+ plan.addSteps(planStep);
+ } else {
+ LOGGER.trace(
+ "{}: appending function node {}",
+ parentNodeName,
+ skillFunctionName);
+ plan.addSteps(new Plan(childNode.getTextContent(), context::getSkills));
+ }
+
+ continue;
+ }
+
+ plan.addSteps(new Plan(childNode.getTextContent(), context::getSkills));
+ }
+ }
+ return plan;
+
+ } catch (RuntimeException | ParserConfigurationException | IOException | SAXException e) {
+ throw new PlanningException(
+ PlanningException.ErrorCodes.InvalidPlan, "Failed to parse plan xml.", e);
+ }
+ }
+
+ private static WritableContextVariables getFunctionVariables(
+ SKFunction skillFunction, Node node) {
+ WritableContextVariables functionVariables = SKBuilders.variables().build().writableClone();
+
+ FunctionView description = skillFunction.describe();
+
+ if (description != null) {
+ description
+ .getParameters()
+ .forEach(
+ p -> {
+ functionVariables.setVariable(p.getName(), p.getDefaultValue());
+ });
+ }
+
+ if (node.getAttributes() != null) {
+ for (int k = 0; k < node.getAttributes().getLength(); k++) {
+ Node attr = node.getAttributes().item(k);
+ String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT);
+ if (!nodeName.equals(SetContextVariableTag)
+ && !nodeName.equals(AppendToResultTag)) {
+ functionVariables.setVariable(attr.getNodeName(), attr.getTextContent());
+ }
+ }
+ }
+ return functionVariables;
+ }
+
+ private static List getFunctionOutputs(Node node) {
+ List functionOutputs = new ArrayList<>();
+ for (int k = 0; k < node.getAttributes().getLength(); k++) {
+ Node attr = node.getAttributes().item(k);
+ String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT);
+ if (nodeName.equals(SetContextVariableTag) || nodeName.equals(AppendToResultTag)) {
+ functionOutputs.add(attr.getTextContent());
+ }
+ }
+ return functionOutputs;
+ }
+
+ private static List getFunctionResults(Node node) {
+ List functionResults = new ArrayList<>();
+ for (int k = 0; k < node.getAttributes().getLength(); k++) {
+ Node attr = node.getAttributes().item(k);
+ String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT);
+ if (nodeName.equals(AppendToResultTag)) {
+ functionResults.add(attr.getTextContent());
+ }
+ }
+ return functionResults;
+ }
+
+ private static String getSkillName(String skillFunctionName) {
+ String[] skillFunctionNameParts = skillFunctionName.split("\\.", -1);
+ return skillFunctionNameParts.length > 0 ? skillFunctionNameParts[0] : "";
+ }
+
+ private static String getFunctionName(String skillFunctionName) {
+ String[] skillFunctionNameParts = skillFunctionName.split("\\.", -1);
+ return skillFunctionNameParts.length > 1 ? skillFunctionNameParts[1] : skillFunctionName;
+ }
+}
diff --git a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java
index 45dea1d4fc..3735ed1eb3 100644
--- a/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java
+++ b/java/semantickernel-extensions-parent/sequentialplanner-extensions/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java
@@ -3,43 +3,36 @@ package com.microsoft.semantickernel.planner.sequentialplanner;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.builders.FunctionBuilders;
-import com.microsoft.semantickernel.planner.SequentialPlannerRequestSettings;
+import com.microsoft.semantickernel.builders.SKBuilders;
+import com.microsoft.semantickernel.orchestration.SKContext;
+import com.microsoft.semantickernel.planner.PlanningException;
+import com.microsoft.semantickernel.planner.actionplanner.Plan;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
-import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import reactor.core.publisher.Mono;
-import java.util.ArrayList;
-
import javax.annotation.Nullable;
-///
-/// A planner that uses semantic function to create a sequential plan.
-///
+/** A planner that uses semantic function to create a sequential plan. */
public class SequentialPlanner {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SequentialPlanner.class);
private static final String StopSequence = "