All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.semantickernel.hooks.KernelHooks Maven / Gradle / Ivy

There is a newer version: 1.3.0
Show newest version
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.hooks;

import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokedHook;
import com.microsoft.semantickernel.hooks.KernelHook.FunctionInvokingHook;
import com.microsoft.semantickernel.hooks.KernelHook.PostChatCompletionHook;
import com.microsoft.semantickernel.hooks.KernelHook.PreChatCompletionHook;
import com.microsoft.semantickernel.hooks.KernelHook.PreToolCallHook;
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.UUID;
import java.util.function.Function;
import javax.annotation.Nullable;

/**
 * Represents a collection of hooks that can be used to intercept and modify events in the kernel.
 */
public class KernelHooks {

    private final Map> hooks;

    /**
     * Creates a new instance of the {@link KernelHooks} class.
     */
    public KernelHooks() {
        this.hooks = new HashMap<>();
    }

    /**
     * Creates a copy of the {@link KernelHooks}.
     *
     * @param kernelHooks the hooks to copy
     */
    public KernelHooks(@Nullable KernelHooks kernelHooks) {
        this();
        if (kernelHooks != null) {
            this.hooks.putAll(kernelHooks.getHooks());
        }
    }

    /**
     * Creates a new instance of the {@link KernelHooks} class from the given hooks.
     *
     * @param hooks the hooks to add
     */
    public KernelHooks(Map> hooks) {
        this();
        this.hooks.putAll(hooks);
    }

    /**
     * Creates an unmodifiable copy of this {@link KernelHooks}.
     *
     * @return an unmodifiable copy of this {@link KernelHooks}
     */
    public UnmodifiableKernelHooks unmodifiableClone() {
        return new UnmodifiableKernelHooks(this);
    }

    /**
     * Gets the hooks in this collection.
     *
     * @return an unmodifiable map of the hooks
     */
    protected Map> getHooks() {
        return Collections.unmodifiableMap(hooks);
    }

    /**
     * Add a {@link FunctionInvokingHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addFunctionInvokingHook(
        Function, FunctionInvokingEvent> function) {
        return addHook((FunctionInvokingHook) function::apply);
    }

    /**
     * Add a {@link FunctionInvokedHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addFunctionInvokedHook(
        Function, FunctionInvokedEvent> function) {
        return addHook((FunctionInvokedHook) function::apply);
    }

    /**
     * Add a {@link PreChatCompletionHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addPreChatCompletionHook(
        Function function) {
        return addHook((PreChatCompletionHook) function::apply);
    }

    /**
     * Add a {@link PreToolCallHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addPreToolCallHook(
        Function function) {
        return addHook((PreToolCallHook) function::apply);
    }

    /**
     * Add a {@link PostChatCompletionEvent} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addPostChatCompletionHook(
        Function function) {
        return addHook((PostChatCompletionHook) function::apply);
    }

    /**
     * Add a {@link PromptRenderedHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addPromptRenderedHook(
        Function function) {
        return addHook((PromptRenderedHook) function::apply);
    }

    /**
     * Add a {@link PromptRenderingHook} to the collection of hooks.
     *
     * @param function the function to add
     * @return the key of the hook in the collection
     */
    public String addPromptRenderingHook(
        Function function) {
        return addHook((PromptRenderingHook) function::apply);
    }

    /**
     * Executes the hooks in this collection that accept the event.
     *
     * @param event the event to execute the hooks on
     * @param    the type of the event
     * @return the event after the hooks have been executed
     */
    @SuppressWarnings("unchecked")
    public  T executeHooks(T event) {
        return this.hooks.values()
            .stream()
            .filter(hook -> hook.test(event))
            .sorted(Comparator.comparingInt(KernelHook::getPriority))
            .reduce(event, (event2, hook) -> {
                // unchecked cast
                return ((KernelHook) hook).apply(event2);
            }, (a, b) -> {
                throw new UnsupportedOperationException("No merging for hooks");
            });
    }

    /**
     * Add a {@link KernelHook} to the collection of hooks.
     *
     * @param hook the hook to add
     * @return the key of the hook in the collection
     */
    public String addHook(KernelHook hook) {
        return addHook(UUID.randomUUID().toString(), hook);
    }

    /**
     * Add a {@link KernelHook} to the collection of hooks.
     *
     * @param hookName the key of the hook in the collection
     * @param hook     the hook to add
     * @return the key of the hook in the collection
     */
    public String addHook(String hookName, KernelHook hook) {
        hooks.put(hookName, hook);
        return hookName;
    }

    /**
     * Remove a hook from the collection of hooks.
     *
     * @param hookName the key of the hook in the collection
     * @return the removed hook, or {@code null} if the hook was not found
     */
    public KernelHook removeHook(String hookName) {
        return hooks.remove(hookName);
    }

    /**
     * Appends the given hooks to this collection.
     *
     * @param kernelHooks the hooks to append
     * @return this instance of the {@link KernelHooks} class
     */
    public KernelHooks addHooks(@Nullable KernelHooks kernelHooks) {
        if (kernelHooks == null) {
            return this;
        }
        hooks.putAll(kernelHooks.getHooks());

        return this;
    }

    /**
     * Determines if this collection of hooks is empty.
     *
     * @return {@code true} if the collection is empty, otherwise {@code false}
     */
    public boolean isEmpty() {
        return hooks.isEmpty();
    }

    /**
     * Builds the list of hooks to be invoked for the given context, by merging the hooks in this
     * collection with the hooks in the context. Duplicate hooks in b will override hooks in a.
     *
     * @param a hooks to merge
     * @param b hooks to merge
     * @return the list of hooks to be invoked
     */
    public static KernelHooks merge(@Nullable KernelHooks a, @Nullable KernelHooks b) {
        KernelHooks hooks = a;
        if (hooks == null) {
            hooks = new KernelHooks();
        }

        if (b == null) {
            return hooks;
        } else if (hooks.isEmpty()) {
            return b;
        } else {
            HashMap> merged = new HashMap<>(hooks.getHooks());
            merged.putAll(b.getHooks());
            return new KernelHooks(merged);
        }
    }

    /**
     * A wrapper for KernelHooks that disables mutating methods.
     */
    public static class UnmodifiableKernelHooks extends KernelHooks {

        private UnmodifiableKernelHooks(KernelHooks kernelHooks) {
            super(kernelHooks);
        }

        @Override
        public String addFunctionInvokingHook(
            Function, FunctionInvokingEvent> function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addFunctionInvokedHook(
            Function, FunctionInvokedEvent> function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addPreChatCompletionHook(
            Function function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addPostChatCompletionHook(
            Function function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addPromptRenderedHook(
            Function function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addPromptRenderingHook(
            Function function) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addHook(KernelHook hook) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public String addHook(String hookName, KernelHook hook) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public KernelHooks addHooks(@Nullable KernelHooks kernelHooks) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }

        @Override
        public KernelHook removeHook(String hookName) {
            throw new UnsupportedOperationException("unmodifiable instance of KernelHooks");
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy