Skip to content

Commit c4d301c

Browse files
committed
Fix some global kernel hooks not being executed
1 parent 61219b5 commit c4d301c

6 files changed

Lines changed: 70 additions & 19 deletions

File tree

‎aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java‎

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ private Mono<ChatMessages> internalChatMessageContentsAsync(
311311

312312
ChatCompletionsOptions options = executeHook(
313313
invocationContext,
314+
kernel,
314315
new PreChatCompletionEvent(
315316
getCompletionsOptions(
316317
this,
@@ -349,7 +350,7 @@ private Mono<ChatMessages> internalChatMessageContentsAsync(
349350
.collect(Collectors.toList());
350351

351352
// execute post chat completion hook
352-
executeHook(invocationContext, new PostChatCompletionEvent(completions));
353+
executeHook(invocationContext, kernel, new PostChatCompletionEvent(completions));
353354

354355
// Just return the result:
355356
// If we don't want to attempt to invoke any functions
@@ -517,11 +518,12 @@ private Mono<FunctionResult<String>> invokeFunctionTool(
517518
pluginName,
518519
openAIFunctionToolCall.getFunctionName());
519520

520-
PreToolCallEvent hookResult = executeHook(invocationContext, new PreToolCallEvent(
521-
openAIFunctionToolCall.getFunctionName(),
522-
openAIFunctionToolCall.getArguments(),
523-
function,
524-
contextVariableTypes));
521+
PreToolCallEvent hookResult = executeHook(invocationContext, kernel,
522+
new PreToolCallEvent(
523+
openAIFunctionToolCall.getFunctionName(),
524+
openAIFunctionToolCall.getArguments(),
525+
function,
526+
contextVariableTypes));
525527

526528
function = hookResult.getFunction();
527529
KernelFunctionArguments arguments = hookResult.getArguments();
@@ -537,12 +539,20 @@ private Mono<FunctionResult<String>> invokeFunctionTool(
537539

538540
private static <T extends KernelHookEvent> T executeHook(
539541
@Nullable InvocationContext invocationContext,
542+
@Nullable Kernel kernel,
540543
T event) {
541-
KernelHooks kernelHooks = invocationContext != null
542-
&& invocationContext.getKernelHooks() != null
543-
? invocationContext.getKernelHooks()
544-
: new KernelHooks();
545-
544+
KernelHooks kernelHooks = null;
545+
if (kernel == null) {
546+
if (invocationContext != null) {
547+
kernelHooks = invocationContext.getKernelHooks();
548+
}
549+
} else {
550+
kernelHooks = kernel.getGlobalKernelHooks()
551+
.buildInvocationHooks(invocationContext);
552+
}
553+
if (kernelHooks == null) {
554+
return event;
555+
}
546556
return kernelHooks.executeHooks(event);
547557
}
548558

‎samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
1111
import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
1212
import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
13+
import com.microsoft.semantickernel.hooks.KernelHooks;
1314
import com.microsoft.semantickernel.orchestration.InvocationContext;
1415
import com.microsoft.semantickernel.orchestration.InvocationContext.Builder;
1516
import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
@@ -73,6 +74,27 @@ public static void main(String[] args) throws Exception {
7374
.toPromptString(new Gson()::toJson)
7475
.build());
7576

77+
KernelHooks hook = new KernelHooks();
78+
79+
hook.addPreToolCallHook((context) -> {
80+
System.out.println("Pre-tool call hook");
81+
return context;
82+
});
83+
84+
hook.addPreChatCompletionHook(
85+
(context) -> {
86+
System.out.println("Pre-chat completion hook");
87+
return context;
88+
});
89+
90+
hook.addPostChatCompletionHook(
91+
(context) -> {
92+
System.out.println("Post-chat completion hook");
93+
return context;
94+
});
95+
96+
kernel.getGlobalKernelHooks().addHooks(hook);
97+
7698
// Enable planning
7799
InvocationContext invocationContext = new Builder()
78100
.withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY)

‎samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/InMemory_DataStorage.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ public static void main(String[] args) {
105105
inMemoryDataStorage(embeddingGeneration);
106106
}
107107

108-
public static void inMemoryDataStorage(OpenAITextEmbeddingGenerationService embeddingGeneration) {
108+
public static void inMemoryDataStorage(
109+
OpenAITextEmbeddingGenerationService embeddingGeneration) {
109110
// Create a new Volatile vector store
110111
var volatileVectorStore = new VolatileVectorStore();
111112

‎semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.microsoft.semantickernel.hooks.KernelHook.PreToolCallHook;
99
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderedHook;
1010
import com.microsoft.semantickernel.hooks.KernelHook.PromptRenderingHook;
11+
import com.microsoft.semantickernel.orchestration.InvocationContext;
1112
import java.util.Collections;
1213
import java.util.Comparator;
1314
import java.util.HashMap;
@@ -66,7 +67,7 @@ public UnmodifiableKernelHooks unmodifiableClone() {
6667
*
6768
* @return an unmodifiable map of the hooks
6869
*/
69-
private Map<String, KernelHook<?>> getHooks() {
70+
protected Map<String, KernelHook<?>> getHooks() {
7071
return Collections.unmodifiableMap(hooks);
7172
}
7273

@@ -224,6 +225,25 @@ public boolean isEmpty() {
224225
return hooks.isEmpty();
225226
}
226227

228+
/**
229+
* Builds the list of hooks to be invoked for the given context, by merging the hooks in this
230+
* collection with the hooks in the context. Hooks in the context will override hooks in this.
231+
*
232+
* @param context the invocation context
233+
* @return the list of hooks to be invoked
234+
*/
235+
public KernelHooks buildInvocationHooks(@Nullable InvocationContext context) {
236+
if (context == null || context.getKernelHooks() == null) {
237+
return this;
238+
} else if (getHooks().isEmpty()) {
239+
return context.getKernelHooks();
240+
} else {
241+
HashMap<String, KernelHook<?>> merged = new HashMap<>(this.getHooks());
242+
merged.putAll(context.getKernelHooks().getHooks());
243+
return new KernelHooks(merged);
244+
}
245+
}
246+
227247
/**
228248
* A wrapper for KernelHooks that disables mutating methods.
229249
*/

‎semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ public static <T> ImplementationFunc<T> getFunction(Method method, Object instan
157157
}
158158

159159
// kernelHooks must be effectively final for lambda
160-
KernelHooks kernelHooks = context.getKernelHooks() != null
161-
? context.getKernelHooks()
162-
: kernel.getGlobalKernelHooks();
160+
KernelHooks kernelHooks = kernel.getGlobalKernelHooks()
161+
.buildInvocationHooks(invocationContext);
163162
assert kernelHooks != null : "getGlobalKernelHooks() should never return null!";
164163

165164
FunctionInvokingEvent updatedState = kernelHooks

‎semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ private Flux<FunctionResult<T>> invokeInternalAsync(
102102
: InvocationContext.builder().build();
103103

104104
// must be effectively final for lambda
105-
KernelHooks kernelHooks = context.getKernelHooks() != null
106-
? context.getKernelHooks()
107-
: kernel.getGlobalKernelHooks();
105+
KernelHooks kernelHooks = kernel.getGlobalKernelHooks().buildInvocationHooks(context);
106+
108107
assert kernelHooks != null : "getGlobalKernelHooks() should never return null";
109108

110109
PromptRenderingEvent preRenderingHookResult = kernelHooks

0 commit comments

Comments
 (0)