From 6df0f5517c8aad681dd5e16b4c4bb5e5ba1147d0 Mon Sep 17 00:00:00 2001 From: John Oliver <1615532+johnoliver@users.noreply.github.com> Date: Tue, 13 Feb 2024 21:21:48 +0000 Subject: [PATCH] Java: add a priority order to hook invocations. Remove withInvocationContext (#5004) ### Motivation and Context ### Description ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --- .../semantickernel/hooks/KernelHook.java | 14 ++++++- .../semantickernel/hooks/KernelHooks.java | 42 ++++++++++++------- .../orchestration/FunctionInvocation.java | 13 ------ 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java index 535727e391..be649fa47b 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java @@ -6,7 +6,19 @@ import java.util.List; import java.util.function.Function; import java.util.function.Predicate; -public interface KernelHook extends Predicate, Function { +public interface KernelHook extends Predicate, + Function { + + /** + * The priority of the hook. The default priority is 50. The priority is used to determine the + * order in which hooks that accept the same event type are executed, lower priorities are executed first. No ordering is + * guaranteed for hooks with the same priority. + * + * @return the priority of the hook + */ + default int getPriority() { + return 50; + } interface FunctionInvokingHook extends KernelHook { diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java index e7cd3f931e..f47bb7fbcd 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java @@ -1,18 +1,19 @@ package com.microsoft.semantickernel.hooks; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.function.Function; - -import javax.annotation.Nullable; - import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokedHook; import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokingHook; import com.microsoft.semantickernel.hooks.KernelHook.PreChatCompletionHook; import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderedHook; import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderingHook; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; +import java.util.function.Function; +import javax.annotation.Nullable; public class KernelHooks { @@ -37,7 +38,7 @@ public class KernelHooks { public UnmodifiableKernelHooks unmodifiableClone() { return new UnmodifiableKernelHooks(this); } - + private Map> getHooks() { return Collections.unmodifiableMap(hooks); } @@ -69,7 +70,11 @@ public class KernelHooks { @SuppressWarnings("unchecked") public T executeHooks(T event) { - for (KernelHook hook : hooks.values()) { + SortedSet> hooks = new TreeSet<>(Comparator.comparingInt(KernelHook::getPriority)); + + hooks.addAll(this.hooks.values()); + + for (KernelHook hook : hooks) { if (hook.test(event)) { // unchecked cast event = ((KernelHook) hook).apply(event); @@ -110,33 +115,38 @@ public class KernelHooks { } public static class UnmodifiableKernelHooks extends KernelHooks { - + private UnmodifiableKernelHooks(KernelHooks kernelHooks) { super(kernelHooks); } @Override - public String addFunctionInvokingHook(Function function) { + public String addFunctionInvokingHook( + Function function) { throw new UnsupportedOperationException("unmodifiable instance of KernelHooks"); } @Override - public String addFunctionInvokedHook(Function, FunctionInvokedEvent> function) { + public String addFunctionInvokedHook( + Function, FunctionInvokedEvent> function) { throw new UnsupportedOperationException("unmodifiable instance of KernelHooks"); } @Override - public String addPreChatCompletionHook(Function function) { + public String addPreChatCompletionHook( + Function function) { throw new UnsupportedOperationException("unmodifiable instance of KernelHooks"); } @Override - public String addPromptRenderedHook(Function function) { + public String addPromptRenderedHook( + Function function) { throw new UnsupportedOperationException("unmodifiable instance of KernelHooks"); } @Override - public String addPromptRenderingHook(Function function) { + public String addPromptRenderingHook( + Function function) { throw new UnsupportedOperationException("unmodifiable instance of KernelHooks"); } diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java index 811578e3fe..d52b50840f 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java @@ -129,19 +129,6 @@ public class FunctionInvocation extends Mono> { return this; } - public FunctionInvocation withInvocationContext( - @Nullable InvocationContext invocationContext) { - if (invocationContext == null) { - return this; - } - withTypes(invocationContext.getContextVariableTypes()); - withToolCallBehavior(invocationContext.getToolCallBehavior()); - withPromptExecutionSettings(invocationContext.getPromptExecutionSettings()); - addKernelHooks(invocationContext.getKernelHooks()); - return this; - } - - @Override public void subscribe(CoreSubscriber> coreSubscriber) { performSubscribe(