forked from microsoft/semantic-kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSemanticKernelEndpoint.cs
124 lines (98 loc) · 4.44 KB
/
SemanticKernelEndpoint.cs
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
// Copyright (c) Microsoft. All rights reserved.
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using KernelHttpServer.Model;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.SemanticKernel.Memory;
using Microsoft.SemanticKernel.Orchestration;
namespace KernelHttpServer;
public class SemanticKernelEndpoint
{
private readonly IMemoryStore _memoryStore;
public SemanticKernelEndpoint(IMemoryStore memoryStore)
{
this._memoryStore = memoryStore;
}
[Function("InvokeFunction")]
public async Task<HttpResponseData> InvokeFunctionAsync(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "skills/{skillName}/invoke/{functionName}")]
HttpRequestData req,
FunctionContext executionContext, string skillName, string functionName)
{
// in this sample we are using a per-request kernel that is created on each invocation
// once created, we feed the kernel the ask received via POST from the client
// and attempt to invoke the function with the given name
var ask = await JsonSerializer.DeserializeAsync<Ask>(req.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
if (ask == null)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, "Invalid request, unable to parse the request payload");
}
var kernel = SemanticKernelFactory.CreateForRequest(
req,
executionContext.GetLogger<SemanticKernelEndpoint>(),
ask.Skills,
this._memoryStore);
if (kernel == null)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, "Missing one or more expected HTTP Headers");
}
var f = kernel.Skills.GetFunction(skillName, functionName);
var contextVariables = new ContextVariables(ask.Value);
foreach (var input in ask.Inputs)
{
contextVariables.Set(input.Key, input.Value);
}
var result = await kernel.RunAsync(contextVariables, f);
if (result.ErrorOccurred)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, result.LastErrorDescription);
}
var r = req.CreateResponse(HttpStatusCode.OK);
await r.WriteAsJsonAsync(new AskResult { Value = result.Result, State = result.Variables.Select(v => new AskInput { Key = v.Key, Value = v.Value }) });
return r;
}
[Function("ExecutePlan")]
public async Task<HttpResponseData> ExecutePlanAsync(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "planner/execute/{maxSteps?}")]
HttpRequestData req,
FunctionContext executionContext, int? maxSteps = 10)
{
var ask = await JsonSerializer.DeserializeAsync<Ask>(req.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
if (ask == null)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, "Invalid request, unable to parse the request payload");
}
var kernel = SemanticKernelFactory.CreateForRequest(
req,
executionContext.GetLogger<SemanticKernelEndpoint>());
if (kernel == null)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, "Missing one or more expected HTTP Headers");
}
var contextVariables = new ContextVariables(ask.Value);
foreach (var input in ask.Inputs)
{
contextVariables.Set(input.Key, input.Value);
}
var planner = kernel.Skills.GetFunction("plannerskill", "executeplan");
var result = await kernel.RunAsync(contextVariables, planner);
var iterations = 1;
while (!result.Variables.ToPlan().IsComplete &&
result.Variables.ToPlan().IsSuccessful &&
iterations < maxSteps)
{
result = await kernel.RunAsync(result.Variables, planner);
iterations++;
}
if (result.ErrorOccurred)
{
return await req.CreateResponseWithMessageAsync(HttpStatusCode.BadRequest, result.LastErrorDescription);
}
var r = req.CreateResponse(HttpStatusCode.OK);
await r.WriteAsJsonAsync(new AskResult { Value = result.Variables.ToPlan().Result });
return r;
}
}