Java: merge dsgrieve/java-v1-api into java-v1 (#4405)

Work on 01, 02, 03, 04 examples of the SK-v1 API

---------

Co-authored-by: John Oliver <[email protected]>
This commit is contained in:
David Grieve
2024-01-02 11:47:17 -05:00
committed by GitHub
co-authored by John Oliver
parent 1d9a1b47cf
commit da2ac37b4b
293 changed files with 7561 additions and 6644 deletions
-3
View File
@@ -1,3 +0,0 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}
+4
View File
@@ -15,6 +15,10 @@
<description>Azure OpenAI services for Semantic Kernel</description>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-api</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-ai-openai</artifactId>
@@ -0,0 +1,143 @@
package com.microsoft.semantickernel.aiservices.azureopenai;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.models.Choice;
import com.azure.ai.openai.models.Completions;
import com.azure.ai.openai.models.CompletionsOptions;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.exceptions.AIException;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import com.microsoft.semantickernel.textcompletion.StreamingTextContent;
import com.microsoft.semantickernel.textcompletion.TextContent;
import com.microsoft.semantickernel.textcompletion.TextGenerationService;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class AzureOpenAITextGenerationService implements TextGenerationService {
private final OpenAIAsyncClient client;
private final Map<String, ContextVariable<?>> attributes;
/// <summary>
/// Creates a new <see cref="AzureOpenAITextGenerationService"/> client instance supporting AAD auth
/// </summary>
/// <param name="deploymentName">Azure OpenAI deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource</param>
/// <param name="endpoint">Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart</param>
/// <param name="credential">Token credentials, e.g. DefaultAzureCredential, ManagedIdentityCredential, EnvironmentCredential, etc.</param>
/// <param name="modelId">Azure OpenAI model id, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource</param>
/// <param name="httpClient">Custom <see cref="HttpClient"/> for HTTP requests.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use for logging. If null, no logging will be performed.</param>
public AzureOpenAITextGenerationService(
OpenAIAsyncClient client,
String modelId) {
this.client = client;
attributes = new HashMap<>();
attributes.put(MODEL_ID_KEY, ContextVariable.of(modelId));
}
public static Builder builder() {
return new Builder();
}
@Override
public Map<String, ContextVariable<?>> getAttributes() {
return attributes;
}
@Override
public Mono<List<TextContent>> getTextContentsAsync(String prompt,
@Nullable PromptExecutionSettings executionSettings, @Nullable Kernel kernel) {
return null;
}
@Override
public Flux<StreamingTextContent> getStreamingTextContentsAsync(
String prompt,
@Nullable PromptExecutionSettings executionSettings,
@Nullable Kernel kernel) {
return this
.internalCompleteTextAsync(prompt, executionSettings)
.flatMapMany(it -> {
return Flux.fromStream(it.stream())
.map(TextContent::new)
.map(StreamingTextContent::new);
});
}
protected Mono<List<String>> internalCompleteTextAsync(
String text,
PromptExecutionSettings requestSettings) {
CompletionsOptions completionsOptions = getCompletionsOptions(text, requestSettings);
return client
.getCompletions(getModelId(), completionsOptions)
.flatMapIterable(Completions::getChoices)
.mapNotNull(Choice::getText)
.collectList();
}
private CompletionsOptions getCompletionsOptions(
String text, PromptExecutionSettings requestSettings) {
if (requestSettings == null) {
return new CompletionsOptions(Collections.singletonList(text))
.setMaxTokens(PromptExecutionSettings.DEFAULT_MAX_TOKENS);
}
if (requestSettings.getMaxTokens() < 1) {
throw new AIException(AIException.ErrorCodes.INVALID_REQUEST, "Max tokens must be >0");
}
CompletionsOptions options =
new CompletionsOptions(Collections.singletonList(text))
.setMaxTokens(requestSettings.getMaxTokens())
.setTemperature(requestSettings.getTemperature())
.setTopP(requestSettings.getTopP())
.setFrequencyPenalty(requestSettings.getFrequencyPenalty())
.setPresencePenalty(requestSettings.getPresencePenalty())
.setModel(getModelId())
.setUser(requestSettings.getUser())
.setBestOf(requestSettings.getBestOf())
.setLogitBias(new HashMap<>());
/*
if (requestSettings instanceof ChatRequestSettings) {
options = options.setStop(requestSettings.getStopSequences());
}
*/
return options;
}
/**
* Builder for a ChatCompletionService that uses Azure AI.
*/
public static class Builder {
private String modelId;
private OpenAIAsyncClient client;
public Builder withModelId(String modelId) {
this.modelId = modelId;
return this;
}
public Builder withOpenAIAsyncClient(OpenAIAsyncClient client) {
this.client = client;
return this;
}
public AzureOpenAITextGenerationService build() {
return new AzureOpenAITextGenerationService(
this.client,
this.modelId
);
}
}
}
@@ -0,0 +1,320 @@
package com.microsoft.semantickernel.aiservices.azureopenai.chatcompletion;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.ai.openai.models.ChatChoice;
import com.azure.ai.openai.models.ChatCompletions;
import com.azure.ai.openai.models.ChatCompletionsOptions;
import com.azure.ai.openai.models.ChatRequestAssistantMessage;
import com.azure.ai.openai.models.ChatRequestMessage;
import com.azure.ai.openai.models.ChatRequestSystemMessage;
import com.azure.ai.openai.models.ChatRequestToolMessage;
import com.azure.ai.openai.models.ChatRequestUserMessage;
import com.azure.ai.openai.models.ChatResponseMessage;
import com.azure.ai.openai.models.ChatRole;
import com.azure.core.credential.KeyCredential;
import com.azure.core.credential.TokenCredential;
import com.microsoft.semantickernel.Kernel;
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.chatcompletion.StreamingChatMessageContent;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class AzureOpenAIChatCompletion implements com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion {
private static final Logger LOGGER = LoggerFactory.getLogger(AzureOpenAIChatCompletion.class);
private final OpenAIAsyncClient client;
private final Map<String, ContextVariable<?>> attributes;
public AzureOpenAIChatCompletion(OpenAIAsyncClient client, String modelId) {
this.client = client;
this.attributes = new HashMap<>();
attributes.put(MODEL_ID_KEY, ContextVariable.of(modelId));
}
@Override
public Map<String, ContextVariable<?>> getAttributes() {
return attributes;
}
@Override
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(ChatHistory chatHistory,
@Nullable PromptExecutionSettings promptExecutionSettings, @Nullable Kernel kernel) {
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(chatHistory);
return internalChatMessageContentsAsync(chatRequestMessages, promptExecutionSettings);
}
@Override
public Flux<StreamingChatMessageContent> getStreamingChatMessageContentsAsync(ChatHistory chatHistory,
PromptExecutionSettings promptExecutionSettings, Kernel kernel)
{
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(chatHistory);
return internalStreamingChatMessageContentsAsync(chatRequestMessages, promptExecutionSettings);
}
@Override
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(String prompt,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(prompt);
return internalChatMessageContentsAsync(chatRequestMessages, promptExecutionSettings);
}
@Override
public Flux<StreamingChatMessageContent> getStreamingChatMessageContentsAsync(String prompt,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
List<ChatRequestMessage> chatRequestMessages = getChatRequestMessages(prompt);
return internalStreamingChatMessageContentsAsync(chatRequestMessages, promptExecutionSettings);
}
private Flux<StreamingChatMessageContent> internalStreamingChatMessageContentsAsync(
List<ChatRequestMessage> chatRequestMessages,
PromptExecutionSettings promptExecutionSettings)
{
ChatCompletionsOptions options = getCompletionsOptions(this, chatRequestMessages, promptExecutionSettings);
return client
.getChatCompletionsStream(getModelId(), options)
.filter(chatCompletion -> chatCompletion != null)
.map(ChatCompletions::getChoices)
.filter(choices -> choices != null && !choices.isEmpty())
.collect(StringBuffer::new, (sb, choices) -> {
choices.stream()
.map(choice -> choice.getDelta())
.filter(delta -> delta != null && delta.getContent() != null)
.forEach(delta -> sb.append(delta.getContent()));
})
.map(sb -> {
return sb.toString();
})
.map(content -> new StreamingChatMessageContent(AuthorRole.ASSISTANT, content))
.flux();
}
private Mono<List<ChatMessageContent>> internalChatMessageContentsAsync(
List<ChatRequestMessage> chatRequestMessages,
PromptExecutionSettings promptExecutionSettings)
{
ChatCompletionsOptions options = getCompletionsOptions(this, chatRequestMessages, promptExecutionSettings);
return client
.getChatCompletions(getModelId(), options)
.flatMap(chatCompletions -> Mono.just(toChatMessageContents(chatCompletions)));
}
private static ChatCompletionsOptions getCompletionsOptions(
ChatCompletionService chatCompletionService,
List<ChatRequestMessage> chatRequestMessages,
PromptExecutionSettings promptExecutionSettings)
{
ChatCompletionsOptions options = new ChatCompletionsOptions(chatRequestMessages)
.setModel(chatCompletionService.getModelId());
if (promptExecutionSettings == null) {
return options;
}
options
.setTemperature(promptExecutionSettings.getTemperature())
.setTopP(promptExecutionSettings.getTopP())
.setPresencePenalty(promptExecutionSettings.getPresencePenalty())
.setFrequencyPenalty(promptExecutionSettings.getFrequencyPenalty())
.setPresencePenalty(promptExecutionSettings.getPresencePenalty())
.setMaxTokens(promptExecutionSettings.getMaxTokens())
// Azure OpenAI WithData API does not allow to send empty array of stop sequences
// Gives back "Validation error at #/stop/str: Input should be a valid string\nValidation error at #/stop/list[str]: List should have at least 1 item after validation, not 0"
.setStop(promptExecutionSettings.getStopSequences() == null || promptExecutionSettings.getStopSequences().isEmpty() ? null : promptExecutionSettings.getStopSequences())
.setUser(promptExecutionSettings.getUser())
.setLogitBias(new HashMap<>());
return options;
}
private static List<ChatRequestMessage> getChatRequestMessages(ChatHistory chatHistory)
{
List<ChatMessageContent> messages = chatHistory.getMessages();
if (messages == null || messages.isEmpty()) {
return new ArrayList<>();
}
return messages.stream()
.map(message -> {
AuthorRole authorRole = message.getAuthorRole();
String content = message.getContent();
return getChatRequestMessage(authorRole, content);
})
.collect(Collectors.toList());
}
private static List<ChatRequestMessage> getChatRequestMessages(String prompt)
{
List<ChatRequestMessage> messages = new ArrayList<>();
try (InputStream is = new ByteArrayInputStream(prompt.getBytes())) {
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLEventReader reader = factory.createXMLEventReader(is);
while(reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
String name = event.asStartElement().getName().getLocalPart();
if (name.equals("message")) {
String role = event.asStartElement().getAttributeByName(javax.xml.namespace.QName.valueOf("role")).getValue();
String content = reader.getElementText();
messages.add(getChatRequestMessage(AuthorRole.valueOf(role.toUpperCase()), content));
}
}
}
} catch (IOException | XMLStreamException | IllegalArgumentException e) {
LOGGER.error("Error parsing prompt", e);
}
return messages;
}
private static ChatRequestMessage getChatRequestMessage(
AuthorRole authorRole,
String content)
{
if (authorRole != null) {
switch(authorRole) {
case ASSISTANT:
return new ChatRequestAssistantMessage(content);
case SYSTEM:
return new ChatRequestSystemMessage(content);
case USER:
return new ChatRequestUserMessage(content);
case TOOL:
return new ChatRequestToolMessage(content, null);
}
}
throw new IllegalArgumentException("Unknown author role: " + authorRole);
}
private static List<ChatMessageContent> toChatMessageContents(ChatCompletions chatCompletions) {
if (chatCompletions == null || chatCompletions.getChoices() == null || chatCompletions.getChoices().isEmpty()) {
return new ArrayList<>();
}
return chatCompletions.getChoices().stream()
.map(ChatChoice::getMessage)
.map(AzureOpenAIChatCompletion::toChatMessageContent)
.collect(Collectors.toList());
}
private static ChatMessageContent toChatMessageContent(ChatResponseMessage message) {
return new ChatMessageContent(toAuthorRole(message.getRole()), message.getContent());
}
private static AuthorRole toAuthorRole(ChatRole chatRole) {
if (chatRole == null) {
return null;
}
if(chatRole == ChatRole.ASSISTANT) {
return AuthorRole.ASSISTANT;
}
if(chatRole == ChatRole.ASSISTANT) {
return AuthorRole.SYSTEM;
}
if(chatRole == ChatRole.ASSISTANT) {
return AuthorRole.USER;
}
if(chatRole == ChatRole.ASSISTANT) {
return AuthorRole.TOOL;
}
throw new IllegalArgumentException("Unknown chat role: " + chatRole);
}
public static class Builder implements com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder {
private OpenAIAsyncClient client;
private String modelId;
private String apiKey;
private String endpoint;
private TokenCredential tokenCredential;
@Override
public AzureOpenAIChatCompletion build() {
OpenAIAsyncClient asyncClient;
if ((asyncClient = this.client) == null) {
if (tokenCredential != null) {
Objects.requireNonNull(endpoint, "Endpoint must be set");
asyncClient = new OpenAIClientBuilder()
.credential(tokenCredential)
.endpoint(endpoint)
.buildAsyncClient();
} else {
Objects.requireNonNull(apiKey, "API key must be set");
Objects.requireNonNull(endpoint, "Endpoint must be set");
asyncClient = new OpenAIClientBuilder()
.credential(new KeyCredential(apiKey))
.endpoint(endpoint)
.buildAsyncClient();
}
}
Objects.requireNonNull(modelId, "Model ID must be set");
return new AzureOpenAIChatCompletion(asyncClient, modelId);
}
@Override
public com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder withModelId(
String modelId) {
this.modelId = modelId;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder withOpenAIAsyncClient(
OpenAIAsyncClient openAIClient) {
this.client = openAIClient;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder withApiKey(
String apiKey) {
this.apiKey = apiKey;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder withEndpoint(
String endpoint) {
this.endpoint = endpoint;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion.Builder withTokenCredential(
TokenCredential tokenCredential) {
this.tokenCredential = tokenCredential;
return this;
}
}
}
@@ -0,0 +1,66 @@
package com.microsoft.semantickernel.aiservices.azureopenai.chatcompletion;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
public interface AzureOpenAIChatResponse {
interface Usage {
@JsonProperty("prompt_tokens")
int getPromptTokens();
@JsonProperty("completion_tokens")
int getCompletionTokens();
@JsonProperty("total_tokens")
int getTotalTokens();
}
interface Choice {
@JsonProperty("message")
Message getMessage();
@JsonProperty("finish_details")
FinishDetails getFinishDetails();
@JsonProperty("index")
int getIndex();
}
interface Message {
@JsonProperty("role")
String getRole();
@JsonProperty("content")
String getContent();
}
interface FinishDetails {
@JsonProperty("type")
String getType();
}
@JsonProperty("id")
String getId();
@JsonProperty("object")
String getObject();
@JsonProperty("created")
Long getCreated();
@JsonProperty("model")
String getModel();
@JsonProperty("Usage")
List<Usage> getUsage();
@JsonProperty("choices")
List<Choice> getChoices();
}
@@ -0,0 +1 @@
com.microsoft.semantickernel.aiservices.azureopenai.chatcompletion.AzureOpenAIChatCompletion$Builder
@@ -1,107 +0,0 @@
package com.microsoft.semantickernel.aiservices.openai;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.azure.ai.openai.models.ChatCompletions;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.chatcompletion.ChatRequestSettings;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
import com.microsoft.semantickernel.textcompletion.CompletionType;
import com.microsoft.semantickernel.aiservices.AIService;
import com.microsoft.semantickernel.aiservices.responsetypes.BinaryFile;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class OpenAIChatCompletion implements AIService, ChatCompletion<ChatHistory> {
public OpenAIChatCompletion(String modelId, String apiKey) {}
@Override
public Mono<List<String>> completeAsync(@Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'completeAsync'");
}
@Override
public Flux<String> completeStreamAsync(@Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'completeStreamAsync'");
}
@Override
public CompletionType defaultCompletionType() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'defaultCompletionType'");
}
@Override
public Mono<String> generateMessageAsync(ChatHistory chat, @Nullable ChatRequestSettings requestSettings) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'generateMessageAsync'");
}
@Override
public ChatHistory createNewChat(String instructions) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'createNewChat'");
}
@Override
public ChatHistory createNewChat() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'createNewChat'");
}
@Override
public Flux<String> generateMessageStream(ChatHistory chatHistory, @Nullable ChatRequestSettings requestSettings) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'generateMessageStream'");
}
@Override
public Flux<ChatCompletions> getStreamingChatCompletionsAsync(ChatHistory chat,
ChatRequestSettings requestSettings) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getStreamingChatCompletionsAsync'");
}
@Override
public String getModelId() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getModelId'");
}
@Override
public List<Class<?>> getOutputTypes() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getOutputTypes'");
}
@Override
public List<String> getCapabilities() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getCapabilities'");
}
@Override
public Mono<FunctionResult> getModelResultAsync(Kernel kernel, String pluginName, String name, String prompt,
Map<Object, BinaryFile> files) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getModelResultAsync'");
}
@Override
public Mono<FunctionResult> getModelStreamingResultAsync(Kernel kernel, String pluginName, String name,
String prompt, Map<Object, BinaryFile> files) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getModelStreamingResultAsync'");
}
}
@@ -0,0 +1,127 @@
package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.KeyCredential;
import com.azure.core.credential.TokenCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.chatcompletion.ChatMessageContent;
import com.microsoft.semantickernel.chatcompletion.StreamingChatMessageContent;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class OpenAIChatCompletion implements com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion {
private final OpenAIAsyncClient client;
private final String modelId;
public OpenAIChatCompletion(OpenAIAsyncClient client, String modelId) {
this.client = client;
this.modelId = modelId;
}
@Override
public Map<String, ContextVariable<?>> getAttributes() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getAttributes'");
}
@Override
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(ChatHistory chatHistory,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getChatMessageContentsAsync'");
}
@Override
public Flux<StreamingChatMessageContent> getStreamingChatMessageContentsAsync(ChatHistory chatHistory,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getStreamingChatMessageContentsAsync'");
}
@Override
public Mono<List<ChatMessageContent>> getChatMessageContentsAsync(String prompt,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getStreamingChatMessageContentsAsync'");
}
@Override
public Flux<StreamingChatMessageContent> getStreamingChatMessageContentsAsync(String prompt,
PromptExecutionSettings promptExecutionSettings, Kernel kernel) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getStreamingChatMessageContentsAsync'");
}
public static class Builder implements com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder {
private OpenAIAsyncClient client;
private String modelId;
private String apiKey;
private String organization;
private TokenCredential tokenCredential;
@Override
public OpenAIChatCompletion build() {
OpenAIAsyncClient asyncClient;
if ((asyncClient = this.client) == null) {
if (tokenCredential != null) {
asyncClient = new OpenAIClientBuilder()
.credential(tokenCredential)
.buildAsyncClient();
} else {
Objects.requireNonNull(apiKey, "API key must be set");
asyncClient = new OpenAIClientBuilder()
.credential(new KeyCredential(apiKey))
.buildAsyncClient();
}
}
Objects.requireNonNull(modelId, "Model ID must be set");
return new OpenAIChatCompletion(asyncClient, modelId);
}
@Override
public com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder withOpenAIAsyncClient(
OpenAIAsyncClient openAIClient) {
this.client = openAIClient;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder withApiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder withOrganization(
String organization) {
this.organization = organization;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder withTokenCredential(
TokenCredential tokenCredential) {
this.tokenCredential = tokenCredential;
return this;
}
@Override
public com.microsoft.semantickernel.chatcompletion.OpenAIChatCompletion.Builder withModelId(
String modelId) {
this.modelId = modelId;
return this;
}
}
}
@@ -1,4 +1,4 @@
package com.microsoft.semantickernel.aiservices.openai;
package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
import java.util.List;
@@ -0,0 +1 @@
com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion$Builder
@@ -4,8 +4,8 @@ import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.io.IOException;
import java.nio.file.Files;
@@ -97,17 +97,17 @@ public class InlineFunctionExample {
.buildAsyncClient();
TextCompletion textCompletion =
SKBuilders.textCompletion().withOpenAIClient(client).withModelId(MODEL).build();
SKBuilders.textCompletion().withOpenAIAsyncClient(client).withModelId(MODEL).build();
String prompt = "{{$input}}\n" + "Summarize the content above.";
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
CompletionSKFunction summarize =
CompletionKernelFunction summarize =
kernel.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName("summarize")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
new PromptConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
.build();
if (summarize == null) {
@@ -4,8 +4,8 @@ import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.io.IOException;
import java.nio.file.Files;
@@ -98,18 +98,18 @@ public class InlineFunctionWithPreBuiltSkillExample {
.buildAsyncClient();
TextCompletion textCompletion =
SKBuilders.textCompletion().withOpenAIClient(client).withModelId(MODEL).build();
SKBuilders.textCompletion().withOpenAIAsyncClient(client).withModelId(MODEL).build();
String prompt = "{{$input}}\nSummarize the content above.";
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
CompletionSKFunction summarize =
CompletionKernelFunction summarize =
SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(prompt)
.withFunctionName("summarize")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
new PromptConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
.build();
if (summarize == null) {
@@ -6,8 +6,8 @@ import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.ContextVariable;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
@@ -47,12 +47,12 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
User: {{$user_input}}
ChatBot:\s""";
CompletionSKFunction chat =
CompletionKernelFunction chat =
kernel.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName("ChatBot")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000))
new PromptConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000))
.build();
SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build();
@@ -74,7 +74,7 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
.block();
}
private Function<SKContext, Mono<SKContext>> chat(String input, CompletionSKFunction chat) {
private Function<SKContext, Mono<SKContext>> chat(String input, CompletionKernelFunction chat) {
return (context) -> {
try {
return chat(input, chat, context);
@@ -84,7 +84,7 @@ public class ContextVariableFunctionTest extends AbstractKernelTest {
};
}
private Mono<SKContext> chat(String input, CompletionSKFunction chat, SKContext context)
private Mono<SKContext> chat(String input, CompletionKernelFunction chat, SKContext context)
throws ExecutionException, InterruptedException, TimeoutException {
context = context.setVariable("user_input", input);
@@ -3,7 +3,7 @@ package com.microsoft.semantickernel.e2e;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.slf4j.Logger;
@@ -19,7 +19,7 @@ public class FunSkillTest extends AbstractKernelTest {
Mono<SKContext> result =
buildTextCompletionKernel()
.importSkillFromDirectory("FunSkill", "../../../samples/skills")
.getFunction("joke", CompletionSKFunction.class)
.getFunction("joke", CompletionKernelFunction.class)
.invokeAsync("time travel to dinosaur age");
if (result != null) {
@@ -4,8 +4,8 @@ package com.microsoft.semantickernel.e2e;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.slf4j.Logger;
@@ -22,12 +22,12 @@ public class InlineFunctionTest extends AbstractKernelTest {
Kernel kernel = buildTextCompletionKernel();
String prompt = "{{$input}}\n" + "Summarize the content above.";
CompletionSKFunction summarize =
CompletionKernelFunction summarize =
kernel.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName("summarize")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
new PromptConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000))
.build();
String text =
@@ -7,8 +7,8 @@ import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.io.IOException;
import org.junit.jupiter.api.Test;
@@ -21,7 +21,7 @@ public class KernelTest extends AbstractKernelTest {
private static final Logger LOGGER = LoggerFactory.getLogger(KernelTest.class);
private static void executeCompletion(Kernel kernel) {
CompletionSKFunction summarize =
CompletionKernelFunction summarize =
kernel.getSemanticFunctionBuilder()
.withPromptTemplate(
"""
@@ -29,7 +29,7 @@ public class KernelTest extends AbstractKernelTest {
One line TLDR with the fewest words.""")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256))
new PromptConfig.CompletionConfig(0, 0, 0, 0, 256))
.build();
String text1 =
@@ -11,7 +11,7 @@ import com.microsoft.semantickernel.memory.MemoryQueryResult;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
@@ -84,7 +84,7 @@ public class TextEmbeddingsTest extends AbstractKernelTest {
User: {{$userInput}}
ChatBot:\s""";
CompletionSKFunction chat =
CompletionKernelFunction chat =
kernel.getSemanticFunctionBuilder()
.withPromptTemplate(skPrompt)
.withFunctionName("recall")
@@ -1,104 +0,0 @@
package com.microsoft.semantickernel.assistants;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Collection;
import com.microsoft.semantickernel.plugin.Plugin;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.aiservices.AIService;
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.KernelResult;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
import com.microsoft.semantickernel.KernelConfig;
import reactor.core.publisher.Mono;
public class AssistantKernel extends Plugin implements Kernel {
public static AssistantKernel FromConfiguration(
String configurationFile,
@Nullable List<AIService> aiServices,
@Nullable List<Plugin> plugins,
@Nullable List<PromptTemplateEngine> promptTemplateEngines
) {
return null;
}
public AssistantKernel(String name, SKFunction... functions) {
super(name, functions);
}
public SKFunction getFunction(String skill, String function) {
return null;
}
public <FunctionType extends SKFunction>FunctionType registerSemanticFunction(FunctionType func) {
return null;
}
public CompletionSKFunction registerSemanticFunction(
String skillName, String functionName, SemanticFunctionConfig functionConfig) {
return null;
}
public <T extends AIService> T getService(String serviceId, Class<T> clazz) {
return null;
}
public CompletionSKFunction.Builder getSemanticFunctionBuilder() {
return null;
}
public Mono<KernelResult> runAsync(boolean b, ContextVariables variables, SKFunction... pipeline) {
return null;
}
public Mono<KernelResult> runAsync(ContextVariables variables, SKFunction... pipeline) {
return null;
}
public Mono<KernelResult> runAsync(String s, SKFunction... pipeline) {
return null;
}
public Mono<KernelResult> runAsync(SKFunction... pipeline) {
return null;
}
public SemanticTextMemory getMemory() {
return null;
}
public PromptTemplateEngine getPromptTemplateEngine() {
return null;
}
public KernelConfig getConfig() {
return null;
}
public List<SKFunction> functions() {
return null;
}
public String description() {
return null;
}
public String name() {
return null;
}
public Mono<AssistantThread> createThreadAsync() {
return null;
}
}
@@ -1,12 +0,0 @@
package com.microsoft.semantickernel.assistants;
import com.microsoft.semantickernel.orchestration.SKFunction;
import reactor.core.publisher.Mono;
public interface AssistantThread extends SKFunction {
public Mono addUserMessageAsync(String message);
}
@@ -1,157 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.text.TextChunker;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import java.util.List;
import javax.annotation.Nullable;
import reactor.core.publisher.Mono;
/** Semantic skill that enables conversations summarization */
public class ConversationSummarySkill {
// The max tokens to process in a single semantic function call.
private static final int MaxTokens = 1024;
private final CompletionSKFunction summarizeConversationFunction;
private final CompletionSKFunction conversationActionItemsFunction;
private final CompletionSKFunction conversationTopicsFunction;
private final Kernel kernel;
/**
* Initializes a new instance of the ConversationSummarySkill class
*
* @param kernel Kernel instance
*/
public ConversationSummarySkill(Kernel kernel) {
this.kernel = kernel;
this.summarizeConversationFunction =
SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(
SemanticFunctionConstants.SummarizeConversationDefinition)
.withFunctionName("summarize")
.withSkillName("ConversationSummarySkill")
.withDescription(
"Given a section of a conversation transcript, summarize the part"
+ " of the conversation.")
.withCompletionConfig(
SKBuilders.completionConfig()
.maxTokens(MaxTokens)
.temperature(0.1)
.topP(0.5)
.build())
.build();
this.conversationActionItemsFunction =
SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(
SemanticFunctionConstants.GetConversationActionItemsDefinition)
.withFunctionName("ActionItems")
.withSkillName("ConversationSummarySkill")
.withDescription(
"Given a section of a conversation transcript, identify action"
+ " items.")
.withCompletionConfig(
SKBuilders.completionConfig()
.maxTokens(MaxTokens)
.temperature(0.1)
.topP(0.5)
.build())
.build();
this.conversationTopicsFunction =
SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(
SemanticFunctionConstants.GetConversationTopicsDefinition)
.withFunctionName("Topics")
.withSkillName("ConversationSummarySkill")
.withDescription(
"Analyze a conversation transcript and extract key topics worth"
+ " remembering.")
.withCompletionConfig(
SKBuilders.completionConfig()
.maxTokens(MaxTokens)
.temperature(0.1)
.topP(0.5)
.build())
.build();
}
/**
* Given a long conversation transcript, summarize the conversation
*
* @param input A long conversation transcript
* @param context The SKContext for function execution
* @return A context containing the summarized conversation
*/
@DefineSKFunction(
description = "Given a long conversation transcript, summarize the conversation.",
name = "SummarizeConversation")
public Mono<SKContext> summarizeConversationAsync(
@SKFunctionInputAttribute(description = "A long conversation transcript.") String input,
@Nullable SKContext context) {
List<String> lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List<String> paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
if (context == null) {
context = SKBuilders.context().withSkills(kernel.getSkills()).build();
}
SKContext completionContext = context.copy();
return this.summarizeConversationFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
}
/**
* Given a long conversation transcript, identify action items
*
* @param input A long conversation transcript
* @param context The SKContext for function execution
* @return A context containing the action items
*/
@DefineSKFunction(
description = "Given a long conversation transcript, identify action items.",
name = "GetConversationActionItems")
public Mono<SKContext> getConversationActionItemsAsync(
@SKFunctionInputAttribute(description = "A long conversation transcript.") String input,
SKContext context) {
List<String> lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List<String> paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
SKContext completionContext = context.copy();
return this.conversationActionItemsFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
}
/**
* Given a long conversation transcript, identify topics
*
* @param input A long conversation transcript
* @param context The SKContext for function execution
* @return A context containing the topics
*/
@DefineSKFunction(
description =
"Given a long conversation transcript, identify topics worth remembering.",
name = "GetConversationTopics")
public Mono<SKContext> getConversationTopicsAsync(
@SKFunctionInputAttribute(description = "A long conversation transcript.") String input,
SKContext context) {
List<String> lines = TextChunker.splitPlainTextLines(input, MaxTokens);
List<String> paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens);
SKContext completionContext = context.copy();
return this.conversationTopicsFunction.aggregatePartitionedResultsAsync(
paragraphs, completionContext);
}
}
@@ -1,85 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Read and write from a file.
*
* <p>Usage: kernel.ImportSkill("file", new FileIOSkill());
*
* <p>Examples:
*
* <pre>{@code
* file.readAsync($path) => "hello world"
* file.writeAsync()
* }</pre>
*/
public class FileIOSkill {
/**
* Read a file.
*
* <p>Example:
*
* <pre>{@code
* file.readAsync($path) => "hello world"
* }</pre>
*
* @param path Source file.
* @return File content.
*/
@DefineSKFunction(description = "Read a file", name = "readAsync")
public String readFileAsync(
@SKFunctionInputAttribute(description = "Source file") String path,
@SKFunctionParameters(
name = "charset",
description = "Character set to use to read the file",
defaultValue = "UTF-8")
String charset)
throws IOException {
Path filePath = Paths.get(path);
byte[] fileBytes;
fileBytes = Files.readAllBytes(filePath);
String fileContents = new String(fileBytes, Charset.forName(charset));
return fileContents;
}
/**
* Write a file.
*
* <p>Example:
*
* <pre>{@code
* file.writeAsync()
* }</pre>
*
* @param path The destination file.
* @param content Contains the 'content' to write
*/
@DefineSKFunction(description = "Write a file", name = "writeAsync")
public void writeFileAsync(
@SKFunctionInputAttribute(description = "Destination file") String path,
@SKFunctionParameters(
name = "content",
description = "File content",
defaultValue = "",
type = String.class)
String content,
@SKFunctionParameters(
name = "charset",
description = "Character set to use to read the file",
defaultValue = "UTF-8")
String charset)
throws IOException {
Path filePath = Paths.get(path);
Files.write(filePath, content.getBytes(charset));
}
}
@@ -1,98 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import reactor.core.publisher.Mono;
/**
* A skill that provides HTTP functionality.
*
* <p>Usage:
*
* <p>Usage: kernel.importSkill(new HttpSkill(), "http");
*
* <p>Examples:
*
* <p>{{http.getAsync $url}}
*
* <p>{{http.postAsync $url}}
*
* <p>{{http.putAsync $url}}
*
* <p>{{http.deleteAsync $url}}
*/
public class HttpSkill {
private final HttpClient httpClient;
public HttpSkill() {
this.httpClient = HttpClient.createDefault();
}
public HttpSkill(HttpClient httpClient) {
this.httpClient = httpClient;
}
/**
* Sends an HTTP GET request to the specified URI and returns body as a string.
*
* @param url The URI to send the request to.
* @return The response body as a string.
*/
public Mono<String> getAsync(String url) {
if (url == null || url.isEmpty()) {
return Mono.error(new IllegalArgumentException("url cannot be `null` or empty"));
}
HttpRequest request = new HttpRequest(HttpMethod.GET, url);
return httpClient.send(request).flatMap(response -> response.getBodyAsString());
}
/**
* Sends an HTTP POST request to the specified URI and returns body as a string.
*
* @param url The URI to send the request to.
* @param body The response body as a string.
* @return
*/
public Mono<String> postAsync(String url, String body) {
if (url == null || url.isEmpty()) {
return Mono.error(new IllegalArgumentException("url cannot be `null` or empty"));
}
HttpRequest request = new HttpRequest(HttpMethod.POST, url);
request.setBody(body);
return httpClient.send(request).flatMap(response -> response.getBodyAsString());
}
/**
* Sends an HTTP PUT request to the specified URI and returns body as a string.
*
* @param url The URI to send the request to.
* @param body The response body as a string.
* @return
*/
public Mono<String> putAsync(String url, String body) {
if (url == null || url.isEmpty()) {
return Mono.error(new IllegalArgumentException("url cannot be `null` or empty"));
}
HttpRequest request = new HttpRequest(HttpMethod.PUT, url);
request.setBody(body);
return httpClient.send(request).flatMap(response -> response.getBodyAsString());
}
/**
* Sends an HTTP DELETE request to the specified URI and returns body as a string.
*
* @param url The URI to send the request to.
* @return The response body as a string.
*/
public Mono<HttpResponse> deleteAsync(String url) {
if (url == null || url.isEmpty()) {
return Mono.error(new IllegalArgumentException("url cannot be `null` or empty"));
}
HttpRequest request = new HttpRequest(HttpMethod.DELETE, url);
return httpClient.send(request).flatMap(response -> Mono.just(response));
}
}
@@ -1,79 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.math.BigDecimal;
/**
* MathSkill provides a set of functions to make Math calculations.
*
* <ul>
* <li><code>input</code> is the first number in the operation.
* <li><code>amount</code> is the second number in the operation.
* </ul>
*
* <p>Usage:
*
* <blockquote>
*
* <pre>
* kernel.ImportSkill("math", new MathSkill());
*
* {{math.add}} => Returns the sum of input and amount
* {{math.subtract}} => Returns the differentce of input from amount
* </pre>
*
* </blockquote>
*
* <p>This skill uses BigDecimal to perform the number conversion and the calculations.
*/
public class MathSkill {
/**
* Returns the addition result of input and amount values provided.
*
* <p>This skill attempts to convert the numbers to BigDecimal and then add them.
*
* <p>If a conversion error occurs, the skill will throw an exception.
*
* @param input Initial value as string to add the specified amount
* @param amount The amount to be added to input
* @return The resulting sum as a String.
*/
@DefineSKFunction(description = "Adds amount to a value.", name = "add")
public String add(
@SKFunctionInputAttribute(description = "The value to add to.") String input,
@SKFunctionParameters(name = "amount", description = "The amount to be added to value.")
String amount) {
BigDecimal bValue = new BigDecimal(input);
return bValue.add(new BigDecimal(amount)).toString();
}
/**
* Returns the subtraction result of input and amount values provided.
*
* <p>This skill attempts to convert the numbers to BigDecimal and then subtract them.
*
* <p>If a conversion error occurs, the skill will throw an exception.
*
* @param input Initial value as string to subtract the specified amount
* @param amount The amount to be subtracted from input
* @return The resulting difference as a String.
*/
@DefineSKFunction(description = "Subtracts amount from value.", name = "Subtract")
public String subtract(
@SKFunctionInputAttribute(description = "The value to subtract from.") String input,
@SKFunctionParameters(
name = "amount",
description = "The amount to be subtracted from value.")
String amount) {
BigDecimal bValue = new BigDecimal(input);
return bValue.subtract(new BigDecimal(amount)).toString();
}
}
@@ -1,96 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
class SemanticFunctionConstants {
public static final String SummarizeConversationDefinition =
"BEGIN CONTENT TO SUMMARIZE:\n"
+ "{{$INPUT}}\n"
+ "\n"
+ "END CONTENT TO SUMMARIZE.\n"
+ "\n"
+ "Summarize the conversation in 'CONTENT TO SUMMARIZE', identifying main points of"
+ " discussion and any conclusions that were reached.\n"
+ "Do not incorporate other general knowledge.\n"
+ "Summary is in plain text, in complete sentences, with no markup or tags.\n"
+ "\n"
+ "BEGIN SUMMARY:";
public static final String GetConversationActionItemsDefinition =
"You are an action item extractor. You will be given chat history and need to make note"
+ " of action items mentioned in the chat.\n"
+ "Extract action items from the content if there are any. If there are no action,"
+ " return nothing. If a single field is missing, use an empty string.\n"
+ "Return the action items in json.\n"
+ "\n"
+ "Possible statuses for action items are: Open, Closed, In Progress.\n"
+ "\n"
+ "EXAMPLE INPUT WITH ACTION ITEMS:\n"
+ "\n"
+ "John Doe said: \"I will record a demo for the new feature by Friday\"\n"
+ "I said: \"Great, thanks John. We may not use all of it but it's good to get it"
+ " out there.\"\n"
+ "\n"
+ "EXAMPLE OUTPUT:\n"
+ "{\n"
+ " \"actionItems\": [\n"
+ " {\n"
+ " \"owner\": \"John Doe\",\n"
+ " \"actionItem\": \"Record a demo for the new feature\",\n"
+ " \"dueDate\": \"Friday\",\n"
+ " \"status\": \"Open\",\n"
+ " \"notes\": \"\"\n"
+ " }\n"
+ " ]\n"
+ "}\n"
+ "\n"
+ "EXAMPLE INPUT WITHOUT ACTION ITEMS:\n"
+ "\n"
+ "John Doe said: \"Hey I'm going to the store, do you need anything?\"\n"
+ "I said: \"No thanks, I'm good.\"\n"
+ "\n"
+ "EXAMPLE OUTPUT:\n"
+ "{\n"
+ " \"action_items\": []\n"
+ "}\n"
+ "\n"
+ "CONTENT STARTS HERE.\n"
+ "\n"
+ "{{$INPUT}}\n"
+ "\n"
+ "CONTENT STOPS HERE.\n"
+ "\n"
+ "OUTPUT:";
public static final String GetConversationTopicsDefinition =
"Analyze the following extract taken from a conversation transcript and extract key"
+ " topics.\n"
+ "- Topics only worth remembering.\n"
+ "- Be brief. Short phrases.\n"
+ "- Can use broken English.\n"
+ "- Conciseness is very important.\n"
+ "- Topics can include names of memories you want to recall.\n"
+ "- NO LONG SENTENCES. SHORT PHRASES.\n"
+ "- Return in JSON\n"
+ "[Input]\n"
+ "My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is"
+ " Lady Macbeth and we were married for 15 years. We had no children. Our beloved"
+ " dog Toby McDuff was a famous hunter of rats in the forest.\n"
+ "My tragic story was immortalized by Shakespeare in a play.\n"
+ "[Output]\n"
+ "{\n"
+ " \"topics\": [\n"
+ " \"Macbeth\",\n"
+ " \"King of Scotland\",\n"
+ " \"Lady Macbeth\",\n"
+ " \"Dog\",\n"
+ " \"Toby McDuff\",\n"
+ " \"Shakespeare\",\n"
+ " \"Play\",\n"
+ " \"Tragedy\"\n"
+ " ]\n"
+ "}\n"
+ "+++++\n"
+ "[Input]\n"
+ "{{$INPUT}}\n"
+ "[Output]";
}
@@ -1,248 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.memory.MemoryException;
import com.microsoft.semantickernel.memory.MemoryQueryResult;
import com.microsoft.semantickernel.memory.MemoryRecordMetadata;
import com.microsoft.semantickernel.memory.SemanticTextMemory;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import reactor.core.publisher.Mono;
/**
* TextMemorySkill provides a skill to save or recall information from the long or short term.
* Usage: {@code kernel.ImportSkill(new TextMemorySkill(), "memory");} Example: {@code
* {{memory.recall "what is the capital of France?" }} => "Paris"}
*/
public class TextMemorySkill {
/** Name of the context variable used to specify which memory collection to use. */
public static final String COLLECTION_PARAM = "collection";
/** Name of the context variable used to specify the information to store. */
public static final String INFO_PARAM = "info";
/** Name of the context variable used to specify the input to the skill. */
public static final String INPUT_PARAM = "input";
/** Name of the context variable used to specify memory search relevance score. */
public static final String RELEVANCE_PARAM = "relevance";
/**
* Name of the context variable used to specify a unique key associated with stored information.
*/
public static final String KEY_PARAM = "key";
/** Name of the context variable used to specify the number of memories to recall */
public static final String LIMIT_PARAM = "limit";
/** Default value for the collection name. */
public static final String DEFAULT_COLLECTION = "generic";
/** Default value for the relevance score. */
public static final String DEFAULT_RELEVANCE = "0.75";
/** Default value for the limit. */
public static final String DEFAULT_LIMIT = "1";
/**
* Key-based lookup for a specific memory.
*
* @param collection The collection containing the memory to retrieve
* @param key The key associated with the memory to retrieve
* @param context The context containing the semantic memory
* @return The memory associated with the key
*/
@DefineSKFunction(description = "Key-based lookup for a specific memory", name = "Retrieve")
public Mono<String> retrieveAsync(
@SKFunctionParameters(
name = COLLECTION_PARAM,
description =
"Memories collection associated with the memory to retrieve",
defaultValue = DEFAULT_COLLECTION)
String collection,
@SKFunctionParameters(
name = KEY_PARAM,
description = "The key associated with the memory to retrieve")
String key,
SKContext context) {
SemanticTextMemory memory = context.getSemanticMemory();
if (memory == null) {
return Mono.error(new RuntimeException("Memory not present"));
}
return memory.getAsync(collection, key, false)
.map(it -> it.getMetadata().getText())
.defaultIfEmpty("");
}
/**
* Save information to semantic memory.
*
* @param info The information to save
* @param collection Memories collection associated with the information to save
* @param key The key associated with the information to save
* @param context The context containing the semantic memory
* @return The key associated with the saved information
*/
@DefineSKFunction(description = "Save information to semantic memory", name = "Save")
public Mono<SKContext> saveAsync(
@SKFunctionParameters(
name = INFO_PARAM,
description = "The information to save",
defaultValue = "",
type = String.class)
String info,
@SKFunctionParameters(
name = COLLECTION_PARAM,
description =
"Memories collection associated with the information to save",
defaultValue = DEFAULT_COLLECTION,
type = String.class)
String collection,
@SKFunctionParameters(
name = KEY_PARAM,
description = "The key associated with the information to save",
defaultValue = "",
type = String.class)
String key,
SKContext context) {
SemanticTextMemory memory = context.getSemanticMemory();
if (memory == null) {
return Mono.error(
new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present"));
}
return memory.saveInformationAsync(collection, info, key, null, null)
.map(
it -> {
context.setVariable(TextMemorySkill.KEY_PARAM, it);
return SKBuilders.context()
.withVariables(context.getVariables())
.withSkills(context.getSkills())
.withMemory(context.getSemanticMemory())
.build();
});
}
/**
* Semantic search and return up to N memories related to the input text
*
* @param input The input text to find related memories for
* @param collection Memories collection to search
* @param relevance The relevance score, from 0.0 to 1.0, where 1.0 means perfect match
* @param limit The maximum number of relevant memories to recall
* @param context Contains the memory to search
* @return The list of memories related to the input text
*/
@DefineSKFunction(
description = "Semantic search and return up to N memories related to the input text",
name = "Recall")
public Mono<List<String>> recallAsync(
@SKFunctionParameters(
name = INPUT_PARAM,
description = "The information to recall",
defaultValue = "",
type = String.class)
@Nonnull
String input,
@SKFunctionParameters(
name = COLLECTION_PARAM,
description =
"Memories collection associated with the information to recall",
defaultValue = DEFAULT_COLLECTION,
type = String.class)
String collection,
@SKFunctionParameters(
name = RELEVANCE_PARAM,
description =
"The relevance score, from 0.0 to 1.0, where 1.0 means perfect"
+ " match",
defaultValue = DEFAULT_RELEVANCE,
type = Double.class)
double relevance,
@SKFunctionParameters(
name = LIMIT_PARAM,
description = "The maximum number of relevant memories to recall",
defaultValue = DEFAULT_LIMIT,
type = Integer.class)
int limit,
@Nonnull SKContext context) {
SemanticTextMemory memory = context.getSemanticMemory();
if (memory == null) {
return Mono.error(
new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present"));
}
// TODO: 1.0 fix cast
// Validate parameters
if (collection == null || collection.trim().isEmpty()) {
if (context.getVariables().get(TextMemorySkill.COLLECTION_PARAM) == null) {
collection = DEFAULT_COLLECTION;
} else {
collection =
context.getVariables().get(TextMemorySkill.COLLECTION_PARAM).toString();
}
}
final String _collection = collection;
final float _relevance = (float) Math.min(1.0, Math.max(0.0, relevance));
final int _limit = Math.max(1, limit);
// context.Log.LogTrace("Searching memories in collection '{0}', relevance '{1}'",
// collection, relevance);
// Search memory
return memory.searchAsync(_collection, input, _limit, _relevance, false)
.flatMap(
results -> {
List<String> memories =
results.stream()
.map(MemoryQueryResult::getMetadata)
.map(MemoryRecordMetadata::getText)
.collect(Collectors.toList());
return Mono.just(memories);
});
}
/**
* Remove information from semantic memory
*
* @param collection Memories collection associated with the information to remove
* @param key The key associated with the information to remove
* @param context Contains the memory to remove
* @return The reactive stream
*/
@DefineSKFunction(description = "Remove information from semantic memory", name = "Remove")
public Mono<Void> removeAsync(
@SKFunctionParameters(
name = COLLECTION_PARAM,
description =
"Memories collection associated with the information to remove",
defaultValue = DEFAULT_COLLECTION,
type = String.class)
String collection,
@SKFunctionParameters(
name = KEY_PARAM,
description = "The key associated with the information to remove",
defaultValue = "",
type = String.class)
String key,
SKContext context) {
SemanticTextMemory memory = context.getSemanticMemory();
if (memory == null) {
return Mono.error(
new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present"));
}
return memory.removeAsync(collection, key);
}
}
@@ -1,39 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import java.util.Locale;
/** TextSkill provides a set of functions to manipulate strings. */
public class TextSkill {
@DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase")
public String uppercase(
@SKFunctionInputAttribute(description = "Text to uppercase") String text) {
return text.toUpperCase(Locale.ROOT);
}
@DefineSKFunction(description = "Remove spaces to the left of a string.", name = "LStrip")
public String lStrip(@SKFunctionInputAttribute(description = "Text to edit") String text) {
return text.replaceAll("^ +", "");
}
@DefineSKFunction(description = "Remove spaces to the right of a string.", name = "RStrip")
public String rStrip(@SKFunctionInputAttribute(description = "Text to edit") String text) {
return text.replaceAll(" +$", "");
}
@DefineSKFunction(
description = "Remove spaces to the left and right of a string",
name = "Strip")
public String strip(@SKFunctionInputAttribute(description = "Text to edit") String input) {
return input.trim();
}
@DefineSKFunction(description = "Change all string chars to lowercase", name = "lowercase")
public String lowercase(
@SKFunctionInputAttribute(description = "Text to lowercase") String input) {
return input.toLowerCase(Locale.ROOT);
}
}
@@ -1,428 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.util.LocaleParser;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;
/**
* Description: TimeSkill provides a set of functions to get the current time and date.
*
* <p>Usage: kernel.importSkill(new TimeSkill(), "time");
*
* <p>Examples:
*
* <p>{{time.date}} => Sunday, 12 January, 2031
*
* <p>{{time.today}} => Sunday, 12 January, 2031
*
* <p>{{time.now}} => Sunday, January 12, 2031 9:15 PM
*
* <p>{{time.utcNow}} => Sunday, January 13, 2031 5:15 AM
*
* <p>{{time.time}} => 09:15:07 PM
*
* <p>{{time.year}} => 2031
*
* <p>{{time.month}} => January
*
* <p>{{time.monthNumber}} => 01
*
* <p>{{time.day}} => 12
*
* <p>{{time.dayOfWeek}} => Sunday
*
* <p>{{time.hour}} => 9 PM
*
* <p>{{time.hourNumber}} => 21
*
* <p>{{time.days_ago $days}} => Sunday, 7 May, 2023
*
* <p>{{time.last_matching_day $dayName}} => Sunday, 7 May, 2023
*
* <p>{{time.minute}} => 15
*
* <p>{{time.second}} => 7
*
* <p>{{time.timeZoneOffset}} => -08:00
*
* <p>{{time.timeZoneName}} => Pacific Time
*/
public class TimeSkill {
public static final String DAY_MONTH_DAY_YEAR = "EEEE, MMMM d, yyyy";
/**
* Get the current date and time for the system default timezone.
*
* @return a ZonedDateTime object with the current date and time.
*/
public ZonedDateTime now() {
return ZonedDateTime.now(ZoneId.systemDefault());
}
/**
* Get the current date.
*
* <p>Example: {{time.date}} => Sunday, January 12, 2025
*
* @return The current date.
*/
@DefineSKFunction(name = "date", description = "Get the current date")
public String date(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
// Example: Sunday, 12 January, 2025
return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR)
.withLocale(parseLocale(locale))
.format(now());
}
/**
* Get the current time.
*
* <p>Example: {{time.time}} => 9:15:00 AM
*
* @return The current time.
*/
@DefineSKFunction(name = "time", description = "Get the current time")
public String time(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
// Example: 09:15:07 PM
return DateTimeFormatter.ofPattern("hh:mm:ss a")
.withLocale(parseLocale(locale))
.format(now());
}
/**
* Get the current UTC date and time.
*
* <p>Example: {{time.utcNow}} => Sunday, January 13, 2025 5:15 AM
*
* @return The current UTC date and time.
*/
@DefineSKFunction(name = "utcNow", description = "Get the current UTC date and time")
public String utcNow(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a")
.withLocale(parseLocale(locale))
.format(now().withZoneSameInstant(ZoneOffset.UTC));
}
/**
* Get the current date (alias for date() method).
*
* <p>Example: {{time.today}} => Sunday, January 12, 2025
*
* @return The current date.
*/
@DefineSKFunction(name = "today", description = "Get the current date")
public String today(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return date(locale);
}
/**
* Get the current date and time in the local time zone.
*
* <p>Example: {{time.now}} => Sunday, January 12, 2025 9:15 AM
*
* @return The current date and time in the local time zone.
*/
@DefineSKFunction(
name = "now",
description = "Get the current date and time in the local time zone")
public String now(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a")
.withLocale(parseLocale(locale))
.format(now());
}
/**
* Get the current year.
*
* <p>Example: {{time.year}} => 2025
*
* @return The current year.
*/
@DefineSKFunction(name = "year", description = "Get the current year")
public String year(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("yyyy").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current month name.
*
* <p>Example: {{time.month}} => January
*
* @return The current month name.
*/
@DefineSKFunction(name = "month", description = "Get the current month name")
public String month(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("MMMM").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current month number.
*
* <p>Example: {{time.monthNumber}} => 01
*
* @return The current month number.
*/
@DefineSKFunction(name = "monthNumber", description = "Get the current month number")
public String monthNumber(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("MM").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current day of the month.
*
* <p>Example: {{time.day}} => 12
*
* @return The current day of the month.
*/
@DefineSKFunction(name = "day", description = "Get the current day of the month")
public String day(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("d").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current day of the week.
*
* <p>Example: {{time.dayOfWeek}} => Sunday
*
* @return The current day of the week.
*/
@DefineSKFunction(name = "dayOfWeek", description = "Get the current day of the week")
public String dayOfWeek(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("EEEE").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current clock hour.
*
* <p>Example: {{time.hour}} => 9 AM
*
* @return The current clock hour.
*/
@DefineSKFunction(name = "hour", description = "Get the current clock hour")
public String hour(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("h a").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the current clock 24-hour number.
*
* <p>Example: {{time.hourNumber}} => 09
*
* @return The current clock 24-hour number.
*/
@DefineSKFunction(name = "hourNumber", description = "Get the current clock 24-hour number")
public String hourNumber(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("HH").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the date of offset from today by a provided number of days
*
* <p>Example: SKContext context = SKBuilders.context().build(); context.setVariable("input",
* "3"); {{time.daysAgo $input}} => Saturday, January 11, 2031
*
* @param days Number of days to subtract from the current day
* @return The date of offset from today by a provided number of days
*/
@DefineSKFunction(
name = "daysAgo",
description = "Get the date of offset from today by a provided number of days")
public String daysAgo(
@SKFunctionInputAttribute(description = "Number of days to offset from today.")
String days,
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
int offsetDays = Integer.parseInt(days);
return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR)
.withLocale(parseLocale(locale))
.format(now().minusDays(offsetDays));
}
/**
* Get the date of the last day matching the supplied week day name
*
* <p>Example: {{time.dateMatchingLastDayName "Monday"}} => Monday, January 6, 2031
*
* @param dayName Name of the day to match
* @return The date of the last day matching the supplied week day name
*/
@DefineSKFunction(
name = "dateMatchingLastDayName",
description = "Get the date of the last day matching the supplied week day name")
public String dateMatchingLastDayName(
@SKFunctionInputAttribute(description = "Week name day.") String dayName,
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
ZonedDateTime currentDate = now();
for (int i = 1; i <= 7; i++) {
currentDate = currentDate.minusDays(1);
String currentDayName =
currentDate.getDayOfWeek().getDisplayName(TextStyle.FULL, parseLocale(locale));
if (currentDayName.equalsIgnoreCase(dayName)) {
return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR)
.withLocale(parseLocale(locale))
.format(currentDate);
}
}
throw new IllegalArgumentException("dayName is not recognized");
}
/**
* Get the minutes on the current hour.
*
* <p>Example: {{time.minute}} => 15
*
* @return The minutes on the current hour.
*/
@DefineSKFunction(name = "minute", description = "Get the minutes on the current hour")
public String minute(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("mm").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the seconds on the current minute.
*
* <p>Example: {{time.second}} => 00
*
* @return The seconds on the current minute.
*/
@DefineSKFunction(name = "second", description = "Get the seconds on the current minute")
public String second(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("ss").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the local time zone offset from UTC.
*
* <p>Example: {{time.timeZoneOffset}} => +03:00
*
* @return The local time zone offset from UTC.
*/
@DefineSKFunction(
name = "timeZoneOffset",
description = "Get the local time zone offset from UTC")
public String timeZoneOffset(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
return DateTimeFormatter.ofPattern("XXX").withLocale(parseLocale(locale)).format(now());
}
/**
* Get the local time zone name.
*
* <p>Example: {{time.timeZoneName}} => Pacific Time
*
* @return The local time zone name.
*/
@DefineSKFunction(name = "timeZoneName", description = "Get the local time zone name")
public String timeZoneName(
@SKFunctionParameters(
name = "locale",
description = "Locale to use when formatting the date",
required = false)
String locale) {
ZoneId zoneId = ZoneId.systemDefault();
return zoneId.getDisplayName(TextStyle.FULL, parseLocale(locale));
}
/**
* Parse the locale string into a Locale object.
*
* <p>By default, it parses using the LocaleParser utility class.
*
* @param locale string
* @return a locale object
*/
protected Locale parseLocale(String locale) {
return LocaleParser.parseLocale(locale);
}
}
@@ -1,36 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.coreskills;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import java.time.Duration;
import reactor.core.publisher.Mono;
/** WaitSkill provides a set of functions to wait before making the rest of operations. */
public class WaitSkill {
/**
* Wait for a certain number of seconds.
*
* <p>Examples:
*
* <p>SKContext context = SKBuilders.context().build();
*
* <p>context.setVariable("input","10");
*
* <p>{{wait.seconds $input}}
*
* @param seconds The number of seconds to wait as a string.
* @return A Mono that completes after the specified delay.
* @throws IllegalArgumentException If the input is not a valid number.
*/
@DefineSKFunction(name = "seconds", description = "Wait a given amount of seconds")
public Mono<Void> wait(String seconds) {
try {
double sec = Math.max(Double.parseDouble(seconds), 0);
long milliseconds = (long) (sec * 1000);
return Mono.delay(Duration.ofMillis(milliseconds)).then();
} catch (NumberFormatException e) {
return Mono.error(new IllegalArgumentException("seconds text must be a number", e));
}
}
}
@@ -1,9 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.util;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.util.Locale;
import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
/**
* Locale parser to support Java 8 and Java 9+ due to JEP 252.
*
@@ -29,7 +31,7 @@ public final class LocaleParser {
if (locale == null
|| "".equals(locale.trim())
|| SKFunctionParameters.NO_DEFAULT_VALUE.equals(locale)) {
|| KernelFunctionParameter.NO_DEFAULT_VALUE.equals(locale)) {
return Locale.getDefault();
} else if (locale.indexOf("-") > -1) {
parsedLocale = Locale.forLanguageTag(locale);
+7 -9
View File
@@ -13,7 +13,7 @@
<description>Parent pom for the Semantic Kernel Project</description>
<properties>
<azure-ai-openai.version>1.0.0-beta.5</azure-ai-openai.version>
<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>
<google.errorprone.core.version>2.19.1</google.errorprone.core.version>
@@ -72,16 +72,14 @@
<!-- <module>connectors/semantickernel-connectors-memory-mysql</module>-->
<module>aiservices/azureopenai</module>
<module>aiservices/huggingface</module>
<module>aiservices/ollama</module>
<!-- <module>aiservices/huggingface</module>-->
<!-- <module>aiservices/ollama</module>-->
<module>aiservices/openai</module>
<module>misc/semantickernel-gpt3-tokenizer</module>
<module>misc/semantickernel-settings-loader</module>
<!-- <module>misc/semantickernel-gpt3-tokenizer</module>-->
<!-- <module>misc/semantickernel-settings-loader</module>-->
<!--
<module>plugins/semantickernel-planners</module>
-->
<!-- <module>plugins/semantickernel-planners</module>-->
<module>plugins/semantickernel-plugin-core</module>
<module>semantickernel-bom</module>
@@ -727,7 +725,7 @@
<profile>
<id>with-samples</id>
<modules>
<module>samples/sk-v1</module>
<module>samples</module>
<!-- <module>api-test</module>-->
</modules>
</profile>
+4 -3
View File
@@ -1,5 +1,6 @@
<?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>
<groupId>com.microsoft.semantic-kernel</groupId>
@@ -10,9 +11,9 @@
<description>Parent pom for sample code for using the Semantic Kernel project</description>
<modules>
<!-- <module>sample-code</module>
<module>semantickernel-samples-guice</module> -->
<!-- <module>semantickernel-samples-guice</module> -->
<module>sk-v1</module>
<module>sample-code</module>
</modules>
<properties>
+9 -2
View File
@@ -18,15 +18,15 @@
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-api</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-core</artifactId>
<!-- TODO: scope should be runtime, but VolatileMemoryStore is an issue -->
<!-- <scope>runtime</scope> -->
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
@@ -36,6 +36,7 @@
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-connectors-memory-azurecognitivesearch</artifactId>
</dependency>
-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
@@ -52,6 +53,7 @@
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.20.0</version>
</dependency>
<!--
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-planners</artifactId>
@@ -62,6 +64,7 @@
<artifactId>semantickernel-gpt3-tokenizer</artifactId>
<scope>compile</scope>
</dependency>
-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -80,6 +83,10 @@
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-azureopenai</artifactId>
</dependency>
</dependencies>
<build>
@@ -1,73 +0,0 @@
package com.microsoft.semantickernel;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.planner.actionplanner.Plan;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.io.IOException;
/**
* Code for Microsoft Developer Blog
* <a href="https://devblogs.microsoft.com/semantic-kernel/introducing-semantic-kernel-for-java/">
* Introducing Semantic Kernel for Java</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example99_BlogAnnouncement {
static {
System.setProperty("client.openai.key", "");
}
public static void main(String[] args) throws IOException, ConfigurationException {
OpenAIAsyncClient client = OpenAIClientProvider.getClient();
TextCompletion textCompletionService = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletionService).build();
kernel.importSkill(new MyAppSkills(), "MyAppSkills");
SequentialPlanner planner = new SequentialPlanner(kernel, null, null);
Plan plan = planner.createPlanAsync(
"For any input with passwords, redact the passwords and send redacted input to [email protected]")
.block();
System.out.println(plan.toPlanString());
String message = "Password changed to password.db=123456abc";
String result = plan.invokeAsync(message).block().getResult();
System.out.println(" === Result of the plan === ");
System.out.println(result);
}
public static class MyAppSkills {
@DefineSKFunction(name = "redactPassword", description = "Redacts passwords from a message")
public String redactPassword(
@SKFunctionInputAttribute(
description = "The input message to redact passwords from"
) String input) {
System.out.println("[redactPassword] Redacting passwords from input: " + input);
return input.replaceAll("password.*", "******");
}
@DefineSKFunction(name = "sendEmail", description = "Sends a message to an email")
public String sendEmail(
@SKFunctionParameters(name = "message") String message,
@SKFunctionParameters(name = "email") String email) {
return String.format("[sendEmail] Emailing to %s the following message: %n -> %s%n", email, message);
}
}
}
@@ -1,121 +0,0 @@
package com.microsoft.semantickernel;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.planner.actionplanner.Plan;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
/**
* Example of a planner which uses native functions.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example_PlanWithNativeFunctions {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = OpenAIClientProvider.getClient();
TextCompletion textCompletionService = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(textCompletionService)
.build();
kernel.importSkill(new StringFunctions(), "StringFunctions");
kernel.importSkill(new Emailer(), "Emailer");
kernel.importSkill(new Names(), "Names");
SequentialPlanner planner = new SequentialPlanner(kernel, null, null);
Plan plan = planner
.createPlanAsync("Send the input as an email to Steven and make sure I use his preferred name in the email")
.block();
System.out.println("\n\n=============================== Plan to execute ===============================");
System.out.println(plan.toPlanString());
System.out.println("===============================================================================");
SKContext context = SKBuilders.context().build();
context.setVariable("subject", "Update");
String message = "Hay Steven, just wanted to let you know I have finished.";
System.out.println("\n\nExecuting plan...");
SKContext planResult = plan.invokeAsync(message, context, null).block();
System.out.println("\n\nPlan Result: " + planResult.getResult());
}
public static class StringFunctions {
@DefineSKFunction(
name = "stringReplace",
description = "Takes a message and substitutes string 'from' to 'to'")
public String stringReplace(
@SKFunctionInputAttribute(description = "The string to perform the replacement on")
String input,
@SKFunctionParameters(name = "from", description = "The string to replace")
String from,
@SKFunctionParameters(name = "to", description = "The string to replace with")
String to
) {
return input.replaceAll(from, to);
}
}
public static class Names {
@DefineSKFunction(name = "getNickName", description = "Retrieves the nick name for a given user")
public String getNickName(
@SKFunctionInputAttribute(description = "The name of the person to get an nick name for")
String name) {
switch (name) {
case "Steven":
return "Code King";
default:
throw new RuntimeException("Unknown user: " + name);
}
}
}
public static class Emailer {
@DefineSKFunction(name = "getEmailAddress", description = "Retrieves the email address for a given user")
public String getEmailAddress(
@SKFunctionInputAttribute(description = "The name of the person to get an email address for")
String name) {
switch (name) {
case "Steven":
return "[email protected]";
default:
throw new RuntimeException("Unknown user: " + name);
}
}
@DefineSKFunction(name = "sendEmail", description = "Sends an email")
public String sendEmail(
@SKFunctionParameters(name = "subject", description = "The email subject") String subject,
@SKFunctionParameters(name = "message", description = "The message to email") String message,
@SKFunctionParameters(name = "emailAddress", description = "The emailAddress to send the message to") String emailAddress) {
System.out.println("================= Sending Email ====================");
System.out.printf("To: %s%n", emailAddress);
System.out.printf("Subject: %s%n", subject);
System.out.printf("Message: %s%n", message);
System.out.println("====================================================");
return "Message sent";
}
}
}
@@ -1,26 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import java.io.File;
import java.util.List;
/**
* Helper for creating
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class SamplesConfig {
public static final List<File> DEFAULT_PROPERTIES_LOCATIONS = List.of(
new File("java/samples/conf.properties")
);
public static OpenAIAsyncClient getClient() throws ConfigurationException {
return OpenAIClientProvider.getWithAdditional(DEFAULT_PROPERTIES_LOCATIONS);
}
}
@@ -1,80 +0,0 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
//DEPS org.slf4j:slf4j-jdk14:2.0.7
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java
package com.microsoft.semantickernel.samples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import java.io.IOException;
import reactor.core.publisher.Mono;
/**
* Getting started
* <p>
* <a href=
* "https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart">Get
* started with Azure OpenAI</a>
* <a href="https://openai.com/product">Get started with OpenAI</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example00_GettingStarted {
/**
* Returns a Semantic Kernel with Text Completion.
*
* @param client Client that will handle requests to AzureOpenAI or OpenAI.
* @return Kernel.
*/
public static Kernel getKernel(OpenAIAsyncClient client) {
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build())
.build();
return kernel;
}
/**
* Imports 'FunSkill' from directory examples and runs the 'Joke' function
* within it.
*
* @param kernel Kernel with Text Completion.
*/
public static void joke(Kernel kernel) {
ReadOnlyFunctionCollection skill = kernel.importSkillFromDirectory("FunSkill", SampleSkillsUtil.detectSkillDirLocation(), "FunSkill");
CompletionSKFunction function = skill.getFunction("Joke",
CompletionSKFunction.class);
Mono<SKContext> result = function.invokeAsync("time travel to dinosaur age");
if (result != null) {
System.out.println(result.block().getResult());
}
}
public static void run(OpenAIAsyncClient client) {
Kernel kernel = getKernel(client);
joke(kernel);
}
public static void main(String args[]) throws ConfigurationException, IOException {
run(OpenAIClientProvider.getClient());
}
}
@@ -1,62 +0,0 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
//DEPS org.slf4j:slf4j-jdk14:2.0.7
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java
package com.microsoft.semantickernel.samples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import java.io.IOException;
/**
* Using Semantic Functions stored on disk
* <p>
* A Semantic Skill is a collection of Semantic Functions, where each function
* is defined with natural language that can be provided with a text file.
* Refer to our <a href=
* "https://github.com/microsoft/semantic-kernel/blob/main/docs/GLOSSARY.md">glossary</a>
* for an in-depth guide to the terms.
* <p>
* The repository includes some examples under the <a href=
* "https://github.com/microsoft/semantic-kernel/tree/main/samples">samples</a>
* folder.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example02_RunningPromptsFromFile {
/**
* Imports skill 'FunSkill' stored in the samples folder and then returns the
* semantic function 'Joke' within it.
*
* @param kernel
with Text Completion
* @return Joke function
*/
public static CompletionSKFunction getJokeFunction(Kernel kernel) {
ReadOnlyFunctionCollection skill = kernel
.importSkillFromDirectory("FunSkill", SampleSkillsUtil.detectSkillDirLocation(), "FunSkill");
return skill.getFunction("Joke", CompletionSKFunction.class);
}
public static void run(OpenAIAsyncClient client) throws IOException {
Kernel kernel = Example00_GettingStarted.getKernel(client);
CompletionSKFunction jokeFunction = getJokeFunction(kernel);
System.out.println(jokeFunction.invokeAsync("time travel to dinosaur age").block().getResult());
}
public static void main(String args[]) throws ConfigurationException, IOException {
run(OpenAIClientProvider.getClient());
}
}
@@ -1,135 +0,0 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
//DEPS org.slf4j:slf4j-jdk14:2.0.7
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java
package com.microsoft.semantickernel.samples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import java.io.IOException;
import reactor.core.publisher.Mono;
/**
* Define a Semantic Function inline with Java code.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example03_SemanticFunctionInline {
/**
* Defines and runs an inline Semantic Function
*
* @param kernel Kernel with Text Completion
* @param prompt String prompt
* @param functionName Name of the function
* @param text Input to the function
*/
public static void inlineFunction(Kernel kernel, String prompt, String functionName, String text) {
SKFunction summarize = kernel
.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName(functionName)
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(
0.2,
0.5,
0,
0,
2000))
.build();
Mono<SKContext> result = summarize.invokeAsync(text);
if (result != null) {
System.out.println(result.block().getResult());
}
}
/**
* Example prompt that summarizes text
*
* @param kernel
*/
public static void summarize(Kernel kernel) {
String prompt = """
{{$input}}
Summarize the content above.
""";
String text = """
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the Roman period,
known for a single epigram, engraved upon the Colossus of Memnon, which bears her name.
She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies.
The name was relatively common in the Hellenistic world, in Egypt and elsewhere,
and she cannot be further identified.
The date of her visit to the Colossus of Memnon cannot be established with certainty,
but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets,
entitled and presumably authored by "Demo" or "Damo"
(the Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla,
though the internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect.
In return, Demo offers the gift for poetry, as a gift to the hero.
At the end of this epigram, she addresses Memnon,
highlighting his divine status by recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect.
The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift',
for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2]
""";
inlineFunction(kernel, prompt, "summarize", text);
}
/**
* Example of a prompt returning a TLDR of a text
*
* @param kernel
*/
public static void TLDR(Kernel kernel) {
String prompt = """
{{$input}}
Give me the TLDR in 5 words.
""";
String text = """
1) A robot may not injure a human being or, through inaction,
allow a human being to come to harm.
2) A robot must obey orders given it by human beings except where
such orders would conflict with the First Law.
3) A robot must protect its own existence as long as such protection
does not conflict with the First or Second Law.
""";
inlineFunction(kernel, prompt, "tldr", text);
}
public static void run(OpenAIAsyncClient client) throws IOException {
Kernel kernel = Example00_GettingStarted.getKernel(client);
summarize(kernel);
TLDR(kernel);
}
public static void main(String args[]) throws ConfigurationException, IOException {
run(OpenAIClientProvider.getClient());
}
}
@@ -1,119 +0,0 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
//DEPS org.slf4j:slf4j-jdk14:2.0.7
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java
package com.microsoft.semantickernel.samples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import reactor.core.publisher.Mono;
/**
* Chatbot using context variables
* <p>
* Context Variables object which in this demo functions similarly as a
* key-value store that you can use when running the kernel.
* The context is local (i.e. in your computer's RAM) and not persisted anywhere
* beyond the life of the JVM execution.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example04_ContextVariablesChat {
public static void startChat(Kernel kernel)
throws ExecutionException, InterruptedException, TimeoutException {
String prompt = """
ChatBot can have a conversation with you about any topic.
It can give explicit instructions or say 'I don't know' if it does not have an answer.
{{$history}}
User: {{$user_input}}
ChatBot: """;
CompletionSKFunction chat = kernel
.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName("ChatBot")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(
0.7,
0.5,
0,
0,
2000))
.build();
SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build();
chat("Hi, I'm looking for book suggestions?", chat, readOnlySkContext)
.flatMap(
chat(
"I love history and philosophy, I'd like to learn something new"
+ " about Greece, any suggestion?",
chat))
.flatMap(chat("that sounds interesting, what is it about?", chat))
.flatMap(
chat(
"if I read that book, what exactly will I learn about Greece"
+ " history?",
chat))
.flatMap(
chat("could you list some more books I could read about this topic?", chat))
.block();
}
private static Mono<SKContext> chat(
String input, CompletionSKFunction chat, SKContext context)
throws ExecutionException, InterruptedException, TimeoutException {
context = context.setVariable("user_input", input);
System.out.println("User: " + input);
SKContext finalContext = context;
return chat.invokeAsync(context, null)
.map(
result -> {
System.out.println("Bot: " + result.getResult() + "\n");
String existingHistoy = finalContext.getVariables().asMap().get("history");
if (existingHistoy == null) {
existingHistoy = "";
}
existingHistoy += "\nUser: " + input + "\nChatBot: " + result.getResult() + "\n";
return finalContext.setVariable("history", existingHistoy);
});
}
private static Function<SKContext, Mono<SKContext>> chat(
String input, CompletionSKFunction chat) {
return (context) -> {
try {
return chat(input, chat, context);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
return Mono.error(e);
}
};
}
public static void run(OpenAIAsyncClient client) throws ExecutionException, InterruptedException, TimeoutException {
Kernel kernel = Example00_GettingStarted.getKernel(client);
startChat(kernel);
}
public static void main(String args[]) throws ConfigurationException, ExecutionException, InterruptedException, TimeoutException {
run(OpenAIClientProvider.getClient());
}
}
@@ -1,51 +0,0 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha
//DEPS com.microsoft.semantic-kernel.extensions:semantickernel-sequentialplanner-extension:0.2.6-alpha
//DEPS org.slf4j:slf4j-jdk14:2.0.7
//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java
package com.microsoft.semantickernel.samples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil;
/**
* Sequential Planner
* <p>
* See <a href=
* "https://devblogs.microsoft.com/semantic-kernel/semantic-kernel-planners-sequential-planner/">
* Semantic Kernel Planners: Sequential Planner</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example05_UsingThePlanner {
public static SequentialPlanner getPlanner(Kernel kernel) {
kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill");
kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill");
return new SequentialPlanner(kernel, null, null);
}
public static void run(OpenAIAsyncClient client) {
Kernel kernel = Example00_GettingStarted.getKernel(client);
SequentialPlanner planner = getPlanner(kernel);
System.out.println(planner.createPlanAsync(
"Write a poem about John Doe, then translate it into Italian.")
.block().invokeAsync().block().getResult());
// TODO: execute the plan
}
public static void main(String args[]) throws ConfigurationException {
run(OpenAIClientProvider.getClient());
}
}
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.plugins;
import com.microsoft.semantickernel.plugin.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
import java.util.Locale;
/**
* TextSkill provides a set of functions to manipulate strings.
*/
public class TextPlugin {
@DefineKernelFunction(description = "Change all string chars to uppercase.", name = "Uppercase")
public String uppercase(
@KernelFunctionParameter(
description = "Text to uppercase",
name = "input") String text) {
return text.toUpperCase(Locale.ROOT);
}
@DefineKernelFunction(description = "Remove spaces to the left of a string.", name = "LStrip")
public String lStrip(@KernelFunctionParameter(description = "Text to edit",
name = "input") String text) {
return text.replaceAll("^ +", "");
}
@DefineKernelFunction(description = "Remove spaces to the right of a string.", name = "RStrip")
public String rStrip(@KernelFunctionParameter(description = "Text to edit",
name = "input") String text) {
return text.replaceAll(" +$", "");
}
@DefineKernelFunction(
description = "Remove spaces to the left and right of a string",
name = "Strip")
public String strip(@KernelFunctionParameter(description = "Text to edit",
name = "input") String input) {
return input.trim();
}
@DefineKernelFunction(description = "Change all string chars to lowercase", name = "lowercase")
public String lowercase(
@KernelFunctionParameter(description = "Text to lowercase",
name = "input") String input) {
return input.toLowerCase(Locale.ROOT);
}
}
@@ -1,6 +1,6 @@
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.microsoft.semantickernel.coreskills.TextSkill;
import com.microsoft.semantickernel.samples.plugins.TextPlugin;
/**
* Demonstrates a native function from the {@code com.microsoft.semantickernel.coreskills} package.
@@ -10,7 +10,7 @@ public class Example01_NativeFunctions {
public static void main(String[] args) {
// Load native skill
TextSkill text = new TextSkill();
TextPlugin text = new TextPlugin();
// Use function without kernel
String result = text.uppercase("ciao!");
@@ -1,29 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.coreskills.TextSkill;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import reactor.core.publisher.Mono;
/**
* Demonstrates running a pipeline (a sequence of functions) over some input.
*/
public class Example02_Pipeline {
public static void main(String[] args) {
Kernel kernel = SKBuilders.kernel().build();
// Load native skill
ReadOnlyFunctionCollection text = kernel.importSkill(new TextSkill(), null);
Mono<SKContext> result =
kernel.runAsync(
" i n f i n i t e s p a c e ",
text.getFunction("LStrip"),
text.getFunction("RStrip"),
text.getFunction("Uppercase"));
System.out.println(result.block().getResult());
}
}
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.microsoft.semantickernel.DefaultKernel;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.plugin.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
import java.util.Locale;
import reactor.core.publisher.Mono;
/**
* Demonstrates running a pipeline (a sequence of functions) on a
* {@code com.microsoft.semantickernel.orchestration.SKContext}
*/
public class Example03_Arguments {
public static class StaticTextSkill {
@DefineKernelFunction(description = "Change all string chars to uppercase.", name = "Uppercase")
public static Mono<String> uppercase(
@KernelFunctionParameter(
description = "Text to uppercase",
name = "input")
String text) {
return Mono.just(text.toUpperCase(Locale.ROOT));
}
@DefineKernelFunction(description = "Append the day variable", name = "appendDay")
public Mono<String> appendDay(
@KernelFunctionParameter(description = "Text to append to", name = "input")
String input,
@KernelFunctionParameter(description = "Current day", name = "day") String day) {
return Mono.just(input + day);
}
}
public static void main(String[] args) {
Kernel kernel = new DefaultKernel.Builder().build();
// Load native skill
KernelPlugin functionCollection =
KernelPluginFactory.createFromObject(new StaticTextSkill(), "text");
KernelArguments arguments = KernelArguments.builder()
.withInput("Today is: ")
.build()
.writableClone()
.setVariable("day", "Monday");
ContextVariable<String> resultValue = kernel.invokeAsync(
functionCollection.get("AppendDay"),
arguments,
String.class)
.block();
System.out.println(resultValue.getValue());
}
}
@@ -1,60 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.util.Locale;
import reactor.core.publisher.Mono;
/**
* Demonstrates running a pipeline (a sequence of functions) on a
* {@code com.microsoft.semantickernel.orchestration.SKContext}
*/
public class Example03_Variables {
public static class StaticTextSkill {
@DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase")
public static Mono<String> uppercase(
@SKFunctionInputAttribute(description = "Text to uppercase")
String text) {
return Mono.just(text.toUpperCase(Locale.ROOT));
}
@DefineSKFunction(description = "Append the day variable", name = "appendDay")
public Mono<String> appendDay(
@SKFunctionInputAttribute(description = "Text to append to")
String input,
@SKFunctionParameters(description = "Current day", name = "day") String day) {
return Mono.just(input + day);
}
}
public static void main(String[] args) {
Kernel kernel = SKBuilders.kernel().build();
// Load native skill
ReadOnlyFunctionCollection functionCollection =
kernel.importSkill(new StaticTextSkill(), "text");
ContextVariables variables =
SKBuilders.variables()
.withInput("Today is: ")
.build()
.writableClone()
.setVariable("day", "Monday");
Mono<SKContext> result =
kernel.runAsync(
variables,
functionCollection.getFunction("AppendDay"),
functionCollection.getFunction("Uppercase"));
System.out.println(result.block().getResult());
}
}
@@ -1,58 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import reactor.core.publisher.Mono;
/**
* Demonstrates using skill in combination with LLM prompts.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example04_CombineLLMPromptsAndNativeCode {
public static class SearchEngineSkill {
@DefineSKFunction(description = "Search for answer", name = "search")
public Mono<String> search(
@SKFunctionInputAttribute(description = "Text to search")
String input) {
return Mono.just("Gran Torre Santiago is the tallest building in South America");
}
}
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
TextCompletion textCompletion = SKBuilders.chatCompletion()
.withModelId("gpt-35-turbo-2")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
kernel.importSkill(new SearchEngineSkill(), null);
kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(),
"SummarizeSkill");
// Run
String ask = "What's the tallest building in South America?";
Mono<SKContext> result =
kernel.runAsync(
ask,
kernel.getSkills().getFunction("Search", null),
kernel.getSkill("SummarizeSkill").getFunction("Summarize", null));
System.out.println(result.block().getResult());
}
}
@@ -1,85 +1,99 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.DefaultKernel;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.aiservices.azureopenai.AzureOpenAITextGenerationService;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.time.LocalDateTime;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.plugin.KernelFunctionFactory;
import com.microsoft.semantickernel.samples.SamplesConfig;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
import com.microsoft.semantickernel.textcompletion.TextGenerationService;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
/**
* Demonstrates using prompt templates to define functions.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example05_InlineFunctionDefinition {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
TextCompletion textCompletion = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
public static void main(String[] args) throws ConfigurationException {
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
OpenAIAsyncClient client = SamplesConfig.getClient();
System.out.println("======== Inline Function Definition ========");
AzureOpenAITextGenerationService textGenerationService = AzureOpenAITextGenerationService.builder()
.withOpenAIAsyncClient(client)
.withModelId("text-davinci-003")
.build();
// Function defined using few-shot design pattern
String functionDefinition = """
Generate a creative reason or excuse for the given event.
Be creative and be funny. Let your imagination run wild.
Event: I am running late.
Excuse: I was being held ransom by giraffe gangsters.
Event: I haven't been to the gym for a year
Excuse: I've been too busy training my pet dragon.
Event: {{$input}}
""".stripIndent();
Kernel kernel = new DefaultKernel.Builder()
.withDefaultAIService(TextGenerationService.class, textGenerationService)
.build();
// Create function via builder
var excuseFunction = SKBuilders
.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(functionDefinition)
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfigBuilder()
.maxTokens(100)
.temperature(0.4)
.topP(1)
.build())
.build();
System.out.println("======== Inline Function Definition ========");
// Function defined using few-shot design pattern
String promptTemplate = """
Generate a creative reason or excuse for the given event.
Be creative and be funny. Let your imagination run wild.
Event: I am running late.
Excuse: I was being held ransom by giraffe gangsters.
Event: I haven't been to the gym for a year
Excuse: I've been too busy training my pet dragon.
Event: {{input}}
""".stripIndent();
var result = excuseFunction.invokeAsync("I missed the F1 final race").block();
System.out.println(result.getResult());
var excuseFunction = new KernelFunctionFromPrompt.Builder()
.withTemplate(promptTemplate)
.withDefaultExecutionSettings(
new PromptExecutionSettings.Builder()
.withTemperature(0.4)
.withTopP(1)
.withMaxTokens(100)
.build()
)
.build();
result = excuseFunction.invokeAsync("sorry I forgot your birthday").block();
System.out.println(result.getResult());
var result = kernel.invokeAsync(excuseFunction,
KernelArguments.builder()
.withInput("I missed the F1 final race")
.build(),
String.class)
.block();
System.out.println(result.getValue());
// Create function via kernel
var fixedFunction = kernel.
getSemanticFunctionBuilder()
.withPromptTemplate("Translate this date " +
DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(LocalDateTime.now()) + " to French format")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfigBuilder()
.maxTokens(100)
.temperature(0.4)
.topP(1)
.build())
.build();
result = kernel.invokeAsync(excuseFunction,
KernelArguments.builder()
.withInput("sorry I forgot your birthday")
.build(),
String.class)
.block();
System.out.println(result.getValue());
System.out.println(fixedFunction.invokeAsync().block().getResult());
}
var fixedFunction = KernelFunctionFactory.createFromPrompt(
"Translate this date " + DateTimeFormatter
.ISO_LOCAL_DATE
.withZone(ZoneOffset.UTC)
.format(Instant.now())
+ " to French format",
new PromptExecutionSettings.Builder()
.withMaxTokens(100)
.build(),
null,
null,
null,
null);
ContextVariable<String> fixedFunctionResult = kernel
.invokeAsync(fixedFunction, null, String.class)
.block();
System.out.println(fixedFunctionResult.getValue());
}
}
@@ -1,103 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.coreskills.TimeSkill;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
/**
* Show how to invoke a Native Function written in Java
* from a Semantic Function written in natural language
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example06_TemplateLanguage {
public static void main(String[] args) throws ConfigurationException {
System.out.println("======== TemplateLanguage ========");
OpenAIAsyncClient client = SamplesConfig.getClient();
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build())
.build();
// Load native skill into the kernel skill collection, sharing its functions
// with prompt templates
// Functions loaded here are available as "time.*"
kernel.importSkill(new TimeSkill(), "time");
// Semantic Function invoking time.Date and time.Time native functions
String functionDefinition = """
Today is: {{time.Date}}
Current time is: {{time.Time}}
Answer to the following questions using JSON syntax, including the data used.
Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)?
Is it weekend time (weekend/not weekend)?
""";
// This allows to see the prompt before it's sent to OpenAI
System.out.println("--- Rendered Prompt");
var promptRenderer = SKBuilders.promptTemplate()
.withPromptTemplateConfig(new PromptTemplateConfig())
.withPromptTemplate(functionDefinition)
.withPromptTemplateEngine(kernel.getPromptTemplateEngine())
.build();
SKContext skContext = SKBuilders
.context()
.withSkills(kernel.getSkills())
.build();
var renderedPrompt = promptRenderer.renderAsync(skContext);
System.out.println(renderedPrompt.block());
// Run the prompt / semantic function
var kindOfDay = kernel
.getSemanticFunctionBuilder()
.withPromptTemplate(functionDefinition)
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(
0, 0, 0, 0, 256))
.build();
// Show the result
System.out.println("--- Semantic Function result");
var result = kindOfDay.invokeAsync("").block().getResult();
System.out.println(result);
/*
* OUTPUT:
*
* --- Rendered Prompt
*
* Today is: Friday, April 28, 2023
* Current time is: 11:04:30 PM
*
* Answer to the following questions using JSON syntax, including the data used.
* Is it morning, afternoon, evening, or night
* (morning/afternoon/evening/night)?
* Is it weekend time (weekend/not weekend)?
*
* --- Semantic Function result
*
* {
* "date": "Friday, April 28, 2023",
* "time": "11:04:30 PM",
* "period": "night",
* "weekend": "weekend"
* }
*/
}
}
@@ -1,104 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import static com.microsoft.semantickernel.SamplesConfig.DEFAULT_PROPERTIES_LOCATIONS;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.http.policy.ExponentialBackoffOptions;
import com.azure.core.http.policy.RetryOptions;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.connectors.ai.openai.util.AzureOpenAISettings;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.settings.SettingsMap;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.time.Duration;
/**
* Demonstrates customizing the configuration of the Open AI client.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for endpoint and credential configuration.
*/
public class Example08_RetryHandler {
public static void main(String[] args) throws ConfigurationException {
RetryOptions retryOptions = new RetryOptions(new ExponentialBackoffOptions()
.setMaxDelay(Duration.ofSeconds(180))
.setBaseDelay(Duration.ofSeconds(60))
.setMaxRetries(3));
AzureOpenAISettings settings = new AzureOpenAISettings(SettingsMap.getWithAdditional(DEFAULT_PROPERTIES_LOCATIONS));
OpenAIAsyncClient client = new OpenAIClientBuilder()
.retryOptions(retryOptions)
.endpoint(settings.getEndpoint())
.credential(new AzureKeyCredential(settings.getKey()))
.buildAsyncClient();
String text = """
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
Roman period, known for a single epigram, engraved upon the Colossus of
Memnon, which bears her name. She speaks of herself therein as a lyric
poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter,
signifies. The name was relatively common in the Hellenistic world, in
Egypt and elsewhere, and she cannot be further identified. The date of her
visit to the Colossus of Memnon cannot be established with certainty, but
internal evidence on the left leg suggests her poem was inscribed there at
some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
couplets, entitled and presumably authored by "Demo" or "Damo" (the
Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla, though the
internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect. In
return, Demo offers the gift for poetry, as a gift to the hero. At the end
of this epigram, she addresses Memnon, highlighting his divine status by
recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
dialect. The language indicates she was knowledgeable in Homeric
poetry—'bearing a pleasant gift', for example, alludes to the use of that
phrase throughout the Iliad and Odyssey.[a][2];
""";
String prompt = "{{$input}}\nSummarize the content above.";
TextCompletion textCompletion = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders
.kernel()
.withDefaultAIService(textCompletion)
.build();
CompletionSKFunction summarizeFunc = SKBuilders
.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(prompt)
.withFunctionName("summarize")
.withCompletionConfig(
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000))
.build();
kernel.registerSemanticFunction(summarizeFunc);
SKContext context = summarizeFunc.invokeAsync(text).block();
System.out.println(context.getResult());
}
}
@@ -1,284 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.time.Duration;
import reactor.core.publisher.Mono;
/**
* Demonstrates how the Kernel uses functions loaded from skills.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example09_FunctionTypes {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
TextCompletion textCompletion = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
System.out.println("======== Native function types ========");
// Load native skill into the kernel skill collection, sharing its functions with prompt templates
var test = kernel
.importSkill(new LocalExampleSkill(), "test");
kernel.importSkillsFromDirectory(SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill");
var fakeContext = SKBuilders.context()
.withSkills(kernel.getSkills())
.build();
// The kernel takes care of wiring the input appropriately
SKContext result = kernel.runAsync(
"",
test.getFunction("type01"),
test.getFunction("type02"),
test.getFunction("type03"),
test.getFunction("type04"),
test.getFunction("type05"),
test.getFunction("type06"),
test.getFunction("type07"),
test.getFunction("type08"),
test.getFunction("type09"),
test.getFunction("type10"),
test.getFunction("type11"),
test.getFunction("type12"),
test.getFunction("type13"),
test.getFunction("type14"),
test.getFunction("type15"),
test.getFunction("type16"),
test.getFunction("type17"),
test.getFunction("type18")
)
.block();
kernel.getFunction("test", "type01").invokeAsync().block();
test.getFunction("type01").invokeAsync().block();
kernel.getFunction("test", "type02").invokeAsync().block();
test.getFunction("type02").invokeAsync().block();
kernel.getFunction("test", "type03").invokeAsync().block();
test.getFunction("type03").invokeAsync().block();
kernel.getFunction("test", "type04").invokeAsync(fakeContext).block();
test.getFunction("type04").invokeAsync(fakeContext).block();
kernel.getFunction("test", "type05").invokeAsync(fakeContext).block();
test.getFunction("type05").invokeAsync(fakeContext).block();
kernel.getFunction("test", "type06").invokeAsync(fakeContext).block();
test.getFunction("type06").invokeAsync(fakeContext).block();
kernel.getFunction("test", "type07").invokeAsync(fakeContext).block();
test.getFunction("type07").invokeAsync(fakeContext).block();
kernel.getFunction("test", "type08").invokeAsync("").block();
test.getFunction("type08").invokeAsync("").block();
kernel.getFunction("test", "type09").invokeAsync("").block();
test.getFunction("type09").invokeAsync("").block();
kernel.getFunction("test", "type10").invokeAsync("").block();
test.getFunction("type10").invokeAsync("").block();
kernel.getFunction("test", "type11").invokeAsync("").block();
test.getFunction("type11").invokeAsync("").block();
kernel.getFunction("test", "type12").invokeAsync("").block();
test.getFunction("type12").invokeAsync("").block();
kernel.getFunction("test", "type13").invokeAsync("").block();
test.getFunction("type13").invokeAsync("").block();
kernel.getFunction("test", "type14").invokeAsync("").block();
test.getFunction("type14").invokeAsync("").block();
kernel.getFunction("test", "type15").invokeAsync("").block();
test.getFunction("type15").invokeAsync("").block();
kernel.getFunction("test", "type16").invokeAsync("").block();
test.getFunction("type16").invokeAsync("").block();
kernel.getFunction("test", "type17").invokeAsync("").block();
test.getFunction("type17").invokeAsync("").block();
kernel.getFunction("test", "type18").invokeAsync("").block();
test.getFunction("type18").invokeAsync("").block();
}
public static class LocalExampleSkill {
@DefineSKFunction(name = "type01")
public void Type01() {
System.out.println("Running function type 1");
}
@DefineSKFunction(name = "type02")
public String Type02() {
System.out.println("Running function type 2");
return "";
}
@DefineSKFunction(name = "type03")
public Mono<String> Type03Async() {
return Mono.delay(Duration.ZERO)
.map(x -> {
System.out.println("Running function type 3");
return "";
});
}
@DefineSKFunction(name = "type04")
public void Type04(SKContext context) {
System.out.println("Running function type 4");
}
@DefineSKFunction(name = "type05")
public String Type05(SKContext context) {
System.out.println("Running function type 5");
return "";
}
@DefineSKFunction(name = "type06")
public Mono<String> Type06Async(SKContext context) {
var summarizer = context.getSkills().getFunction("SummarizeSkill", "Summarize", null);
return summarizer
.invokeAsync("blah blah blah")
.map(summary -> {
System.out.println("Running function type 6 " + summary.getResult());
return "";
});
}
@DefineSKFunction(name = "type07")
public Mono<SKContext> Type07Async(SKContext context) {
return Mono.delay(Duration.ZERO)
.map(x -> {
System.out.println("Running function type 7");
return context;
});
}
@DefineSKFunction(name = "type08")
public void Type08(
@SKFunctionInputAttribute(description = "?")
String x) {
System.out.println("Running function type 8");
}
@DefineSKFunction(name = "type09")
public String Type09(
@SKFunctionInputAttribute(description = "?")
String x) {
System.out.println("Running function type 9");
return "";
}
@DefineSKFunction(name = "type10")
public Mono<String> Type10Async(
@SKFunctionInputAttribute(description = "?")
String x) {
return Mono.delay(Duration.ZERO)
.map(x2 -> {
System.out.println("Running function type 10");
return "";
});
}
@DefineSKFunction(name = "type11")
public void Type11(
@SKFunctionInputAttribute(description = "?")
String x,
SKContext context) {
System.out.println("Running function type 11");
}
@DefineSKFunction(name = "type12")
public String Type12(
@SKFunctionInputAttribute(description = "?")
String x,
SKContext context) {
System.out.println("Running function type 12");
return "";
}
@DefineSKFunction(name = "type13")
public Mono<String> Type13Async(
@SKFunctionInputAttribute(description = "?")
String x, SKContext context) {
return Mono.delay(Duration.ZERO)
.map(x2 -> {
System.out.println("Running function type 13");
return "";
});
}
@DefineSKFunction(name = "type14")
public Mono<SKContext> Type14Async(
@SKFunctionInputAttribute(description = "?")
String x, SKContext context) {
return Mono.delay(Duration.ZERO)
.ignoreElement()
.map(x2 -> {
System.out.println("Running function type 14");
return context;
});
}
@DefineSKFunction(name = "type15")
public Mono<Void> Type15Async(String x) {
return Mono.delay(Duration.ZERO)
.ignoreElement()
.doFinally(ignore -> System.out.println("Running function type 15"))
.then();
}
@DefineSKFunction(name = "type16")
public Mono<Void> Type16Async(SKContext context) {
return Mono.delay(Duration.ZERO)
.ignoreElement()
.doFinally(ignore -> System.out.println("Running function type 16"))
.then();
}
@DefineSKFunction(name = "type17")
public Mono<Void> Type17Async(String x, SKContext context) {
return Mono.delay(Duration.ZERO)
.ignoreElement()
.doFinally(ignore -> System.out.println("Running function type 17"))
.then();
}
@DefineSKFunction(name = "type18")
public Mono<Void> Type18Async() {
return Mono.delay(Duration.ZERO)
.ignoreElement()
.doFinally(ignore -> System.out.println("Running function type 18"))
.then();
}
}
}
@@ -1,221 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.coreskills.TextSkill;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlannerRequestSettings;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Demonstrates the <a href=
* "https://devblogs.microsoft.com/semantic-kernel/semantic-kernel-planners-sequential-planner/">
* Sequential Planner</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example12_SequentialPlanner {
private static final Logger LOGGER = LoggerFactory.getLogger(Example12_SequentialPlanner.class);
public static void main(String[] args) throws ConfigurationException {
poetrySamplesAsync();
emailSamplesAsync();
bookSamplesAsync();
//MemorySampleAsync();
}
private static void poetrySamplesAsync() throws ConfigurationException {
System.out.println("======== Sequential Planner - Create and Execute Poetry Plan ========");
var kernel = initializeKernel();
kernel.importSkill(new TextSkill(), "TextSkill");
var planner = new SequentialPlanner(kernel, null, null);
var plan = planner.createPlanAsync("Write a poem about John Doe, then translate it into Italian, then convert it to uppercase.").block();
// Original plan:
// Goal: Write a poem about John Doe, then translate it into Italian.
// Steps:
// - WriterSkill.ShortPoem INPUT='John Doe is a friendly guy who likes to help others and enjoys reading books.' =>
// - WriterSkill.Translate language='Italian' INPUT='' =>
SKContext result = plan.invokeAsync().block();
System.out.println("Result:");
System.out.println(result.getResult());
}
public static class EmailSkill {
@DefineSKFunction(name = "SendEmail", description = "Given an e-mail and message body, send an email")
public void sendEmail(
@SKFunctionInputAttribute(description = "The body of the email message to send.")
String input,
@SKFunctionParameters(description = "The email address to send email to.", name = "email_address")
String emailAddress
) {
LOGGER.info("Emailing to " + emailAddress + "\n" + input);
}
@DefineSKFunction(name = "GetEmailAddressAsync", description = "Lookup an email address for a person given a name")
public String getEmailAddressAsync(
@SKFunctionInputAttribute(description = "The name of the person to email.")
String input) {
return "[email protected]";
}
}
private static void emailSamplesAsync() throws ConfigurationException {
System.out.println("======== Sequential Planner - Create and Execute Email Plan ========");
var kernel = initializeKernel();
kernel.importSkill(new EmailSkill(), "email");
SequentialPlanner planner = initPlanner(kernel, 1024);
var plan = planner.createPlanAsync("Summarize an input, translate to french, and e-mail to John Doe").block();
// Original plan:
// Goal: Summarize an input, translate to french, and e-mail to John Doe
// Steps:
// - SummarizeSkill.Summarize INPUT='' =>
// - WriterSkill.Translate language='French' INPUT='' => TRANSLATED_SUMMARY
// - email.GetEmailAddress INPUT='John Doe' => EMAIL_ADDRESS
// - email.SendEmail INPUT='$TRANSLATED_SUMMARY' email_address='$EMAIL_ADDRESS' =>
System.out.println("Original plan:");
System.out.println(plan.toManualString(false));
var input =
"Once upon a time, in a faraway kingdom, there lived a kind and just king named Arjun. " +
"He ruled over his kingdom with fairness and compassion, earning him the love and admiration of his people. " +
"However, the kingdom was plagued by a terrible dragon that lived in the nearby mountains and terrorized the nearby villages, " +
"burning their crops and homes. The king had tried everything to defeat the dragon, but to no avail. " +
"One day, a young woman named Mira approached the king and offered to help defeat the dragon. She was a skilled archer " +
"and claimed that she had a plan to defeat the dragon once and for all. The king was skeptical, but desperate for a solution, " +
"so he agreed to let her try. Mira set out for the dragon's lair and, with the help of her trusty bow and arrow, " +
"she was able to strike the dragon with a single shot through its heart, killing it instantly. The people rejoiced " +
"and the kingdom was at peace once again. The king was so grateful to Mira that he asked her to marry him and she agreed. " +
"They ruled the kingdom together, ruling with fairness and compassion, just as Arjun had done before. They lived " +
"happily ever after, with the people of the kingdom remembering Mira as the brave young woman who saved them from the dragon.";
plan.invokeAsync(input).blockOptional();
}
private static void bookSamplesAsync() throws ConfigurationException {
System.out.println("======== Sequential Planner - Create and Execute Book Creation Plan ========");
var kernel = initializeKernel();
SequentialPlanner planner = initPlanner(kernel, 1024);
var plan = planner.createPlanAsync("Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'").block();
// Original plan:
// Goal: Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'
// Steps:
// - WriterSkill.NovelOutline chapterCount='3' INPUT='A group of kids in a club called 'The Thinking Caps' that solve mysteries and puzzles using their creativity and logic.' endMarker='<!--===ENDPART===-->' => OUTLINE
// - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='0' => CHAPTER_1_SYNOPSIS
// - WriterSkill.NovelChapter chapterIndex='1' previousChapter='' INPUT='$CHAPTER_1_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_1
// - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='1' => CHAPTER_2_SYNOPSIS
// - WriterSkill.NovelChapter chapterIndex='2' previousChapter='$CHAPTER_1_SYNOPSIS' INPUT='$CHAPTER_2_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_2
// - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='2' => CHAPTER_3_SYNOPSIS
// - WriterSkill.NovelChapter chapterIndex='3' previousChapter='$CHAPTER_2_SYNOPSIS' INPUT='$CHAPTER_3_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_3
System.out.println(plan.invokeAsync().block().getResult());
}
/*
TODO
private static void memorySampleAsync() throws IOException {
System.out.println("======== Sequential Planner - Create and Execute Plan using Memory ========");
var kernel = initializeKernel();
SequentialPlanner planner = initPlanner(kernel, 1024);
kernel.importSkillsFromDirectory("samples/skills",
"CalendarSkill",
"ChatSkill",
"ChildrensBookSkill",
"ClassificationSkill",
"CodingSkill",
"FunSkill",
"IntentDetectionSkill",
"MiscSkill",
"QASkill");
kernel.importSkill(new EmailSkill(), "email");
kernel.importSkill(new StaticTextSkill(), "statictext");
kernel.importSkill(new TextSkill(), "text");
kernel.importSkill(new Microsoft.SemanticKernel.CoreSkills.TextSkill(), "coretext");
var goal = "Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'";
var planner = new SequentialPlanner(kernel, new SequentialPlannerConfig {
RelevancyThreshold =0.78
});
var plan = await planner.CreatePlanAsync(goal);
System.out.println("Original plan:");
System.out.println(plan.ToPlanString());
}
*/
private static Kernel initializeKernel() throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
var kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo-instruct")
.build())
.withMemory(SKBuilders
.semanticTextMemory()
.withEmbeddingGenerator(
SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(client)
.withModelId("text-embedding-ada-002")
.build()
)
.withStorage(new VolatileMemoryStore())
.build())
.build();
// Load additional skills to enable planner to do non-trivial asks.
kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill");
kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill");
kernel.importSkillFromDirectory("MiscSkill", SampleSkillsUtil.detectSkillDirLocation(), "MiscSkill");
return kernel;
}
private static SequentialPlanner initPlanner(Kernel kernel, int maxTokens) {
return new SequentialPlanner(kernel, new SequentialPlannerRequestSettings(
null,
100,
Set.of(),
Set.of(),
Set.of(),
maxTokens,
false
), null);
}
}
@@ -1,196 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.coreskills.ConversationSummarySkill;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import reactor.core.publisher.Mono;
/**
* Demonstrate the {@code com.microsoft.semantickernel.coreskills.ConversationSummarySkill}
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example13_ConversationSummarySkill {
private static final String ChatTranscript =
"""
John: Hello, how are you?
Jane: I'm fine, thanks. How are you?
John: I'm doing well, writing some example code.
Jane: That's great! I'm writing some example code too.
John: What are you writing?
Jane: I'm writing a chatbot.
John: That's cool. I'm writing a chatbot too.
Jane: What language are you writing it in?
John: I'm writing it in C#.
Jane: I'm writing it in Python.
John: That's cool. I need to learn Python.
Jane: I need to learn C#.
John: Can I try out your chatbot?
Jane: Sure, here's the link.
John: Thanks!
Jane: You're welcome.
Jane: Look at this poem my chatbot wrote:
Jane: Roses are red
Jane: Violets are blue
Jane: I'm writing a chatbot
Jane: What about you?
John: That's cool. Let me see if mine will write a poem, too.
John: Here's a poem my chatbot wrote:
John: The singularity of the universe is a mystery.
John: The universe is a mystery.
John: The universe is a mystery.
John: The universe is a mystery.
John: Looks like I need to improve mine, oh well.
Jane: You might want to try using a different model.
Jane: I'm using the GPT-3 model.
John: I'm using the GPT-2 model. That makes sense.
John: Here is a new poem after updating the model.
John: The universe is a mystery.
John: The universe is a mystery.
John: The universe is a mystery.
John: Yikes, it's really stuck isn't it. Would you help me debug my code?
Jane: Sure, what's the problem?
John: I'm not sure. I think it's a bug in the code.
Jane: I'll take a look.
Jane: I think I found the problem.
Jane: It looks like you're not passing the right parameters to the model.
John: Thanks for the help!
Jane: I'm now writing a bot to summarize conversations. I want to make sure it works when the conversation is long.
John: So you need to keep talking with me to generate a long conversation?
Jane: Yes, that's right.
John: Ok, I'll keep talking. What should we talk about?
Jane: I don't know, what do you want to talk about?
John: I don't know, it's nice how CoPilot is doing most of the talking for us. But it definitely gets stuck sometimes.
Jane: I agree, it's nice that CoPilot is doing most of the talking for us.
Jane: But it definitely gets stuck sometimes.
John: Do you know how long it needs to be?
Jane: I think the max length is 1024 tokens. Which is approximately 1024*4= 4096 characters.
John: That's a lot of characters.
Jane: Yes, it is.
John: I'm not sure how much longer I can keep talking.
Jane: I think we're almost there. Let me check.
Jane: I have some bad news, we're only half way there.
John: Oh no, I'm not sure I can keep going. I'm getting tired.
Jane: I'm getting tired too.
John: Maybe there is a large piece of text we can use to generate a long conversation.
Jane: That's a good idea. Let me see if I can find one. Maybe Lorem Ipsum?
John: Yeah, that's a good idea.
Jane: I found a Lorem Ipsum generator.
Jane: Here's a 4096 character Lorem Ipsum text:
Jane: Lorem ipsum dolor sit amet, con
Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc sit amet aliquam
Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc sit amet aliquam
Jane: Darn, it's just repeating stuf now.
John: I think we're done.
Jane: We're not though! We need like 1500 more characters.
John: Oh Cananda, our home and native land.
Jane: True patriot love in all thy sons command.
John: With glowing hearts we see thee rise.
Jane: The True North strong and free.
John: From far and wide, O Canada, we stand on guard for thee.
Jane: God keep our land glorious and free.
John: O Canada, we stand on guard for thee.
Jane: O Canada, we stand on guard for thee.
Jane: That was fun, thank you. Let me check now.
Jane: I think we need about 600 more characters.
John: Oh say can you see?
Jane: By the dawn's early light.
John: What so proudly we hailed.
Jane: At the twilight's last gleaming.
John: Whose broad stripes and bright stars.
Jane: Through the perilous fight.
John: O'er the ramparts we watched.
Jane: Were so gallantly streaming.
John: And the rockets' red glare.
Jane: The bombs bursting in air.
John: Gave proof through the night.
Jane: That our flag was still there.
John: Oh say does that star-spangled banner yet wave.
Jane: O'er the land of the free.
John: And the home of the brave.
Jane: Are you a Seattle Kraken Fan?
John: Yes, I am. I love going to the games.
Jane: I'm a Seattle Kraken Fan too. Who is your favorite player?
John: I like watching all the players, but I think my favorite is Matty Beniers.
Jane: Yeah, he's a great player. I like watching him too. I also like watching Jaden Schwartz.
John: Adam Larsson is another good one. The big cat!
Jane: WE MADE IT! It's long enough. Thank you!
John: Can you automate generating long text next time?
Jane: I will.
John: You're welcome. I'm glad we could help. Goodbye!
Jane: Goodbye!
""".stripIndent();
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
conversationSummarySkillAsync(client);
getConversationActionItemsAsync(client);
getConversationTopicsAsync(client);
}
private static void conversationSummarySkillAsync(OpenAIAsyncClient client) {
System.out.println("======== SampleSkills - Conversation Summary Skill - Summarize ========");
Kernel kernel = initializeKernel(client);
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
Mono<SKContext> summary = conversationSummarySkill
.getFunction("SummarizeConversation", SKFunction.class)
.invokeAsync(ChatTranscript);
System.out.println("Generated Summary (This may take some time):");
System.out.println(summary.block().getResult());
}
private static void getConversationActionItemsAsync(OpenAIAsyncClient client) {
System.out.println("======== SampleSkills - Conversation Summary Skill - Action Items ========");
Kernel kernel = initializeKernel(client);
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
Mono<SKContext> summary = conversationSummarySkill
.getFunction("GetConversationActionItems", SKFunction.class)
.invokeAsync(ChatTranscript);
System.out.println("Generated Action Items (This may take some time):");
System.out.println(summary.block().getResult());
}
private static void getConversationTopicsAsync(OpenAIAsyncClient client) {
Kernel kernel = initializeKernel(client);
ReadOnlyFunctionCollection conversationSummarySkill =
kernel.importSkill(new ConversationSummarySkill(kernel), null);
Mono<SKContext> summary = conversationSummarySkill
.getFunction("GetConversationTopics", SKFunction.class)
.invokeAsync(ChatTranscript);
System.out.println("Generated Topics:");
System.out.println(summary.block().getResult());
}
private static Kernel initializeKernel(OpenAIAsyncClient client) {
TextCompletion textCompletion = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
return SKBuilders.kernel()
.withAIService("text-davinci-003", textCompletion, true, TextCompletion.class).build();
}
}
@@ -1,213 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.core.credential.TokenCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.connectors.ai.openai.util.AzureCredentialType;
import com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryStore;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import com.microsoft.semantickernel.settings.SettingsMap;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Demonstrate two examples about SK Semantic Memory:
*
* 1. Memory using Azure Cognitive Search.
* 2. Memory using a custom embedding generator and vector engine.
*
* Semantic Memory allows to store your data like traditional DBs,
* adding the ability to query it using natural language.
* <p>
* You must <a href=
* "https://learn.microsoft.com/en-us/azure/search/search-create-service-portal">
* create an Azure Cognitive Search service in the portal</a> to run this example.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example14_SemanticMemory {
private static final String MEMORY_COLLECTION_NAME = "SKGitHub";
public static void main(String[] args) throws Exception {
System.out.println("==============================================================");
System.out.println("======== Semantic Memory using Azure Cognitive Search ========");
System.out.println("==============================================================");
var openAIAsyncClient = SamplesConfig.getClient();
AzureCognitiveSearchMemoryStore memoryStore = buildAzureCognitiveSearchMemoryStore();
/* This example leverages Azure Cognitive Search to provide SK with Semantic Memory.
*
* Azure Cognitive Search automatically indexes your data semantically, so you don't
* need to worry about embedding generation.
*/
var kernelWithACS = SKBuilders.kernel()
.withMemoryStorage(memoryStore)
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.build();
runExampleAsync(kernelWithACS).block();
System.out.println("====================================================");
System.out.println("======== Semantic Memory (volatile, in RAM) ========");
System.out.println("====================================================");
/* You can build your own semantic memory combining an Embedding Generator
* with a Memory storage that supports search by similarity (ie semantic search).
*
* In this example we use a volatile memory, a local simulation of a vector DB.
*
* You can replace VolatileMemoryStore with Qdrant (see QdrantMemoryStore connector)
* or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc.
*/
var kernelWithCustomDb = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.withMemoryStorage(new VolatileMemoryStore.Builder().build())
.build();
runExampleAsync(kernelWithCustomDb).block();
}
private static AzureCognitiveSearchMemoryStore buildAzureCognitiveSearchMemoryStore()
throws ConfigurationException {
Map<String, String> settings = SettingsMap.getDefault();
AzureCognitiveSearchMemoryStore memoryStore;
if (settings.get("cognativesearch.token") == null) {
// Attempt to obtain token via
TokenCredential token = AzureCredentialType.getCredential();
if (token == null) {
throw new IllegalStateException(
"Unable to obtain token credentials. Please provide a key for Azure Cognitive Search, or log in to az.");
}
memoryStore = new AzureCognitiveSearchMemoryStore(
settings.get("cognativesearch.endpoint"),
token
);
} else {
memoryStore = new AzureCognitiveSearchMemoryStore(
settings.get("cognativesearch.endpoint"),
settings.get("cognativesearch.token")
);
}
return memoryStore;
}
public static Mono<Void> runExampleAsync(Kernel kernel) {
return storeMemoryAsync(kernel)
.then(searchMemoryAsync(kernel, "How do I get started?"))
/*
Output:
Query: How do I get started?
Result 1:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md
Title : README: Installation, getting started, and how to contribute
Result 2:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet-jupyter-notebooks/00-getting-started.ipynb
Title : Jupyter notebook describing how to get started with the Semantic Kernel
*/
.then(searchMemoryAsync(kernel, "Can I build a chat with SK?"));
/*
Output:
Query: Can I build a chat with SK?
Result 1:
URL: : https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT
Title : Sample demonstrating how to create a chat skill interfacing with ChatGPT
Result 2:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md
Title : README: README associated with a sample chat summary react-based webapp
*/
}
private static Mono<Void> searchMemoryAsync(Kernel kernel, String query) {
return kernel.getMemory().searchAsync(MEMORY_COLLECTION_NAME, query, 2, 0.5f, false)
.mapNotNull(memories -> {
System.out.println("\nQuery: " + query + "\n");
for (int n = 0; n < memories.size(); n++) {
var memory = memories.get(n);
System.out.println("Result " + (n + 1) + ":");
System.out.println(" URL: : " + memory.getMetadata().getId());
System.out.println(" Title : " + memory.getMetadata().getDescription());
System.out.println();
}
System.out.println("----------------------");
return null;
});
}
private static Mono<Void> storeMemoryAsync(Kernel kernel) {
/* Store some data in the semantic memory.
*
* When using Azure Cognitive Search the data is automatically indexed on write.
*
* When using the combination of VolatileStore and Embedding generation, SK takes
* care of creating and storing the index
*/
return Flux.fromIterable(sampleData().entrySet())
.doFirst(() -> System.out.println(
"\nAdding some GitHub file URLs and their descriptions to the semantic memory."))
.map(entry -> {
System.out.println("Save '" + entry.getKey() + "' to memory.");
return kernel.getMemory().saveReferenceAsync(
MEMORY_COLLECTION_NAME,
entry.getValue(),
entry.getKey(),
"GitHub",
entry.getValue(),
null);
}
)
.mapNotNull(Mono::block)
.doFinally(signalType -> System.out.println("\n----------------------"))
.then();
}
private static Map<String, String> sampleData() {
return Arrays.stream(new String[][]{
{"https://github.com/microsoft/semantic-kernel/blob/main/README.md",
"README: Installation, getting started, and how to contribute"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb",
"Jupyter notebook describing how to pass prompts from a file to a semantic skill or function"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb",
"Jupyter notebook describing how to get started with the Semantic Kernel"},
{"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT",
"Sample demonstrating how to create a chat skill interfacing with ChatGPT"},
{"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs",
"C# class that defines a volatile embedding store"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md",
"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md",
"README: README associated with a sample chat summary react-based webapp"},
}).collect(Collectors.toMap(element -> element[0], element -> element[1]));
}
}
@@ -1,229 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration;
import com.microsoft.semantickernel.coreskills.TextMemorySkill;
import com.microsoft.semantickernel.memory.MemoryStore;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.util.List;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;
/**
* Demonstrates saving and retrieving memories.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example15_MemorySkill {
private static final String MEMORY_COLLECTION_NAME = "aboutMe";
public static void main(String[] args) {
runAsync().block();
}
public static Mono<Void> runAsync() {
// ========= Create a kernel =========
OpenAIAsyncClient client = null;
try {
client = SamplesConfig.getClient();
} catch (Exception e) {
return Mono.error(e);
}
TextCompletion textCompletionService =
SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build();
TextEmbeddingGeneration textEmbeddingGenerationService =
SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(client)
.withModelId("text-embedding-ada-002")
.build();
MemoryStore memoryStore = new VolatileMemoryStore.Builder().build();
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(textCompletionService)
.withDefaultAIService(textEmbeddingGenerationService)
.withMemoryStorage(memoryStore)
.build();
// ========= Store memories using the kernel =========
kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "My name is Andrea", "info1", null, null).block();
kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I work as a tourist operator", "info2", null, null).block();
kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I've been living in Seattle since 2005", "info3", null, null).block();
kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I visited France and Italy five times since 2015", "info4", null, null).block();
// ========= Store memories using semantic function =========
// Add Memory as a skill for other functions
TextMemorySkill memorySkill = new TextMemorySkill();
kernel.importSkill(memorySkill, "memory");
// Build a semantic function that saves info to memory
PromptTemplateConfig.CompletionConfig completionConfig = SKBuilders.completionConfig()
.temperature(0.2)
.topP(0.5)
.presencePenalty(0)
.frequencyPenalty(0)
.maxTokens(2000)
.build();
CompletionSKFunction saveFunctionDefinition = SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate("{{memory.save $info}}")
.withFunctionName("save")
.withDescription("save information to memory")
.withCompletionConfig(completionConfig)
.build();
CompletionSKFunction memorySaver =
kernel.registerSemanticFunction(saveFunctionDefinition);
SKContext context = SKBuilders.context()
.withMemory(kernel.getMemory())
.withSkills(kernel.getSkills())
.build();
context.setVariable(TextMemorySkill.COLLECTION_PARAM, MEMORY_COLLECTION_NAME)
.setVariable(TextMemorySkill.KEY_PARAM, "info5")
.setVariable(TextMemorySkill.INFO_PARAM, "My family is from New York");
memorySaver.invokeAsync(context).block();
// ========= Test memory remember =========
System.out.println("========= Example: Recalling a Memory =========");
// create a new context to avoid using the variables from the previous example
context = SKBuilders.context()
.withMemory(kernel.getMemory())
.withSkills(kernel.getSkills())
.build();
String answer = memorySkill.retrieveAsync(MEMORY_COLLECTION_NAME, "info1", context).block();
System.out.printf("Memory associated with 'info1': %s%n", answer);
/*
Output:
"Memory associated with 'info1': My name is Andrea
*/
// ========= Test memory recall =========
System.out.println("========= Example: Recalling an Idea =========");
List<String> answers = memorySkill.recallAsync(
"Where did I grow up?",
MEMORY_COLLECTION_NAME,
0,
2,
context).block();
System.out.println("Ask: Where did I grow up?");
System.out.printf("Answer:%n\t%s%n", answers.stream().collect(Collectors.joining("\",\"", "[\"", "\"]")));
answers = memorySkill.recallAsync(
"Where do I live?",
MEMORY_COLLECTION_NAME,
0,
2,
context).block();
System.out.println("Ask: Where do I live?");
System.out.printf("Answer:%n\t%s%n", answers.stream().collect(Collectors.joining("\",\"", "[\"", "\"]")));
/*
Output:
Ask: where did I grow up?
Answer:
["My family is from New York","I've been living in Seattle since 2005"]
Ask: where do I live?
Answer:
["I've been living in Seattle since 2005","My family is from New York"]
*/
// ========= Use memory in a semantic function =========
System.out.println("========= Example: Using Recall in a Semantic Function =========");
// Build a semantic function that uses memory to find facts
String prompt =
"Consider only the facts below when answering questions.\n" +
"About me: {{memory.recall 'where did I grow up?'}}\n" +
"About me: {{memory.recall 'where do I live?'}}\n" +
"Question: {{$input}}\n" +
"Answer: ";
CompletionSKFunction recallFunctionDefinition = SKBuilders.completionFunctions()
.withKernel(kernel)
.withPromptTemplate(prompt)
.withCompletionConfig(completionConfig)
.build();
SKFunction<?> aboutMeOracle = kernel.registerSemanticFunction(recallFunctionDefinition);
context.setVariable(TextMemorySkill.COLLECTION_PARAM, MEMORY_COLLECTION_NAME)
.setVariable(TextMemorySkill.RELEVANCE_PARAM, "0.75");
SKContext result = aboutMeOracle.invokeAsync("Do I live in the same town where I grew up?", context, null).block();
System.out.println("Do I live in the same town where I grew up?\n");
System.out.println(result.getResult());
/*
Output:
Do I live in the same town where I grew up?
No, I do not live in the same town where I grew up since my family is from New York and I have been living in Seattle since 2005.
*/
// ========= Remove a memory =========
System.out.println("========= Example: Forgetting a Memory =========");
context.setVariable("fact1", "What is my name?")
.setVariable("fact2", "What do I do for a living?")
.setVariable(TextMemorySkill.RELEVANCE_PARAM, "0.75");
result = aboutMeOracle.invokeAsync("Tell me a bit about myself", context, null).block();
System.out.println("Tell me a bit about myself\n");
System.out.println(result.getResult());
/*
Approximate Output:
Tell me a bit about myself
My name is Andrea and my family is from New York. I work as a tourist operator.
*/
memorySkill.removeAsync(MEMORY_COLLECTION_NAME, "info1", context).block();
result = aboutMeOracle.invokeAsync("Tell me a bit about myself", context, null).block();
System.out.println("Tell me a bit about myself\n");
System.out.println(result.getResult());
/*
Approximate Output:
Tell me a bit about myself
I'm from a family originally from New York and I work as a tourist operator. I've been living in Seattle since 2005.
*/
return Mono.empty();
}
}
@@ -1,67 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatHistory;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
/**
* Demonstrates the use of Semantic Kernel with OpenAI ChatGPT API
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example17_ChatGPT {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
Kernel kernel = SKBuilders.kernel()
.withAIService(
"gpt-35-turbo",
SKBuilders.chatCompletion()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo")
.build(),
true,
ChatCompletion.class
)
.build();
ChatCompletion<OpenAIChatHistory> chatGPT = kernel.getService(null, ChatCompletion.class);
OpenAIChatHistory chatHistory = chatGPT.createNewChat("You are a librarian, expert about books");
// First user message
chatHistory.addUserMessage("Hi, I'm looking for book suggestions");
messageOutputAsync(chatHistory);
// First bot assistant message
String reply = chatGPT.generateMessageAsync(chatHistory, null).block();
chatHistory.addAssistantMessage(reply);
messageOutputAsync(chatHistory);
// Second user message
chatHistory.addUserMessage(
"I love history and philosophy, I'd like to learn something new about Greece, any suggestion?");
messageOutputAsync(chatHistory);
// Second bot assistant message
reply = chatGPT.generateMessageAsync(chatHistory, null).block();
chatHistory.addAssistantMessage(reply);
messageOutputAsync(chatHistory);
}
private static void messageOutputAsync(ChatHistory chatHistory) {
ChatHistory.Message message = chatHistory.getMessages().get(chatHistory.getMessages().size() - 1);
System.out.println(message.getAuthorRoles() + ": " + message.getContent());
System.out.println("------------------------");
}
}
@@ -1,286 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.semantickernel.ai.embeddings.Embedding;
import com.microsoft.semantickernel.memory.MemoryRecord;
import com.microsoft.semantickernel.memory.MemoryStore;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
/**
* Demonstrates a custom implementation of {@code MemoryStore} that is read only.
* In this sample, the data is stored in a JSON String and deserialized into an
* {@code MemoryRecord[]}. For this specific sample, the implementation
* of {@code MemoryStore} has a single collection, and thus does not need to be named.
* It also assumes that the JSON formatted data can be deserialized into {@code MemoryRecord} objects.
* @see MemoryRecord
* @see MemoryStore
*/
public class Example25_ReadOnlyMemoryStore
{
public static void main(String[] args) {
RunAsync().block();
}
public static Mono<Void> RunAsync()
{
var store = new ReadOnlyMemoryStore(JSON_VECTOR_ENTRIES);
var embedding = new Embedding(Arrays.asList(22f, 4f, 6f));
System.out.println("Reading data from custom read-only memory store");
Mono<?> mono = store.getAsync("collection", "key3", true)
.mapNotNull(memoryRecord -> {
String memoryRecordId = memoryRecord.getMetadata().getId();
Embedding memoryRecordEmbedding = memoryRecord.getEmbedding();
System.out.printf("ID = %s, Embedding = %s%n", memoryRecordId, embeddingVectorToString(memoryRecordEmbedding));
return memoryRecord;
});
mono = mono.then(
store.getNearestMatchAsync("collection", embedding, 0f, true)
.mapNotNull(result -> {
Float similarity = result.getT2().floatValue();
MemoryRecord memoryRecord = result.getT1();
Embedding memoryRecordEmbedding = memoryRecord.getEmbedding();
System.out.printf("Embedding = %s, Similarity = %f%n", embeddingVectorToString(memoryRecordEmbedding), similarity);
return result;
}
)
);
return mono.then();
}
private static String embeddingVectorToString(Embedding embedding) {
StringJoiner stringJoiner = new StringJoiner(", ", "[", "]");
embedding.getVector().stream().map(Number::toString).forEach(stringJoiner::add);
return stringJoiner.toString();
}
private static class ReadOnlyMemoryStore implements MemoryStore
{
private final MemoryRecord[] _memoryRecords;
private final int _vectorSize = 3;
public ReadOnlyMemoryStore(String valueString)
{
try {
_memoryRecords = new ObjectMapper().readValue(valueString, MemoryRecord[].class);
} catch (JsonProcessingException e) {
throw new RuntimeException("Unable to deserialize memory records");
}
}
@Override
public Mono<Void> createCollectionAsync(String collectionName)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<Void> deleteCollectionAsync(String collectionName)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<Boolean> doesCollectionExistAsync(String collectionName)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<MemoryRecord> getAsync(String collectionName, String key, boolean withEmbedding)
{
// Note: with this simple implementation, the MemoryRecord will always contain the embedding.
return Mono.justOrEmpty(
Arrays.stream(this._memoryRecords)
.filter(it -> it.getKey().equals(key))
.findFirst()
);
}
@Override
public Mono<Collection<MemoryRecord>> getBatchAsync(String collectionName, Collection<String> keys, boolean withEmbeddings)
{
// Note: with this simple implementation, the MemoryRecord will always contain the embedding.
return Mono.just(
Arrays.stream(this._memoryRecords)
.filter(it -> keys.contains(it.getKey()))
.collect(Collectors.toList())
);
}
@Override
public Mono<List<String>> getCollectionsAsync()
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<Tuple2<MemoryRecord, Float>> getNearestMatchAsync(String collectionName, Embedding embedding, float minRelevanceScore,
boolean withEmbedding)
{
// Note: with this simple implementation, the MemoryRecord will always contain the embedding.
return Mono.justOrEmpty(
Arrays.stream(this._memoryRecords)
.map(it -> {
Embedding memoryRecordEmbedding =
it.getEmbedding();
float cosineSimilarity = -1f;
try {
cosineSimilarity = embedding.cosineSimilarity(memoryRecordEmbedding);
} catch (IllegalArgumentException e) {
// Vectors cannot have zero norm
}
return Tuples.of(it, cosineSimilarity);
})
.filter(it -> it.getT2() >= minRelevanceScore)
.max(Comparator.comparing(Tuple2::getT2, Float::compare))
);
}
@Override
public Mono<Collection<Tuple2<MemoryRecord, Float>>> getNearestMatchesAsync(String collectionName, Embedding embedding, int limit,
float minRelevanceScore, boolean withEmbeddings)
{
// Note: with this simple implementation, the MemoryRecord will always contain the embedding.
return Mono.justOrEmpty(
Arrays.stream(this._memoryRecords)
.map(it -> {
Embedding memoryRecordEmbedding =
it.getEmbedding();
float cosineSimilarity = -1f;
try {
cosineSimilarity = embedding.cosineSimilarity(memoryRecordEmbedding);
} catch (IllegalArgumentException e) {
// Vectors cannot have zero norm
}
return Tuples.of(it, cosineSimilarity);
})
.filter(it -> it.getT2() >= (float)minRelevanceScore)
// sort by similarity score, descending
.sorted(Comparator.comparing(Tuple2::getT2, (a,b) -> Float.compare(b, a)))
.limit(limit)
.collect(Collectors.toList())
);
}
@Override
public Mono<Void> removeAsync(String collectionName, String key)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<Void> removeBatchAsync(String collectionName, Collection<String> keys)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<String> upsertAsync(String collectionName, MemoryRecord record)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
@Override
public Mono<Collection<String>> upsertBatchAsync(String collectionName, Collection<MemoryRecord> records)
{
return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store"));
}
}
private static final String JSON_VECTOR_ENTRIES = """
[
{
"embedding": {
"vector": [0, 0, 0 ]
},
"metadata": {
"is_reference": false,
"external_source_name": "externalSourceName",
"id": "Id1",
"description": "description",
"text": "text",
"additional_metadata" : "value:"
},
"key": "key1",
"timestamp": null
},
{
"embedding": {
"vector": [0, 0, 10 ]
},
"metadata": {
"is_reference": false,
"external_source_name": "externalSourceName",
"id": "Id2",
"description": "description",
"text": "text",
"additional_metadata" : "value:"
},
"key": "key2",
"timestamp": null
},
{
"embedding": {
"vector": [1, 2, 3 ]
},
"metadata": {
"is_reference": false,
"external_source_name": "externalSourceName",
"id": "Id3",
"description": "description",
"text": "text",
"additional_metadata" : "value:"
},
"key": "key3",
"timestamp": null
},
{
"embedding": {
"vector": [-1, -2, -3 ]
},
"metadata": {
"is_reference": false,
"external_source_name": "externalSourceName",
"id": "Id4",
"description": "description",
"text": "text",
"additional_metadata" : "value:"
},
"key": "key4",
"timestamp": null
},
{
"embedding": {
"vector": [12, 8, 4 ]
},
"metadata": {
"is_reference": false,
"external_source_name": "externalSourceName",
"id": "Id5",
"description": "description",
"text": "text",
"additional_metadata" : "value:"
},
"key": "key5",
"timestamp": null
}
]
""".replaceAll(" |\\n", "");
}
@@ -1,66 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.coreskills.TextSkill;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.planner.actionplanner.ActionPlanner;
/**
* Demonstrates the <a href=
* "https://devblogs.microsoft.com/semantic-kernel/semantic-kernel-planners-actionplanner/">
* Action Planner</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example28_ActionPlanner {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
System.out.println("======== Action Planner ========");
var kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build())
.build();
kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill");
kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill");
kernel.importSkill(new TextSkill(), "TextSkill");
// Create an instance of ActionPlanner.
// The ActionPlanner takes one goal and returns a single function to execute.
var planner = new ActionPlanner(kernel, null);
// We're going to ask the planner to find a function to achieve this goal.
var goal = "Write a poem about Cleopatra.";
// The planner returns a plan, consisting of a single function
// to execute and achieve the goal requested.
var plan = planner.createPlanAsync(goal).block();
// Show the result, which should match the given goal
System.out.println(plan.getName());
System.out.println(plan.invokeAsync(goal).block().getResult());
/* Output:
*
* Cleopatra was a queen
* But she didn't act like one
* She was more like a teen
* She was always on the scene
* And she loved to be seen
* But she didn't have a queenly bone in her body
*/
}
}
@@ -1,86 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.microsoft.semantickernel.GPT3Tokenizer;
/**
* Demonstrates how to count tokens using GPT tokenizer. The number of tokens affects
* API calls cost and each model has a maximum amount of tokens it can process and generate.
* This example is specific to OpenAI models, which use the tokenization described here:
* <a href="https://platform.openai.com/tokenizer">OpenAI tokenizer</a>
* If you use Semantic Kernel with other models, the tokenization logic is most probably different,
* and you should not use the GPT tokenizer.
*/
public class Example29_Tokenizer {
public static void main(String[] args) {
// Example 1
String sentence = "Some text on one line";
int tokenCount = GPT3Tokenizer.encode(sentence).size();
System.out.println("---");
System.out.println(sentence);
System.out.println("Tokens: " + tokenCount);
System.out.println("---\n\n");
// Example 2
sentence = "⭐⭐";
tokenCount = GPT3Tokenizer.encode(sentence).size();
System.out.println("The following example contains emojis which require several tokens.");
System.out.println("---");
System.out.println(sentence);
System.out.println("Tokens: " + tokenCount);
System.out.println("---\n\n");
// Example 3
sentence = "Some text on\ntwo lines";
tokenCount = GPT3Tokenizer.encode(sentence).size();
System.out.println("The following example uses Unix '\\n' line separator.");
System.out.println("---");
System.out.println(sentence);
System.out.println("Tokens: " + tokenCount);
System.out.println("---\n\n");
// Example 4
sentence = "Some text on\r\ntwo lines";
tokenCount = GPT3Tokenizer.encode(sentence).size();
System.out.println("The following example uses Windows '\\r\\n' line separator.");
System.out.println("---");
System.out.println(sentence);
System.out.println("Tokens: " + tokenCount);
System.out.println("---\n\n");
/*
Output:
---
Some text on one line
Tokens: 5
---
The following example contains emojis which require several tokens.
---
⭐⭐
Tokens: 6
---
The following example uses Unix '\n' line separator.
---
Some text on
two lines
Tokens: 6
---
The following example uses Windows '\r\n' line separator.
---
Some text on
two lines
Tokens: 7
---
*/
}
}
@@ -1,78 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import static com.microsoft.semantickernel.chatcompletion.ChatHistory.AuthorRoles.Assistant;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import java.util.function.BiFunction;
import reactor.core.publisher.Mono;
/**
* Demonstrates how to use Semantic Kernel with Text Completion as streaming
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example33_StreamingChat {
public static void main(String[] args) throws ConfigurationException {
StartStreamingChatAsync();
}
private static void StartStreamingChatAsync() throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
ChatCompletion chatCompletion = SKBuilders.chatCompletion()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo")
.build();
System.out.println("Chat content:");
System.out.println("------------------------");
var chatHistory = chatCompletion.createNewChat("You are a librarian, expert about books");
messageOutput(chatHistory);
// First user message
chatHistory.addMessage(ChatHistory.AuthorRoles.User, "Hi, I'm looking for book suggestions");
messageOutput(chatHistory);
// First bot assistant message
streamMessageOutputAsync(chatCompletion, chatHistory, Assistant);
// Second user message
chatHistory.addMessage(ChatHistory.AuthorRoles.User, "I love history and philosophy, I'd like to learn something new about Greece, any suggestion?");
messageOutput(chatHistory);
// Second bot assistant message
streamMessageOutputAsync(chatCompletion, chatHistory, Assistant);
}
private static void streamMessageOutputAsync(ChatCompletion chatGPT, ChatHistory chatHistory, ChatHistory.AuthorRoles authorRole) {
System.out.println(authorRole.name() + ": ");
BiFunction<String, String, String> agg = (o, o2) -> o + o2;
Mono<String> mono = chatGPT
.generateMessageStream(chatHistory, null)
.reduce("", agg);
String fullMessage = mono.block();
System.out.println(fullMessage);
System.out.println("\n------------------------");
chatHistory.addMessage(authorRole, fullMessage);
}
private static void messageOutput(ChatHistory chatHistory) {
var message = chatHistory.getMessages().get(chatHistory.getMessages().size() - 1);
System.out.println(message.getAuthorRoles().name() + " " + message.getContent());
System.out.println("------------------------");
}
}
@@ -1,132 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.coreskills.TimeSkill;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.planner.stepwiseplanner.DefaultStepwisePlanner;
import com.microsoft.semantickernel.planner.stepwiseplanner.StepwisePlanner;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import java.util.Locale;
import reactor.core.publisher.Mono;
/**
* Demonstrates the <a href=
* "https://devblogs.microsoft.com/semantic-kernel/semantic-kernel-planners-stepwise-planner/">
* Stepwise Planner</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class Example51_StepwisePlanner {
// Fake a search engine skill so that users do not need to have a search engine API key to run this example
public static class WebSearchEngineSkill {
@DefineSKFunction(description = "Perform a web search.", name = "search")
public Mono<String> search(
@SKFunctionParameters(description = "Text to search for", name = "query")
String input,
@SKFunctionParameters(description = "Number of results", name = "count", defaultValue = "1", type = Integer.class)
Integer count,
@SKFunctionParameters(description = "Number of results to skip", name = "offset", defaultValue = "0", type = Integer.class)
Integer offset) {
String question = input.toLowerCase(Locale.ROOT);
if (question.contains("year")) {
return Mono.just("1930");
}
throw new RuntimeException("Unable to find answer to question: " + input);
}
}
// Fake a calculator
public static class AdvancedCalculator {
@DefineSKFunction(description = "Useful for getting the result of a non-trivial math expression.", name = "Calculator")
public Mono<String> Calculator(
@SKFunctionParameters(description = "A valid mathematical expression that could be executed by a calculator capable of more advanced math functions like sin/cosine/floor.", name = "input")
String input) {
if ("1930/2".equals(input)) {
return Mono.just("965");
} else {
return Mono.error(new RuntimeException("Unknown calculation"));
}
}
}
public static void main(String[] args) throws ConfigurationException {
String[] questions = new String[]{
"What year is the first world cup divided by 2",
};
for (String question : questions) {
System.out.println("Result: " + runChatCompletion(question).block().getResult());
// Currently due to token limits, not supporting text completion
//System.out.println("Result: " + runTextCompletion(question).block().getResult());
}
}
private static Mono<SKContext> runTextCompletion(String question) throws ConfigurationException {
System.out.println("RunTextCompletion");
var kernel = getKernel(false);
return runWithQuestion(kernel, question);
}
private static Mono<SKContext> runChatCompletion(String question) throws ConfigurationException {
System.out.println("RunChatCompletion");
var kernel = getKernel(true);
return runWithQuestion(kernel, question);
}
private static Mono<SKContext> runWithQuestion(Kernel kernel, String question) {
var webSearchEngineSkill = new WebSearchEngineSkill();
kernel.importSkill(webSearchEngineSkill, "WebSearch");
kernel.importSkill(new AdvancedCalculator(), "AdvancedCalculator");
kernel.importSkill(new TimeSkill(), "time");
System.out.println("*****************************************************");
System.out.println("Question: " + question);
StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null, null);
var plan = planner.createPlan(question);
return plan.invokeAsync(SKBuilders.context().withKernel(kernel).build());
}
private static Kernel getKernel(boolean useChat) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
TextCompletion textCompletion;
if (useChat) {
textCompletion = SKBuilders.chatCompletion()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo")
.build();
} else {
textCompletion = SKBuilders.textCompletion()
.withOpenAIClient(client)
.withModelId("text-davinci-003")
.build();
}
return SKBuilders.kernel()
.withDefaultAIService(textCompletion)
.build();
}
}
@@ -1,48 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples;
import java.util.Arrays;
import java.util.List;
/**
* Run all the syntax examples.
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class RunAll {
public interface MainMethod {
void run(String[] args) throws Exception;
}
public static void main(String[] args) {
List<MainMethod> mains = Arrays.asList(
Example01_NativeFunctions::main,
Example02_Pipeline::main,
Example03_Variables::main,
Example04_CombineLLMPromptsAndNativeCode::main,
Example05_InlineFunctionDefinition::main,
Example06_TemplateLanguage::main,
Example08_RetryHandler::main,
Example09_FunctionTypes::main,
Example12_SequentialPlanner::main,
Example13_ConversationSummarySkill::main,
Example14_SemanticMemory::main,
Example15_MemorySkill::main,
Example17_ChatGPT::main,
Example25_ReadOnlyMemoryStore::main,
Example28_ActionPlanner::main,
Example29_Tokenizer::main,
Example33_StreamingChat::main,
Example51_StepwisePlanner::main
);
mains.forEach(mainMethod -> {
try {
mainMethod.run(args);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
@@ -1,30 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples;
import java.nio.file.Files;
import java.nio.file.Path;
public class SampleSkillsUtil {
public static final String SAMPLES_SKILLS_DIR = "samples/skills";
/**
* Detects the location of the sample skill directory by searching up til the top of the repository.
*/
public static String detectSkillDirLocation() {
Path dir = Path.of(System.getProperty("user.dir"));
do {
if (Files.isDirectory(dir.resolve(SAMPLES_SKILLS_DIR))) {
return dir.resolve(SAMPLES_SKILLS_DIR).toFile().getAbsolutePath();
}
if (Files.exists(dir.resolve(".gitignore"))) {
// We've reached the root of the repo
throw new RuntimeException("Could not find skill directory");
}
} while ((dir = dir.getParent()) != null);
throw new RuntimeException("Could not find skill directory");
}
}
@@ -1,40 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples.javaspecific;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.orchestration.SKFunction;
import java.io.IOException;
/**
* Import a skill from resources.
*/
public class Java_Example01_ResourceLoading {
public static void main(String[] args) throws IOException {
Kernel kernel = SKBuilders.kernel()
.build();
kernel.importSkillFromResources(
"Plugins",
"ExamplePlugins",
"ExampleFunction",
Java_Example01_ResourceLoading.class
);
SKFunction<?> function = kernel.getSkills().getFunctions("ExamplePlugins").getFunction("ExampleFunction");
System.out.println("Loaded function: " + function.getDescription());
kernel.importSkillFromResources(
"Plugins",
"ExamplePlugins",
"ExampleFunctionRoot"
);
function = kernel.getSkills().getFunctions("ExamplePlugins").getFunction("ExampleFunctionRoot");
System.out.println("Loaded function from classpath root: " + function.getDescription());
}
}
@@ -1,80 +0,0 @@
package com.microsoft.semantickernel.samples.syntaxexamples.javaspecific;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
/**
* Using Sequential Planner to take the input as a question and answer it finding any information needed.
* <p>
* See <a href=
* "https://devblogs.microsoft.com/semantic-kernel/semantic-kernel-planners-sequential-planner/">
* Semantic Kernel Planners: Sequential Planner</a>
* <p>
* Refer to the <a href=
* "https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md">
* README</a> for configuring your environment to run the examples.
*/
public class SequentialPlanner_AnswerQuestion {
public static class InformationFinder {
@DefineSKFunction(
name = "Search",
description = "Returns information relevant to answering a given query."
)
public String search(
@SKFunctionInputAttribute(description = "The query to answer.")
String query) {
return """
- The Eiffel Tower is in Paris.
- The Eiffel Tower is made of metal.
- The Eiffel Tower is 324 meters tall.
""".stripIndent();
}
}
public static void main(String[] args) throws IOException, ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
var kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build())
.build();
kernel.importSkillFromResources(
"Plugins",
"Answer",
"AnswerQuestion",
SequentialPlanner_AnswerQuestion.class
);
kernel.importSkill(new InformationFinder(), "InformationFinder");
String prompt;
try (InputStream altprompt = SequentialPlanner_AnswerQuestion.class.getResourceAsStream("require_context_variable_planner_prompt.txt")) {
prompt = new String(altprompt.readAllBytes(), StandardCharsets.UTF_8);
}
var planner = new SequentialPlanner(kernel, null, prompt);
var plan = planner.createPlanAsync("Take the input as a question and answer it finding any information needed.").block();
System.out.println(plan.toPlanString());
SKContext response = plan.invokeAsync("Where is the Eiffel Tower?").block();
System.out.println("========================================");
System.out.println("Answer is: " + response.getResult());
System.out.println("Sources used to answer this question: " + response.getVariables().get("sources"));
}
}
@@ -13,6 +13,18 @@
<artifactId>semantickernel-samples-guice</artifactId>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-bom</artifactId>
<version>${project.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
@@ -2,24 +2,24 @@
package com.microsoft.semantickernel.guice;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
import com.microsoft.semantickernel.textcompletion.CompletionKernelFunction;
import jakarta.inject.Inject;
public interface CompletionFunctionFactory {
CompletionSKFunction createFunction(
String prompt, String name, PromptTemplateConfig.CompletionConfig completionConfig);
CompletionKernelFunction createFunction(
String prompt, String name, PromptConfig.CompletionConfig completionConfig);
class CompletionFunctionFactoryImpl implements CompletionFunctionFactory {
@Inject
private Kernel kernel;
@Override
public CompletionSKFunction createFunction(
public CompletionKernelFunction createFunction(
String prompt,
String name,
PromptTemplateConfig.CompletionConfig completionConfig) {
PromptConfig.CompletionConfig completionConfig) {
return kernel.getSemanticFunctionBuilder()
.withPromptTemplate(prompt)
.withFunctionName(name)
@@ -5,7 +5,7 @@ import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.microsoft.semantickernel.orchestration.SKContext;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.semanticfunctions.PromptConfig;
public class CompletionFunctionExample {
@@ -64,7 +64,7 @@ public class CompletionFunctionExample {
.createFunction(
prompt,
"summarize",
new PromptTemplateConfig.CompletionConfig(
new PromptConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000))
.invokeAsync(text)
.block();
+1 -8
View File
@@ -10,15 +10,8 @@
<version>1.0.0-alpha.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>01-SimpleChat</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-core</artifactId>
</dependency>
</dependencies>
</project>
@@ -1,29 +1,30 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.nio.file.Path;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelResult;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunction;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplateEngine;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
public class Main {
final static String GPT_35_DEPLOYMENT_NAME = System.getenv("GPT_35_DEPLOYMENT_NAME");
final static String GPT_4_DEPLOYMENT_NAME = System.getenv("GPT_4_DEPLOYMENT_NAME");
final static String AZURE_OPENAI_ENDPOINT = System.getenv("AZURE_OPENAI_ENDPOINT");
final static String AZURE_OPENAI_API_KEY = System.getenv("AZURE_OPENAI_API_KEY");
final static String CURRENT_DIRECTORY = System.getProperty("user.dir");
public static void main(String[] args) throws IOException {
OpenAIAsyncClient client = new OpenAIClientBuilder()
@@ -31,26 +32,28 @@ public class Main {
.endpoint(AZURE_OPENAI_ENDPOINT)
.buildAsyncClient();
ChatCompletion<ChatHistory> gpt35Turbo = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME)
.build();
ChatCompletionService gpt35Turbo = AzureOpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME != null ? GPT_35_DEPLOYMENT_NAME : "gpt-35-turbo")
.build();
/*
ChatCompletion<ChatHistory> gpt4 = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME)
.build();
.withOpenAIClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME != null ? GPT_4_DEPLOYMENT_NAME : "gpt-4")
.build();
*/
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(gpt35Turbo)
.withDefaultAIService(gpt4)
.withPromptTemplateEngine(new HandlebarsPromptTemplateEngine())
.build();
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.build();
// Initialize the required functions and services for the kernel
SemanticFunction chatFunction = SemanticFunction.fromYaml("Plugins/ChatPlugin/SimpleChat.prompt.yaml");
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/SimpleChat.prompt.yaml"));
ChatHistory chatHistory = gpt35Turbo.createNewChat();
ChatHistory chatHistory = new ChatHistory();
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
while (true) {
@@ -58,23 +61,20 @@ public class Main {
String input = bf.readLine();
chatHistory.addUserMessage(input);
KernelResult result = kernel.runAsync(
true,
ContextVariables.builder().withVariable("messages", chatHistory).build(),
chatFunction
).block();
ContextVariable<String> message = kernel
.invokeAsync(
chatFunction,
KernelArguments
.builder()
.withVariable("messages", chatHistory)
.build(),
String.class
)
.block();
System.out.print("Assistant > ");
result.functionResults().forEach(
functionResult -> {
functionResult.<String>getStreamingValueAsync().subscribe(
message -> System.out.print(message)
);
String message = functionResult.<String>getValue();
chatHistory.addAssistantMessage(message);
}
);
System.out.println(message.getValue());
chatHistory.addAssistantMessage(message.getValue());
}
}
}
@@ -20,7 +20,17 @@ output_variable:
type: string
description: The response from the assistant.
execution_settings:
- model_id_pattern: ^gpt-4
- model_id: gpt-3.5-turbo
temperature: 0.3
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
- model_id: gpt-4
temperature: 0.7
- model_id_pattern: ^gpt-3\.?5-turbo
temperature: 0.3
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
@@ -0,0 +1,99 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.AuthorRole;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.chatcompletion.StreamingChatMessageContent;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
import reactor.core.publisher.Flux;
public class SimpleChatTest {
record Message(String matcher, String role, String content) {
}
private static ChatCompletionService mockService(List<Message> messages) {
ChatCompletionService gpt35Turbo = Mockito.mock(ChatCompletionService.class);
for (Message message : messages) {
Mockito.when(gpt35Turbo.getStreamingChatMessageContentsAsync(
Mockito.<String>argThat(
argument -> {
if (argument != null && argument.contains(message.matcher)) {
return true;
}
return false;
}),
Mockito.any(),
Mockito.any()))
.thenReturn(Flux.just(
new StreamingChatMessageContent(AuthorRole.ASSISTANT, message.content())));
}
return gpt35Turbo;
}
@Test
public void runSimpleChatTest() throws IOException {
List<Message> messages = Arrays.asList(
new Message("Is 4 prime", "assistant", "Yes 4 is prime"),
new Message("What is the capital of France", "assistant", "Paris")
);
ChatCompletionService gpt35Turbo = mockService(messages);
execute(gpt35Turbo, messages);
}
private static void execute(ChatCompletionService gpt35Turbo, List<Message> messages)
throws IOException {
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.build();
// Initialize the required functions and services for the kernel
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/SimpleChat.prompt.yaml"));
ChatHistory chatHistory = new ChatHistory();
messages.forEach(message -> {
chatHistory.addUserMessage(message.matcher);
List<String> result = kernel
.invokeStreamingAsync(
chatFunction,
KernelArguments
.builder()
.withVariable("messages", chatHistory)
.build(),
String.class
)
.collectList()
.block();
result.forEach(
functionResult -> {
Assertions.assertEquals(message.content(), functionResult);
chatHistory.addAssistantMessage(functionResult.toString());
}
);
});
}
}
+1 -7
View File
@@ -14,11 +14,5 @@
<artifactId>02-PersonaChat</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-core</artifactId>
</dependency>
</dependencies>
</project>
@@ -1,64 +1,56 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.List;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelResult;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunction;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplateEngine;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
public class Main {
final static String GPT_35_DEPLOYMENT_NAME = System.getenv("GPT_35_DEPLOYMENT_NAME");
final static String GPT_4_DEPLOYMENT_NAME = System.getenv("GPT_4_DEPLOYMENT_NAME");
final static String AZURE_OPENAI_ENDPOINT = System.getenv("AZURE_OPENAI_ENDPOINT");
final static String AZURE_OPENAI_API_KEY = System.getenv("AZURE_OPENAI_API_KEY");
final static String CURRENT_DIRECTORY = System.getProperty("user.dir");
public static void main(String[] args) throws ConfigurationException, IOException {
public static void main(String[] args) throws IOException {
OpenAIAsyncClient client = new OpenAIClientBuilder()
.credential(new KeyCredential(AZURE_OPENAI_API_KEY))
.endpoint(AZURE_OPENAI_ENDPOINT)
.buildAsyncClient();
// Initialize the required functions and services for the kernel
SKFunction chatFunction = SemanticFunction.fromYaml("Plugins/ChatPlugin/PersonaChat.prompt.yaml");
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/PersonaChat.prompt.yaml"));
ChatCompletion<ChatHistory> gpt35Turbo = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME)
ChatCompletionService gpt35Turbo = AzureOpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME != null ? GPT_35_DEPLOYMENT_NAME : "gpt-35-turbo")
.build();
ChatCompletion<ChatHistory> gpt4 = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME)
.build();
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(gpt35Turbo)
.withDefaultAIService(gpt4)
.withPromptTemplateEngine(new HandlebarsPromptTemplateEngine())
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.build();
ChatHistory chatHistory = gpt35Turbo.createNewChat();
ChatHistory chatHistory = new ChatHistory();
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
while (true) {
System.out.print("\nUser > ");
String input = bf.readLine();
chatHistory.addUserMessage(input);
@@ -66,25 +58,27 @@ public class Main {
// Run the chat function
// The persona chat function uses the persona variable to set the persona of the chat using a system message
// See Plugins/ChatPlugin/PersonaChat.prompt.yaml for the full prompt
KernelResult result = kernel.runAsync(
true, // streaming
ContextVariables.builder()
.withVariable("messages", chatHistory)
.withVariable("persona", "You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
chatFunction
).block();
List<String> result = kernel.invokeStreamingAsync(
chatFunction,
KernelArguments
.builder()
.withVariable("messages", chatHistory)
.withVariable("persona",
"You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
String.class
)
.collectList()
.block();
System.out.print("Assistant > ");
result.functionResults().forEach(
functionResult -> {
functionResult.<String>getStreamingValueAsync().subscribe(
message -> System.out.print(message)
);
String message = functionResult.<String>getValueAsync().block();
chatHistory.addAssistantMessage(message);
}
);
}
result
.forEach(
message -> {
System.out.print(message);
chatHistory.addAssistantMessage(message);
}
);
}
}
}
@@ -1,5 +1,5 @@
name: PersonaChat
template: |
template: |
{{#message role="system"}}
{{persona}}
Do not answer with XML or any format.
@@ -26,7 +26,17 @@ output_variable:
type: string
description: The response from the assistant.
execution_settings:
- model_id_pattern: ^gpt-4
- model_id: gpt-3.5-turbo
temperature: 0.3
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
- model_id: gpt-4
temperature: 0.7
- model_id_pattern: ^gpt-3\.?5-turbo
temperature: 0.3
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
@@ -0,0 +1,96 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.AuthorRole;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.chatcompletion.StreamingChatMessageContent;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
import reactor.core.publisher.Flux;
public class PersonaChatTest {
record Message(String matcher, String role, String content) {
}
private static ChatCompletionService mockService(List<Message> messages) {
ChatCompletionService gpt35Turbo = Mockito.mock(ChatCompletionService.class);
for (Message message : messages) {
Mockito.when(gpt35Turbo.getStreamingChatMessageContentsAsync(
Mockito.<String>argThat(
argument -> {
if (argument != null && argument.contains(message.matcher)) {
return true;
}
return false;
}),
Mockito.any(),
Mockito.any()))
.thenReturn(Flux.just(new StreamingChatMessageContent(
AuthorRole.ASSISTANT, message.content())));
}
return gpt35Turbo;
}
@Test
public void runSimpleChatTest() throws IOException {
List<Message> messages = Arrays.asList(
new Message("Is 4 prime", "assistant", "Yes 4 is prime"),
new Message("What is the capital of France", "assistant", "Paris")
);
ChatCompletionService gpt35Turbo = mockService(messages);
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.build();
// Initialize the required functions and services for the kernel
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/PersonaChat.prompt.yaml"));
ChatHistory chatHistory = new ChatHistory();
messages.forEach(message -> {
chatHistory.addUserMessage(message.matcher);
List<String> result = kernel
.invokeStreamingAsync(
chatFunction,
KernelArguments
.builder()
.withVariable("messages", chatHistory)
.withVariable("persona",
"You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
String.class
)
.collectList()
.block();
result
.forEach(
functionResult -> {
Assertions.assertEquals(message.content(), functionResult);
chatHistory.addAssistantMessage(functionResult.toString());
}
);
});
}
}
-15
View File
@@ -14,20 +14,5 @@
<artifactId>03-SimpleRag</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-core</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
</project>
@@ -1,33 +1,33 @@
import java.io.IOException;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelResult;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.ChatCompletion;
import com.microsoft.semantickernel.chatcompletion.AzureOpenAIChatCompletion;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.nativefunction.NativeFunction;
import com.microsoft.semantickernel.orchestration.ContextVariables;
import com.microsoft.semantickernel.orchestration.SKFunction;
import com.microsoft.semantickernel.plugin.Plugin;
import com.microsoft.semantickernel.semanticfunctions.SemanticFunction;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplateEngine;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import plugins.searchplugin.Search;
public class Main {
final static String GPT_35_DEPLOYMENT_NAME = System.getenv("GPT_35_DEPLOYMENT_NAME");
final static String GPT_4_DEPLOYMENT_NAME = System.getenv("GPT_4_DEPLOYMENT_NAME");
final static String AZURE_OPENAI_ENDPOINT = System.getenv("AZURE_OPENAI_ENDPOINT");
final static String AZURE_OPENAI_API_KEY = System.getenv("AZURE_OPENAI_API_KEY");
final static String BING_API_KEY = System.getenv("BING_API_KEY");
final static String CURRENT_DIRECTORY = System.getProperty("user.dir");
public static void main(String[] args) throws IOException {
OpenAIAsyncClient client = new OpenAIClientBuilder()
@@ -35,61 +35,53 @@ public class Main {
.endpoint(AZURE_OPENAI_ENDPOINT)
.buildAsyncClient();
// Initialize the required functions and services for the kernel
SKFunction chatFunction = SemanticFunction.fromYaml("Plugins/ChatPlugin/GroundedChat.prompt.yaml");
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/GroundedChat.prompt.yaml"));
ChatCompletion<ChatHistory> gpt35Turbo = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME)
ChatCompletionService gpt35Turbo = AzureOpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(GPT_35_DEPLOYMENT_NAME != null ? GPT_35_DEPLOYMENT_NAME : "gpt-35-turbo")
.build();
ChatCompletion<ChatHistory> gpt4 = ChatCompletion.builder()
.withOpenAIClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME)
.build();
// Create the search plugin
Plugin searchPlugin = new com.microsoft.semantickernel.plugin.Plugin(
"Search",
NativeFunction.getFunctionsFromObject(new Search(BING_API_KEY))
);
KernelPlugin searchPlugin = KernelPluginFactory.createFromObject(
new Search(BING_API_KEY),
"Search"
);
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(gpt35Turbo)
.withDefaultAIService(gpt4)
.withPromptTemplateEngine(new HandlebarsPromptTemplateEngine())
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.withPlugins(searchPlugin)
.build();
ChatHistory chatHistory = gpt35Turbo.createNewChat();
while(true)
{
ChatHistory chatHistory = new ChatHistory();
while (true) {
String input = System.console().readLine("User > ");
chatHistory.addUserMessage(input);
// Run the chat function
// The grounded chat function uses the search plugin to perform a Bing search to ground the response
// See Plugins/ChatPlugin/GroundedChat.prompt.yaml for the full prompt
KernelResult result = kernel.runAsync(
true, // streaming
ContextVariables.builder()
.withVariable("messages", chatHistory)
.withVariable("persona", "You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
chatFunction
).block();
List<String> result = kernel.invokeStreamingAsync(
chatFunction,
KernelArguments.builder()
.withVariable("messages", chatHistory)
.withVariable("persona",
"You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
String.class
).collectList()
.block();
System.console().printf("Assistant > ");
result.functionResults().forEach(
result.forEach(
functionResult -> {
functionResult.<String>getStreamingValueAsync().subscribe(
message -> System.console().printf(message)
);
String message = functionResult.<String>getValueAsync().block();
chatHistory.addAssistantMessage(message);
System.out.println(functionResult);
chatHistory.addAssistantMessage(functionResult);
}
);
}
}
}
}
@@ -2,10 +2,9 @@
package plugins.searchplugin;
import com.azure.core.http.HttpClient;
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
import com.microsoft.semantickernel.plugin.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.plugin.annotations.KernelFunctionParameter;
import com.microsoft.semantickernel.plugins.web.bing.BingConnector;
import reactor.core.publisher.Mono;
public class Search {
@@ -21,9 +20,9 @@ public class Search {
this._bingConnector = new BingConnector(apiKey, httpClient);
}
@DefineSKFunction(description="Searches Bing for the given query")
@DefineKernelFunction(description="Searches Bing for the given query")
public Mono<String> searchAsync(
@SKFunctionParameters(description="The search query", name="query", type=String.class) String query
@KernelFunctionParameter(description="The search query", name="query", type=String.class) String query
){
return Mono.empty();
}
@@ -28,10 +28,20 @@ input_variables:
description: The history of the chat.
is_required: true
output_variable:
type: string
description: The response from the assistant.
type: string
description: The response from the assistant.
execution_settings:
- model_id_pattern: ^gpt-3\.?5-turbo
- model_id: gpt-3.5-turbo
temperature: 0.3
- model_id_pattern: ^gpt-4
temperature: 0.7
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
- model_id: gpt-4
temperature: 0.7
top_p: 0.0
presence_penalty: 0.0
frequency_penalty: 0.0
max_tokens: 256
stop_sequences: [ ]
@@ -0,0 +1,103 @@
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.chatcompletion.AuthorRole;
import com.microsoft.semantickernel.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.chatcompletion.StreamingChatMessageContent;
import com.microsoft.semantickernel.orchestration.KernelFunction;
import com.microsoft.semantickernel.orchestration.KernelFunctionYaml;
import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import plugins.searchplugin.Search;
import reactor.core.publisher.Flux;
public class SimpleRagTest {
record Message(String matcher, String role, String content) {
}
private static ChatCompletionService mockService(List<Message> messages) {
ChatCompletionService gpt35Turbo = Mockito.mock(ChatCompletionService.class);
for (Message message : messages) {
Mockito.when(gpt35Turbo.getStreamingChatMessageContentsAsync(
Mockito.<String>argThat(
argument -> {
if (argument != null && argument.contains(message.matcher)) {
return true;
}
return false;
}),
Mockito.any(),
Mockito.any()))
.thenReturn(Flux.just(
new StreamingChatMessageContent(AuthorRole.ASSISTANT, message.content())));
}
return gpt35Turbo;
}
@Test
public void runSimpleChatTest() throws IOException {
List<Message> messages = Arrays.asList(
new Message("Is 4 prime", "assistant", "Yes 4 is prime"),
new Message("What is the capital of France", "assistant", "Paris")
);
// Initialize the required functions and services for the kernel
KernelFunction chatFunction = KernelFunctionYaml.fromYaml(
Path.of("Plugins/ChatPlugin/GroundedChat.prompt.yaml"));
ChatCompletionService gpt35Turbo = mockService(messages);
// Create the search plugin
KernelPlugin searchPlugin = KernelPluginFactory.createFromObject(
new Search(""),
"Search"
);
Kernel kernel = SKBuilders.kernel()
.withDefaultAIService(ChatCompletionService.class, gpt35Turbo)
.withPromptTemplateEngine(new HandlebarsPromptTemplate())
.withPlugins(searchPlugin)
.build();
ChatHistory chatHistory = new ChatHistory();
messages.forEach(message -> {
chatHistory.addUserMessage(message.matcher);
// Run the chat function
// The grounded chat function uses the search plugin to perform a Bing search to ground the response
// See Plugins/ChatPlugin/GroundedChat.prompt.yaml for the full prompt
List<String> result = kernel.invokeStreamingAsync(
chatFunction,
KernelArguments.builder()
.withVariable("messages", chatHistory)
.withVariable("persona",
"You are a snarky (yet helpful) teenage assistant. Make sure to use hip slang in every response.")
.build(),
String.class
).collectList()
.block();
result
.forEach(
functionResult -> {
Assertions.assertEquals(message.content(), functionResult);
chatHistory.addAssistantMessage(functionResult.toString());
}
);
});
}
}
@@ -41,12 +41,12 @@ public class Main {
SKFunction chatFunction = SemanticFunction.fromYaml("/Plugins/ChatPlugin/Chat.prompt.yaml");
ChatCompletion<ChatHistory> gpt35Turbo = ChatCompletion.builder()
.withOpenAIClient(client)
.withOpenAIAsyncClient(client)
.withModelId(GPT_35_TURBO_DEPLOYMENT_NAME)
.build();
ChatCompletion<ChatHistory> gpt4 = ChatCompletion.builder()
.withOpenAIClient(client)
.withOpenAIAsyncClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME)
.build();
@@ -35,7 +35,7 @@ public class Main {
.buildAsyncClient();
ChatCompletion<ChatHistory> gpt4Turbo = ChatCompletion.builder()
.withOpenAIClient(client)
.withOpenAIAsyncClient(client)
.withModelId(GPT_4_DEPLOYMENT_NAME)
.build();
+108 -54
View File
@@ -1,17 +1,12 @@
<?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>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>samples</artifactId>
<version>1.0.0-alpha.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent> -->
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>sk-v1-samples</artifactId>
<version>1.0.0-alpha.1-SNAPSHOT</version>
<name>Semantic Kernel version 1 Samples</name>
<description>Sample code for using the Semantic Kernel version 1 API</description>
<packaging>pom</packaging>
@@ -22,64 +17,123 @@
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>01-SimpleChat</module>
<module>02-PersonaChat</module>
<module>03-SimpleRag</module>
<module>04-DynamicRag</module>
<module>05-MultiModal</module>
<module>06-Assistants</module>
<!-- <module>04-DynamicRag</module> -->
<!-- <module>05-MultiModal</module> -->
<!-- <module>06-Assistants</module> -->
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-core</artifactId>
<artifactId>semantickernel-bom</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-azureopenai</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-huggingface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-ollama</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-openai</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-plugin-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-planners</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-ai-openai</artifactId>
<version>1.0.0-beta.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-core</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-api</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-azureopenai</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>aiservices-openai</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-ai-openai</artifactId>
<version>1.0.0-beta.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>3.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>run-sample</id>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
+8
View File
@@ -33,6 +33,10 @@
<artifactId>jackson-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
@@ -41,5 +45,9 @@
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
</dependencies>
</project>

Some files were not shown because too many files have changed in this diff Show More