diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java new file mode 100644 index 0000000000..dc7abe14a2 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.tests; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.plugin.KernelPlugin; +import com.microsoft.semantickernel.plugin.KernelPluginFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ImportingMultiplePluginsTest { + + @Test + public void canImportMultiplePlugins() { + KernelPlugin summarize = KernelPluginFactory.importPluginFromResourcesDirectory( + "Plugins", + "SummarizePlugin", + "Summarize", + null, + String.class); + + KernelPlugin topics = KernelPluginFactory.importPluginFromResourcesDirectory( + "Plugins", + "SummarizePlugin", + "Topics", + null, + String.class); + + KernelPlugin notegen = KernelPluginFactory.importPluginFromResourcesDirectory( + "Plugins", + "SummarizePlugin", + "Notegen", + null, + String.class); + + Kernel kernel = Kernel.builder() + .withPlugin(summarize) + .withPlugin(topics) + .withPlugin(notegen) + .build(); + + Assertions.assertEquals(3, + kernel.getPlugin("SummarizePlugin").getFunctions().size()); + Assertions.assertEquals("Summarize", + kernel.getPlugin("SummarizePlugin").get("Summarize").getName()); + Assertions.assertEquals("Topics", + kernel.getPlugin("SummarizePlugin").get("Topics").getName()); + Assertions.assertEquals("Notegen", + kernel.getPlugin("SummarizePlugin").get("Notegen").getName()); + + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java index 1b682e4c34..851934d423 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java @@ -36,7 +36,17 @@ class KernelPluginCollection { * plugins. */ KernelPluginCollection(List plugins) { - plugins.forEach(plugin -> this.plugins.put(plugin.getName(), plugin)); + plugins.forEach(plugin -> putOrMerge(plugin.getName(), plugin)); + } + + private void putOrMerge(String pluginName, KernelPlugin plugin) { + if (plugins.containsKey(pluginName)) { + plugin.getFunctions() + .entrySet() + .forEach(entry -> plugins.get(pluginName).addFunction(entry.getValue())); + } else { + plugins.put(pluginName, plugin); + } } /** diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java index 620afb87a1..a36f4f8628 100644 --- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java @@ -322,7 +322,8 @@ public class KernelPluginFactory { // configuration, unable to parse {configPath}"); } - KernelFunction plugin = getKernelFunction(promptTemplateFactory, configPath, + KernelFunction plugin = getKernelFunction(dir.getName(), promptTemplateFactory, + configPath, promptPath); plugins.put(dir.getName(), plugin); @@ -338,6 +339,7 @@ public class KernelPluginFactory { } private static KernelFunction getKernelFunction( + @Nullable String functionName, @Nullable PromptTemplateFactory promptTemplateFactory, File configPath, File promptPath) @@ -350,7 +352,7 @@ public class KernelPluginFactory { String template = new String(Files.readAllBytes(promptPath.toPath()), Charset.defaultCharset()); - return getKernelFunction(promptTemplateFactory, config, template); + return getKernelFunction(functionName, promptTemplateFactory, config, template); } catch (Exception e) { LOGGER.error("Failed to read file " + configPath.getAbsolutePath(), e); @@ -360,6 +362,7 @@ public class KernelPluginFactory { @SuppressWarnings("unchecked") private static KernelFunction getKernelFunction( + @Nullable String functionName, @Nullable PromptTemplateFactory promptTemplateFactory, PromptTemplateConfig config, String template) { @@ -373,8 +376,12 @@ public class KernelPluginFactory { promptTemplate = new KernelPromptTemplateFactory().tryCreate(config); } + if (config.getName() != null) { + functionName = config.getName(); + } + return (KernelFunction) new KernelFunctionFromPrompt.Builder<>() - .withName(config.getName()) + .withName(functionName) .withDescription(config.getDescription()) .withExecutionSettings(config.getExecutionSettings()) .withInputParameters(config.getInputVariables()) @@ -439,7 +446,7 @@ public class KernelPluginFactory { + pluginDirectoryName); return null; } - KernelFunction function = getKernelFunction(promptTemplateFactory, + KernelFunction function = getKernelFunction(functionName, promptTemplateFactory, promptTemplateConfig, template); HashMap> plugins = new HashMap<>();