Skip to content

Latest commit

 

History

History

semantickernel-concepts

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Semantic Kernel Java Version Doc

The purpose of this article is to help you quickly grasp the key concepts in Semantic Kernel and get started quickly.

In Semantic Kernel Java, the builder pattern is extensively used. If you are not familiar with the builder pattern, I recommend you check out: Builder Design Pattern

All the code examples below are from samples/semantickernel-concepts/semantickernel-syntax-examples.

How to Define an AI Service?

ChatCompletionServicechatCompletionService = ChatCompletionService.builder() .withOpenAIAsyncClient(client) .withModelId("gpt-3.5-turbo-0613") .withServiceId("fridayChatGeneration") .build();

How to Use an AI Service?

  • Retrieve the AI Service from the Kernel

    ChatCompletionServiceservice = kernel.getService(ChatCompletionService.class);
  • Directly call service.getChatMessageContentsAsync to get the LLM response

    ChatCompletionServiceservice = kernel.getService(ChatCompletionService.class); varchatHistory = newChatHistory(systemMessage); chatHistory.addUserMessage(userMessage); varanswer = service.getChatMessageContentsAsync(chatHistory, kernel, null).block();

How to Define a KernelBuilder?

The KernelBuilder is a builder used to create and configure a new Kernel with necessary services and plugins.

ChatCompletionServicechatCompletionService = ChatCompletionService.builder() .withOpenAIAsyncClient(client) .withModelId("gpt-3.5-turbo-0613") .withServiceId("fridayChatGeneration") .build(); returnKernel.builder() .withAIService(ChatCompletionService.class, chatCompletionService);

How to Define a Kernel?

A Kernel is created using the KernelBuilder, where various services and plugins are configured via withXXX().

Create a Kernel using KernelBuilder and configure the necessary parameters

Kernelkernel = Kernel.builder() .withPlugin(myPlugin) .withAIService(openAiChatService) .withServiceSelector() .build();

How to Define a KernelPlugin?

  1. Define a custom class

  2. Construct using KernelPluginFactory

publicstaticclassTime { @DefineKernelFunction(name = "date") publicStringdate() { System.out.println("date is called"); Datenow = newDate(); SimpleDateFormatdateFormat = newSimpleDateFormat("yyyy-MM-dd"); returndateFormat.format(now); } @DefineKernelFunction(name = "time") publicStringtime() { System.out.println("time is called"); Datenow = newDate(); SimpleDateFormattimeFormat = newSimpleDateFormat("HH:mm:ss"); returntimeFormat.format(now); } } KernelPlugintime = KernelPluginFactory.createFromObject(newTime(), "time");

How to Define a KernelFunction?

Native function

A native function in Semantic Kernel performs precise tasks like data retrieval, time checks, and complex math, which large language models (LLMs) may make mistake. Native functions are written in code and ensure accuracy. In contrast, LLMs offer flexibility, generality, and creativity, excelling in generating and predicting text. Combining both leverages their respective strengths for optimal performance. For more details, refer to Microsoft Documentation on Kernel Functions.

Here’s an example of how to define a native kernel function:

publicclassTextPlugin { @DefineKernelFunction(description = "Change all string chars to uppercase.", name = "Uppercase") publicStringuppercase(@KernelFunctionParameter(description = "Text to uppercase", name = "input") Stringtext) { returntext.toUpperCase(Locale.ROOT); } }

Inline function

To create a inline KernelFunction from a prompt, you can use either of the following methods, which are equivalent:

  • KernelFunctionFromPrompt.builder().withTemplate(promptTemplate).build();
  • KernelFunction.createFromPrompt(message).build();

KernelFunctionFromPrompt.builder().withTemplate(promptTemplate).build();

StringpromptTemplate = """ 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(); varexcuseFunction = KernelFunctionFromPrompt.builder() .withTemplate(promptTemplate) .withDefaultExecutionSettings( PromptExecutionSettings.builder() .withTemperature(0.4) .withTopP(1) .withMaxTokens(500) .withUser("bx-h") .build() ) .withName("ExcuseGeneratorFunction") .build();

KernelFunction.createFromPrompt(message).build();

varmessage = "Translate this date " + date + " to French format"; varfixedFunction = KernelFunction .createFromPrompt(message) .withDefaultExecutionSettings( PromptExecutionSettings.builder() .withMaxTokens(100) .build()) .withTemplateFormat(PromptTemplateConfig.SEMANTIC_KERNEL_TEMPLATE_FORMAT) .withName("translator") .build();

The SEMANTIC_KERNEL_TEMPLATE_FORMAT corresponds to the 'semantic-kernel' rendering engine, which uses the syntax {{$variable}} for variables.

Another rendering engine is 'handlebars', which uses the syntax {{variable}}. Here's an example of how to use both:

runPrompt(kernel, "semantic-kernel", "Hello AI, my name is {{$name}}. What is the origin of my name?", templateFactory); runPrompt(kernel, "handlebars", "Hello AI, my name is {{name}}. What is the origin of my name?", templateFactory);

The runPrompt method is defined as follows:

publicstaticvoidrunPrompt(Kernelkernel, StringtemplateFormat, Stringprompt, PromptTemplateFactorytemplateFactory) { varfunction = newKernelFunctionFromPrompt.Builder<>() .withTemplate(prompt) .withTemplateFormat(templateFormat) .withPromptTemplateFactory(templateFactory) .build(); vararguments = KernelFunctionArguments.builder() .withVariable("name", "Bob") .build(); varresult = kernel.invokeAsync(function).withArguments(arguments).block(); System.out.println(result.getResult()); }

For more information, please refer to the following resources:

Configuration file

Define a function from a configuration file (json)

varprompt = "Hello AI, what can you do for me?"; StringconfigPayload = """ { "schema": 1, "name": "HelloAI", "description": "Say hello to an AI", "type": "completion", "completion": { "max_tokens": 256, "temperature": 0.5, "top_p": 0.0, "presence_penalty": 0.0, "frequency_penalty": 0.0 } }""".stripIndent(); PromptTemplateConfigpromptConfig = PromptTemplateConfig .parseFromJson(configPayload) .copy() .withTemplate(prompt) .build(); varfunc = KernelFunction .createFromPrompt(promptConfig) .build();

How to Define a KernelFunctionArguments?

KernelFunctionArguments.builder().withVariable("input", "Jupiter").build();

This can also be done as:

KernelFunctionArguments.builder().withInput("Jupiter").build();

How to Call a KernelFunction?

  • Direct call:
TextPlugintext = newTextPlugin(); returntext.uppercase("ciao!");
  • Invoke via Kernel.invokeAsync(KernelFunction)
Kernelkernel = Kernel.builder().build(); KernelPluginkernelPlugin = KernelPluginFactory.createFromObject(newStaticTextPlugin(), "text"); KernelFunctionArgumentsarguments = KernelFunctionArguments.builder() .withVariable("input", "Today is: ") .withVariable("day", "Monday") .build(); returnkernel.invokeAsync(kernelPlugin.get("AppendDay")) .withArguments(arguments) .block() .getResult();

OR:

varresult = kernel .invokeAsync(excuseFunction) .withArguments( KernelFunctionArguments.builder() .withInput("I missed the F1 final race") .build() ) .block();

How to Define a PromptTemplate?

The purpose of a prompt template is to:

  • Render the prompt
  • Be passed as a parameter to createFromPrompt() to construct KernelFunction

Using KernelPromptTemplateFactory.tryCreate(PromptTemplateConfig)

  1. Define the prompt template

  2. Create using KernelPromptTemplateFactory()

StringfunctionDefinition = """ Today is: {{time.date}} Current time is: {{time.time}} Answer 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)?"""; PromptTemplatepromptTemplate = newKernelPromptTemplateFactory().tryCreate( PromptTemplateConfig .builder() .withTemplate(functionDefinition) .build() );

Create using PromptTemplateFactory.build

StringsystemPromptTemplate = "..."; PromptTemplatepromptTemplate = PromptTemplateFactory.build( PromptTemplateConfig .builder() .withTemplate(systemPromptTemplate) .build() );

How to Render a Prompt Without Sending an LLM Query?

varrenderedPrompt = promptTemplate.renderAsync(kernel, KernelFunctionArguments, InvocationContext).block(); System.out.println(renderedPrompt);

Hooks

Hooks are functions triggered in specific situations attached to the kernel.

  • Global Registration: If added to kernel.getGlobalKernelHooks(), it is globally effective

    kernel.getGlobalKernelHooks().addHook("hookName", KernelHook);
  • Single Call Registration: If passed as a parameter in invokeAsync, it is effective for that call only

    KernelHookskernelHooks = newKernelHooks(); kernelHooks.addPreChatCompletionHook(...); varresult = kernel.invokeAsync(writerFunction) .withArguments(KernelFunctionArguments.builder().build()) .addKernelHooks(kernelHooks) .block();

FunctionInvokingHook

Triggered before function call.

FunctionInvokingHookpreHook = event -> { System.out.println(event.getFunction().getName() + " : Pre Execution Handler - Triggered"); returnevent; }; kernel.getGlobalKernelHooks().addHook("", preHook);

FunctionInvokedHook

Triggered after function call

FunctionInvokedHookhook = event -> { Stringresult = (String) event.getResult().getResult(); System.out.println(event.getFunction().getName() + " : Modified result via FunctionInvokedHook: " + result); result = result.replaceAll("[aeiouAEIOU0-9]", "*"); returnnewFunctionInvokedEvent( event.getFunction(), event.getArguments(), newFunctionResult<>(ContextVariable.of(result), event.getResult().getMetadata(), result) ); }; kernel.getGlobalKernelHooks().addHook(hook);

PromptRenderingHook

PromptRenderingHookmyRenderingHandler = event -> { System.out.println(event.getFunction().getName() + " : Triggered PromptRenderingHook"); event.getArguments().put("style", ContextVariable.of("Seinfeld")); returnevent; };

PromptRenderedHook

PromptRenderedHookmyRenderedHandler = event -> { System.out.println(event.getFunction().getName() + " : Triggered PromptRenderedHook"); Stringprompt = event.getPrompt() + "\nUSE SHORT, CLEAR, COMPLETE SENTENCES."; returnnewPromptRenderedEvent(event.getFunction(), event.getArguments(), prompt); };

PromptRenderingHook and PromptRenderedHook are triggered only at the start of a conversation. They won't trigger during multiple tool calls. To trigger at every LLM interaction, use ChatCompletionsHook

PreChatCompletionHook

Add a pre-chat completion hook to add instructions before ChatCompletion.

kernel.getGlobalKernelHooks().addPreChatCompletionHook(event -> { ChatCompletionsOptionsoptions = event.getOptions(); List<ChatRequestMessage> messages = options.getMessages(); messages = newArrayList<>(messages); messages.add(newChatRequestSystemMessage("Use upper case text when responding to the prompt.")); System.out.println("------- Triggered before ChatCompletion -------"); System.out.println("---- Added: Use upper case text when responding to the prompt. ----"); for (ChatRequestMessagemsg : messages) { System.out.println(msg); } returnnewPreChatCompletionEvent( PreChatCompletionHook.cloneOptionsWithMessages(options, messages) ); });

PostChatCompletionHook

Add a post-chat completion hook to adjust the output format

kernel.getGlobalKernelHooks().addPostChatCompletionHook(event -> { System.out.println("------- Triggered after ChatCompletion -------"); System.out.println("--- Output ChatCompletion and id ----"); System.out.println("Chat completion"); System.out.println("Id: " + event.getChatCompletions().getId()); returnevent; });
close