diff --git a/java/semantickernel-api/pom.xml b/java/semantickernel-api/pom.xml index 18e8763d48..c2d9566963 100644 --- a/java/semantickernel-api/pom.xml +++ b/java/semantickernel-api/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 @@ -50,6 +51,10 @@ com.github.spotbugs spotbugs-annotations + + org.apache.commons + commons-text + org.junit.jupiter junit-jupiter @@ -72,6 +77,7 @@ mockito-junit-jupiter 5.11.0 + diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java index 8ca6aca11a..d03c5c9a2c 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Optional; import java.util.function.Function; import javax.annotation.Nullable; +import org.apache.commons.text.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +25,7 @@ public class ContextVariableTypeConverter { ContextVariableTypeConverter.class); public interface ToPromptStringFunction { + String toPromptString(ContextVariableTypes types, T t); } @@ -389,4 +391,18 @@ public class ContextVariableTypeConverter { fromPromptString); } } + + /** + * To be used when toPromptString is called + * + * @param value the value to escape + * @return the escaped value + */ + @Nullable + public static String escapeXmlString(@Nullable String value) { + if (value == null) { + return null; + } + return StringEscapeUtils.escapeXml11(value); + } } \ No newline at end of file diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java index ad111e3785..92e331e3fd 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java @@ -43,7 +43,7 @@ public class ChatHistoryVariableContextVariableTypeConverter extends .stream() .map(message -> String.format("%s", message.getAuthorRole(), - message.getContent())) + escapeXmlString(message.getContent()))) .collect(Collectors.joining("\n")); return String.format("%n%s%n", messages); diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java index 41e509eb87..5a5c14cf5a 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java @@ -41,12 +41,15 @@ public class CollectionVariableContextVariableTypeConverter extends this(","); } + @SuppressWarnings("NullAway") public static ToPromptStringFunction getString(String delimiter) { return (types, collection) -> { - return (String) collection + String formatted = (String) collection .stream() .map(t -> getString(types, t)) .collect(Collectors.joining(delimiter)); + + return escapeXmlString(formatted); }; } diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java index a8f0ba5922..5b9bc866e6 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java @@ -34,7 +34,7 @@ public class PrimitiveVariableContextVariableTypeConverter extends super( clazz, s -> convert(s, clazz), - toPromptString, + s -> escapeXmlString(toPromptString.apply(s)), fromPromptString); this.fromObject = fromObject; } diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java index f7096b0747..32fe420051 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java @@ -23,7 +23,7 @@ public class StringVariableContextVariableTypeConverter extends super( String.class, s -> convert(s, String.class), - Object::toString, + ContextVariableTypeConverter::escapeXmlString, s -> s); } } diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java index f38d334761..e43ed0f084 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java @@ -5,6 +5,7 @@ import static com.microsoft.semantickernel.contextvariables.ContextVariableTypes import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; import com.microsoft.semantickernel.services.textcompletion.TextContent; +import javax.annotation.Nullable; /** * A converter for a context variable type. This class is used to convert objects to and from a @@ -21,10 +22,18 @@ public class TextContentVariableContextVariableTypeConverter extends super( TextContent.class, s -> convert(s, TextContent.class), - TextContent::getContent, + TextContentVariableContextVariableTypeConverter::escapeXmlStringValue, x -> { throw new UnsupportedOperationException( "TextContentVariableContextVariableTypeConverter does not support fromPromptString"); }); } + + @Nullable + public static String escapeXmlStringValue(@Nullable TextContent value) { + if (value == null) { + return null; + } + return escapeXmlString(value.getContent()); + } } diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java index d9167a3de4..8d5828568b 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java @@ -50,7 +50,7 @@ public class PromptExecutionSettings { /** * The default for {@link #getFrequencyPenalty()} if - * {@link Builder#withMaxTokens(doulbe) frequency_penalty} is not provided. Defaults to + * {@link Builder#withFrequencyPenalty(double)} frequency_penalty} is not provided. Defaults to * {@code 0.0} */ public static final double DEFAULT_FREQUENCY_PENALTY = 0.0; @@ -97,6 +97,7 @@ public class PromptExecutionSettings { private final String user; private final List stopSequences; private final Map tokenSelectionBiases; + @Nullable private final ResponseFormat responseFormat; /** @@ -114,8 +115,7 @@ public class PromptExecutionSettings { * @param user The user to associate with the prompt execution. * @param stopSequences The stop sequences to use for prompt execution. * @param tokenSelectionBiases The token selection biases to use for prompt execution. - * @param responseFormat The response format to use for prompt execution @{link - * ResponseFormat}. + * @param responseFormat The response format to use for prompt execution {@link ResponseFormat}. */ @JsonCreator public PromptExecutionSettings( diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java index b1e5c19d60..2c0448491a 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/handlebars/HandlebarsPromptTemplate.java @@ -11,6 +11,7 @@ import com.github.jknack.handlebars.ValueResolver; import com.microsoft.semantickernel.Kernel; import com.microsoft.semantickernel.contextvariables.ContextVariable; import com.microsoft.semantickernel.contextvariables.ContextVariableType; +import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter; import com.microsoft.semantickernel.exceptions.SKException; import com.microsoft.semantickernel.orchestration.InvocationContext; import com.microsoft.semantickernel.orchestration.ToolCallBehavior; @@ -85,7 +86,8 @@ public class HandlebarsPromptTemplate implements PromptTemplate { if ("role".equalsIgnoreCase(name)) { return ((ChatMessageContent) context).getAuthorRole().name(); } else if ("content".equalsIgnoreCase(name)) { - return ((ChatMessageContent) context).getContent(); + return ContextVariableTypeConverter + .escapeXmlString(((ChatMessageContent) context).getContent()); } } return UNRESOLVED; @@ -104,7 +106,7 @@ public class HandlebarsPromptTemplate implements PromptTemplate { "%s", ((ChatMessageContent) context).getAuthorRole().toString() .toLowerCase(Locale.ROOT), - content); + ContextVariableTypeConverter.escapeXmlString(content)); } return UNRESOLVED; } diff --git a/java/semantickernel-bom/pom.xml b/java/semantickernel-bom/pom.xml index c0c1cce3de..b208e3dbbc 100644 --- a/java/semantickernel-bom/pom.xml +++ b/java/semantickernel-bom/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 com.microsoft.semantic-kernel @@ -152,6 +153,11 @@ spotbugs-annotations 4.8.3 + + org.apache.commons + commons-text + 1.11.0 +