-
Notifications
You must be signed in to change notification settings - Fork 3.7k
.Net: Allow inputs to be injected into OpenAPI plugins #6605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Since OpenAPI specs are predominantly used for AI devs (Python) and app devs (C#) to work together. The "solution" to this should be serializable so it can be shared across languages. Perhaps using our template engines to inject inputs from other plugins |
Added to the Ignite bucket but it needs more clarification before working on it. |
This can be solved by transforming the plugin and allowing additional parameters to be injected. I will create a Blog Post showing how to do this for any type of |
### Motivation and Context Closes #6605 ### Description Some minor enhancements to the sample to match content in the Blog Post ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
@markwallace-microsoft appreciate the original code. I modified it to remove magic strings so you can add in parameters that were removed without having to rely on them always being there. var transformedPlugin = CreatePluginWithParameters(
agentPlugin,
(KernelParameterMetadata parameter) => parameter.ParameterType != typeof(IUser) ,
(KernelFunctionMetadata function, KernelArguments arguments, IReadOnlyList<KernelParameterMetadata> originalParameter) => {
var userParameter = originalParameter.Where(x => x.ParameterType == typeof(IUser)).FirstOrDefault();
if (userParameter != null)
arguments.Add(userParameter.Name, User);
}
); public delegate bool IncludeKernelParameter(KernelParameterMetadata parameter);
public delegate void UpdateKernelArguments(KernelFunctionMetadata function, KernelArguments arguments, IReadOnlyList<KernelParameterMetadata> originalParameter);
/// <summary>
/// Create a <see cref="KernelPlugin"/> instance from the provided instance where each function only includes
/// permitted parameters. The <see cref="IncludeKernelParameter"/> delegate is called to determine whether or not
/// parameter will be included. The <see cref="UpdateKernelArguments"/> delegate is called to update the arguments
/// and allow additional values to be included.
/// </summary>
public static KernelPlugin CreatePluginWithParameters(KernelPlugin plugin, IncludeKernelParameter includeKernelParameter, UpdateKernelArguments updateKernelArguments)
{
List<KernelFunction>? functions = new();
foreach (KernelFunction function in plugin)
{
functions.Add(CreateFunctionWithParameters(function, includeKernelParameter, updateKernelArguments));
}
return KernelPluginFactory.CreateFromFunctions(plugin.Name, plugin.Description, functions);
}
/// <summary>
/// Create a <see cref="KernelFunction"/> instance from the provided instance which only includes permitted parameters.
/// The function method will add additional argument values before calling the original function.
/// </summary>
private static KernelFunction CreateFunctionWithParameters(KernelFunction function, IncludeKernelParameter includeKernelParameter, UpdateKernelArguments updateKernelArguments)
{
var originalParameters = function.Metadata.Parameters;
var method = (Kernel kernel, KernelFunction currentFunction, KernelArguments arguments, CancellationToken cancellationToken) =>
{
updateKernelArguments( currentFunction.Metadata, arguments, originalParameters);
return function.InvokeAsync(kernel, arguments, cancellationToken);
};
var options = new KernelFunctionFromMethodOptions()
{
FunctionName = function.Name,
Description = function.Description,
Parameters = CreateParameterMetadataWithParameters(function.Metadata.Parameters, includeKernelParameter),
ReturnParameter = function.Metadata.ReturnParameter,
};
return KernelFunctionFactory.CreateFromMethod(method, options);
} |
With native functions, you can inject services that can provide additional information to plugins so the AI doesn't need to provide it.
For example, you may inject a
UserContextService
service that allows you to get the current user's ID so you can use it within the plugin without the LLM ever needing to know it and pass it in. This reduces token usage and simplifies the job of the AI.Today, with OpenAPI plugins, this is not possible. This task is to resolve this gap.
The text was updated successfully, but these errors were encountered: