From 666a9bb86e34f18b2f537963733dc79f3de31554 Mon Sep 17 00:00:00 2001 From: John Oliver <1615532+johnoliver@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:13:47 +0000 Subject: [PATCH] Java: Add retry example (#4480) --- .../Example06_TemplateLanguage.java | 18 ++++--- .../Example08_RetryHandler.java | 52 +++++++++++++++++++ .../KernelFunctionFromPrompt.java | 7 ++- .../KernelPromptTemplateFactory.java | 4 ++ 4 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java index d23e48a0c8..9e8857c5c6 100644 --- a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java @@ -19,6 +19,12 @@ import com.microsoft.semantickernel.textcompletion.TextGenerationService; public class Example06_TemplateLanguage { + private static final boolean USE_AZURE_CLIENT = Boolean.parseBoolean( + System.getenv("USE_AZURE_CLIENT")); + private static final String CLIENT_KEY = System.getenv("CLIENT_KEY"); + + // Only required if USE_AZURE_CLIENT is true + private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT"); public static class Time { @@ -39,14 +45,10 @@ public class Example06_TemplateLanguage { TextGenerationService textGenerationService; - String clientKey = System.getenv("CLIENT_KEY"); - - if (Boolean.parseBoolean(System.getenv("USE_AZURE_CLIENT"))) { - String clientEndpoint = System.getenv("CLIENT_ENDPOINT"); - + if (USE_AZURE_CLIENT) { OpenAIAsyncClient client = new OpenAIClientBuilder() - .credential(new AzureKeyCredential(clientKey)) - .endpoint(clientEndpoint) + .credential(new AzureKeyCredential(CLIENT_KEY)) + .endpoint(CLIENT_ENDPOINT) .buildAsyncClient(); textGenerationService = AzureOpenAITextGenerationService.builder() @@ -55,7 +57,7 @@ public class Example06_TemplateLanguage { .build(); } else { OpenAIAsyncClient client = new OpenAIClientBuilder() - .credential(new KeyCredential(clientKey)) + .credential(new KeyCredential(CLIENT_KEY)) .buildAsyncClient(); // TODO: Add support for OpenAI API diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java new file mode 100644 index 0000000000..8d0f917440 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java @@ -0,0 +1,52 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +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.DefaultKernel; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.aiservices.azureopenai.AzureOpenAITextGenerationService; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.KernelFunction; +import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt; +import com.microsoft.semantickernel.textcompletion.TextGenerationService; +import java.time.Duration; + +public class Example08_RetryHandler { + + public static void main(String[] args) throws ConfigurationException { + // Create a Kernel with the HttpClient + RetryOptions retryOptions = new RetryOptions(new ExponentialBackoffOptions() + .setMaxDelay(Duration.ofSeconds(10)) + .setBaseDelay(Duration.ofSeconds(2)) + .setMaxRetries(3)); + + OpenAIAsyncClient client = new OpenAIClientBuilder() + .retryOptions(retryOptions) + .endpoint("https://localhost:5000") + .credential(new AzureKeyCredential("BAD KEY")) + .buildAsyncClient(); + + AzureOpenAITextGenerationService textGenerationService = AzureOpenAITextGenerationService.builder() + .withOpenAIAsyncClient(client) + .withModelId("text-davinci-003") + .build(); + + Kernel kernel = new DefaultKernel.Builder() + .withDefaultAIService(TextGenerationService.class, textGenerationService) + .build(); + + String question = "How popular is the Polly library?"; + + KernelFunction fuction = KernelFunctionFromPrompt.create(question); + + try { + // Will retry 3 times with exponential backoff + kernel.invokeAsync(fuction, null, String.class).block(); + } catch (Exception e) { + System.out.println("Hit max retries"); + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java index bb66af506c..a9b700c454 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java @@ -12,8 +12,6 @@ import com.microsoft.semantickernel.orchestration.StreamingContent; import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariable; import com.microsoft.semantickernel.orchestration.contextvariables.ContextVariableType; import com.microsoft.semantickernel.orchestration.contextvariables.KernelArguments; -import com.microsoft.semantickernel.templateengine.handlebars.HandlebarsPromptTemplate; -import com.microsoft.semantickernel.templateengine.semantickernel.DefaultPromptTemplate; import com.microsoft.semantickernel.textcompletion.TextGenerationService; import java.util.HashMap; import java.util.List; @@ -153,6 +151,11 @@ public class KernelFunctionFromPrompt extends DefaultKernelFunction { } + public static KernelFunction create( + String promptTemplate) { + return create(promptTemplate, null, null, null, null, null); + } + /// /// Creates a instance for a prompt specified via a prompt template. /// diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelPromptTemplateFactory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelPromptTemplateFactory.java index 8e2172d734..70bf268669 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelPromptTemplateFactory.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelPromptTemplateFactory.java @@ -7,6 +7,10 @@ import java.util.Locale; public class KernelPromptTemplateFactory implements PromptTemplateFactory { public PromptTemplate tryCreate(PromptTemplateConfig templateConfig) { + if (templateConfig == null || templateConfig.getTemplateFormat() == null) { + return new DefaultPromptTemplate(templateConfig); + } + switch (templateConfig.getTemplateFormat().toLowerCase(Locale.ROOT)) { case "semantic-kernel": return new DefaultPromptTemplate(templateConfig);