diff --git a/CHANGELOG.md b/CHANGELOG.md index 0630f2071..d0a3d203e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.4.4-RC1 + +- Add Agent framework abstractions. +- Add ChatCompletionAgent implementation. +- Add FunctionChoiceBehavior for OpenAI, replacing the older ToolCallBehavior. + # 1.4.3 - Bug fix for execution on Android (https://github.com/microsoft/semantic-kernel-java/pull/284) diff --git a/agents/semantickernel-agents-core/pom.xml b/agents/semantickernel-agents-core/pom.xml new file mode 100644 index 000000000..162868ee6 --- /dev/null +++ b/agents/semantickernel-agents-core/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 1.4.4-RC1 + ../../pom.xml + + + semantickernel-agents-core + + Semantic Kernel Chat Completion Agent + Chat Completion Agent for Semantic Kernel + + + + com.microsoft.semantic-kernel + semantickernel-api + + + + \ No newline at end of file diff --git a/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatCompletionAgent.java b/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatCompletionAgent.java new file mode 100644 index 000000000..b5294fe6b --- /dev/null +++ b/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatCompletionAgent.java @@ -0,0 +1,329 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents.chatcompletion; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.agents.AgentInvokeOptions; +import com.microsoft.semantickernel.agents.AgentResponseItem; +import com.microsoft.semantickernel.agents.AgentThread; +import com.microsoft.semantickernel.agents.KernelAgent; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.functionchoice.AutoFunctionChoiceBehavior; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.InvocationReturnMode; +import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateFactory; +import com.microsoft.semantickernel.services.ServiceNotFoundException; +import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; +import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.stream.Collectors; + +public class ChatCompletionAgent extends KernelAgent { + + private ChatCompletionAgent( + String id, + String name, + String description, + Kernel kernel, + KernelArguments kernelArguments, + InvocationContext context, + String instructions, + PromptTemplate template) { + super( + id, + name, + description, + kernel, + kernelArguments, + context, + instructions, + template); + } + + /** + * Invoke the agent with the given chat history. + * + * @param messages The chat history to process + * @param thread The agent thread to use + * @param options The options for invoking the agent + * @return A Mono containing the agent response + */ + @Override + public Mono>>> invokeAsync( + List> messages, + @Nullable AgentThread thread, + @Nullable AgentInvokeOptions options) { + return ensureThreadExistsWithMessagesAsync(messages, thread, ChatHistoryAgentThread::new) + .cast(ChatHistoryAgentThread.class) + .flatMap(agentThread -> { + // Extract the chat history from the thread + ChatHistory history = new ChatHistory( + agentThread.getChatHistory().getMessages()); + + // Invoke the agent with the chat history + return internalInvokeAsync( + history, + agentThread, + options) + .map(chatMessageContents -> chatMessageContents.stream() + .map(message -> new AgentResponseItem>(message, + agentThread)) + .collect(Collectors.toList())); + }); + } + + private Mono>> internalInvokeAsync( + ChatHistory history, + AgentThread thread, + @Nullable AgentInvokeOptions options) { + if (options == null) { + options = new AgentInvokeOptions(); + } + + final Kernel kernel = options.getKernel() != null ? options.getKernel() : this.kernel; + final KernelArguments arguments = mergeArguments(options.getKernelArguments()); + final String additionalInstructions = options.getAdditionalInstructions(); + final InvocationContext invocationContext = options.getInvocationContext() != null + ? options.getInvocationContext() + : this.invocationContext; + + try { + ChatCompletionService chatCompletionService = kernel + .getService(ChatCompletionService.class, arguments); + + PromptExecutionSettings executionSettings = invocationContext != null + && invocationContext.getPromptExecutionSettings() != null + ? invocationContext.getPromptExecutionSettings() + : arguments.getExecutionSettings() + .get(chatCompletionService.getServiceId()); + + // Build base invocation context + InvocationContext.Builder builder = InvocationContext.builder() + .withPromptExecutionSettings(executionSettings) + .withReturnMode(InvocationReturnMode.NEW_MESSAGES_ONLY); + + if (invocationContext != null) { + builder = builder + .withTelemetry(invocationContext.getTelemetry()) + .withFunctionChoiceBehavior(invocationContext.getFunctionChoiceBehavior()) + .withToolCallBehavior(invocationContext.getToolCallBehavior()) + .withContextVariableConverter(invocationContext.getContextVariableTypes()) + .withKernelHooks(invocationContext.getKernelHooks()); + } + + InvocationContext agentInvocationContext = builder.build(); + + return renderInstructionsAsync(kernel, arguments, agentInvocationContext).flatMap( + instructions -> { + // Create a new chat history with the instructions + ChatHistory chat = new ChatHistory( + instructions); + + // Add agent additional instructions + if (additionalInstructions != null) { + chat.addMessage(new ChatMessageContent<>( + AuthorRole.SYSTEM, + additionalInstructions)); + } + + // Add the chat history to the new chat + chat.addAll(history); + + // Retrieve the chat message contents asynchronously and notify the thread + if (shouldNotifyFunctionCalls(agentInvocationContext)) { + // Notify all messages including function calls + return chatCompletionService + .getChatMessageContentsAsync(chat, kernel, agentInvocationContext) + .flatMapMany(Flux::fromIterable) + .concatMap(message -> notifyThreadOfNewMessageAsync(thread, message) + .thenReturn(message)) + // Filter out function calls and their results + .filter(message -> message.getContent() != null + && message.getAuthorRole() != AuthorRole.TOOL) + .collect(Collectors.toList()); + } + + // Return chat completion messages without notifying the thread + // We shouldn't add the function call content to the thread, since + // we don't know if the user will execute the call. They should add it themselves. + return chatCompletionService.getChatMessageContentsAsync(chat, kernel, + agentInvocationContext); + }); + + } catch (ServiceNotFoundException e) { + return Mono.error(e); + } + } + + boolean shouldNotifyFunctionCalls(InvocationContext invocationContext) { + if (invocationContext == null) { + return false; + } + + if (invocationContext.getFunctionChoiceBehavior() != null && invocationContext + .getFunctionChoiceBehavior() instanceof AutoFunctionChoiceBehavior) { + return ((AutoFunctionChoiceBehavior) invocationContext.getFunctionChoiceBehavior()) + .isAutoInvoke(); + } + + if (invocationContext.getToolCallBehavior() != null) { + return invocationContext.getToolCallBehavior().isAutoInvokeAllowed(); + } + + return false; + } + + @Override + public Mono notifyThreadOfNewMessageAsync(AgentThread thread, + ChatMessageContent message) { + return Mono.defer(() -> { + return thread.onNewMessageAsync(message); + }); + } + + /** + * Builder for creating instances of ChatCompletionAgent. + */ + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements SemanticKernelBuilder { + private String id; + private String name; + private String description; + private Kernel kernel; + private KernelArguments kernelArguments; + private InvocationContext invocationContext; + private String instructions; + private PromptTemplate template; + + /** + * Set the ID of the agent. + * + * @param id The ID of the agent. + */ + public Builder withId(String id) { + this.id = id; + return this; + } + + /** + * Set the name of the agent. + * + * @param name The name of the agent. + */ + public Builder withName(String name) { + this.name = name; + return this; + } + + /** + * Set the description of the agent. + * + * @param description The description of the agent. + */ + public Builder withDescription(String description) { + this.description = description; + return this; + } + + /** + * Set the kernel to use for the agent. + * + * @param kernel The kernel to use. + */ + public Builder withKernel(Kernel kernel) { + this.kernel = kernel; + return this; + } + + /** + * Set the kernel arguments to use for the agent. + * + * @param KernelArguments The kernel arguments to use. + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") + public Builder withKernelArguments(KernelArguments KernelArguments) { + this.kernelArguments = KernelArguments; + return this; + } + + /** + * Set the instructions for the agent. + * + * @param instructions The instructions for the agent. + */ + public Builder withInstructions(String instructions) { + this.instructions = instructions; + return this; + } + + /** + * Set the invocation context for the agent. + * + * @param invocationContext The invocation context to use. + */ + public Builder withInvocationContext(InvocationContext invocationContext) { + this.invocationContext = invocationContext; + return this; + } + + /** + * Set the template for the agent. + * + * @param template The template to use. + */ + public Builder withTemplate(PromptTemplate template) { + this.template = template; + return this; + } + + /** + * Build the ChatCompletionAgent instance. + * + * @return The ChatCompletionAgent instance. + */ + public ChatCompletionAgent build() { + return new ChatCompletionAgent( + id, + name, + description, + kernel, + kernelArguments, + invocationContext, + instructions, + template); + } + + /** + * Build the ChatCompletionAgent instance with the given prompt template config and factory. + * + * @param promptTemplateConfig The prompt template config to use. + * @param promptTemplateFactory The prompt template factory to use. + * @return The ChatCompletionAgent instance. + */ + public ChatCompletionAgent build(PromptTemplateConfig promptTemplateConfig, + PromptTemplateFactory promptTemplateFactory) { + return new ChatCompletionAgent( + id, + name, + description, + kernel, + kernelArguments, + invocationContext, + promptTemplateConfig.getTemplate(), + promptTemplateFactory.tryCreate(promptTemplateConfig)); + } + } +} diff --git a/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatHistoryAgentThread.java b/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatHistoryAgentThread.java new file mode 100644 index 000000000..6b3f62a9b --- /dev/null +++ b/agents/semantickernel-agents-core/src/main/java/com/microsoft/semantickernel/agents/chatcompletion/ChatHistoryAgentThread.java @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents.chatcompletion; + +import com.microsoft.semantickernel.agents.AgentThread; +import com.microsoft.semantickernel.agents.BaseAgentThread; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import reactor.core.publisher.Mono; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.UUID; + +public class ChatHistoryAgentThread extends BaseAgentThread { + private ChatHistory chatHistory; + + /** + * Constructor for ChatHistoryAgentThread. + * + */ + public ChatHistoryAgentThread() { + this(UUID.randomUUID().toString(), new ChatHistory()); + } + + /** + * Constructor for ChatHistoryAgentThread. + * + * @param chatHistory The chat history. + */ + public ChatHistoryAgentThread(@Nullable ChatHistory chatHistory) { + this(UUID.randomUUID().toString(), chatHistory); + } + + /** + * Constructor for ChatHistoryAgentThread. + * + * @param id The ID of the thread. + * @param chatHistory The chat history. + */ + public ChatHistoryAgentThread(String id, @Nullable ChatHistory chatHistory) { + super(id); + this.chatHistory = chatHistory != null ? chatHistory : new ChatHistory(); + } + + /** + * Get the chat history. + * + * @return The chat history. + */ + @SuppressFBWarnings("EI_EXPOSE_REP") + public ChatHistory getChatHistory() { + return chatHistory; + } + + @Override + public Mono createAsync() { + if (this.id == null) { + this.id = UUID.randomUUID().toString(); + chatHistory = new ChatHistory(); + } + return Mono.just(id); + } + + @Override + public Mono deleteAsync() { + return Mono.fromRunnable(chatHistory::clear); + } + + /** + * Create a copy of the thread. + * + * @return A new instance of the thread. + */ + @Override + public ChatHistoryAgentThread copy() { + return new ChatHistoryAgentThread(this.id, new ChatHistory(chatHistory.getMessages())); + } + + @Override + public Mono onNewMessageAsync(ChatMessageContent newMessage) { + return Mono.fromRunnable(() -> { + chatHistory.addMessage(newMessage); + }); + } + + public List> getMessages() { + return chatHistory.getMessages(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements SemanticKernelBuilder { + private String id; + private ChatHistory chatHistory; + + /** + * Set the ID of the thread. + * + * @param id The ID of the thread. + * @return The builder instance. + */ + public Builder withId(String id) { + this.id = id; + return this; + } + + /** + * Set the chat history. + * + * @param chatHistory The chat history. + * @return The builder instance. + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") + public Builder withChatHistory(ChatHistory chatHistory) { + this.chatHistory = chatHistory; + return this; + } + + @Override + public ChatHistoryAgentThread build() { + return new ChatHistoryAgentThread(id, chatHistory); + } + } +} diff --git a/aiservices/google/pom.xml b/aiservices/google/pom.xml index 8c6ac73d7..22b492d79 100644 --- a/aiservices/google/pom.xml +++ b/aiservices/google/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java index e226b4c66..2bd45c022 100644 --- a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java +++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java @@ -32,7 +32,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.semanticfunctions.InputVariable; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; @@ -436,7 +436,7 @@ public Mono performFunctionCall(@Nullable Kernel kernel, ? new ContextVariableTypes() : invocationContext.getContextVariableTypes(); - KernelFunctionArguments.Builder arguments = KernelFunctionArguments.builder(); + KernelArguments.Builder arguments = KernelArguments.builder(); geminiFunction.getFunctionCall().getArgs().getFieldsMap().forEach((key, value) -> { arguments.withVariable(key, value.getStringValue()); }); diff --git a/aiservices/huggingface/pom.xml b/aiservices/huggingface/pom.xml index 8ca1d183f..6ae919477 100644 --- a/aiservices/huggingface/pom.xml +++ b/aiservices/huggingface/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/aiservices/openai/pom.xml b/aiservices/openai/pom.xml index 34c1477d2..e826dcc11 100644 --- a/aiservices/openai/pom.xml +++ b/aiservices/openai/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java index b842e43d0..1db5bd388 100644 --- a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java +++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java @@ -44,6 +44,10 @@ import com.microsoft.semantickernel.exceptions.AIException.ErrorCodes; import com.microsoft.semantickernel.exceptions.SKCheckedException; import com.microsoft.semantickernel.exceptions.SKException; +import com.microsoft.semantickernel.functionchoice.AutoFunctionChoiceBehavior; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior; +import com.microsoft.semantickernel.functionchoice.NoneFunctionChoiceBehavior; +import com.microsoft.semantickernel.functionchoice.RequiredFunctionChoiceBehavior; import com.microsoft.semantickernel.hooks.KernelHookEvent; import com.microsoft.semantickernel.hooks.KernelHooks; import com.microsoft.semantickernel.hooks.PostChatCompletionEvent; @@ -61,7 +65,7 @@ import com.microsoft.semantickernel.orchestration.responseformat.JsonResponseSchema; import com.microsoft.semantickernel.orchestration.responseformat.JsonSchemaResponseFormat; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; @@ -196,10 +200,20 @@ public Flux> getStreamingChatMessageContentsAsync( ChatHistory chatHistory, @Nullable Kernel kernel, @Nullable InvocationContext invocationContext) { - if (invocationContext != null && invocationContext.getToolCallBehavior() - .isAutoInvokeAllowed()) { + if (invocationContext != null && + invocationContext.getToolCallBehavior() != null && + invocationContext.getToolCallBehavior().isAutoInvokeAllowed()) { throw new SKException( - "Auto invoke is not supported for streaming chat message contents"); + "ToolCallBehavior auto-invoke is not supported for streaming chat message contents"); + } + + if (invocationContext != null && + invocationContext.getFunctionChoiceBehavior() != null && + invocationContext.getFunctionChoiceBehavior() instanceof AutoFunctionChoiceBehavior && + ((AutoFunctionChoiceBehavior) invocationContext.getFunctionChoiceBehavior()) + .isAutoInvoke()) { + throw new SKException( + "FunctionChoiceBehavior auto-invoke is not supported for streaming chat message contents"); } if (invocationContext != null @@ -219,6 +233,12 @@ public Flux> getStreamingChatMessageContentsAsync( .add(OpenAIFunction.build(function.getMetadata(), plugin.getName())))); } + OpenAIToolCallConfig toolCallConfig = getToolCallConfig( + invocationContext, + functions, + messages.allMessages, + 0); + ChatCompletionsOptions options = executeHook( invocationContext, kernel, @@ -226,8 +246,8 @@ public Flux> getStreamingChatMessageContentsAsync( getCompletionsOptions( this, messages.allMessages, - functions, - invocationContext))) + invocationContext, + toolCallConfig))) .getOptions(); return getClient() @@ -389,16 +409,12 @@ private Mono internalChatMessageContentsAsync( .add(OpenAIFunction.build(function.getMetadata(), plugin.getName())))); } - // Create copy to avoid reactor exceptions when updating request messages internally return internalChatMessageContentsAsync( messages, kernel, functions, invocationContext, - Math.min(MAXIMUM_INFLIGHT_AUTO_INVOKES, - invocationContext != null && invocationContext.getToolCallBehavior() != null - ? invocationContext.getToolCallBehavior().getMaximumAutoInvokeAttempts() - : 0)); + 0); } private Mono internalChatMessageContentsAsync( @@ -406,7 +422,13 @@ private Mono internalChatMessageContentsAsync( @Nullable Kernel kernel, List functions, @Nullable InvocationContext invocationContext, - int autoInvokeAttempts) { + int requestIndex) { + + OpenAIToolCallConfig toolCallConfig = getToolCallConfig( + invocationContext, + functions, + messages.allMessages, + requestIndex); ChatCompletionsOptions options = executeHook( invocationContext, @@ -415,8 +437,8 @@ private Mono internalChatMessageContentsAsync( getCompletionsOptions( this, messages.allMessages, - functions, - invocationContext))) + invocationContext, + toolCallConfig))) .getOptions(); return Mono.deferContextual(contextView -> { @@ -458,9 +480,10 @@ private Mono internalChatMessageContentsAsync( executeHook(invocationContext, kernel, new PostChatCompletionEvent(completions)); // Just return the result: - // If we don't want to attempt to invoke any functions + // If auto-invoking is not enabled // Or if we are auto-invoking, but we somehow end up with other than 1 choice even though only 1 was requested - if (autoInvokeAttempts == 0 || responseMessages.size() != 1) { + if (toolCallConfig == null || !toolCallConfig.isAutoInvoke() + || responseMessages.size() != 1) { List> chatMessageContents = getChatMessageContentsAsync( completions); return Mono.just(messages.addChatMessage(chatMessageContents)); @@ -497,14 +520,14 @@ private Mono internalChatMessageContentsAsync( .flatMap(it -> it) .flatMap(msgs -> { return internalChatMessageContentsAsync(msgs, kernel, functions, - invocationContext, autoInvokeAttempts - 1); + invocationContext, requestIndex + 1); }) .onErrorResume(e -> { LOGGER.warn("Tool invocation attempt failed: ", e); // If FunctionInvocationError occurred and there are still attempts left, retry, else exit - if (autoInvokeAttempts > 0) { + if (requestIndex < MAXIMUM_INFLIGHT_AUTO_INVOKES) { ChatMessages currentMessages = messages; if (e instanceof FunctionInvocationError) { currentMessages.assertCommonHistory( @@ -518,7 +541,7 @@ private Mono internalChatMessageContentsAsync( kernel, functions, invocationContext, - autoInvokeAttempts - 1); + requestIndex + 1); } else { return Mono.error(e); } @@ -629,7 +652,7 @@ private Mono> invokeFunctionTool( contextVariableTypes)); function = hookResult.getFunction(); - KernelFunctionArguments arguments = hookResult.getArguments(); + KernelArguments arguments = hookResult.getArguments(); return function .invokeAsync(kernel) @@ -673,7 +696,7 @@ private OpenAIFunctionToolCall extractOpenAIFunctionToolCall( String pluginName = parts.length > 1 ? parts[0] : ""; String fnName = parts.length > 1 ? parts[1] : parts[0]; - KernelFunctionArguments arguments = KernelFunctionArguments.builder().build(); + KernelArguments arguments = KernelArguments.builder().build(); ObjectMapper mapper = new ObjectMapper(); JsonNode jsonToolCallArguments = mapper.readTree(toolCall.getFunction().getArguments()); @@ -860,8 +883,8 @@ private List formOpenAiToolCalls( private static ChatCompletionsOptions getCompletionsOptions( ChatCompletionService chatCompletionService, List chatRequestMessages, - @Nullable List functions, - @Nullable InvocationContext invocationContext) { + @Nullable InvocationContext invocationContext, + @Nullable OpenAIToolCallConfig toolCallConfig) { chatRequestMessages = chatRequestMessages .stream() @@ -871,12 +894,13 @@ private static ChatCompletionsOptions getCompletionsOptions( ChatCompletionsOptions options = new ChatCompletionsOptions(chatRequestMessages) .setModel(chatCompletionService.getModelId()); - if (invocationContext != null && invocationContext.getToolCallBehavior() != null) { - configureToolCallBehaviorOptions( - options, - invocationContext.getToolCallBehavior(), - functions, - chatRequestMessages); + if (toolCallConfig != null) { + options.setTools(toolCallConfig.getTools()); + options.setToolChoice(toolCallConfig.getToolChoice()); + + if (toolCallConfig.getOptions() != null) { + options.setParallelToolCalls(toolCallConfig.getOptions().isParallelCallsAllowed()); + } } PromptExecutionSettings promptExecutionSettings = invocationContext != null @@ -946,92 +970,184 @@ private static ChatCompletionsOptions getCompletionsOptions( return options; } - private static void configureToolCallBehaviorOptions( - ChatCompletionsOptions options, + @Nullable + private static OpenAIToolCallConfig getToolCallConfig( + @Nullable InvocationContext invocationContext, + @Nullable List functions, + List chatRequestMessages, + int requestIndex) { + + if (invocationContext == null || functions == null || functions.isEmpty()) { + return null; + } + + if (invocationContext.getFunctionChoiceBehavior() == null + && invocationContext.getToolCallBehavior() == null) { + return null; + } + + if (invocationContext.getFunctionChoiceBehavior() != null) { + return getFunctionChoiceBehaviorConfig( + invocationContext.getFunctionChoiceBehavior(), + functions, + requestIndex); + } else { + return getToolCallBehaviorConfig( + invocationContext.getToolCallBehavior(), + functions, + chatRequestMessages, + requestIndex); + } + } + + @Nullable + private static OpenAIToolCallConfig getFunctionChoiceBehaviorConfig( + @Nullable FunctionChoiceBehavior functionChoiceBehavior, + @Nullable List functions, + int requestIndex) { + if (functionChoiceBehavior == null) { + return null; + } + + if (functions == null || functions.isEmpty()) { + return null; + } + + ChatCompletionsToolSelection toolChoice; + boolean autoInvoke; + + if (functionChoiceBehavior instanceof RequiredFunctionChoiceBehavior) { + // After first request a required function must have been called already + if (requestIndex >= 1) { + return null; + } + + toolChoice = new ChatCompletionsToolSelection( + ChatCompletionsToolSelectionPreset.REQUIRED); + autoInvoke = ((RequiredFunctionChoiceBehavior) functionChoiceBehavior).isAutoInvoke(); + } else if (functionChoiceBehavior instanceof AutoFunctionChoiceBehavior) { + toolChoice = new ChatCompletionsToolSelection(ChatCompletionsToolSelectionPreset.AUTO); + autoInvoke = ((AutoFunctionChoiceBehavior) functionChoiceBehavior).isAutoInvoke() + && requestIndex < MAXIMUM_INFLIGHT_AUTO_INVOKES; + } else if (functionChoiceBehavior instanceof NoneFunctionChoiceBehavior) { + toolChoice = new ChatCompletionsToolSelection(ChatCompletionsToolSelectionPreset.NONE); + autoInvoke = false; + } else { + throw new SKException( + "Unsupported function choice behavior: " + functionChoiceBehavior); + } + + // List of functions advertised to the model + List toolDefinitions = functions.stream() + .filter(function -> functionChoiceBehavior.isFunctionAllowed(function.getPluginName(), + function.getName())) + .map(OpenAIFunction::getFunctionDefinition) + .map(it -> new ChatCompletionsFunctionToolDefinitionFunction(it.getName()) + .setDescription(it.getDescription()) + .setParameters(it.getParameters())) + .map(ChatCompletionsFunctionToolDefinition::new) + .collect(Collectors.toList()); + + return new OpenAIToolCallConfig( + toolDefinitions, + toolChoice, + autoInvoke, + functionChoiceBehavior.getOptions()); + } + + @Nullable + private static OpenAIToolCallConfig getToolCallBehaviorConfig( @Nullable ToolCallBehavior toolCallBehavior, @Nullable List functions, - List chatRequestMessages) { + List chatRequestMessages, + int requestIndex) { if (toolCallBehavior == null) { - return; + return null; } if (functions == null || functions.isEmpty()) { - return; + return null; } + List toolDefinitions; + ChatCompletionsToolSelection toolChoice; + // If a specific function is required to be called if (toolCallBehavior instanceof ToolCallBehavior.RequiredKernelFunction) { - KernelFunction toolChoice = ((ToolCallBehavior.RequiredKernelFunction) toolCallBehavior) + KernelFunction requiredFunction = ((ToolCallBehavior.RequiredKernelFunction) toolCallBehavior) .getRequiredFunction(); String toolChoiceName = String.format("%s%s%s", - toolChoice.getPluginName(), + requiredFunction.getPluginName(), OpenAIFunction.getNameSeparator(), - toolChoice.getName()); + requiredFunction.getName()); // If required tool call has already been called dont ask for it again boolean hasBeenExecuted = hasToolCallBeenExecuted(chatRequestMessages, toolChoiceName); if (hasBeenExecuted) { - return; + return null; } - List toolDefinitions = new ArrayList<>(); - FunctionDefinition function = OpenAIFunction.toFunctionDefinition( - toolChoice.getMetadata(), - toolChoice.getPluginName()); + requiredFunction.getMetadata(), + requiredFunction.getPluginName()); + toolDefinitions = new ArrayList<>(); toolDefinitions.add(new ChatCompletionsFunctionToolDefinition( new ChatCompletionsFunctionToolDefinitionFunction(function.getName()) .setDescription(function.getDescription()) .setParameters(function.getParameters()))); - options.setTools(toolDefinitions); try { String json = String.format( "{\"type\":\"function\",\"function\":{\"name\":\"%s\"}}", toolChoiceName); - options.setToolChoice( - new ChatCompletionsToolSelection( - ChatCompletionsNamedToolSelection.fromJson( - DefaultJsonReader.fromString( - json, - new JsonOptions())))); + toolChoice = new ChatCompletionsToolSelection( + ChatCompletionsNamedToolSelection.fromJson( + DefaultJsonReader.fromString( + json, + new JsonOptions()))); } catch (JsonProcessingException e) { throw SKException.build("Failed to parse tool choice", e); } catch (IOException e) { throw new SKException(e); } - return; } - // If a set of functions are enabled to be called - ToolCallBehavior.AllowedKernelFunctions enabledKernelFunctions = (ToolCallBehavior.AllowedKernelFunctions) toolCallBehavior; - List toolDefinitions = functions.stream() - .filter(function -> { - // check if all kernel functions are enabled - if (enabledKernelFunctions.isAllKernelFunctionsAllowed()) { - return true; - } - // otherwise, check for the specific function - return enabledKernelFunctions.isFunctionAllowed(function.getPluginName(), - function.getName()); - }) - .map(OpenAIFunction::getFunctionDefinition) - .map(it -> new ChatCompletionsFunctionToolDefinitionFunction(it.getName()) - .setDescription(it.getDescription()) - .setParameters(it.getParameters())) - .map(it -> new ChatCompletionsFunctionToolDefinition(it)) - .collect(Collectors.toList()); + else { + toolChoice = new ChatCompletionsToolSelection(ChatCompletionsToolSelectionPreset.AUTO); + + ToolCallBehavior.AllowedKernelFunctions enabledKernelFunctions = (ToolCallBehavior.AllowedKernelFunctions) toolCallBehavior; + toolDefinitions = functions.stream() + .filter(function -> { + // check if all kernel functions are enabled + if (enabledKernelFunctions.isAllKernelFunctionsAllowed()) { + return true; + } + // otherwise, check for the specific function + return enabledKernelFunctions.isFunctionAllowed(function.getPluginName(), + function.getName()); + }) + .map(OpenAIFunction::getFunctionDefinition) + .map(it -> new ChatCompletionsFunctionToolDefinitionFunction(it.getName()) + .setDescription(it.getDescription()) + .setParameters(it.getParameters())) + .map(ChatCompletionsFunctionToolDefinition::new) + .collect(Collectors.toList()); - if (toolDefinitions.isEmpty()) { - return; + if (toolDefinitions.isEmpty()) { + return null; + } } - options.setTools(toolDefinitions); - options.setToolChoice( - new ChatCompletionsToolSelection(ChatCompletionsToolSelectionPreset.AUTO)); + return new OpenAIToolCallConfig( + toolDefinitions, + toolChoice, + toolCallBehavior.isAutoInvokeAllowed() + && requestIndex < Math.min(MAXIMUM_INFLIGHT_AUTO_INVOKES, + toolCallBehavior.getMaximumAutoInvokeAttempts()), + null); } private static boolean hasToolCallBeenExecuted(List chatRequestMessages, @@ -1144,7 +1260,7 @@ private static ChatRequestAssistantMessage formAssistantMessage( asstMessage.setToolCalls( toolCalls.stream() .map(toolCall -> { - KernelFunctionArguments arguments = toolCall.getArguments(); + KernelArguments arguments = toolCall.getArguments(); String args = arguments != null && !arguments.isEmpty() ? arguments.entrySet().stream() diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java index ad6dbadbb..cf126d095 100644 --- a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java +++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java @@ -7,14 +7,19 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.exceptions.SKException; +import com.microsoft.semantickernel.orchestration.responseformat.ResponseSchemaGenerator; import com.microsoft.semantickernel.semanticfunctions.InputVariable; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionMetadata; +import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -159,14 +164,17 @@ private static String getSchemaForFunctionParameter(@Nullable InputVariable para entries.add("\"type\":\"" + type + "\""); // Add description if present + String description = null; if (parameter != null && parameter.getDescription() != null && !parameter.getDescription() .isEmpty()) { - String description = parameter.getDescription(); + description = parameter.getDescription(); description = description.replaceAll("\\r?\\n|\\r", ""); description = description.replace("\"", "\\\""); - - description = String.format("\"description\":\"%s\"", description); - entries.add(description); + entries.add(String.format("\"description\":\"%s\"", description)); + } + // If custom type, generate schema + if ("object".equalsIgnoreCase(type)) { + return getObjectSchema(parameter.getType(), description); } // Add enum options if parameter is an enum @@ -219,4 +227,20 @@ private static String getJavaTypeToOpenAiFunctionType(String javaType) { return "object"; } } + + private static String getObjectSchema(String type, String description) { + String schema = "{ \"type\" : \"object\" }"; + try { + Class clazz = Class.forName(type); + schema = ResponseSchemaGenerator.jacksonGenerator().generateSchema(clazz); + + } catch (ClassNotFoundException | SKException ignored) { + + } + Map properties = BinaryData.fromString(schema).toObject(Map.class); + if (StringUtils.isNotBlank(description)) { + properties.put("description", description); + } + return BinaryData.fromObject(properties).toString(); + } } diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java index 18111330d..b7999cf00 100644 --- a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java +++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. package com.microsoft.semantickernel.aiservices.openai.chatcompletion; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; /** @@ -23,7 +23,7 @@ public class OpenAIFunctionToolCall { /// Gets a name/value collection of the arguments to the function, if any. @Nullable - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; /** * Creates a new instance of the {@link OpenAIFunctionToolCall} class. @@ -37,7 +37,7 @@ public OpenAIFunctionToolCall( @Nullable String id, @Nullable String pluginName, String functionName, - @Nullable KernelFunctionArguments arguments) { + @Nullable KernelArguments arguments) { this.id = id; this.pluginName = pluginName; this.functionName = functionName; @@ -83,7 +83,7 @@ public String getFunctionName() { * @return A name/value collection of the arguments to the function, if any. */ @Nullable - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { if (arguments == null) { return null; } diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIToolCallConfig.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIToolCallConfig.java new file mode 100644 index 000000000..454ed3ce1 --- /dev/null +++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIToolCallConfig.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.aiservices.openai.chatcompletion; + +import com.azure.ai.openai.models.ChatCompletionsToolDefinition; +import com.azure.ai.openai.models.ChatCompletionsToolSelection; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehaviorOptions; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; + +public class OpenAIToolCallConfig { + private final List tools; + private final ChatCompletionsToolSelection toolChoice; + private final boolean autoInvoke; + @Nullable + private final FunctionChoiceBehaviorOptions options; + + /** + * Creates a new instance of the {@link OpenAIToolCallConfig} class. + * + * @param tools The list of tools available for the call. + * @param toolChoice The tool selection strategy. + * @param autoInvoke Indicates whether to automatically invoke the tool. + * @param options Additional options for function choice behavior. + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") + public OpenAIToolCallConfig( + List tools, + ChatCompletionsToolSelection toolChoice, + boolean autoInvoke, + @Nullable FunctionChoiceBehaviorOptions options) { + this.tools = tools; + this.toolChoice = toolChoice; + this.autoInvoke = autoInvoke; + this.options = options; + } + + /** + * Gets the list of tools available for the call. + * + * @return The list of tools. + */ + public List getTools() { + return Collections.unmodifiableList(tools); + } + + /** + * Gets the tool selection strategy. + * + * @return The tool selection strategy. + */ + public ChatCompletionsToolSelection getToolChoice() { + return toolChoice; + } + + /** + * Indicates whether to automatically invoke the tool. + * + * @return True if auto-invocation is enabled; otherwise, false. + */ + public boolean isAutoInvoke() { + return autoInvoke; + } + + /** + * Gets additional options for function choice behavior. + * + * @return The function choice behavior options. + */ + public FunctionChoiceBehaviorOptions getOptions() { + return options; + } +} diff --git a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java index c9136c554..5c3444b3a 100644 --- a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java +++ b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java @@ -118,9 +118,9 @@ public void otelChatCaptureTest() { spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.system"))); Assertions.assertEquals(21, spans.get(0).getAttributes() - .get(AttributeKey.longKey("gen_ai.response.completion_tokens"))); + .get(AttributeKey.longKey("gen_ai.usage.output_tokens"))); Assertions.assertEquals(42, spans.get(0).getAttributes() - .get(AttributeKey.longKey("gen_ai.response.prompt_tokens"))); + .get(AttributeKey.longKey("gen_ai.usage.input_tokens"))); } } diff --git a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/JsonSchemaTest.java b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/JsonSchemaTest.java index d0cdc0d9c..33870fba2 100644 --- a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/JsonSchemaTest.java +++ b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/JsonSchemaTest.java @@ -1,10 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. package com.microsoft.semantickernel.aiservices.openai.chatcompletion; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.core.JsonProcessingException; import com.microsoft.semantickernel.orchestration.responseformat.JsonSchemaResponseFormat; +import com.microsoft.semantickernel.plugin.KernelPlugin; +import com.microsoft.semantickernel.plugin.KernelPluginFactory; +import com.microsoft.semantickernel.semanticfunctions.KernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; public class JsonSchemaTest { @@ -24,4 +31,82 @@ public void jacksonGenerationTest() throws JsonProcessingException { "\"type\":\"object\",\"properties\":{\"bar\":{}}")); } + @Test + public void openAIFunctionTest() { + KernelPlugin plugin = KernelPluginFactory.createFromObject( + new TestPlugin(), + "test"); + + Assertions.assertNotNull(plugin); + Assertions.assertEquals(plugin.getName(), "test"); + Assertions.assertEquals(plugin.getFunctions().size(), 3); + + KernelFunction testFunction = plugin.getFunctions() + .get("asyncPersonFunction"); + OpenAIFunction openAIFunction = OpenAIFunction.build( + testFunction.getMetadata(), + plugin.getName()); + + String parameters = "{\"type\":\"object\",\"required\":[\"person\",\"input\"],\"properties\":{\"input\":{\"type\":\"string\",\"description\":\"input string\"},\"person\":{\"type\":\"object\",\"properties\":{\"age\":{\"type\":\"integer\",\"description\":\"The age of the person.\"},\"name\":{\"type\":\"string\",\"description\":\"The name of the person.\"},\"title\":{\"type\":\"string\",\"enum\":[\"MS\",\"MRS\",\"MR\"],\"description\":\"The title of the person.\"}},\"required\":[\"age\",\"name\",\"title\"],\"additionalProperties\":false,\"description\":\"input person\"}}}"; + Assertions.assertEquals(parameters, + openAIFunction.getFunctionDefinition().getParameters().toString()); + + } + + public static class TestPlugin { + + @DefineKernelFunction + public String testFunction( + @KernelFunctionParameter(name = "input", description = "input string") String input) { + return "test" + input; + } + + @DefineKernelFunction(returnType = "int") + public Mono asyncTestFunction( + @KernelFunctionParameter(name = "input") String input) { + return Mono.just(1); + } + + @DefineKernelFunction(returnType = "int", description = "test function description", name = "asyncPersonFunction", returnDescription = "test return description") + public Mono asyncPersonFunction( + @KernelFunctionParameter(name = "person", description = "input person", type = Person.class) Person person, + @KernelFunctionParameter(name = "input", description = "input string") String input) { + return Mono.just(1); + } + } + + private static enum Title { + MS, MRS, MR + } + + public static class Person { + @JsonPropertyDescription("The name of the person.") + private String name; + @JsonPropertyDescription("The age of the person.") + private int age; + @JsonPropertyDescription("The title of the person.") + private Title title; + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + public Title getTitle() { + return title; + } + + public void setTitle(Title title) { + this.title = title; + } + } + } diff --git a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java index 05aebc3d6..5a1be82a4 100644 --- a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java +++ b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java @@ -13,7 +13,7 @@ import com.azure.json.implementation.DefaultJsonReader; import com.microsoft.semantickernel.implementation.EmbeddedResourceLoader; import com.microsoft.semantickernel.orchestration.FunctionResultMetadata; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; import java.nio.charset.Charset; @@ -46,7 +46,7 @@ public void serializesToolCallsCorrectly() { "a-tool-id", "pluginName", "funcName", - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("id", "ca2fc6bc-1307-4da6-a009-d7bf88dec37b") .build())))); chatHistory.addMessage(new OpenAIChatMessageContent( diff --git a/api-test/integration-tests/pom.xml b/api-test/integration-tests/pom.xml index 64c122e98..f6c51af78 100644 --- a/api-test/integration-tests/pom.xml +++ b/api-test/integration-tests/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel api-test - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java index ac1821246..dd283952d 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java @@ -6,7 +6,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example03_Arguments.StaticTextPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -24,7 +24,7 @@ public void main() { KernelPlugin functionCollection = KernelPluginFactory .createFromObject(new StaticTextPlugin(), "text"); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withInput("Today is: ") .withVariable("day", "Monday") .build(); diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java index f74268b25..d791ec9c2 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java @@ -10,9 +10,9 @@ import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; -import com.microsoft.semantickernel.services.textcompletion.TextGenerationService; + import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -68,7 +68,7 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) { var result = kernel.invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput("I missed the F1 final race") .build()) .block(); @@ -79,7 +79,7 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) { result = kernel.invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput("sorry I forgot your birthday") .build()) .block(); diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java index 16b9cadaf..4a128fb16 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java @@ -12,7 +12,7 @@ import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokingHook; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.OutputVariable; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -90,7 +90,7 @@ public void getUsageAsync(WireMockRuntimeInfo wmRuntimeInfo) { kernel.invokeAsync( excuseFunction) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("input", "I missed the F1 final race") .build()) diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java index 3f09b50b2..ff4655d26 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java @@ -12,7 +12,7 @@ import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -49,7 +49,7 @@ public void textSemanticKernelTemplateXml() { """) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "\"hello world\"") .build()) @@ -71,7 +71,7 @@ public void textSemanticKernelTemplate() { """) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "{{$ignore}}") .withVariable("ignore", "dont show") @@ -94,7 +94,7 @@ public void textHandleBarsTemplate() { """) .withTemplateFormat("handlebars") .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "{{ignore}}") .withVariable("ignore", "dont show") @@ -117,7 +117,7 @@ public void chatSemanticKernelTemplateXml() { """) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "\"hello world\"") .build()) @@ -139,7 +139,7 @@ public void chatSemanticKernelTemplate() { """) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "{{$ignore}}") .withVariable("ignore", "dont show") @@ -162,7 +162,7 @@ public void chatHandleBarsTemplate() { """) .withTemplateFormat("handlebars") .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "{{ignore}}") .withVariable("ignore", "dont show") @@ -185,7 +185,7 @@ public void chatSemanticKernelTemplate2() { """) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .build()) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("value", "{{$ignore}}") .withVariable("ignore", "dont show") diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java index 77d4b4a36..4ec677742 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java @@ -161,16 +161,18 @@ private static void verifyCalled(OpenAIAsyncClient client, String expected) { new JsonOptions() ); JsonWriter format = chatCompletionsOptions.getResponseFormat() - .toJson(jsonWriter); + .toJson(jsonWriter); jsonWriter.flush(); writer.flush(); String json = String.valueOf(writer.getBuffer()) .replaceAll("\n", "") + .replaceAll("\r", "") .replaceAll(" +", ""); String expectedClean = expected .stripIndent() .replaceAll("\n", "") + .replaceAll("\r", "") .replaceAll(" +", ""); return json.equals(expectedClean); diff --git a/api-test/pom.xml b/api-test/pom.xml index 674f733b0..a60112908 100644 --- a/api-test/pom.xml +++ b/api-test/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/data/semantickernel-data-azureaisearch/pom.xml b/data/semantickernel-data-azureaisearch/pom.xml index c53436bb0..b27936031 100644 --- a/data/semantickernel-data-azureaisearch/pom.xml +++ b/data/semantickernel-data-azureaisearch/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/data/semantickernel-data-jdbc/pom.xml b/data/semantickernel-data-jdbc/pom.xml index 0379f9815..ab4dfe5e8 100644 --- a/data/semantickernel-data-jdbc/pom.xml +++ b/data/semantickernel-data-jdbc/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/data/semantickernel-data-redis/pom.xml b/data/semantickernel-data-redis/pom.xml index e2c18c2d0..871fc9310 100644 --- a/data/semantickernel-data-redis/pom.xml +++ b/data/semantickernel-data-redis/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../../pom.xml diff --git a/pom.xml b/pom.xml index ab526a96e..b8fef17f6 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 pom https://www.github.com/microsoft/semantic-kernel @@ -60,7 +60,7 @@ 5.14.2 0.9.1 - 6.55.0 + 7.10.0 UTF-8 microsoft/semantic-kernel git@github.com:${project.github.repository}.git @@ -77,6 +77,7 @@ data/semantickernel-data-azureaisearch data/semantickernel-data-jdbc data/semantickernel-data-redis + agents/semantickernel-agents-core @@ -837,6 +838,6 @@ https://github.com/microsoft/semantic-kernel scm:git:https://github.com/microsoft/semantic-kernel.git scm:git:https://github.com/microsoft/semantic-kernel.git - java-1.4.3 + java-1.4.4-RC1 diff --git a/samples/pom.xml b/samples/pom.xml index d78bc0dd3..aa9e46050 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-concepts/pom.xml b/samples/semantickernel-concepts/pom.xml index 70f831df2..4adace8fb 100644 --- a/samples/semantickernel-concepts/pom.xml +++ b/samples/semantickernel-concepts/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-samples-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml b/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml index a37752084..700f42c3e 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-concepts - 1.4.3 + 1.4.4-RC1 ../pom.xml @@ -49,6 +49,11 @@ semantickernel-data-redis + + com.microsoft.semantic-kernel + semantickernel-agents-core + + com.microsoft.semantic-kernel semantickernel-experimental diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java index 08a8f3b52..21a4b1c8c 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java @@ -70,9 +70,7 @@ public static void main(String[] args) throws Exception { ChatCompletionService.class); ContextVariableTypes - .addGlobalConverter(ContextVariableTypeConverter.builder(LightModel.class) - .toPromptString(new Gson()::toJson) - .build()); + .addGlobalConverter(new LightModelTypeConverter()); KernelHooks hook = new KernelHooks(); @@ -99,9 +97,7 @@ public static void main(String[] args) throws Exception { InvocationContext invocationContext = new Builder() .withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY) .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)) - .withContextVariableConverter(ContextVariableTypeConverter.builder(LightModel.class) - .toPromptString(new Gson()::toJson) - .build()) + .withContextVariableConverter(new LightModelTypeConverter()) .build(); // Create a history to store the conversation diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java index 072763a91..e7958507b 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java @@ -1,10 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. package com.microsoft.semantickernel.samples.demos.lights; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; + public class LightModel { + @JsonPropertyDescription("The unique identifier of the light") private int id; + + @JsonPropertyDescription("The name of the light") private String name; + + @JsonPropertyDescription("The state of the light") private Boolean isOn; public LightModel(int id, String name, Boolean isOn) { diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModelTypeConverter.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModelTypeConverter.java new file mode 100644 index 000000000..2752eb624 --- /dev/null +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModelTypeConverter.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.demos.lights; + +import com.google.gson.Gson; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; + +public class LightModelTypeConverter extends ContextVariableTypeConverter { + private static final Gson gson = new Gson(); + + public LightModelTypeConverter() { + super( + LightModel.class, + obj -> { + if (obj instanceof String) { + return gson.fromJson((String) obj, LightModel.class); + } else { + return gson.fromJson(gson.toJson(obj), LightModel.class); + } + }, + (types, lightModel) -> gson.toJson(lightModel), + json -> gson.fromJson(json, LightModel.class)); + } +} diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java index d2f4ed08e..398a8d16d 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java @@ -24,6 +24,17 @@ public List getLights() { return lights; } + @DefineKernelFunction(name = "add_light", description = "Adds a new light") + public String addLight( + @KernelFunctionParameter(name = "newLight", description = "new Light Details", type = LightModel.class) LightModel light) { + if (light != null) { + System.out.println("Adding light " + light.getName()); + lights.add(light); + return "Light added"; + } + return "Light failed to added"; + } + @DefineKernelFunction(name = "change_state", description = "Changes the state of the light") public LightModel changeState( @KernelFunctionParameter(name = "id", description = "The ID of the light to change", type = int.class) int id, diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java index 089a4941e..f61d1d873 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import com.microsoft.semantickernel.text.TextChunker; @@ -71,7 +71,7 @@ private static Mono processAsync(KernelFunction func, String inp // The first parameter is the input text. return func.invokeAsync(kernel) .withArguments( - new KernelFunctionArguments.Builder() + KernelArguments.builder() .withInput(paragraph) .build()) .withResultType( diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java new file mode 100644 index 000000000..0f8065ee1 --- /dev/null +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.plugins.github; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +public abstract class GitHubModel { + public final static ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + @Override + public String toString() { + try { + return objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static class User extends GitHubModel { + @JsonProperty("login") + private String login; + @JsonProperty("id") + private long id; + @JsonProperty("name") + private String name; + @JsonProperty("company") + private String company; + @JsonProperty("html_url") + private String url; + + @JsonCreator + public User(@JsonProperty("login") String login, + @JsonProperty("id") long id, + @JsonProperty("name") String name, + @JsonProperty("company") String company, + @JsonProperty("html_url") String url) { + this.login = login; + this.id = id; + this.name = name; + this.company = company; + this.url = url; + } + + public String getLogin() { + return login; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getCompany() { + return company; + } + + public String getUrl() { + return url; + } + } + + public static class Repository extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("full_name") + private String name; + @JsonProperty("description") + private String description; + @JsonProperty("html_url") + private String url; + + @JsonCreator + public Repository(@JsonProperty("id") long id, + @JsonProperty("full_name") String name, + @JsonProperty("description") String description, + @JsonProperty("html_url") String url) { + this.id = id; + this.name = name; + this.description = description; + this.url = url; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getUrl() { + return url; + } + + @Override + public String toString() { + try { + return objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + } + + public static class Issue extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("number") + private long number; + @JsonProperty("title") + private String title; + @JsonProperty("state") + private String state; + @JsonProperty("html_url") + private String url; + @JsonProperty("labels") + private Label[] labels; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("closed_at") + private String closedAt; + + @JsonCreator + public Issue(@JsonProperty("id") long id, + @JsonProperty("number") long number, + @JsonProperty("title") String title, + @JsonProperty("state") String state, + @JsonProperty("html_url") String url, + @JsonProperty("labels") Label[] labels, + @JsonProperty("created_at") String createdAt, + @JsonProperty("closed_at") String closedAt) { + this.id = id; + this.number = number; + this.title = title; + this.state = state; + this.url = url; + this.labels = labels; + this.createdAt = createdAt; + this.closedAt = closedAt; + } + + public long getId() { + return id; + } + + public long getNumber() { + return number; + } + + public String getTitle() { + return title; + } + + public String getState() { + return state; + } + + public String getUrl() { + return url; + } + + public Label[] getLabels() { + return labels; + } + + public String getCreatedAt() { + return createdAt; + } + + public String getClosedAt() { + return closedAt; + } + } + + public static class IssueDetail extends Issue { + @JsonProperty("body") + private String body; + + @JsonCreator + public IssueDetail(@JsonProperty("id") long id, + @JsonProperty("number") long number, + @JsonProperty("title") String title, + @JsonProperty("state") String state, + @JsonProperty("html_url") String url, + @JsonProperty("labels") Label[] labels, + @JsonProperty("created_at") String createdAt, + @JsonProperty("closed_at") String closedAt, + @JsonProperty("body") String body) { + super(id, number, title, state, url, labels, createdAt, closedAt); + this.body = body; + } + + public String getBody() { + return body; + } + } + + public static class Label extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("name") + private String name; + @JsonProperty("description") + private String description; + + @JsonCreator + public Label(@JsonProperty("id") long id, + @JsonProperty("name") String name, + @JsonProperty("description") String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + } +} diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java new file mode 100644 index 000000000..f0bddee10 --- /dev/null +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.plugins.github; + +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; + +import java.io.IOException; +import java.util.List; + +public class GitHubPlugin { + public static final String baseUrl = "https://api.github.com"; + private final String token; + + public GitHubPlugin(String token) { + this.token = token; + } + + @DefineKernelFunction(name = "get_user_info", description = "Get user information from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$User") + public Mono getUserProfileAsync() { + HttpClient client = createClient(); + + return makeRequestAsync(client, "/user") + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.User.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubUser", e); + } + }); + } + + @DefineKernelFunction(name = "get_repo_info", description = "Get repository information from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$Repository") + public Mono getRepositoryAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the repository to retrieve information for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve information for") String repoName) { + HttpClient client = createClient(); + + return makeRequestAsync(client, String.format("/repos/%s/%s", organization, repoName)) + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.Repository.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubRepository", e); + } + }); + } + + @DefineKernelFunction(name = "get_issues", description = "Get issues from GitHub", returnType = "java.util.List") + public Mono> getIssuesAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the organization to retrieve issues for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve issues for") String repoName, + @KernelFunctionParameter(name = "max_results", description = "The maximum number of issues to retrieve", required = false, defaultValue = "10", type = int.class) int maxResults, + @KernelFunctionParameter(name = "state", description = "The state of the issues to retrieve", required = false, defaultValue = "open") String state, + @KernelFunctionParameter(name = "assignee", description = "The assignee of the issues to retrieve", required = false) String assignee) { + HttpClient client = createClient(); + + String query = String.format("/repos/%s/%s/issues", organization, repoName); + query = buildQueryString(query, "state", state); + query = buildQueryString(query, "assignee", assignee); + query = buildQueryString(query, "per_page", String.valueOf(maxResults)); + + return makeRequestAsync(client, query) + .flatMap(json -> { + try { + GitHubModel.Issue[] issues = GitHubModel.objectMapper.readValue(json, + GitHubModel.Issue[].class); + return Mono.just(List.of(issues)); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubIssues", e); + } + }); + } + + @DefineKernelFunction(name = "get_issue_detail_info", description = "Get detail information of a single issue from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$IssueDetail") + public GitHubModel.IssueDetail getIssueDetailAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the repository to retrieve information for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve information for") String repoName, + @KernelFunctionParameter(name = "issue_number", description = "The issue number to retrieve information for", type = int.class) int issueNumber) { + HttpClient client = createClient(); + + return makeRequestAsync(client, + String.format("/repos/%s/%s/issues/%d", organization, repoName, issueNumber)) + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.IssueDetail.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubIssue", e); + } + }).block(); + } + + private HttpClient createClient() { + return HttpClient.create() + .baseUrl(baseUrl) + .headers(headers -> { + headers.add("User-Agent", "request"); + headers.add("Accept", "application/vnd.github+json"); + headers.add("Authorization", "Bearer " + token); + headers.add("X-GitHub-Api-Version", "2022-11-28"); + }); + } + + private static String buildQueryString(String path, String param, String value) { + if (value == null || value.isEmpty() + || value.equals(KernelFunctionParameter.NO_DEFAULT_VALUE)) { + return path; + } + + return path + (path.contains("?") ? "&" : "?") + param + "=" + value; + } + + private Mono makeRequestAsync(HttpClient client, String path) { + return client + .get() + .uri(path) + .responseSingle((res, content) -> { + if (res.status().code() != 200) { + return Mono.error(new IllegalStateException("Request failed: " + res.status())); + } + return content.asString(); + }); + } +} diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java index 63abdbccb..1386cc619 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java @@ -4,7 +4,7 @@ import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.web.SearchUrlPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; public class Example11_WebSearchQueries { @@ -19,7 +19,7 @@ public static void main(String[] args) { // Run var ask = "What's the largest building in Europe?"; - var kernelArguments = KernelFunctionArguments.builder() + var kernelArguments = KernelArguments.builder() .withVariable("query", ask) .build(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java index a388c130e..14fccf0a0 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.aiservices.huggingface.HuggingFaceClient; import com.microsoft.semantickernel.aiservices.huggingface.services.HuggingFaceTextGenerationService; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.textcompletion.TextGenerationService; @@ -43,7 +43,7 @@ public static void runInferenceApiExampleAsync() { var result = kernel.invokeAsync(questionAnswerFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("input", "What is New York?") .build()) .withResultType(String.class) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java index 9dc86a68f..7b1e5752e 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java @@ -10,7 +10,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -61,7 +61,7 @@ public static void main(String[] args) { FunctionResult result = kernel.invokeAsync( myFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("input", "travel") .build()) .block(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java index 0203f66c8..ffa09a677 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java @@ -24,7 +24,7 @@ import com.microsoft.semantickernel.hooks.PromptRenderedEvent; import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.OutputVariable; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -133,7 +133,7 @@ private static void getUsageAsync(Kernel kernel) { String input = "I missed the F1 final race"; var result = kernel.invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("input", input) .build()) @@ -189,7 +189,7 @@ private static void getRenderedPromptAsync(Kernel kernel) { String input = "I missed the F1 final race"; var result = kernel.invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("input", input) .build()) @@ -235,7 +235,7 @@ private static void changingResultAsync(Kernel kernel) { // Invoke prompt to trigger execution hooks. var result = kernel.invokeAsync(writerFunction) .withArguments( - KernelFunctionArguments.builder().build()) + KernelArguments.builder().build()) .block(); System.out.println("Function Result: " + result.getResult()); } @@ -275,7 +275,7 @@ private static void beforeInvokeCancellationAsync(Kernel kernel) { // Invoke prompt to trigger execution hooks. var result = kernel.invokeAsync(writerFunction) .withArguments( - KernelFunctionArguments.builder().build()) + KernelArguments.builder().build()) .block(); System.out.println("Function Result: " + result.getResult()); } catch (Exception e) { @@ -312,7 +312,7 @@ private static void afterInvokeCancellationAsync(Kernel kernel) { // Invoke prompt to trigger execution hooks. try { var result = kernel.invokeAsync(secondFunction) - .withArguments(KernelFunctionArguments.builder().build()) + .withArguments(KernelArguments.builder().build()) .block(); System.out.println("Function Result: " + result.getResult()); } catch (Exception e) { @@ -359,7 +359,7 @@ private static void chatCompletionHook(Kernel kernel) { // Invoke prompt to trigger execution hooks. var result = kernel.invokeAsync(writerFunction) .withArguments( - KernelFunctionArguments.builder().build()) + KernelArguments.builder().build()) .block(); System.out.println("Function Result: " + result.getResult()); } catch (Exception e) { @@ -403,7 +403,7 @@ private static void invocationHook(Kernel kernel) { try { // Invoke prompt to trigger execution hooks. var result = kernel.invokeAsync(writerFunction) - .withArguments(KernelFunctionArguments.builder().build()) + .withArguments(KernelArguments.builder().build()) .addKernelHooks(kernelHooks) .block(); System.out.println("Function Result: " + result.getResult()); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java index 8348ee517..0396d575f 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java @@ -9,6 +9,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; @@ -73,7 +74,7 @@ public static void runByServiceIdAsync(Kernel kernel, String serviceId) { var prompt = "Hello AI, what can you do for me?"; - KernelFunctionArguments arguments = KernelFunctionArguments.builder().build(); + KernelArguments arguments = KernelArguments.builder().build(); KernelFunction func = KernelFunctionFromPrompt .builder() @@ -104,7 +105,7 @@ public static void runByModelIdAsync(Kernel kernel, String modelId) { .build()) .withOutputVariable("result", "java.lang.String") .build()) - .withArguments(KernelFunctionArguments.builder().build()) + .withArguments(KernelArguments.builder().build()) .block(); System.out.println(result.getResult()); @@ -136,7 +137,7 @@ public static void runByFirstModelIdAsync(Kernel kernel, String... modelIds) { .build(); var result = kernel.invokeAsync(function) - .withArguments(KernelFunctionArguments.builder().build()) + .withArguments(KernelArguments.builder().build()) .block(); System.out.println(result.getResult()); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java index afa5b2e33..5e01d13a2 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java @@ -9,7 +9,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.AIService; import com.microsoft.semantickernel.services.AIServiceCollection; @@ -67,7 +67,7 @@ public static void main(String[] args) { var prompt = "Hello AI, what can you do for me?"; - KernelFunctionArguments arguments = KernelFunctionArguments.builder().build(); + KernelArguments arguments = KernelArguments.builder().build(); KernelFunction func = KernelFunctionFromPrompt .builder() @@ -98,7 +98,7 @@ public AIServiceSelection trySelectAIService( @Nullable KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, Map, AIService> services) { // Just get the first one diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/agents/CompletionAgent.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/agents/CompletionAgent.java new file mode 100644 index 000000000..336406a33 --- /dev/null +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/agents/CompletionAgent.java @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples.agents; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.KeyCredential; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.agents.AgentInvokeOptions; +import com.microsoft.semantickernel.agents.AgentThread; +import com.microsoft.semantickernel.agents.chatcompletion.ChatCompletionAgent; +import com.microsoft.semantickernel.agents.chatcompletion.ChatHistoryAgentThread; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior; +import com.microsoft.semantickernel.implementation.templateengine.tokenizer.DefaultPromptTemplate; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; +import com.microsoft.semantickernel.orchestration.ToolCallBehavior; +import com.microsoft.semantickernel.plugin.KernelPluginFactory; +import com.microsoft.semantickernel.samples.plugins.github.GitHubModel; +import com.microsoft.semantickernel.samples.plugins.github.GitHubPlugin; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; +import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; + +import java.util.List; +import java.util.Scanner; + +public class CompletionAgent { + private static final String CLIENT_KEY = System.getenv("CLIENT_KEY"); + private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY"); + + // Only required if AZURE_CLIENT_KEY is set + private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT"); + private static final String MODEL_ID = System.getenv() + .getOrDefault("MODEL_ID", "gpt-4o"); + + private static final String GITHUB_PAT = System.getenv("GITHUB_PAT"); + + public static void main(String[] args) { + System.out.println("======== ChatCompletion Agent ========"); + + OpenAIAsyncClient client; + + if (AZURE_CLIENT_KEY != null) { + client = new OpenAIClientBuilder() + .credential(new AzureKeyCredential(AZURE_CLIENT_KEY)) + .endpoint(CLIENT_ENDPOINT) + .buildAsyncClient(); + + } else { + client = new OpenAIClientBuilder() + .credential(new KeyCredential(CLIENT_KEY)) + .buildAsyncClient(); + } + + System.out.println("------------------------"); + + ChatCompletionService chatCompletion = OpenAIChatCompletion.builder() + .withModelId(MODEL_ID) + .withOpenAIAsyncClient(client) + .build(); + + Kernel kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chatCompletion) + .withPlugin(KernelPluginFactory.createFromObject(new GitHubPlugin(GITHUB_PAT), + "GitHubPlugin")) + .build(); + + InvocationContext invocationContext = InvocationContext.builder() + .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true)) + .withContextVariableConverter(new ContextVariableTypeConverter<>( + GitHubModel.Issue.class, + o -> (GitHubModel.Issue) o, + o -> o.toString(), + s -> null)) + .build(); + + ChatCompletionAgent agent = ChatCompletionAgent.builder() + .withKernel(kernel) + .withKernelArguments( + KernelArguments.builder() + .withVariable("repository", "microsoft/semantic-kernel-java") + .withExecutionSettings(PromptExecutionSettings.builder() + .build()) + .build()) + .withInvocationContext(invocationContext) + .withTemplate( + DefaultPromptTemplate.build( + PromptTemplateConfig.builder() + .withTemplate( + """ + You are an agent designed to query and retrieve information from a single GitHub repository in a read-only manner. + You are also able to access the profile of the active user. + + Use the current date and time to provide up-to-date details or time-sensitive responses. + + The repository you are querying is a public repository with the following name: {{$repository}} + + The current date and time is: {{$now}}. + """) + .build())) + .build(); + + AgentThread agentThread = new ChatHistoryAgentThread(); + Scanner scanner = new Scanner(System.in); + + while (true) { + System.out.print("> "); + + String input = scanner.nextLine(); + if (input.equalsIgnoreCase("exit")) { + break; + } + + var message = new ChatMessageContent<>(AuthorRole.USER, input); + KernelArguments arguments = KernelArguments.builder() + .withVariable("now", System.currentTimeMillis()) + .build(); + + var response = agent.invokeAsync( + message, + agentThread, + AgentInvokeOptions.builder() + .withKernelArguments(arguments) + .build()) + .block().get(0); + + System.out.println("> " + response.getMessage()); + agentThread = response.getThread(); + } + } +} diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java index 1357cc476..04a7a34fe 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java @@ -11,7 +11,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.TimePlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateFactory; import com.microsoft.semantickernel.services.ServiceNotFoundException; @@ -82,7 +82,7 @@ public static void main(String[] args) throws FileNotFoundException, ServiceNotF // Adding required arguments referenced by the prompt templates. - var arguments = KernelFunctionArguments + var arguments = KernelArguments .builder() .withVariable("selectedText", selectedText) .withVariable("startTime", DateTimeFormatter.ofPattern("hh:mm:ss a zz").format( diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java index 2096386dd..7db37899c 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import java.util.Locale; @@ -24,7 +24,7 @@ public static void main(String[] args) { KernelPlugin functionCollection = KernelPluginFactory .createFromObject(new StaticTextPlugin(), "text"); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withInput("Today is: ") .withVariable("day", "Monday") .build(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java index 7ecf9a0da..52edb0dba 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java @@ -11,10 +11,10 @@ import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; -import com.microsoft.semantickernel.services.textcompletion.TextGenerationService; + import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -82,7 +82,7 @@ public static void main(String[] args) throws ConfigurationException { var result = kernel .invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput("I missed the F1 final race") .build()) .block(); @@ -90,7 +90,7 @@ public static void main(String[] args) throws ConfigurationException { result = kernel.invokeAsync(excuseFunction) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput("sorry I forgot your birthday") .build()) .block(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java index c6c1fdffa..4c14ef54f 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java @@ -9,7 +9,6 @@ import com.azure.core.credential.KeyCredential; import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; -import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService; import com.microsoft.semantickernel.contextvariables.ContextVariable; import com.microsoft.semantickernel.contextvariables.ContextVariableType; import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; @@ -17,11 +16,11 @@ import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; -import com.microsoft.semantickernel.services.textcompletion.TextGenerationService; + import java.nio.file.Path; import java.time.Instant; import java.time.OffsetDateTime; @@ -119,7 +118,7 @@ public static void main(String[] args) throws InterruptedException { result = kernel .invokeAsync(plugin.get("InputDateTimeWithStringResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("currentDate", ContextVariable.of( @@ -135,7 +134,7 @@ public static void main(String[] args) throws InterruptedException { result = kernel.invokeAsync(plugin.get("MultipleInputsWithVoidResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("x", "x string") .withVariable("y", 100) @@ -146,7 +145,7 @@ public static void main(String[] args) throws InterruptedException { result = kernel .invokeAsync(plugin.get("ComplexInputWithStringResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable( "complexObject", @@ -165,7 +164,7 @@ public String toString() { result = kernel .invokeAsync(plugin.get("InputStringTaskWithStringResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("echoInput", "return this") .build()) @@ -175,7 +174,7 @@ public String toString() { result = kernel .invokeAsync(plugin.get("InputStringTaskWithVoidResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("x", "x input") .build()) @@ -258,7 +257,7 @@ public String toString() { result = kernel.invokeAsync(plugin.get("MultipleComplexInputsWithVoidResult")) .withArguments( - KernelFunctionArguments + KernelArguments .builder() .withVariable("x", OffsetDateTime.of(1, 1, 1, 1, 1, 1, 1, ZoneOffset.UTC)) .withVariable("y", OffsetDateTime.of(1, 1, 1, 1, 1, 1, 1, ZoneOffset.UTC)) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java index f72ec2370..1f139e2ff 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java @@ -9,7 +9,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; public class Example27_PromptFunctionsUsingChatGPT { @@ -54,7 +54,7 @@ public static void main(String[] args) { var result = func.invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("input", "Jupiter") .build()) .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(String.class)) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java index e52c2be79..e921bb784 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java @@ -10,6 +10,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatMessageContent; import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIFunctionToolCall; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior; import com.microsoft.semantickernel.implementation.CollectionUtil; import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.orchestration.FunctionResultMetadata; @@ -38,7 +39,7 @@ public class Example59_OpenAIFunctionCalling { // Only required if AZURE_CLIENT_KEY is set private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT"); private static final String MODEL_ID = System.getenv() - .getOrDefault("MODEL_ID", "gpt-35-turbo-2"); + .getOrDefault("MODEL_ID", "gpt-4o"); // Define functions that can be called by the model public static class HelperFunctions { @@ -118,7 +119,7 @@ public static void main(String[] args) throws NoSuchMethodException { var result = kernel .invokeAsync(function) - .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)) + .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true)) .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(String.class)) .block(); System.out.println(result.getResult()); @@ -134,7 +135,7 @@ public static void main(String[] args) throws NoSuchMethodException { chatHistory, kernel, InvocationContext.builder() - .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(false)) + .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(false)) .withReturnMode(InvocationReturnMode.FULL_HISTORY) .build()) .block(); @@ -243,7 +244,7 @@ public static void multiTurnaroundCall() { chatHistory, kernel, InvocationContext.builder() - .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)) + .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true)) .withReturnMode(InvocationReturnMode.FULL_HISTORY) .build()) .block(); @@ -258,7 +259,7 @@ public static void multiTurnaroundCall() { chatHistory, kernel, InvocationContext.builder() - .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)) + .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true)) .withReturnMode(InvocationReturnMode.FULL_HISTORY) .build()) .block(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java index 87669a40c..dfbaeb722 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import reactor.core.publisher.Mono; @@ -37,7 +37,7 @@ public static void main(String[] args) { var result = kernel .invokeAsync(FunctionsChainingPlugin.PluginName, "Function1") .withArguments( - KernelFunctionArguments + KernelArguments .builder() .build()) .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(MyCustomType.class)) @@ -82,7 +82,7 @@ public Mono function1Async(Kernel kernel) { // Execute another function return kernel .invokeAsync(PluginName, "Function2") - .withArguments(KernelFunctionArguments.builder().build()) + .withArguments(KernelArguments.builder().build()) .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass( Example60_AdvancedMethodFunctions.MyCustomType.class)) .flatMap(value -> { diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java index 0dd425f6e..b585775db 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.orchestration.ToolCallBehavior; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; @@ -140,7 +140,7 @@ public static void main(String[] args) throws NoSuchMethodException { var fn = kernel.getFunction(geminiFunction.getPluginName(), geminiFunction.getFunctionName()); - var arguments = KernelFunctionArguments.builder(); + var arguments = KernelArguments.builder(); geminiFunction.getFunctionCall().getArgs().getFieldsMap() .forEach((key, value) -> { arguments.withVariable(key, value.getStringValue()); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/CustomTypes_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/CustomTypes_Example.java index e809474dc..fcf2cc812 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/CustomTypes_Example.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/CustomTypes_Example.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.contextvariables.converters.ContextVariableJacksonConverter; import com.microsoft.semantickernel.exceptions.ConfigurationException; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import java.io.IOException; import java.util.Arrays; @@ -114,7 +114,7 @@ private static void exampleBuildingCustomConverter( Pet updated = kernel.invokePromptAsync( "Change Sandy's name to Daisy:\n{{$Sandy}}", - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("Sandy", sandy, typeConverter) .build()) .withTypeConverter(typeConverter) @@ -139,7 +139,7 @@ public static void exampleUsingJackson(ChatCompletionService chatCompletionServi // Invoke the prompt with the custom converter Pet updated = kernel.invokePromptAsync( "Increase Sandy's age by a year:\n{{$Sandy}}", - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("Sandy", sandy, typeConverter) .build()) .withTypeConverter(typeConverter) @@ -167,7 +167,7 @@ public static void exampleUsingGlobalTypes(ChatCompletionService chatCompletionS // No need to explicitly tell the invocation how to convert the type Pet updated = kernel.invokePromptAsync( "Sandy's is actually a cat correct this:\n{{$Sandy}}", - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("Sandy", sandy) .build()) .withResultType(Pet.class) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionTelemetry_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionTelemetry_Example.java index 1d228250c..4ca35a80f 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionTelemetry_Example.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionTelemetry_Example.java @@ -14,7 +14,7 @@ import com.microsoft.semantickernel.orchestration.ToolCallBehavior; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example59_OpenAIFunctionCalling.PetPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import com.microsoft.semantickernel.services.ServiceNotFoundException; @@ -204,7 +204,7 @@ public static void testNestedCalls() { Analyse the following text: Hello There """, - KernelFunctionArguments.builder().build(), + KernelArguments.builder().build(), InvocationContext.builder() .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)) .withReturnMode(InvocationReturnMode.NEW_MESSAGES_ONLY) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java index b13f06998..29ad37696 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java @@ -4,7 +4,7 @@ import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.exceptions.ConfigurationException; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelPromptTemplateFactory; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; @@ -41,7 +41,7 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio var renderedPrompt = promptTemplate.renderAsync( kernel, - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("choices", choices) .build(), null) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java index ceb9983ed..7e92e3e6e 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java @@ -12,7 +12,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; @@ -154,7 +154,7 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio // Invoke handlebars prompt var intent = kernel.invokeAsync(getIntent) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("request", request) .withVariable("choices", choices) .withVariable("history", historyString) @@ -173,7 +173,7 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio // Get chat response var chatResult = kernel.invokeAsync(chat) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("request", request) .withVariable("history", historyString) .build()) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java index ec38aae05..10e9a014e 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.implementation.telemetry.SemanticKernelTelemetry; import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionYaml; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import java.io.IOException; @@ -70,7 +70,7 @@ private static void handlebarsTemplate(Kernel kernel, FunctionResult result = function .invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("length", 5) .withVariable("topic", "dogs") .build()) @@ -91,7 +91,7 @@ private static void semanticKernelTemplate(Kernel kernel, FunctionResult result = function .invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("length", 5) .withVariable("topic", "cats") .build()) diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example07_BingAndGooglePlugins.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example07_BingAndGooglePlugins.java index 6ca71745b..2e4462fd2 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example07_BingAndGooglePlugins.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example07_BingAndGooglePlugins.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.web.WebSearchEnginePlugin; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.KernelPromptTemplateFactory; import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; @@ -84,7 +84,7 @@ private static void example1Async(Kernel kernel, String searchPluginName) { // Run var question = "What's the largest building in the world?"; - var kernelArguments = KernelFunctionArguments.builder() + var kernelArguments = KernelArguments.builder() .withVariable("query", question) .build(); @@ -166,7 +166,7 @@ private static void example2Async(Kernel kernel) { .withDefaultExecutionSettings(promptExecutionSettings) .build(); - var kernelArguments = KernelFunctionArguments.builder() + var kernelArguments = KernelArguments.builder() .withVariable("question", question) .withVariable("externalInformation", "") .build(); @@ -187,7 +187,7 @@ private static void example2Async(Kernel kernel) { System.out.println("Information found:"); System.out.println(information); - kernelArguments = KernelFunctionArguments.builder() + kernelArguments = KernelArguments.builder() .withVariable("question", question) .withVariable("externalInformation", information) .build(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example13_ConversationSummaryPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example13_ConversationSummaryPlugin.java index b185c8946..63412b600 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example13_ConversationSummaryPlugin.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugin/Example13_ConversationSummaryPlugin.java @@ -12,7 +12,9 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments.Builder; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments.Builder; +import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import reactor.core.publisher.Mono; @@ -163,7 +165,7 @@ private static void getConversationActionItemsAsync() { conversationSummaryPlugin .get("GetConversationActionItems")) .withArguments( - new Builder() + KernelArguments.builder() .withInput(chatTranscript) .build()); System.out.println("Generated Action Items:"); @@ -179,7 +181,7 @@ private static void getConversationTopicsAsync() { Mono> summary = kernel .invokeAsync(conversationSummaryPlugin.get("GetConversationTopics")) .withArguments( - new Builder() + KernelArguments.builder() .withInput(chatTranscript) .build()); @@ -201,7 +203,7 @@ private static void conversationSummaryPluginAsync() { .getFunctions() .get("SummarizeConversation")) .withArguments( - new Builder() + KernelArguments.builder() .withInput(chatTranscript) .build()) .block(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java index dc663d2d1..e26babe61 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java @@ -10,7 +10,7 @@ import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.text.TextPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.KernelPromptTemplateFactory; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; @@ -53,7 +53,7 @@ public static void main(String[] args) { System.out.println("======== TemplateMethodFunctionsWithMultipleArguments ========"); - var arguments = KernelFunctionArguments.builder() + var arguments = KernelArguments.builder() .withVariable("word2", " Potter") .build(); diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java index ae534e70f..75568a6e9 100644 --- a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java +++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java @@ -9,7 +9,7 @@ import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; import com.microsoft.semantickernel.semanticfunctions.AggregatorPromptTemplateFactory; import com.microsoft.semantickernel.semanticfunctions.HandlebarsPromptTemplateFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.semanticfunctions.KernelPromptTemplateFactory; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateFactory; @@ -75,7 +75,7 @@ public static void runPrompt(Kernel kernel, String templateFormat, String prompt .withPromptTemplateFactory(templateFactory) .build(); - var arguments = KernelFunctionArguments.builder() + var arguments = KernelArguments.builder() .withVariable("name", "Bob") .build(); diff --git a/samples/semantickernel-demos/booking-agent-m365/pom.xml b/samples/semantickernel-demos/booking-agent-m365/pom.xml index 69c9d527e..fb1461f56 100644 --- a/samples/semantickernel-demos/booking-agent-m365/pom.xml +++ b/samples/semantickernel-demos/booking-agent-m365/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-demos - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-demos/pom.xml b/samples/semantickernel-demos/pom.xml index 7a6e76f4a..7637b820a 100644 --- a/samples/semantickernel-demos/pom.xml +++ b/samples/semantickernel-demos/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-samples-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml b/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml index ad5b020b1..30d23e794 100644 --- a/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml +++ b/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-demos - 1.4.3 + 1.4.4-RC1 ../pom.xml @@ -56,7 +56,7 @@ org.springframework.boot spring-boot - 3.3.1 + 3.3.11 org.springframework diff --git a/samples/semantickernel-demos/sk-presidio-sample/pom.xml b/samples/semantickernel-demos/sk-presidio-sample/pom.xml index 9277e1f8c..ff5520d79 100644 --- a/samples/semantickernel-demos/sk-presidio-sample/pom.xml +++ b/samples/semantickernel-demos/sk-presidio-sample/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-demos - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java b/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java index 366d50148..ad14c3caf 100644 --- a/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java +++ b/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.presidio.AnonymizedText; import com.microsoft.semantickernel.presidio.AnonymizedTextConverter; import com.microsoft.semantickernel.presidio.RedactorPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.ServiceNotFoundException; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; @@ -50,7 +50,7 @@ public static void main(String[] args) throws InterruptedException { .invokeAsync("redactor", "redact") .withResultType(AnonymizedText.class) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("input", text) .build()) .block() diff --git a/samples/semantickernel-learn-resources/pom.xml b/samples/semantickernel-learn-resources/pom.xml index 904178d8b..338394719 100644 --- a/samples/semantickernel-learn-resources/pom.xml +++ b/samples/semantickernel-learn-resources/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-samples-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java index 2cbb5baa0..ec3b9b951 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java @@ -12,7 +12,7 @@ import com.microsoft.semantickernel.orchestration.ToolCallBehavior; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.MathPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; import java.util.Scanner; @@ -54,7 +54,7 @@ public static void main(String[] args) { // Test the math plugin var answer = kernel .invokeAsync(kernel.getFunction("MathPlugin", "sqrt")) - .withArguments(KernelFunctionArguments + .withArguments(KernelArguments .builder() .withVariable("number1", 12.0) .build()) diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java index f271b7574..de394835d 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java @@ -16,7 +16,7 @@ import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; @@ -139,7 +139,7 @@ public static void main(String[] args) { System.console().printf("User > "); String request = System.console().readLine(); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("request", request) .withVariable("choices", choices) .withVariable("history", history) @@ -162,7 +162,7 @@ public static void main(String[] args) { // Get chat response FunctionResult chatResult = chat.invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("request", request) .withVariable("history", history) .build()) diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java index 3b5ba5915..233177e7d 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java @@ -11,7 +11,7 @@ import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin; import com.microsoft.semantickernel.semanticfunctions.HandlebarsPromptTemplateFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionYaml; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -119,7 +119,7 @@ public static void main(String[] args) throws IOException { // var intent = kernel.invokeAsync(getIntent) - .withArguments(KernelFunctionArguments.builder() + .withArguments(KernelArguments.builder() .withVariable("request", userInput) .withVariable("choices", choices) .withVariable("history", historyString) @@ -134,7 +134,7 @@ public static void main(String[] args) throws IOException { } var reply = kernel.invokeAsync(prompts.get("Chat")) - .withArguments(KernelFunctionArguments.builder() + .withArguments(KernelArguments.builder() .withVariable("request", userInput) .withVariable("history", String.join("\n", diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java index 41b096511..b830cd29f 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java @@ -14,7 +14,7 @@ import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; @@ -154,7 +154,7 @@ public static void main(String[] args) { System.out.print("User > "); String request = scanner.nextLine(); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("request", request) .withVariable("choices", choices) .withVariable("chatHistory", history) @@ -180,7 +180,7 @@ public static void main(String[] args) { // Get chat response FunctionResult chatResult = chat.invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("request", request) .withVariable("history", history, chatHistoryType) .build()) diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java index 73f137dc8..ebb0e4979 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java @@ -10,7 +10,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; import com.microsoft.semantickernel.samples.plugins.MathPlugin; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; public class UsingTheKernel { @@ -76,7 +76,7 @@ public static void main(String[] args) { var result = poemPlugin.get("ShortPoem") .invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput("The cat sat on a mat") .build()) .withResultType(String.class) @@ -88,7 +88,7 @@ public static void main(String[] args) { var root = mathPlugin.get("sqrt") .invokeAsync(kernel) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withInput(12) .build()) .withResultType(Double.class) diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java index 247fc48c1..0a224c2fd 100644 --- a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; import com.microsoft.semantickernel.text.TextChunker; @@ -71,7 +71,7 @@ private static Mono processAsync(KernelFunction func, String inp // The first parameter is the input text. return func.invokeAsync(kernel) .withArguments( - new KernelFunctionArguments.Builder() + KernelArguments.builder() .withInput(paragraph) .build()) .withResultType( diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java new file mode 100644 index 000000000..0f8065ee1 --- /dev/null +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubModel.java @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.plugins.github; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +public abstract class GitHubModel { + public final static ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + @Override + public String toString() { + try { + return objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static class User extends GitHubModel { + @JsonProperty("login") + private String login; + @JsonProperty("id") + private long id; + @JsonProperty("name") + private String name; + @JsonProperty("company") + private String company; + @JsonProperty("html_url") + private String url; + + @JsonCreator + public User(@JsonProperty("login") String login, + @JsonProperty("id") long id, + @JsonProperty("name") String name, + @JsonProperty("company") String company, + @JsonProperty("html_url") String url) { + this.login = login; + this.id = id; + this.name = name; + this.company = company; + this.url = url; + } + + public String getLogin() { + return login; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getCompany() { + return company; + } + + public String getUrl() { + return url; + } + } + + public static class Repository extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("full_name") + private String name; + @JsonProperty("description") + private String description; + @JsonProperty("html_url") + private String url; + + @JsonCreator + public Repository(@JsonProperty("id") long id, + @JsonProperty("full_name") String name, + @JsonProperty("description") String description, + @JsonProperty("html_url") String url) { + this.id = id; + this.name = name; + this.description = description; + this.url = url; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getUrl() { + return url; + } + + @Override + public String toString() { + try { + return objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + } + + public static class Issue extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("number") + private long number; + @JsonProperty("title") + private String title; + @JsonProperty("state") + private String state; + @JsonProperty("html_url") + private String url; + @JsonProperty("labels") + private Label[] labels; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("closed_at") + private String closedAt; + + @JsonCreator + public Issue(@JsonProperty("id") long id, + @JsonProperty("number") long number, + @JsonProperty("title") String title, + @JsonProperty("state") String state, + @JsonProperty("html_url") String url, + @JsonProperty("labels") Label[] labels, + @JsonProperty("created_at") String createdAt, + @JsonProperty("closed_at") String closedAt) { + this.id = id; + this.number = number; + this.title = title; + this.state = state; + this.url = url; + this.labels = labels; + this.createdAt = createdAt; + this.closedAt = closedAt; + } + + public long getId() { + return id; + } + + public long getNumber() { + return number; + } + + public String getTitle() { + return title; + } + + public String getState() { + return state; + } + + public String getUrl() { + return url; + } + + public Label[] getLabels() { + return labels; + } + + public String getCreatedAt() { + return createdAt; + } + + public String getClosedAt() { + return closedAt; + } + } + + public static class IssueDetail extends Issue { + @JsonProperty("body") + private String body; + + @JsonCreator + public IssueDetail(@JsonProperty("id") long id, + @JsonProperty("number") long number, + @JsonProperty("title") String title, + @JsonProperty("state") String state, + @JsonProperty("html_url") String url, + @JsonProperty("labels") Label[] labels, + @JsonProperty("created_at") String createdAt, + @JsonProperty("closed_at") String closedAt, + @JsonProperty("body") String body) { + super(id, number, title, state, url, labels, createdAt, closedAt); + this.body = body; + } + + public String getBody() { + return body; + } + } + + public static class Label extends GitHubModel { + @JsonProperty("id") + private long id; + @JsonProperty("name") + private String name; + @JsonProperty("description") + private String description; + + @JsonCreator + public Label(@JsonProperty("id") long id, + @JsonProperty("name") String name, + @JsonProperty("description") String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + } +} diff --git a/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java new file mode 100644 index 000000000..f0bddee10 --- /dev/null +++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/github/GitHubPlugin.java @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.plugins.github; + +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; + +import java.io.IOException; +import java.util.List; + +public class GitHubPlugin { + public static final String baseUrl = "https://api.github.com"; + private final String token; + + public GitHubPlugin(String token) { + this.token = token; + } + + @DefineKernelFunction(name = "get_user_info", description = "Get user information from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$User") + public Mono getUserProfileAsync() { + HttpClient client = createClient(); + + return makeRequestAsync(client, "/user") + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.User.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubUser", e); + } + }); + } + + @DefineKernelFunction(name = "get_repo_info", description = "Get repository information from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$Repository") + public Mono getRepositoryAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the repository to retrieve information for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve information for") String repoName) { + HttpClient client = createClient(); + + return makeRequestAsync(client, String.format("/repos/%s/%s", organization, repoName)) + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.Repository.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubRepository", e); + } + }); + } + + @DefineKernelFunction(name = "get_issues", description = "Get issues from GitHub", returnType = "java.util.List") + public Mono> getIssuesAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the organization to retrieve issues for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve issues for") String repoName, + @KernelFunctionParameter(name = "max_results", description = "The maximum number of issues to retrieve", required = false, defaultValue = "10", type = int.class) int maxResults, + @KernelFunctionParameter(name = "state", description = "The state of the issues to retrieve", required = false, defaultValue = "open") String state, + @KernelFunctionParameter(name = "assignee", description = "The assignee of the issues to retrieve", required = false) String assignee) { + HttpClient client = createClient(); + + String query = String.format("/repos/%s/%s/issues", organization, repoName); + query = buildQueryString(query, "state", state); + query = buildQueryString(query, "assignee", assignee); + query = buildQueryString(query, "per_page", String.valueOf(maxResults)); + + return makeRequestAsync(client, query) + .flatMap(json -> { + try { + GitHubModel.Issue[] issues = GitHubModel.objectMapper.readValue(json, + GitHubModel.Issue[].class); + return Mono.just(List.of(issues)); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubIssues", e); + } + }); + } + + @DefineKernelFunction(name = "get_issue_detail_info", description = "Get detail information of a single issue from GitHub", returnType = "com.microsoft.semantickernel.samples.plugins.github.GitHubModel$IssueDetail") + public GitHubModel.IssueDetail getIssueDetailAsync( + @KernelFunctionParameter(name = "organization", description = "The name of the repository to retrieve information for") String organization, + @KernelFunctionParameter(name = "repo_name", description = "The name of the repository to retrieve information for") String repoName, + @KernelFunctionParameter(name = "issue_number", description = "The issue number to retrieve information for", type = int.class) int issueNumber) { + HttpClient client = createClient(); + + return makeRequestAsync(client, + String.format("/repos/%s/%s/issues/%d", organization, repoName, issueNumber)) + .map(json -> { + try { + return GitHubModel.objectMapper.readValue(json, GitHubModel.IssueDetail.class); + } catch (IOException e) { + throw new IllegalStateException("Failed to deserialize GitHubIssue", e); + } + }).block(); + } + + private HttpClient createClient() { + return HttpClient.create() + .baseUrl(baseUrl) + .headers(headers -> { + headers.add("User-Agent", "request"); + headers.add("Accept", "application/vnd.github+json"); + headers.add("Authorization", "Bearer " + token); + headers.add("X-GitHub-Api-Version", "2022-11-28"); + }); + } + + private static String buildQueryString(String path, String param, String value) { + if (value == null || value.isEmpty() + || value.equals(KernelFunctionParameter.NO_DEFAULT_VALUE)) { + return path; + } + + return path + (path.contains("?") ? "&" : "?") + param + "=" + value; + } + + private Mono makeRequestAsync(HttpClient client, String path) { + return client + .get() + .uri(path) + .responseSingle((res, content) -> { + if (res.status().code() != 200) { + return Mono.error(new IllegalStateException("Request failed: " + res.status())); + } + return content.asString(); + }); + } +} diff --git a/samples/semantickernel-sample-plugins/pom.xml b/samples/semantickernel-sample-plugins/pom.xml index d82def681..6f8185b0b 100644 --- a/samples/semantickernel-sample-plugins/pom.xml +++ b/samples/semantickernel-sample-plugins/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-samples-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml index 3bb0353cc..085a462f0 100644 --- a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml +++ b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-sample-plugins - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java index e37b08916..ebdc84495 100644 --- a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java +++ b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.microsoft.semantickernel.contextvariables.ContextVariable; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.parameters.Parameter; @@ -66,7 +66,7 @@ public OpenAPIHttpRequestPlugin( * @param arguments The arguments to the http request. * @return The body of the response. */ - public Mono execute(KernelFunctionArguments arguments) { + public Mono execute(KernelArguments arguments) { String body = getBody(arguments); String query = buildQueryString(arguments); String path = buildQueryPath(arguments); @@ -113,7 +113,7 @@ public Mono execute(KernelFunctionArguments arguments) { .doOnNext(response -> LOGGER.debug("Request response: {}", response)); } - private static @Nullable String getBody(KernelFunctionArguments arguments) { + private static @Nullable String getBody(KernelArguments arguments) { String body = null; if (arguments.containsKey("requestbody")) { ContextVariable requestBody = arguments.get("requestbody"); @@ -130,7 +130,7 @@ public Mono execute(KernelFunctionArguments arguments) { return body; } - private String buildQueryPath(KernelFunctionArguments arguments) { + private String buildQueryPath(KernelArguments arguments) { return getParameterStreamOfArguments(arguments) .filter(p -> p instanceof PathParameter) .reduce(path, (path, parameter) -> { @@ -142,7 +142,7 @@ private String buildQueryPath(KernelFunctionArguments arguments) { } private static String getRenderedParameter( - KernelFunctionArguments arguments, String name) { + KernelArguments arguments, String name) { ContextVariable value = arguments.get(name); if (value == null) { @@ -156,7 +156,7 @@ private static String getRenderedParameter( return URLEncoder.encode(rendered, StandardCharsets.US_ASCII); } - private String buildQueryString(KernelFunctionArguments arguments) { + private String buildQueryString(KernelArguments arguments) { return getParameterStreamOfArguments(arguments) .filter(p -> p instanceof QueryParameter) .map(parameter -> { @@ -168,7 +168,7 @@ private String buildQueryString(KernelFunctionArguments arguments) { } private Stream getParameterStreamOfArguments( - KernelFunctionArguments arguments) { + KernelArguments arguments) { if (operation.getParameters() == null) { return Stream.empty(); } diff --git a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java index c1be538dc..2c01f0767 100644 --- a/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java +++ b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java @@ -15,7 +15,7 @@ import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.semanticfunctions.InputVariable; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.OutputVariable; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -518,7 +518,7 @@ private static KernelFunction buildKernelFunction( try { Method method = OpenAPIHttpRequestPlugin.class.getMethod("execute", - KernelFunctionArguments.class); + KernelArguments.class); return KernelFunction .createFromMethod(method, plugin) diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml index e06845d5c..78b75aac4 100644 --- a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml +++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-sample-plugins - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/samples/semantickernel-sample-plugins/semantickernel-text-splitter-plugin/pom.xml b/samples/semantickernel-sample-plugins/semantickernel-text-splitter-plugin/pom.xml index 9f9a298ab..906b62db6 100644 --- a/samples/semantickernel-sample-plugins/semantickernel-text-splitter-plugin/pom.xml +++ b/samples/semantickernel-sample-plugins/semantickernel-text-splitter-plugin/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-sample-plugins - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/semantickernel-api/pom.xml b/semantickernel-api/pom.xml index efe7d2261..06e1ebc06 100644 --- a/semantickernel-api/pom.xml +++ b/semantickernel-api/pom.xml @@ -6,7 +6,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 ../pom.xml diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java index 57e461656..5e6cc2fdf 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java @@ -9,7 +9,7 @@ import com.microsoft.semantickernel.orchestration.InvocationContext; import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.AIService; import com.microsoft.semantickernel.services.AIServiceCollection; import com.microsoft.semantickernel.services.AIServiceSelection; @@ -173,7 +173,7 @@ public FunctionInvocation invokePromptAsync(@Nonnull String prompt) { * @see KernelFunction#invokeAsync(Kernel) */ public FunctionInvocation invokePromptAsync(@Nonnull String prompt, - @Nonnull KernelFunctionArguments arguments) { + @Nonnull KernelArguments arguments) { KernelFunction function = KernelFunction.createFromPrompt(prompt).build(); return function.invokeAsync(this) @@ -192,7 +192,7 @@ public FunctionInvocation invokePromptAsync(@Nonnull String prompt, */ public FunctionInvocation invokePromptAsync(@Nonnull String prompt, - @Nonnull KernelFunctionArguments arguments, @Nonnull InvocationContext invocationContext) { + @Nonnull KernelArguments arguments, @Nonnull InvocationContext invocationContext) { KernelFunction function = KernelFunction.createFromPrompt(prompt).build(); @@ -278,7 +278,7 @@ public List> getFunctions() { * addition to any hooks provided to a function. * * @return The {@code KernelHooks} used throughout the kernel. - * @see KernelFunction#invokeAsync(Kernel, KernelFunctionArguments, ContextVariableType, + * @see KernelFunction#invokeAsync(Kernel, KernelArguments, ContextVariableType, * InvocationContext) */ @SuppressFBWarnings("EI_EXPOSE_REP") @@ -302,14 +302,12 @@ public AIServiceSelector getServiceSelector() { * @param clazz The class of the service to get. * @return The service of the specified type from the kernel. * @throws ServiceNotFoundException if the service is not found. - * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, - * KernelFunction, com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments) + * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, KernelArguments) */ public T getService(Class clazz) throws ServiceNotFoundException { AIServiceSelection selector = serviceSelector .trySelectAIService( clazz, - null, null); if (selector == null) { @@ -319,6 +317,30 @@ public T getService(Class clazz) throws ServiceNotFound return selector.getService(); } + /** + * Get the service of the specified type from the kernel. + * + * @param The type of the service to get. + * @param clazz The class of the service to get. + * @param args The arguments to help select the service to get. + * @return The service of the specified type from the kernel. + * @throws ServiceNotFoundException if the service is not found. + * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, KernelArguments) + */ + public T getService(Class clazz, KernelArguments args) + throws ServiceNotFoundException { + AIServiceSelection selector = serviceSelector + .trySelectAIService( + clazz, + args); + + if (selector == null) { + throw new ServiceNotFoundException("Unable to find service of type " + clazz.getName()); + } + + return selector.getService(); + } + /** * A fluent builder for creating a new instance of {@code Kernel}. */ diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/Agent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/Agent.java new file mode 100644 index 000000000..f69b2152d --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/Agent.java @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.annotation.Nullable; + +/** + * Interface for a semantic kernel agent. + */ +public interface Agent { + + /** + * Gets the agent's ID. + * + * @return The agent's ID + */ + String getId(); + + /** + * Gets the agent's name. + * + * @return The agent's name + */ + String getName(); + + /** + * Gets the agent's description. + * + * @return The agent's description + */ + String getDescription(); + + /** + * Invokes the agent with the given message. + * + * @param message The message to process + * @return A Mono containing the agent response + */ + Mono>>> invokeAsync( + @Nullable ChatMessageContent message); + + /** + * Invokes the agent with the given message and thread. + * + * @param message The message to process + * @param thread The agent thread to use + * @return A Mono containing the agent response + */ + Mono>>> invokeAsync( + @Nullable ChatMessageContent message, + @Nullable AgentThread thread); + + /** + * Invokes the agent with the given message, thread, and options. + * + * @param message The message to process + * @param thread The agent thread to use + * @param options The options for invoking the agent + * @return A Mono containing the agent response + */ + Mono>>> invokeAsync( + @Nullable ChatMessageContent message, + @Nullable AgentThread thread, + @Nullable AgentInvokeOptions options); + + /** + * Invoke the agent with the given chat history. + * + * @param messages The chat history to process + * @param thread The agent thread to use + * @param options The options for invoking the agent + * @return A Mono containing the agent response + */ + Mono>>> invokeAsync( + List> messages, + @Nullable AgentThread thread, + @Nullable AgentInvokeOptions options); + + /** + * Notifies the agent of a new message. + * + * @param thread The agent thread to use + */ + Mono notifyThreadOfNewMessageAsync(AgentThread thread, ChatMessageContent newMessage); +} \ No newline at end of file diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentInvokeOptions.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentInvokeOptions.java new file mode 100644 index 000000000..6b6d57ed3 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentInvokeOptions.java @@ -0,0 +1,161 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import javax.annotation.Nullable; + +/** + * Options for invoking an agent. + */ +public class AgentInvokeOptions { + + @Nullable + private final KernelArguments kernelArguments; + @Nullable + private final Kernel kernel; + @Nullable + private final String additionalInstructions; + @Nullable + private final InvocationContext invocationContext; + + /** + * Default constructor for AgentInvokeOptions. + */ + public AgentInvokeOptions() { + this(null, null, null, null); + } + + /** + * Constructor for AgentInvokeOptions. + * + * @param kernelArguments The arguments for the kernel function. + * @param kernel The kernel to use. + * @param additionalInstructions Additional instructions for the agent. + * @param invocationContext The invocation context. + */ + public AgentInvokeOptions(@Nullable KernelArguments kernelArguments, + @Nullable Kernel kernel, + @Nullable String additionalInstructions, + @Nullable InvocationContext invocationContext) { + this.kernelArguments = kernelArguments != null ? kernelArguments.copy() : null; + this.kernel = kernel; + this.additionalInstructions = additionalInstructions; + this.invocationContext = invocationContext; + } + + /** + * Get the kernel arguments. + * + * @return The kernel arguments. + */ + @SuppressFBWarnings("EI_EXPOSE_REP") + public KernelArguments getKernelArguments() { + return kernelArguments; + } + + /** + * Get the kernel. + * + * @return The kernel. + */ + public Kernel getKernel() { + return kernel; + } + + /** + * Get additional instructions. + * + * @return The additional instructions. + */ + public String getAdditionalInstructions() { + return additionalInstructions; + } + + /** + * Get the invocation context. + * + * @return The invocation context. + */ + public InvocationContext getInvocationContext() { + return invocationContext; + } + + /** + * Builder for AgentInvokeOptions. + */ + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements SemanticKernelBuilder { + + private KernelArguments kernelArguments; + private Kernel kernel; + private String additionalInstructions; + private InvocationContext invocationContext; + + /** + * Set the kernel arguments. + * + * @param kernelArguments The kernel arguments. + * @return The builder. + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") + public Builder withKernelArguments(KernelArguments kernelArguments) { + this.kernelArguments = kernelArguments; + return this; + } + + /** + * Set the kernel. + * + * @param kernel The kernel. + * @return The builder. + */ + public Builder withKernel(Kernel kernel) { + this.kernel = kernel; + return this; + } + + /** + * Set additional instructions. + * + * @param additionalInstructions The additional instructions. + * @return The builder. + */ + public Builder withAdditionalInstructions(String additionalInstructions) { + this.additionalInstructions = additionalInstructions; + return this; + } + + /** + * Set the invocation context. + * + * @param invocationContext The invocation context. + * @return The builder. + */ + public Builder withInvocationContext(InvocationContext invocationContext) { + this.invocationContext = invocationContext; + return this; + } + + /** + * Build the object. + * + * @return a constructed object. + */ + @Override + public AgentInvokeOptions build() { + return new AgentInvokeOptions( + kernelArguments, + kernel, + additionalInstructions, + invocationContext); + } + } +} \ No newline at end of file diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentResponseItem.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentResponseItem.java new file mode 100644 index 000000000..0b4550986 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentResponseItem.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +public class AgentResponseItem { + private final T message; + private final AgentThread thread; + + @SuppressFBWarnings("EI_EXPOSE_REP2") + public AgentResponseItem(T message, AgentThread thread) { + this.message = message; + this.thread = thread; + } + + /** + * Gets the agent response message. + * + * @return The message. + */ + public T getMessage() { + return message; + } + + /** + * Gets the thread. + * + * @return The thread. + */ + @SuppressFBWarnings("EI_EXPOSE_REP") + public AgentThread getThread() { + return thread; + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentThread.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentThread.java new file mode 100644 index 000000000..94538f41a --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/AgentThread.java @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; +import reactor.core.publisher.Mono; + +/** + * Interface for an agent thread. + */ +public interface AgentThread { + /** + * Get the thread ID. + * + * @return The thread ID. + */ + String getId(); + + /** + * Create a new thread. + * + * @return A Mono containing the thread ID. + */ + Mono createAsync(); + + /** + * Delete the thread. + * + * @return A Mono indicating completion. + */ + Mono deleteAsync(); + + /** + * Check if the thread is deleted. + * + * @return A Mono containing true if the thread is deleted, false otherwise. + */ + boolean isDeleted(); + + /** + * Create a copy of the thread. + * + * @return A new instance of the thread. + */ + AgentThread copy(); + + /** + * Handle a new message in the thread. + * + * @param newMessage The new message to handle. + * @return A Mono indicating completion. + */ + Mono onNewMessageAsync(ChatMessageContent newMessage); +} \ No newline at end of file diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/BaseAgentThread.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/BaseAgentThread.java new file mode 100644 index 000000000..c66fe9b90 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/BaseAgentThread.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +public abstract class BaseAgentThread implements AgentThread { + + protected String id; + protected boolean isDeleted; + + public BaseAgentThread() { + } + + public BaseAgentThread(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + @Override + public boolean isDeleted() { + return isDeleted; + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/KernelAgent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/KernelAgent.java new file mode 100644 index 000000000..8403093eb --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/agents/KernelAgent.java @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.agents; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.InvocationReturnMode; +import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Supplier; + +public abstract class KernelAgent implements Agent { + + protected final String id; + protected final String name; + protected final String description; + protected final Kernel kernel; + protected final KernelArguments kernelArguments; + protected final InvocationContext invocationContext; + protected final String instructions; + protected final PromptTemplate template; + + protected KernelAgent( + String id, + String name, + String description, + Kernel kernel, + KernelArguments kernelArguments, + InvocationContext invocationContext, + String instructions, + PromptTemplate template) { + this.id = id != null ? id : UUID.randomUUID().toString(); + this.name = name; + this.description = description; + this.kernel = kernel; + this.kernelArguments = kernelArguments != null + ? kernelArguments.copy() + : KernelArguments.builder().build(); + this.invocationContext = invocationContext != null + ? invocationContext + : InvocationContext.builder().build(); + this.instructions = instructions; + this.template = template; + } + + /** + * Gets the agent's ID. + * + * @return The agent's ID + */ + public String getId() { + return id; + } + + /** + * Gets the agent's name. + * + * @return The agent's name + */ + public String getName() { + return name; + } + + /** + * Gets the agent's description. + * + * @return The agent's description + */ + public String getDescription() { + return description; + } + + /** + * Gets the kernel used by the agent. + * + * @return The kernel used by the agent + */ + public Kernel getKernel() { + return kernel; + } + + /** + * Gets the invocation context used by the agent. + * + * @return The invocation context used by the agent + */ + @SuppressFBWarnings("EI_EXPOSE_REP") + public KernelArguments getKernelArguments() { + return kernelArguments; + } + + /** + * Gets the invocation context used by the agent. + * + * @return The invocation context used by the agent + */ + public String getInstructions() { + return instructions; + } + + /** + * Gets the invocation context used by the agent. + * + * @return The invocation context used by the agent + */ + public PromptTemplate getTemplate() { + return template; + } + + /** + * Merges the provided arguments with the current arguments. + * Provided arguments will override the current arguments. + * + * @param arguments The arguments to merge with the current arguments. + */ + protected KernelArguments mergeArguments(KernelArguments arguments) { + if (arguments == null) { + return kernelArguments; + } + + Map executionSettings = new HashMap<>( + kernelArguments.getExecutionSettings()); + executionSettings.putAll(arguments.getExecutionSettings()); + + return KernelArguments.builder() + .withVariables(kernelArguments) + .withVariables(arguments) + .withExecutionSettings(executionSettings) + .build(); + } + + /** + * Formats the instructions using the provided kernel, arguments, and context. + * + * @param kernel The kernel to use for formatting. + * @param arguments The arguments to use for formatting. + * @param context The context to use for formatting. + * @return A Mono that resolves to the formatted instructions. + */ + protected Mono renderInstructionsAsync(Kernel kernel, KernelArguments arguments, + InvocationContext context) { + if (template != null) { + return template.renderAsync(kernel, arguments, context); + } else { + return Mono.just(instructions); + } + } + + protected Mono ensureThreadExistsWithMessagesAsync( + List> messages, AgentThread thread, Supplier threadSupplier) { + return Mono.defer(() -> { + // Check if the thread already exists + // If it does, we can work with a copy of it + AgentThread newThread = thread == null ? threadSupplier.get() : thread.copy(); + + return newThread.createAsync() + .thenMany(Flux.fromIterable(messages)) + .concatMap(message -> { + return notifyThreadOfNewMessageAsync(newThread, message) + .then(Mono.just(message)); + }) + .then(Mono.just((T) newThread)); + }); + } + + @Override + public Mono>>> invokeAsync( + @Nullable ChatMessageContent message) { + return invokeAsync(message, null, null); + } + + @Override + public Mono>>> invokeAsync( + @Nullable ChatMessageContent message, + @Nullable AgentThread thread) { + return invokeAsync(message, thread, null); + } + + @Override + public Mono>>> invokeAsync( + @Nullable ChatMessageContent message, + @Nullable AgentThread thread, + @Nullable AgentInvokeOptions options) { + ArrayList> messages = new ArrayList<>(); + if (message != null) { + messages.add(message); + } + return invokeAsync(messages, thread, options); + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/AutoFunctionChoiceBehavior.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/AutoFunctionChoiceBehavior.java new file mode 100644 index 000000000..b4993f44c --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/AutoFunctionChoiceBehavior.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.functionchoice; + +import com.microsoft.semantickernel.semanticfunctions.KernelFunction; + +import javax.annotation.Nullable; +import java.util.List; + +/** + * A set of allowed kernel functions. All kernel functions are allowed if allKernelFunctionsAllowed is true. + * Otherwise, only the functions in allowedFunctions are allowed. + *

+ * If a function is allowed, it may be called. If it is not allowed, it will not be called. + */ +public class AutoFunctionChoiceBehavior extends FunctionChoiceBehavior { + private final boolean autoInvoke; + + /** + * Create a new instance of AutoFunctionChoiceBehavior. + * + * @param autoInvoke Whether auto-invocation is enabled. + * @param functions A set of functions to advertise to the model. + * @param options Options for the function choice behavior. + */ + public AutoFunctionChoiceBehavior(boolean autoInvoke, + @Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + super(functions, options); + this.autoInvoke = autoInvoke; + } + + /** + * Check whether the given function is allowed. + * + * @return Whether the function is allowed. + */ + public boolean isAutoInvoke() { + return autoInvoke; + } +} \ No newline at end of file diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehavior.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehavior.java new file mode 100644 index 000000000..f00249524 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehavior.java @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.functionchoice; + +import com.microsoft.semantickernel.semanticfunctions.KernelFunction; + +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Defines the behavior of a tool call. Currently, the only tool available is function calling. + */ +public abstract class FunctionChoiceBehavior { + private final Set fullFunctionNames; + + protected final List> functions; + protected final FunctionChoiceBehaviorOptions options; + + protected FunctionChoiceBehavior(@Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + this.functions = functions != null ? Collections.unmodifiableList(functions) : null; + this.fullFunctionNames = new HashSet<>(); + + if (functions != null) { + functions.stream().filter(Objects::nonNull).forEach( + f -> this.fullFunctionNames + .add(formFullFunctionName(f.getPluginName(), f.getName()))); + } + + if (options != null) { + this.options = options; + } else { + this.options = FunctionChoiceBehaviorOptions.builder().build(); + } + } + + /** + * Gets the functions that are allowed. + * + * @return The functions that are allowed. + */ + public List> getFunctions() { + return Collections.unmodifiableList(functions); + } + + /** + * Gets the options for the function choice behavior. + * + * @return The options for the function choice behavior. + */ + public FunctionChoiceBehaviorOptions getOptions() { + return options; + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides all the Kernel's plugins functions to the AI model to call. + * + * @param autoInvoke Indicates whether the functions should be automatically invoked by AI connectors + * + * @return A new ToolCallBehavior instance with all kernel functions allowed. + */ + public static FunctionChoiceBehavior auto(boolean autoInvoke) { + return new AutoFunctionChoiceBehavior(autoInvoke, null, null); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + * + * @param autoInvoke Enable or disable auto-invocation. + * If auto-invocation is enabled, the model may request that the Semantic Kernel + * invoke the kernel functions and return the value to the model. + * @param functions Functions to provide to the model. If null, all the Kernel's plugins' functions are provided to the model. + * If empty, no functions are provided to the model, which is equivalent to disabling function calling. + * + * @return A new FunctionChoiceBehavior instance with all kernel functions allowed. + */ + public static FunctionChoiceBehavior auto(boolean autoInvoke, + @Nullable List> functions) { + return new AutoFunctionChoiceBehavior(autoInvoke, functions, null); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + * + * @param autoInvoke Enable or disable auto-invocation. + * If auto-invocation is enabled, the model may request that the Semantic Kernel + * invoke the kernel functions and return the value to the model. + * @param functions Functions to provide to the model. If null, all the Kernel's plugins' functions are provided to the model. + * If empty, no functions are provided to the model, which is equivalent to disabling function calling. + * @param options Options for the function choice behavior. + * + * @return A new FunctionChoiceBehavior instance with all kernel functions allowed. + */ + public static FunctionChoiceBehavior auto(boolean autoInvoke, + @Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + return new AutoFunctionChoiceBehavior(autoInvoke, functions, options); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + *

+ * This behavior forces the model to call the provided functions. + * SK connectors will invoke a requested function or multiple requested functions if the model requests multiple ones in one request, + * while handling the first request, and stop advertising the functions for the following requests to prevent the model from repeatedly calling the same function(s). + * + * @return A new FunctionChoiceBehavior instance with the required function. + */ + public static FunctionChoiceBehavior required(boolean autoInvoke, + @Nullable List> functions) { + return new RequiredFunctionChoiceBehavior(autoInvoke, functions, null); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + *

+ * This behavior forces the model to call the provided functions. + * SK connectors will invoke a requested function or multiple requested functions if the model requests multiple ones in one request, + * while handling the first request, and stop advertising the functions for the following requests to prevent the model from repeatedly calling the same function(s). + * + * @param functions Functions to provide to the model. If null, all the Kernel's plugins' functions are provided to the model. + * If empty, no functions are provided to the model, which is equivalent to disabling function calling. + * @return A new FunctionChoiceBehavior instance with the required function. + */ + public static FunctionChoiceBehavior required(boolean autoInvoke, + @Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + return new RequiredFunctionChoiceBehavior(autoInvoke, functions, options); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + *

+ * This behavior is useful if the user should first validate what functions the model will use. + */ + public static FunctionChoiceBehavior none() { + return new NoneFunctionChoiceBehavior(null, null); + } + + /** + * Gets an instance of the FunctionChoiceBehavior that provides either all the Kernel's plugins functions to the AI model to call or specific functions. + *

+ * This behavior is useful if the user should first validate what functions the model will use. + * + * @param functions Functions to provide to the model. If null, all the Kernel's plugins' functions are provided to the model. + * If empty, no functions are provided to the model, which is equivalent to disabling function calling. + */ + public static FunctionChoiceBehavior none(@Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + return new NoneFunctionChoiceBehavior(functions, options); + } + + /** + * The separator between the plugin name and the function name. + */ + public static final String FUNCTION_NAME_SEPARATOR = "-"; + + /** + * Form the full function name. + * + * @param pluginName The name of the plugin that the function is in. + * @param functionName The name of the function. + * @return The key for the function. + */ + public static String formFullFunctionName(@Nullable String pluginName, String functionName) { + if (pluginName == null) { + pluginName = ""; + } + return String.format("%s%s%s", pluginName, FUNCTION_NAME_SEPARATOR, functionName); + } + + /** + * Check whether the given function is allowed. + * + * @param function The function to check. + * @return Whether the function is allowed. + */ + public boolean isFunctionAllowed(KernelFunction function) { + return isFunctionAllowed(function.getPluginName(), function.getName()); + } + + /** + * Check whether the given function is allowed. + * + * @param pluginName The name of the plugin that the function is in. + * @param functionName The name of the function. + * @return Whether the function is allowed. + */ + public boolean isFunctionAllowed(@Nullable String pluginName, String functionName) { + // If no functions are provided, all functions are allowed. + if (functions == null || functions.isEmpty()) { + return true; + } + + String key = formFullFunctionName(pluginName, functionName); + return fullFunctionNames.contains(key); + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehaviorOptions.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehaviorOptions.java new file mode 100644 index 000000000..ffb17c780 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/FunctionChoiceBehaviorOptions.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.functionchoice; + +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; + +public class FunctionChoiceBehaviorOptions { + private final boolean parallelCallsAllowed; + + private FunctionChoiceBehaviorOptions(boolean parallelCallsAllowed) { + this.parallelCallsAllowed = parallelCallsAllowed; + } + + /** + * Returns a new builder for {@link FunctionChoiceBehaviorOptions}. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Indicates whether parallel calls to functions are allowed. + * + * @return True if parallel calls are allowed; otherwise, false. + */ + public boolean isParallelCallsAllowed() { + return parallelCallsAllowed; + } + + /** + * Builder for {@link FunctionChoiceBehaviorOptions}. + */ + public static class Builder implements SemanticKernelBuilder { + private boolean allowParallelCalls = false; + + /** + * Sets whether parallel calls to functions are allowed. + * + * @param allowParallelCalls True if parallel calls are allowed; otherwise, false. + * @return The builder instance. + */ + public Builder withParallelCallsAllowed(boolean allowParallelCalls) { + this.allowParallelCalls = allowParallelCalls; + return this; + } + + public FunctionChoiceBehaviorOptions build() { + return new FunctionChoiceBehaviorOptions(allowParallelCalls); + } + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/NoneFunctionChoiceBehavior.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/NoneFunctionChoiceBehavior.java new file mode 100644 index 000000000..f0d247d36 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/NoneFunctionChoiceBehavior.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.functionchoice; + +import com.microsoft.semantickernel.semanticfunctions.KernelFunction; + +import javax.annotation.Nullable; +import java.util.List; + +public class NoneFunctionChoiceBehavior extends FunctionChoiceBehavior { + + /** + * Create a new instance of NoneFunctionChoiceBehavior. + */ + public NoneFunctionChoiceBehavior(@Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + super(functions, options); + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/RequiredFunctionChoiceBehavior.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/RequiredFunctionChoiceBehavior.java new file mode 100644 index 000000000..ac1ae2bfe --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/functionchoice/RequiredFunctionChoiceBehavior.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.functionchoice; + +import com.microsoft.semantickernel.semanticfunctions.KernelFunction; + +import javax.annotation.Nullable; +import java.util.List; + +public class RequiredFunctionChoiceBehavior extends AutoFunctionChoiceBehavior { + + /** + * Create a new instance of RequiredFunctionChoiceBehavior. + * + * @param autoInvoke Whether auto-invocation is enabled. + * @param functions A set of functions to advertise to the model. + * @param options Options for the function choice behavior. + */ + public RequiredFunctionChoiceBehavior(boolean autoInvoke, + @Nullable List> functions, + @Nullable FunctionChoiceBehaviorOptions options) { + super(autoInvoke, functions, options); + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java index 8f2d7eed8..7a39cdfe8 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java @@ -3,7 +3,7 @@ import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.annotation.Nullable; @@ -16,7 +16,7 @@ public class FunctionInvokedEvent implements KernelHookEvent { private final KernelFunction function; @Nullable - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; private final FunctionResult result; /** @@ -28,10 +28,10 @@ public class FunctionInvokedEvent implements KernelHookEvent { */ public FunctionInvokedEvent( KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, FunctionResult result) { this.function = function; - this.arguments = KernelFunctionArguments.builder().withVariables(arguments).build(); + this.arguments = KernelArguments.builder().withVariables(arguments).build(); this.result = result; } @@ -51,7 +51,7 @@ public KernelFunction getFunction() { */ @SuppressFBWarnings("EI_EXPOSE_REP") @Nullable - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { return arguments; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java index ab765cabe..ca360a760 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.hooks; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.annotation.Nullable; @@ -16,7 +16,7 @@ public class FunctionInvokingEvent implements KernelHookEvent { private final KernelFunction function; - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; /** * Creates a new instance of the FunctionInvokingEvent class. @@ -25,9 +25,9 @@ public class FunctionInvokingEvent implements KernelHookEvent { * @param arguments The arguments that are being passed to the function */ public FunctionInvokingEvent(KernelFunction function, - @Nullable KernelFunctionArguments arguments) { + @Nullable KernelArguments arguments) { this.function = function; - this.arguments = KernelFunctionArguments.builder().withVariables(arguments).build(); + this.arguments = KernelArguments.builder().withVariables(arguments).build(); } /** @@ -45,7 +45,7 @@ public KernelFunction getFunction() { * @return the arguments */ @SuppressFBWarnings("EI_EXPOSE_REP") - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { return arguments; } } \ No newline at end of file diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java index c991efca1..42430f085 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java @@ -3,7 +3,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.annotation.Nullable; @@ -15,7 +15,7 @@ public class PreToolCallEvent implements KernelHookEvent { private final ContextVariableTypes contextVariableTypes; private final String functionName; @Nullable - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; private final KernelFunction function; /** @@ -29,7 +29,7 @@ public class PreToolCallEvent implements KernelHookEvent { @SuppressFBWarnings("EI_EXPOSE_REP2") public PreToolCallEvent( String functionName, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, KernelFunction function, ContextVariableTypes contextVariableTypes) { this.functionName = functionName; @@ -44,7 +44,7 @@ public PreToolCallEvent( */ @SuppressFBWarnings("EI_EXPOSE_REP") @Nullable - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { return arguments; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java index f3f349725..348d3bf12 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.hooks; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.annotation.Nullable; @@ -12,7 +12,7 @@ public class PromptRenderedEvent implements KernelHookEvent { private final KernelFunction function; - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; private final String prompt; /** @@ -24,10 +24,10 @@ public class PromptRenderedEvent implements KernelHookEvent { */ public PromptRenderedEvent( KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, String prompt) { this.function = function; - this.arguments = KernelFunctionArguments.builder().withVariables(arguments).build(); + this.arguments = KernelArguments.builder().withVariables(arguments).build(); this.prompt = prompt; } @@ -46,7 +46,7 @@ public KernelFunction getFunction() { * @return the arguments */ @SuppressFBWarnings("EI_EXPOSE_REP") - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { return arguments; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java index 7bba17a38..fe9c54459 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.hooks; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.annotation.Nullable; @@ -12,7 +12,7 @@ public class PromptRenderingEvent implements KernelHookEvent { private final KernelFunction function; - private final KernelFunctionArguments arguments; + private final KernelArguments arguments; /** * Creates a new instance of the {@link PromptRenderingEvent} class. @@ -21,9 +21,9 @@ public class PromptRenderingEvent implements KernelHookEvent { * @param arguments the arguments */ public PromptRenderingEvent(KernelFunction function, - @Nullable KernelFunctionArguments arguments) { + @Nullable KernelArguments arguments) { this.function = function; - this.arguments = KernelFunctionArguments.builder().withVariables(arguments).build(); + this.arguments = KernelArguments.builder().withVariables(arguments).build(); } /** @@ -41,7 +41,7 @@ public KernelFunction getFunction() { * @return the arguments */ @SuppressFBWarnings("EI_EXPOSE_REP") - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { return arguments; } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/ChatCompletionSpan.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/ChatCompletionSpan.java index 87945860a..9fa465ed9 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/ChatCompletionSpan.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/ChatCompletionSpan.java @@ -104,8 +104,8 @@ public void endSpanWithUsage(ChatCompletions chatCompletions) { CompletionsUsage usage = chatCompletions.getUsage(); getSpan().setStatus(StatusCode.OK); getSpan() - .setAttribute("gen_ai.response.completion_tokens", usage.getCompletionTokens()); - getSpan().setAttribute("gen_ai.response.prompt_tokens", usage.getPromptTokens()); + .setAttribute("gen_ai.usage.output_tokens", usage.getCompletionTokens()); + getSpan().setAttribute("gen_ai.usage.input_tokens", usage.getPromptTokens()); close(); } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/FunctionSpan.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/FunctionSpan.java index 601b41305..72cc02609 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/FunctionSpan.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/FunctionSpan.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.implementation.telemetry; import com.microsoft.semantickernel.orchestration.FunctionResult; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanKind; @@ -27,7 +27,7 @@ public static FunctionSpan build( ContextView contextView, String pluginName, String name, - KernelFunctionArguments arguments) { + KernelArguments arguments) { SpanBuilder builder = telemetry.spanBuilder( String.format("function_invocation %s-%s", pluginName, name)) diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java index d0b70083a..15b80a662 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks.VarBlock; import com.microsoft.semantickernel.orchestration.InvocationContext; import com.microsoft.semantickernel.semanticfunctions.InputVariable; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException; @@ -137,7 +137,7 @@ private static PromptTemplateConfig addMissingInputVariables( @Override public Mono renderAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable InvocationContext context) { ContextVariableTypes types; diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java index e294c9251..cd6fffaad 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java @@ -9,7 +9,7 @@ import com.microsoft.semantickernel.localization.SemanticKernelResources; import com.microsoft.semantickernel.orchestration.FunctionResult; import com.microsoft.semantickernel.orchestration.InvocationContext; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.KernelFunctionMetadata; import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException; import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException.ErrorCodes; @@ -97,7 +97,7 @@ private boolean isValidFunctionCall() { @Override public Mono renderCodeAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable InvocationContext context) { if (!this.isValid()) { throw new TemplateException(ErrorCodes.SYNTAX_ERROR); @@ -136,7 +136,7 @@ public Mono renderCodeAsync( private Mono> renderFunctionCallAsync( FunctionIdBlock fBlock, Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, InvocationContext context, ContextVariableType resultType) { @@ -145,7 +145,7 @@ private Mono> renderFunctionCallAsync( 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, - KernelFunctionArguments.builder().withVariables(arguments).build(), + KernelArguments.builder().withVariables(arguments).build(), context); } @@ -168,10 +168,10 @@ private Mono> renderFunctionCallAsync( /// The prompt rendering arguments. /// The function arguments. /// Occurs when any argument other than the first is not a named argument. - private KernelFunctionArguments enrichFunctionArguments( + private KernelArguments enrichFunctionArguments( Kernel kernel, FunctionIdBlock fBlock, - KernelFunctionArguments arguments, + KernelArguments arguments, @Nullable InvocationContext context) { Block firstArg = this.tokens.get(1); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java index 7a411a095..673bcf68a 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java @@ -3,7 +3,7 @@ import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.orchestration.InvocationContext; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; import reactor.core.publisher.Mono; @@ -24,6 +24,6 @@ public interface CodeRendering { */ Mono renderCodeAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable InvocationContext context); } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java index 58f8f5346..69e5a63be 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; /** @@ -49,7 +49,7 @@ private static boolean hasMoreThanOneDot(String value) { @Override @Nullable - public String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables) { + public String render(ContextVariableTypes types, @Nullable KernelArguments variables) { return this.getContent(); } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java index 010ba44e1..bed795020 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java @@ -7,7 +7,7 @@ import com.microsoft.semantickernel.exceptions.SKException; import com.microsoft.semantickernel.implementation.Verify; import com.microsoft.semantickernel.localization.SemanticKernelResources; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -132,7 +132,7 @@ public boolean isValid() { } @Override - public String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables) { + public String render(ContextVariableTypes types, @Nullable KernelArguments variables) { return getContent(); } @@ -155,7 +155,7 @@ public String getName() { } @SuppressWarnings("NullAway") - public String getValue(ContextVariableTypes types, KernelFunctionArguments arguments) { + public String getValue(ContextVariableTypes types, KernelArguments arguments) { boolean valueIsValidValBlock = this.valBlock != null && this.valBlock.isValid(); if (valueIsValidValBlock) { return this.valBlock.render(types, arguments); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java index 3b7d1c09c..38128538e 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; public final class TextBlock extends Block implements TextRendering { @@ -21,7 +21,7 @@ public boolean isValid() { } @Override - public String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables) { + public String render(ContextVariableTypes types, @Nullable KernelArguments variables) { return super.getContent(); } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java index 751190742..184b4ca45 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; /** @@ -17,5 +17,5 @@ public interface TextRendering { * @return Rendered content */ @Nullable - String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables); + String render(ContextVariableTypes types, @Nullable KernelArguments variables); } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java index 3d647840f..d81c84b9a 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java @@ -3,7 +3,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.localization.SemanticKernelResources; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.util.annotation.Nullable; @@ -41,7 +41,7 @@ public static boolean hasValPrefix(@Nullable String text) { @Override @Nullable - public String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables) { + public String render(ContextVariableTypes types, @Nullable KernelArguments variables) { return value; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java index 1aec228c3..5ae70bb32 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java @@ -4,7 +4,7 @@ import com.microsoft.semantickernel.contextvariables.ContextVariable; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.localization.SemanticKernelResources; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException; import javax.annotation.Nullable; import org.slf4j.Logger; @@ -26,7 +26,7 @@ public VarBlock(String content) { } @Override - public String render(ContextVariableTypes types, @Nullable KernelFunctionArguments variables) { + public String render(ContextVariableTypes types, @Nullable KernelArguments variables) { if (variables == null) { return ""; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java index 435d8538f..9b8a518c3 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java @@ -8,13 +8,14 @@ import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; import com.microsoft.semantickernel.contextvariables.converters.ContextVariableJacksonConverter; import com.microsoft.semantickernel.exceptions.SKException; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior; import com.microsoft.semantickernel.hooks.KernelHook; import com.microsoft.semantickernel.hooks.KernelHooks; import com.microsoft.semantickernel.hooks.KernelHooks.UnmodifiableKernelHooks; import com.microsoft.semantickernel.implementation.telemetry.SemanticKernelTelemetry; import com.microsoft.semantickernel.localization.SemanticKernelResources; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.NoSuchElementException; import java.util.function.BiConsumer; @@ -41,13 +42,16 @@ public class FunctionInvocation extends Mono> { protected final ContextVariableType resultType; protected final ContextVariableTypes contextVariableTypes = new ContextVariableTypes(); @Nullable - protected KernelFunctionArguments arguments; + protected KernelArguments arguments; @Nullable protected UnmodifiableKernelHooks hooks; @Nullable protected PromptExecutionSettings promptExecutionSettings; @Nullable protected ToolCallBehavior toolCallBehavior; + @Nullable + protected FunctionChoiceBehavior functionChoiceBehavior; + @Nullable protected SemanticKernelTelemetry telemetry; @@ -95,7 +99,7 @@ private static void performSubscribe( CoreSubscriber> coreSubscriber, Kernel kernel, KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext context) { if (variableType == null) { @@ -111,7 +115,7 @@ private static void performSubscribe( function .invokeAsync( kernel, - KernelFunctionArguments + KernelArguments .builder() .withVariables(arguments) .build(), @@ -174,9 +178,9 @@ private static UnmodifiableKernelHooks unmodifiableClone( * @return this {@code FunctionInvocation} for fluent chaining. */ public FunctionInvocation withArguments( - @Nullable KernelFunctionArguments arguments) { + @Nullable KernelArguments arguments) { logSubscribeWarning(); - this.arguments = KernelFunctionArguments.builder().withVariables(arguments).build(); + this.arguments = KernelArguments.builder().withVariables(arguments).build(); return this; } @@ -196,6 +200,7 @@ public FunctionInvocation withResultType(ContextVariableType resultTyp .withArguments(arguments) .addKernelHooks(hooks) .withPromptExecutionSettings(promptExecutionSettings) + .withFunctionChoiceBehavior(functionChoiceBehavior) .withToolCallBehavior(toolCallBehavior) .withTypes(contextVariableTypes); } @@ -287,10 +292,32 @@ public FunctionInvocation withPromptExecutionSettings( */ public FunctionInvocation withToolCallBehavior(@Nullable ToolCallBehavior toolCallBehavior) { logSubscribeWarning(); + if (toolCallBehavior != null && functionChoiceBehavior != null) { + throw new SKException( + "ToolCallBehavior cannot be set when FunctionChoiceBehavior is set."); + } this.toolCallBehavior = toolCallBehavior; return this; } + /** + * Supply function choice behavior to the function invocation. + * + * @param functionChoiceBehavior The function choice behavior to supply to the function + * invocation. + * @return this {@code FunctionInvocation} for fluent chaining. + */ + public FunctionInvocation withFunctionChoiceBehavior( + @Nullable FunctionChoiceBehavior functionChoiceBehavior) { + if (functionChoiceBehavior != null && toolCallBehavior != null) { + throw new SKException( + "FunctionChoiceBehavior cannot be set when ToolCallBehavior is set."); + } + logSubscribeWarning(); + this.functionChoiceBehavior = functionChoiceBehavior; + return this; + } + /** * Supply a type converter to the function invocation. * @@ -340,6 +367,7 @@ public FunctionInvocation withInvocationContext( } logSubscribeWarning(); withTypes(invocationContext.getContextVariableTypes()); + withFunctionChoiceBehavior(invocationContext.getFunctionChoiceBehavior()); withToolCallBehavior(invocationContext.getToolCallBehavior()); withPromptExecutionSettings(invocationContext.getPromptExecutionSettings()); addKernelHooks(invocationContext.getKernelHooks()); @@ -387,6 +415,7 @@ public void subscribe(CoreSubscriber> coreSubscriber) hooks, promptExecutionSettings, toolCallBehavior, + functionChoiceBehavior, contextVariableTypes, InvocationReturnMode.NEW_MESSAGES_ONLY, telemetry)); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java index 6fd3f0d21..6a8547c43 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java @@ -4,6 +4,8 @@ import com.microsoft.semantickernel.builders.SemanticKernelBuilder; import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; +import com.microsoft.semantickernel.exceptions.SKException; +import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior; import com.microsoft.semantickernel.hooks.KernelHooks; import com.microsoft.semantickernel.hooks.KernelHooks.UnmodifiableKernelHooks; import com.microsoft.semantickernel.implementation.telemetry.SemanticKernelTelemetry; @@ -23,6 +25,8 @@ public class InvocationContext { private final PromptExecutionSettings promptExecutionSettings; @Nullable private final ToolCallBehavior toolCallBehavior; + @Nullable + private final FunctionChoiceBehavior functionChoiceBehavior; private final ContextVariableTypes contextVariableTypes; private final InvocationReturnMode invocationReturnMode; private final SemanticKernelTelemetry telemetry; @@ -39,12 +43,14 @@ protected InvocationContext( @Nullable KernelHooks hooks, @Nullable PromptExecutionSettings promptExecutionSettings, @Nullable ToolCallBehavior toolCallBehavior, + @Nullable FunctionChoiceBehavior functionChoiceBehavior, @Nullable ContextVariableTypes contextVariableTypes, InvocationReturnMode invocationReturnMode, SemanticKernelTelemetry telemetry) { this.hooks = unmodifiableClone(hooks); this.promptExecutionSettings = promptExecutionSettings; this.toolCallBehavior = toolCallBehavior; + this.functionChoiceBehavior = functionChoiceBehavior; this.invocationReturnMode = invocationReturnMode; if (contextVariableTypes == null) { this.contextVariableTypes = new ContextVariableTypes(); @@ -61,6 +67,7 @@ protected InvocationContext() { this.hooks = null; this.promptExecutionSettings = null; this.toolCallBehavior = null; + this.functionChoiceBehavior = null; this.contextVariableTypes = new ContextVariableTypes(); this.invocationReturnMode = InvocationReturnMode.NEW_MESSAGES_ONLY; this.telemetry = null; @@ -76,6 +83,7 @@ protected InvocationContext(@Nullable InvocationContext context) { this.hooks = null; this.promptExecutionSettings = null; this.toolCallBehavior = null; + this.functionChoiceBehavior = null; this.contextVariableTypes = new ContextVariableTypes(); this.invocationReturnMode = InvocationReturnMode.NEW_MESSAGES_ONLY; this.telemetry = null; @@ -83,6 +91,7 @@ protected InvocationContext(@Nullable InvocationContext context) { this.hooks = context.hooks; this.promptExecutionSettings = context.promptExecutionSettings; this.toolCallBehavior = context.toolCallBehavior; + this.functionChoiceBehavior = context.functionChoiceBehavior; this.contextVariableTypes = context.contextVariableTypes; this.invocationReturnMode = context.invocationReturnMode; this.telemetry = context.telemetry; @@ -156,6 +165,16 @@ public ToolCallBehavior getToolCallBehavior() { return toolCallBehavior; } + /** + * Get the behavior for function choice. + * + * @return The behavior for function choice. + */ + @Nullable + public FunctionChoiceBehavior getFunctionChoiceBehavior() { + return functionChoiceBehavior; + } + /** * Get the types of context variables. * @@ -190,6 +209,8 @@ public static class Builder implements SemanticKernelBuilder private PromptExecutionSettings promptExecutionSettings; @Nullable private ToolCallBehavior toolCallBehavior; + @Nullable + private FunctionChoiceBehavior functionChoiceBehavior; private InvocationReturnMode invocationReturnMode = InvocationReturnMode.NEW_MESSAGES_ONLY; @Nullable private SemanticKernelTelemetry telemetry; @@ -226,10 +247,30 @@ public Builder withPromptExecutionSettings( */ public Builder withToolCallBehavior( @Nullable ToolCallBehavior toolCallBehavior) { + if (toolCallBehavior != null && functionChoiceBehavior != null) { + throw new SKException( + "ToolCallBehavior cannot be set when FunctionChoiceBehavior is set."); + } this.toolCallBehavior = toolCallBehavior; return this; } + /** + * Add function choice behavior to the builder. + * + * @param functionChoiceBehavior the behavior to add. + * @return this {@link Builder} + */ + public Builder withFunctionChoiceBehavior( + @Nullable FunctionChoiceBehavior functionChoiceBehavior) { + if (functionChoiceBehavior != null && toolCallBehavior != null) { + throw new SKException( + "FunctionChoiceBehavior cannot be set when ToolCallBehavior is set."); + } + this.functionChoiceBehavior = functionChoiceBehavior; + return this; + } + /** * Add a context variable type converter to the builder. * @@ -269,7 +310,7 @@ public Builder withReturnMode(InvocationReturnMode invocationReturnMode) { /** * Add a tracer to the builder. * - * @param tracer the tracer to add. + * @param telemetry the tracer to add. * @return this {@link Builder} */ public Builder withTelemetry(@Nullable SemanticKernelTelemetry telemetry) { @@ -283,6 +324,7 @@ public InvocationContext build() { telemetry = new SemanticKernelTelemetry(); } return new InvocationContext(hooks, promptExecutionSettings, toolCallBehavior, + functionChoiceBehavior, contextVariableTypes, invocationReturnMode, telemetry); } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java new file mode 100644 index 000000000..bf9e65658 --- /dev/null +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java @@ -0,0 +1,427 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.semanticfunctions; + +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.contextvariables.CaseInsensitiveMap; +import com.microsoft.semantickernel.contextvariables.ContextVariable; +import com.microsoft.semantickernel.contextvariables.ContextVariableType; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypes; +import com.microsoft.semantickernel.exceptions.SKException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; +import reactor.util.annotation.NonNull; + +/** + * Arguments to a kernel function. + */ +public class KernelArguments implements Map> { + + /** + * Default key for the main input. + */ + public static final String MAIN_KEY = "input"; + + protected final CaseInsensitiveMap> variables; + protected final Map executionSettings; + + /** + * Create a new instance of KernelArguments. + * + * @param variables The variables to use for the function invocation. + */ + protected KernelArguments( + @Nullable Map> variables, + @Nullable Map executionSettings) { + if (variables == null) { + this.variables = new CaseInsensitiveMap<>(); + } else { + this.variables = new CaseInsensitiveMap<>(variables); + } + + if (executionSettings == null) { + this.executionSettings = new HashMap<>(); + } else { + this.executionSettings = new HashMap<>(executionSettings); + } + } + + /** + * Create a new instance of KernelArguments. + * + * @param content The content to use for the function invocation. + */ + protected KernelArguments(@NonNull ContextVariable content) { + this(); + this.variables.put(MAIN_KEY, content); + } + + /** + * Create a new instance of KernelArguments. + */ + protected KernelArguments() { + this.variables = new CaseInsensitiveMap<>(); + this.executionSettings = new HashMap<>(); + } + + /** + * Create a new instance of KernelArguments. + * + * @param arguments The arguments to copy. + */ + protected KernelArguments(@NonNull KernelArguments arguments) { + this.variables = new CaseInsensitiveMap<>(arguments.variables); + this.executionSettings = new HashMap<>(arguments.executionSettings); + } + + /** + * Get the prompt execution settings + * + * @return prompt execution settings + */ + @Nonnull + public Map getExecutionSettings() { + return Collections.unmodifiableMap(executionSettings); + } + + /** + * Get the input (entry in the MAIN_KEY slot) + * + * @return input + */ + @Nullable + public ContextVariable getInput() { + return get(MAIN_KEY); + } + + /** + * Create formatted string of the variables + * + * @return formatted string + */ + public String prettyPrint() { + return variables.entrySet().stream() + .reduce( + "", + (str, entry) -> str + + System.lineSeparator() + + entry.getKey() + + ": " + + entry.getValue().toPromptString(ContextVariableTypes.getGlobalTypes()), + (a, b) -> a + b); + } + + /** + * Return the variable with the given name + * + * @param key variable name + * @return content of the variable + */ + @Nullable + public ContextVariable get(String key) { + return variables.get(key); + } + + /** + * Return the variable with the given name + * + * @param key variable name + * @return content of the variable + */ + @Nullable + ContextVariable get(String key, Class clazz) { + ContextVariable value = variables.get(key); + if (value == null) { + return null; + } else if (clazz.isAssignableFrom(value.getType().getClazz())) { + return (ContextVariable) value; + } + + throw new SKException( + String.format( + "Variable %s is of type %s, but requested type is %s", + key, value.getType().getClazz(), clazz)); + } + + /** + * Return whether the variable with the given name is {@code null} or empty. + * + * @param key the key for the variable + * @return {@code true} if the variable is {@code null} or empty, {@code false} otherwise + */ + public boolean isNullOrEmpty(String key) { + return get(key) == null || get(key).isEmpty(); + } + + @Override + public int size() { + return variables.size(); + } + + @Override + public boolean isEmpty() { + return variables.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return variables.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return variables.containsValue(value); + } + + @Override + @Nullable + public ContextVariable get(Object key) { + return variables.get(key); + } + + @Override + public ContextVariable put(String key, ContextVariable value) { + return variables.put(key, value); + } + + @Override + public ContextVariable remove(Object key) { + return variables.remove(key); + } + + @Override + public void putAll(Map> m) { + variables.putAll(m); + } + + @Override + public void clear() { + variables.clear(); + } + + @Override + public Set keySet() { + return variables.keySet(); + } + + @Override + public Collection> values() { + return variables.values(); + } + + @Override + public Set>> entrySet() { + return variables.entrySet(); + } + + /** + * Create a copy of the current instance + * + * @return copy of the current instance + */ + public KernelArguments copy() { + return new KernelArguments(variables, executionSettings); + } + + /** + * Create a new instance of Builder. + * + * @return Builder + */ + public static Builder builder() { + return new Builder<>(KernelArguments::new); + } + + /** + * Builder for ContextVariables + */ + public static class Builder implements SemanticKernelBuilder { + + private final Function constructor; + private final Map> variables; + private final Map executionSettings; + + protected Builder(Function constructor) { + this.constructor = constructor; + this.variables = new HashMap<>(); + this.executionSettings = new HashMap<>(); + } + + /** + * Builds an instance with the given content in the default main key + * + * @param content Entry to place in the "input" slot + * @param Type of the value + * @return {$code this} Builder for fluent coding + */ + public Builder withInput(ContextVariable content) { + return withVariable(MAIN_KEY, content); + } + + /** + * Builds an instance with the given content in the default main key + * + * @param content Entry to place in the "input" slot + * @return {$code this} Builder for fluent coding + * @throws SKException if the content cannot be converted to a ContextVariable + */ + public Builder withInput(Object 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 + * @param Type of the value + * @return {$code this} Builder for fluent coding + * @throws SKException if the content cannot be converted to a ContextVariable + */ + public Builder withInput(T content, ContextVariableTypeConverter typeConverter) { + return withInput(new ContextVariable<>( + new ContextVariableType<>( + typeConverter, + typeConverter.getType()), + content)); + } + + /** + * Builds an instance with the given variables + * + * @param map Existing variables + * @return {$code this} Builder for fluent coding + */ + public Builder withVariables(@Nullable Map> map) { + if (map == null) { + return this; + } + variables.putAll(map); + return this; + } + + /** + * Set variable + * + * @param key variable name + * @param value variable value + * @param Type of the value + * @return {$code this} Builder for fluent coding + */ + public Builder withVariable(String key, ContextVariable value) { + variables.put(key, value); + return this; + } + + /** + * Set variable, uses the default type converters + * + * @param key variable name + * @param value variable value + * @return {$code this} Builder for fluent coding + * @throws SKException if the value cannot be converted to a ContextVariable + */ + public Builder withVariable(String key, Object value) { + if (value instanceof ContextVariable) { + return withVariable(key, (ContextVariable) value); + } + return withVariable(key, ContextVariable.ofGlobalType(value)); + } + + /** + * Set variable + * + * @param key variable name + * @param value variable value + * @param typeConverter Type converter for the value + * @param Type of the value + * @return {$code this} Builder for fluent coding + * @throws SKException if the value cannot be converted to a ContextVariable + */ + public Builder withVariable(String key, T value, + ContextVariableTypeConverter typeConverter) { + return withVariable(key, new ContextVariable<>( + new ContextVariableType<>( + typeConverter, + typeConverter.getType()), + value)); + } + + /** + * Set prompt execution settings + * + * @param executionSettings Execution settings + * @return {$code this} Builder for fluent coding + */ + public Builder withExecutionSettings(PromptExecutionSettings executionSettings) { + return withExecutionSettings(Collections.singletonList(executionSettings)); + } + + /** + * Set prompt execution settings + * + * @param executionSettings Execution settings + * @return {$code this} Builder for fluent coding + */ + public Builder withExecutionSettings( + Map executionSettings) { + if (executionSettings == null) { + return this; + } + + this.executionSettings.putAll(executionSettings); + return this; + } + + /** + * Set prompt execution settings + * + * @param executionSettings Execution settings + * @return {$code this} Builder for fluent coding + */ + public Builder withExecutionSettings(List executionSettings) { + if (executionSettings == null) { + return this; + } + + for (PromptExecutionSettings settings : executionSettings) { + String serviceId = settings.getServiceId(); + + if (this.executionSettings.containsKey(serviceId)) { + if (serviceId.equals(PromptExecutionSettings.DEFAULT_SERVICE_ID)) { + throw new SKException( + String.format( + "Multiple prompt execution settings with the default service id '%s' or no service id have been provided. Specify a single default prompt execution settings and provide a unique service id for all other instances.", + PromptExecutionSettings.DEFAULT_SERVICE_ID)); + } + + throw new SKException( + String.format( + "Multiple prompt execution settings with the service id '%s' have been provided. Specify a unique service id for all instances.", + serviceId)); + } + + this.executionSettings.put(serviceId, settings); + } + + return this; + } + + @Override + public U build() { + KernelArguments arguments = new KernelArguments(variables, executionSettings); + return constructor.apply(arguments); + } + } +} diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java index 70f33bd75..742e84572 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java @@ -189,7 +189,7 @@ public KernelFunctionMetadata getMetadata() { */ public abstract Mono> invokeAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext); @@ -221,7 +221,7 @@ public abstract Mono> invokeAsync( */ public FunctionResult invoke( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext) { return invokeAsync(kernel, arguments, variableType, invocationContext).block(); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java index f3b46c21a..76936cf23 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java @@ -17,16 +17,17 @@ /** * Arguments to a kernel function. + * + * @deprecated Use {@link KernelArguments} instead. */ -public class KernelFunctionArguments implements Map> { +@Deprecated +public class KernelFunctionArguments extends KernelArguments { /** * Default key for the main input. */ public static final String MAIN_KEY = "input"; - private final CaseInsensitiveMap> variables; - /** * Create a new instance of KernelFunctionArguments. * @@ -34,11 +35,7 @@ public class KernelFunctionArguments implements Map> */ protected KernelFunctionArguments( @Nullable Map> variables) { - if (variables == null) { - this.variables = new CaseInsensitiveMap<>(); - } else { - this.variables = new CaseInsensitiveMap<>(variables); - } + super(variables, null); } /** @@ -47,15 +44,23 @@ protected KernelFunctionArguments( * @param content The content to use for the function invocation. */ protected KernelFunctionArguments(@NonNull ContextVariable content) { - this.variables = new CaseInsensitiveMap<>(); - this.variables.put(MAIN_KEY, content); + super(content); + } + + /** + * Create a new instance of KernelArguments. + * + * @param arguments The arguments to copy. + */ + protected KernelFunctionArguments(@NonNull KernelArguments arguments) { + super(arguments); } /** * Create a new instance of KernelFunctionArguments. */ protected KernelFunctionArguments() { - this.variables = new CaseInsensitiveMap<>(); + super(); } /** @@ -208,121 +213,18 @@ public KernelFunctionArguments copy() { /** * Builder for ContextVariables + * + * @deprecated Use {@link KernelArguments} builder instead. */ - public static class Builder implements SemanticKernelBuilder { - - private final Map> variables; + @Deprecated + public static class Builder extends KernelArguments.Builder { /** * Create a new instance of Builder. */ + @Deprecated public Builder() { - variables = new HashMap<>(); - } - - /** - * Builds an instance with the given content in the default main key - * - * @param content Entry to place in the "input" slot - * @param Type of the value - * @return {$code this} Builder for fluent coding - */ - public Builder withInput(ContextVariable content) { - return withVariable(MAIN_KEY, content); - } - - /** - * Builds an instance with the given content in the default main key - * - * @param content Entry to place in the "input" slot - * @return {$code this} Builder for fluent coding - * @throws SKException if the content cannot be converted to a ContextVariable - */ - public Builder withInput(Object 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 - * @param Type of the value - * @return {$code this} Builder for fluent coding - * @throws SKException if the content cannot be converted to a ContextVariable - */ - public Builder withInput(T content, ContextVariableTypeConverter typeConverter) { - return withInput(new ContextVariable<>( - new ContextVariableType<>( - typeConverter, - typeConverter.getType()), - content)); - } - - /** - * Builds an instance with the given variables - * - * @param map Existing variables - * @return {$code this} Builder for fluent coding - */ - public Builder withVariables(@Nullable Map> map) { - if (map == null) { - return this; - } - variables.putAll(map); - return this; - } - - /** - * Set variable - * - * @param key variable name - * @param value variable value - * @param Type of the value - * @return {$code this} Builder for fluent coding - */ - public Builder withVariable(String key, ContextVariable value) { - variables.put(key, value); - return this; - } - - /** - * Set variable, uses the default type converters - * - * @param key variable name - * @param value variable value - * @return {$code this} Builder for fluent coding - * @throws SKException if the value cannot be converted to a ContextVariable - */ - public Builder withVariable(String key, Object value) { - if (value instanceof ContextVariable) { - return withVariable(key, (ContextVariable) value); - } - return withVariable(key, ContextVariable.ofGlobalType(value)); - } - - /** - * Set variable - * - * @param key variable name - * @param value variable value - * @param typeConverter Type converter for the value - * @param Type of the value - * @return {$code this} Builder for fluent coding - * @throws SKException if the value cannot be converted to a ContextVariable - */ - public Builder withVariable(String key, T value, - ContextVariableTypeConverter typeConverter) { - return withVariable(key, new ContextVariable<>( - new ContextVariableType<>( - typeConverter, - typeConverter.getType()), - value)); - } - - @Override - public KernelFunctionArguments build() { - return new KernelFunctionArguments(variables); + super(KernelFunctionArguments::new); } } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java index afda500ae..6704255ff 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java @@ -176,7 +176,7 @@ public static ImplementationFunc getFunction(Method method, Object instan FunctionInvokingEvent updatedState = kernelHooks .executeHooks( new FunctionInvokingEvent(function, arguments)); - KernelFunctionArguments updatedArguments = updatedState != null + KernelArguments updatedArguments = updatedState != null ? updatedState.getArguments() : arguments; @@ -344,11 +344,11 @@ private static Mono invokeAsyncFunction( @Nullable private static Function getParameters( Method method, - @Nullable KernelFunctionArguments context, + @Nullable KernelArguments context, Kernel kernel, InvocationContext invocationContext) { return parameter -> { - if (KernelFunctionArguments.class.isAssignableFrom(parameter.getType())) { + if (KernelArguments.class.isAssignableFrom(parameter.getType())) { return context; } else if (Kernel.class.isAssignableFrom(parameter.getType())) { return kernel; @@ -361,7 +361,7 @@ private static Function getParameters( @Nullable private static Object getArgumentValue( Method method, - @Nullable KernelFunctionArguments context, + @Nullable KernelArguments context, Parameter parameter, Kernel kernel, InvocationContext invocationContext) { @@ -525,15 +525,15 @@ private static Object toObjectType( @Nullable private static ContextVariable getVariableFromContext( Method method, - @Nullable KernelFunctionArguments context, + @Nullable KernelArguments context, String variableName) { ContextVariable variable = context == null ? null : context.get(variableName); // If there is 1 argument use "input" or the only argument if (variable == null && method.getParameters().length == 1) { if (context != null) { - if (context.containsKey(KernelFunctionArguments.MAIN_KEY)) { - variable = context.get(KernelFunctionArguments.MAIN_KEY); + if (context.containsKey(KernelArguments.MAIN_KEY)) { + variable = context.get(KernelArguments.MAIN_KEY); } else if (context.size() == 1) { variable = context.values().iterator().next(); } @@ -672,7 +672,7 @@ private static InputVariable toKernelParameterMetadata(Parameter parameter) { boolean isRequired = true; Class type = parameter.getType(); - if (Kernel.class.isAssignableFrom(type) || KernelFunctionArguments.class.isAssignableFrom( + if (Kernel.class.isAssignableFrom(type) || KernelArguments.class.isAssignableFrom( type)) { return null; } @@ -729,7 +729,7 @@ public static Builder builder() { @Override public Mono> invokeAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext) { @@ -770,7 +770,7 @@ public interface ImplementationFunc { Mono> invokeAsync( Kernel kernel, KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext); @@ -787,7 +787,7 @@ Mono> invokeAsync( default FunctionResult invoke( Kernel kernel, KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext) { return invokeAsync(kernel, function, arguments, variableType, diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java index 5c2c5412e..642b5addc 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java @@ -98,7 +98,7 @@ public static Builder builder(Class returnType) { private Flux> invokeInternalAsync( Kernel kernel, - @Nullable KernelFunctionArguments argumentsIn, + @Nullable KernelArguments argumentsIn, @Nullable ContextVariableType contextVariableType, @Nullable InvocationContext invocationContext) { @@ -113,7 +113,7 @@ private Flux> invokeInternalAsync( PromptRenderingEvent preRenderingHookResult = kernelHooks .executeHooks(new PromptRenderingEvent(this, argumentsIn)); - KernelFunctionArguments arguments = preRenderingHookResult.getArguments(); + KernelArguments arguments = preRenderingHookResult.getArguments(); // TODO: put in method, add catch for classcastexception, fallback to noopconverter ContextVariableType variableType = contextVariableType != null @@ -127,13 +127,17 @@ private Flux> invokeInternalAsync( PromptRenderedEvent promptHookResult = kernelHooks .executeHooks(new PromptRenderedEvent(this, arguments, prompt)); prompt = promptHookResult.getPrompt(); - KernelFunctionArguments args = promptHookResult.getArguments(); + KernelArguments args = promptHookResult.getArguments(); LOGGER.info(SemanticKernelResources.getString("rendered.prompt"), prompt); - FunctionInvokingEvent updateArguments = kernelHooks + FunctionInvokingEvent invokingEvent = kernelHooks .executeHooks(new FunctionInvokingEvent(this, args)); - args = updateArguments.getArguments(); + + args = KernelArguments.builder() + .withVariables(invokingEvent.getArguments()) + .withExecutionSettings(this.getExecutionSettings()) + .build(); AIServiceSelection aiServiceSelection = kernel .getServiceSelector() @@ -273,7 +277,7 @@ private Flux> invokeInternalAsync( @Override public Mono> invokeAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable ContextVariableType variableType, @Nullable InvocationContext invocationContext) { return Mono.deferContextual(contextView -> { diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java index 04f0c6432..58a5c6a81 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java @@ -24,7 +24,7 @@ public interface PromptTemplate { */ Mono renderAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable InvocationContext context); } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java index 3255d79e0..ac95f7d35 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java @@ -2,7 +2,7 @@ package com.microsoft.semantickernel.services; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import javax.annotation.Nullable; /** @@ -15,12 +15,12 @@ public interface AIServiceSelector { /** * Resolves an {@link AIService} and associated and * {@link com.microsoft.semantickernel.orchestration.PromptExecutionSettings} based on the - * associated {@link KernelFunction} and {@link KernelFunctionArguments}. + * associated {@link KernelFunction} and {@link KernelArguments}. * * @param serviceType The type of service to select. This must be the same type with which the * service was registered in the {@link AIServiceSelection} * @param function The KernelFunction to use to select the service, or {@code null}. - * @param arguments The KernelFunctionArguments to use to select the service, or + * @param arguments The KernelArguments to use to select the service, or * {@code null}. * @param The type of service to select. * @return An {@code AIServiceSelection} containing the selected service and associated @@ -30,5 +30,26 @@ public interface AIServiceSelector { AIServiceSelection trySelectAIService( Class serviceType, @Nullable KernelFunction function, - @Nullable KernelFunctionArguments arguments); + @Nullable KernelArguments arguments); + + /** + * Resolves an {@link AIService} and associated and + * {@link com.microsoft.semantickernel.orchestration.PromptExecutionSettings} based on the + * associated {@link KernelFunction} and {@link KernelArguments}. + * + * @param serviceType The type of service to select. This must be the same type with which the + * service was registered in the {@link AIServiceSelection} + * @param arguments The KernelArguments to use to select the service, or + * {@code null}. + * @param The type of service to select. + * @return An {@code AIServiceSelection} containing the selected service and associated + * PromptExecutionSettings. + */ + @Nullable + default AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments) { + throw new UnsupportedOperationException( + "This method is not implemented."); + } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java index 2eaa9404c..b022bf358 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java @@ -2,16 +2,16 @@ package com.microsoft.semantickernel.services; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import java.util.Map; import javax.annotation.Nullable; /** * Base class for {@link AIServiceSelector} implementations which provides a {@code Map} based * collection from which an {@link AIService} can be selected. The - * {@link #trySelectAIService(Class, KernelFunction, KernelFunctionArguments)} method has been + * {@link #trySelectAIService(Class, KernelFunction, KernelArguments)} method has been * implemented. Child classes must implement the method - * {@link #trySelectAIService(Class, KernelFunction, KernelFunctionArguments, Map)}. + * {@link #trySelectAIService(Class, KernelFunction, KernelArguments, Map)}. */ public abstract class BaseAIServiceSelector implements AIServiceSelector { @@ -31,10 +31,18 @@ protected BaseAIServiceSelector(AIServiceCollection services) { public AIServiceSelection trySelectAIService( Class serviceType, @Nullable KernelFunction function, - @Nullable KernelFunctionArguments arguments) { + @Nullable KernelArguments arguments) { return trySelectAIService(serviceType, function, arguments, services); } + @Override + @Nullable + public AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments) { + return trySelectAIService(serviceType, arguments, services); + } + /** * Resolves an {@link AIService} from the {@code services} argument using the specified * {@code function} and {@code arguments} for selection. @@ -47,11 +55,32 @@ public AIServiceSelection trySelectAIService( * @param services The services to select from. * @param The type of service to select. * @return The selected service, or {@code null} if no service could be selected. + * */ @Nullable protected abstract AIServiceSelection trySelectAIService( Class serviceType, @Nullable KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, Map, AIService> services); + + /** + * Resolves an {@link AIService} from the {@code services} argument using the specified + * {@code function} and {@code arguments} for selection. + * + * @param serviceType The type of service to select. This must be the same type with which the + * service was registered in the {@link AIServiceSelection} + * @param arguments The KernelArguments to use to select the service, or + * {@code null}. + * @param services The services to select from. + * @param The type of service to select. + * @return The selected service, or {@code null} if no service could be selected. + */ + @Nullable + protected AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments, + Map, AIService> services) { + return trySelectAIService(serviceType, null, arguments, services); + } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java index 8e607cdb1..30828233d 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java @@ -5,7 +5,7 @@ import com.microsoft.semantickernel.localization.SemanticKernelResources; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; import com.microsoft.semantickernel.services.textcompletion.TextGenerationService; import java.util.List; @@ -57,26 +57,25 @@ private static AIServiceSelection castServiceSelection( } } - @Nullable - private static Map settingsFromFunctionSettings( - @Nullable KernelFunction function) { - if (function != null) { - return function.getExecutionSettings(); - } - return null; - } - @Nullable @Override public AIServiceSelection trySelectAIService( Class serviceType, @Nullable KernelFunction function, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, Map, AIService> services) { - // Allow the execution settings from the kernel arguments to take precedence - Map executionSettings = settingsFromFunctionSettings( - function); + if (function == null) { + return selectAIService(serviceType, + arguments != null ? arguments.getExecutionSettings() : null); + } + + return selectAIService(serviceType, function.getExecutionSettings()); + } + + private AIServiceSelection selectAIService( + Class serviceType, + @Nullable Map executionSettings) { if (executionSettings == null || executionSettings.isEmpty()) { AIService service = getAnyService(serviceType); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/TextAIService.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/TextAIService.java index 09b3ea1fe..3eee32d36 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/TextAIService.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/TextAIService.java @@ -29,5 +29,5 @@ public interface TextAIService extends AIService { * future and/or made configurable should need arise. *

*/ - int MAXIMUM_INFLIGHT_AUTO_INVOKES = 5; + int MAXIMUM_INFLIGHT_AUTO_INVOKES = 128; } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatHistory.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatHistory.java index 25cd8ea89..df5f18322 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatHistory.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatHistory.java @@ -187,6 +187,13 @@ public ChatHistory addSystemMessage(String content) { return addMessage(AuthorRole.SYSTEM, content); } + /** + * Clear the chat history + */ + public void clear() { + chatMessageContents.clear(); + } + /** * Add all messages to the chat history * @param messages The messages to add to the chat history diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatMessageContent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatMessageContent.java index 9784648b3..e06472d12 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatMessageContent.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/chatcompletion/ChatMessageContent.java @@ -23,7 +23,6 @@ * @param the type of the inner content within the messages */ public class ChatMessageContent extends KernelContentImpl { - private final AuthorRole authorRole; @Nullable private final String content; @@ -52,6 +51,28 @@ public ChatMessageContent( null); } + /** + * Creates a new instance of the {@link ChatMessageContent} class. Defaults to + * {@link ChatMessageContentType#TEXT} content type. + * + * @param authorRole the author role that generated the content + * @param authorName the author name + * @param content the content + */ + public ChatMessageContent( + AuthorRole authorRole, + String authorName, + String content) { + this( + authorRole, + authorName, + content, + null, + null, + null, + null); + } + /** * Creates a new instance of the {@link ChatMessageContent} class. Defaults to * {@link ChatMessageContentType#TEXT} content type. diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java index aed37718d..460e48159 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. package com.microsoft.semantickernel.templateengine.handlebars; -import static com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments.MAIN_KEY; +import static com.microsoft.semantickernel.semanticfunctions.KernelArguments.MAIN_KEY; import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.EscapingStrategy; @@ -19,7 +19,7 @@ import com.microsoft.semantickernel.orchestration.ToolCallBehavior; import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateOption; @@ -59,7 +59,7 @@ public HandlebarsPromptTemplate( @Override public Mono renderAsync( Kernel kernel, - @Nullable KernelFunctionArguments arguments, + @Nullable KernelArguments arguments, @Nullable InvocationContext context) { String template = promptTemplate.getTemplate(); if (template == null) { @@ -75,7 +75,7 @@ public Mono renderAsync( template, context); if (arguments == null) { - arguments = KernelFunctionArguments.builder().build(); + arguments = KernelArguments.builder().build(); } return handler.render(arguments); } @@ -131,8 +131,8 @@ private static class ContextVariableResolver implements ValueResolver { public Object resolve(Object context, String name) { Object value = null; ContextVariable variable = null; - if (context instanceof KernelFunctionArguments) { - variable = ((KernelFunctionArguments) context).get(name); + if (context instanceof KernelArguments) { + variable = ((KernelArguments) context).get(name); } else if (context instanceof ContextVariable) { variable = ((ContextVariable) context); } @@ -174,9 +174,9 @@ private String promptString(ContextVariable context) { @Override public Set> propertySet(Object context) { - if (context instanceof KernelFunctionArguments) { + if (context instanceof KernelArguments) { HashMap result = new HashMap<>(); - result.putAll((KernelFunctionArguments) context); + result.putAll((KernelArguments) context); return result.entrySet(); } else if (context instanceof ContextVariable) { HashMap result = new HashMap<>(); @@ -270,7 +270,7 @@ private CharSequence handleMessage(Object context, Options options) return null; } - public Mono render(KernelFunctionArguments variables) { + public Mono render(KernelArguments variables) { try { ArrayList resolvers = new ArrayList<>(); resolvers.add(new MessageResolver()); @@ -319,9 +319,9 @@ private static Helper functionInvokeHelper( InvocationContext invocationContext) { return (context, options) -> { - KernelFunctionArguments.Builder builder = KernelFunctionArguments.builder(); - if (context instanceof KernelFunctionArguments) { - builder.withVariables((KernelFunctionArguments) context); + KernelArguments.Builder builder = KernelArguments.builder(); + if (context instanceof KernelArguments) { + builder.withVariables((KernelArguments) context); } else { builder.withInput(context); } diff --git a/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java b/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java index 589705f33..a2dae1370 100644 --- a/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java +++ b/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java @@ -52,7 +52,7 @@ void typeConversionOnMethodCall() { .invokeAsync(kernel) .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(String.class)) .withArguments( - KernelFunctionArguments.builder() + KernelArguments.builder() .withVariable("number1", "12.0") .build()) .block(); @@ -182,7 +182,7 @@ interface InvocationTest { Method getMethod() throws NoSuchMethodException; - KernelFunctionArguments getArguments(); + KernelArguments getArguments(); void assertCalled(); } @@ -203,8 +203,8 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { - return KernelFunctionArguments.builder() + public KernelArguments getArguments() { + return KernelArguments.builder() .withVariable("i", 123) .build(); } @@ -232,8 +232,8 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { - return KernelFunctionArguments.builder() + public KernelArguments getArguments() { + return KernelArguments.builder() .withVariable("i", 123) .build(); } @@ -261,8 +261,8 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { - return KernelFunctionArguments.builder() + public KernelArguments getArguments() { + return KernelArguments.builder() .withVariable("i", 123) .build(); } @@ -290,8 +290,8 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { - return KernelFunctionArguments.builder() + public KernelArguments getArguments() { + return KernelArguments.builder() .withVariable("i", Arrays.asList(1, 2, 3)) .build(); } @@ -319,8 +319,8 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { - return KernelFunctionArguments.builder() + public KernelArguments getArguments() { + return KernelArguments.builder() .build(); } @@ -347,7 +347,7 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { ContextVariableTypeConverter dbConverter = ContextVariableTypeConverter .builder(BigDecimal.class) @@ -355,7 +355,7 @@ public KernelFunctionArguments getArguments() { .toPromptString(i -> null) .build(); - return KernelFunctionArguments.builder() + return KernelArguments.builder() .withVariable("i", new BigDecimal(123), dbConverter) .build(); } @@ -401,14 +401,14 @@ public Method getMethod() throws NoSuchMethodException { } @Override - public KernelFunctionArguments getArguments() { + public KernelArguments getArguments() { ContextVariableTypeConverter sourceConverter = ContextVariableTypeConverter .builder(SourceClass.class) .fromObject(i -> (SourceClass) i) .toPromptString(i -> null) .build(); - return KernelFunctionArguments.builder() + return KernelArguments.builder() .withVariable("i", new SourceClass(123), sourceConverter) .build(); } diff --git a/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateFactoryTest.java b/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateFactoryTest.java index f386084e4..67e86d43d 100644 --- a/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateFactoryTest.java +++ b/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateFactoryTest.java @@ -93,7 +93,7 @@ private void executeTest(String templateFormat) throws Exception { PromptTemplate promptTemplate = PromptTemplateFactory.build(config); - KernelFunctionArguments args = KernelFunctionArguments.builder() + KernelArguments args = KernelArguments.builder() .withInput(ContextVariable.of("input from args")).build(); String expected = String.format("A template for testing: %s", diff --git a/semantickernel-api/src/test/java/com/microsoft/semantickernel/services/AIServiceSelectorTest.java b/semantickernel-api/src/test/java/com/microsoft/semantickernel/services/AIServiceSelectorTest.java index f9be46cdd..13ee076f1 100644 --- a/semantickernel-api/src/test/java/com/microsoft/semantickernel/services/AIServiceSelectorTest.java +++ b/semantickernel-api/src/test/java/com/microsoft/semantickernel/services/AIServiceSelectorTest.java @@ -8,7 +8,7 @@ import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.orchestration.PromptExecutionSettings; import com.microsoft.semantickernel.semanticfunctions.KernelFunction; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import org.junit.jupiter.api.Test; @@ -185,7 +185,7 @@ public String getServiceId() { AIServiceSelection expected = new AIServiceSelection<>(aService, null); - KernelFunctionArguments arguments = KernelFunctionArguments.builder().build(); + KernelArguments arguments = KernelArguments.builder().build(); Kernel kernel = Kernel.builder() .withAIService((Class) aService.getClass(), aService) diff --git a/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplateTest.java b/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplateTest.java index 228d64dc7..3a31de30e 100644 --- a/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplateTest.java +++ b/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplateTest.java @@ -13,7 +13,7 @@ import com.microsoft.semantickernel.orchestration.InvocationContext; import com.microsoft.semantickernel.plugin.KernelPlugin; import com.microsoft.semantickernel.plugin.KernelPluginFactory; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; @@ -97,7 +97,7 @@ void testRenderAsync() { HandlebarsPromptTemplate instance = new HandlebarsPromptTemplate(promptTemplate); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", "Hello ") .withVariable("suffix", "World") .withVariable("choices", choices) @@ -146,7 +146,7 @@ public void testSerializesObject() { HandlebarsPromptTemplate instance = new HandlebarsPromptTemplate(promptTemplate); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", new Foo("bar"), ContextVariableJacksonConverter.create(Foo.class)) .build(); @@ -171,7 +171,7 @@ public void testMessageContent() { HandlebarsPromptTemplate instance = new HandlebarsPromptTemplate(promptTemplate); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", new ChatHistory() .addAssistantMessage("foo") .addUserMessage("bar\"<>&")) @@ -196,7 +196,7 @@ public void testMessageHandler() { HandlebarsPromptTemplate instance = new HandlebarsPromptTemplate(promptTemplate); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", "bar\"<>&") .build(); @@ -220,7 +220,7 @@ public void iterableWithContextVariable() { HandlebarsPromptTemplate instance = new HandlebarsPromptTemplate(promptTemplate); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", Arrays.asList(ContextVariable.of("foo\"<>&"))) .build(); @@ -245,7 +245,7 @@ public void withCustomConverter() { Foo.class) .toPromptString(Foo::getVal) .build(); - KernelFunctionArguments arguments = KernelFunctionArguments.builder() + KernelArguments arguments = KernelArguments.builder() .withVariable("input", ContextVariable.of(new Foo("bar\"<>&"), converter)) .build(); diff --git a/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/semantickernel/CodeTokenizerTest.java b/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/semantickernel/CodeTokenizerTest.java index 8a491680c..d39c6aaff 100644 --- a/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/semantickernel/CodeTokenizerTest.java +++ b/semantickernel-api/src/test/java/com/microsoft/semantickernel/templateengine/semantickernel/CodeTokenizerTest.java @@ -6,7 +6,7 @@ import com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks.Block; import com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks.FunctionIdBlock; import com.microsoft.semantickernel.implementation.templateengine.tokenizer.blocks.NamedArgBlock; -import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments; +import com.microsoft.semantickernel.semanticfunctions.KernelArguments; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -28,7 +28,7 @@ public void parseNamedArgs1() { Assertions.assertEquals("street", namedArgBlock.getName()); Assertions.assertEquals("123 Main St", namedArgBlock.getValue( new ContextVariableTypes(), - new KernelFunctionArguments.Builder() + KernelArguments.builder() .withVariable("street", "123 Main St") .build())); @@ -36,13 +36,13 @@ public void parseNamedArgs1() { Assertions.assertEquals("zip", namedArgBlock.getName()); Assertions.assertEquals("98123", namedArgBlock.getValue( new ContextVariableTypes(), - new KernelFunctionArguments.Builder().build())); + KernelArguments.builder().build())); namedArgBlock = (NamedArgBlock) tokens.get(3); Assertions.assertEquals("city", namedArgBlock.getName()); Assertions.assertEquals("Seattle", namedArgBlock.getValue( new ContextVariableTypes(), - new KernelFunctionArguments.Builder().build())); + KernelArguments.builder().build())); } @Test @@ -60,7 +60,6 @@ public void parseNamedArgs2() { Assertions.assertEquals("recall", namedArgBlock.getName()); Assertions.assertEquals("where did I grow up?", namedArgBlock.getValue( new ContextVariableTypes(), - new KernelFunctionArguments.Builder() - .build())); + KernelArguments.builder().build())); } } diff --git a/semantickernel-bom/pom.xml b/semantickernel-bom/pom.xml index e9f338627..2fbb78917 100644 --- a/semantickernel-bom/pom.xml +++ b/semantickernel-bom/pom.xml @@ -5,7 +5,7 @@ com.microsoft.semantic-kernel semantickernel-bom - 1.4.3 + 1.4.4-RC1 pom Semantic Kernel Java BOM @@ -112,6 +112,12 @@ ${project.version} + + com.microsoft.semantic-kernel + semantickernel-agents-core + ${project.version} + + com.azure azure-ai-openai @@ -290,6 +296,6 @@ https://github.com/microsoft/semantic-kernel scm:git:https://github.com/microsoft/semantic-kernel.git scm:git:https://github.com/microsoft/semantic-kernel.git - java-1.4.3 + java-1.4.4-RC1 diff --git a/semantickernel-experimental/pom.xml b/semantickernel-experimental/pom.xml index ce5f80556..cb34ede62 100644 --- a/semantickernel-experimental/pom.xml +++ b/semantickernel-experimental/pom.xml @@ -4,7 +4,7 @@ com.microsoft.semantic-kernel semantickernel-parent - 1.4.3 + 1.4.4-RC1 semantickernel-experimental