mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Java: Apply ADR 008 (#3366)
Closed #2417 in favour of this PR which also includes @relango s commits. This PR updates for full support for ADR 008 (https://github.com/microsoft/semantic-kernel/blob/main/docs/decisions/0008-support-generic-llm-request-settings.md), which is the ADR in this area. This PR does the following: - Updates the code to support ADR 008. - Apply code formatting needed on these - If you dont want do do this PR via your branch I can PR it directly and close this PR. Now you can add serviceId and model to invocation, i.e: `` Mono<SKContext> result = function.invokeAsync("time travel to dinosaur age", SKBuilders .completionRequestSettings() .serviceId("text-davinci-003") .build()); `` function config, i.e: ``` var function = kernel. getSemanticFunctionBuilder() .withPromptTemplate("tell a joke about {{$input}}") .withRequestSettings( SKBuilders.completionRequestSettings() .temperature(0.4) .topP(1) .maxTokens(100) .serviceId("text-davinci-003") .build()) .build(); ``` Or config file ``` { "schema": 1, "description": "Sample plugin with a model and service id", "type": "completion", "completion": { "max_tokens": 150, "temperature": 0.9, "top_p": 0.0, "presence_penalty": 0.6, "frequency_penalty": 0.0, "service_id": "text-davinci-003", "model_id": "text-davinci-003" } } ``` --------- Co-authored-by: Rajasekar Elango <[email protected]>
This commit is contained in:
co-authored by
Rajasekar Elango
parent
299bde90bd
commit
aff5552977
@@ -4,7 +4,6 @@ import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.io.IOException;
|
||||
@@ -106,8 +105,14 @@ public class InlineFunctionExample {
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
if (summarize == null) {
|
||||
|
||||
+38
-32
@@ -4,7 +4,6 @@ import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.io.IOException;
|
||||
@@ -17,6 +16,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class InlineFunctionWithPreBuiltSkillExample {
|
||||
|
||||
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
|
||||
private static final Logger LOGGER =
|
||||
LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class);
|
||||
@@ -26,35 +26,35 @@ public class InlineFunctionWithPreBuiltSkillExample {
|
||||
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];
|
||||
""";
|
||||
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 {
|
||||
@@ -108,8 +108,14 @@ public class InlineFunctionWithPreBuiltSkillExample {
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
if (summarize == null) {
|
||||
|
||||
+8
-3
@@ -5,7 +5,6 @@ import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -50,8 +49,14 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("ChatBot")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.7)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build();
|
||||
|
||||
+9
-3
@@ -2,9 +2,9 @@
|
||||
package com.microsoft.semantickernel.e2e;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
@@ -26,8 +26,14 @@ public class InlineFunctionTest extends AbstractKernelTest {
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
String text =
|
||||
|
||||
+17
-9
@@ -7,7 +7,6 @@ import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.io.IOException;
|
||||
@@ -18,6 +17,7 @@ import org.slf4j.LoggerFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class KernelTest extends AbstractKernelTest {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KernelTest.class);
|
||||
|
||||
private static void executeCompletion(Kernel kernel) {
|
||||
@@ -25,23 +25,31 @@ public class KernelTest extends AbstractKernelTest {
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(
|
||||
"""
|
||||
{{$input}}
|
||||
{{$input}}
|
||||
|
||||
One line TLDR with the fewest words.""")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256))
|
||||
One line TLDR with the fewest words.""")
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0)
|
||||
.topP(0)
|
||||
.maxTokens(256)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
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""";
|
||||
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<SKContext> 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) {
|
||||
|
||||
+2
-1
@@ -179,6 +179,7 @@ public class SequentialPlanTest {
|
||||
Kernel kernel = SKBuilders.kernel().build();
|
||||
kernel.importSkill(new Skills(), "Skills");
|
||||
|
||||
return SequentialPlanParser.toPlanFromXml(planString.stripIndent(), "", kernel.getSkills());
|
||||
return SequentialPlanParser.toPlanFromXml(
|
||||
planString.stripIndent(), "", kernel.getSkills(), kernel::getService);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-3
@@ -76,7 +76,7 @@ public class OpenAITextCompletion extends ClientBase implements TextCompletion {
|
||||
|
||||
private Flux<String> generateMessageStream(CompletionsOptions completionsOptions) {
|
||||
return getClient()
|
||||
.getCompletionsStream(getModelId(), completionsOptions)
|
||||
.getCompletionsStream(getModelId(completionsOptions), completionsOptions)
|
||||
.groupBy(Completions::getId)
|
||||
.concatMap(
|
||||
completionResult -> {
|
||||
@@ -103,12 +103,28 @@ public class OpenAITextCompletion extends ClientBase implements TextCompletion {
|
||||
CompletionsOptions completionsOptions = getCompletionsOptions(text, requestSettings);
|
||||
|
||||
return getClient()
|
||||
.getCompletions(getModelId(), completionsOptions)
|
||||
.getCompletions(getModelId(requestSettings), completionsOptions)
|
||||
.flatMapIterable(Completions::getChoices)
|
||||
.mapNotNull(Choice::getText)
|
||||
.collectList();
|
||||
}
|
||||
|
||||
private String getModelId(CompletionRequestSettings requestSettings) {
|
||||
String model = requestSettings.getModelId();
|
||||
if (model == null) {
|
||||
model = getModelId();
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private String getModelId(CompletionsOptions completionsOptions) {
|
||||
String model = completionsOptions.getModel();
|
||||
if (model == null) {
|
||||
model = getModelId();
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private CompletionsOptions getCompletionsOptions(
|
||||
String text, CompletionRequestSettings requestSettings) {
|
||||
if (requestSettings.getMaxTokens() < 1) {
|
||||
@@ -122,7 +138,7 @@ public class OpenAITextCompletion extends ClientBase implements TextCompletion {
|
||||
.setTopP(requestSettings.getTopP())
|
||||
.setFrequencyPenalty(requestSettings.getFrequencyPenalty())
|
||||
.setPresencePenalty(requestSettings.getPresencePenalty())
|
||||
.setModel(getModelId())
|
||||
.setModel(getModelId(requestSettings))
|
||||
.setUser(requestSettings.getUser())
|
||||
.setBestOf(requestSettings.getBestOf())
|
||||
.setLogitBias(new HashMap<>());
|
||||
|
||||
+11
-5
@@ -8,7 +8,6 @@ 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.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
|
||||
@@ -34,6 +33,7 @@ import reactor.core.publisher.Mono;
|
||||
/// the Plan object in future.
|
||||
/// </summary>
|
||||
public class ActionPlanner {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ActionPlanner.class);
|
||||
|
||||
// Extracts the json portion of a plan between the braces, stripping off any non-json content
|
||||
@@ -71,8 +71,14 @@ public class ActionPlanner {
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(promptTemplate)
|
||||
.withSkillName(SkillName)
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.0, 0.0, 0.0, 0.0, 1024))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.0)
|
||||
.topP(0.0)
|
||||
.maxTokens(1024)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
kernel.importSkill(this, SkillName);
|
||||
@@ -150,9 +156,9 @@ public class ActionPlanner {
|
||||
|
||||
if (function == null) {
|
||||
// No function was found - return a plan with no steps.
|
||||
return new Plan(goal, variables, () -> kernel.getSkills());
|
||||
return new Plan(goal, variables, kernel::getSkills, kernel::getService);
|
||||
} else {
|
||||
return new Plan(goal, variables, () -> kernel.getSkills(), function);
|
||||
return new Plan(goal, variables, kernel::getSkills, kernel::getService, function);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+47
-18
@@ -5,13 +5,14 @@ import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.Verify;
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
import com.microsoft.semantickernel.orchestration.AbstractSkFunction;
|
||||
import com.microsoft.semantickernel.orchestration.AIFunction;
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
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.PlanningException.ErrorCodes;
|
||||
import com.microsoft.semantickernel.services.AIServiceSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.FunctionView;
|
||||
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
@@ -30,7 +31,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/** Standard Semantic Kernel callable plan. Plan is used to create trees of SKFunctions. */
|
||||
public class Plan extends AbstractSkFunction<CompletionRequestSettings> {
|
||||
public class Plan extends AIFunction<CompletionRequestSettings> {
|
||||
|
||||
private static final Pattern s_variablesRegex = Pattern.compile("\\$(\\w+)", Pattern.MULTILINE);
|
||||
|
||||
@@ -53,33 +54,40 @@ public class Plan extends AbstractSkFunction<CompletionRequestSettings> {
|
||||
public Plan(
|
||||
String goal,
|
||||
ContextVariables state,
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier,
|
||||
@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
super(
|
||||
new ArrayList<>(),
|
||||
Plan.class.getName(),
|
||||
"",
|
||||
goal,
|
||||
Collections.emptyList(),
|
||||
kernelSkillsSupplier);
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public Plan(String goal, @Nullable KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
this(goal, SKBuilders.variables().build(), kernelSkillsSupplier);
|
||||
public Plan(
|
||||
String goal,
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier,
|
||||
@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
this(goal, SKBuilders.variables().build(), kernelSkillsSupplier, aiServiceSupplier);
|
||||
}
|
||||
|
||||
public Plan(
|
||||
SKFunction<?> function,
|
||||
ContextVariables state,
|
||||
List<String> functionOutputs,
|
||||
KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier) {
|
||||
super(
|
||||
function.describe().getParameters(),
|
||||
function.getSkillName(),
|
||||
function.getName(),
|
||||
function.getDescription(),
|
||||
formReturnParameters(functionOutputs),
|
||||
kernelSkillsSupplier);
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
|
||||
this.parameters = null;
|
||||
this.function = function;
|
||||
@@ -92,14 +100,16 @@ public class Plan extends AbstractSkFunction<CompletionRequestSettings> {
|
||||
@Nullable ContextVariables parameters,
|
||||
ContextVariables state,
|
||||
List<String> functionOutputs,
|
||||
KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier) {
|
||||
super(
|
||||
function.describe().getParameters(),
|
||||
function.getSkillName(),
|
||||
function.getName(),
|
||||
function.getDescription(),
|
||||
formReturnParameters(functionOutputs),
|
||||
kernelSkillsSupplier);
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
this.parameters = parameters;
|
||||
this.function = function;
|
||||
this.outputs = new ArrayList<>(functionOutputs);
|
||||
@@ -113,25 +123,44 @@ public class Plan extends AbstractSkFunction<CompletionRequestSettings> {
|
||||
public Plan(
|
||||
SKFunction<?> function,
|
||||
List<String> functionOutputs,
|
||||
KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
this(function, SKBuilders.variables().build(), functionOutputs, kernelSkillsSupplier);
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier) {
|
||||
this(
|
||||
function,
|
||||
SKBuilders.variables().build(),
|
||||
functionOutputs,
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
}
|
||||
|
||||
public Plan(SKFunction<?> function, KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
this(function, SKBuilders.variables().build(), new ArrayList<>(), kernelSkillsSupplier);
|
||||
public Plan(
|
||||
SKFunction<?> function,
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier) {
|
||||
this(
|
||||
function,
|
||||
SKBuilders.variables().build(),
|
||||
new ArrayList<>(),
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
}
|
||||
|
||||
public Plan(
|
||||
String goal,
|
||||
ContextVariables parameters,
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier,
|
||||
SKFunction<?>... steps) {
|
||||
this(goal, parameters, kernelSkillsSupplier);
|
||||
this(goal, parameters, kernelSkillsSupplier, aiServiceSupplier);
|
||||
this.addSteps(steps);
|
||||
}
|
||||
|
||||
public Plan(String goal, KernelSkillsSupplier kernelSkillsSupplier, SKFunction<?>... steps) {
|
||||
this(goal, kernelSkillsSupplier);
|
||||
public Plan(
|
||||
String goal,
|
||||
KernelSkillsSupplier kernelSkillsSupplier,
|
||||
AIServiceSupplier aiServiceSupplier,
|
||||
SKFunction<?>... steps) {
|
||||
this(goal, kernelSkillsSupplier, aiServiceSupplier);
|
||||
this.addSteps(steps);
|
||||
}
|
||||
|
||||
@@ -179,7 +208,7 @@ public class Plan extends AbstractSkFunction<CompletionRequestSettings> {
|
||||
public void addSteps(SKFunction<?>... steps) {
|
||||
List<Plan> plans =
|
||||
Arrays.stream(steps)
|
||||
.map(step -> new Plan(step, getSkillsSupplier()))
|
||||
.map(step -> new Plan(step, getSkillsSupplier(), getAiServiceSupplier()))
|
||||
.collect(Collectors.toList());
|
||||
this.steps.addAll(plans);
|
||||
}
|
||||
|
||||
+24
-8
@@ -6,6 +6,7 @@ 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.services.AIServiceSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.FunctionView;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -27,6 +28,7 @@ import org.xml.sax.SAXException;
|
||||
|
||||
/** 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.
|
||||
@@ -56,10 +58,14 @@ public class SequentialPlanParser {
|
||||
* @return The plan
|
||||
* @throws PlanningException If the plan xml is invalid
|
||||
*/
|
||||
public static Plan toPlanFromXml(String xmlString, String goal, ReadOnlySkillCollection skills)
|
||||
public static Plan toPlanFromXml(
|
||||
String xmlString,
|
||||
String goal,
|
||||
ReadOnlySkillCollection skills,
|
||||
AIServiceSupplier aiServiceSupplier)
|
||||
throws PlanningException {
|
||||
// to maintain backward compatibility -- uses the preexisting signature and behavior
|
||||
return toPlanFromXml(xmlString, goal, skills, true);
|
||||
return toPlanFromXml(xmlString, goal, skills, aiServiceSupplier, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,6 +82,7 @@ public class SequentialPlanParser {
|
||||
String xmlString,
|
||||
String goal,
|
||||
ReadOnlySkillCollection skills,
|
||||
AIServiceSupplier aiServiceSupplier,
|
||||
boolean allowMissingFunctions)
|
||||
throws PlanningException {
|
||||
|
||||
@@ -90,7 +97,7 @@ public class SequentialPlanParser {
|
||||
|
||||
NodeList solution = doc.getElementsByTagName(SolutionTag);
|
||||
|
||||
Plan plan = new Plan(goal, () -> skills);
|
||||
Plan plan = new Plan(goal, () -> skills, aiServiceSupplier);
|
||||
|
||||
for (int i = 0; i < solution.getLength(); i++) {
|
||||
Node solutionNode = solution.item(i);
|
||||
@@ -101,7 +108,11 @@ public class SequentialPlanParser {
|
||||
if (childNode.getNodeName().equals("#text")) {
|
||||
if (childNode.getNodeValue() != null
|
||||
&& !childNode.getNodeValue().trim().isEmpty()) {
|
||||
plan.addSteps(new Plan(childNode.getNodeValue().trim(), () -> skills));
|
||||
plan.addSteps(
|
||||
new Plan(
|
||||
childNode.getNodeValue().trim(),
|
||||
() -> skills,
|
||||
aiServiceSupplier));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -136,7 +147,8 @@ public class SequentialPlanParser {
|
||||
functionVariables,
|
||||
SKBuilders.variables().build(),
|
||||
functionOutputs,
|
||||
() -> skills);
|
||||
() -> skills,
|
||||
aiServiceSupplier);
|
||||
|
||||
plan.addOutputs(functionResults);
|
||||
plan.addSteps(planStep);
|
||||
@@ -145,9 +157,12 @@ public class SequentialPlanParser {
|
||||
"{}: appending function node {}",
|
||||
parentNodeName,
|
||||
skillFunctionName);
|
||||
|
||||
if (allowMissingFunctions) {
|
||||
plan.addSteps(new Plan(childNode.getTextContent(), () -> skills));
|
||||
plan.addSteps(
|
||||
new Plan(
|
||||
childNode.getTextContent(),
|
||||
() -> skills,
|
||||
aiServiceSupplier));
|
||||
} else {
|
||||
String errorMessage =
|
||||
String.format(
|
||||
@@ -161,7 +176,8 @@ public class SequentialPlanParser {
|
||||
continue;
|
||||
}
|
||||
|
||||
plan.addSteps(new Plan(childNode.getTextContent(), () -> skills));
|
||||
plan.addSteps(
|
||||
new Plan(childNode.getTextContent(), () -> skills, aiServiceSupplier));
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
|
||||
+9
-4
@@ -6,7 +6,6 @@ import com.microsoft.semantickernel.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.CompletionSKFunction;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@@ -68,9 +67,14 @@ public class SequentialPlanner {
|
||||
"Given a request or command or goal generate a step by step plan to"
|
||||
+ " fulfill the request using functions. This ability is also"
|
||||
+ " known as decision making and function flow")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0.0, 0.0, 0.0, 0.0, this.config.getMaxTokens()))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.0)
|
||||
.topP(0.0)
|
||||
.maxTokens(this.config.getMaxTokens())
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
this.kernel = kernel;
|
||||
@@ -123,6 +127,7 @@ public class SequentialPlanner {
|
||||
planResultString,
|
||||
goal,
|
||||
context.getSkills(),
|
||||
kernel::getService,
|
||||
config.getAllowMissingFunctions());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
|
||||
+27
-30
@@ -104,13 +104,9 @@ public class DefaultStepwisePlanner implements StepwisePlanner {
|
||||
* @param kernel The semantic kernel instance.
|
||||
* @param config Optional configuration object
|
||||
* @param prompt Optional prompt override
|
||||
* @param promptUserConfig Optional prompt config override
|
||||
*/
|
||||
public DefaultStepwisePlanner(
|
||||
Kernel kernel,
|
||||
@Nullable StepwisePlannerConfig config,
|
||||
@Nullable String prompt,
|
||||
@Nullable PromptTemplateConfig promptUserConfig) {
|
||||
Kernel kernel, @Nullable StepwisePlannerConfig config, @Nullable String prompt) {
|
||||
Verify.notNull(kernel);
|
||||
this.kernel = kernel;
|
||||
|
||||
@@ -121,28 +117,9 @@ public class DefaultStepwisePlanner implements StepwisePlanner {
|
||||
this.config = config;
|
||||
this.config.addExcludedSkills(RESTRICTED_SKILL_NAME);
|
||||
|
||||
PromptTemplateConfig promptConfig;
|
||||
if (promptUserConfig == null) {
|
||||
String promptConfigString = null;
|
||||
try {
|
||||
promptConfigString =
|
||||
EmbeddedResourceLoader.readFile(
|
||||
"config.json", DefaultStepwisePlanner.class);
|
||||
if (!Verify.isNullOrEmpty(promptConfigString)) {
|
||||
promptConfig =
|
||||
new ObjectMapper()
|
||||
.readValue(promptConfigString, PromptTemplateConfig.class);
|
||||
} else {
|
||||
promptConfig = new PromptTemplateConfig();
|
||||
}
|
||||
} catch (FileNotFoundException | JsonProcessingException e) {
|
||||
throw new PlanningException(
|
||||
PlanningException.ErrorCodes.INVALID_CONFIGURATION,
|
||||
"Could not find or parse config.json",
|
||||
e);
|
||||
}
|
||||
} else {
|
||||
promptConfig = promptUserConfig;
|
||||
PromptTemplateConfig promptConfig = config.promptTemplateConfig;
|
||||
if (promptConfig == null) {
|
||||
promptConfig = loadPromptConfig();
|
||||
}
|
||||
|
||||
if (prompt == null) {
|
||||
@@ -163,8 +140,8 @@ public class DefaultStepwisePlanner implements StepwisePlanner {
|
||||
promptConfig.getSchema(),
|
||||
promptConfig.getDescription(),
|
||||
promptConfig.getType(),
|
||||
new PromptTemplateConfig.CompletionConfigBuilder(
|
||||
promptConfig.getCompletionConfig())
|
||||
new CompletionRequestSettings.Builder(
|
||||
promptConfig.getCompletionRequestSettings())
|
||||
.maxTokens(this.config.getMaxTokens())
|
||||
.build(),
|
||||
promptConfig.getInput());
|
||||
@@ -176,6 +153,26 @@ public class DefaultStepwisePlanner implements StepwisePlanner {
|
||||
this.context = SKBuilders.context().withKernel(kernel).build();
|
||||
}
|
||||
|
||||
private static PromptTemplateConfig loadPromptConfig() {
|
||||
PromptTemplateConfig promptConfig;
|
||||
String promptConfigString = null;
|
||||
try {
|
||||
promptConfigString =
|
||||
EmbeddedResourceLoader.readFile("config.json", DefaultStepwisePlanner.class);
|
||||
if (!Verify.isNullOrEmpty(promptConfigString)) {
|
||||
promptConfig =
|
||||
new ObjectMapper()
|
||||
.readValue(promptConfigString, PromptTemplateConfig.class);
|
||||
} else {
|
||||
promptConfig = new PromptTemplateConfig();
|
||||
}
|
||||
} catch (FileNotFoundException | JsonProcessingException e) {
|
||||
throw new PlanningException(
|
||||
ErrorCodes.INVALID_CONFIGURATION, "Could not find or parse config.json", e);
|
||||
}
|
||||
return promptConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a plan for the specified goal.
|
||||
*
|
||||
@@ -199,7 +196,7 @@ public class DefaultStepwisePlanner implements StepwisePlanner {
|
||||
/*
|
||||
planStep.addOutputs(Arrays.asList("agentScratchPad", "stepCount", "skillCount", "stepsTaken"));
|
||||
*/
|
||||
return new Plan(goal, parameters, kernel::getSkills, planStep);
|
||||
return new Plan(goal, parameters, kernel::getSkills, kernel::getService, planStep);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
@@ -1,9 +1,11 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.planner.stepwiseplanner;
|
||||
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for Stepwise planner instances.
|
||||
@@ -61,6 +63,11 @@ public class StepwisePlannerConfig {
|
||||
/// </summary>
|
||||
private int minIterationTimeMs = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The configuration to use for the prompt template.
|
||||
/// </summary>
|
||||
@Nullable public PromptTemplateConfig promptTemplateConfig;
|
||||
|
||||
public void addExcludedSkills(String restrictedSkillName) {
|
||||
excludedSkills.add(restrictedSkillName);
|
||||
}
|
||||
|
||||
+6
-6
@@ -39,8 +39,8 @@ public class ConversationSummarySkill {
|
||||
.withDescription(
|
||||
"Given a section of a conversation transcript, summarize the part"
|
||||
+ " of the conversation.")
|
||||
.withCompletionConfig(
|
||||
SKBuilders.completionConfig()
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.maxTokens(MaxTokens)
|
||||
.temperature(0.1)
|
||||
.topP(0.5)
|
||||
@@ -57,8 +57,8 @@ public class ConversationSummarySkill {
|
||||
.withDescription(
|
||||
"Given a section of a conversation transcript, identify action"
|
||||
+ " items.")
|
||||
.withCompletionConfig(
|
||||
SKBuilders.completionConfig()
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.maxTokens(MaxTokens)
|
||||
.temperature(0.1)
|
||||
.topP(0.5)
|
||||
@@ -75,8 +75,8 @@ public class ConversationSummarySkill {
|
||||
.withDescription(
|
||||
"Analyze a conversation transcript and extract key topics worth"
|
||||
+ " remembering.")
|
||||
.withCompletionConfig(
|
||||
SKBuilders.completionConfig()
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.maxTokens(MaxTokens)
|
||||
.temperature(0.1)
|
||||
.topP(0.5)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<artifactId>semantickernel-core</artifactId>
|
||||
<!-- TODO: scope should be runtime, but VolatileMemoryStore is an issue -->
|
||||
<!-- <scope>runtime</scope> -->
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
|
||||
+9
-7
@@ -8,6 +8,7 @@ package com.microsoft.semantickernel.samples;
|
||||
|
||||
import com.azure.ai.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
@@ -38,13 +39,14 @@ public class Example03_SemanticFunctionInline {
|
||||
.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName(functionName)
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0.2,
|
||||
0.5,
|
||||
0,
|
||||
0,
|
||||
2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Mono<SKContext> result = summarize.invokeAsync(text);
|
||||
|
||||
+8
-8
@@ -12,7 +12,6 @@ import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -46,13 +45,14 @@ public class Example04_ContextVariablesChat {
|
||||
.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("ChatBot")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0.7,
|
||||
0.5,
|
||||
0,
|
||||
0,
|
||||
2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.7)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build();
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
///usr/bin/env jbang "$0" "$@" ; exit $?
|
||||
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
|
||||
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
|
||||
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
|
||||
//DEPS org.slf4j:slf4j-jdk14:2.0.7
|
||||
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java
|
||||
package com.microsoft.semantickernel.samples;
|
||||
|
||||
import com.azure.ai.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import java.io.IOException;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Getting started
|
||||
* <p>
|
||||
* Create a conf.properties file based on the examples files at the root of this module.
|
||||
* <p>
|
||||
* <a href= "https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart">Get
|
||||
* started with Azure OpenAI</a>
|
||||
* <a href="https://openai.com/product">Get started with OpenAI</a>
|
||||
*/
|
||||
public class Example11_UseMultipleModels {
|
||||
|
||||
/**
|
||||
* Returns a Semantic Kernel with Text Completion.
|
||||
*
|
||||
* @param client Client that will handle requests to AzureOpenAI or OpenAI.
|
||||
* @return Kernel.
|
||||
*/
|
||||
public static Kernel getKernel(OpenAIAsyncClient client) {
|
||||
OpenAITextCompletion davinciTextCompletion = new OpenAITextCompletion(client,
|
||||
"text-davinci-003");
|
||||
OpenAITextCompletion adaTextCompletion = new OpenAITextCompletion(client, "text-ada-001");
|
||||
|
||||
Kernel kernel = SKBuilders.kernel()
|
||||
// Add one of this serviceId to config.json in FunSkill to test difference models
|
||||
.withAIService("text-davinci-003", davinciTextCompletion, false, OpenAITextCompletion.class)
|
||||
.withAIService("text-ada-001", adaTextCompletion, false, OpenAITextCompletion.class)
|
||||
.build();
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports 'FunSkill' from directory examples and runs the 'Joke' function within it.
|
||||
*
|
||||
* @param kernel Kernel with Text Completion.
|
||||
*/
|
||||
public static void runWithServiceDefinedAtInvocation(Kernel kernel) {
|
||||
ReadOnlyFunctionCollection skill = kernel
|
||||
.importSkillFromDirectory("FunSkill", SampleSkillsUtil.detectSkillDirLocation(),
|
||||
"FunSkill");
|
||||
|
||||
CompletionSKFunction function = skill.getFunction("Joke",
|
||||
CompletionSKFunction.class);
|
||||
|
||||
Mono<SKContext> result = function.invokeAsync("time travel to dinosaur age",
|
||||
SKBuilders
|
||||
.completionRequestSettings()
|
||||
.serviceId("text-davinci-003")
|
||||
.build());
|
||||
|
||||
String davinci = result.block().getResult();
|
||||
|
||||
result = function.invokeAsync("time travel to dinosaur age",
|
||||
SKBuilders
|
||||
.completionRequestSettings()
|
||||
.serviceId("text-ada-001")
|
||||
.build());
|
||||
|
||||
String ada = result.block().getResult();
|
||||
|
||||
System.out.println("=== RESULT FROM text-davinci-003 ===");
|
||||
System.out.println(davinci);
|
||||
System.out.println("====================================");
|
||||
|
||||
System.out.println("===== RESULT FROM text-ada-001 =====");
|
||||
System.out.println(ada);
|
||||
System.out.println("====================================");
|
||||
}
|
||||
|
||||
|
||||
public static void runWithServiceDefinedByInlineFunction(Kernel kernel) {
|
||||
// Create function via kernel
|
||||
var function = kernel.
|
||||
getSemanticFunctionBuilder()
|
||||
.withPromptTemplate("tell a joke about {{$input}}")
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.4)
|
||||
.topP(1)
|
||||
.maxTokens(100)
|
||||
.serviceId("text-davinci-003")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
String davinci = function.invokeAsync("time travel to dinosaur age").block().getResult();
|
||||
|
||||
System.out.println("=== RESULT FROM text-davinci-003 ===");
|
||||
System.out.println(davinci);
|
||||
System.out.println("====================================");
|
||||
}
|
||||
|
||||
|
||||
public static void runWithServiceDefinedInFile(Kernel kernel) {
|
||||
ReadOnlyFunctionCollection skills = kernel.importSkillFromResources(
|
||||
"Plugins",
|
||||
"ExamplePlugins",
|
||||
"ExampleFunctionWithService"
|
||||
);
|
||||
|
||||
SKFunction<?> function = skills.getFunction("ExampleFunctionWithService");
|
||||
|
||||
System.out.println("=== RESULT FROM text-davinci-003 ===");
|
||||
System.out.println(function.invokeAsync().block().getResult());
|
||||
System.out.println("====================================");
|
||||
}
|
||||
|
||||
|
||||
public static void run(OpenAIAsyncClient client) {
|
||||
Kernel kernel = getKernel(client);
|
||||
runWithServiceDefinedInFile(kernel);
|
||||
runWithServiceDefinedAtInvocation(kernel);
|
||||
runWithServiceDefinedByInlineFunction(kernel);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws ConfigurationException, IOException {
|
||||
run(OpenAIClientProvider.getClient());
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -7,7 +7,6 @@ import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.SamplesConfig;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@@ -52,11 +51,11 @@ public class Example05_InlineFunctionDefinition {
|
||||
.completionFunctions()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfigBuilder()
|
||||
.maxTokens(100)
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.4)
|
||||
.topP(1)
|
||||
.maxTokens(100)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@@ -72,11 +71,11 @@ public class Example05_InlineFunctionDefinition {
|
||||
getSemanticFunctionBuilder()
|
||||
.withPromptTemplate("Translate this date " +
|
||||
DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(LocalDateTime.now()) + " to French format")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfigBuilder()
|
||||
.maxTokens(100)
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.4)
|
||||
.topP(1)
|
||||
.maxTokens(100)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
|
||||
+76
-71
@@ -11,8 +11,8 @@ import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
|
||||
/**
|
||||
* Show how to invoke a Native Function written in Java
|
||||
* from a Semantic Function written in natural language
|
||||
* Show how to invoke a Native Function written in Java from a Semantic Function written in natural
|
||||
* language
|
||||
* <p>
|
||||
* Refer to the <a href=
|
||||
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
|
||||
@@ -20,84 +20,89 @@ import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
*/
|
||||
public class Example06_TemplateLanguage {
|
||||
|
||||
public static void main(String[] args) throws ConfigurationException {
|
||||
System.out.println("======== TemplateLanguage ========");
|
||||
public static void main(String[] args) throws ConfigurationException {
|
||||
System.out.println("======== TemplateLanguage ========");
|
||||
|
||||
OpenAIAsyncClient client = SamplesConfig.getClient();
|
||||
OpenAIAsyncClient client = SamplesConfig.getClient();
|
||||
|
||||
Kernel kernel = SKBuilders.kernel()
|
||||
.withDefaultAIService(SKBuilders.textCompletion()
|
||||
.withModelId("text-davinci-003")
|
||||
.withOpenAIClient(client)
|
||||
.build())
|
||||
.build();
|
||||
Kernel kernel = SKBuilders.kernel()
|
||||
.withDefaultAIService(SKBuilders.textCompletion()
|
||||
.withModelId("text-davinci-003")
|
||||
.withOpenAIClient(client)
|
||||
.build())
|
||||
.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()
|
||||
.withPromptTemplateConfig(new PromptTemplateConfig())
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withPromptTemplateEngine(kernel.getPromptTemplateEngine())
|
||||
.build();
|
||||
var promptRenderer = SKBuilders.promptTemplate()
|
||||
.withPromptTemplateConfig(new PromptTemplateConfig())
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withPromptTemplateEngine(kernel.getPromptTemplateEngine())
|
||||
.build();
|
||||
|
||||
SKContext skContext = SKBuilders
|
||||
.context()
|
||||
.withSkills(kernel.getSkills())
|
||||
.build();
|
||||
SKContext skContext = SKBuilders
|
||||
.context()
|
||||
.withSkills(kernel.getSkills())
|
||||
.build();
|
||||
|
||||
var renderedPrompt = promptRenderer.renderAsync(skContext);
|
||||
System.out.println(renderedPrompt.block());
|
||||
var renderedPrompt = promptRenderer.renderAsync(skContext);
|
||||
System.out.println(renderedPrompt.block());
|
||||
|
||||
// Run the prompt / semantic function
|
||||
var kindOfDay = kernel
|
||||
.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0, 0, 0, 0, 256))
|
||||
.build();
|
||||
// Run the prompt / semantic function
|
||||
var kindOfDay = kernel
|
||||
.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0)
|
||||
.topP(0)
|
||||
.maxTokens(256)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// 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"
|
||||
* }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -13,7 +13,6 @@ import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.util.AzureOpenAISettings;
|
||||
import com.microsoft.semantickernel.exceptions.ConfigurationException;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.settings.SettingsMap;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
@@ -90,9 +89,14 @@ public class Example08_RetryHandler {
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0.2, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
kernel.registerSemanticFunction(summarizeFunc);
|
||||
|
||||
+10
-10
@@ -11,7 +11,7 @@ import com.microsoft.semantickernel.memory.MemoryStore;
|
||||
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.util.List;
|
||||
@@ -75,20 +75,20 @@ public class Example15_MemorySkill {
|
||||
kernel.importSkill(memorySkill, "memory");
|
||||
|
||||
// Build a semantic function that saves info to memory
|
||||
PromptTemplateConfig.CompletionConfig completionConfig = SKBuilders.completionConfig()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build();
|
||||
CompletionRequestSettings completionConfig = SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build();
|
||||
|
||||
CompletionSKFunction saveFunctionDefinition = SKBuilders.completionFunctions()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate("{{memory.save $info}}")
|
||||
.withFunctionName("save")
|
||||
.withDescription("save information to memory")
|
||||
.withCompletionConfig(completionConfig)
|
||||
.withRequestSettings(completionConfig)
|
||||
.build();
|
||||
|
||||
CompletionSKFunction memorySaver =
|
||||
@@ -170,7 +170,7 @@ public class Example15_MemorySkill {
|
||||
CompletionSKFunction recallFunctionDefinition = SKBuilders.completionFunctions()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withCompletionConfig(completionConfig)
|
||||
.withRequestSettings(completionConfig)
|
||||
.build();
|
||||
|
||||
SKFunction<?> aboutMeOracle = kernel.registerSemanticFunction(recallFunctionDefinition);
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class Example51_StepwisePlanner {
|
||||
System.out.println("*****************************************************");
|
||||
System.out.println("Question: " + question);
|
||||
|
||||
StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null, null);
|
||||
StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null);
|
||||
|
||||
var plan = planner.createPlan(question);
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"description": "Sample plugin with a model and service id",
|
||||
"type": "completion",
|
||||
"completion": {
|
||||
"max_tokens": 150,
|
||||
"temperature": 0.9,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"frequency_penalty": 0.0,
|
||||
"service_id": "text-davinci-003",
|
||||
"model_id": "text-davinci-003"
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
Tell me a joke.
|
||||
+4
-4
@@ -2,14 +2,14 @@
|
||||
package com.microsoft.semantickernel.guice;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
public interface CompletionFunctionFactory {
|
||||
|
||||
CompletionSKFunction createFunction(
|
||||
String prompt, String name, PromptTemplateConfig.CompletionConfig completionConfig);
|
||||
String prompt, String name, CompletionRequestSettings completionConfig);
|
||||
|
||||
class CompletionFunctionFactoryImpl implements CompletionFunctionFactory {
|
||||
@Inject
|
||||
@@ -19,11 +19,11 @@ public interface CompletionFunctionFactory {
|
||||
public CompletionSKFunction createFunction(
|
||||
String prompt,
|
||||
String name,
|
||||
PromptTemplateConfig.CompletionConfig completionConfig) {
|
||||
CompletionRequestSettings completionConfig) {
|
||||
return kernel.getSemanticFunctionBuilder()
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName(name)
|
||||
.withCompletionConfig(completionConfig)
|
||||
.withRequestSettings(completionConfig)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
+64
-58
@@ -4,75 +4,81 @@ package com.microsoft.semantickernel.guice;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
|
||||
public class CompletionFunctionExample {
|
||||
|
||||
private final CompletionFunctionFactory completionFunctionFactory;
|
||||
private final CompletionFunctionFactory completionFunctionFactory;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Injector injector =
|
||||
Guice.createInjector(
|
||||
new SemanticKernelModule().withTextCompletionService("text-davinci-003"));
|
||||
public static void main(String[] args) {
|
||||
Injector injector =
|
||||
Guice.createInjector(
|
||||
new SemanticKernelModule().withTextCompletionService("text-davinci-003"));
|
||||
|
||||
CompletionFunctionExample example = injector.getInstance(CompletionFunctionExample.class);
|
||||
example.run();
|
||||
}
|
||||
CompletionFunctionExample example = injector.getInstance(CompletionFunctionExample.class);
|
||||
example.run();
|
||||
}
|
||||
|
||||
@Inject
|
||||
public CompletionFunctionExample(CompletionFunctionFactory completionFunctionFactory) {
|
||||
this.completionFunctionFactory = completionFunctionFactory;
|
||||
}
|
||||
@Inject
|
||||
public CompletionFunctionExample(CompletionFunctionFactory completionFunctionFactory) {
|
||||
this.completionFunctionFactory = completionFunctionFactory;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
String prompt = "{{$input}}\n" + "Summarize the content above.";
|
||||
public void run() {
|
||||
String prompt = "{{$input}}\n" + "Summarize the content above.";
|
||||
|
||||
String text =
|
||||
"\n"
|
||||
+ "Demo (ancient Greek poet)\n"
|
||||
+ "From Wikipedia, the free encyclopedia\n"
|
||||
+ "Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the\n"
|
||||
+ "Roman period, known for a single epigram, engraved upon the Colossus of\n"
|
||||
+ "Memnon, which bears her name. She speaks of herself therein as a lyric\n"
|
||||
+ "poetess dedicated to the Muses, but nothing is known of her life.[1]\n"
|
||||
+ "Identity\n"
|
||||
+ "Demo was evidently Greek, as her name, a traditional epithet of Demeter,\n"
|
||||
+ "signifies. The name was relatively common in the Hellenistic world, in\n"
|
||||
+ "Egypt and elsewhere, and she cannot be further identified. The date of her\n"
|
||||
+ "visit to the Colossus of Memnon cannot be established with certainty, but\n"
|
||||
+ "internal evidence on the left leg suggests her poem was inscribed there at\n"
|
||||
+ "some point in or after AD 196.[2]\n"
|
||||
+ "Epigram\n"
|
||||
+ "There are a number of graffiti inscriptions on the Colossus of Memnon.\n"
|
||||
+ "Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac\n"
|
||||
+ "couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the\n"
|
||||
+ "Greek inscription is difficult to read), is a dedication to the Muses.[2]\n"
|
||||
+ "The poem is traditionally published with the works of Balbilla, though the\n"
|
||||
+ "internal evidence suggests a different author.[1]\n"
|
||||
+ "In the poem, Demo explains that Memnon has shown her special respect. In\n"
|
||||
+ "return, Demo offers the gift for poetry, as a gift to the hero. At the end\n"
|
||||
+ "of this epigram, she addresses Memnon, highlighting his divine status by\n"
|
||||
+ "recalling his strength and holiness.[2]\n"
|
||||
+ "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic\n"
|
||||
+ "dialect. The language indicates she was knowledgeable in Homeric\n"
|
||||
+ "poetry—'bearing a pleasant gift', for example, alludes to the use of that\n"
|
||||
+ "phrase throughout the Iliad and Odyssey.[a][2];";
|
||||
String text =
|
||||
"\n"
|
||||
+ "Demo (ancient Greek poet)\n"
|
||||
+ "From Wikipedia, the free encyclopedia\n"
|
||||
+ "Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the\n"
|
||||
+ "Roman period, known for a single epigram, engraved upon the Colossus of\n"
|
||||
+ "Memnon, which bears her name. She speaks of herself therein as a lyric\n"
|
||||
+ "poetess dedicated to the Muses, but nothing is known of her life.[1]\n"
|
||||
+ "Identity\n"
|
||||
+ "Demo was evidently Greek, as her name, a traditional epithet of Demeter,\n"
|
||||
+ "signifies. The name was relatively common in the Hellenistic world, in\n"
|
||||
+ "Egypt and elsewhere, and she cannot be further identified. The date of her\n"
|
||||
+ "visit to the Colossus of Memnon cannot be established with certainty, but\n"
|
||||
+ "internal evidence on the left leg suggests her poem was inscribed there at\n"
|
||||
+ "some point in or after AD 196.[2]\n"
|
||||
+ "Epigram\n"
|
||||
+ "There are a number of graffiti inscriptions on the Colossus of Memnon.\n"
|
||||
+ "Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac\n"
|
||||
+ "couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the\n"
|
||||
+ "Greek inscription is difficult to read), is a dedication to the Muses.[2]\n"
|
||||
+ "The poem is traditionally published with the works of Balbilla, though the\n"
|
||||
+ "internal evidence suggests a different author.[1]\n"
|
||||
+ "In the poem, Demo explains that Memnon has shown her special respect. In\n"
|
||||
+ "return, Demo offers the gift for poetry, as a gift to the hero. At the end\n"
|
||||
+ "of this epigram, she addresses Memnon, highlighting his divine status by\n"
|
||||
+ "recalling his strength and holiness.[2]\n"
|
||||
+ "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic\n"
|
||||
+ "dialect. The language indicates she was knowledgeable in Homeric\n"
|
||||
+ "poetry—'bearing a pleasant gift', for example, alludes to the use of that\n"
|
||||
+ "phrase throughout the Iliad and Odyssey.[a][2];";
|
||||
|
||||
SKContext summary =
|
||||
completionFunctionFactory
|
||||
.createFunction(
|
||||
prompt,
|
||||
"summarize",
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0.2, 0.5, 0, 0, 2000))
|
||||
.invokeAsync(text)
|
||||
.block();
|
||||
SKContext summary =
|
||||
completionFunctionFactory
|
||||
.createFunction(
|
||||
prompt,
|
||||
"summarize",
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.maxTokens(2000)
|
||||
.frequencyPenalty(0)
|
||||
.presencePenalty(0)
|
||||
.build())
|
||||
.invokeAsync(text)
|
||||
.block();
|
||||
|
||||
if (summary != null) {
|
||||
System.out.println("Result: " + summary.getResult());
|
||||
} else {
|
||||
System.out.println("Null result");
|
||||
}
|
||||
if (summary != null) {
|
||||
System.out.println("Result: " + summary.getResult());
|
||||
} else {
|
||||
System.out.println("Null result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,14 @@ import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings.Builder;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
|
||||
public class SKBuilders {
|
||||
|
||||
// Prevent creating object
|
||||
private SKBuilders() {}
|
||||
|
||||
@@ -60,9 +61,9 @@ public class SKBuilders {
|
||||
return BuildersSingleton.INST.getInstance(SKContext.Builder.class);
|
||||
}
|
||||
|
||||
public static PromptTemplateConfig.CompletionConfigBuilder completionConfig() {
|
||||
return BuildersSingleton.INST.getInstance(
|
||||
PromptTemplateConfig.CompletionConfigBuilder.class);
|
||||
public static Builder completionRequestSettings() {
|
||||
// No need to look up as this is in the API
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.ai;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Request settings for an AI request. */
|
||||
public class AIRequestSettings {
|
||||
|
||||
/**
|
||||
* Service identifier. This identifies a service and is set when the AI service is registered.
|
||||
*/
|
||||
@JsonProperty("service_id")
|
||||
@Nullable
|
||||
private final String serviceId;
|
||||
|
||||
/// <summary>
|
||||
/// Model identifier.
|
||||
/// This identifies the AI model these settings are configured for e.g., gpt-4, gpt-3.5-turbo
|
||||
/// </summary>
|
||||
@JsonProperty("model_id")
|
||||
@Nullable
|
||||
private final String modelId;
|
||||
|
||||
@JsonCreator
|
||||
public AIRequestSettings(
|
||||
@JsonProperty("service_id") @Nullable String serviceId,
|
||||
@JsonProperty("model_id") @Nullable String modelId) {
|
||||
this.serviceId = serviceId;
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getModelId() {
|
||||
return modelId;
|
||||
}
|
||||
}
|
||||
-6
@@ -10,7 +10,6 @@ import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
@@ -31,8 +30,6 @@ public enum BuildersSingleton {
|
||||
|
||||
private static final String FALLBACK_CHAT_COMPLETION_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatCompletion$Builder";
|
||||
private static final String FALLBACK_COMPLETION_CONFIG_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig$CompletionConfigBuilder";
|
||||
private static final String FALLBACK_COMPLETION_FUNCTION_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction$Builder";
|
||||
private static final String FALLBACK_CONTEXT_BUILDER_CLASS =
|
||||
@@ -65,9 +62,6 @@ public enum BuildersSingleton {
|
||||
try {
|
||||
// Keep this list in alphabetical order by fallback variable name
|
||||
registerBuilder(ChatCompletion.Builder.class, FALLBACK_CHAT_COMPLETION_BUILDER_CLASS);
|
||||
registerBuilder(
|
||||
PromptTemplateConfig.CompletionConfigBuilder.class,
|
||||
FALLBACK_COMPLETION_CONFIG_BUILDER_CLASS);
|
||||
registerBuilder(
|
||||
CompletionSKFunction.Builder.class, FALLBACK_COMPLETION_FUNCTION_BUILDER_CLASS);
|
||||
registerBuilder(SKContext.Builder.class, FALLBACK_CONTEXT_BUILDER_CLASS);
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.ai.AIRequestSettings;
|
||||
import com.microsoft.semantickernel.services.AIServiceSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AIFunction<RequestConfiguration extends AIRequestSettings>
|
||||
extends AbstractSkFunction<RequestConfiguration>
|
||||
implements SKFunction<RequestConfiguration> {
|
||||
|
||||
@Nullable private AIServiceSupplier aiServiceSupplier;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param parameters The parameters of the function.
|
||||
* @param skillName The name of the skill.
|
||||
* @param functionName The name of the function.
|
||||
* @param description The description of the function.
|
||||
* @param returnParameters
|
||||
* @param skillsSupplier The skill supplier.
|
||||
*/
|
||||
public AIFunction(
|
||||
List<ParameterView> parameters,
|
||||
String skillName,
|
||||
String functionName,
|
||||
String description,
|
||||
List<ParameterView> returnParameters,
|
||||
@Nullable KernelSkillsSupplier skillsSupplier,
|
||||
@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
super(parameters, skillName, functionName, description, returnParameters, skillsSupplier);
|
||||
this.aiServiceSupplier = aiServiceSupplier;
|
||||
}
|
||||
|
||||
protected void setServiceSupplier(@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
this.aiServiceSupplier = aiServiceSupplier;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected AIServiceSupplier getAiServiceSupplier() {
|
||||
return aiServiceSupplier;
|
||||
}
|
||||
}
|
||||
+6
@@ -84,6 +84,12 @@ public abstract class AbstractSkFunction<RequestConfiguration>
|
||||
return skillsSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<SKContext> invokeAsync(
|
||||
@Nullable String input, @Nullable RequestConfiguration settings) {
|
||||
return invokeAsync(input, null, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<SKContext> invokeAsync(
|
||||
@Nullable String input,
|
||||
|
||||
+11
@@ -15,6 +15,7 @@ import reactor.core.publisher.Mono;
|
||||
* the function is invoked
|
||||
*/
|
||||
public interface SKFunction<RequestConfiguration> {
|
||||
|
||||
/**
|
||||
* Returns a description of the function, including parameters.
|
||||
*
|
||||
@@ -77,6 +78,16 @@ public interface SKFunction<RequestConfiguration> {
|
||||
@CheckReturnValue
|
||||
Mono<SKContext> invokeAsync(SKContext context, @Nullable RequestConfiguration settings);
|
||||
|
||||
/**
|
||||
* Invokes the function with the given context and settings
|
||||
*
|
||||
* @param input input provided to the function
|
||||
* @param settings Configuration of the request
|
||||
* @return an updated context with the result of the request
|
||||
*/
|
||||
@CheckReturnValue
|
||||
Mono<SKContext> invokeAsync(String input, @Nullable RequestConfiguration settings);
|
||||
|
||||
/**
|
||||
* @return The name of the skill that this function is within
|
||||
*/
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/** Input configuration (list of all input parameters for a semantic function). */
|
||||
public class InputConfig {
|
||||
|
||||
public final List<InputParameter> parameters;
|
||||
|
||||
@JsonCreator
|
||||
public InputConfig(@JsonProperty("parameters") List<InputParameter> parameters) {
|
||||
this.parameters = Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
public List<InputParameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/** Input parameter for semantic functions */
|
||||
public class InputParameter {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String defaultValue;
|
||||
|
||||
@JsonCreator
|
||||
public InputParameter(
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("defaultValue") String defaultValue) {
|
||||
this.name = name;
|
||||
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;
|
||||
}
|
||||
}
|
||||
+36
-361
@@ -4,366 +4,17 @@ package com.microsoft.semantickernel.semanticfunctions;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.builders.BuildersSingleton;
|
||||
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import reactor.util.annotation.Nullable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Prompt template configuration */
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class PromptTemplateConfig {
|
||||
private final CompletionConfig completionConfig;
|
||||
|
||||
private final CompletionRequestSettings completionRequestSettings;
|
||||
private final InputConfig input;
|
||||
|
||||
/**
|
||||
* A returns the configuration for the text completion
|
||||
*
|
||||
* @return CompletionConfig
|
||||
*/
|
||||
public CompletionConfig getCompletionConfig() {
|
||||
return completionConfig;
|
||||
}
|
||||
|
||||
public int getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** Builder for CompletionConfig */
|
||||
public static class CompletionConfigBuilder implements SemanticKernelBuilder<CompletionConfig> {
|
||||
|
||||
private CompletionConfig completionConfig;
|
||||
|
||||
public CompletionConfigBuilder() {
|
||||
completionConfig = new CompletionConfig();
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder(CompletionConfig completionConfig) {
|
||||
this.completionConfig = completionConfig;
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder temperature(double temperature) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder topP(double topP) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
completionConfig.temperature,
|
||||
topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder presencePenalty(double presencePenalty) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder frequencyPenalty(double frequencyPenalty) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder maxTokens(int maxTokens) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfigBuilder stopSequences(List<String> stopSequences) {
|
||||
return new CompletionConfigBuilder(
|
||||
new CompletionConfig(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
stopSequences));
|
||||
}
|
||||
|
||||
public CompletionConfig build() {
|
||||
return completionConfig;
|
||||
}
|
||||
}
|
||||
|
||||
public InputConfig getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
/** Completion configuration parameters */
|
||||
public static class CompletionConfig implements Buildable {
|
||||
/*
|
||||
/// <summary>
|
||||
/// Sampling temperature to use, between 0 and 2. Higher values will make the output more random.
|
||||
/// Lower values will make it more focused and deterministic.
|
||||
/// </summary>
|
||||
[JsonPropertyName("temperature")]
|
||||
[JsonPropertyOrder(1)]
|
||||
*/
|
||||
private final double temperature;
|
||||
/*
|
||||
/// <summary>
|
||||
/// Cut-off of top_p probability mass of tokens to consider.
|
||||
/// For example, 0.1 means only the tokens comprising the top 10% probability mass are considered.
|
||||
/// </summary>
|
||||
[JsonPropertyName("top_p")]
|
||||
[JsonPropertyOrder(2)]
|
||||
*/
|
||||
private final double topP;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Lowers the probability of a word appearing if it already appeared in the predicted text.
|
||||
/// Unlike the frequency penalty, the presence penalty does not depend on the frequency at which words
|
||||
/// appear in past predictions.
|
||||
/// </summary>
|
||||
[JsonPropertyName("presence_penalty")]
|
||||
[JsonPropertyOrder(3)]
|
||||
*/
|
||||
private final double presencePenalty;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Controls the model’s tendency to repeat predictions. The frequency penalty reduces the probability
|
||||
/// of words that have already been generated. The penalty depends on how many times a word has already
|
||||
/// occurred in the prediction.
|
||||
/// </summary>
|
||||
[JsonPropertyName("frequency_penalty")]
|
||||
[JsonPropertyOrder(4)]
|
||||
*/
|
||||
private final double frequencyPenalty;
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maximum number of tokens that can be generated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("max_tokens")]
|
||||
[JsonPropertyOrder(5)]*/
|
||||
private final int maxTokens; // { get; set; } = 256;
|
||||
/*
|
||||
/// <summary>
|
||||
/// Stop sequences are optional sequences that tells the AI model when to stop generating tokens.
|
||||
/// </summary>
|
||||
[JsonPropertyName("stop_sequences")]
|
||||
[JsonPropertyOrder(6)]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
*/
|
||||
public final List<String> 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, 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
|
||||
public CompletionConfig(
|
||||
@JsonProperty("temperature") double temperature,
|
||||
@JsonProperty("top_p") double topP,
|
||||
@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<String> 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<>();
|
||||
}
|
||||
this.stopSequences = stopSequences;
|
||||
}
|
||||
|
||||
public double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public double getTopP() {
|
||||
return topP;
|
||||
}
|
||||
|
||||
public double getPresencePenalty() {
|
||||
return presencePenalty;
|
||||
}
|
||||
|
||||
public double getFrequencyPenalty() {
|
||||
return frequencyPenalty;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public SemanticKernelBuilder<CompletionConfig> builder() {
|
||||
return BuildersSingleton.INST.getInstance(CompletionConfigBuilder.class);
|
||||
}
|
||||
|
||||
public List<String> getStopSequences() {
|
||||
return Collections.unmodifiableList(stopSequences);
|
||||
}
|
||||
}
|
||||
|
||||
/** Input parameter for semantic functions */
|
||||
public static class InputParameter {
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private final String defaultValue;
|
||||
|
||||
@JsonCreator
|
||||
public InputParameter(
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("defaultValue") String defaultValue) {
|
||||
this.name = name;
|
||||
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). */
|
||||
public static class InputConfig {
|
||||
|
||||
public final List<InputParameter> parameters;
|
||||
|
||||
@JsonCreator
|
||||
public InputConfig(@JsonProperty("parameters") List<InputParameter> parameters) {
|
||||
this.parameters = Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
public List<InputParameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
private final int schema;
|
||||
|
||||
private final String type; // { get; set; } = "completion";
|
||||
private final String description;
|
||||
|
||||
@@ -371,13 +22,15 @@ public class PromptTemplateConfig {
|
||||
this("", "", null);
|
||||
}
|
||||
|
||||
public PromptTemplateConfig(CompletionConfig completionConfig) {
|
||||
this(1, "", "", completionConfig, new InputConfig(new ArrayList<>()));
|
||||
public PromptTemplateConfig(CompletionRequestSettings completionRequestSettings) {
|
||||
this(1, "", "", completionRequestSettings, new InputConfig(new ArrayList<>()));
|
||||
}
|
||||
|
||||
public PromptTemplateConfig(
|
||||
String description, String type, @Nullable CompletionConfig completionConfig) {
|
||||
this(1, description, type, completionConfig, new InputConfig(new ArrayList<>()));
|
||||
String description,
|
||||
String type,
|
||||
@Nullable CompletionRequestSettings completionRequestSettings) {
|
||||
this(1, description, type, completionRequestSettings, new InputConfig(new ArrayList<>()));
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
@@ -385,15 +38,16 @@ public class PromptTemplateConfig {
|
||||
@JsonProperty("schema") int schema,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("type") String type,
|
||||
@Nullable @JsonProperty("completion") CompletionConfig completionConfig,
|
||||
@Nullable @JsonProperty("completion")
|
||||
CompletionRequestSettings completionRequestSettings,
|
||||
@Nullable @JsonProperty("input") InputConfig input) {
|
||||
if (completionConfig == null) {
|
||||
completionConfig = new CompletionConfig();
|
||||
if (completionRequestSettings == null) {
|
||||
completionRequestSettings = new CompletionRequestSettings();
|
||||
}
|
||||
this.schema = schema;
|
||||
this.description = description;
|
||||
this.type = type;
|
||||
this.completionConfig = completionConfig;
|
||||
this.completionRequestSettings = completionRequestSettings;
|
||||
if (input == null) {
|
||||
input = new InputConfig(new ArrayList<>());
|
||||
}
|
||||
@@ -408,4 +62,25 @@ public class PromptTemplateConfig {
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* A returns the configuration for the text completion
|
||||
*
|
||||
* @return CompletionRequestSettings
|
||||
*/
|
||||
public CompletionRequestSettings getCompletionRequestSettings() {
|
||||
return completionRequestSettings;
|
||||
}
|
||||
|
||||
public int getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public InputConfig getInput() {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.services;
|
||||
|
||||
public interface AIServiceSupplier {
|
||||
|
||||
<T extends AIService> T get(String serviceId, Class<T> clazz);
|
||||
}
|
||||
+204
-33
@@ -1,14 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.textcompletion;
|
||||
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.microsoft.semantickernel.ai.AIRequestSettings;
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Settings for a text completion request */
|
||||
public class CompletionRequestSettings {
|
||||
public class CompletionRequestSettings extends AIRequestSettings implements Buildable {
|
||||
|
||||
/**
|
||||
* Temperature controls the randomness of the completion. The higher the temperature, the more
|
||||
* random the completion
|
||||
@@ -79,7 +84,9 @@ public class CompletionRequestSettings {
|
||||
maxTokens,
|
||||
1,
|
||||
"",
|
||||
Collections.emptyList());
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,27 +108,39 @@ public class CompletionRequestSettings {
|
||||
* @param stopSequences Sequences where the completion will stop generating further tokens.
|
||||
*/
|
||||
public CompletionRequestSettings(
|
||||
double temperature,
|
||||
double topP,
|
||||
double presencePenalty,
|
||||
double frequencyPenalty,
|
||||
int maxTokens,
|
||||
int bestOf,
|
||||
String user,
|
||||
List<String> stopSequences) {
|
||||
@JsonProperty("temperature") double temperature,
|
||||
@JsonProperty("top_p") double topP,
|
||||
@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<String> stopSequences,
|
||||
@JsonProperty(value = "service_id") @Nullable String serviceId,
|
||||
@JsonProperty(value = "model_id") @Nullable String modelId) {
|
||||
super(serviceId, modelId);
|
||||
this.temperature = temperature;
|
||||
this.topP = topP;
|
||||
this.presencePenalty = presencePenalty;
|
||||
this.frequencyPenalty = frequencyPenalty;
|
||||
this.maxTokens = maxTokens;
|
||||
this.bestOf = bestOf;
|
||||
|
||||
// bestOf must be at least 1
|
||||
this.bestOf = Math.max(1, bestOf);
|
||||
|
||||
if (user == null) {
|
||||
user = "";
|
||||
}
|
||||
this.user = user;
|
||||
this.stopSequences = new ArrayList<>(stopSequences);
|
||||
if (stopSequences == null) {
|
||||
stopSequences = new ArrayList<>();
|
||||
}
|
||||
this.stopSequences = stopSequences;
|
||||
}
|
||||
|
||||
/** Create a new settings object with default values. */
|
||||
public CompletionRequestSettings() {
|
||||
this(0, 0, 0, 0, 256, 1, "", new ArrayList<>());
|
||||
this(0, 0, 0, 0, 256, 1, "", new ArrayList<>(), null, null);
|
||||
}
|
||||
|
||||
public CompletionRequestSettings(@Nonnull CompletionRequestSettings requestSettings) {
|
||||
@@ -133,25 +152,9 @@ public class CompletionRequestSettings {
|
||||
requestSettings.getMaxTokens(),
|
||||
requestSettings.getBestOf(),
|
||||
requestSettings.getUser(),
|
||||
requestSettings.getStopSequences());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new settings object with the values from another settings object.
|
||||
*
|
||||
* @param config The config to copy values from
|
||||
*/
|
||||
public static CompletionRequestSettings fromCompletionConfig(
|
||||
PromptTemplateConfig.CompletionConfig config) {
|
||||
return new CompletionRequestSettings(
|
||||
config.getTemperature(),
|
||||
config.getTopP(),
|
||||
config.getPresencePenalty(),
|
||||
config.getFrequencyPenalty(),
|
||||
config.getMaxTokens(),
|
||||
config.getBestOf(),
|
||||
config.getUser(),
|
||||
config.getStopSequences());
|
||||
requestSettings.getStopSequences(),
|
||||
requestSettings.getServiceId(),
|
||||
requestSettings.getModelId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,4 +215,172 @@ public class CompletionRequestSettings {
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
/** Builder for CompletionRequestSettings */
|
||||
public static class Builder implements SemanticKernelBuilder<CompletionRequestSettings> {
|
||||
|
||||
private final CompletionRequestSettings completionConfig;
|
||||
|
||||
public Builder() {
|
||||
completionConfig = new CompletionRequestSettings();
|
||||
}
|
||||
|
||||
public Builder(CompletionRequestSettings completionConfig) {
|
||||
this.completionConfig = completionConfig;
|
||||
}
|
||||
|
||||
public Builder temperature(double temperature) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder topP(double topP) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder presencePenalty(double presencePenalty) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder frequencyPenalty(double frequencyPenalty) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder maxTokens(int maxTokens) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder bestOf(int bestOf) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder user(String user) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder stopSequences(List<String> stopSequences) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder serviceId(String serviceId) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
serviceId,
|
||||
completionConfig.getModelId()));
|
||||
}
|
||||
|
||||
public Builder modelId(String modelId) {
|
||||
return new Builder(
|
||||
new CompletionRequestSettings(
|
||||
completionConfig.temperature,
|
||||
completionConfig.topP,
|
||||
completionConfig.presencePenalty,
|
||||
completionConfig.frequencyPenalty,
|
||||
completionConfig.maxTokens,
|
||||
completionConfig.bestOf,
|
||||
completionConfig.user,
|
||||
completionConfig.stopSequences,
|
||||
completionConfig.getServiceId(),
|
||||
modelId));
|
||||
}
|
||||
|
||||
public CompletionRequestSettings build() {
|
||||
return completionConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public interface CompletionSKFunction extends SKFunction<CompletionRequestSettin
|
||||
|
||||
Builder withPromptTemplateConfig(PromptTemplateConfig config);
|
||||
|
||||
Builder withCompletionConfig(PromptTemplateConfig.CompletionConfig completionConfig);
|
||||
Builder withRequestSettings(CompletionRequestSettings completionRequestSettings);
|
||||
|
||||
Builder withSemanticFunctionConfig(SemanticFunctionConfig functionConfig);
|
||||
|
||||
|
||||
+37
-13
@@ -9,6 +9,7 @@ import com.microsoft.semantickernel.orchestration.FunctionNotRegisteredException
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
|
||||
import com.microsoft.semantickernel.services.AIServiceSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.FunctionView;
|
||||
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
@@ -51,8 +52,15 @@ public class DefaultCompletionSKFunction
|
||||
String description,
|
||||
CompletionRequestSettings requestSettings,
|
||||
SemanticFunctionConfig functionConfig,
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
super(parameters, skillName, functionName, description, kernelSkillsSupplier);
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier,
|
||||
@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
super(
|
||||
parameters,
|
||||
skillName,
|
||||
functionName,
|
||||
description,
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
// TODO
|
||||
// Verify.NotNull(delegateFunction, "The function delegate is empty");
|
||||
// Verify.ValidSkillName(skillName);
|
||||
@@ -163,13 +171,20 @@ public class DefaultCompletionSKFunction
|
||||
settings = this.requestSettings;
|
||||
}
|
||||
|
||||
if (this.aiService.get() == null) {
|
||||
TextCompletion service;
|
||||
if (settings.getServiceId() != null && getAiServiceSupplier() != null) {
|
||||
service = getAiServiceSupplier().get(settings.getServiceId(), TextCompletion.class);
|
||||
} else {
|
||||
service = this.aiService.get();
|
||||
}
|
||||
|
||||
if (service == null) {
|
||||
throw new IllegalStateException("Failed to initialise aiService");
|
||||
}
|
||||
|
||||
CompletionRequestSettings finalSettings = settings;
|
||||
|
||||
return function.run(this.aiService.get(), finalSettings, context)
|
||||
return function.run(service, finalSettings, context)
|
||||
.map(
|
||||
result -> {
|
||||
return context.update(result.getVariables());
|
||||
@@ -230,7 +245,16 @@ public class DefaultCompletionSKFunction
|
||||
};
|
||||
|
||||
this.setSkillsSupplier(kernel::getSkills);
|
||||
this.aiService = () -> kernel.getService(null, TextCompletion.class);
|
||||
this.setServiceSupplier(kernel::getService);
|
||||
|
||||
this.aiService =
|
||||
() ->
|
||||
kernel.getService(
|
||||
this.functionConfig
|
||||
.getConfig()
|
||||
.getCompletionRequestSettings()
|
||||
.getServiceId(),
|
||||
TextCompletion.class);
|
||||
}
|
||||
|
||||
private static Mono<SKContext> performCompletionRequest(
|
||||
@@ -284,10 +308,9 @@ public class DefaultCompletionSKFunction
|
||||
@Nullable private String functionName = null;
|
||||
@Nullable private String skillName = null;
|
||||
@Nullable private String description = null;
|
||||
private PromptTemplateConfig.CompletionConfig completionConfig =
|
||||
new PromptTemplateConfig.CompletionConfig();
|
||||
@Nullable private SemanticFunctionConfig functionConfig = null;
|
||||
@Nullable private PromptTemplateConfig promptTemplateConfig = null;
|
||||
@Nullable private CompletionRequestSettings completionRequestSettings;
|
||||
|
||||
@Override
|
||||
public CompletionSKFunction build() {
|
||||
@@ -320,7 +343,8 @@ public class DefaultCompletionSKFunction
|
||||
|
||||
if (promptTemplateConfig == null) {
|
||||
promptTemplateConfig =
|
||||
new PromptTemplateConfig(description, "completion", completionConfig);
|
||||
new PromptTemplateConfig(
|
||||
description, "completion", completionRequestSettings);
|
||||
}
|
||||
|
||||
PromptTemplate template =
|
||||
@@ -335,8 +359,7 @@ public class DefaultCompletionSKFunction
|
||||
}
|
||||
|
||||
CompletionRequestSettings requestSettings =
|
||||
CompletionRequestSettings.fromCompletionConfig(
|
||||
functionConfig.getConfig().getCompletionConfig());
|
||||
functionConfig.getConfig().getCompletionRequestSettings();
|
||||
|
||||
PromptTemplate promptTemplate = functionConfig.getTemplate();
|
||||
|
||||
@@ -348,6 +371,7 @@ public class DefaultCompletionSKFunction
|
||||
functionConfig.getConfig().getDescription(),
|
||||
requestSettings,
|
||||
functionConfig,
|
||||
null,
|
||||
null);
|
||||
|
||||
kernel.registerSemanticFunction(function);
|
||||
@@ -374,9 +398,9 @@ public class DefaultCompletionSKFunction
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionSKFunction.Builder withCompletionConfig(
|
||||
PromptTemplateConfig.CompletionConfig completionConfig) {
|
||||
this.completionConfig = completionConfig;
|
||||
public CompletionSKFunction.Builder withRequestSettings(
|
||||
CompletionRequestSettings completionRequestSettings) {
|
||||
this.completionRequestSettings = completionRequestSettings;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -2,7 +2,9 @@
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.SKBuilders;
|
||||
import com.microsoft.semantickernel.ai.AIRequestSettings;
|
||||
import com.microsoft.semantickernel.memory.NullMemory;
|
||||
import com.microsoft.semantickernel.services.AIServiceSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
import java.util.Collections;
|
||||
@@ -16,23 +18,24 @@ import reactor.core.publisher.Mono;
|
||||
// cref="Action"/>,
|
||||
/// with additional methods required by the kernel.
|
||||
/// </summary>
|
||||
public abstract class DefaultSemanticSKFunction<RequestConfiguration>
|
||||
extends AbstractSkFunction<RequestConfiguration>
|
||||
implements SKFunction<RequestConfiguration> {
|
||||
public abstract class DefaultSemanticSKFunction<RequestConfiguration extends AIRequestSettings>
|
||||
extends AIFunction<RequestConfiguration> {
|
||||
|
||||
public DefaultSemanticSKFunction(
|
||||
List<ParameterView> parameters,
|
||||
String skillName,
|
||||
String functionName,
|
||||
String description,
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier) {
|
||||
@Nullable KernelSkillsSupplier kernelSkillsSupplier,
|
||||
@Nullable AIServiceSupplier aiServiceSupplier) {
|
||||
super(
|
||||
parameters,
|
||||
skillName,
|
||||
functionName,
|
||||
description,
|
||||
Collections.emptyList(),
|
||||
kernelSkillsSupplier);
|
||||
kernelSkillsSupplier,
|
||||
aiServiceSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+156
-13
@@ -11,7 +11,8 @@ import com.azure.ai.openai.models.Completions;
|
||||
import com.azure.ai.openai.models.CompletionsOptions;
|
||||
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.orchestration.SKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
import java.util.Arrays;
|
||||
@@ -50,8 +51,14 @@ public class DefaultKernelTest {
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("ChatBot")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.7)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
SKContext readOnlySkContext =
|
||||
@@ -261,14 +268,14 @@ public class DefaultKernelTest {
|
||||
openAIAsyncClient.getCompletionsStream(
|
||||
Mockito.any(String.class),
|
||||
Mockito.argThat(
|
||||
it ->
|
||||
response.getT1()
|
||||
.matches(
|
||||
it.getPrompt()
|
||||
.get(
|
||||
it.getPrompt()
|
||||
.size()
|
||||
- 1)))))
|
||||
it -> {
|
||||
return response.getT1()
|
||||
.matches(
|
||||
it.getPrompt()
|
||||
.get(
|
||||
it.getPrompt().size()
|
||||
- 1));
|
||||
})))
|
||||
.then(
|
||||
(arg) -> {
|
||||
response.getT3()
|
||||
@@ -371,8 +378,14 @@ public class DefaultKernelTest {
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Mono<SKContext> mono = summarize.invokeAsync(text);
|
||||
@@ -402,4 +415,134 @@ public class DefaultKernelTest {
|
||||
.get(0)
|
||||
.equals(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modelCanBeOverriddenInTheInvocationTest() {
|
||||
String model = "a-model";
|
||||
|
||||
String expectedResponse = "foo";
|
||||
OpenAIAsyncClient openAIAsyncClient =
|
||||
mockCompletionOpenAIAsyncClient("block", expectedResponse);
|
||||
|
||||
Kernel kernel = buildKernel(model, openAIAsyncClient);
|
||||
|
||||
String text = "A block of text\n";
|
||||
String prompt = "{{$input}}\n" + "Summarize the content above.";
|
||||
String expectedPrompt = "A block of text\n\nSummarize the content above.";
|
||||
|
||||
CompletionSKFunction summarize =
|
||||
SKBuilders.completionFunctions()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Mono<SKContext> mono = summarize.invokeAsync(text);
|
||||
|
||||
SKContext result = mono.block();
|
||||
|
||||
assertCompletionsWasCalledWithModelAndText(openAIAsyncClient, model, expectedPrompt);
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
|
||||
// Invoke again, this time overriding with a different model
|
||||
mono =
|
||||
summarize.invokeAsync(
|
||||
text,
|
||||
SKBuilders.completionRequestSettings().modelId("text-ada-001").build());
|
||||
|
||||
result = mono.block();
|
||||
|
||||
assertCompletionsWasCalledWithModelAndText(
|
||||
openAIAsyncClient, "text-ada-001", expectedPrompt);
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modelAndServiceCanBeOverriddenInTheConfigFileTest() {
|
||||
String expectedResponse = "foo";
|
||||
OpenAIAsyncClient openAIAsyncClient =
|
||||
mockCompletionOpenAIAsyncClient("Tell me a joke.", expectedResponse);
|
||||
|
||||
TextCompletion textCompletion =
|
||||
new OpenAITextCompletion(openAIAsyncClient, "model-that-should-not-be-used");
|
||||
|
||||
Kernel kernel =
|
||||
SKBuilders.kernel()
|
||||
.withAIService("a-service-id", textCompletion, false, TextCompletion.class)
|
||||
.build();
|
||||
|
||||
ReadOnlyFunctionCollection skills =
|
||||
kernel.importSkillFromResources(
|
||||
"Plugins", "ExamplePlugins", "ExampleFunctionWithService");
|
||||
|
||||
SKFunction<?> function = skills.getFunction("ExampleFunctionWithService");
|
||||
|
||||
SKContext result = function.invokeAsync().block();
|
||||
|
||||
assertCompletionsWasCalledWithModelAndText(
|
||||
openAIAsyncClient, "a-model-id", "Tell me a joke.");
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serviceCanBeOverriddenInTheInvocationTest() {
|
||||
String model = "a-model";
|
||||
|
||||
String expectedResponse = "foo";
|
||||
OpenAIAsyncClient openAIAsyncClient =
|
||||
mockCompletionOpenAIAsyncClient("block", expectedResponse);
|
||||
|
||||
TextCompletion textCompletion = new OpenAITextCompletion(openAIAsyncClient, model);
|
||||
|
||||
Kernel kernel =
|
||||
SKBuilders.kernel()
|
||||
.withAIService("a-service-id", textCompletion, false, TextCompletion.class)
|
||||
.build();
|
||||
|
||||
String text = "A block of text\n";
|
||||
String prompt = "{{$input}}\n" + "Summarize the content above.";
|
||||
String expectedPrompt = "A block of text\n\nSummarize the content above.";
|
||||
|
||||
CompletionSKFunction summarize =
|
||||
SKBuilders.completionFunctions()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(prompt)
|
||||
.withFunctionName("summarize")
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0.2)
|
||||
.topP(0.5)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(2000)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Mono<SKContext> mono = summarize.invokeAsync(text);
|
||||
|
||||
SKContext result = mono.block();
|
||||
|
||||
assertCompletionsWasCalledWithModelAndText(openAIAsyncClient, model, expectedPrompt);
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
|
||||
// Invoke again, this time overriding with a different model
|
||||
mono =
|
||||
summarize.invokeAsync(
|
||||
text,
|
||||
SKBuilders.completionRequestSettings().modelId("text-ada-001").build());
|
||||
|
||||
result = mono.block();
|
||||
|
||||
assertCompletionsWasCalledWithModelAndText(
|
||||
openAIAsyncClient, "text-ada-001", expectedPrompt);
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ public class StepwisePlannerTest {
|
||||
System.out.println("*****************************************************");
|
||||
System.out.println("Question: " + question);
|
||||
|
||||
StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null, null);
|
||||
StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null);
|
||||
|
||||
Plan plan = planner.createPlan(question);
|
||||
|
||||
|
||||
+8
-2
@@ -71,8 +71,14 @@ public class Example06TemplateLanguageTest {
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.withKernel(kernel)
|
||||
.withPromptTemplate(functionDefinition)
|
||||
.withCompletionConfig(
|
||||
new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256))
|
||||
.withRequestSettings(
|
||||
SKBuilders.completionRequestSettings()
|
||||
.temperature(0)
|
||||
.topP(0)
|
||||
.presencePenalty(0)
|
||||
.frequencyPenalty(0)
|
||||
.maxTokens(256)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Assertions.assertEquals("A-RESULT", kindOfDay.invokeAsync("").block().getResult());
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"description": "Sample plugin with a model and service id",
|
||||
"type": "completion",
|
||||
"completion": {
|
||||
"max_tokens": 150,
|
||||
"temperature": 0.9,
|
||||
"top_p": 0.0,
|
||||
"presence_penalty": 0.6,
|
||||
"frequency_penalty": 0.0,
|
||||
"service_id": "a-service-id",
|
||||
"model_id": "a-model-id"
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
Tell me a joke.
|
||||
Reference in New Issue
Block a user