mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Fixes from review and add type converters to the InvocationContext
This commit is contained in:
+12
-11
@@ -20,7 +20,6 @@ import com.azure.core.util.BinaryData;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.util.JSONPObject;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.chatcompletion.AuthorRole;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
|
||||
@@ -42,7 +41,6 @@ import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariab
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -99,7 +97,8 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
@Nullable InvocationContext invocationContext) {
|
||||
|
||||
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(chatHistory);
|
||||
List<FunctionDefinition> functions = kernel != null ? getFunctions(kernel) : Collections.emptyList();
|
||||
List<FunctionDefinition> functions =
|
||||
kernel != null ? getFunctions(kernel) : Collections.emptyList();
|
||||
|
||||
return internalChatMessageContentsAsync(
|
||||
chatRequestMessages,
|
||||
@@ -127,7 +126,8 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
List<FunctionDefinition> functions,
|
||||
@Nullable InvocationContext invocationContext) {
|
||||
|
||||
ChatCompletionsOptions options = getCompletionsOptions(this, chatRequestMessages, functions, invocationContext);
|
||||
ChatCompletionsOptions options = getCompletionsOptions(this, chatRequestMessages, functions,
|
||||
invocationContext);
|
||||
Mono<List<ChatMessageContent>> results =
|
||||
internalChatMessageContentsAsync(options, invocationContext);
|
||||
|
||||
@@ -155,7 +155,7 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
ChatCompletionsOptions options,
|
||||
@Nullable InvocationContext invocationContext) {
|
||||
|
||||
KernelHooks kernelHooks =
|
||||
KernelHooks kernelHooks =
|
||||
invocationContext != null && invocationContext.getKernelHooks() != null
|
||||
? invocationContext.getKernelHooks()
|
||||
: new KernelHooks();
|
||||
@@ -283,7 +283,7 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
});
|
||||
arguments = KernelFunctionArguments.builder().withVariables(variables).build();
|
||||
}
|
||||
ContextVariableType<String> variableType = ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
ContextVariableType<String> variableType = ContextVariableTypes.getGlobalVariableTypeForClass(
|
||||
String.class);
|
||||
return kernelFunction.invokeAsync(kernel, arguments, variableType);
|
||||
}
|
||||
@@ -314,12 +314,12 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
MAX_RESULTS_PER_PROMPT));
|
||||
}
|
||||
|
||||
ToolCallBehavior toolCallBehavior = invocationContext != null
|
||||
ToolCallBehavior toolCallBehavior = invocationContext != null
|
||||
? invocationContext.getToolCallBehavior()
|
||||
: null;
|
||||
List<ChatCompletionsToolDefinition> toolDefinitions =
|
||||
chatCompletionsToolDefinitions(toolCallBehavior,functions);
|
||||
|
||||
chatCompletionsToolDefinitions(toolCallBehavior, functions);
|
||||
|
||||
if (toolDefinitions != null && !toolDefinitions.isEmpty()) {
|
||||
options.setTools(toolDefinitions);
|
||||
// TODO: options.setToolChoices(toolChoices);
|
||||
@@ -432,7 +432,7 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
});
|
||||
});
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
|
||||
private static FunctionDefinition toFunctionDefinition(KernelFunction function) {
|
||||
String name = String.format("%s-%s", function.getSkillName(), function.getName());
|
||||
@@ -464,7 +464,8 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
"{\"type\": \"object\", \"properties\": {");
|
||||
parameters.forEach(parameter -> {
|
||||
// make "param": {"type": "string", "description": "desc"},
|
||||
sb.append(String.format("\"%s\": %s,", parameter.getName(), parameter.getDescription()));
|
||||
sb.append(
|
||||
String.format("\"%s\": %s,", parameter.getName(), parameter.getDescription()));
|
||||
if (parameter.isRequired()) {
|
||||
requiredParmeters.add(parameter.getName());
|
||||
}
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ public class ConversationSummaryPlugin {
|
||||
new KernelFunctionArguments.Builder()
|
||||
.withInput(paragraph)
|
||||
.build(),
|
||||
ContextVariableTypes.getDefaultVariableTypeForClass(String.class));
|
||||
ContextVariableTypes.getGlobalVariableTypeForClass(String.class));
|
||||
})
|
||||
.reduce("", (acc, next) -> {
|
||||
return acc + "\n" + next.getResult();
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class Example06_TemplateLanguage {
|
||||
var promptTemplate = new KernelPromptTemplateFactory()
|
||||
.tryCreate(new PromptTemplateConfig(functionDefinition));
|
||||
|
||||
var renderedPrompt = promptTemplate.renderAsync(kernel, null).block();
|
||||
var renderedPrompt = promptTemplate.renderAsync(kernel, null, null).block();
|
||||
System.out.println(renderedPrompt);
|
||||
|
||||
var kindOfDay = KernelFunctionFactory
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ public class Example07_BingAndGooglePlugins {
|
||||
.tryCreate(new PromptTemplateConfig(result));
|
||||
|
||||
System.out.println("---- Fetching information from Bing...");
|
||||
var information = promptTemplate.renderAsync(kernel, null).block();
|
||||
var information = promptTemplate.renderAsync(kernel, null, null).block();
|
||||
|
||||
System.out.println("Information found:");
|
||||
System.out.println(information);
|
||||
|
||||
+14
-2
@@ -8,7 +8,6 @@ import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.azure.core.credential.KeyCredential;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
@@ -29,6 +28,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class Example09_FunctionTypes {
|
||||
@@ -78,7 +78,7 @@ public class Example09_FunctionTypes {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
System.out.println("======== Method Function types ========");
|
||||
|
||||
@@ -130,6 +130,18 @@ public class Example09_FunctionTypes {
|
||||
FunctionResult<?> result = kernel.invokeAsync(plugin.get("NoInputWithVoidResult"))
|
||||
.block();
|
||||
assert result == null;
|
||||
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
|
||||
kernel
|
||||
.invokeAsync(plugin.get("NoInputWithVoidResult"))
|
||||
.doFinally(ignore -> cdl.countDown())
|
||||
.subscribe(ignore -> {
|
||||
throw new RuntimeException("No return expected");
|
||||
});
|
||||
|
||||
cdl.await();
|
||||
|
||||
System.out.println(result != null ? result.getResult() : "null");
|
||||
result = kernel.invokeAsync(plugin.get("NoInputTaskWithVoidResult"))
|
||||
.block();
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class Example27_PromptFunctionsUsingChatGPT {
|
||||
KernelFunctionArguments.builder()
|
||||
.withVariable("input", "Jupiter")
|
||||
.build(),
|
||||
ContextVariableTypes.getDefaultVariableTypeForClass(String.class)
|
||||
ContextVariableTypes.getGlobalVariableTypeForClass(String.class)
|
||||
)
|
||||
.block();
|
||||
System.out.println(result.getResult());
|
||||
|
||||
+2
-2
@@ -90,7 +90,7 @@ public class Example30_ChatWithPrompts {
|
||||
// This contains the context, ie a piece of a wikipedia page selected by the user.
|
||||
String systemMessage = PromptTemplateFactory
|
||||
.build(new PromptTemplateConfig(systemPromptTemplate))
|
||||
.renderAsync(kernel, arguments)
|
||||
.renderAsync(kernel, arguments, null)
|
||||
.block();
|
||||
|
||||
System.out.println("------------------------------------\n" + systemMessage);
|
||||
@@ -99,7 +99,7 @@ public class Example30_ChatWithPrompts {
|
||||
// This contains the user request, ie "extract locations as a bullet point list"
|
||||
String userMessage = PromptTemplateFactory
|
||||
.build(new PromptTemplateConfig(userPromptTemplate))
|
||||
.renderAsync(kernel, arguments)
|
||||
.renderAsync(kernel, arguments, null)
|
||||
.block();
|
||||
|
||||
System.out.println("------------------------------------\n" + userMessage);
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ public class Example56_TemplateMethodFunctionsWithMultipleArguments {
|
||||
var promptTemplateFactory = new KernelPromptTemplateFactory();
|
||||
var promptTemplate = promptTemplateFactory.tryCreate(
|
||||
new PromptTemplateConfig(functionDefinition));
|
||||
var renderedPrompt = promptTemplate.renderAsync(kernel, arguments).block();
|
||||
var renderedPrompt = promptTemplate.renderAsync(kernel, arguments, null).block();
|
||||
System.out.println(renderedPrompt);
|
||||
|
||||
// Run the prompt / prompt function
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ public class Example60_AdvancedMethodFunctions {
|
||||
s -> null
|
||||
);
|
||||
|
||||
ContextVariableTypes.DEFAULT_TYPES.putConverter(type);
|
||||
ContextVariableTypes.addGlobalConverter(type);
|
||||
|
||||
var result = kernel
|
||||
.invokeAsync(FunctionsChainingPlugin.PluginName, "Function1")
|
||||
@@ -38,7 +38,7 @@ public class Example60_AdvancedMethodFunctions {
|
||||
KernelFunctionArguments
|
||||
.builder()
|
||||
.build())
|
||||
.withResultType(ContextVariableTypes.getDefaultVariableTypeForClass(MyCustomType.class))
|
||||
.withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(MyCustomType.class))
|
||||
.block();
|
||||
|
||||
System.out.println("CustomType.Number: " + result.getResult().number); // 2
|
||||
@@ -85,7 +85,7 @@ public class Example60_AdvancedMethodFunctions {
|
||||
return kernel
|
||||
.invokeAsync(PluginName, "Function2")
|
||||
.withArguments(KernelFunctionArguments.builder().build())
|
||||
.withResultType(ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
.withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(
|
||||
Example60_AdvancedMethodFunctions.MyCustomType.class))
|
||||
.flatMap(value -> {
|
||||
// Process the result
|
||||
|
||||
+35
-19
@@ -12,6 +12,7 @@ import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
|
||||
import com.microsoft.semantickernel.orchestration.ToolCallBehavior.UnmodifiableToolCallBehavior;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@@ -27,15 +28,17 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
private final KernelFunction<?> function;
|
||||
private final Kernel kernel;
|
||||
@Nullable
|
||||
private KernelFunctionArguments arguments;
|
||||
private final ContextVariableType<T> resultType;
|
||||
|
||||
@Nullable
|
||||
private ContextVariableType<T> resultType;
|
||||
private KernelFunctionArguments arguments;
|
||||
@Nullable
|
||||
private UnmodifiableKernelHooks hooks;
|
||||
@Nullable
|
||||
private PromptExecutionSettings promptExecutionSettings;
|
||||
@Nullable
|
||||
private UnmodifiableToolCallBehavior toolCallBehavior;
|
||||
private final ContextVariableTypes contextVariableTypes = new ContextVariableTypes();
|
||||
|
||||
|
||||
public FunctionInvocation(
|
||||
@@ -43,6 +46,7 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
KernelFunction<T> function) {
|
||||
this.function = function;
|
||||
this.kernel = kernel;
|
||||
this.resultType = null;
|
||||
}
|
||||
|
||||
public FunctionInvocation(
|
||||
@@ -53,6 +57,9 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
this.function = function;
|
||||
this.kernel = kernel;
|
||||
this.resultType = resultType;
|
||||
if (resultType != null) {
|
||||
contextVariableTypes.putConverter(resultType.getConverter());
|
||||
}
|
||||
}
|
||||
|
||||
public FunctionInvocation<T> withArguments(
|
||||
@@ -96,6 +103,27 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FunctionInvocation<T> withTypeConverter(ContextVariableType<?> typeConverter) {
|
||||
contextVariableTypes.putConverter(typeConverter.getConverter());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(CoreSubscriber<? super FunctionResult<T>> coreSubscriber) {
|
||||
performSubscribe(
|
||||
coreSubscriber,
|
||||
kernel,
|
||||
function,
|
||||
arguments,
|
||||
resultType,
|
||||
new InvocationContext(
|
||||
hooks,
|
||||
promptExecutionSettings,
|
||||
toolCallBehavior,
|
||||
contextVariableTypes
|
||||
));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static UnmodifiableToolCallBehavior unmodifiableClone(
|
||||
@Nullable
|
||||
@@ -121,20 +149,6 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(CoreSubscriber<? super FunctionResult<T>> coreSubscriber) {
|
||||
performSubscribe(
|
||||
coreSubscriber,
|
||||
kernel,
|
||||
function,
|
||||
arguments,
|
||||
resultType,
|
||||
new InvocationContext(
|
||||
hooks,
|
||||
promptExecutionSettings,
|
||||
toolCallBehavior
|
||||
));
|
||||
}
|
||||
|
||||
// Extracted to static to ensure mutable state is not used
|
||||
private static <T> void performSubscribe(
|
||||
@@ -148,6 +162,7 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
@Nullable
|
||||
InvocationContext context
|
||||
) {
|
||||
|
||||
if (variableType == null) {
|
||||
LOGGER.debug(
|
||||
"No variable type explicitly specified by calling 'withResultType' for function invocation: "
|
||||
@@ -155,11 +170,12 @@ public class FunctionInvocation<T> extends Mono<FunctionResult<T>> {
|
||||
+ " This may cause a runtime error (probably a ClassCastException) if the result type is not compatible with the expected type.");
|
||||
}
|
||||
|
||||
function.invokeAsync(
|
||||
function
|
||||
.invokeAsync(
|
||||
kernel,
|
||||
arguments,
|
||||
new KernelFunctionArguments(arguments),
|
||||
null,
|
||||
context)
|
||||
new InvocationContext(context))
|
||||
.handle(FunctionInvocation.convertToType(variableType))
|
||||
.subscribe(coreSubscriber);
|
||||
}
|
||||
|
||||
@@ -13,14 +13,6 @@ public class Verify {
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
public static boolean isNullOrEmpty(@Nullable ContextVariable<?> s) {
|
||||
return s == null
|
||||
|| s.getValue() == null
|
||||
|| s.getType().equals(String.class) && ((ContextVariable<String>) s).getValue()
|
||||
.isEmpty();
|
||||
}
|
||||
*/
|
||||
public static boolean isNullOrWhiteSpace(String s) {
|
||||
return s == null || s.matches("^\\w+$");
|
||||
}
|
||||
|
||||
+44
-6
@@ -5,6 +5,8 @@ import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks.UnmodifiableKernelHooks;
|
||||
import com.microsoft.semantickernel.orchestration.ToolCallBehavior.UnmodifiableToolCallBehavior;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -19,20 +21,42 @@ public class InvocationContext implements Buildable {
|
||||
private final PromptExecutionSettings promptExecutionSettings;
|
||||
@Nullable
|
||||
private final UnmodifiableToolCallBehavior toolCallBehavior;
|
||||
private final ContextVariableTypes contextVariableTypes;
|
||||
|
||||
public InvocationContext(
|
||||
@Nullable KernelHooks hooks,
|
||||
@Nullable PromptExecutionSettings promptExecutionSettings,
|
||||
@Nullable ToolCallBehavior toolCallBehavior) {
|
||||
@Nullable ToolCallBehavior toolCallBehavior,
|
||||
@Nullable ContextVariableTypes contextVariableTypes) {
|
||||
this.hooks = unmodifiableClone(hooks);
|
||||
this.promptExecutionSettings = promptExecutionSettings;
|
||||
this.toolCallBehavior = unmodifiableClone(toolCallBehavior);
|
||||
if (contextVariableTypes == null) {
|
||||
this.contextVariableTypes = new ContextVariableTypes();
|
||||
} else {
|
||||
this.contextVariableTypes = new ContextVariableTypes(contextVariableTypes);
|
||||
}
|
||||
}
|
||||
|
||||
public InvocationContext(InvocationContext context) {
|
||||
this.hooks = context.hooks;
|
||||
this.promptExecutionSettings = context.promptExecutionSettings;
|
||||
this.toolCallBehavior = context.toolCallBehavior;
|
||||
public InvocationContext() {
|
||||
this.hooks = null;
|
||||
this.promptExecutionSettings = null;
|
||||
this.toolCallBehavior = null;
|
||||
this.contextVariableTypes = new ContextVariableTypes();
|
||||
}
|
||||
|
||||
public InvocationContext(@Nullable InvocationContext context) {
|
||||
if (context == null) {
|
||||
this.hooks = null;
|
||||
this.promptExecutionSettings = null;
|
||||
this.toolCallBehavior = null;
|
||||
this.contextVariableTypes = new ContextVariableTypes();
|
||||
} else {
|
||||
this.hooks = context.hooks;
|
||||
this.promptExecutionSettings = context.promptExecutionSettings;
|
||||
this.toolCallBehavior = context.toolCallBehavior;
|
||||
this.contextVariableTypes = context.contextVariableTypes;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "returns UnmodifiableKernelHooks")
|
||||
@@ -52,6 +76,10 @@ public class InvocationContext implements Buildable {
|
||||
return toolCallBehavior;
|
||||
}
|
||||
|
||||
public ContextVariableTypes getContextVariableTypes() {
|
||||
return new ContextVariableTypes(contextVariableTypes);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
@@ -93,6 +121,8 @@ public class InvocationContext implements Buildable {
|
||||
@Nullable
|
||||
private UnmodifiableToolCallBehavior toolCallBehavior;
|
||||
|
||||
private final ContextVariableTypes contextVariableTypes = new ContextVariableTypes();
|
||||
|
||||
public Builder withKernelHooks(
|
||||
@Nullable KernelHooks hooks) {
|
||||
this.hooks = unmodifiableClone(hooks);
|
||||
@@ -113,9 +143,17 @@ public class InvocationContext implements Buildable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withContextVariableConverter(ContextVariableTypeConverter<?> converter) {
|
||||
this.contextVariableTypes.putConverter(
|
||||
converter
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationContext build() {
|
||||
return new InvocationContext(hooks, promptExecutionSettings, toolCallBehavior);
|
||||
return new InvocationContext(hooks, promptExecutionSettings, toolCallBehavior,
|
||||
contextVariableTypes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -172,7 +172,7 @@ public abstract class KernelFunction<T> implements Buildable {
|
||||
@Nullable ContextVariableType<T> variableType,
|
||||
@Nullable InvocationContext invocationContext);
|
||||
|
||||
public static interface FromPromptBuilder<T> {
|
||||
public interface FromPromptBuilder<T> {
|
||||
|
||||
FromPromptBuilder<T> withName(@Nullable String name);
|
||||
|
||||
|
||||
+52
-10
@@ -6,15 +6,14 @@ import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.CaseInsensitiveMap;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Context Variables is a data structure that holds temporary data while a task is being performed.
|
||||
@@ -30,8 +29,13 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
private final CaseInsensitiveMap<ContextVariable<?>> variables;
|
||||
|
||||
public KernelFunctionArguments(
|
||||
@Nullable
|
||||
Map<String, ContextVariable<?>> variables) {
|
||||
this.variables = new CaseInsensitiveMap<>(variables);
|
||||
if (variables == null) {
|
||||
this.variables = new CaseInsensitiveMap<>();
|
||||
} else {
|
||||
this.variables = new CaseInsensitiveMap<>(variables);
|
||||
}
|
||||
}
|
||||
|
||||
public KernelFunctionArguments(@NonNull ContextVariable<?> content) {
|
||||
@@ -169,7 +173,7 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
public Set<Entry<String, ContextVariable<?>>> entrySet() {
|
||||
return variables.entrySet();
|
||||
}
|
||||
|
||||
|
||||
public static Builder builder() {
|
||||
return new KernelFunctionArguments.Builder();
|
||||
}
|
||||
@@ -179,7 +183,7 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
*/
|
||||
public static class Builder implements SemanticKernelBuilder<KernelFunctionArguments> {
|
||||
|
||||
private final Map<String,ContextVariable<?>> variables;
|
||||
private final Map<String, ContextVariable<?>> variables;
|
||||
|
||||
public Builder() {
|
||||
variables = new HashMap<>();
|
||||
@@ -204,7 +208,25 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
* @throws SKException if the content cannot be converted to a ContextVariable
|
||||
*/
|
||||
public Builder withInput(Object content) {
|
||||
return withInput(ContextVariable.of(content));
|
||||
return withInput(ContextVariable.ofGlobalType(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance with the given content in the default main key
|
||||
*
|
||||
* @param content Entry to place in the "input" slot
|
||||
* @param typeConverter Type converter for the content
|
||||
* @return {$code this} Builder for fluent coding
|
||||
* @throws SKException if the content cannot be converted to a ContextVariable
|
||||
*/
|
||||
public <T> Builder withInput(T content, ContextVariableTypeConverter<T> typeConverter) {
|
||||
return withInput(new ContextVariable<>(
|
||||
new ContextVariableType<>(
|
||||
typeConverter,
|
||||
typeConverter.getType()
|
||||
),
|
||||
content)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +253,7 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variable
|
||||
* Set variable, uses the default type converters
|
||||
*
|
||||
* @param key variable name
|
||||
* @param value variable value
|
||||
@@ -239,7 +261,27 @@ public class KernelFunctionArguments implements Buildable, Map<String, ContextVa
|
||||
* @throws SKException if the value cannot be converted to a ContextVariable
|
||||
*/
|
||||
public Builder withVariable(String key, Object value) {
|
||||
return withVariable(key, ContextVariable.of(value));
|
||||
return withVariable(key, ContextVariable.ofGlobalType(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variable
|
||||
*
|
||||
* @param key variable name
|
||||
* @param value variable value
|
||||
* @param typeConverter Type converter for the value
|
||||
* @return {$code this} Builder for fluent coding
|
||||
* @throws SKException if the value cannot be converted to a ContextVariable
|
||||
*/
|
||||
public <T> Builder withVariable(String key, T value,
|
||||
ContextVariableTypeConverter<T> typeConverter) {
|
||||
return withVariable(key, new ContextVariable<>(
|
||||
new ContextVariableType<>(
|
||||
typeConverter,
|
||||
typeConverter.getType()
|
||||
),
|
||||
value
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+42
-63
@@ -1,13 +1,11 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration.contextvariables;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.azure.ai.openai.models.CompletionsUsage;
|
||||
import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter.NoopConverter;
|
||||
import java.util.Arrays;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -18,67 +16,21 @@ public class ContextVariable<T> {
|
||||
@Nullable
|
||||
private final T value;
|
||||
|
||||
public ContextVariable(ContextVariableType<T> type,
|
||||
public ContextVariable(
|
||||
ContextVariableType<T> type,
|
||||
@Nullable T value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static <T> ContextVariable<T> of(Class<T> type, @Nullable T t) {
|
||||
if (t == null) {
|
||||
return new ContextVariable<>(
|
||||
ContextVariableTypes.getDefaultVariableTypeForClass(type),
|
||||
null);
|
||||
}
|
||||
|
||||
return of(t);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static ContextVariable<?> untypedOf(
|
||||
@Nullable Object value,
|
||||
Class<?> clazz) {
|
||||
ContextVariableType<?> type = ContextVariableTypes.getDefaultVariableTypeForClass(clazz);
|
||||
return new ContextVariable(type, value);
|
||||
}
|
||||
|
||||
public static ContextVariable<?> untypedOf(
|
||||
@Nullable Object value,
|
||||
ContextVariableTypeConverter<?> converter) {
|
||||
ContextVariableType<?> type = new ContextVariableType(converter, converter.getType());
|
||||
return new ContextVariable(type, value);
|
||||
}
|
||||
|
||||
public static <T, U> ContextVariable<T> convert(
|
||||
@Nullable
|
||||
U it,
|
||||
ContextVariableType<T> requestedResultType) {
|
||||
try {
|
||||
return convert(
|
||||
it,
|
||||
requestedResultType.getClazz(),
|
||||
new ContextVariableTypes(
|
||||
Arrays.asList(requestedResultType.getConverter()))
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
return convert(
|
||||
it,
|
||||
requestedResultType.getClazz(),
|
||||
ContextVariableTypes.DEFAULT_TYPES
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static <T, U> ContextVariable<T> convert(
|
||||
@Nullable
|
||||
U it,
|
||||
Class<T> requestedResultType) {
|
||||
return convert(
|
||||
it,
|
||||
requestedResultType,
|
||||
ContextVariableTypes.DEFAULT_TYPES
|
||||
requestedResultType.getClazz(),
|
||||
new ContextVariableTypes(Collections.singletonList(requestedResultType.getConverter()))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -86,7 +38,12 @@ public class ContextVariable<T> {
|
||||
@Nullable
|
||||
U it,
|
||||
Class<T> requestedResultType,
|
||||
@Nullable
|
||||
ContextVariableTypes contextVariableTypes) {
|
||||
if (contextVariableTypes == null) {
|
||||
contextVariableTypes = new ContextVariableTypes();
|
||||
}
|
||||
|
||||
if (it == null) {
|
||||
return new ContextVariable<>(
|
||||
contextVariableTypes.getVariableTypeForClass(requestedResultType),
|
||||
@@ -95,7 +52,9 @@ public class ContextVariable<T> {
|
||||
|
||||
if (requestedResultType.isAssignableFrom(it.getClass())) {
|
||||
try {
|
||||
return ContextVariable.of(requestedResultType, requestedResultType.cast(it));
|
||||
return contextVariableTypes
|
||||
.getVariableTypeForClass(requestedResultType)
|
||||
.of(requestedResultType.cast(it));
|
||||
} catch (Exception e) {
|
||||
return new ContextVariable<>(
|
||||
new ContextVariableType<>(
|
||||
@@ -167,6 +126,31 @@ public class ContextVariable<T> {
|
||||
throw new SKException("Unable to convert " + it.getClass() + " to " + requestedResultType);
|
||||
}
|
||||
|
||||
public static ContextVariable<?> untypedOf(
|
||||
@Nullable Object value,
|
||||
Class<?> clazz,
|
||||
ContextVariableTypes types) {
|
||||
ContextVariableType<?> type = types.getVariableTypeForClass(clazz);
|
||||
|
||||
return new ContextVariable(type, value);
|
||||
}
|
||||
|
||||
public static ContextVariable<CompletionsUsage> of(CompletionsUsage x) {
|
||||
return ofValue(x);
|
||||
}
|
||||
|
||||
public static ContextVariable<OffsetDateTime> of(OffsetDateTime x) {
|
||||
return ofValue(x);
|
||||
}
|
||||
|
||||
public static ContextVariable<String> of(String value) {
|
||||
return ofValue(value);
|
||||
}
|
||||
|
||||
public static ContextVariable<Object> ofGlobalType(Object x) {
|
||||
return ofValue(x);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getValue() {
|
||||
return value;
|
||||
@@ -182,7 +166,6 @@ public class ContextVariable<T> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ContextVariableType<T> getType() {
|
||||
return type;
|
||||
}
|
||||
@@ -199,19 +182,15 @@ public class ContextVariable<T> {
|
||||
return value == null || value.toString().isEmpty();
|
||||
}
|
||||
|
||||
public ContextVariable<T> cloneVariable() {
|
||||
return new ContextVariable<>(type, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ContextVariable<T> of(T value) {
|
||||
private static <T> ContextVariable<T> ofValue(T value) {
|
||||
Objects.requireNonNull(value, "value cannot be null");
|
||||
|
||||
if (value instanceof ContextVariable) {
|
||||
return (ContextVariable<T>) value;
|
||||
}
|
||||
|
||||
ContextVariableType<T> type = ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
ContextVariableType<T> type = ContextVariableTypes.getGlobalVariableTypeForClass(
|
||||
(Class<T>) value.getClass());
|
||||
return new ContextVariable<>(type, value);
|
||||
}
|
||||
|
||||
+10
-3
@@ -30,14 +30,21 @@ public class ContextVariableType<T> {
|
||||
*/
|
||||
public ContextVariable<T> of(@Nullable Object it) {
|
||||
if (it == null) {
|
||||
return ContextVariable.of(clazz, clazz.cast(null));
|
||||
return new ContextVariable<>(
|
||||
this,
|
||||
clazz.cast(null)
|
||||
);
|
||||
}
|
||||
|
||||
if (clazz.isAssignableFrom(it.getClass())) {
|
||||
return ContextVariable.of(clazz.cast(it), getConverter());
|
||||
}
|
||||
ContextVariableTypeConverter<T> converter = getConverter();
|
||||
return ContextVariable.of(converter.getType(), converter.fromObject(it));
|
||||
|
||||
return new ContextVariable<>(
|
||||
this,
|
||||
converter.fromObject(it)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+46
-15
@@ -1,15 +1,6 @@
|
||||
package com.microsoft.semantickernel.orchestration.contextvariables;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter.NoopConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.BooleanVariableContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.CharacterVariableContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.ChatHistoryVariableContextVariableTypeConverter;
|
||||
@@ -19,10 +10,15 @@ import com.microsoft.semantickernel.orchestration.contextvariables.converters.In
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.NumberVariableContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.StringVariableContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.converters.VoidVariableContextVariableTypeConverter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ContextVariableTypes {
|
||||
|
||||
public static final ContextVariableTypes DEFAULT_TYPES;
|
||||
private static final ContextVariableTypes DEFAULT_TYPES;
|
||||
|
||||
static {
|
||||
List<ContextVariableTypeConverter<?>> types = Arrays.asList(
|
||||
@@ -60,12 +56,30 @@ public class ContextVariableTypes {
|
||||
}
|
||||
|
||||
|
||||
private final Map<Class<?>, ContextVariableType<?>> variableTypes = new HashMap<>();
|
||||
private final Map<Class<?>, ContextVariableType<?>> variableTypes;
|
||||
|
||||
public ContextVariableTypes(List<ContextVariableTypeConverter<?>> converters) {
|
||||
variableTypes = new HashMap<>();
|
||||
converters.forEach(this::putConverter);
|
||||
}
|
||||
|
||||
public ContextVariableTypes() {
|
||||
variableTypes = new HashMap<>();
|
||||
}
|
||||
|
||||
public ContextVariableTypes(ContextVariableTypes contextVariableTypes) {
|
||||
this.variableTypes = new HashMap<>(contextVariableTypes.variableTypes);
|
||||
}
|
||||
|
||||
public static void addGlobalConverter(
|
||||
ContextVariableTypeConverter<?> type) {
|
||||
DEFAULT_TYPES.putConverter(type);
|
||||
}
|
||||
|
||||
public static <T> ContextVariableType<T> getGlobalVariableTypeForClass(Class<T> aClass) {
|
||||
return DEFAULT_TYPES.getVariableTypeForClass(aClass);
|
||||
}
|
||||
|
||||
public <T> void putConverter(
|
||||
ContextVariableTypeConverter<T> contextVariableTypeConverter) {
|
||||
variableTypes.put(contextVariableTypeConverter.getType(),
|
||||
@@ -87,12 +101,28 @@ public class ContextVariableTypes {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> ContextVariableType<T> getDefaultVariableTypeForClass(Class<T> aClass) {
|
||||
return DEFAULT_TYPES.getVariableTypeForClass(aClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ContextVariableType<T> getVariableTypeForClass(Class<T> aClass) {
|
||||
try {
|
||||
return this.getVariableTypeForClassInternal(aClass);
|
||||
} catch (Exception e) {
|
||||
return DEFAULT_TYPES.getVariableTypeForClassInternal(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ContextVariableType<T> getVariableTypeForSuperClass(Class<T> aClass) {
|
||||
try {
|
||||
return this.getVariableTypeForSuperClassInternal(aClass);
|
||||
} catch (Exception e) {
|
||||
return DEFAULT_TYPES.getVariableTypeForSuperClassInternal(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ContextVariableType<T> getVariableTypeForClassInternal(Class<T> aClass) {
|
||||
ContextVariableType<?> contextVariableType = variableTypes.get(aClass);
|
||||
|
||||
if (contextVariableType != null) {
|
||||
@@ -111,7 +141,7 @@ public class ContextVariableTypes {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ContextVariableType<T> getVariableTypeForSuperClass(Class<T> aClass) {
|
||||
private <T> ContextVariableType<T> getVariableTypeForSuperClassInternal(Class<T> aClass) {
|
||||
ContextVariableType<?> contextVariableType = variableTypes.get(aClass);
|
||||
|
||||
if (contextVariableType != null) {
|
||||
@@ -128,4 +158,5 @@ public class ContextVariableTypes {
|
||||
.orElseThrow(
|
||||
() -> new SKException("Unknown context variable type: " + aClass.getName()));
|
||||
}
|
||||
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.microsoft.semantickernel.orchestration.contextvariables;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter.NoopConverter;
|
||||
|
||||
public class NullContextVariable<T> extends ContextVariable<T> {
|
||||
|
||||
public NullContextVariable(Class<T> type) {
|
||||
super(new ContextVariableType<>(
|
||||
new NoopConverter<>(type),
|
||||
type
|
||||
), null);
|
||||
}
|
||||
}
|
||||
+27
-16
@@ -19,7 +19,6 @@ import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariab
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypeConverter.NoopConverter;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.KernelReturnParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.annotations.DefineKernelFunction;
|
||||
@@ -168,13 +167,16 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> ImplementationFunc<T> getFunction(Method method, Object instance) {
|
||||
return (kernel, function, arguments, variableType, invocationContext) -> {
|
||||
InvocationContext context;
|
||||
if (invocationContext == null) {
|
||||
invocationContext = InvocationContext.builder().build();
|
||||
context = InvocationContext.builder().build();
|
||||
} else {
|
||||
context = invocationContext;
|
||||
}
|
||||
|
||||
// kernelHooks must be effectively final for lambda
|
||||
KernelHooks kernelHooks = invocationContext.getKernelHooks() != null
|
||||
? invocationContext.getKernelHooks()
|
||||
KernelHooks kernelHooks = context.getKernelHooks() != null
|
||||
? context.getKernelHooks()
|
||||
: kernel.getGlobalKernelHooks();
|
||||
assert kernelHooks != null : "getGlobalKernelHooks() should never return null!";
|
||||
|
||||
@@ -187,7 +189,7 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
try {
|
||||
List<Object> args =
|
||||
Arrays.stream(method.getParameters())
|
||||
.map(getParameters(method, updatedArguments, kernel))
|
||||
.map(getParameters(method, updatedArguments, kernel, context))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Mono<?> mono;
|
||||
@@ -231,6 +233,7 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
|
||||
// If the function has a return type that has a ContextVariableType<T>, use it.
|
||||
ContextVariableType<T> contextVariableType = getContextVariableType(
|
||||
invocationContext,
|
||||
returnParameterType);
|
||||
if (contextVariableType == null) {
|
||||
// If getting the context variable type from the function fails, default to
|
||||
@@ -267,14 +270,15 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> ContextVariableType<T> getContextVariableType(Class<?> clazz) {
|
||||
private static <T> ContextVariableType<T> getContextVariableType(
|
||||
InvocationContext invocationContext, Class<?> clazz) {
|
||||
|
||||
if (clazz != null) {
|
||||
try {
|
||||
// unchecked cast
|
||||
Class<T> tClazz = (Class<T>) clazz;
|
||||
ContextVariableType<T> type = ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
tClazz);
|
||||
ContextVariableType<T> type = invocationContext.getContextVariableTypes()
|
||||
.getVariableTypeForClass(tClazz);
|
||||
return type;
|
||||
} catch (ClassCastException | SKException e) {
|
||||
// SKException is thrown from ContextVariableTypes.getDefaultVariableTypeForClass
|
||||
@@ -341,12 +345,13 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
Method method,
|
||||
@Nullable
|
||||
KernelFunctionArguments context,
|
||||
Kernel kernel) {
|
||||
Kernel kernel,
|
||||
InvocationContext invocationContext) {
|
||||
return parameter -> {
|
||||
if (KernelFunctionArguments.class.isAssignableFrom(parameter.getType())) {
|
||||
return context;
|
||||
} else {
|
||||
return getArgumentValue(method, context, parameter, kernel);
|
||||
return getArgumentValue(method, context, parameter, kernel, invocationContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -356,7 +361,8 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
Method method,
|
||||
@Nullable KernelFunctionArguments context,
|
||||
Parameter parameter,
|
||||
Kernel kernel) {
|
||||
Kernel kernel,
|
||||
InvocationContext invocationContext) {
|
||||
String variableName = getGetVariableName(parameter);
|
||||
|
||||
ContextVariable<?> arg = context == null ? null : context.get(variableName);
|
||||
@@ -367,12 +373,17 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
// Convert from the defaultValue, which is a String to the argument type
|
||||
// Expectation here is that the fromPromptString method will be able to handle a null or empty string
|
||||
Class<?> type = annotation.type();
|
||||
ContextVariableType<?> cvType = ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
type);
|
||||
|
||||
ContextVariableType<?> cvType = invocationContext
|
||||
.getContextVariableTypes()
|
||||
.getVariableTypeForClass(type);
|
||||
|
||||
if (cvType != null) {
|
||||
String defaultValue = annotation.defaultValue();
|
||||
Object value = cvType.getConverter().fromPromptString(defaultValue);
|
||||
arg = ContextVariable.untypedOf(value, cvType.getConverter());
|
||||
|
||||
arg = ContextVariable.convert(value, type,
|
||||
invocationContext.getContextVariableTypes());
|
||||
}
|
||||
|
||||
if (arg != null && NO_DEFAULT_VALUE.equals(arg.getValue())) {
|
||||
@@ -450,8 +461,8 @@ public class KernelFunctionFromMethod<T> extends KernelFunction<T> {
|
||||
}
|
||||
|
||||
// Well-known types only
|
||||
ContextVariableType<?> converter = ContextVariableTypes.getDefaultVariableTypeForClass(
|
||||
type);
|
||||
ContextVariableType<?> converter = invocationContext.getContextVariableTypes()
|
||||
.getVariableTypeForClass(type);
|
||||
if (converter != null) {
|
||||
try {
|
||||
value = converter.getConverter().fromObject(arg);
|
||||
|
||||
+55
-41
@@ -1,17 +1,5 @@
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.azure.core.exception.HttpResponseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
@@ -35,11 +23,18 @@ import com.microsoft.semantickernel.orchestration.KernelFunctionMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.services.AIServiceSelection;
|
||||
import com.microsoft.semantickernel.textcompletion.TextGenerationService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -112,11 +107,12 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
@Nullable ContextVariableType<T> contextVariableType,
|
||||
@Nullable InvocationContext invocationContext) {
|
||||
|
||||
InvocationContext context = invocationContext != null ? invocationContext : InvocationContext.builder().build();
|
||||
InvocationContext context =
|
||||
invocationContext != null ? invocationContext : InvocationContext.builder().build();
|
||||
|
||||
// must be effectively final for lambda
|
||||
KernelHooks kernelHooks = context.getKernelHooks() != null
|
||||
? context.getKernelHooks()
|
||||
KernelHooks kernelHooks = context.getKernelHooks() != null
|
||||
? context.getKernelHooks()
|
||||
: kernel.getGlobalKernelHooks();
|
||||
assert kernelHooks != null : "getGlobalKernelHooks() should never return null";
|
||||
|
||||
@@ -126,13 +122,13 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
// TOOD: put in method, add catch for classcastexception, fallback to noopconverter
|
||||
ContextVariableType<T> variableType = contextVariableType != null
|
||||
? contextVariableType
|
||||
: ContextVariableTypes.<T>getDefaultVariableTypeForClass(
|
||||
: context.getContextVariableTypes().getVariableTypeForClass(
|
||||
(Class<T>) this.getMetadata().getReturnParameter().getParameterType()
|
||||
);
|
||||
|
||||
return this
|
||||
.template
|
||||
.renderAsync(kernel, preRenderingHookResult.getArguments())
|
||||
.renderAsync(kernel, preRenderingHookResult.getArguments(), context)
|
||||
.flatMapMany(prompt -> {
|
||||
PromptRenderedEvent promptHookResult = kernelHooks
|
||||
.executeHooks(new PromptRenderedEvent(this, arguments, prompt));
|
||||
@@ -153,7 +149,8 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
args
|
||||
);
|
||||
|
||||
AIService client = aiServiceSelection != null ? aiServiceSelection.getService() : null;
|
||||
AIService client =
|
||||
aiServiceSelection != null ? aiServiceSelection.getService() : null;
|
||||
if (aiServiceSelection == null) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to initialise aiService, could not find any TextAIService implementations");
|
||||
@@ -199,7 +196,8 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
return Flux.error(new IllegalStateException(
|
||||
"Tool message content is empty"));
|
||||
}
|
||||
Mono<FunctionResult<T>> toolResult = invokeTool(kernel,content);
|
||||
Mono<FunctionResult<T>> toolResult = invokeTool(kernel, content,
|
||||
context);
|
||||
return toolResult.flux();
|
||||
}
|
||||
return Flux.empty();
|
||||
@@ -307,13 +305,16 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
* {"type":"function", "function": {"name":"search-search", "parameters": {"query":"Banksy"}}}
|
||||
* where 'name' is <plugin name '-' function name>.
|
||||
*/
|
||||
private Mono<FunctionResult<T>> invokeTool(Kernel kernel, String json) {
|
||||
private Mono<FunctionResult<T>> invokeTool(
|
||||
Kernel kernel,
|
||||
String json,
|
||||
InvocationContext invocationContext) {
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(json);
|
||||
jsonNode = jsonNode.get("function");
|
||||
if (jsonNode != null) {
|
||||
return invokeFunction(kernel, jsonNode);
|
||||
return invokeFunction(kernel, jsonNode, invocationContext);
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
LOGGER.error("Failed to parse json", e);
|
||||
@@ -327,7 +328,11 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
* The jsonNode should represent: {"name":"search-search", "parameters": {"query":"Banksy"}}}
|
||||
*/
|
||||
@SuppressWarnings({"StringSplitter", "unchecked"})
|
||||
private Mono<FunctionResult<T>> invokeFunction(Kernel kernel, JsonNode jsonNode) {
|
||||
private Mono<FunctionResult<T>> invokeFunction(
|
||||
Kernel kernel,
|
||||
JsonNode jsonNode,
|
||||
InvocationContext invocationContext
|
||||
) {
|
||||
String name = jsonNode.get("name").asText();
|
||||
String[] parts = name.split("-");
|
||||
String pluginName = parts.length > 0 ? parts[0] : "";
|
||||
@@ -338,13 +343,15 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
KernelFunction<T> kernelFunction = null;
|
||||
try {
|
||||
// unchecked cast
|
||||
kernelFunction = (KernelFunction<T>)kernel.getPlugins().getFunction(pluginName, fnName);
|
||||
kernelFunction = (KernelFunction<T>) kernel.getPlugins()
|
||||
.getFunction(pluginName, fnName);
|
||||
} catch (IllegalArgumentException | ClassCastException e) {
|
||||
return Mono.error(new SKException(e.getMessage(), e));
|
||||
}
|
||||
|
||||
List<KernelParameterMetadata<?>> params = kernelFunction.getMetadata().getParameters();
|
||||
Map<String, KernelParameterMetadata<?>> parameterMetaaData =
|
||||
List<KernelParameterMetadata<?>> params = kernelFunction.getMetadata()
|
||||
.getParameters();
|
||||
Map<String, KernelParameterMetadata<?>> parameterMetaaData =
|
||||
params.stream()
|
||||
.collect(Collectors.toMap(KernelParameterMetadata::getName, it -> it));
|
||||
|
||||
@@ -353,7 +360,8 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
String paramName = entry.getKey();
|
||||
String paramValue = entry.getValue().asText();
|
||||
|
||||
KernelParameterMetadata<?> parameterMetadata = parameterMetaaData.get(paramName);
|
||||
KernelParameterMetadata<?> parameterMetadata = parameterMetaaData.get(
|
||||
paramName);
|
||||
if (parameterMetadata == null) {
|
||||
// parameter in json not found in function metadata
|
||||
// TODO: this shouldn't happen, so log it.
|
||||
@@ -361,10 +369,15 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
}
|
||||
|
||||
Class<?> parameterType = parameterMetadata.getType();
|
||||
ContextVariable<?> contextVariable = ContextVariable.untypedOf(paramValue, parameterType);
|
||||
ContextVariable<?> contextVariable = ContextVariable.untypedOf(
|
||||
paramValue,
|
||||
parameterType,
|
||||
invocationContext.getContextVariableTypes()
|
||||
);
|
||||
variables.put(paramName, contextVariable);
|
||||
});
|
||||
KernelFunctionArguments arguments = KernelFunctionArguments.builder().withVariables(variables)
|
||||
KernelFunctionArguments arguments = KernelFunctionArguments.builder()
|
||||
.withVariables(variables)
|
||||
.build();
|
||||
return kernelFunction.invokeAsync(kernel, arguments);
|
||||
} catch (Exception e) {
|
||||
@@ -443,13 +456,14 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withName(@Nullable String name) {
|
||||
public FromPromptBuilder<T> withName(@Nullable String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withInputParameters(@Nullable List<InputVariable> inputVariables) {
|
||||
public FromPromptBuilder<T> withInputParameters(
|
||||
@Nullable List<InputVariable> inputVariables) {
|
||||
if (inputVariables != null) {
|
||||
this.inputVariables = new ArrayList<>(inputVariables);
|
||||
} else {
|
||||
@@ -459,13 +473,13 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withPromptTemplate(@Nullable PromptTemplate promptTemplate) {
|
||||
public FromPromptBuilder<T> withPromptTemplate(@Nullable PromptTemplate promptTemplate) {
|
||||
this.promptTemplate = promptTemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withExecutionSettings(
|
||||
public FromPromptBuilder<T> withExecutionSettings(
|
||||
@Nullable
|
||||
Map<String, PromptExecutionSettings> executionSettings) {
|
||||
if (this.executionSettings == null) {
|
||||
@@ -479,7 +493,7 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withDefaultExecutionSettings(
|
||||
public FromPromptBuilder<T> withDefaultExecutionSettings(
|
||||
@Nullable PromptExecutionSettings executionSettings) {
|
||||
if (executionSettings == null) {
|
||||
return this;
|
||||
@@ -499,37 +513,37 @@ public class KernelFunctionFromPrompt<T> extends KernelFunction<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withDescription(@Nullable String description) {
|
||||
public FromPromptBuilder<T> withDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withTemplate(@Nullable String template) {
|
||||
public FromPromptBuilder<T> withTemplate(@Nullable String template) {
|
||||
this.template = template;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withTemplateFormat(String templateFormat) {
|
||||
public FromPromptBuilder<T> withTemplateFormat(String templateFormat) {
|
||||
this.templateFormat = templateFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withOutputVariable(@Nullable OutputVariable outputVariable) {
|
||||
public FromPromptBuilder<T> withOutputVariable(@Nullable OutputVariable outputVariable) {
|
||||
this.outputVariable = outputVariable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withOutputVariable(@Nullable String description, String type) {
|
||||
public FromPromptBuilder<T> withOutputVariable(@Nullable String description, String type) {
|
||||
return this.withOutputVariable(new OutputVariable(description, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder<T> withPromptTemplateFactory(
|
||||
public FromPromptBuilder<T> withPromptTemplateFactory(
|
||||
@Nullable
|
||||
PromptTemplateFactory promptTemplateFactory) {
|
||||
this.promptTemplateFactory = promptTemplateFactory;
|
||||
|
||||
+5
-4
@@ -3,9 +3,8 @@ package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.orchestration.InvocationContext;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -21,7 +20,9 @@ public interface PromptTemplate extends Buildable {
|
||||
/// <param name="arguments">The arguments.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>Prompt rendered to string</returns>
|
||||
Mono<String> renderAsync(Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments);
|
||||
Mono<String> renderAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
@Nullable InvocationContext context);
|
||||
|
||||
}
|
||||
|
||||
+19
-20
@@ -1,6 +1,23 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.handlebars;
|
||||
|
||||
import com.github.jknack.handlebars.Context;
|
||||
import com.github.jknack.handlebars.Handlebars;
|
||||
import com.github.jknack.handlebars.Options;
|
||||
import com.github.jknack.handlebars.ValueResolver;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatMessageContent;
|
||||
import com.microsoft.semantickernel.orchestration.InvocationContext;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.KernelPlugin;
|
||||
import com.microsoft.semantickernel.plugin.KernelPluginCollection;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -11,27 +28,8 @@ import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.github.jknack.handlebars.Context;
|
||||
import com.github.jknack.handlebars.Handlebars;
|
||||
import com.github.jknack.handlebars.Options;
|
||||
import com.github.jknack.handlebars.ValueResolver;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatMessageContent;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.KernelPlugin;
|
||||
import com.microsoft.semantickernel.plugin.KernelPluginCollection;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
@@ -47,7 +45,8 @@ public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
@Override
|
||||
public Mono<String> renderAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments) {
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
@Nullable InvocationContext context) {
|
||||
HandleBarsPromptTemplateHandler handler =
|
||||
new HandleBarsPromptTemplateHandler(kernel, promptTemplate.getTemplate());
|
||||
|
||||
|
||||
+4
-2
@@ -3,6 +3,7 @@ package com.microsoft.semantickernel.templateengine.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.Verify;
|
||||
import com.microsoft.semantickernel.orchestration.InvocationContext;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.semanticfunctions.InputVariable;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
@@ -96,7 +97,8 @@ public class DefaultPromptTemplate implements PromptTemplate {
|
||||
@Override
|
||||
public Mono<String> renderAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments) {
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
@Nullable InvocationContext context) {
|
||||
|
||||
List<Block> blocks = this.extractBlocks();
|
||||
addMissingInputVariables(blocks);
|
||||
@@ -109,7 +111,7 @@ public class DefaultPromptTemplate implements PromptTemplate {
|
||||
((TextRendering) block).render(arguments)
|
||||
);
|
||||
} else if (block instanceof CodeRendering) {
|
||||
return ((CodeRendering) block).renderCodeAsync(kernel, arguments);
|
||||
return ((CodeRendering) block).renderCodeAsync(kernel, arguments, context);
|
||||
} else {
|
||||
return Mono.error(new TemplateException(ErrorCodes.UNEXPECTED_BLOCK_TYPE));
|
||||
}
|
||||
|
||||
+33
-16
@@ -1,18 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.semantickernel.blocks;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.InvocationContext;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
@@ -20,6 +12,12 @@ import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariab
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException;
|
||||
import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException.ErrorCodes;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public final class CodeBlock extends Block implements CodeRendering {
|
||||
@@ -79,11 +77,18 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> renderCodeAsync(Kernel kernel, @Nullable KernelFunctionArguments arguments) {
|
||||
public Mono<String> renderCodeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
@Nullable InvocationContext context) {
|
||||
if (!this.isValid()) {
|
||||
throw new TemplateException(ErrorCodes.SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
context = new InvocationContext();
|
||||
}
|
||||
|
||||
// this.Log.LogTrace("Rendering code: `{0}`", this.Content);
|
||||
|
||||
switch (this.tokens.get(0).getType()) {
|
||||
@@ -98,7 +103,8 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
(FunctionIdBlock) this.tokens.get(0),
|
||||
kernel,
|
||||
arguments,
|
||||
ContextVariableTypes.getDefaultVariableTypeForClass(String.class))
|
||||
context,
|
||||
ContextVariableTypes.getGlobalVariableTypeForClass(String.class))
|
||||
.map(it -> {
|
||||
return it.getValue();
|
||||
});
|
||||
@@ -115,6 +121,7 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
FunctionIdBlock fBlock,
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
InvocationContext context,
|
||||
ContextVariableType<T> resultType) {
|
||||
|
||||
// If the code syntax is {{functionName $varName}} use $varName instead of $input
|
||||
@@ -122,9 +129,10 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
if (this.tokens.size() > 1) {
|
||||
//Cloning the original arguments to avoid side effects - arguments added to the original arguments collection as a result of rendering template variables.
|
||||
arguments = this.enrichFunctionArguments(kernel, fBlock,
|
||||
arguments == null
|
||||
arguments == null
|
||||
? new KernelFunctionArguments()
|
||||
: new KernelFunctionArguments(arguments));
|
||||
: new KernelFunctionArguments(arguments),
|
||||
context);
|
||||
}
|
||||
|
||||
return kernel
|
||||
@@ -150,7 +158,9 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
private KernelFunctionArguments enrichFunctionArguments(
|
||||
Kernel kernel,
|
||||
FunctionIdBlock fBlock,
|
||||
KernelFunctionArguments arguments) {
|
||||
KernelFunctionArguments arguments,
|
||||
@Nullable
|
||||
InvocationContext context) {
|
||||
Block firstArg = this.tokens.get(1);
|
||||
|
||||
// Get the function metadata
|
||||
@@ -182,8 +192,15 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
}
|
||||
|
||||
// Keep previous trust information when updating the input
|
||||
arguments.put(firstPositionalParameterName,
|
||||
ContextVariable.of(firstPositionalInputValue));
|
||||
arguments.put(
|
||||
firstPositionalParameterName,
|
||||
ContextVariable
|
||||
.convert(
|
||||
firstPositionalInputValue,
|
||||
functionMetadata.getParameters().get(0).getType(),
|
||||
context == null ? null : context.getContextVariableTypes()
|
||||
)
|
||||
);
|
||||
namedArgsStartIndex++;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -2,8 +2,8 @@
|
||||
package com.microsoft.semantickernel.templateengine.semantickernel.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.orchestration.InvocationContext;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionArguments;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -19,5 +19,8 @@ public interface CodeRendering {
|
||||
* @param arguments Optional arguments used to render the block
|
||||
* @return Rendered content
|
||||
*/
|
||||
Mono<String> renderCodeAsync(Kernel kernel, @Nullable KernelFunctionArguments arguments);
|
||||
Mono<String> renderCodeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelFunctionArguments arguments,
|
||||
@Nullable InvocationContext context);
|
||||
}
|
||||
|
||||
+7
-7
@@ -18,7 +18,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
*/
|
||||
@Test
|
||||
void testConvertIntegerToString() {
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
Object expResult = "1";
|
||||
Object result = instance.toObject(1, String.class);
|
||||
@@ -31,7 +31,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testFromStringToInteger() {
|
||||
Object s = "123";
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
Number expResult = Integer.valueOf((String)s);
|
||||
Number result = instance.fromObject(s);
|
||||
@@ -41,7 +41,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testFromPromptStringToInteger() {
|
||||
String s = "123";
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
Number expResult = Integer.valueOf(s);
|
||||
Number result = instance.fromPromptString(s);
|
||||
@@ -51,7 +51,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testFromPromptStringReturnsNullForEmptyString() {
|
||||
String s = "";
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
Number expResult = null;
|
||||
Number result = instance.fromPromptString(s);
|
||||
@@ -61,7 +61,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testFromPromptStringReturnsNullForNullString() {
|
||||
String s = null;
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
Number expResult = null;
|
||||
Number result = instance.fromPromptString(s);
|
||||
@@ -71,7 +71,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testToPromptString() {
|
||||
Integer num = 123;
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
String expResult = "123";
|
||||
String result = instance.toPromptString(num);
|
||||
@@ -81,7 +81,7 @@ public class NumberVariableContextVariableTypeConverterTest {
|
||||
@Test
|
||||
void testToPromptStringReturnsEmptyStringForNull() {
|
||||
Integer num = null;
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getDefaultVariableTypeForClass(Integer.class);
|
||||
ContextVariableType<Integer> type = ContextVariableTypes.getGlobalVariableTypeForClass(Integer.class);
|
||||
ContextVariableTypeConverter<Integer> instance = type.getConverter();
|
||||
String expResult = "";
|
||||
String result = instance.toPromptString(num);
|
||||
|
||||
Reference in New Issue
Block a user