Skip to content

Commit 8794328

Browse files
authored
Merge pull request microsoft#102 from johnoliver/fix-hooks
Fix some global kernel hooks not being executed
2 parents 737897c + caff8b6 commit 8794328

File tree

6 files changed

+78
-21
lines changed

6 files changed

+78
-21
lines changed

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

Lines changed: 22 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,21 @@ 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 = KernelHooks.merge(
551+
kernel.getGlobalKernelHooks(),
552+
invocationContext != null ? invocationContext.getKernelHooks() : null);
553+
}
554+
if (kernelHooks == null) {
555+
return event;
556+
}
546557
return kernelHooks.executeHooks(event);
547558
}
548559

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: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public UnmodifiableKernelHooks unmodifiableClone() {
6666
*
6767
* @return an unmodifiable map of the hooks
6868
*/
69-
private Map<String, KernelHook<?>> getHooks() {
69+
protected Map<String, KernelHook<?>> getHooks() {
7070
return Collections.unmodifiableMap(hooks);
7171
}
7272

@@ -224,6 +224,31 @@ public boolean isEmpty() {
224224
return hooks.isEmpty();
225225
}
226226

227+
/**
228+
* Builds the list of hooks to be invoked for the given context, by merging the hooks in this
229+
* collection with the hooks in the context. Duplicate hooks in b will override hooks in a.
230+
*
231+
* @param a hooks to merge
232+
* @param b hooks to merge
233+
* @return the list of hooks to be invoked
234+
*/
235+
public static KernelHooks merge(@Nullable KernelHooks a, @Nullable KernelHooks b) {
236+
KernelHooks hooks = a;
237+
if (hooks == null) {
238+
hooks = new KernelHooks();
239+
}
240+
241+
if (b == null) {
242+
return hooks;
243+
} else if (hooks.isEmpty()) {
244+
return b;
245+
} else {
246+
HashMap<String, KernelHook<?>> merged = new HashMap<>(hooks.getHooks());
247+
merged.putAll(b.getHooks());
248+
return new KernelHooks(merged);
249+
}
250+
}
251+
227252
/**
228253
* A wrapper for KernelHooks that disables mutating methods.
229254
*/

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,9 @@ 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();
163-
assert kernelHooks != null : "getGlobalKernelHooks() should never return null!";
160+
KernelHooks kernelHooks = KernelHooks.merge(
161+
kernel.getGlobalKernelHooks(),
162+
context.getKernelHooks());
164163

165164
FunctionInvokingEvent updatedState = kernelHooks
166165
.executeHooks(

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,9 @@ 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();
108-
assert kernelHooks != null : "getGlobalKernelHooks() should never return null";
105+
KernelHooks kernelHooks = KernelHooks.merge(
106+
kernel.getGlobalKernelHooks(),
107+
context.getKernelHooks());
109108

110109
PromptRenderingEvent preRenderingHookResult = kernelHooks
111110
.executeHooks(new PromptRenderingEvent(this, argumentsIn));

0 commit comments

Comments
 (0)