diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java index 77d4b4a3..4ec67774 100644 --- a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java +++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ResponseSchemaTest.java @@ -161,16 +161,18 @@ private static void verifyCalled(OpenAIAsyncClient client, String expected) { new JsonOptions() ); JsonWriter format = chatCompletionsOptions.getResponseFormat() - .toJson(jsonWriter); + .toJson(jsonWriter); jsonWriter.flush(); writer.flush(); String json = String.valueOf(writer.getBuffer()) .replaceAll("\n", "") + .replaceAll("\r", "") .replaceAll(" +", ""); String expectedClean = expected .stripIndent() .replaceAll("\n", "") + .replaceAll("\r", "") .replaceAll(" +", ""); return json.equals(expectedClean); diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java index cf38760f..d8059ef7 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java @@ -302,14 +302,12 @@ public AIServiceSelector getServiceSelector() { * @param clazz The class of the service to get. * @return The service of the specified type from the kernel. * @throws ServiceNotFoundException if the service is not found. - * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, - * KernelFunction, KernelArguments) + * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, KernelArguments) */ public T getService(Class clazz) throws ServiceNotFoundException { AIServiceSelection selector = serviceSelector .trySelectAIService( clazz, - null, null); if (selector == null) { @@ -319,6 +317,29 @@ public T getService(Class clazz) throws ServiceNotFound return selector.getService(); } + /** + * Get the service of the specified type from the kernel. + * + * @param The type of the service to get. + * @param clazz The class of the service to get. + * @param args The arguments to help select the service to get. + * @return The service of the specified type from the kernel. + * @throws ServiceNotFoundException if the service is not found. + * @see com.microsoft.semantickernel.services.AIServiceSelector#trySelectAIService(Class, KernelArguments) + */ + public T getService(Class clazz, KernelArguments args) throws ServiceNotFoundException { + AIServiceSelection selector = serviceSelector + .trySelectAIService( + clazz, + args); + + if (selector == null) { + throw new ServiceNotFoundException("Unable to find service of type " + clazz.getName()); + } + + return selector.getService(); + } + /** * A fluent builder for creating a new instance of {@code Kernel}. */ diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java index 80ec5972..e4fb8319 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelArguments.java @@ -360,6 +360,16 @@ public Builder withVariable(String key, T value, value)); } + /** + * Set prompt execution settings + * + * @param executionSettings Execution settings + * @return {$code this} Builder for fluent coding + */ + public Builder withExecutionSettings(PromptExecutionSettings executionSettings) { + return withExecutionSettings(Collections.singletonList(executionSettings)); + } + /** * Set prompt execution settings * @@ -399,6 +409,8 @@ public Builder withExecutionSettings(List executionS serviceId) ); } + + this.executionSettings.put(serviceId, settings); } return this; diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java index 1d12f961..2ea90974 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromPrompt.java @@ -131,15 +131,18 @@ private Flux> invokeInternalAsync( LOGGER.info(SemanticKernelResources.getString("rendered.prompt"), prompt); - FunctionInvokingEvent updateArguments = kernelHooks + FunctionInvokingEvent invokingEvent = kernelHooks .executeHooks(new FunctionInvokingEvent(this, args)); - args = updateArguments.getArguments(); + + args = KernelArguments.builder() + .withVariables(invokingEvent.getArguments()) + .withExecutionSettings(this.getExecutionSettings()) + .build(); AIServiceSelection aiServiceSelection = kernel .getServiceSelector() .trySelectAIService( TextAIService.class, - this, args); AIService client = aiServiceSelection != null ? aiServiceSelection.getService() diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java index e68e6a69..ac95f7d3 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceSelector.java @@ -20,7 +20,7 @@ public interface AIServiceSelector { * @param serviceType The type of service to select. This must be the same type with which the * service was registered in the {@link AIServiceSelection} * @param function The KernelFunction to use to select the service, or {@code null}. - * @param arguments The KernelFunctionArguments to use to select the service, or + * @param arguments The KernelArguments to use to select the service, or * {@code null}. * @param The type of service to select. * @return An {@code AIServiceSelection} containing the selected service and associated @@ -31,4 +31,25 @@ AIServiceSelection trySelectAIService( Class serviceType, @Nullable KernelFunction function, @Nullable KernelArguments arguments); + + /** + * Resolves an {@link AIService} and associated and + * {@link com.microsoft.semantickernel.orchestration.PromptExecutionSettings} based on the + * associated {@link KernelFunction} and {@link KernelArguments}. + * + * @param serviceType The type of service to select. This must be the same type with which the + * service was registered in the {@link AIServiceSelection} + * @param arguments The KernelArguments to use to select the service, or + * {@code null}. + * @param The type of service to select. + * @return An {@code AIServiceSelection} containing the selected service and associated + * PromptExecutionSettings. + */ + @Nullable + default AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments) { + throw new UnsupportedOperationException( + "This method is not implemented."); + } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java index c3e42b8e..03ecdd78 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/BaseAIServiceSelector.java @@ -35,6 +35,14 @@ public AIServiceSelection trySelectAIService( return trySelectAIService(serviceType, function, arguments, services); } + @Override + @Nullable + public AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments) { + return trySelectAIService(serviceType, arguments, services); + } + /** * Resolves an {@link AIService} from the {@code services} argument using the specified * {@code function} and {@code arguments} for selection. @@ -47,6 +55,7 @@ public AIServiceSelection trySelectAIService( * @param services The services to select from. * @param The type of service to select. * @return The selected service, or {@code null} if no service could be selected. + * */ @Nullable protected abstract AIServiceSelection trySelectAIService( @@ -54,4 +63,25 @@ protected abstract AIServiceSelection trySelectAIServic @Nullable KernelFunction function, @Nullable KernelArguments arguments, Map, AIService> services); + + + /** + * Resolves an {@link AIService} from the {@code services} argument using the specified + * {@code function} and {@code arguments} for selection. + * + * @param serviceType The type of service to select. This must be the same type with which the + * service was registered in the {@link AIServiceSelection} + * @param arguments The KernelArguments to use to select the service, or + * {@code null}. + * @param services The services to select from. + * @param The type of service to select. + * @return The selected service, or {@code null} if no service could be selected. + */ + @Nullable + protected AIServiceSelection trySelectAIService( + Class serviceType, + @Nullable KernelArguments arguments, + Map, AIService> services) { + return trySelectAIService(serviceType, null, arguments, services); + } } diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java index 2be73543..6b04fe2b 100644 --- a/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java +++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/OrderedAIServiceSelector.java @@ -57,23 +57,6 @@ private static AIServiceSelection castServiceSelection( } } - @Nullable - private static Map settingsFromFunctionSettings( - @Nullable KernelFunction function) { - if (function != null) { - return function.getExecutionSettings(); - } - return null; - } - -// @Nullable -// @Override -// public AIServiceSelection trySelectAIService( -// Class serviceType, -// @Nullable KernelArguments arguments) { -// return selectAIService(serviceType, arguments.getPromptExecutionSettings()); -// } - @Nullable @Override public AIServiceSelection trySelectAIService( @@ -82,11 +65,11 @@ public AIServiceSelection trySelectAIService( @Nullable KernelArguments arguments, Map, AIService> services) { - // Allow the execution settings from the kernel arguments to take precedence - Map executionSettings = settingsFromFunctionSettings( - function); + if (function == null) { + return selectAIService(serviceType, arguments != null ? arguments.getExecutionSettings() : null); + } - return selectAIService(serviceType, executionSettings); + return selectAIService(serviceType, function.getExecutionSettings()); }