mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Java: Proposal for adding hooks (#4730)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
@@ -33,6 +34,13 @@
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Required for Android -->
|
||||
<dependency>
|
||||
<groupId>javax.xml.stream</groupId>
|
||||
<artifactId>stax-api</artifactId>
|
||||
<version>1.0-2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
+75
-28
@@ -26,6 +26,9 @@ import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatMessageContent;
|
||||
import com.microsoft.semantickernel.chatcompletion.StreamingChatMessageContent;
|
||||
import com.microsoft.semantickernel.exceptions.AIException;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.hooks.PreChatCompletionEvent;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
@@ -33,7 +36,6 @@ import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
@@ -69,7 +71,7 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
|
||||
@Override
|
||||
public Map<String, ContextVariable<?>> getAttributes() {
|
||||
return attributes;
|
||||
return Collections.unmodifiableMap(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,56 +80,101 @@ public class OpenAIChatCompletion implements ChatCompletionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(ChatHistory chatHistory,
|
||||
@Nullable PromptExecutionSettings promptExecutionSettings, @Nullable Kernel kernel) {
|
||||
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(
|
||||
ChatHistory chatHistory,
|
||||
PromptExecutionSettings promptExecutionSettings,
|
||||
Kernel kernel,
|
||||
KernelHooks kernelHooks) {
|
||||
|
||||
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(chatHistory);
|
||||
List<FunctionDefinition> functions = Collections.emptyList();
|
||||
return internalChatMessageContentsAsync(chatRequestMessages, functions,
|
||||
promptExecutionSettings);
|
||||
|
||||
if (kernelHooks == null) {
|
||||
kernelHooks = new KernelHooks();
|
||||
}
|
||||
|
||||
return internalChatMessageContentsAsync(
|
||||
chatRequestMessages,
|
||||
functions,
|
||||
promptExecutionSettings,
|
||||
kernelHooks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(
|
||||
ChatHistory chatHistory,
|
||||
@Nullable PromptExecutionSettings promptExecutionSettings,
|
||||
@Nullable Kernel kernel) {
|
||||
return getChatMessageContentsAsync(chatHistory, promptExecutionSettings, kernel, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(
|
||||
String prompt,
|
||||
PromptExecutionSettings promptExecutionSettings,
|
||||
Kernel kernel,
|
||||
@Nullable
|
||||
KernelHooks kernelHooks) {
|
||||
ParsedPrompt parsedPrompt = XMLPromptParser.parse(prompt);
|
||||
|
||||
if (kernelHooks == null) {
|
||||
kernelHooks = new KernelHooks();
|
||||
}
|
||||
|
||||
return internalChatMessageContentsAsync(
|
||||
parsedPrompt.getChatRequestMessages(),
|
||||
parsedPrompt.getFunctions(),
|
||||
promptExecutionSettings,
|
||||
kernelHooks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(String prompt,
|
||||
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
|
||||
ParsedPrompt parsedPrompt = XMLPromptParser.parse(prompt);
|
||||
return internalChatMessageContentsAsync(
|
||||
parsedPrompt.getChatRequestMessages(),
|
||||
parsedPrompt.getFunctions(),
|
||||
promptExecutionSettings);
|
||||
return getChatMessageContentsAsync(prompt, promptExecutionSettings, kernel, null);
|
||||
}
|
||||
|
||||
|
||||
private Mono<List<ChatMessageContent>> internalChatMessageContentsAsync(
|
||||
List<ChatRequestMessage> chatRequestMessages,
|
||||
List<FunctionDefinition> functions,
|
||||
PromptExecutionSettings promptExecutionSettings) {
|
||||
PromptExecutionSettings promptExecutionSettings,
|
||||
KernelHooks kernelHooks) {
|
||||
|
||||
ChatCompletionsOptions options = getCompletionsOptions(this, chatRequestMessages, functions,
|
||||
promptExecutionSettings);
|
||||
Mono<List<ChatMessageContent>> results =
|
||||
internalChatMessageContentsAsync(options);
|
||||
internalChatMessageContentsAsync(kernelHooks, options);
|
||||
|
||||
return results.flatMap(list -> {
|
||||
boolean makeSecondCall = false;
|
||||
for (ChatMessageContent messageContent : list) {
|
||||
if (messageContent.getAuthorRole() == AuthorRole.TOOL) {
|
||||
makeSecondCall = true;
|
||||
String content = messageContent.getContent();
|
||||
String id = messageContent.getModelId();
|
||||
ChatRequestToolMessage toolMessage = new ChatRequestToolMessage(content, id);
|
||||
chatRequestMessages.add(toolMessage);
|
||||
return results
|
||||
.flatMap(list -> {
|
||||
boolean makeSecondCall = false;
|
||||
for (ChatMessageContent messageContent : list) {
|
||||
if (messageContent.getAuthorRole() == AuthorRole.TOOL) {
|
||||
makeSecondCall = true;
|
||||
String content = messageContent.getContent();
|
||||
String id = messageContent.getModelId();
|
||||
ChatRequestToolMessage toolMessage = new ChatRequestToolMessage(content,
|
||||
id);
|
||||
chatRequestMessages.add(toolMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (makeSecondCall) {
|
||||
return internalChatMessageContentsAsync(options);
|
||||
}
|
||||
return Mono.just(list);
|
||||
});
|
||||
if (makeSecondCall) {
|
||||
return internalChatMessageContentsAsync(kernelHooks, options);
|
||||
}
|
||||
return Mono.just(list);
|
||||
});
|
||||
}
|
||||
|
||||
private Mono<List<ChatMessageContent>> internalChatMessageContentsAsync(
|
||||
KernelHooks kernelHooks,
|
||||
ChatCompletionsOptions options) {
|
||||
|
||||
options = kernelHooks
|
||||
.executeHooks(new PreChatCompletionEvent(options))
|
||||
.getOptions();
|
||||
|
||||
return client
|
||||
.getChatCompletions(getModelId(), options)
|
||||
.filter(choices -> choices.getChoices() != null && !choices.getChoices().isEmpty())
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@ import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -61,7 +62,7 @@ class XMLPromptParser {
|
||||
// If one handler does not recognize the element, it should pass it to the next handler.
|
||||
// In this way, we can avoid parsing the whole prompt twice and easily extend the parsing logic.
|
||||
List<ChatRequestMessage> messages = new ArrayList<>();
|
||||
try (InputStream is = new ByteArrayInputStream(prompt.getBytes())) {
|
||||
try (InputStream is = new ByteArrayInputStream(prompt.getBytes(StandardCharsets.UTF_8))) {
|
||||
XMLInputFactory factory = XMLInputFactory.newFactory();
|
||||
XMLEventReader reader = factory.createXMLEventReader(is);
|
||||
while (reader.hasNext()) {
|
||||
@@ -87,7 +88,7 @@ class XMLPromptParser {
|
||||
// <parameter name=\"%s\" description=\"%s\" defaultValue=\"%s\" isRequired=\"%s\" type=\"%s\"/>...
|
||||
// </function>
|
||||
List<FunctionDefinition> functionDefinitions = new ArrayList<>();
|
||||
try (InputStream is = new ByteArrayInputStream(prompt.getBytes())) {
|
||||
try (InputStream is = new ByteArrayInputStream(prompt.getBytes(StandardCharsets.UTF_8))) {
|
||||
XMLInputFactory factory = XMLInputFactory.newFactory();
|
||||
XMLEventReader reader = factory.createXMLEventReader(is);
|
||||
FunctionDefinition functionDefinition = null;
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public class OpenAITextGenerationService implements TextGenerationService {
|
||||
|
||||
@Override
|
||||
public Map<String, ContextVariable<?>> getAttributes() {
|
||||
return attributes;
|
||||
return Collections.unmodifiableMap(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ import com.microsoft.semantickernel.exceptions.SKException;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class BingConnector implements WebSearchEngineConnector {
|
||||
public class BingConnector implements WebSearchEngineConnector {
|
||||
|
||||
private static String BING_SEARCH_URL;
|
||||
static {
|
||||
@@ -91,7 +91,7 @@ public class BingConnector implements WebSearchEngineConnector {
|
||||
@Override
|
||||
public String getSnippet() {
|
||||
return snippet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final String apiKey; // TODO: secure this
|
||||
@@ -107,7 +107,7 @@ public class BingConnector implements WebSearchEngineConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<WebPage>> searchAsync(String query, int count, int offset) {
|
||||
public Mono<List<WebPage>> searchAsync(String query, int count, int offset) {
|
||||
|
||||
if (count <= 0 || 50 <= count) throw new IllegalArgumentException("count must be between 1 and 50");
|
||||
if (offset < 0) throw new IllegalArgumentException("offset must be greater than or equal to 0");
|
||||
|
||||
+6
-5
@@ -1,9 +1,8 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.util;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,7 +13,8 @@ import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
|
||||
*/
|
||||
public final class LocaleParser {
|
||||
|
||||
private LocaleParser() {}
|
||||
private LocaleParser() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the locale. If the input is "en-US", it will return a Locale based on the language
|
||||
@@ -26,12 +26,13 @@ public final class LocaleParser {
|
||||
* @param locale the locale in String text.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("StringSplitter")
|
||||
public static final Locale parseLocale(String locale) {
|
||||
Locale parsedLocale = null;
|
||||
|
||||
if (locale == null
|
||||
|| "".equals(locale.trim())
|
||||
|| KernelFunctionParameter.NO_DEFAULT_VALUE.equals(locale)) {
|
||||
|| "".equals(locale.trim())
|
||||
|| KernelFunctionParameter.NO_DEFAULT_VALUE.equals(locale)) {
|
||||
return Locale.getDefault();
|
||||
} else if (locale.indexOf("-") > -1) {
|
||||
parsedLocale = Locale.forLanguageTag(locale);
|
||||
|
||||
+11
-3
@@ -15,7 +15,7 @@
|
||||
<properties>
|
||||
<azure-ai-openai.version>1.0.0-beta.6</azure-ai-openai.version>
|
||||
<checkstyle.version>10.12.2</checkstyle.version>
|
||||
<com.uber.nullaway.version>0.10.10</com.uber.nullaway.version>
|
||||
<com.uber.nullaway.version>0.10.21</com.uber.nullaway.version>
|
||||
<google.errorprone.core.version>2.19.1</google.errorprone.core.version>
|
||||
<google.java.format.version>1.17.0</google.java.format.version>
|
||||
<jreleaser.plugin.version>1.6.0</jreleaser.plugin.version>
|
||||
@@ -60,7 +60,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.github.repository>microsoft/semantic-kernel</project.github.repository>
|
||||
<repository.url>[email protected]:${project.github.repository}.git</repository.url>
|
||||
<spotbugs.version>4.7.3</spotbugs.version>
|
||||
<spotbugs.version>4.8.3</spotbugs.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@@ -155,7 +155,13 @@
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-connectors-web-bing</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-annotations</artifactId>
|
||||
<version>${spotbugs.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -685,6 +691,7 @@
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!--
|
||||
<java>
|
||||
<googleJavaFormat>
|
||||
<version>${google.java.format.version}</version>
|
||||
@@ -696,6 +703,7 @@
|
||||
</licenseHeader>
|
||||
<toggleOffOn />
|
||||
</java>
|
||||
-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
+26
-52
@@ -87,40 +87,26 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||
<version>1.23</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>android</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<!-- <dependencies>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-connectors-ai-openai</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j2-impl</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-planners</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies> -->
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>bug-check</id>
|
||||
@@ -140,28 +126,16 @@
|
||||
<target>${maven.compiler.release}</target>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
<showWarnings>true</showWarnings>
|
||||
<compilerArgs>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Remove exclusions when more project is stable -->
|
||||
<arg>-Xplugin:ErrorProne
|
||||
-XepOpt:NullAway:AnnotatedPackages=com.microsoft.semantickernel
|
||||
-Xep:AlmostJavadoc:OFF -Xep:MissingSummary:OFF
|
||||
-Xep:UnusedVariable:OFF -Xep:EmptyBlockTag:OFF
|
||||
</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<version>${google.errorprone.core.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.uber.nullaway</groupId>
|
||||
<artifactId>nullaway</artifactId>
|
||||
<version>${com.uber.nullaway.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<!-- Ignore linting on samples -->
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>${maven.spotbugs-plugin.version}</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -39,17 +39,6 @@
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-connectors-web-bing</artifactId>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-connectors-ai-openai</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-connectors-memory-azurecognitivesearch</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
@@ -66,18 +55,6 @@
|
||||
<artifactId>log4j-slf4j2-impl</artifactId>
|
||||
<version>2.20.0</version>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-planners</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantic-kernel</groupId>
|
||||
<artifactId>semantickernel-gpt3-tokenizer</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
|
||||
+2
@@ -19,6 +19,7 @@ public class Example17_ChatGPT {
|
||||
.getOrDefault("MODEL_ID", "gpt-35-turbo");
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println("======== Open AI - ChatGPT ========");
|
||||
|
||||
OpenAIAsyncClient client;
|
||||
@@ -67,6 +68,7 @@ public class Example17_ChatGPT {
|
||||
}
|
||||
|
||||
private static void GPTReply(ChatCompletionService chatGPT, ChatHistory chatHistory) {
|
||||
|
||||
var reply = chatGPT.getChatMessageContentsAsync(chatHistory, null, null)
|
||||
.block();
|
||||
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ 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.ServiceNotFoundException;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
@@ -30,7 +31,7 @@ public class Example30_ChatWithPrompts {
|
||||
private static final String MODEL_ID = System.getenv()
|
||||
.getOrDefault("MODEL_ID", "gpt-35-turbo");
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
public static void main(String[] args) throws FileNotFoundException, ServiceNotFoundException {
|
||||
OpenAIAsyncClient client;
|
||||
|
||||
if (AZURE_CLIENT_KEY != null) {
|
||||
|
||||
+2
-1
@@ -67,7 +67,8 @@ public class Example42_KernelBuilder {
|
||||
// using the public constructor that's available for anyone to use directly if desired.
|
||||
Kernel kernel = new Kernel(
|
||||
new OrderedAIServiceSelector(),
|
||||
new KernelPluginCollection()
|
||||
new KernelPluginCollection(),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+417
@@ -0,0 +1,417 @@
|
||||
package com.microsoft.semantickernel.samples.syntaxexamples;
|
||||
|
||||
import com.azure.ai.openai.OpenAIAsyncClient;
|
||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.ai.openai.models.ChatCompletionsOptions;
|
||||
import com.azure.ai.openai.models.ChatRequestMessage;
|
||||
import com.azure.ai.openai.models.ChatRequestSystemMessage;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.azure.core.credential.KeyCredential;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.Kernel.Builder;
|
||||
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
|
||||
import com.microsoft.semantickernel.hooks.FunctionInvokedEvent;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokedHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokingHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PreChatCompletionHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderedHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderingHook;
|
||||
import com.microsoft.semantickernel.hooks.PreChatCompletionEvent;
|
||||
import com.microsoft.semantickernel.hooks.PromptRenderedEvent;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Example57_KernelHooks {
|
||||
|
||||
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-35-turbo");
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
|
||||
.withModelId(MODEL_ID)
|
||||
.withOpenAIAsyncClient(client)
|
||||
.build();
|
||||
|
||||
Builder kernelBuilder = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, openAIChatCompletion);
|
||||
|
||||
getUsageAsync(kernelBuilder.build());
|
||||
getRenderedPromptAsync(kernelBuilder.build());
|
||||
changingResultAsync(kernelBuilder.build());
|
||||
beforeInvokeCancellationAsync(kernelBuilder.build());
|
||||
afterInvokeCancellationAsync(kernelBuilder.build());
|
||||
chatCompletionHook(kernelBuilder.build());
|
||||
invocationHook(kernelBuilder.build());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using kernel invocation-hooks to monitor usage:
|
||||
/// <see cref="Kernel.FunctionInvoking"/>
|
||||
/// <see cref="Kernel.FunctionInvoked"/>
|
||||
/// </summary>
|
||||
private static void getUsageAsync(Kernel kernel) {
|
||||
System.out.println("\n======== Get Usage Data ========\n");
|
||||
|
||||
// Initialize prompt
|
||||
String functionPrompt = "Write a random paragraph about: {{$input}}.";
|
||||
|
||||
var excuseFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Excuse")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(100)
|
||||
.withTemperature(0.4)
|
||||
.withTopP(1)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
FunctionInvokingHook preHook = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName() + " : Pre Execution Handler - Triggered");
|
||||
return event;
|
||||
};
|
||||
|
||||
FunctionInvokingHook removedPreExecutionHandler = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName() + " : Pre Execution Handler - Should not trigger");
|
||||
return event;
|
||||
};
|
||||
|
||||
FunctionInvokedHook postExecutionHandler = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName() + " : Post Execution Handler - Usage: " + event
|
||||
.getResult()
|
||||
.getMetadata()
|
||||
.getUsage()
|
||||
.getTotalTokens());
|
||||
return event;
|
||||
};
|
||||
|
||||
kernel.getHookService().addHook(preHook);
|
||||
|
||||
// Demonstrate pattern for removing a handler.
|
||||
kernel.getHookService().addHook("pre-invoke-removed", removedPreExecutionHandler);
|
||||
kernel.getHookService().removeHook("pre-invoke-removed");
|
||||
|
||||
kernel.getHookService().addHook(postExecutionHandler);
|
||||
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
String input = "I missed the F1 final race";
|
||||
var result = kernel.invokeAsync(
|
||||
excuseFunction,
|
||||
KernelArguments
|
||||
.builder()
|
||||
.withVariable("input", input)
|
||||
.build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using kernel-hooks to around prompt rendering:
|
||||
/// <see cref="Kernel.PromptRendering"/>
|
||||
/// <see cref="Kernel.PromptRendered"/>
|
||||
/// </summary>
|
||||
private static void getRenderedPromptAsync(Kernel kernel) {
|
||||
System.out.println("\n======== Get Rendered Prompt ========\n");
|
||||
|
||||
// Initialize prompt
|
||||
String functionPrompt = "Write a random paragraph about: {{$input}} in the style of {{$style}}.";
|
||||
|
||||
var excuseFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Excuse")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(100)
|
||||
.withTemperature(0.4)
|
||||
.withTopP(1)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
PromptRenderingHook myRenderingHandler = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName() + " : Prompt Rendering Handler - Triggered");
|
||||
event.getArguments().put("style", ContextVariable.of("Seinfeld"));
|
||||
return event;
|
||||
};
|
||||
|
||||
PromptRenderedHook myRenderedHandler = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName() + " : Prompt Rendered Handler - Triggered");
|
||||
|
||||
String prompt = event.getPrompt() + "\nUSE SHORT, CLEAR, COMPLETE SENTENCES.";
|
||||
|
||||
return new PromptRenderedEvent(
|
||||
event.getFunction(),
|
||||
event.getArguments(),
|
||||
prompt
|
||||
);
|
||||
};
|
||||
kernel.getHookService().addHook(myRenderingHandler);
|
||||
kernel.getHookService().addHook(myRenderedHandler);
|
||||
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
String input = "I missed the F1 final race";
|
||||
var result = kernel.invokeAsync(excuseFunction,
|
||||
KernelArguments
|
||||
.builder()
|
||||
.withVariable("input", input)
|
||||
.build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using kernel invocation-hooks to post process result:
|
||||
/// <see cref="Kernel.FunctionInvoked"/>
|
||||
/// </summary>
|
||||
private static void changingResultAsync(Kernel kernel) {
|
||||
System.out.println("\n======== Changing/Filtering Function Result ========\n");
|
||||
|
||||
// Initialize function
|
||||
String functionPrompt = "Write a paragraph about Handlers.";
|
||||
|
||||
var writerFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Writer")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(100)
|
||||
.withTemperature(0.4)
|
||||
.withTopP(1)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
FunctionInvokedHook hook = event -> {
|
||||
String result = (String) event.getResult().getResult();
|
||||
result = result.replaceAll("[aeiouAEIOU0-9]", "*");
|
||||
|
||||
return new FunctionInvokedEvent<>(
|
||||
event.getFunction(),
|
||||
event.getArguments(),
|
||||
new FunctionResult<>(
|
||||
ContextVariable.of(result),
|
||||
event.getResult().getMetadata()
|
||||
)
|
||||
);
|
||||
};
|
||||
kernel.getHookService().addHook(hook);
|
||||
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
var result = kernel.invokeAsync(
|
||||
writerFunction,
|
||||
KernelArguments.builder().build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using kernel invocation-hooks to cancel prior to execution:
|
||||
/// <see cref="Kernel.FunctionInvoking"/>
|
||||
/// <see cref="Kernel.FunctionInvoked"/>
|
||||
/// </summary>
|
||||
private static void beforeInvokeCancellationAsync(Kernel kernel) {
|
||||
System.out.println("\n======== Cancelling Pipeline Execution - Invoking event ========\n");
|
||||
|
||||
// Initialize prompt
|
||||
String functionPrompt = "Write a paragraph about: Cancellation.";
|
||||
|
||||
var writerFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Writer")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(1000)
|
||||
.withTemperature(1)
|
||||
.withTopP(0.5)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
FunctionInvokingHook hook = event -> {
|
||||
System.out.println(
|
||||
event.getFunction().getName()
|
||||
+ " : FunctionInvoking - Cancelling before execution");
|
||||
throw new RuntimeException("Cancelled");
|
||||
};
|
||||
|
||||
kernel.getHookService().addHook(hook);
|
||||
|
||||
try {
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
var result = kernel.invokeAsync(
|
||||
writerFunction,
|
||||
KernelArguments.builder().build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using kernel invocation-hooks to cancel post after execution:
|
||||
/// <see cref="Kernel.FunctionInvoking"/>
|
||||
/// <see cref="Kernel.FunctionInvoked"/>
|
||||
/// </summary>
|
||||
private static void afterInvokeCancellationAsync(Kernel kernel) {
|
||||
System.out.println("\n======== Cancelling Pipeline Execution - Invoked event ========\n");
|
||||
|
||||
// Initialize prompts
|
||||
var firstFunction = KernelFunctionFromPrompt.create("Write a phrase with Invoke.");
|
||||
var secondFunction = KernelFunctionFromPrompt.create("Write a phrase with Cancellation.");
|
||||
|
||||
AtomicInteger invokingCounter = new AtomicInteger(0);
|
||||
kernel.getHookService().addHook((FunctionInvokingHook) event -> {
|
||||
invokingCounter.incrementAndGet();
|
||||
return event;
|
||||
});
|
||||
|
||||
AtomicInteger invokedCounter = new AtomicInteger(0);
|
||||
kernel.getHookService().addHook((FunctionInvokedHook) event -> {
|
||||
invokedCounter.incrementAndGet();
|
||||
throw new RuntimeException("Cancelled");
|
||||
});
|
||||
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
try {
|
||||
var result = kernel.invokeAsync(
|
||||
secondFunction,
|
||||
KernelArguments.builder().build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
System.out.println("Function Invoked Times: " + invokedCounter.get());
|
||||
System.out.println("Function Invoking Times: " + invokedCounter.get());
|
||||
}
|
||||
}
|
||||
|
||||
private static void chatCompletionHook(Kernel kernel) {
|
||||
// Initialize prompt
|
||||
String functionPrompt = "Write a paragraph about hats";
|
||||
|
||||
var writerFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Writer")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(1000)
|
||||
.withTemperature(1)
|
||||
.withTopP(0.5)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
kernel.getHookService().addPreChatCompletionHook(event -> {
|
||||
ChatCompletionsOptions options = event.getOptions();
|
||||
List<ChatRequestMessage> messages = options.getMessages();
|
||||
|
||||
messages = new ArrayList<>(messages);
|
||||
messages.add(
|
||||
new ChatRequestSystemMessage("Use upper case text when responding to the prompt."));
|
||||
|
||||
return new PreChatCompletionEvent(
|
||||
PreChatCompletionHook.cloneOptionsWithMessages(options, messages)
|
||||
);
|
||||
});
|
||||
|
||||
try {
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
var result = kernel.invokeAsync(
|
||||
writerFunction,
|
||||
KernelArguments.builder().build(),
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show use of hooks added on a single invocations.
|
||||
*
|
||||
* @param kernel
|
||||
*/
|
||||
private static void invocationHook(Kernel kernel) {
|
||||
// Initialize prompt
|
||||
String functionPrompt = "Write a paragraph about hats";
|
||||
|
||||
var writerFunction = KernelFunctionFromPrompt.builder()
|
||||
.withTemplate(functionPrompt)
|
||||
.withName("Writer")
|
||||
.withDefaultExecutionSettings(PromptExecutionSettings
|
||||
.builder()
|
||||
.withMaxTokens(1000)
|
||||
.withTemperature(1)
|
||||
.withTopP(0.5)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
KernelHooks kernelHooks = new KernelHooks();
|
||||
kernelHooks.addPreChatCompletionHook(event -> {
|
||||
ChatCompletionsOptions options = event.getOptions();
|
||||
List<ChatRequestMessage> messages = options.getMessages();
|
||||
|
||||
messages = new ArrayList<>(messages);
|
||||
messages.add(
|
||||
new ChatRequestSystemMessage("Use upper case text when responding to the prompt."));
|
||||
|
||||
return new PreChatCompletionEvent(
|
||||
PreChatCompletionHook.cloneOptionsWithMessages(options, messages)
|
||||
);
|
||||
});
|
||||
|
||||
try {
|
||||
// Invoke prompt to trigger execution hooks.
|
||||
var result = kernel.invokeAsync(
|
||||
writerFunction,
|
||||
KernelArguments.builder().build(),
|
||||
kernelHooks,
|
||||
String.class)
|
||||
.block();
|
||||
System.out.println("Function Result: " + result.getResult());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -90,8 +90,8 @@ public class Example62_CustomAIServiceSelector {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AIServiceSelection trySelectAIService(
|
||||
Class<? extends AIService> serviceType,
|
||||
public <T extends AIService> AIServiceSelection<T> trySelectAIService(
|
||||
Class<T> serviceType,
|
||||
|
||||
@Nullable
|
||||
KernelFunction function,
|
||||
|
||||
@@ -43,7 +43,6 @@ public class Main {
|
||||
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.build();
|
||||
|
||||
// Initialize the required functions and services for the kernel
|
||||
|
||||
@@ -3,11 +3,10 @@ import com.microsoft.semantickernel.chatcompletion.AuthorRole;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatMessageContent;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
@@ -65,7 +64,6 @@ public class SimpleChatTest {
|
||||
throws IOException {
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.build();
|
||||
|
||||
// Initialize the required functions and services for the kernel
|
||||
|
||||
@@ -41,7 +41,6 @@ public class Main {
|
||||
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.build();
|
||||
|
||||
ChatHistory chatHistory = new ChatHistory();
|
||||
|
||||
@@ -59,7 +59,6 @@ public class PersonaChatTest {
|
||||
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.build();
|
||||
|
||||
// Initialize the required functions and services for the kernel
|
||||
|
||||
@@ -49,7 +49,6 @@ public class Main {
|
||||
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.withPlugin(searchPlugin)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ public class SimpleRagTest {
|
||||
|
||||
Kernel kernel = Kernel.builder()
|
||||
.withAIService(ChatCompletionService.class, gpt35Turbo)
|
||||
.withPromptTemplate(new HandlebarsPromptTemplate())
|
||||
.withPlugin(searchPlugin)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -66,5 +66,9 @@
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-annotations</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.microsoft.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,7 @@ public interface AIService {
|
||||
/// <summary>
|
||||
/// Gets the specified attribute.
|
||||
/// </summary>
|
||||
@Nullable
|
||||
static String getAttribute(AIService service, String key)
|
||||
{
|
||||
if (service.getAttributes() != null) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.microsoft.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
@@ -12,13 +13,16 @@ import com.microsoft.semantickernel.orchestration.contextvariables.KernelArgumen
|
||||
import com.microsoft.semantickernel.plugin.KernelPlugin;
|
||||
import com.microsoft.semantickernel.plugin.KernelPluginCollection;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.services.AIServiceSelection;
|
||||
import com.microsoft.semantickernel.services.AIServiceSelector;
|
||||
import com.microsoft.semantickernel.services.OrderedAIServiceSelector;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -33,23 +37,37 @@ public class Kernel implements Buildable {
|
||||
|
||||
private final AIServiceSelector serviceSelector;
|
||||
private final KernelPluginCollection plugins;
|
||||
private final KernelHooks kernelHooks;
|
||||
|
||||
public Kernel(
|
||||
AIServiceSelector serviceSelector,
|
||||
@Nullable KernelPluginCollection plugins) {
|
||||
@Nullable KernelPluginCollection plugins,
|
||||
@Nullable KernelHooks kernelHooks) {
|
||||
this.serviceSelector = serviceSelector;
|
||||
|
||||
if (plugins != null) {
|
||||
this.plugins = plugins;
|
||||
this.plugins = new KernelPluginCollection(plugins.getPlugins());
|
||||
} else {
|
||||
this.plugins = new KernelPluginCollection();
|
||||
}
|
||||
|
||||
this.kernelHooks = new KernelHooks(kernelHooks);
|
||||
}
|
||||
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
KernelFunction function,
|
||||
@Nullable KernelArguments arguments,
|
||||
@Nullable KernelHooks kernelHooks,
|
||||
ContextVariableType<T> resultType) {
|
||||
kernelHooks = mergeInGlobalHooks(kernelHooks);
|
||||
return function.invokeAsync(this, arguments, kernelHooks, resultType);
|
||||
}
|
||||
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
KernelFunction function,
|
||||
@Nullable KernelArguments arguments,
|
||||
ContextVariableType<T> resultType) {
|
||||
return function.invokeAsync(this, arguments, resultType);
|
||||
return invokeAsync(function, arguments, null, resultType);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,16 +75,29 @@ public class Kernel implements Buildable {
|
||||
String pluginName,
|
||||
String functionName,
|
||||
@Nullable KernelArguments arguments,
|
||||
@Nullable KernelHooks kernelHooks,
|
||||
ContextVariableType<T> resultType) {
|
||||
kernelHooks = mergeInGlobalHooks(kernelHooks);
|
||||
return plugins.getFunction(pluginName, functionName)
|
||||
.invokeAsync(this, arguments, resultType);
|
||||
.invokeAsync(this, arguments, kernelHooks, resultType);
|
||||
}
|
||||
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
String pluginName,
|
||||
String functionName,
|
||||
@Nullable KernelArguments arguments,
|
||||
ContextVariableType<T> resultType) {
|
||||
return invokeAsync(pluginName, functionName, arguments, null, resultType);
|
||||
}
|
||||
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
KernelFunction function,
|
||||
@Nullable KernelArguments arguments,
|
||||
@Nullable KernelHooks kernelHooks,
|
||||
Class<T> resultType) {
|
||||
|
||||
kernelHooks = mergeInGlobalHooks(kernelHooks);
|
||||
|
||||
ContextVariableType<T> contextVariable;
|
||||
|
||||
try {
|
||||
@@ -80,39 +111,72 @@ public class Kernel implements Buildable {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return function.invokeAsync(this, arguments, contextVariable);
|
||||
return function.invokeAsync(this, arguments, kernelHooks, contextVariable);
|
||||
}
|
||||
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
KernelFunction function,
|
||||
@Nullable KernelArguments arguments,
|
||||
Class<T> resultType) {
|
||||
return invokeAsync(function, arguments, null, resultType);
|
||||
}
|
||||
|
||||
private KernelHooks mergeInGlobalHooks(@Nullable KernelHooks kernelHooks) {
|
||||
KernelHooks allKernelHooks = this.kernelHooks;
|
||||
if (kernelHooks != null) {
|
||||
allKernelHooks = allKernelHooks.append(kernelHooks);
|
||||
}
|
||||
return allKernelHooks;
|
||||
}
|
||||
|
||||
public List<KernelFunction> getFunctions() {
|
||||
return null;
|
||||
return plugins.getPlugins()
|
||||
.stream()
|
||||
.map(KernelPlugin::getFunctions)
|
||||
.flatMap(m -> m.values().stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public AIServiceSelector getServiceSelector() {
|
||||
return serviceSelector;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP")
|
||||
public KernelPluginCollection getPlugins() {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public <T extends AIService> T getService(Class<T> clazz) {
|
||||
return (T) serviceSelector
|
||||
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP")
|
||||
public KernelHooks getHookService() {
|
||||
return kernelHooks;
|
||||
}
|
||||
|
||||
public <T extends AIService> T getService(Class<T> clazz) throws ServiceNotFoundException {
|
||||
AIServiceSelection<T> selector = serviceSelector
|
||||
.trySelectAIService(
|
||||
clazz,
|
||||
null,
|
||||
null
|
||||
)
|
||||
.getService();
|
||||
);
|
||||
|
||||
if (selector == null) {
|
||||
throw new ServiceNotFoundException("Unable to find service of type " + clazz.getName());
|
||||
}
|
||||
|
||||
return selector.getService();
|
||||
}
|
||||
|
||||
public static Kernel.Builder builder() {
|
||||
return new Kernel.Builder();
|
||||
}
|
||||
|
||||
|
||||
public static class Builder implements SemanticKernelBuilder<Kernel> {
|
||||
|
||||
private final Map<Class<? extends AIService>, AIService> services = new HashMap<>();
|
||||
private final List<KernelPlugin> plugins = new ArrayList<>();
|
||||
@Nullable
|
||||
private Function<Map<Class<? extends AIService>, AIService>, AIServiceSelector> serviceSelectorProvider;
|
||||
|
||||
public <T extends AIService> Builder withAIService(Class<T> clazz, T aiService) {
|
||||
@@ -147,7 +211,8 @@ public class Kernel implements Buildable {
|
||||
|
||||
return new Kernel(
|
||||
serviceSelector,
|
||||
new KernelPluginCollection(plugins));
|
||||
new KernelPluginCollection(plugins),
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.microsoft.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.exceptions.SKCheckedException;
|
||||
|
||||
public class ServiceNotFoundException extends SKCheckedException {
|
||||
|
||||
public ServiceNotFoundException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+15
@@ -8,6 +8,7 @@ import com.microsoft.semantickernel.TextAIService;
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
|
||||
import com.microsoft.semantickernel.builders.ServiceLoadUtil;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
import java.util.List;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -26,6 +27,20 @@ public interface ChatCompletionService extends Buildable, TextAIService {
|
||||
Kernel kernel
|
||||
);
|
||||
|
||||
Mono<List<ChatMessageContent>> getChatMessageContentsAsync(
|
||||
ChatHistory chatHistory,
|
||||
PromptExecutionSettings promptExecutionSettings,
|
||||
Kernel kernel,
|
||||
KernelHooks kernelHooks
|
||||
);
|
||||
|
||||
Mono<List<ChatMessageContent>> getChatMessageContentsAsync(
|
||||
String prompt,
|
||||
PromptExecutionSettings promptExecutionSettings,
|
||||
Kernel kernel,
|
||||
KernelHooks kernelHooks
|
||||
);
|
||||
|
||||
static Builder builder() {
|
||||
return ServiceLoadUtil.findServiceLoader(Builder.class,
|
||||
"com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion$Builder")
|
||||
|
||||
+5
-5
@@ -3,11 +3,11 @@ package com.microsoft.semantickernel.chatcompletion;
|
||||
|
||||
import com.microsoft.semantickernel.KernelContent;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ChatMessageContent extends KernelContent<ChatMessageContent> {
|
||||
@@ -61,7 +61,7 @@ public class ChatMessageContent extends KernelContent<ChatMessageContent> {
|
||||
super(innerContent, modelId, metadata);
|
||||
this.authorRole = authorRole;
|
||||
this.encoding = encoding != null ? encoding : StandardCharsets.UTF_8;
|
||||
this.items = items;
|
||||
this.items = new ArrayList<>(items);
|
||||
}
|
||||
|
||||
public AuthorRole getAuthorRole() {
|
||||
@@ -81,11 +81,11 @@ public class ChatMessageContent extends KernelContent<ChatMessageContent> {
|
||||
}
|
||||
|
||||
public List<KernelContent> getItems() {
|
||||
return items;
|
||||
return Collections.unmodifiableList(items);
|
||||
}
|
||||
|
||||
public void setItems(List<KernelContent> items) {
|
||||
this.items = items;
|
||||
this.items = new ArrayList<>(items);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
|
||||
public class FunctionInvokedEvent<T> implements KernelHookEvent {
|
||||
|
||||
private final KernelFunction function;
|
||||
private final KernelArguments arguments;
|
||||
private final FunctionResult<T> result;
|
||||
|
||||
public FunctionInvokedEvent(KernelFunction function, KernelArguments arguments,
|
||||
FunctionResult<T> result) {
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public KernelFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public KernelArguments getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public FunctionResult<T> getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
|
||||
public class FunctionInvokingEvent implements KernelHookEvent {
|
||||
|
||||
private final KernelFunction function;
|
||||
private final KernelArguments arguments;
|
||||
|
||||
public FunctionInvokingEvent(KernelFunction function, KernelArguments arguments) {
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public KernelFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public KernelArguments getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.azure.ai.openai.models.ChatCompletionsOptions;
|
||||
import com.azure.ai.openai.models.ChatRequestMessage;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface KernelHook<T extends KernelHookEvent> extends Predicate<KernelHookEvent>, Function<T, T> {
|
||||
|
||||
interface FunctionInvokingHook extends KernelHook<FunctionInvokingEvent> {
|
||||
|
||||
@Override
|
||||
default boolean test(KernelHookEvent arguments) {
|
||||
return FunctionInvokingEvent.class.isAssignableFrom(arguments.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
interface FunctionInvokedHook extends KernelHook<FunctionInvokedEvent> {
|
||||
|
||||
@Override
|
||||
default boolean test(KernelHookEvent arguments) {
|
||||
return FunctionInvokedEvent.class.isAssignableFrom(arguments.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
interface PromptRenderingHook extends KernelHook<PromptRenderingEvent> {
|
||||
|
||||
@Override
|
||||
default boolean test(KernelHookEvent arguments) {
|
||||
return PromptRenderingEvent.class.isAssignableFrom(arguments.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
interface PromptRenderedHook extends KernelHook<PromptRenderedEvent> {
|
||||
|
||||
@Override
|
||||
default boolean test(KernelHookEvent arguments) {
|
||||
return PromptRenderedEvent.class.isAssignableFrom(arguments.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
interface PreChatCompletionHook extends KernelHook<PreChatCompletionEvent> {
|
||||
|
||||
@Override
|
||||
default boolean test(KernelHookEvent arguments) {
|
||||
return PreChatCompletionEvent.class.isAssignableFrom(arguments.getClass());
|
||||
}
|
||||
|
||||
static ChatCompletionsOptions cloneOptionsWithMessages(
|
||||
ChatCompletionsOptions options,
|
||||
List<ChatRequestMessage> messages) {
|
||||
ChatCompletionsOptions newOptions = new ChatCompletionsOptions(messages)
|
||||
.setPresencePenalty(options.getPresencePenalty())
|
||||
.setFrequencyPenalty(options.getFrequencyPenalty())
|
||||
.setLogitBias(options.getLogitBias())
|
||||
.setMaxTokens(options.getMaxTokens())
|
||||
.setModel(options.getModel())
|
||||
.setStop(options.getStop())
|
||||
.setTemperature(options.getTemperature())
|
||||
.setTools(options.getTools())
|
||||
.setTopP(options.getTopP())
|
||||
.setUser(options.getUser())
|
||||
.setDataSources(options.getDataSources())
|
||||
.setEnhancements(options.getEnhancements())
|
||||
.setFunctions(options.getFunctions())
|
||||
.setN(options.getN())
|
||||
.setResponseFormat(options.getResponseFormat())
|
||||
.setSeed(options.getSeed())
|
||||
.setStream(options.isStream())
|
||||
.setToolChoice(options.getToolChoice());
|
||||
|
||||
if (options.getFunctionCall() != null) {
|
||||
newOptions = newOptions.setFunctionCall(options.getFunctionCall());
|
||||
}
|
||||
return newOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
public interface KernelHookEvent {
|
||||
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokedHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokingHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PreChatCompletionHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderedHook;
|
||||
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderingHook;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class KernelHooks {
|
||||
|
||||
private final Map<String, KernelHook<?>> hooks;
|
||||
|
||||
public KernelHooks() {
|
||||
this.hooks = new HashMap<>();
|
||||
}
|
||||
|
||||
public KernelHooks(@Nullable KernelHooks kernelHooks) {
|
||||
if (kernelHooks == null) {
|
||||
this.hooks = new HashMap<>();
|
||||
} else {
|
||||
this.hooks = new HashMap<>(kernelHooks.getHooks());
|
||||
}
|
||||
}
|
||||
|
||||
public KernelHooks(Map<String, KernelHook<?>> hooks) {
|
||||
this.hooks = new HashMap<>(hooks);
|
||||
}
|
||||
|
||||
private Map<String, KernelHook<?>> getHooks() {
|
||||
return Collections.unmodifiableMap(hooks);
|
||||
}
|
||||
|
||||
public String addFunctionInvokingHook(
|
||||
Function<FunctionInvokingEvent, FunctionInvokingEvent> function) {
|
||||
return addHook((FunctionInvokingHook) function::apply);
|
||||
}
|
||||
|
||||
public String addFunctionInvokedHook(
|
||||
Function<FunctionInvokedEvent, FunctionInvokedEvent> function) {
|
||||
return addHook((FunctionInvokedHook) function::apply);
|
||||
}
|
||||
|
||||
public String addPreChatCompletionHook(
|
||||
Function<PreChatCompletionEvent, PreChatCompletionEvent> function) {
|
||||
return addHook((PreChatCompletionHook) function::apply);
|
||||
}
|
||||
|
||||
public String addPromptRenderedHook(
|
||||
Function<PromptRenderedEvent, PromptRenderedEvent> function) {
|
||||
return addHook((PromptRenderedHook) function::apply);
|
||||
}
|
||||
|
||||
public String addPromptRenderingHook(
|
||||
Function<PromptRenderingEvent, PromptRenderingEvent> function) {
|
||||
return addHook((PromptRenderingHook) function::apply);
|
||||
}
|
||||
|
||||
public <T extends KernelHookEvent> T executeHooks(T event) {
|
||||
for (KernelHook<?> hook : hooks.values()) {
|
||||
if (hook.test(event)) {
|
||||
event = ((KernelHook<T>) hook).apply(event);
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
public String addHook(KernelHook<?> hook) {
|
||||
return addHook(UUID.randomUUID().toString(), hook);
|
||||
}
|
||||
|
||||
public String addHook(String hookName, KernelHook<?> hook) {
|
||||
hooks.put(hookName, hook);
|
||||
return hookName;
|
||||
}
|
||||
|
||||
public KernelHook<?> removeHook(String hookName) {
|
||||
return hooks.remove(hookName);
|
||||
}
|
||||
|
||||
public KernelHooks append(KernelHooks kernelHooks) {
|
||||
Map<String, KernelHook<?>> newHooks = new HashMap<>(this.hooks);
|
||||
newHooks.putAll(this.hooks);
|
||||
newHooks.putAll(kernelHooks.getHooks());
|
||||
|
||||
return new KernelHooks(newHooks);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.azure.ai.openai.models.ChatCompletionsOptions;
|
||||
|
||||
public class PreChatCompletionEvent implements KernelHookEvent {
|
||||
|
||||
private final ChatCompletionsOptions options;
|
||||
|
||||
public PreChatCompletionEvent(ChatCompletionsOptions options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public ChatCompletionsOptions getOptions() {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
|
||||
public class PromptRenderedEvent implements KernelHookEvent {
|
||||
|
||||
private final KernelFunction function;
|
||||
private final KernelArguments arguments;
|
||||
private final String prompt;
|
||||
|
||||
public PromptRenderedEvent(KernelFunction function, KernelArguments arguments,
|
||||
String prompt) {
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
public KernelFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public KernelArguments getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public String getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.microsoft.semantickernel.hooks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
|
||||
public class PromptRenderingEvent implements KernelHookEvent {
|
||||
|
||||
private final KernelFunction function;
|
||||
private final KernelArguments arguments;
|
||||
|
||||
public PromptRenderingEvent(KernelFunction function, KernelArguments arguments) {
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public KernelFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public KernelArguments getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -1,5 +1,6 @@
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -64,6 +65,10 @@ public abstract class DefaultKernelFunction implements KernelFunction {
|
||||
@Override
|
||||
@Nullable
|
||||
public Map<String, PromptExecutionSettings> getExecutionSettings() {
|
||||
return executionSettings;
|
||||
if (executionSettings != null) {
|
||||
return Collections.unmodifiableMap(executionSettings);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class FunctionResultMetadata {
|
||||
private final CaseInsensitiveMap<ContextVariable<?>> metadata;
|
||||
|
||||
public FunctionResultMetadata(CaseInsensitiveMap<ContextVariable<?>> metadata) {
|
||||
this.metadata = metadata;
|
||||
this.metadata = new CaseInsensitiveMap<>(metadata);
|
||||
}
|
||||
|
||||
public static FunctionResultMetadata build(
|
||||
|
||||
+7
-2
@@ -3,6 +3,7 @@ package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.builders.Buildable;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import com.microsoft.semantickernel.semanticfunctions.InputVariable;
|
||||
@@ -81,6 +82,12 @@ public interface KernelFunction extends Buildable {
|
||||
@Nullable KernelArguments arguments,
|
||||
ContextVariableType<T> variableType);
|
||||
|
||||
<T> Mono<FunctionResult<T>> invokeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
KernelHooks kernelHooks,
|
||||
ContextVariableType<T> variableType);
|
||||
|
||||
@Nullable
|
||||
Map<String, PromptExecutionSettings> getExecutionSettings();
|
||||
|
||||
@@ -92,8 +99,6 @@ public interface KernelFunction extends Buildable {
|
||||
|
||||
FromPromptBuilder withPromptTemplate(PromptTemplate promptTemplate);
|
||||
|
||||
FromPromptBuilder withPluginName(String name);
|
||||
|
||||
FromPromptBuilder withExecutionSettings(
|
||||
Map<String, PromptExecutionSettings> executionSettings);
|
||||
|
||||
|
||||
+4
-2
@@ -2,6 +2,8 @@ package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.KernelReturnParameterMetadata;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class KernelFunctionMetadata {
|
||||
@@ -25,7 +27,7 @@ public class KernelFunctionMetadata {
|
||||
KernelReturnParameterMetadata<?> returnParameter) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.parameters = parameters;
|
||||
this.parameters = new ArrayList<>(parameters);
|
||||
this.returnParameter = returnParameter;
|
||||
}
|
||||
|
||||
@@ -34,7 +36,7 @@ public class KernelFunctionMetadata {
|
||||
}
|
||||
|
||||
public List<KernelParameterMetadata> getParameters() {
|
||||
return parameters;
|
||||
return Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
|
||||
+3
-3
@@ -10,6 +10,7 @@ import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTe
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -26,14 +27,14 @@ public class KernelFunctionYaml {
|
||||
String yaml,
|
||||
@Nullable PromptTemplateFactory promptTemplateFactory
|
||||
) throws IOException {
|
||||
InputStream targetStream = new ByteArrayInputStream(yaml.getBytes());
|
||||
InputStream targetStream = new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8));
|
||||
return fromYaml(targetStream, promptTemplateFactory);
|
||||
}
|
||||
|
||||
public static KernelFunction fromPromptYaml(
|
||||
String yaml
|
||||
) throws IOException {
|
||||
InputStream targetStream = new ByteArrayInputStream(yaml.getBytes());
|
||||
InputStream targetStream = new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8));
|
||||
return fromYaml(targetStream, null);
|
||||
}
|
||||
|
||||
@@ -62,7 +63,6 @@ public class KernelFunctionYaml {
|
||||
.withName(functionModel.getName())
|
||||
.withInputParameters(functionModel.getInputVariables())
|
||||
.withPromptTemplate(promptTemplate)
|
||||
.withPluginName(functionModel.getName()) // TODO: 1.0 add plugin name
|
||||
.withExecutionSettings(functionModel.getExecutionSettings())
|
||||
.withDescription(functionModel.getDescription())
|
||||
.withOutputVariable(functionModel.getOutputVariable())
|
||||
|
||||
+5
-3
@@ -1,8 +1,10 @@
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromMethod.ImplementationFunc;
|
||||
import com.microsoft.semantickernel.plugin.KernelParameterMetadata;
|
||||
import com.microsoft.semantickernel.plugin.KernelReturnParameterMetadata;
|
||||
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromMethod.ImplementationFunc;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class MethodDetails {
|
||||
@@ -22,7 +24,7 @@ public class MethodDetails {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.function = function;
|
||||
this.parameters = parameters;
|
||||
this.parameters = new ArrayList<>(parameters);
|
||||
this.returnParameter = returnParameter;
|
||||
}
|
||||
|
||||
@@ -39,7 +41,7 @@ public class MethodDetails {
|
||||
}
|
||||
|
||||
public List<KernelParameterMetadata> getParameters() {
|
||||
return parameters;
|
||||
return Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
public KernelReturnParameterMetadata getReturnParameter() {
|
||||
|
||||
+74
-53
@@ -1,22 +1,20 @@
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class PromptExecutionSettings {
|
||||
|
||||
public static final String DEFAULT_SERVICE_ID = "default";
|
||||
public static final int DEFAULT_MAX_TOKENS = 256;
|
||||
public static final double DEFAULT_TEMPERATURE= 1.0;
|
||||
public static final double DEFAULT_TEMPERATURE = 1.0;
|
||||
public static final double DEFAULT_TOP_P = 1.0;
|
||||
public static final double DEFAULT_PRESENCE_PENALTY = 0.0;
|
||||
public static final double DEFAULT_FREQUENCY_PENALTY = 0.0;
|
||||
@@ -56,12 +54,15 @@ public class PromptExecutionSettings {
|
||||
private final int bestOf;
|
||||
private final int resultsPerPrompt;
|
||||
private final String user;
|
||||
@Nullable
|
||||
private final List<String> stopSequences;
|
||||
@Nullable
|
||||
private final ToolCallBehavior toolCallBehavior;
|
||||
|
||||
/// <summary>
|
||||
/// Modify the likelihood of specified tokens appearing in the completion.
|
||||
/// </summary>s
|
||||
@Nullable
|
||||
public Map<Integer, Integer> tokenSelectionBiases;
|
||||
|
||||
@JsonCreator
|
||||
@@ -76,22 +77,24 @@ public class PromptExecutionSettings {
|
||||
@JsonProperty(RESULTS_PER_PROMPT) int resultsPerPrompt,
|
||||
@JsonProperty(BEST_OF) int bestOf,
|
||||
@JsonProperty(USER) String user,
|
||||
@Nullable
|
||||
@JsonProperty(STOP_SEQUENCES) List<String> stopSequences,
|
||||
@Nullable
|
||||
@JsonProperty(TOKEN_SELECTION_BIASES) Map<Integer, Integer> tokenSelectionBiases) {
|
||||
this(
|
||||
serviceId,
|
||||
modelId,
|
||||
temperature,
|
||||
topP,
|
||||
presencePenalty,
|
||||
frequencyPenalty,
|
||||
maxTokens,
|
||||
resultsPerPrompt,
|
||||
bestOf,
|
||||
user,
|
||||
stopSequences,
|
||||
tokenSelectionBiases,
|
||||
null);
|
||||
this(
|
||||
serviceId,
|
||||
modelId,
|
||||
temperature,
|
||||
topP,
|
||||
presencePenalty,
|
||||
frequencyPenalty,
|
||||
maxTokens,
|
||||
resultsPerPrompt,
|
||||
bestOf,
|
||||
user,
|
||||
stopSequences,
|
||||
tokenSelectionBiases,
|
||||
null);
|
||||
}
|
||||
|
||||
public PromptExecutionSettings(
|
||||
@@ -108,19 +111,23 @@ public class PromptExecutionSettings {
|
||||
@Nullable List<String> stopSequences,
|
||||
@Nullable Map<Integer, Integer> tokenSelectionBiases,
|
||||
@Nullable ToolCallBehavior toolCallBehavior) {
|
||||
this.serviceId = serviceId;
|
||||
this.modelId = modelId;
|
||||
this.temperature = temperature;
|
||||
this.topP = topP;
|
||||
this.presencePenalty = presencePenalty;
|
||||
this.frequencyPenalty = frequencyPenalty;
|
||||
this.maxTokens = maxTokens;
|
||||
this.resultsPerPrompt = resultsPerPrompt;
|
||||
this.bestOf = bestOf;
|
||||
this.user = user;
|
||||
this.stopSequences = stopSequences != null ? stopSequences : Collections.emptyList();
|
||||
this.tokenSelectionBiases = tokenSelectionBiases != null ? tokenSelectionBiases : Collections.emptyMap();
|
||||
this.toolCallBehavior = toolCallBehavior;
|
||||
this.serviceId = serviceId;
|
||||
this.modelId = modelId;
|
||||
this.temperature = temperature;
|
||||
this.topP = topP;
|
||||
this.presencePenalty = presencePenalty;
|
||||
this.frequencyPenalty = frequencyPenalty;
|
||||
this.maxTokens = maxTokens;
|
||||
this.resultsPerPrompt = resultsPerPrompt;
|
||||
this.bestOf = bestOf;
|
||||
this.user = user;
|
||||
this.stopSequences =
|
||||
stopSequences != null ? new ArrayList<>(stopSequences) : Collections.emptyList();
|
||||
this.tokenSelectionBiases =
|
||||
tokenSelectionBiases != null ? new HashMap<>(tokenSelectionBiases)
|
||||
: Collections.emptyMap();
|
||||
this.toolCallBehavior =
|
||||
toolCallBehavior != null ? new ToolCallBehavior(toolCallBehavior) : null;
|
||||
}
|
||||
|
||||
@JsonProperty(SERVICE_ID)
|
||||
@@ -143,7 +150,7 @@ public class PromptExecutionSettings {
|
||||
return topP;
|
||||
}
|
||||
|
||||
@JsonProperty(PRESENCE_PENALTY)
|
||||
@JsonProperty(PRESENCE_PENALTY)
|
||||
public double getPresencePenalty() {
|
||||
return presencePenalty;
|
||||
}
|
||||
@@ -175,19 +182,30 @@ public class PromptExecutionSettings {
|
||||
}
|
||||
|
||||
@JsonProperty(STOP_SEQUENCES)
|
||||
@Nullable
|
||||
public List<String> getStopSequences() {
|
||||
return stopSequences;
|
||||
if (stopSequences != null) {
|
||||
return Collections.unmodifiableList(stopSequences);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@JsonProperty(TOKEN_SELECTION_BIASES)
|
||||
@Nullable
|
||||
public Map<Integer, Integer> getTokenSelectionBiases() {
|
||||
return tokenSelectionBiases;
|
||||
if (tokenSelectionBiases != null) {
|
||||
return Collections.unmodifiableMap(tokenSelectionBiases);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Nullable
|
||||
public ToolCallBehavior getToolCallBehavior() {
|
||||
return toolCallBehavior;
|
||||
if (toolCallBehavior != null) {
|
||||
return new ToolCallBehavior(toolCallBehavior);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
@@ -265,7 +283,8 @@ public class PromptExecutionSettings {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Builder withStopSequences(List<String> stopSequences) {
|
||||
if (stopSequences != null) {
|
||||
((List<String>)settings.computeIfAbsent(STOP_SEQUENCES, k -> new ArrayList<>())).addAll(stopSequences);
|
||||
((List<String>) settings.computeIfAbsent(STOP_SEQUENCES,
|
||||
k -> new ArrayList<>())).addAll(stopSequences);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -273,7 +292,8 @@ public class PromptExecutionSettings {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Builder withTokenSelectionBiases(Map<Integer, Integer> tokenSelectionBiases) {
|
||||
if (tokenSelectionBiases != null) {
|
||||
((Map<Integer, Integer>)settings.computeIfAbsent(TOKEN_SELECTION_BIASES, k -> new HashMap<>())).putAll(tokenSelectionBiases);
|
||||
((Map<Integer, Integer>) settings.computeIfAbsent(TOKEN_SELECTION_BIASES,
|
||||
k -> new HashMap<>())).putAll(tokenSelectionBiases);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -281,19 +301,20 @@ public class PromptExecutionSettings {
|
||||
@SuppressWarnings("unchecked")
|
||||
public PromptExecutionSettings build() {
|
||||
return new PromptExecutionSettings(
|
||||
(String)settings.getOrDefault(SERVICE_ID, ""),
|
||||
(String)settings.getOrDefault(MODEL_ID, ""),
|
||||
(double)settings.getOrDefault(TEMPERATURE, DEFAULT_TEMPERATURE),
|
||||
(double)settings.getOrDefault(TOP_P, DEFAULT_TOP_P),
|
||||
(double)settings.getOrDefault(PRESENCE_PENALTY, DEFAULT_PRESENCE_PENALTY),
|
||||
(double)settings.getOrDefault(FREQUENCY_PENALTY, DEFAULT_FREQUENCY_PENALTY),
|
||||
(int)settings.getOrDefault(MAX_TOKENS, DEFAULT_MAX_TOKENS),
|
||||
(int)settings.getOrDefault(RESULTS_PER_PROMPT, DEFAULT_RESULTS_PER_PROMPT),
|
||||
(int)settings.getOrDefault(BEST_OF, DEFAULT_BEST_OF),
|
||||
(String)settings.getOrDefault(USER, ""),
|
||||
(List<String>)settings.getOrDefault(STOP_SEQUENCES, Collections.emptyList()),
|
||||
(Map<Integer, Integer>)settings.getOrDefault(TOKEN_SELECTION_BIASES, Collections.emptyMap()),
|
||||
(ToolCallBehavior)settings.getOrDefault("toolCallBehavior", new ToolCallBehavior())
|
||||
(String) settings.getOrDefault(SERVICE_ID, ""),
|
||||
(String) settings.getOrDefault(MODEL_ID, ""),
|
||||
(double) settings.getOrDefault(TEMPERATURE, DEFAULT_TEMPERATURE),
|
||||
(double) settings.getOrDefault(TOP_P, DEFAULT_TOP_P),
|
||||
(double) settings.getOrDefault(PRESENCE_PENALTY, DEFAULT_PRESENCE_PENALTY),
|
||||
(double) settings.getOrDefault(FREQUENCY_PENALTY, DEFAULT_FREQUENCY_PENALTY),
|
||||
(int) settings.getOrDefault(MAX_TOKENS, DEFAULT_MAX_TOKENS),
|
||||
(int) settings.getOrDefault(RESULTS_PER_PROMPT, DEFAULT_RESULTS_PER_PROMPT),
|
||||
(int) settings.getOrDefault(BEST_OF, DEFAULT_BEST_OF),
|
||||
(String) settings.getOrDefault(USER, ""),
|
||||
(List<String>) settings.getOrDefault(STOP_SEQUENCES, Collections.emptyList()),
|
||||
(Map<Integer, Integer>) settings.getOrDefault(TOKEN_SELECTION_BIASES,
|
||||
Collections.emptyMap()),
|
||||
(ToolCallBehavior) settings.getOrDefault("toolCallBehavior", new ToolCallBehavior())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
|
||||
public class TextRequestContent<T> {
|
||||
|
||||
/// <summary>
|
||||
/// In a scenario of multiple choices per request, this represents zero-based index of the choice in the streaming sequence
|
||||
/// </summary>
|
||||
public int choiceIndex;
|
||||
|
||||
/// <summary>
|
||||
/// The inner content representation. Use this to bypass the current abstraction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The usage of this property is considered "unsafe". Use it only if strictly necessary.
|
||||
/// </remarks>
|
||||
public T innerContent;
|
||||
|
||||
/// <summary>
|
||||
/// The model ID used to generate the content.
|
||||
/// </summary>
|
||||
public String modelId;
|
||||
|
||||
/// <summary>
|
||||
/// The metadata associated with the content.
|
||||
/// </summary>
|
||||
public KernelArguments metadata;
|
||||
|
||||
|
||||
public TextRequestContent(T content) {
|
||||
this.innerContent = content;
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -4,7 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines the behavior of a tool call. Currently, the only tool available is function calling.
|
||||
* Defines the behavior of a tool call. Currently, the only tool available is function calling.
|
||||
*/
|
||||
public class ToolCallBehavior {
|
||||
|
||||
@@ -46,6 +46,12 @@ public class ToolCallBehavior {
|
||||
public ToolCallBehavior() {
|
||||
}
|
||||
|
||||
public ToolCallBehavior(ToolCallBehavior toolCallBehavior) {
|
||||
flags.putAll(toolCallBehavior.flags);
|
||||
functionSettings.putAll(toolCallBehavior.functionSettings);
|
||||
settings.putAll(toolCallBehavior.settings);
|
||||
}
|
||||
|
||||
public ToolCallBehavior kernelFunctions(boolean enable) {
|
||||
setFlag("kernelFunctions", enable);
|
||||
return this;
|
||||
@@ -61,7 +67,7 @@ public class ToolCallBehavior {
|
||||
String key = FunctionCallBehavior.getKey(function);
|
||||
functionSettings.compute(
|
||||
key,
|
||||
(k,v) -> {
|
||||
(k, v) -> {
|
||||
if (v == null) {
|
||||
return new FunctionCallBehavior(function, require, false);
|
||||
} else {
|
||||
@@ -78,7 +84,7 @@ public class ToolCallBehavior {
|
||||
String key = FunctionCallBehavior.getKey(function);
|
||||
functionSettings.compute(
|
||||
key,
|
||||
(k,v) -> {
|
||||
(k, v) -> {
|
||||
if (v == null) {
|
||||
return new FunctionCallBehavior(function, false, enable);
|
||||
} else {
|
||||
@@ -93,7 +99,7 @@ public class ToolCallBehavior {
|
||||
public ToolCallBehavior maximumAutoInvokeAttempts(int maximumAutoInvokeAttempts) {
|
||||
setSetting("maximumAutoInvokeAttempts", maximumAutoInvokeAttempts);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean kernelFunctionsEnabled() {
|
||||
return getFlag("kernelFunctions");
|
||||
@@ -127,7 +133,7 @@ public class ToolCallBehavior {
|
||||
}
|
||||
|
||||
public boolean functionEnabled(String pluginName, String functionName) {
|
||||
|
||||
|
||||
String key = FunctionCallBehavior.getKey(pluginName, functionName);
|
||||
if (functionSettings.containsKey(key)) {
|
||||
return functionSettings.get(key).enabled();
|
||||
|
||||
+2
@@ -7,6 +7,7 @@ import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CaseInsensitiveMap<T> extends HashMap<String, T> {
|
||||
|
||||
@@ -53,6 +54,7 @@ public class CaseInsensitiveMap<T> extends HashMap<String, T> {
|
||||
return super.containsKey(((String) key).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T get(Object key) {
|
||||
if (key == null) {
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
package com.microsoft.semantickernel.orchestration.contextvariables;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -75,7 +76,7 @@ public class ContextVariableTypeConverter<T> {
|
||||
this.fromObject = fromObject;
|
||||
this.toPromptString = toPromptString;
|
||||
this.fromPromptString = fromPromptString;
|
||||
this.toObjects = toObjects;
|
||||
this.toObjects = new ArrayList<>(toObjects);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +105,7 @@ public class ContextVariableTypeConverter<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T fromObject(Object s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
@@ -118,6 +120,7 @@ public class ContextVariableTypeConverter<T> {
|
||||
return toPromptString.apply(t);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T fromPromptString(String t) {
|
||||
if (t == null) {
|
||||
return null;
|
||||
|
||||
+5
-3
@@ -2,12 +2,14 @@
|
||||
package com.microsoft.semantickernel.orchestration.contextvariables;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
/// <summary>
|
||||
/// Context Variables is a data structure that holds temporary data while a task is being performed.
|
||||
@@ -161,7 +163,7 @@ public class DefaultKernelArguments implements KernelArguments, WritableKernelAr
|
||||
@Nullable
|
||||
@Override
|
||||
public Map<String, PromptExecutionSettings> getExecutionSettings() {
|
||||
return executionSettings;
|
||||
return Collections.unmodifiableMap(executionSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public interface KernelArguments extends Buildable, Map<String, ContextVariable<
|
||||
* @return content of the variable
|
||||
*/
|
||||
@Nullable
|
||||
<T extends ContextVariable<?>> T get(String key);
|
||||
ContextVariable<?> get(String key);
|
||||
|
||||
/**
|
||||
* Return the variable with the given name
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
package com.microsoft.semantickernel.plugin;
|
||||
|
||||
public class KernelParameterMetadata {
|
||||
public class KernelParameterMetadata<T> {
|
||||
|
||||
/// <summary>The name of the parameter.</summary>
|
||||
private final String name;
|
||||
@@ -8,18 +8,18 @@ public class KernelParameterMetadata {
|
||||
private final String description;
|
||||
private final String defaultValue;
|
||||
private final boolean isRequired;
|
||||
private final Class<?> parameterType;
|
||||
private final Class<T> parameterType;
|
||||
|
||||
public KernelParameterMetadata(
|
||||
String name,
|
||||
String description,
|
||||
Class<?> parameterType,
|
||||
Class<T> parameterType,
|
||||
String defaultValue, boolean isRequired) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultValue = defaultValue;
|
||||
this.isRequired = isRequired;
|
||||
this.parameterType = String.class;
|
||||
this.parameterType = parameterType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
+6
-7
@@ -1,11 +1,10 @@
|
||||
package com.microsoft.semantickernel.plugin;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.CaseInsensitiveMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class KernelPlugin implements Iterable<KernelFunction> {
|
||||
|
||||
@@ -20,17 +19,17 @@ public class KernelPlugin implements Iterable<KernelFunction> {
|
||||
this.description = description;
|
||||
this.functions = new CaseInsensitiveMap<>();
|
||||
if (plugins != null) {
|
||||
plugins.forEach((key,kerneFunction) -> this.functions.put(key, kerneFunction));
|
||||
this.functions.putAll(plugins);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, KernelFunction> getFunctions() {
|
||||
return functions;
|
||||
return Collections.unmodifiableMap(functions);
|
||||
}
|
||||
|
||||
public KernelFunction get(String functionName) {
|
||||
return functions.get(functionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<KernelFunction> iterator() {
|
||||
|
||||
+9
-9
@@ -1,19 +1,17 @@
|
||||
package com.microsoft.semantickernel.plugin;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.CaseInsensitiveMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.CaseInsensitiveMap;
|
||||
|
||||
public class KernelPluginCollection implements Iterable<KernelPlugin> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KernelPluginCollection.class);
|
||||
@@ -28,12 +26,10 @@ public class KernelPluginCollection implements Iterable<KernelPlugin> {
|
||||
plugins.forEach(plugin -> this.plugins.put(plugin.getName(), plugin));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public KernelFunction getFunction(String pluginName, String functionName) {
|
||||
KernelPlugin plugin = plugins.get(pluginName);
|
||||
if (plugin == null) {
|
||||
LOGGER.warn("Failed to find plugin '{}'", pluginName);
|
||||
return null;
|
||||
throw new IllegalArgumentException("Failed to find plugin " + pluginName);
|
||||
}
|
||||
KernelFunction function = plugin.get(functionName);
|
||||
|
||||
@@ -56,6 +52,10 @@ public class KernelPluginCollection implements Iterable<KernelPlugin> {
|
||||
return plugins.values().iterator();
|
||||
}
|
||||
|
||||
public List<KernelPlugin> getPlugins() {
|
||||
return new ArrayList<>(plugins.values());
|
||||
}
|
||||
|
||||
public void add(KernelPlugin plugin) {
|
||||
if (plugins.containsKey(plugin.getName())) {
|
||||
LOGGER.warn("Plugin {} already exists, overwriting existing plugin", plugin.getName());
|
||||
|
||||
+5
-5
@@ -1,6 +1,5 @@
|
||||
package com.microsoft.semantickernel.plugin;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.microsoft.semantickernel.exceptions.SKException;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
@@ -22,7 +21,6 @@ import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -219,11 +217,13 @@ public class KernelPluginFactory {
|
||||
|
||||
return new Builder().withName(config.getName()).withDescription(config.getDescription())
|
||||
.withExecutionSettings(config.getExecutionSettings())
|
||||
.withInputParameters(config.getInputVariables()).withPromptTemplate(promptTemplate)
|
||||
.withPluginName(pluginDirectoryName).withTemplate(template)
|
||||
.withInputParameters(config.getInputVariables()
|
||||
).withPromptTemplate(promptTemplate)
|
||||
.withTemplate(template)
|
||||
.withTemplateFormat(config.getTemplateFormat())
|
||||
.withOutputVariable(config.getOutputVariable())
|
||||
.withPromptTemplateFactory(promptTemplateFactory).build();
|
||||
.withPromptTemplateFactory(promptTemplateFactory)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static KernelPlugin importPluginFromResourcesDirectory(String parentDirectory,
|
||||
|
||||
+1
-1
@@ -27,6 +27,6 @@ public class Plugin {
|
||||
}
|
||||
|
||||
public List<KernelFunction> functions() {
|
||||
return functions;
|
||||
return Collections.unmodifiableList(functions);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,12 +2,13 @@ package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AggregatorPromptTemplateFactory implements PromptTemplateFactory {
|
||||
private final List<PromptTemplateFactory> templateFactories;
|
||||
public AggregatorPromptTemplateFactory(List<PromptTemplateFactory> templateFactories) {
|
||||
this.templateFactories = templateFactories;
|
||||
this.templateFactories = new ArrayList<>(templateFactories);
|
||||
}
|
||||
@Override
|
||||
public PromptTemplate tryCreate(@NonNull PromptTemplateConfig templateConfig) {
|
||||
|
||||
+56
-39
@@ -5,6 +5,9 @@ import static com.microsoft.semantickernel.plugin.annotations.KernelFunctionPara
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.exceptions.AIException;
|
||||
import com.microsoft.semantickernel.exceptions.AIException.ErrorCodes;
|
||||
import com.microsoft.semantickernel.hooks.FunctionInvokedEvent;
|
||||
import com.microsoft.semantickernel.hooks.FunctionInvokingEvent;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.orchestration.DefaultKernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
@@ -66,7 +69,21 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
ContextVariableType<T> variableType) {
|
||||
return function.invoke(kernel, this, arguments);
|
||||
return function.invoke(kernel, this, arguments, kernel.getHookService());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
@Nullable KernelHooks kernelHooks,
|
||||
ContextVariableType<T> variableType) {
|
||||
|
||||
if (kernelHooks == null) {
|
||||
kernelHooks = kernel.getHookService();
|
||||
}
|
||||
|
||||
return function.invoke(kernel, this, arguments, kernelHooks);
|
||||
}
|
||||
|
||||
public interface ImplementationFunc {
|
||||
@@ -75,7 +92,8 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
Kernel kernel,
|
||||
KernelFunction function,
|
||||
@Nullable
|
||||
KernelArguments arguments);
|
||||
KernelArguments arguments,
|
||||
KernelHooks kernelHooks);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,16 +156,22 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
|
||||
return new ImplementationFunc() {
|
||||
@Override
|
||||
public <T> Mono<FunctionResult<T>> invoke(Kernel kernel, KernelFunction function,
|
||||
public <T> Mono<FunctionResult<T>> invoke(
|
||||
Kernel kernel,
|
||||
KernelFunction function,
|
||||
@Nullable
|
||||
KernelArguments arguments) {
|
||||
KernelArguments arguments,
|
||||
KernelHooks kernelHooks) {
|
||||
|
||||
//Set<Parameter> inputArgs = determineInputArgs(method);
|
||||
FunctionInvokingEvent updatedState = kernelHooks
|
||||
.executeHooks(
|
||||
new FunctionInvokingEvent(function, arguments));
|
||||
KernelArguments updatedArguments = updatedState.getArguments();
|
||||
|
||||
try {
|
||||
List<Object> args =
|
||||
Arrays.stream(method.getParameters())
|
||||
.map(getParameters(method, arguments, kernel))
|
||||
.map(getParameters(method, updatedArguments, kernel))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Mono<?> mono;
|
||||
@@ -169,7 +193,13 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
});
|
||||
|
||||
return r
|
||||
.map(it -> new FunctionResult<>(ContextVariable.of(it)));
|
||||
.map(it -> new FunctionResult<>(ContextVariable.of(it)))
|
||||
.map(it -> {
|
||||
FunctionInvokedEvent<T> updatedResult = kernelHooks
|
||||
.executeHooks(
|
||||
new FunctionInvokedEvent<>(function, updatedArguments, it));
|
||||
return updatedResult.getResult();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
return Mono.error(e);
|
||||
}
|
||||
@@ -232,22 +262,10 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
|
||||
ContextVariable<?> arg = context == null ? null : context.get(variableName);
|
||||
if (arg == null) {
|
||||
/*
|
||||
// If this is bound to input get the input value
|
||||
if (inputArgs.contains(parameter)) {
|
||||
ContextVariable<?> input = context.get(KernelArguments.MAIN_KEY);
|
||||
if (input != null) {
|
||||
arg = input;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (arg == null) {
|
||||
KernelFunctionParameter annotation =
|
||||
parameter.getAnnotation(KernelFunctionParameter.class);
|
||||
if (annotation != null) {
|
||||
// Convert from the defaultValue, which is a String to the argument type
|
||||
KernelFunctionParameter annotation =
|
||||
parameter.getAnnotation(KernelFunctionParameter.class);
|
||||
if (annotation != null) {
|
||||
// Convert from the defaultValue, which is a String to the argument type
|
||||
// Expectation here is that the fromPromptString method will be able to handle a null or empty string
|
||||
Class<?> type = annotation.type();
|
||||
ContextVariableType<?> cvType = ContextVariableTypes.getDefaultVariableTypeForClass(type);
|
||||
@@ -257,22 +275,21 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
arg = ContextVariable.of(value);
|
||||
}
|
||||
|
||||
if (NO_DEFAULT_VALUE.equals(arg)) {
|
||||
if (!annotation.required()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new AIException(
|
||||
AIException.ErrorCodes.INVALID_CONFIGURATION,
|
||||
"Attempted to invoke function "
|
||||
+ method.getDeclaringClass().getName()
|
||||
+ "."
|
||||
+ method.getName()
|
||||
+ ". The context variable \""
|
||||
+ variableName
|
||||
+ "\" has not been set, and no default value is"
|
||||
+ " specified.");
|
||||
if (arg != null && NO_DEFAULT_VALUE.equals(arg.getValue())) {
|
||||
if (!annotation.required()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new AIException(
|
||||
AIException.ErrorCodes.INVALID_CONFIGURATION,
|
||||
"Attempted to invoke function "
|
||||
+ method.getDeclaringClass().getName()
|
||||
+ "."
|
||||
+ method.getName()
|
||||
+ ". The context variable \""
|
||||
+ variableName
|
||||
+ "\" has not been set, and no default value is"
|
||||
+ " specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,7 +298,7 @@ public class KernelFunctionFromMethod extends DefaultKernelFunction {
|
||||
LOGGER.warn(formErrorMessage(method, parameter));
|
||||
}
|
||||
|
||||
if (NO_DEFAULT_VALUE.equals(arg)) {
|
||||
if (arg != null && NO_DEFAULT_VALUE.equals(arg.getValue())) {
|
||||
if (parameter.getName().matches("arg\\d")) {
|
||||
throw new AIException(
|
||||
AIException.ErrorCodes.INVALID_CONFIGURATION,
|
||||
|
||||
+55
-19
@@ -8,17 +8,23 @@ import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.TextAIService;
|
||||
import com.microsoft.semantickernel.chatcompletion.AuthorRole;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
|
||||
import com.microsoft.semantickernel.hooks.FunctionInvokedEvent;
|
||||
import com.microsoft.semantickernel.hooks.FunctionInvokingEvent;
|
||||
import com.microsoft.semantickernel.hooks.KernelHooks;
|
||||
import com.microsoft.semantickernel.hooks.PromptRenderedEvent;
|
||||
import com.microsoft.semantickernel.hooks.PromptRenderingEvent;
|
||||
import com.microsoft.semantickernel.orchestration.DefaultKernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunction;
|
||||
import com.microsoft.semantickernel.orchestration.KernelFunctionMetadata;
|
||||
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableTypes;
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import com.microsoft.semantickernel.services.AIServiceSelection;
|
||||
import com.microsoft.semantickernel.textcompletion.TextGenerationService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -83,23 +89,36 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private <T> Flux<FunctionResult<T>> invokeInternalAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
KernelHooks kernelHooks,
|
||||
ContextVariableType<T> variableType) {
|
||||
|
||||
PromptRenderingEvent preRenderingHookResult = kernelHooks
|
||||
.executeHooks(new PromptRenderingEvent(this, arguments));
|
||||
|
||||
return this
|
||||
.template
|
||||
.renderAsync(kernel, arguments)
|
||||
.renderAsync(kernel, preRenderingHookResult.getArguments())
|
||||
.flatMapMany(prompt -> {
|
||||
PromptRenderedEvent promptHookResult = kernelHooks
|
||||
.executeHooks(new PromptRenderedEvent(this, arguments, prompt));
|
||||
prompt = promptHookResult.getPrompt();
|
||||
KernelArguments args = promptHookResult.getArguments();
|
||||
|
||||
LOGGER.info("RENDERED PROMPT: \n{}", prompt);
|
||||
|
||||
FunctionInvokingEvent updateArguments = kernelHooks
|
||||
.executeHooks(new FunctionInvokingEvent(this, args));
|
||||
args = updateArguments.getArguments();
|
||||
|
||||
AIServiceSelection aiServiceSelection = kernel
|
||||
.getServiceSelector()
|
||||
.trySelectAIService(
|
||||
TextAIService.class,
|
||||
this,
|
||||
arguments
|
||||
args
|
||||
);
|
||||
|
||||
AIService client = aiServiceSelection.getService();
|
||||
@@ -117,7 +136,8 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
.getChatMessageContentsAsync(
|
||||
prompt,
|
||||
executionSettings,
|
||||
kernel)
|
||||
kernel,
|
||||
kernelHooks)
|
||||
.flatMapMany(Flux::fromIterable)
|
||||
.concatMap(chatMessageContent -> {
|
||||
if (chatMessageContent.getAuthorRole()
|
||||
@@ -157,8 +177,6 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
it.getMetadata()
|
||||
);
|
||||
});
|
||||
return result;
|
||||
|
||||
} else if (client instanceof TextGenerationService) {
|
||||
result = ((TextGenerationService) client)
|
||||
.getTextContentsAsync(
|
||||
@@ -190,7 +208,18 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
} else {
|
||||
return Flux.error(new IllegalStateException("Unknown service type"));
|
||||
}
|
||||
return result;
|
||||
|
||||
return result
|
||||
.map(it -> {
|
||||
FunctionInvokedEvent<T> updatedResult = kernelHooks
|
||||
.executeHooks(
|
||||
new FunctionInvokedEvent<>(
|
||||
this,
|
||||
arguments,
|
||||
it));
|
||||
|
||||
return updatedResult.getResult();
|
||||
});
|
||||
})
|
||||
.doOnError(
|
||||
ex -> {
|
||||
@@ -228,12 +257,25 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
@Nullable KernelHooks kernelHooks,
|
||||
ContextVariableType<T> variableType) {
|
||||
return invokeInternalAsync(kernel, arguments, variableType)
|
||||
if (kernelHooks == null) {
|
||||
kernelHooks = kernel.getHookService();
|
||||
}
|
||||
return invokeInternalAsync(kernel, arguments, kernelHooks, variableType)
|
||||
.take(1)
|
||||
.single();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Mono<FunctionResult<T>> invokeAsync(
|
||||
Kernel kernel,
|
||||
@Nullable KernelArguments arguments,
|
||||
ContextVariableType<T> variableType) {
|
||||
return invokeAsync(kernel, arguments, null, variableType);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given a json string, invoke the tool specified in the json string.
|
||||
* At this time, the only tool we have is 'function'.
|
||||
@@ -327,12 +369,11 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
|
||||
private PromptTemplate promptTemplate;
|
||||
private String name;
|
||||
private String pluginName;
|
||||
private Map<String, PromptExecutionSettings> executionSettings;
|
||||
private String description;
|
||||
private List<InputVariable> inputVariables;
|
||||
private String template;
|
||||
private String templateFormat;
|
||||
private String templateFormat = PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT;
|
||||
private OutputVariable outputVariable;
|
||||
private PromptTemplateFactory promptTemplateFactory;
|
||||
|
||||
@@ -345,7 +386,7 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder withInputParameters(List<InputVariable> inputVariables) {
|
||||
this.inputVariables = inputVariables;
|
||||
this.inputVariables = new ArrayList<>(inputVariables);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -355,12 +396,6 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder withPluginName(String name) {
|
||||
this.pluginName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FromPromptBuilder withExecutionSettings(
|
||||
Map<String, PromptExecutionSettings> executionSettings) {
|
||||
@@ -381,7 +416,8 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction {
|
||||
this.executionSettings = new HashMap<>();
|
||||
}
|
||||
|
||||
this.executionSettings.put("default", executionSettings);
|
||||
this.executionSettings.put(PromptExecutionSettings.DEFAULT_SERVICE_ID,
|
||||
executionSettings);
|
||||
|
||||
if (executionSettings.getServiceId() != null) {
|
||||
this.executionSettings.put(executionSettings.getServiceId(), executionSettings);
|
||||
|
||||
+2
-5
@@ -5,15 +5,12 @@ import static com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfi
|
||||
|
||||
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
|
||||
import com.microsoft.semantickernel.templateengine.semantickernel.DefaultPromptTemplate;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Locale;
|
||||
|
||||
public class KernelPromptTemplateFactory implements PromptTemplateFactory {
|
||||
|
||||
public PromptTemplate tryCreate(PromptTemplateConfig templateConfig) {
|
||||
if (templateConfig == null || templateConfig.getTemplateFormat() == null) {
|
||||
return new DefaultPromptTemplate(templateConfig);
|
||||
}
|
||||
|
||||
public PromptTemplate tryCreate(@Nonnull PromptTemplateConfig templateConfig) {
|
||||
switch (templateConfig.getTemplateFormat().toLowerCase(Locale.ROOT)) {
|
||||
case SEMANTIC_KERNEL_TEMPLATE_FORMAT:
|
||||
return new DefaultPromptTemplate(templateConfig);
|
||||
|
||||
+34
-91
@@ -16,11 +16,13 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class PromptTemplateConfig {
|
||||
|
||||
public static final int CURRENT_SCHEMA = 1;
|
||||
public static final String DEFAULT_CONFIG_NAME = "default";
|
||||
private String name;
|
||||
|
||||
private String template;
|
||||
@@ -40,7 +42,7 @@ public class PromptTemplateConfig {
|
||||
public PromptTemplateConfig(String template) {
|
||||
this(
|
||||
CURRENT_SCHEMA,
|
||||
"default",
|
||||
DEFAULT_CONFIG_NAME,
|
||||
template,
|
||||
SEMANTIC_KERNEL_TEMPLATE_FORMAT,
|
||||
"",
|
||||
@@ -58,7 +60,10 @@ public class PromptTemplateConfig {
|
||||
String name,
|
||||
@JsonProperty("template")
|
||||
String template,
|
||||
@JsonProperty("template_format")
|
||||
@Nullable
|
||||
@JsonProperty(
|
||||
value = "template_format",
|
||||
defaultValue = SEMANTIC_KERNEL_TEMPLATE_FORMAT)
|
||||
String templateFormat,
|
||||
@JsonProperty("description")
|
||||
String description,
|
||||
@@ -70,6 +75,9 @@ public class PromptTemplateConfig {
|
||||
Map<String, PromptExecutionSettings> executionSettings) {
|
||||
this.name = name;
|
||||
this.template = template;
|
||||
if (templateFormat == null) {
|
||||
templateFormat = SEMANTIC_KERNEL_TEMPLATE_FORMAT;
|
||||
}
|
||||
this.templateFormat = templateFormat;
|
||||
this.description = description;
|
||||
if (inputVariables == null) {
|
||||
@@ -78,7 +86,11 @@ public class PromptTemplateConfig {
|
||||
this.inputVariables = new ArrayList<>(inputVariables);
|
||||
}
|
||||
this.outputVariable = outputVariable;
|
||||
this.executionSettings = executionSettings;
|
||||
if (executionSettings == null) {
|
||||
this.executionSettings = new HashMap<>();
|
||||
} else {
|
||||
this.executionSettings = new HashMap<>(executionSettings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +119,18 @@ public class PromptTemplateConfig {
|
||||
);
|
||||
}
|
||||
|
||||
public PromptTemplateConfig(PromptTemplateConfig promptTemplate) {
|
||||
this(
|
||||
promptTemplate.name,
|
||||
promptTemplate.template,
|
||||
promptTemplate.templateFormat,
|
||||
promptTemplate.description,
|
||||
promptTemplate.inputVariables,
|
||||
promptTemplate.outputVariable,
|
||||
promptTemplate.executionSettings
|
||||
);
|
||||
}
|
||||
|
||||
public List<KernelParameterMetadata> getKernelParametersMetadata() {
|
||||
if (inputVariables == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -134,98 +158,16 @@ public class PromptTemplateConfig {
|
||||
}
|
||||
|
||||
public void addInputVariable(InputVariable inputVariable) {
|
||||
if (inputVariables == null) {
|
||||
inputVariables = new ArrayList<>();
|
||||
}
|
||||
inputVariables.add(inputVariable);
|
||||
}
|
||||
|
||||
|
||||
public static class ExecutionSettingsModel {
|
||||
|
||||
@JsonProperty("model_id")
|
||||
private String modelId;
|
||||
|
||||
@JsonProperty("model_id_pattern")
|
||||
private String modelIdPattern;
|
||||
|
||||
@JsonProperty("service_id")
|
||||
private String serviceId;
|
||||
|
||||
@JsonProperty("temperature")
|
||||
private String temperature;
|
||||
|
||||
@JsonProperty("additional_properties")
|
||||
private final Map<String, Object> additionalProperties;
|
||||
|
||||
public Object get(String propertyName) {
|
||||
return additionalProperties.get(propertyName);
|
||||
}
|
||||
|
||||
public void set(String propertyName, Object value) {
|
||||
additionalProperties.put(propertyName, value);
|
||||
}
|
||||
|
||||
public ExecutionSettingsModel() {
|
||||
this.additionalProperties = new HashMap<>();
|
||||
}
|
||||
|
||||
public ExecutionSettingsModel(
|
||||
String modelId,
|
||||
String modelIdPattern,
|
||||
String serviceId,
|
||||
String temperature,
|
||||
Map<String, Object> additionalProperties) {
|
||||
this.modelId = modelId;
|
||||
this.modelIdPattern = modelIdPattern;
|
||||
this.serviceId = serviceId;
|
||||
this.temperature = temperature;
|
||||
this.additionalProperties = additionalProperties;
|
||||
}
|
||||
|
||||
public String getModelId() {
|
||||
return modelId;
|
||||
}
|
||||
|
||||
public void setModelId(String modelId) {
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public String getModelIdPattern() {
|
||||
return modelIdPattern;
|
||||
}
|
||||
|
||||
public void setModelIdPattern(String modelIdPattern) {
|
||||
this.modelIdPattern = modelIdPattern;
|
||||
}
|
||||
|
||||
public String getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
public void setServiceId(String serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
public String getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(String temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAdditionalProperties() {
|
||||
return additionalProperties;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
public PromptTemplateConfig setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTemplate() {
|
||||
@@ -253,11 +195,11 @@ public class PromptTemplateConfig {
|
||||
}
|
||||
|
||||
public List<InputVariable> getInputVariables() {
|
||||
return inputVariables;
|
||||
return Collections.unmodifiableList(inputVariables);
|
||||
}
|
||||
|
||||
public void setInputVariables(List<InputVariable> inputVariables) {
|
||||
this.inputVariables = inputVariables;
|
||||
this.inputVariables = new ArrayList<>(inputVariables);
|
||||
}
|
||||
|
||||
public OutputVariable getOutputVariable() {
|
||||
@@ -269,11 +211,12 @@ public class PromptTemplateConfig {
|
||||
}
|
||||
|
||||
public Map<String, PromptExecutionSettings> getExecutionSettings() {
|
||||
return executionSettings;
|
||||
return Collections.unmodifiableMap(executionSettings);
|
||||
}
|
||||
|
||||
|
||||
public void setExecutionSettings(Map<String, PromptExecutionSettings> executionSettings) {
|
||||
this.executionSettings = executionSettings;
|
||||
this.executionSettings = new HashMap<>(executionSettings);
|
||||
}
|
||||
|
||||
public static PromptTemplateConfig parseFromJson(String json) throws SKException {
|
||||
|
||||
+12
-7
@@ -7,32 +7,37 @@ import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
|
||||
/**
|
||||
* The result of an AI service selection.
|
||||
*/
|
||||
public class AIServiceSelection {
|
||||
public class AIServiceSelection<T extends AIService> {
|
||||
|
||||
private final AIService service;
|
||||
private final T service;
|
||||
private final PromptExecutionSettings settings;
|
||||
|
||||
/**
|
||||
* Creates a new AI service selection.
|
||||
* @param service The selected AI service.
|
||||
* @param settings The settings associated with the selected service. This may be null even if a service is selected..
|
||||
*
|
||||
* @param service The selected AI service.
|
||||
* @param settings The settings associated with the selected service. This may be null even if a
|
||||
* service is selected..
|
||||
*/
|
||||
public AIServiceSelection(AIService service, PromptExecutionSettings settings) {
|
||||
public AIServiceSelection(T service, PromptExecutionSettings settings) {
|
||||
this.service = service;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected AI service.
|
||||
*
|
||||
* @return The selected AI service.
|
||||
*/
|
||||
public AIService getService() {
|
||||
public T getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the settings associated with the selected service.
|
||||
* @return The settings associated with the selected service. This may be null even if a service is selected.
|
||||
*
|
||||
* @return The settings associated with the selected service. This may be null even if a service
|
||||
* is selected.
|
||||
*/
|
||||
public PromptExecutionSettings getSettings() {
|
||||
return settings;
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ public interface AIServiceSelector {
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
AIServiceSelection trySelectAIService(
|
||||
Class<? extends AIService> serviceType,
|
||||
<T extends AIService> AIServiceSelection<T> trySelectAIService(
|
||||
Class<T> serviceType,
|
||||
@Nullable
|
||||
KernelFunction function,
|
||||
|
||||
|
||||
+6
-6
@@ -20,20 +20,20 @@ public abstract class BaseAIServiceSelector implements AIServiceSelector {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AIServiceSelection trySelectAIService(
|
||||
Class<? extends AIService> serviceType,
|
||||
|
||||
public <T extends AIService> AIServiceSelection<T> trySelectAIService(
|
||||
Class<T> serviceType,
|
||||
@Nullable
|
||||
KernelFunction function,
|
||||
|
||||
@Nullable
|
||||
KernelArguments arguments) {
|
||||
KernelArguments arguments
|
||||
) {
|
||||
return trySelectAIService(serviceType, function, arguments, services);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract AIServiceSelection trySelectAIService(
|
||||
Class<? extends AIService> serviceType,
|
||||
public abstract <T extends AIService> AIServiceSelection<T> trySelectAIService(
|
||||
Class<T> serviceType,
|
||||
|
||||
@Nullable
|
||||
KernelFunction function,
|
||||
|
||||
+3
-4
@@ -29,8 +29,8 @@ public class OrderedAIServiceSelector extends BaseAIServiceSelector {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AIServiceSelection trySelectAIService(
|
||||
Class<? extends AIService> serviceType,
|
||||
public <T extends AIService> AIServiceSelection<T> trySelectAIService(
|
||||
Class<T> serviceType,
|
||||
@Nullable
|
||||
KernelFunction function,
|
||||
@Nullable
|
||||
@@ -108,10 +108,9 @@ public class OrderedAIServiceSelector extends BaseAIServiceSelector {
|
||||
PromptExecutionSettings settings;
|
||||
|
||||
if (executionSettings.containsKey(PromptExecutionSettings.DEFAULT_SERVICE_ID)) {
|
||||
executionSettings.get(PromptExecutionSettings.DEFAULT_SERVICE_ID);
|
||||
settings = executionSettings.get(PromptExecutionSettings.DEFAULT_SERVICE_ID);
|
||||
} else {
|
||||
settings = executionSettings.values().stream().findFirst().orElseGet(null);
|
||||
settings = executionSettings.values().stream().findFirst().orElseGet(() -> null);
|
||||
}
|
||||
|
||||
if (service != null) {
|
||||
|
||||
+101
-105
@@ -1,21 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.handlebars;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.github.jknack.handlebars.Context;
|
||||
import com.github.jknack.handlebars.Handlebars;
|
||||
import com.github.jknack.handlebars.Options;
|
||||
import com.github.jknack.handlebars.ValueResolver;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
|
||||
@@ -28,21 +16,28 @@ import com.microsoft.semantickernel.plugin.KernelPlugin;
|
||||
import com.microsoft.semantickernel.plugin.KernelPluginCollection;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
|
||||
@Nullable
|
||||
private PromptTemplateConfig promptTemplate;
|
||||
|
||||
public HandlebarsPromptTemplate() {
|
||||
this(null);
|
||||
}
|
||||
private final PromptTemplateConfig promptTemplate;
|
||||
|
||||
public HandlebarsPromptTemplate(
|
||||
@Nullable PromptTemplateConfig promptTemplate) {
|
||||
this.promptTemplate = promptTemplate;
|
||||
@Nonnull PromptTemplateConfig promptTemplate) {
|
||||
this.promptTemplate = new PromptTemplateConfig(promptTemplate);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +88,7 @@ public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
|
||||
@Override
|
||||
public Object resolve(Object context, String name) {
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
return context;
|
||||
}
|
||||
if (context instanceof KernelFunction) {
|
||||
@@ -109,7 +104,7 @@ public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
|
||||
@Override
|
||||
public Object resolve(Object context) {
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
return ((KernelPluginCollection) context).iterator();
|
||||
}
|
||||
return UNRESOLVED;
|
||||
@@ -163,98 +158,99 @@ public class HandlebarsPromptTemplate implements PromptTemplate {
|
||||
private final String template;
|
||||
private final Handlebars handlebars;
|
||||
|
||||
|
||||
@SuppressFBWarnings("CT_CONSTRUCTOR_THROW")// Think this is a false positive
|
||||
public HandleBarsPromptTemplateHandler(Kernel kernel, String template) {
|
||||
this.kernel = kernel;
|
||||
this.template = template;
|
||||
this.handlebars = new Handlebars();
|
||||
this.handlebars.registerHelper(
|
||||
"message",
|
||||
(context, options) -> {
|
||||
String role = options.hash("role");
|
||||
String content = (String) options.fn(context);
|
||||
this.handlebars
|
||||
.registerHelper("message", HandleBarsPromptTemplateHandler::handleMessage)
|
||||
.registerHelper("each", HandleBarsPromptTemplateHandler::handleEach)
|
||||
.registerHelper("functions", (context, options) -> handleFunctions(kernel, options))
|
||||
.registerHelper("function",
|
||||
(context, options) -> handleFunction((KernelFunction) context));
|
||||
// TODO: 1.0 Add more helpers
|
||||
}
|
||||
|
||||
if (context instanceof Optional) {
|
||||
ChatMessageContent message = ((Optional<ChatMessageContent>) context).orElse(null);
|
||||
if (message != null) {
|
||||
if (role == null || role.isEmpty()) {
|
||||
role = message.getAuthorRole().name();
|
||||
}
|
||||
content = message.getContent();
|
||||
}
|
||||
}
|
||||
private static Handlebars.SafeString handleFunction(KernelFunction context) {
|
||||
KernelFunction function = context;
|
||||
String pluginName = function.getSkillName();
|
||||
String functionName = function.getName();
|
||||
String description = function.getDescription();
|
||||
StringBuilder sb = new StringBuilder(
|
||||
String.format(
|
||||
"<function pluginName=\"%s\" name=\"%s\" description=\"%s\">",
|
||||
pluginName, functionName, description));
|
||||
List<KernelParameterMetadata> parameters = function.getMetadata().getParameters();
|
||||
parameters.forEach(p -> {
|
||||
sb.append(String.format(
|
||||
"<parameter name=\"%s\" description=\"%s\" defaultValue=\"%s\" isRequired=\"%s\" type=\"%s\"/>",
|
||||
p.getName(), p.getDescription(), p.getDefaultValue(), p.isRequired(),
|
||||
p.getType()));
|
||||
});
|
||||
sb.append("</function>");
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
|
||||
if (role != null && !role.isEmpty()) {
|
||||
return new Handlebars.SafeString(
|
||||
String.format(
|
||||
"<message role=\"%s\">%s</message>",
|
||||
role.toLowerCase(Locale.ROOT), content));
|
||||
}
|
||||
return "";
|
||||
private static Handlebars.SafeString handleFunctions(Kernel kernel, Options options)
|
||||
throws IOException {
|
||||
StringBuilder sb = new StringBuilder("<functions>");
|
||||
KernelPluginCollection plugins = kernel.getPlugins();
|
||||
sb.append(options.fn(plugins));
|
||||
sb.append("</functions>");
|
||||
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
|
||||
private static CharSequence handleEach(Object context, Options options)
|
||||
throws IOException {
|
||||
if (context instanceof ChatHistory) {
|
||||
StringBuilder sb = new StringBuilder("<messages>");
|
||||
for (ChatMessageContent message : (ChatHistory) context) {
|
||||
sb.append(options.fn(message));
|
||||
}
|
||||
sb.append("</messages>");
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Iterator<KernelPlugin> plugins = ((KernelPluginCollection) context).iterator();
|
||||
while (plugins.hasNext()) {
|
||||
KernelPlugin plugin = plugins.next();
|
||||
Iterator<KernelFunction> functions = plugin.iterator();
|
||||
while (functions.hasNext()) {
|
||||
KernelFunction function = functions.next();
|
||||
sb.append(options.fn(function));
|
||||
}
|
||||
)
|
||||
}
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
.registerHelper(
|
||||
"each",
|
||||
(context, options) -> {
|
||||
if (context instanceof ChatHistory) {
|
||||
StringBuilder sb = new StringBuilder("<messages>");
|
||||
for(ChatMessageContent message : (ChatHistory) context) {
|
||||
sb.append(options.fn(message));
|
||||
}
|
||||
sb.append("</messages>");
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
if (context instanceof KernelPluginCollection) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Iterator<KernelPlugin> plugins = ((KernelPluginCollection) context).iterator();
|
||||
while (plugins.hasNext()) {
|
||||
KernelPlugin plugin = plugins.next();
|
||||
Iterator<KernelFunction> functions = plugin.iterator();
|
||||
while (functions.hasNext()) {
|
||||
KernelFunction function = functions.next();
|
||||
sb.append(options.fn(function));
|
||||
}
|
||||
}
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
)
|
||||
private static CharSequence handleMessage(Object context, Options options)
|
||||
throws IOException {
|
||||
String role = options.hash("role");
|
||||
String content = (String) options.fn(context);
|
||||
|
||||
.registerHelper(
|
||||
"functions",
|
||||
(context, options) -> {
|
||||
StringBuilder sb = new StringBuilder("<functions>");
|
||||
KernelPluginCollection plugins = kernel.getPlugins();
|
||||
sb.append(options.fn(plugins));
|
||||
sb.append("</functions>");
|
||||
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
if (context instanceof Optional) {
|
||||
ChatMessageContent message = ((Optional<ChatMessageContent>) context).orElse(null);
|
||||
if (message != null) {
|
||||
if (role == null || role.isEmpty()) {
|
||||
role = message.getAuthorRole().name();
|
||||
}
|
||||
)
|
||||
content = message.getContent();
|
||||
}
|
||||
}
|
||||
|
||||
.registerHelper(
|
||||
"function",
|
||||
(context, options) -> {
|
||||
KernelFunction function = (KernelFunction) context;
|
||||
String pluginName = function.getSkillName();
|
||||
String functionName = function.getName();
|
||||
String description = function.getDescription();
|
||||
StringBuilder sb = new StringBuilder(
|
||||
String.format(
|
||||
"<function pluginName=\"%s\" name=\"%s\" description=\"%s\">",
|
||||
pluginName, functionName, description));
|
||||
List<KernelParameterMetadata> parameters = function.getMetadata().getParameters();
|
||||
parameters.forEach(p -> {
|
||||
sb.append(String.format(
|
||||
"<parameter name=\"%s\" description=\"%s\" defaultValue=\"%s\" isRequired=\"%s\" type=\"%s\"/>",
|
||||
p.getName(), p.getDescription(), p.getDefaultValue(), p.isRequired(), p.getType()));
|
||||
});
|
||||
sb.append("</function>");
|
||||
return new Handlebars.SafeString(sb.toString());
|
||||
}
|
||||
);
|
||||
// TODO: 1.0 Add more helpers
|
||||
if (role != null && !role.isEmpty()) {
|
||||
return new Handlebars.SafeString(
|
||||
String.format(
|
||||
"<message role=\"%s\">%s</message>",
|
||||
role.toLowerCase(Locale.ROOT), content));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-8
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -28,16 +29,11 @@ import reactor.core.publisher.Mono;
|
||||
/// </summary>
|
||||
public class DefaultPromptTemplate implements PromptTemplate {
|
||||
|
||||
@Nullable
|
||||
private PromptTemplateConfig promptTemplate;
|
||||
|
||||
public DefaultPromptTemplate() {
|
||||
this(null);
|
||||
}
|
||||
private final PromptTemplateConfig promptTemplate;
|
||||
|
||||
public DefaultPromptTemplate(
|
||||
@Nullable PromptTemplateConfig promptTemplate) {
|
||||
this.promptTemplate = promptTemplate;
|
||||
@Nonnull PromptTemplateConfig promptTemplate) {
|
||||
this.promptTemplate = new PromptTemplateConfig(promptTemplate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ import com.microsoft.semantickernel.orchestration.contextvariables.DefaultKernel
|
||||
import com.microsoft.semantickernel.orchestration.FunctionResult;
|
||||
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
|
||||
import com.microsoft.semantickernel.templateengine.semantickernel.TemplateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -123,7 +124,9 @@ public final class CodeBlock extends Block implements CodeRendering {
|
||||
arguments = this.enrichFunctionArguments(kernel, fBlock,
|
||||
arguments ==
|
||||
null ? new DefaultKernelArguments()
|
||||
: new DefaultKernelArguments(arguments, new HashMap<>()));
|
||||
: new DefaultKernelArguments(
|
||||
arguments,
|
||||
new HashMap<>()));
|
||||
}
|
||||
|
||||
return kernel
|
||||
|
||||
@@ -1,119 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<FindBugsFilter>
|
||||
|
||||
<!-- NullMemory.getInstance() may expose internal representation by returning NullMemory.DEFAULT, but NullMemory has no internal representation. -->
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.memory.NullMemory"/>
|
||||
<Method name="getInstance"/>
|
||||
<Bug pattern="MS_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
<!-- DefaultSemanticTextMemory(MemoryStore, EmbeddingGeneration) may expose internal representation by storing an externally mutable object into DefaultSemanticTextMemory._storage -->
|
||||
<!-- TODO: This should be a temporary exclusion pending a proper fix, if possible. -->
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.memory.DefaultSemanticTextMemory"/>
|
||||
<Field name="_storage"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.Kernel$Builder"/>
|
||||
<Method name="withMemoryStore"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.Kernel$Builder"/>
|
||||
<Method name="withMemory"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.DefaultKernel"/>
|
||||
<Field name="memoryStore"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.DefaultKernel"/>
|
||||
<Method name="getMemory"/>
|
||||
<Bug pattern="EI_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.DefaultKernel"/>
|
||||
<Field name="memory"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.DefaultKernel"/>
|
||||
<Method name="registerMemory"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.ai.embeddings.Embedding"/>
|
||||
<Method name="getVector"/>
|
||||
<Bug pattern="EI_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.memory.DefaultSemanticTextMemory$Builder"/>
|
||||
<Method name="withStorage"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection"/>
|
||||
<Method name="getSkillCollection"/>
|
||||
<Bug pattern="EI_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.jdbc.JDBCConnector"/>
|
||||
<Method name="<init>"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore"/>
|
||||
<Method name="<init>"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore$Builder"/>
|
||||
<Method name="withConnection"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.sqlite.SQLiteMemoryStore$Builder"/>
|
||||
<Method name="withConnection"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.postgresql.PostgreSQLMemoryStore$Builder"/>
|
||||
<Method name="withConnection"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.mysql.MySQLMemoryStore$Builder"/>
|
||||
<Method name="withConnection"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryRecord"/>
|
||||
<Bug pattern="EI_EXPOSE_REP"/>
|
||||
</Match>
|
||||
|
||||
<Match>
|
||||
<Class name="com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryStore"/>
|
||||
<Bug pattern="EI_EXPOSE_REP2"/>
|
||||
</Match>
|
||||
|
||||
</FindBugsFilter>
|
||||
|
||||
Reference in New Issue
Block a user