-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctionInvocationApproval.cs
More file actions
143 lines (120 loc) · 4.76 KB
/
FunctionInvocationApproval.cs
File metadata and controls
143 lines (120 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
/// <summary>
/// Service that verifies if function invocation is approved.
/// </summary>
public interface IFunctionApprovalService
{
bool IsInvocationApproved(KernelFunction function, KernelArguments arguments);
}
public sealed class ConsoleFunctionApprovalService : IFunctionApprovalService
{
public bool IsInvocationApproved(KernelFunction function, KernelArguments arguments)
{
Console.WriteLine("====================");
Console.WriteLine($"Function name: {function.Name}");
Console.WriteLine($"Plugin name: {function.PluginName ?? "N/A"}");
if (arguments.Count == 0)
{
Console.WriteLine("\nArguments: N/A");
}
else
{
Console.WriteLine("\nArguments:");
foreach (var argument in arguments)
{
Console.WriteLine($"{argument.Key}: {argument.Value}");
}
}
Console.WriteLine("\nApprove invocation? (yes/no)");
var input = Console.ReadLine();
return input?.Equals("yes", StringComparison.OrdinalIgnoreCase) ?? false;
}
}
/// <summary>
/// Filter to invoke function only if it's approved.
/// </summary>
public sealed class FunctionInvocationFilter(IFunctionApprovalService approvalService) : IFunctionInvocationFilter
{
private readonly IFunctionApprovalService _approvalService = approvalService;
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
{
// Invoke the function only if it's approved.
if (_approvalService.IsInvocationApproved(context.Function, context.Arguments))
{
await next(context);
}
else
{
// Otherwise, return a result that operation was rejected.
context.Result = new FunctionResult(context.Result, "Operation was rejected.");
}
}
}
#region Plugins
[Description("Software Builder Plugin")]
public sealed class SoftwareBuilderPlugin
{
[KernelFunction]
[Description("Collects requirements for the software project.")]
public string CollectRequirements()
{
Console.WriteLine("Collecting requirements...");
return "Requirements";
}
[KernelFunction]
[Description("Designs the software based on the requirements.")]
public string Design(string requirements)
{
Console.WriteLine($"Designing based on: {requirements}");
return "Design";
}
[KernelFunction]
[Description("Implements the software based on the requirements and design.")]
public string Implement(string requirements, string design)
{
Console.WriteLine($"Implementing based on {requirements} and {design}");
return "Implementation";
}
[KernelFunction]
[Description("Tests the software based on the requirements, design, and implementation.")]
public string Test(string requirements, string design, string implementation)
{
Console.WriteLine($"Testing based on {requirements}, {design} and {implementation}");
return "Test Results";
}
[KernelFunction]
[Description("Deploys the software based on the requirements, design, implementation, and test results.")]
public string Deploy(string requirements, string design, string implementation, string testResults)
{
Console.WriteLine($"Deploying based on {requirements}, {design}, {implementation} and {testResults}");
return "Deployment";
}
}
#endregion
class FunctionInvocationApproval
{
public static async Task ExecuteAsync(IKernelBuilder builder)
{
// Add function approval service and filter
builder.Services.AddSingleton<IFunctionApprovalService, ConsoleFunctionApprovalService>();
builder.Services.AddSingleton<IFunctionInvocationFilter, FunctionInvocationFilter>();
// Add software builder plugin
builder.Plugins.AddFromType<SoftwareBuilderPlugin>();
var kernel = builder.Build();
// Enable automatic function calling
var executionSettings = new OpenAIPromptExecutionSettings
{
Temperature = 0,
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
// Initialize kernel arguments.
var arguments = new KernelArguments(executionSettings);
// Start execution
// Try to reject invocation at each stage to compare LLM results.
var result = await kernel.InvokePromptAsync("I want to build a software. Let's start from the first step. Continue unitll all steps were executed or one of the steps are rejected.", arguments);
Console.WriteLine(result);
}
}