inputVariables = new ArrayList<>();
@@ -433,6 +456,11 @@ public Builder withTemplateFormat(String templateFormat) {
return this;
}
+ public Builder addPromptTemplateOption(PromptTemplateOption option) {
+ promptTemplateOptions.add(option);
+ return this;
+ }
+
/**
* Set the inputVariables of the prompt template config.
*
@@ -477,6 +505,7 @@ public PromptTemplateConfig build() {
name,
template,
templateFormat,
+ promptTemplateOptions,
description,
inputVariables,
outputVariable,
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateOption.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateOption.java
new file mode 100644
index 00000000..5d244613
--- /dev/null
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateOption.java
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.semanticfunctions;
+
+public enum PromptTemplateOption {
+ /**
+ * Allow methods on objects provided as arguments to an invocation, to be invoked when rendering
+ * a template and its return value used. Typically, this would be used to call a getter on an
+ * object i.e. {@code {{#each users}} {{userName}} {{/each}} } on a handlebars template will
+ * call the method {@code getUserName()} on each object in {@code users}.
+ *
+ * WARNING: If this option is used, ensure that your template is trusted, and that objects added
+ * as arguments to an invocation, do not contain methods that are unsafe to be invoked when
+ * rendering a template.
+ */
+ ALLOW_CONTEXT_VARIABLE_METHOD_CALLS_UNSAFE
+}
\ No newline at end of file
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/AudioToTextService.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/AudioToTextService.java
index 91e14466..871d4cb4 100644
--- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/AudioToTextService.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/AudioToTextService.java
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.services.audio;
+import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.implementation.ServiceLoadUtil;
import com.microsoft.semantickernel.services.AIService;
import com.microsoft.semantickernel.services.openai.OpenAiServiceBuilder;
@@ -32,7 +33,8 @@ static Builder builder() {
/**
* Builder for the AudioToTextService.
*/
- abstract class Builder extends OpenAiServiceBuilder {
+ abstract class Builder
+ extends OpenAiServiceBuilder {
}
}
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/TextToAudioService.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/TextToAudioService.java
index 80a42436..ff2cd40a 100644
--- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/TextToAudioService.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/audio/TextToAudioService.java
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.services.audio;
+import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.implementation.ServiceLoadUtil;
import com.microsoft.semantickernel.services.AIService;
import com.microsoft.semantickernel.services.openai.OpenAiServiceBuilder;
@@ -36,7 +37,7 @@ static Builder builder() {
* Builder for the TextToAudioService.
*/
abstract class Builder extends
- OpenAiServiceBuilder {
+ OpenAiServiceBuilder {
}
}
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 d2f391ff..ea910c01 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
@@ -33,7 +33,7 @@ public ChatHistory() {
* @param instructions The instructions to add to the chat history
*/
public ChatHistory(@Nullable String instructions) {
- this.chatMessageContents = new ArrayList<>();
+ this.chatMessageContents = Collections.synchronizedList(new ArrayList<>());
if (instructions != null) {
this.chatMessageContents.add(
ChatMessageTextContent.systemMessage(instructions));
@@ -45,8 +45,9 @@ public ChatHistory(@Nullable String instructions) {
*
* @param chatMessageContents The chat message contents to add to the chat history
*/
- public ChatHistory(List extends ChatMessageContent> chatMessageContents) {
- this.chatMessageContents = new ArrayList(chatMessageContents);
+ public ChatHistory(List extends ChatMessageContent>> chatMessageContents) {
+ this.chatMessageContents = Collections
+ .synchronizedList(new ArrayList<>(chatMessageContents));
}
/**
@@ -55,7 +56,7 @@ public ChatHistory(List extends ChatMessageContent> chatMessageContents) {
* @return List of messages in the chat
*/
public List> getMessages() {
- return Collections.unmodifiableList(chatMessageContents);
+ return Collections.unmodifiableList(new ArrayList<>(chatMessageContents));
}
/**
@@ -67,7 +68,8 @@ public Optional> getLastMessage() {
if (chatMessageContents.isEmpty()) {
return Optional.empty();
}
- return Optional.of(chatMessageContents.get(chatMessageContents.size() - 1));
+ return Optional
+ .of(chatMessageContents.get(chatMessageContents.size() - 1));
}
/**
@@ -113,8 +115,8 @@ public Spliterator> spliterator() {
* @param encoding The encoding of the message
* @param metadata The metadata of the message
*/
- public void addMessage(AuthorRole authorRole, String content, Charset encoding,
- FunctionResultMetadata metadata) {
+ public ChatHistory addMessage(AuthorRole authorRole, String content, Charset encoding,
+ FunctionResultMetadata> metadata) {
chatMessageContents.add(
ChatMessageTextContent.builder()
.withAuthorRole(authorRole)
@@ -122,6 +124,7 @@ public void addMessage(AuthorRole authorRole, String content, Charset encoding,
.withEncoding(encoding)
.withMetadata(metadata)
.build());
+ return this;
}
/**
@@ -130,12 +133,13 @@ public void addMessage(AuthorRole authorRole, String content, Charset encoding,
* @param authorRole The role of the author of the message
* @param content The content of the message
*/
- public void addMessage(AuthorRole authorRole, String content) {
+ public ChatHistory addMessage(AuthorRole authorRole, String content) {
chatMessageContents.add(
ChatMessageTextContent.builder()
.withAuthorRole(authorRole)
.withContent(content)
.build());
+ return this;
}
/**
@@ -143,8 +147,9 @@ public void addMessage(AuthorRole authorRole, String content) {
*
* @param content The content of the message
*/
- public void addMessage(ChatMessageContent> content) {
+ public ChatHistory addMessage(ChatMessageContent> content) {
chatMessageContents.add(content);
+ return this;
}
/**
@@ -152,8 +157,8 @@ public void addMessage(ChatMessageContent> content) {
*
* @param content The content of the user message
*/
- public void addUserMessage(String content) {
- addMessage(AuthorRole.USER, content);
+ public ChatHistory addUserMessage(String content) {
+ return addMessage(AuthorRole.USER, content);
}
/**
@@ -161,8 +166,8 @@ public void addUserMessage(String content) {
*
* @param content The content of the assistant message
*/
- public void addAssistantMessage(String content) {
- addMessage(AuthorRole.ASSISTANT, content);
+ public ChatHistory addAssistantMessage(String content) {
+ return addMessage(AuthorRole.ASSISTANT, content);
}
/**
@@ -170,11 +175,12 @@ public void addAssistantMessage(String content) {
*
* @param content The content of the system message
*/
- public void addSystemMessage(String content) {
- addMessage(AuthorRole.SYSTEM, content);
+ public ChatHistory addSystemMessage(String content) {
+ return addMessage(AuthorRole.SYSTEM, content);
}
- public void addAll(List> messages) {
+ public ChatHistory addAll(List> messages) {
chatMessageContents.addAll(messages);
+ return this;
}
}
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/openai/OpenAiServiceBuilder.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/openai/OpenAiServiceBuilder.java
index 0197a55a..5386cd83 100644
--- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/openai/OpenAiServiceBuilder.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/openai/OpenAiServiceBuilder.java
@@ -1,20 +1,25 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.services.openai;
-import com.azure.ai.openai.OpenAIAsyncClient;
+import com.microsoft.semantickernel.services.AIService;
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
import javax.annotation.Nullable;
/**
* Builder for an OpenAI service.
- */
-public abstract class OpenAiServiceBuilder> implements
+ * @param The client type
+ * @param The service type
+ * @param The builder type
+*/
+public abstract class OpenAiServiceBuilder>
+ implements
+
SemanticKernelBuilder {
@Nullable
protected String modelId;
@Nullable
- protected OpenAIAsyncClient client;
+ protected C client;
@Nullable
protected String serviceId;
@Nullable
@@ -51,7 +56,7 @@ public U withDeploymentName(String deploymentName) {
* @param client The OpenAI client
* @return The builder
*/
- public U withOpenAIAsyncClient(OpenAIAsyncClient client) {
+ public U withOpenAIAsyncClient(C client) {
this.client = client;
return (U) this;
}
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/textcompletion/TextGenerationService.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/textcompletion/TextGenerationService.java
index ab592c86..0ab08f5f 100644
--- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/textcompletion/TextGenerationService.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/textcompletion/TextGenerationService.java
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.services.textcompletion;
+import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.implementation.ServiceLoadUtil;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
@@ -60,6 +61,7 @@ Flux getStreamingTextContentsAsync(
/**
* Builder for a TextGenerationService
*/
- abstract class Builder extends OpenAiServiceBuilder {
+ abstract class Builder
+ extends OpenAiServiceBuilder {
}
}
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 2e7c260e..ec701ce3 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
@@ -9,6 +9,7 @@
import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.Options;
import com.github.jknack.handlebars.ValueResolver;
+import com.github.jknack.handlebars.context.JavaBeanValueResolver;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.contextvariables.ContextVariable;
import com.microsoft.semantickernel.contextvariables.ContextVariableType;
@@ -21,6 +22,7 @@
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
+import com.microsoft.semantickernel.semanticfunctions.PromptTemplateOption;
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
@@ -35,7 +37,6 @@
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.apache.commons.text.StringEscapeUtils;
import reactor.core.publisher.Mono;
/**
@@ -168,7 +169,7 @@ public Set> propertySet(Object context) {
}
}
- private static class HandleBarsPromptTemplateHandler {
+ private class HandleBarsPromptTemplateHandler {
private final String template;
private final Handlebars handlebars;
@@ -181,7 +182,7 @@ public HandleBarsPromptTemplateHandler(
this.template = template;
this.handlebars = new Handlebars();
this.handlebars
- .registerHelper("message", HandleBarsPromptTemplateHandler::handleMessage)
+ .registerHelper("message", this::handleMessage)
.registerHelper("each", handleEach(context))
.with(EscapingStrategy.XML);
@@ -190,7 +191,7 @@ public HandleBarsPromptTemplateHandler(
// TODO: 1.0 Add more helpers
}
- private static Helper